Loading...
Searching...
No Matches
epsilon_divdiv.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"
11#include "linalg/vector.hpp"
12#include "linalg/vector_q1.hpp"
13#include "util/timer.hpp"
14
16
17template < typename ScalarT, int VecDim = 3 >
19{
20 public:
23 using ScalarType = ScalarT;
24 static constexpr int LocalMatrixDim = 18;
27
28 private:
29 LocalMatrixStorage local_matrix_storage_;
30
32
37
38 bool treat_boundary_;
39 bool diagonal_;
40
41 linalg::OperatorApplyMode operator_apply_mode_;
42 linalg::OperatorCommunicationMode operator_communication_mode_;
43 linalg::OperatorStoredMatrixMode operator_stored_matrix_mode_;
44
47
50
51 // Quadrature points.
52 const int num_quad_points = quadrature::quad_felippa_3x2_num_quad_points;
53
56
57 public:
64 bool treat_boundary,
65 bool diagonal,
67 linalg::OperatorCommunicationMode operator_communication_mode =
70 : domain_( domain )
71 , grid_( grid )
72 , radii_( radii )
73 , mask_( mask )
74 , k_( k )
75 , treat_boundary_( treat_boundary )
76 , diagonal_( diagonal )
77 , operator_apply_mode_( operator_apply_mode )
78 , operator_communication_mode_( operator_communication_mode )
79 , operator_stored_matrix_mode_( operator_stored_matrix_mode )
80 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
81 , send_buffers_( domain )
82 , recv_buffers_( domain )
83 {
86 }
87
89 const linalg::OperatorApplyMode operator_apply_mode,
90 const linalg::OperatorCommunicationMode operator_communication_mode )
91 {
92 operator_apply_mode_ = operator_apply_mode;
93 operator_communication_mode_ = operator_communication_mode;
94 }
95
96 /// @brief S/Getter for diagonal member
97 void set_diagonal( bool v ) { diagonal_ = v; }
98
99 /// @brief Getter for coefficient
101
102 /// @brief Getter for domain member
103 const grid::shell::DistributedDomain& get_domain() const { return domain_; }
104
105 /// @brief Getter for radii member
107
108 /// @brief Getter for grid member
110
111 /// @brief Getter for mask member
112 KOKKOS_INLINE_FUNCTION
114 const int local_subdomain_id,
115 const int x_cell,
116 const int y_cell,
117 const int r_cell,
119 {
120 return util::has_flag( mask_( local_subdomain_id, x_cell, y_cell, r_cell ), flag );
121 }
122 /// @brief allocates memory for the local matrices
124 linalg::OperatorStoredMatrixMode operator_stored_matrix_mode,
125 std::optional< int > level_range,
126 std::optional< grid::Grid4DDataScalar< ScalarType > > GCAElements )
127 {
128 operator_stored_matrix_mode_ = operator_stored_matrix_mode;
129
130 // allocate storage if necessary
131 if ( operator_stored_matrix_mode_ != linalg::OperatorStoredMatrixMode::Off )
132 {
134 domain_, operator_stored_matrix_mode_, level_range, GCAElements );
135 }
136 }
137
138 linalg::OperatorStoredMatrixMode get_stored_matrix_mode() { return operator_stored_matrix_mode_; }
139
140 /// @brief Set the local matrix stored in the operator
141 KOKKOS_INLINE_FUNCTION
143 const int local_subdomain_id,
144 const int x_cell,
145 const int y_cell,
146 const int r_cell,
147 const int wedge,
149 {
150 KOKKOS_ASSERT( operator_stored_matrix_mode_ != linalg::OperatorStoredMatrixMode::Off );
151 local_matrix_storage_.set_matrix( local_subdomain_id, x_cell, y_cell, r_cell, wedge, mat );
152 }
153
154 /// @brief Retrives the local matrix
155 /// if there is stored local matrices, the desired local matrix is loaded and returned
156 /// if not, the local matrix is assembled on-the-fly
157 KOKKOS_INLINE_FUNCTION
159 const int local_subdomain_id,
160 const int x_cell,
161 const int y_cell,
162 const int r_cell,
163 const int wedge ) const
164 {
165 // request from storage
166 if ( operator_stored_matrix_mode_ != linalg::OperatorStoredMatrixMode::Off )
167 {
168 if ( !local_matrix_storage_.has_matrix( local_subdomain_id, x_cell, y_cell, r_cell, wedge ) )
169 {
170 Kokkos::abort( "No matrix found at that spatial index." );
171 }
172 return local_matrix_storage_.get_matrix( local_subdomain_id, x_cell, y_cell, r_cell, wedge );
173 }
174 else
175 {
176 return assemble_local_matrix( local_subdomain_id, x_cell, y_cell, r_cell, wedge );
177 }
178 }
179
180 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
181 {
182 util::Timer timer_apply( "epsilon_divdiv_apply" );
183
184 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
185 {
186 assign( dst, 0 );
187 }
188
189 src_ = src.grid_data();
190 dst_ = dst.grid_data();
191
192 if ( src_.extent( 0 ) != dst_.extent( 0 ) || src_.extent( 1 ) != dst_.extent( 1 ) ||
193 src_.extent( 2 ) != dst_.extent( 2 ) || src_.extent( 3 ) != dst_.extent( 3 ) )
194 {
195 throw std::runtime_error( "EpsilonDivDiv: src/dst mismatch" );
196 }
197
198 if ( src_.extent( 1 ) != grid_.extent( 1 ) || src_.extent( 2 ) != grid_.extent( 2 ) )
199 {
200 throw std::runtime_error( "EpsilonDivDiv: src/dst mismatch" );
201 }
202
203 util::Timer timer_kernel( "epsilon_divdiv_kernel" );
204 Kokkos::parallel_for( "matvec", grid::shell::local_domain_md_range_policy_cells( domain_ ), *this );
205 Kokkos::fence();
206 timer_kernel.stop();
207
208 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
209 {
210 util::Timer timer_comm( "epsilon_divdiv_comm" );
211
213 domain_, dst_, send_buffers_, recv_buffers_ );
215 }
216 }
217
218 KOKKOS_INLINE_FUNCTION void
219 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
220 {
221 // If we have stored lmatrices, use them.
222 // It's the user's responsibility to write meaningful matrices via set_lmatrix()
223 // We probably never want to assemble lmatrices with DCA and store,
224 // so GCA should be the actor storing matrices.
225 // use stored matrices (at least on some elements)
226 if ( operator_stored_matrix_mode_ != linalg::OperatorStoredMatrixMode::Off )
227 {
229
230 if ( operator_stored_matrix_mode_ == linalg::OperatorStoredMatrixMode::Full )
231 {
232 A[0] = local_matrix_storage_.get_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 0 );
233 A[1] = local_matrix_storage_.get_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 1 );
234 }
235 else if ( operator_stored_matrix_mode_ == linalg::OperatorStoredMatrixMode::Selective )
236 {
237 if ( local_matrix_storage_.has_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 0 ) &&
238 local_matrix_storage_.has_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 1 ) )
239 {
240 A[0] = local_matrix_storage_.get_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 0 );
241 A[1] = local_matrix_storage_.get_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 1 );
242 }
243 else
244 {
245 // Kokkos::abort("Matrix not found.");
246 A[0] = assemble_local_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 0 );
247 A[1] = assemble_local_matrix( local_subdomain_id, x_cell, y_cell, r_cell, 1 );
248 }
249 }
250 // BCs are applied by GCA ... to be discussed for free-slip
251
252 if ( diagonal_ )
253 {
254 A[0] = A[0].diagonal();
255 A[1] = A[1].diagonal();
256 }
257
259 for ( int dimj = 0; dimj < 3; dimj++ )
260 {
263 src_d, local_subdomain_id, x_cell, y_cell, r_cell, dimj, src_ );
264
265 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
266 {
267 for ( int i = 0; i < num_nodes_per_wedge; i++ )
268 {
269 src[wedge]( dimj * num_nodes_per_wedge + i ) = src_d[wedge]( i );
270 }
271 }
272 }
273
275
276 dst[0] = A[0] * src[0];
277 dst[1] = A[1] * src[1];
278
279 for ( int dimi = 0; dimi < 3; dimi++ )
280 {
282 dst_d[0] = dst[0].template slice< 6 >( dimi * num_nodes_per_wedge );
283 dst_d[1] = dst[1].template slice< 6 >( dimi * num_nodes_per_wedge );
284
286 dst_, local_subdomain_id, x_cell, y_cell, r_cell, dimi, dst_d );
287 }
288 }
289 else
290 {
291 // Gather surface points for each wedge.
293 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
294
295 // Gather wedge radii.
296 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
297 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
298
300 extract_local_wedge_scalar_coefficients( k_local_hex, local_subdomain_id, x_cell, y_cell, r_cell, k_ );
301
302 constexpr int hex_offset_x[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
303 constexpr int hex_offset_y[8] = { 0, 0, 1, 1, 0, 0, 1, 1 };
304 constexpr int hex_offset_r[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
305
306 // FE dimensions: velocity coupling components of epsilon operator
307
308 for ( int dimi = 0; dimi < 3; ++dimi )
309 {
310 for ( int dimj = 0; dimj < 3; ++dimj )
311 {
312 if ( diagonal_ and dimi != dimj )
313 continue;
314
315 ScalarType src_local_hex[8] = {};
316 ScalarType dst_local_hex[8] = {};
317
318 for ( int i = 0; i < 8; i++ )
319 {
320 src_local_hex[i] = src_(
321 local_subdomain_id,
322 x_cell + hex_offset_x[i],
323 y_cell + hex_offset_y[i],
324 r_cell + hex_offset_r[i],
325 dimi );
326 }
327
328 // spatial dimensions: quadrature points and wedge
329 for ( int q = 0; q < num_quad_points; q++ )
330 {
331 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
332 {
335 ScalarType jdet_keval_quadweight = 0;
336
338 wedge,
339 quad_points[q],
340 quad_weights[q],
341 r_1,
342 r_2,
343 wedge_phy_surf,
344 k_local_hex,
345 dimi,
346 dimj,
347 sym_grad_i,
348 sym_grad_j,
349 jdet_keval_quadweight );
350
352 src_local_hex,
353 dst_local_hex,
354 wedge,
355 jdet_keval_quadweight,
356 sym_grad_i,
357 sym_grad_j,
358 dimi,
359 dimj,
360 r_cell );
361 }
362 }
363
364 for ( int i = 0; i < 8; i++ )
365 {
366 Kokkos::atomic_add(
367 &dst_(
368 local_subdomain_id,
369 x_cell + hex_offset_x[i],
370 y_cell + hex_offset_y[i],
371 r_cell + hex_offset_r[i],
372 dimj ),
373 dst_local_hex[i] );
374 }
375 }
376 }
377 }
378 }
379
380 /// @brief: For both trial and test space this function sets up a vector:
381 /// each vector element holds the symmetric gradient (a 3x3 matrix) of the shape function of the corresponding dof
382 /// (if dimi == dimj, these are the same and we are on the diagonal of the vectorial diffusion operator)
383 /// Additionally, we compute the scalar factor for the numerical integral comp: determinant of the jacobian,
384 /// evaluation of the coefficient k on the element and the quadrature weight of the current quad-point.
385
386 /// The idea of this function is that the two vectors can be:
387 /// - accumulated to the result of the local matvec with 2 * num_nodes_per_wedge complexity
388 /// by scaling the dot product of the trial vec and local src dofs with each element of the test vec
389 /// (and adding to the dst dofs, this is the fused local matvec).
390 /// - propagated to the local matrix by an outer product of the two vectors
391 /// (without applying it to dofs). This is e.g. required to assemble the finest grid local
392 /// matrix on-the-fly during GCA/Galerkin coarsening.
393
394 ///
395 KOKKOS_INLINE_FUNCTION void assemble_trial_test_vecs(
396 const int wedge,
397 const dense::Vec< ScalarType, VecDim >& quad_point,
398 const ScalarType quad_weight,
399 const ScalarT r_1,
400 const ScalarT r_2,
401 dense::Vec< ScalarT, 3 > ( *wedge_phy_surf )[3],
402 const dense::Vec< ScalarT, 6 >* k_local_hex,
403 const int dimi,
404 const int dimj,
407 ScalarType& jdet_keval_quadweight ) const
408 {
409 dense::Mat< ScalarType, VecDim, VecDim > J = jac( wedge_phy_surf[wedge], r_1, r_2, quad_point );
410 const auto det = J.det();
411 const auto abs_det = Kokkos::abs( det );
412 const dense::Mat< ScalarType, VecDim, VecDim > J_inv_transposed = J.inv_transposed( det );
413
414 // dot of coeff dofs and element-local shape functions to evaluate the coefficent on the current element
415 ScalarType k_eval = 0.0;
416 for ( int k = 0; k < num_nodes_per_wedge; k++ )
417 {
418 k_eval += shape( k, quad_point ) * k_local_hex[wedge]( k );
419 }
420
421 for ( int k = 0; k < num_nodes_per_wedge; k++ )
422 {
423 sym_grad_i[k] = symmetric_grad( J_inv_transposed, quad_point, k, dimi );
424 sym_grad_j[k] = symmetric_grad( J_inv_transposed, quad_point, k, dimj );
425 }
426 jdet_keval_quadweight = quad_weight * k_eval * abs_det;
427 }
428
429 /// @brief assemble the local matrix and return it for a given element, wedge, and vectorial component
430 /// (determined by dimi, dimj)
431 KOKKOS_INLINE_FUNCTION
433 const int local_subdomain_id,
434 const int x_cell,
435 const int y_cell,
436 const int r_cell,
437 const int wedge ) const
438 {
439 // Gather surface points for each wedge.
440 // TODO gather this for only 1 wedge
442 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
443
444 // Gather wedge radii.
445 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
446 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
447
449 extract_local_wedge_scalar_coefficients( k_local_hex, local_subdomain_id, x_cell, y_cell, r_cell, k_ );
450
451 // Compute the local element matrix.
453 for ( int dimi = 0; dimi < 3; ++dimi )
454 {
455 for ( int dimj = 0; dimj < 3; ++dimj )
456 {
457 // spatial dimensions: quadrature points and wedge
458 for ( int q = 0; q < num_quad_points; q++ )
459 {
462 ScalarType jdet_keval_quadweight = 0;
464 wedge,
465 quad_points[q],
466 quad_weights[q],
467 r_1,
468 r_2,
469 wedge_phy_surf,
470 k_local_hex,
471 dimi,
472 dimj,
473 sym_grad_i,
474 sym_grad_j,
475 jdet_keval_quadweight );
476
477 // propagate on local matrix by outer product of test and trial vecs
478 for ( int i = 0; i < num_nodes_per_wedge; i++ )
479 {
480 for ( int j = 0; j < num_nodes_per_wedge; j++ )
481 {
482 A( i + dimi * num_nodes_per_wedge, j + dimj * num_nodes_per_wedge ) +=
483 jdet_keval_quadweight *
484 ( 2 * sym_grad_j[j].double_contract( sym_grad_i[i] ) -
485 2.0 / 3.0 * sym_grad_j[j]( dimj, dimj ) * sym_grad_i[i]( dimi, dimi ) );
486 // for the div, we just extract the component from the gradient vector
487 }
488 }
489 }
490 }
491 }
492
493 if ( treat_boundary_ )
494 {
496 boundary_mask.fill( 1.0 );
497
498 for ( int dimi = 0; dimi < 3; ++dimi )
499 {
500 for ( int dimj = 0; dimj < 3; ++dimj )
501 {
502 if ( r_cell == 0 )
503 {
504 // Inner boundary (CMB).
505 for ( int i = 0; i < 6; i++ )
506 {
507 for ( int j = 0; j < 6; j++ )
508 {
509 // on diagonal components of the vectorial diffusion operator, we exclude the diagonal entries from elimination
510 if ( ( dimi == dimj && i != j && ( i < 3 || j < 3 ) ) or
511 ( dimi != dimj && ( i < 3 || j < 3 ) ) )
512 {
513 boundary_mask( i + dimi * num_nodes_per_wedge, j + dimj * num_nodes_per_wedge ) =
514 0.0;
515 }
516 }
517 }
518 }
519
520 if ( r_cell + 1 == radii_.extent( 1 ) - 1 )
521 {
522 // Outer boundary (surface).
523 for ( int i = 0; i < 6; i++ )
524 {
525 for ( int j = 0; j < 6; j++ )
526 {
527 // on diagonal components of the vectorial diffusion operator, we exclude the diagonal entries from elimination
528 if ( ( dimi == dimj && i != j && ( i >= 3 || j >= 3 ) ) or
529 ( dimi != dimj && ( i >= 3 || j >= 3 ) ) )
530 {
531 boundary_mask( i + dimi * num_nodes_per_wedge, j + dimj * num_nodes_per_wedge ) =
532 0.0;
533 }
534 }
535 }
536 }
537 }
538 }
539 A.hadamard_product( boundary_mask );
540 }
541
542 return A;
543 }
544
545 // executes the fused local matvec on an element, given the assembled trial and test vectors
546 KOKKOS_INLINE_FUNCTION void fused_local_mv(
547 ScalarType src_local_hex[8],
548 ScalarType dst_local_hex[8],
549 const int wedge,
550 const ScalarType jdet_keval_quadweight,
553 const int dimi,
554 const int dimj,
555 int r_cell ) const
556 {
557 constexpr int offset_x[2][6] = { { 0, 1, 0, 0, 1, 0 }, { 1, 0, 1, 1, 0, 1 } };
558 constexpr int offset_y[2][6] = { { 0, 0, 1, 0, 0, 1 }, { 1, 1, 0, 1, 1, 0 } };
559 constexpr int offset_r[2][6] = { { 0, 0, 0, 1, 1, 1 }, { 0, 0, 0, 1, 1, 1 } };
560
562 ScalarType divu = 0.0;
563 grad_u.fill( 0.0 );
564
565 const bool at_cmb = r_cell == 0;
566 const bool at_surface = r_cell + 1 == radii_.extent( 1 ) - 1;
567 int cmb_shift = 0;
568 int surface_shift = 0;
569
570 // Compute ∇u at this quadrature point.
571 if ( !diagonal_ )
572 {
573 if ( treat_boundary_ && at_cmb )
574 {
575 // at the core-mantle boundary, we exclude dofs that are lower-indexed than the dof on the boundary
576 cmb_shift = 3;
577 }
578 else if ( treat_boundary_ && at_surface )
579 {
580 // at the surface boundary, we exclude dofs that are higher-indexed than the dof on the boundary
581 surface_shift = 3;
582 }
583
584 // accumulate the element-local gradient/divergence of the trial function (loop over columns of local matrix/local dofs)
585 // by dot of trial vec and src dofs
586 for ( int i = 0 + cmb_shift; i < num_nodes_per_wedge - surface_shift; i++ )
587 {
588 grad_u =
589 grad_u +
590 sym_grad_i[i] * src_local_hex[4 * offset_r[wedge][i] + 2 * offset_y[wedge][i] + offset_x[wedge][i]];
591 divu += sym_grad_i[i]( dimi, dimi ) *
592 src_local_hex[4 * offset_r[wedge][i] + 2 * offset_y[wedge][i] + offset_x[wedge][i]];
593 }
594
595 // Add the test function contributions.
596 // for each row of the local matrix (test-functions):
597 // multiply trial part (fully assembled for the current element from loop above) with test part corresponding to the current row/dof
598 // += due to contributions from other elements
599 for ( int j = 0 + cmb_shift; j < num_nodes_per_wedge - surface_shift; j++ )
600 {
601 dst_local_hex[4 * offset_r[wedge][j] + 2 * offset_y[wedge][j] + offset_x[wedge][j]] +=
602 jdet_keval_quadweight * ( 2 * ( sym_grad_j[j] ).double_contract( grad_u ) -
603 2.0 / 3.0 * sym_grad_j[j]( dimj, dimj ) * divu );
604 // for the div, we just extract the component from the gradient vector
605 }
606 }
607
608 // Dirichlet DoFs are only to be eliminated on diagonal blocks of epsilon
609 if ( diagonal_ || ( dimi == dimj && ( treat_boundary_ && ( at_cmb || at_surface ) ) ) )
610 {
611 // for the diagonal elements at the boundary, we switch the shifts
612 for ( int i = 0 + surface_shift; i < num_nodes_per_wedge - cmb_shift; i++ )
613 {
614 const auto grad_u_diag =
615 sym_grad_i[i] * src_local_hex[4 * offset_r[wedge][i] + 2 * offset_y[wedge][i] + offset_x[wedge][i]];
616 const auto div_u_diag =
617 sym_grad_i[i]( dimi, dimi ) *
618 src_local_hex[4 * offset_r[wedge][i] + 2 * offset_y[wedge][i] + offset_x[wedge][i]];
619
620 dst_local_hex[4 * offset_r[wedge][i] + 2 * offset_y[wedge][i] + offset_x[wedge][i]] +=
621 jdet_keval_quadweight * ( 2 * ( sym_grad_j[i] ).double_contract( grad_u_diag ) -
622 2.0 / 3.0 * sym_grad_j[i]( dimj, dimj ) * div_u_diag );
623 }
624 }
625 }
626};
627
630
631} // namespace terra::fe::wedge::operators::shell
Send and receive buffers for all process-local subdomain boundaries.
Definition communication.hpp:56
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Definition epsilon_divdiv.hpp:219
linalg::OperatorStoredMatrixMode get_stored_matrix_mode()
Definition epsilon_divdiv.hpp:138
bool has_flag(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, grid::shell::ShellBoundaryFlag flag) const
Getter for mask member.
Definition epsilon_divdiv.hpp:113
static constexpr int LocalMatrixDim
Definition epsilon_divdiv.hpp:24
void assemble_trial_test_vecs(const int wedge, const dense::Vec< ScalarType, VecDim > &quad_point, const ScalarType quad_weight, const ScalarT r_1, const ScalarT r_2, dense::Vec< ScalarT, 3 >(*wedge_phy_surf)[3], const dense::Vec< ScalarT, 6 > *k_local_hex, const int dimi, const int dimj, dense::Mat< ScalarType, VecDim, VecDim > *sym_grad_i, dense::Mat< ScalarType, VecDim, VecDim > *sym_grad_j, ScalarType &jdet_keval_quadweight) const
: For both trial and test space this function sets up a vector: each vector element holds the symmetr...
Definition epsilon_divdiv.hpp:395
ScalarT ScalarType
Definition epsilon_divdiv.hpp:23
grid::Grid2DDataScalar< ScalarT > get_radii() const
Getter for radii member.
Definition epsilon_divdiv.hpp:106
EpsilonDivDiv(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, linalg::OperatorStoredMatrixMode operator_stored_matrix_mode=linalg::OperatorStoredMatrixMode::Off)
Definition epsilon_divdiv.hpp:58
void fused_local_mv(ScalarType src_local_hex[8], ScalarType dst_local_hex[8], const int wedge, const ScalarType jdet_keval_quadweight, dense::Mat< ScalarType, 3, 3 > *sym_grad_i, dense::Mat< ScalarType, 3, 3 > *sym_grad_j, const int dimi, const int dimj, int r_cell) const
Definition epsilon_divdiv.hpp:546
void set_operator_apply_and_communication_modes(const linalg::OperatorApplyMode operator_apply_mode, const linalg::OperatorCommunicationMode operator_communication_mode)
Definition epsilon_divdiv.hpp:88
void set_stored_matrix_mode(linalg::OperatorStoredMatrixMode operator_stored_matrix_mode, std::optional< int > level_range, std::optional< grid::Grid4DDataScalar< ScalarType > > GCAElements)
allocates memory for the local matrices
Definition epsilon_divdiv.hpp:123
const grid::shell::DistributedDomain & get_domain() const
Getter for domain member.
Definition epsilon_divdiv.hpp:103
grid::Grid3DDataVec< ScalarT, 3 > get_grid()
Getter for grid member.
Definition epsilon_divdiv.hpp:109
void set_local_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge, const dense::Mat< ScalarT, LocalMatrixDim, LocalMatrixDim > &mat) const
Set the local matrix stored in the operator.
Definition epsilon_divdiv.hpp:142
dense::Mat< ScalarT, LocalMatrixDim, LocalMatrixDim > assemble_local_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge) const
assemble the local matrix and return it for a given element, wedge, and vectorial component (determin...
Definition epsilon_divdiv.hpp:432
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition epsilon_divdiv.hpp:180
dense::Mat< ScalarT, LocalMatrixDim, LocalMatrixDim > get_local_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge) const
Retrives the local matrix if there is stored local matrices, the desired local matrix is loaded and r...
Definition epsilon_divdiv.hpp:158
terra::grid::Grid4DDataMatrices< ScalarType, LocalMatrixDim, LocalMatrixDim, 2 > Grid4DDataLocalMatrices
Definition epsilon_divdiv.hpp:25
void set_diagonal(bool v)
S/Getter for diagonal member.
Definition epsilon_divdiv.hpp:97
const grid::Grid4DDataScalar< ScalarType > & k_grid_data()
Getter for coefficient.
Definition epsilon_divdiv.hpp:100
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
bool has_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge) const
Checks for presence of a local matrix for a certain element.
Definition local_matrix_storage.hpp:223
dense::Mat< ScalarT, LocalMatrixDim, LocalMatrixDim > get_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge) const
Retrives the local matrix if there is stored local matrices, the desired local matrix is loaded and r...
Definition local_matrix_storage.hpp:175
void set_matrix(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int wedge, dense::Mat< ScalarT, LocalMatrixDim, LocalMatrixDim > mat) const
Set the local matrix stored in the operator.
Definition local_matrix_storage.hpp:118
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 can be used as Galerkin coarse-grid operators in a multigrid hierarchy....
Definition operator.hpp:81
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
constexpr dense::Mat< T, 3, 3 > symmetric_grad(const dense::Mat< T, 3, 3 > &J_inv_transposed, const dense::Vec< T, 3 > &quad_point, const int dof, const int dim)
Returns the symmetric gradient of the shape function of a dof at a quadrature point.
Definition integrands.hpp:671
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 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
ShellBoundaryFlag
FlagLike that indicates boundary types for the thick spherical shell.
Definition shell/bit_masks.hpp:12
Kokkos::MDRangePolicy< Kokkos::Rank< 4 > > local_domain_md_range_policy_cells(const DistributedDomain &distributed_domain)
Definition spherical_shell.hpp:2668
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.
OperatorStoredMatrixMode
Modes for applying stored matrices.
Definition operator.hpp:47
@ Selective
Use stored matrices on selected, marked elements only, assemble on all others.
@ Full
Use stored matrices on all elements.
@ Off
Do not use stored matrices.
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
Mat & hadamard_product(const Mat &mat)
Definition mat.hpp:213
T double_contract(const Mat &mat)
Definition mat.hpp:226