Loading...
Searching...
No Matches
restriction_constant.hpp
Go to the documentation of this file.
1
2
3#pragma once
4
5#include "../../quadrature/quadrature.hpp"
7#include "dense/vec.hpp"
12#include "linalg/operator.hpp"
13#include "linalg/vector.hpp"
14#include "linalg/vector_q1.hpp"
15
17
18template < typename ScalarT >
20{
21 public:
24 using ScalarType = ScalarT;
25
26 private:
27 grid::shell::DistributedDomain domain_coarse_;
28
29 linalg::OperatorApplyMode operator_apply_mode_;
30
33
36
38
39 public:
41 const grid::shell::DistributedDomain& domain_coarse,
43 : domain_coarse_( domain_coarse )
44 , operator_apply_mode_( operator_apply_mode )
45 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
46 , send_buffers_( domain_coarse )
47 , recv_buffers_( domain_coarse )
48 {}
49
50 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
51 {
52 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
53 {
54 assign( dst, 0 );
55 }
56
57 src_ = src.grid_data();
58 dst_ = dst.grid_data();
59 mask_src_ = src.mask_data();
60
61 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
62 {
63 throw std::runtime_error( "Restriction: src and dst must have the same number of subdomains." );
64 }
65
66 for ( int i = 1; i <= 3; i++ )
67 {
68 if ( src_.extent( i ) - 1 != 2 * ( dst_.extent( i ) - 1 ) )
69 {
70 throw std::runtime_error( "Restriction: src and dst must have a compatible number of cells." );
71 }
72 }
73
74 // Looping over the coarse grid.
75 Kokkos::parallel_for(
76 "matvec",
77 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
78 { 0, 0, 0, 0 },
79 {
80 dst_.extent( 0 ),
81 dst_.extent( 1 ),
82 dst_.extent( 2 ),
83 dst_.extent( 3 ),
84 } ),
85 *this );
86
87 Kokkos::fence();
88
89 // Additive communication.
90
92 domain_coarse_, dst_, send_buffers_, recv_buffers_ );
93 communication::shell::unpack_and_reduce_local_subdomain_boundaries( domain_coarse_, dst_, recv_buffers_ );
94 }
95
96 KOKKOS_INLINE_FUNCTION void
97 operator()( const int local_subdomain_id, const int x_coarse, const int y_coarse, const int r_coarse ) const
98 {
99 const auto x_fine = 2 * x_coarse;
100 const auto y_fine = 2 * y_coarse;
101 const auto r_fine = 2 * r_coarse;
102
103 dense::Vec< int, 3 > offsets[21];
105
106 for ( const auto& offset : offsets )
107 {
108 const auto fine_stencil_x = x_fine + offset( 0 );
109 const auto fine_stencil_y = y_fine + offset( 1 );
110 const auto fine_stencil_r = r_fine + offset( 2 );
111
112 if ( fine_stencil_x >= 0 && fine_stencil_x < src_.extent( 1 ) && fine_stencil_y >= 0 &&
113 fine_stencil_y < src_.extent( 2 ) && fine_stencil_r >= 0 && fine_stencil_r < src_.extent( 3 ) )
114 {
115 const auto weight = wedge::shell::prolongation_constant_weight< ScalarType >(
116 fine_stencil_x, fine_stencil_y, fine_stencil_r, x_coarse, y_coarse, r_coarse );
117
118 const auto mask_weight =
120 mask_src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r ),
122 1.0 :
123 0.0;
124
125 Kokkos::atomic_add(
126 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse ),
127 weight * mask_weight * src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r ) );
128 }
129 }
130 }
131};
132
133template < typename ScalarT, int VecDim = 3 >
135{
136 public:
139 using ScalarType = ScalarT;
140
141 private:
142 grid::shell::DistributedDomain domain_coarse_;
143
144 linalg::OperatorApplyMode operator_apply_mode_;
145
148
151
153
154 public:
156 const grid::shell::DistributedDomain& domain_coarse,
158 : domain_coarse_( domain_coarse )
159 , operator_apply_mode_( operator_apply_mode )
160 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
161 , send_buffers_( domain_coarse )
162 , recv_buffers_( domain_coarse )
163 {}
164
165 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
166 {
167 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
168 {
169 assign( dst, 0 );
170 }
171
172 src_ = src.grid_data();
173 dst_ = dst.grid_data();
174 mask_src_ = src.mask_data();
175
176 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
177 {
178 throw std::runtime_error( "Restriction: src and dst must have the same number of subdomains." );
179 }
180
181 for ( int i = 1; i <= 3; i++ )
182 {
183 if ( src_.extent( i ) - 1 != 2 * ( dst_.extent( i ) - 1 ) )
184 {
185 throw std::runtime_error( "Restriction: src and dst must have a compatible number of cells." );
186 }
187 }
188
189 // Looping over the coarse grid.
190 Kokkos::parallel_for(
191 "matvec",
192 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
193 { 0, 0, 0, 0 },
194 {
195 dst_.extent( 0 ),
196 dst_.extent( 1 ),
197 dst_.extent( 2 ),
198 dst_.extent( 3 ),
199 } ),
200 *this );
201
202 Kokkos::fence();
203
204 // Additive communication.
205
207 domain_coarse_, dst_, send_buffers_, recv_buffers_ );
208 communication::shell::unpack_and_reduce_local_subdomain_boundaries( domain_coarse_, dst_, recv_buffers_ );
209 }
210
211 KOKKOS_INLINE_FUNCTION void
212 operator()( const int local_subdomain_id, const int x_coarse, const int y_coarse, const int r_coarse ) const
213 {
214 const auto x_fine = 2 * x_coarse;
215 const auto y_fine = 2 * y_coarse;
216 const auto r_fine = 2 * r_coarse;
217
218 dense::Vec< int, 3 > offsets[21];
220
221 for ( const auto& offset : offsets )
222 {
223 const auto fine_stencil_x = x_fine + offset( 0 );
224 const auto fine_stencil_y = y_fine + offset( 1 );
225 const auto fine_stencil_r = r_fine + offset( 2 );
226
227 if ( fine_stencil_x >= 0 && fine_stencil_x < src_.extent( 1 ) && fine_stencil_y >= 0 &&
228 fine_stencil_y < src_.extent( 2 ) && fine_stencil_r >= 0 && fine_stencil_r < src_.extent( 3 ) )
229 {
230 const auto weight = wedge::shell::prolongation_constant_weight< ScalarType >(
231 fine_stencil_x, fine_stencil_y, fine_stencil_r, x_coarse, y_coarse, r_coarse );
232
233 const auto mask_weight =
235 mask_src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r ),
237 1.0 :
238 0.0;
239
240 for ( int d = 0; d < VecDim; ++d )
241 {
242 Kokkos::atomic_add(
243 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse, d ),
244 weight * mask_weight *
245 src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r, d ) );
246 }
247 }
248 }
249 }
250};
251} // namespace terra::fe::wedge::operators::shell
Send and receive buffers for all process-local subdomain boundaries.
Definition communication.hpp:56
Definition restriction_constant.hpp:20
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition restriction_constant.hpp:50
void operator()(const int local_subdomain_id, const int x_coarse, const int y_coarse, const int r_coarse) const
Definition restriction_constant.hpp:97
RestrictionConstant(const grid::shell::DistributedDomain &domain_coarse, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace)
Definition restriction_constant.hpp:40
ScalarT ScalarType
Definition restriction_constant.hpp:24
Definition restriction_constant.hpp:135
void operator()(const int local_subdomain_id, const int x_coarse, const int y_coarse, const int r_coarse) const
Definition restriction_constant.hpp:212
ScalarT ScalarType
Definition restriction_constant.hpp:139
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition restriction_constant.hpp:165
RestrictionVecConstant(const grid::shell::DistributedDomain &domain_coarse, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace)
Definition restriction_constant.hpp:155
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
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 void prolongation_constant_fine_grid_stencil_offsets_at_coarse_vertex(dense::Vec< int, 3 >(&offsets)[21])
Definition grid_transfer_constant.hpp:9
Kokkos::View< ScalarType ****[VecDim], Layout > Grid4DDataVec
Definition grid_types.hpp:43
Kokkos::View< ScalarType ****, Layout > Grid4DDataScalar
Definition grid_types.hpp:25
OperatorApplyMode
Modes for applying an operator to a vector.
Definition operator.hpp:30
@ Replace
Overwrite the destination vector.
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 vec.hpp:9