Loading...
Searching...
No Matches
prolongation_linear.hpp
Go to the documentation of this file.
1
2
3#pragma once
4
6#include "dense/vec.hpp"
8#include "grid/grid_types.hpp"
9#include "linalg/operator.hpp"
10#include "linalg/vector.hpp"
11#include "linalg/vector_q1.hpp"
12
14
15template < typename ScalarT >
17{
18 public:
21 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 applyStoredLMatrices_ =
28 false; // set to make apply_impl() load and use the stored LMatrices for the operator application
29
30 Grid4DDataLocalMatrices LMatrices_;
31
34
35 linalg::OperatorApplyMode operator_apply_mode_;
36
39
40 public:
45 : grid_fine_( grid_fine )
46 , radii_fine_( radii_fine )
47 , operator_apply_mode_( operator_apply_mode )
48 {}
49
50 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
51 {
52 if ( storeLMatrices_ or applyStoredLMatrices_ )
53 assert( LMatrices_.data() != nullptr );
54
55 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
56 {
57 assign( dst, 0 );
58 }
59
60 src_ = src.grid_data();
61 dst_ = dst.grid_data();
62
63 if ( dst_.extent( 1 ) != grid_fine_.extent( 1 ) )
64 {
65 throw std::runtime_error(
66 "Prolongation: dst and grid_fine must have the same number of cells in the x direction." );
67 }
68
69 if ( dst_.extent( 3 ) != radii_fine_.extent( 1 ) )
70 {
71 throw std::runtime_error(
72 "Prolongation: dst and radii_fine must have the same number of cells in the r direction." );
73 }
74
75 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
76 {
77 throw std::runtime_error( "Prolongation: src and dst must have the same number of subdomains." );
78 }
79
80 for ( int i = 1; i <= 3; i++ )
81 {
82 if ( 2 * ( src_.extent( i ) - 1 ) != dst_.extent( i ) - 1 )
83 {
84 throw std::runtime_error( "Prolongation: src and dst must have a compatible number of cells." );
85 }
86 }
87
88 // Looping over the fine grid.
89 Kokkos::parallel_for(
90 "matvec",
91 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
92 { 0, 0, 0, 0 },
93 {
94 dst_.extent( 0 ),
95 dst_.extent( 1 ),
96 dst_.extent( 2 ),
97 dst_.extent( 3 ),
98 } ),
99 *this );
100
101 Kokkos::fence();
102 }
103
104 KOKKOS_INLINE_FUNCTION void
105 operator()( const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine ) const
106 {
107 dense::Vec< int, 4 > fine_hex_fine = { local_subdomain_id, x_fine, y_fine, r_fine };
108 (void) fine_hex_fine; // unused
109
110 if ( x_fine % 2 == 0 && y_fine % 2 == 0 && r_fine % 2 == 0 )
111 {
112 const auto x_coarse = x_fine / 2;
113 const auto y_coarse = y_fine / 2;
114 const auto r_coarse = r_fine / 2;
115
116 dst_( local_subdomain_id, x_fine, y_fine, r_fine ) +=
117 src_( local_subdomain_id, x_coarse, y_coarse, r_coarse );
118
119 return;
120 }
121
122 const auto r_coarse_bot = r_fine < dst_.extent( 3 ) - 1 ? r_fine / 2 : r_fine / 2 - 1;
123 const auto r_coarse_top = r_coarse_bot + 1;
124
125 if ( x_fine % 2 == 0 && y_fine % 2 == 0 )
126 {
127 const auto x_coarse = x_fine / 2;
128 const auto y_coarse = y_fine / 2;
129
131 dense::Vec< int, 4 >{ local_subdomain_id, x_fine, y_fine, r_fine },
132 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse, y_coarse, r_coarse_bot },
133 grid_fine_,
134 radii_fine_ );
135
136 dst_( local_subdomain_id, x_fine, y_fine, r_fine ) +=
137 weights( 0 ) * src_( local_subdomain_id, x_coarse, y_coarse, r_coarse_bot ) +
138 weights( 1 ) * src_( local_subdomain_id, x_coarse, y_coarse, r_coarse_top );
139
140 return;
141 }
142
143 int x_coarse_0 = -1;
144 int x_coarse_1 = -1;
145
146 int y_coarse_0 = -1;
147 int y_coarse_1 = -1;
148
149 if ( x_fine % 2 == 0 )
150 {
151 // "Vertical" edge.
152 x_coarse_0 = x_fine / 2;
153 x_coarse_1 = x_fine / 2;
154
155 y_coarse_0 = y_fine / 2;
156 y_coarse_1 = y_fine / 2 + 1;
157 }
158 else if ( y_fine % 2 == 0 )
159 {
160 // "Horizontal" edge.
161 x_coarse_0 = x_fine / 2;
162 x_coarse_1 = x_fine / 2 + 1;
163
164 y_coarse_0 = y_fine / 2;
165 y_coarse_1 = y_fine / 2;
166 }
167 else
168 {
169 // "Diagonal" edge.
170 x_coarse_0 = x_fine / 2 + 1;
171 x_coarse_1 = x_fine / 2;
172
173 y_coarse_0 = y_fine / 2;
174 y_coarse_1 = y_fine / 2 + 1;
175 }
176
178 dense::Vec< int, 4 >{ local_subdomain_id, x_fine, y_fine, r_fine },
179 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot },
180 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot },
181 grid_fine_,
182 radii_fine_ );
183
184 dst_( local_subdomain_id, x_fine, y_fine, r_fine ) +=
185 weights( 0 ) * src_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot ) +
186 weights( 0 ) * src_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot ) +
187 weights( 1 ) * src_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_top ) +
188 weights( 1 ) * src_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_top );
189 }
190};
191
192template < typename ScalarT >
194{
195 public:
198 using ScalarType = ScalarT;
200
201 private:
202 bool storeLMatrices_ =
203 false; // set to let apply_impl() know, that it should store the local matrices after assembling them
204 bool applyStoredLMatrices_ =
205 false; // set to make apply_impl() load and use the stored LMatrices for the operator application
206
207 Grid4DDataLocalMatrices LMatrices_;
208
211
212 linalg::OperatorApplyMode operator_apply_mode_;
213
216
217 public:
220 const grid::Grid2DDataScalar< ScalarType >& radii_fine,
222 : grid_fine_( grid_fine )
223 , radii_fine_( radii_fine )
224 , operator_apply_mode_( operator_apply_mode )
225 {}
226
227 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
228 {
229 if ( storeLMatrices_ or applyStoredLMatrices_ )
230 assert( LMatrices_.data() != nullptr );
231
232 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
233 {
234 assign( dst, 0 );
235 }
236
237 src_ = src.grid_data();
238 dst_ = dst.grid_data();
239
240 if ( dst_.extent( 1 ) != grid_fine_.extent( 1 ) )
241 {
242 throw std::runtime_error(
243 "Prolongation: dst and grid_fine must have the same number of cells in the x direction." );
244 }
245
246 if ( dst_.extent( 3 ) != radii_fine_.extent( 1 ) )
247 {
248 throw std::runtime_error(
249 "Prolongation: dst and radii_fine must have the same number of cells in the r direction." );
250 }
251
252 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
253 {
254 throw std::runtime_error( "Prolongation: src and dst must have the same number of subdomains." );
255 }
256
257 for ( int i = 1; i <= 3; i++ )
258 {
259 if ( 2 * ( src_.extent( i ) - 1 ) != dst_.extent( i ) - 1 )
260 {
261 throw std::runtime_error( "Prolongation: src and dst must have a compatible number of cells." );
262 }
263 }
264
265 // Looping over the fine grid.
266 Kokkos::parallel_for(
267 "matvec",
268 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
269 { 0, 0, 0, 0 },
270 {
271 dst_.extent( 0 ),
272 dst_.extent( 1 ),
273 dst_.extent( 2 ),
274 dst_.extent( 3 ),
275 } ),
276 *this );
277
278 Kokkos::fence();
279 }
280
281 KOKKOS_INLINE_FUNCTION void
282 operator()( const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine ) const
283 {
284 for ( int dim = 0; dim < 3; ++dim )
285 {
286 dense::Vec< int, 4 > fine_hex_fine = { local_subdomain_id, x_fine, y_fine, r_fine };
287 (void) fine_hex_fine; // unused
288
289 if ( x_fine % 2 == 0 && y_fine % 2 == 0 && r_fine % 2 == 0 )
290 {
291 const auto x_coarse = x_fine / 2;
292 const auto y_coarse = y_fine / 2;
293 const auto r_coarse = r_fine / 2;
294
295 dst_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) +=
296 src_( local_subdomain_id, x_coarse, y_coarse, r_coarse, dim );
297
298 return;
299 }
300
301 const auto r_coarse_bot = r_fine < dst_.extent( 3 ) - 1 ? r_fine / 2 : r_fine / 2 - 1;
302 const auto r_coarse_top = r_coarse_bot + 1;
303
304 if ( x_fine % 2 == 0 && y_fine % 2 == 0 )
305 {
306 const auto x_coarse = x_fine / 2;
307 const auto y_coarse = y_fine / 2;
308
310 dense::Vec< int, 4 >{ local_subdomain_id, x_fine, y_fine, r_fine },
311 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse, y_coarse, r_coarse_bot },
312 grid_fine_,
313 radii_fine_ );
314
315 dst_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) +=
316 weights( 0 ) * src_( local_subdomain_id, x_coarse, y_coarse, r_coarse_bot, dim ) +
317 weights( 1 ) * src_( local_subdomain_id, x_coarse, y_coarse, r_coarse_top, dim );
318
319 return;
320 }
321
322 int x_coarse_0 = -1;
323 int x_coarse_1 = -1;
324
325 int y_coarse_0 = -1;
326 int y_coarse_1 = -1;
327
328 if ( x_fine % 2 == 0 )
329 {
330 // "Vertical" edge.
331 x_coarse_0 = x_fine / 2;
332 x_coarse_1 = x_fine / 2;
333
334 y_coarse_0 = y_fine / 2;
335 y_coarse_1 = y_fine / 2 + 1;
336 }
337 else if ( y_fine % 2 == 0 )
338 {
339 // "Horizontal" edge.
340 x_coarse_0 = x_fine / 2;
341 x_coarse_1 = x_fine / 2 + 1;
342
343 y_coarse_0 = y_fine / 2;
344 y_coarse_1 = y_fine / 2;
345 }
346 else
347 {
348 // "Diagonal" edge.
349 x_coarse_0 = x_fine / 2 + 1;
350 x_coarse_1 = x_fine / 2;
351
352 y_coarse_0 = y_fine / 2;
353 y_coarse_1 = y_fine / 2 + 1;
354 }
355
357 dense::Vec< int, 4 >{ local_subdomain_id, x_fine, y_fine, r_fine },
358 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot },
359 dense::Vec< int, 4 >{ local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot },
360 grid_fine_,
361 radii_fine_ );
362
363 dst_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) +=
364 weights( 0 ) * src_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot, dim ) +
365 weights( 0 ) * src_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot, dim ) +
366 weights( 1 ) * src_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_top, dim ) +
367 weights( 1 ) * src_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_top, dim );
368 }
369 }
370};
371} // namespace terra::fe::wedge::operators::shell
Definition prolongation_linear.hpp:17
void operator()(const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine) const
Definition prolongation_linear.hpp:105
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition prolongation_linear.hpp:50
ScalarT ScalarType
Definition prolongation_linear.hpp:21
terra::grid::Grid4DDataMatrices< ScalarType, 6, 6, 2 > Grid4DDataLocalMatrices
Definition prolongation_linear.hpp:22
ProlongationLinear(const grid::Grid3DDataVec< ScalarType, 3 > &grid_fine, const grid::Grid2DDataScalar< ScalarType > &radii_fine, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace)
Definition prolongation_linear.hpp:41
Definition prolongation_linear.hpp:194
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition prolongation_linear.hpp:227
ScalarT ScalarType
Definition prolongation_linear.hpp:198
terra::grid::Grid4DDataMatrices< ScalarType, 6, 6, 2 > Grid4DDataLocalMatrices
Definition prolongation_linear.hpp:199
ProlongationVecLinear(const grid::Grid3DDataVec< ScalarType, 3 > &grid_fine, const grid::Grid2DDataScalar< ScalarType > &radii_fine, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace)
Definition prolongation_linear.hpp:218
void operator()(const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine) const
Definition prolongation_linear.hpp:282
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
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< dense::Mat< ScalarType, Rows, Cols > ****[NumMatrices], Layout > Grid4DDataMatrices
Definition grid_types.hpp:46
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.
Definition vec.hpp:9