Loading...
Searching...
No Matches
gca.hpp
Go to the documentation of this file.
1
2
3#pragma once
4
6#include "dense/vec.hpp"
11#include "grid/grid_types.hpp"
12#include "linalg/operator.hpp"
14#include "linalg/vector.hpp"
15#include "linalg/vector_q1.hpp"
16
19
23namespace terra::linalg::solvers {
24
25/// @brief Modes for choosing interpolation weights.
27{
29 Linear,
30 //OpDep?
31};
32
33/// @brief: Galerkin coarse approximation (GCA).
34/// TwoGridGCA takes a coarser and a finer operator. Each thread assembles a
35/// coarse-grid gca matrix in the coarser operator on a single hex. To do this, it loops
36/// the finer hexes of the coarse hex and its respective wedges. It computes the interpolation
37/// matrix P mapping from coarse wedge to the current fine wedge, computes the
38/// triple-product P^TAP with the fine-operator local matrix A and adds the resulting gca matrix
39/// up for all fine wedges comprising the coarse wedge. Finally, it stores the result in the
40/// wedge-wise matrix storage of the coarse operator.
41template < typename ScalarT, terra::linalg::GCACapable Operator >
43{
44 public:
47 using ScalarType = ScalarT;
48
49 private:
51 Operator fine_op_;
52 Operator coarse_op_;
56 bool treat_boundary_;
57
58 int level_range_;
60 InterpolationMode interpolation_mode_;
61
62 public:
63 /// @brief GCA Ctor
64 /// Assembles Galerkin coarse-grid operators in the coarse-op passed.
65 /// @param fine_op: operator on the finer grid to derive the coarse-grid operators from
66 /// @param coarse_op: operator on the coarser grid to store the coarse-grid operators in
67 /// @param level_range: max_level - min_level range used in the app: required check whether a certain element
68 /// is a child of a GCA element.
69 /// @param GCAElements: map of coarsest-grid elements, on which GCA should be used. Using this and level_range,
70 /// the GCA can check for a certain element whether it is a child of a marked coarsest-grid
71 /// element. If that is the case, GCA is applied to it.
72 explicit TwoGridGCA(
73 Operator fine_op,
74 Operator coarse_op,
75 int level_range,
77 bool treat_boundary = true,
79 : domain_fine_( fine_op.get_domain() )
80 , fine_op_( fine_op )
81 , coarse_op_( coarse_op )
82 , grid_fine_( fine_op.get_grid() )
83 , radii_fine_( fine_op.get_radii() )
84 , radii_coarse_( coarse_op.get_radii() )
85 , GCAElements_( GCAElements )
86 , level_range_( level_range )
87 , treat_boundary_( treat_boundary )
88 , interpolation_mode_( interpolation_mode )
89 {
90 // assert( coarse_op_.get_stored_matrix_mode() != linalg::OperatorStoredMatrixMode::Off );
91
92 // this probably cant not happen
93 if ( coarse_op.get_domain().subdomains().size() != domain_fine_.subdomains().size() )
94 {
95 throw std::runtime_error( "Prolongation: src and dst must have a compatible number of subdomains." );
96 }
97
98 if ( 2 * ( coarse_op.get_domain().domain_info().subdomain_num_nodes_per_side_laterally() - 1 ) !=
100 {
101 throw std::runtime_error( "Prolongation: src and dst must have a compatible number of lateral cells." );
102 }
103 if ( 2 * ( coarse_op.get_domain().domain_info().subdomain_num_nodes_radially() - 1 ) !=
104 domain_fine_.domain_info().subdomain_num_nodes_radially() - 1 )
105 {
106 throw std::runtime_error( "Prolongation: src and dst must have a compatible number of radial cells." );
107 }
108
109 // Looping over the coarse grid.
110 Kokkos::parallel_for(
111 "gca_coarsening",
112 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
113 { 0, 0, 0, 0 },
114 {
115 static_cast< long long >( coarse_op.get_domain().subdomains().size() ),
116 coarse_op.get_domain().domain_info().subdomain_num_nodes_per_side_laterally() - 1,
117 coarse_op.get_domain().domain_info().subdomain_num_nodes_per_side_laterally() - 1,
118 coarse_op.get_domain().domain_info().subdomain_num_nodes_radially() - 1,
119 } ),
120 *this );
121
122 Kokkos::fence();
123 }
124
125 /// @brief Computes indices of vertices associated to a wedge in a hex cell.
126 /// @param coarse_hex_idx [in] global index of the hex cell
127 /// @param wedge [in] wedge index (local index 0 or 1)
128 /// @param wedge_local_vertex_indices [out] global indices of the vertices located on the wedge
129 KOKKOS_INLINE_FUNCTION void wedge_vertex_indices(
130 dense::Vec< int, 4 > hex_idx,
131 int wedge,
132 dense::Vec< int, 4 > ( &wedge_local_vertex_indices )[6] ) const
133 {
134 if ( wedge == 0 )
135 {
136 wedge_local_vertex_indices[0] = hex_idx;
137 wedge_local_vertex_indices[1] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 0, 0 } );
138 wedge_local_vertex_indices[2] = hex_idx + dense::Vec< int, 4 >( { 0, 0, 1, 0 } );
139 wedge_local_vertex_indices[3] = hex_idx + dense::Vec< int, 4 >( { 0, 0, 0, 1 } );
140 wedge_local_vertex_indices[4] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 0, 1 } );
141 wedge_local_vertex_indices[5] = hex_idx + dense::Vec< int, 4 >( { 0, 0, 1, 1 } );
142 }
143 else
144 {
145 wedge_local_vertex_indices[0] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 1, 0 } );
146 wedge_local_vertex_indices[1] = hex_idx + dense::Vec< int, 4 >( { 0, 0, 1, 0 } );
147 wedge_local_vertex_indices[2] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 0, 0 } );
148 wedge_local_vertex_indices[3] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 1, 1 } );
149 wedge_local_vertex_indices[4] = hex_idx + dense::Vec< int, 4 >( { 0, 0, 1, 1 } );
150 wedge_local_vertex_indices[5] = hex_idx + dense::Vec< int, 4 >( { 0, 1, 0, 1 } );
151 }
152 }
153
154 KOKKOS_INLINE_FUNCTION void operator()(
155 const int local_subdomain_id,
156 const int x_coarse_idx,
157 const int y_coarse_idx,
158 const int r_coarse_idx ) const
159 {
160 int x_cell_coarsest = map_to_coarse_element( x_coarse_idx, level_range_ );
161 int y_cell_coarsest = map_to_coarse_element( y_coarse_idx, level_range_ );
162 int r_cell_coarsest = map_to_coarse_element( r_coarse_idx, level_range_ );
163 if ( GCAElements_( local_subdomain_id, x_cell_coarsest, y_cell_coarsest, r_cell_coarsest ) > 0 )
164 {
165 dense::Vec< int, 4 > fine_hex_shifts[8] = {
166 { 0, 0, 0, 0 },
167 { 0, 1, 0, 0 },
168 { 0, 0, 1, 0 },
169 { 0, 1, 1, 0 },
170 { 0, 0, 0, 1 },
171 { 0, 1, 0, 1 },
172 { 0, 0, 1, 1 },
173 { 0, 1, 1, 1 },
174 };
175
176 dense::Vec< int, 4 > coarse_hex_idx = { local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx };
177 (void) coarse_hex_idx; // unused
178
179 dense::Vec< int, 4 > coarse_hex_idx_fine = {
180 local_subdomain_id, 2 * x_coarse_idx, 2 * y_coarse_idx, 2 * r_coarse_idx };
181
183 A_coarse[num_wedges_per_hex_cell] = {};
184 A_coarse[0].fill( 0 );
185 A_coarse[1].fill( 0 );
186 // loop finer hexes of our coarse hex
187 for ( int fine_hex_lidx = 0; fine_hex_lidx < 8; fine_hex_lidx++ )
188 {
189 auto fine_hex_idx = coarse_hex_idx_fine + fine_hex_shifts[fine_hex_lidx];
190
191 // two wedges per fine hex
192 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
193 {
195
196 // obtain vertex indices of the current fine wedge
197 dense::Vec< int, 4 > wedge_local_vertex_indices_fine[6];
198 wedge_vertex_indices( fine_hex_idx, wedge, wedge_local_vertex_indices_fine );
199
200 // compute local (fully-assembled!) interpolation matrices mapping from the coarse DoFs in the hex to the current fine wedge DoFs
201
202 // loop destination of the interpolation (row dim of P): fine DoFs
203 for ( int fine_dof_lidx = 0; fine_dof_lidx < num_nodes_per_wedge; fine_dof_lidx++ )
204 {
205 auto fine_dof_idx = wedge_local_vertex_indices_fine[fine_dof_lidx];
206
207 // fine dof is on coarse dof
208 if ( fine_dof_idx( 1 ) % 2 == 0 && fine_dof_idx( 2 ) % 2 == 0 && fine_dof_idx( 3 ) % 2 == 0 )
209 {
210 // local index of destination fine DoF == local index of source coarse DoF
211 P( fine_dof_lidx, fine_dof_lidx ) = 1.0;
212 continue;
213 }
214
215 // else: need radial direction bot (>=) and top (<=) of current fine DoF
216 int r_idx_coarse_bot = fine_dof_idx( 3 ) < radii_fine_.extent( 1 ) - 1 ?
217 fine_dof_idx( 3 ) / 2 :
218 fine_dof_idx( 3 ) / 2 - 1;
219 int r_idx_coarse_top = r_idx_coarse_bot + 1;
220 (void) r_idx_coarse_top; // unused
221
222 // fine dof is radially aligned: x and y index match with coarse DoFs
223 // interpolate on the line in radial direction (coarse DoF bot -- fine DoF -- coarse DoF top)
224 if ( fine_dof_idx( 1 ) % 2 == 0 && fine_dof_idx( 2 ) % 2 == 0 )
225 {
226 // x, y on coarse, so we can just divide by 2 to obtain coarse indices
227 const auto fine_dof_x_idx_coarse = fine_dof_idx( 1 ) / 2;
228 const auto fine_dof_y_idx_coarse = fine_dof_idx( 2 ) / 2;
229
231 if ( interpolation_mode_ == InterpolationMode::Linear )
232 {
233 // actual weight computation
236 local_subdomain_id, fine_dof_idx( 1 ), fine_dof_idx( 2 ), fine_dof_idx( 3 ) },
238 local_subdomain_id,
239 fine_dof_x_idx_coarse,
240 fine_dof_y_idx_coarse,
241 r_idx_coarse_bot },
242 grid_fine_,
243 radii_fine_ );
244 }
245 else if ( interpolation_mode_ == InterpolationMode::Constant )
246 {
247 weights( 0 ) = 0.5;
248 weights( 1 ) = 0.5;
249 }
250 else
251 {
252 Kokkos::abort( "Unknown interpolation mode." );
253 }
254
255 if ( fine_dof_lidx == 2 or fine_dof_lidx == 5 )
256 {
257 P( fine_dof_lidx, 2 ) = weights( 0 );
258 P( fine_dof_lidx, 5 ) = weights( 1 );
259 }
260 else if ( fine_dof_lidx == 0 or fine_dof_lidx == 3 )
261 {
262 P( fine_dof_lidx, 0 ) = weights( 0 );
263 P( fine_dof_lidx, 3 ) = weights( 1 );
264 }
265 else if ( fine_dof_lidx == 1 or fine_dof_lidx == 4 )
266 {
267 P( fine_dof_lidx, 1 ) = weights( 0 );
268 P( fine_dof_lidx, 4 ) = weights( 1 );
269 }
270 continue;
271 }
272
273 // else: we interpolate fine DoF from the plane of 4 coarse DoFs that contains the fine DoF
274
275 // for the two botting coarse DoFs
276 int x0_idx_coarse = -1;
277 int x1_idx_coarse = -1;
278 int y0_idx_coarse = -1;
279 int y1_idx_coarse = -1;
280
281 // local indices of the 4 coarse DoFs in the plane
282 int coarse_dof_lindices[4] = { -1 };
283
284 if ( fine_dof_idx( 1 ) % 2 == 0 )
285 {
286 // "Vertical" edge.
287 x0_idx_coarse = fine_dof_idx( 1 ) / 2;
288 x1_idx_coarse = fine_dof_idx( 1 ) / 2;
289
290 y0_idx_coarse = fine_dof_idx( 2 ) / 2;
291 y1_idx_coarse = fine_dof_idx( 2 ) / 2 + 1;
292
293 coarse_dof_lindices[0] = 0;
294 coarse_dof_lindices[1] = 2;
295 coarse_dof_lindices[2] = 3;
296 coarse_dof_lindices[3] = 5;
297 }
298 else if ( fine_dof_idx( 2 ) % 2 == 0 )
299 {
300 // "Horizontal" edge.
301 x0_idx_coarse = fine_dof_idx( 1 ) / 2;
302 x1_idx_coarse = fine_dof_idx( 1 ) / 2 + 1;
303
304 y0_idx_coarse = fine_dof_idx( 2 ) / 2;
305 y1_idx_coarse = fine_dof_idx( 2 ) / 2;
306
307 coarse_dof_lindices[0] = 0;
308 coarse_dof_lindices[1] = 1;
309 coarse_dof_lindices[2] = 3;
310 coarse_dof_lindices[3] = 4;
311 }
312 else
313 {
314 // "Diagonal" edge.
315 x0_idx_coarse = fine_dof_idx( 1 ) / 2 + 1;
316 x1_idx_coarse = fine_dof_idx( 1 ) / 2;
317
318 y0_idx_coarse = fine_dof_idx( 2 ) / 2;
319 y1_idx_coarse = fine_dof_idx( 2 ) / 2 + 1;
320
321 coarse_dof_lindices[0] = 1;
322 coarse_dof_lindices[1] = 2;
323 coarse_dof_lindices[2] = 4;
324 coarse_dof_lindices[3] = 5;
325 }
326
327 if ( interpolation_mode_ == InterpolationMode::Linear )
328 {
331 local_subdomain_id, fine_dof_idx( 1 ), fine_dof_idx( 2 ), fine_dof_idx( 3 ) },
333 local_subdomain_id, x0_idx_coarse, y0_idx_coarse, r_idx_coarse_bot },
335 local_subdomain_id, x1_idx_coarse, y1_idx_coarse, r_idx_coarse_bot },
336 grid_fine_,
337 radii_fine_ );
338
339 P( fine_dof_lidx, coarse_dof_lindices[0] ) = weights( 0 );
340 P( fine_dof_lidx, coarse_dof_lindices[1] ) = weights( 0 );
341 P( fine_dof_lidx, coarse_dof_lindices[2] ) = weights( 1 );
342 P( fine_dof_lidx, coarse_dof_lindices[3] ) = weights( 1 );
343 }
344 else if ( interpolation_mode_ == InterpolationMode::Constant )
345 {
346 P( fine_dof_lidx, coarse_dof_lindices[0] ) =
347 terra::fe::wedge::shell::prolongation_constant_weight< ScalarType >(
348 fine_dof_idx( 1 ),
349 fine_dof_idx( 2 ),
350 fine_dof_idx( 3 ),
351 x0_idx_coarse,
352 y0_idx_coarse,
353 r_idx_coarse_bot );
354 P( fine_dof_lidx, coarse_dof_lindices[1] ) =
355 terra::fe::wedge::shell::prolongation_constant_weight< ScalarType >(
356 fine_dof_idx( 1 ),
357 fine_dof_idx( 2 ),
358 fine_dof_idx( 3 ),
359 x1_idx_coarse,
360 y1_idx_coarse,
361 r_idx_coarse_bot );
362 P( fine_dof_lidx, coarse_dof_lindices[2] ) =
363 terra::fe::wedge::shell::prolongation_constant_weight< ScalarType >(
364 fine_dof_idx( 1 ),
365 fine_dof_idx( 2 ),
366 fine_dof_idx( 3 ),
367 x0_idx_coarse,
368 y0_idx_coarse,
369 r_idx_coarse_top );
370 P( fine_dof_lidx, coarse_dof_lindices[3] ) =
371 terra::fe::wedge::shell::prolongation_constant_weight< ScalarType >(
372 fine_dof_idx( 1 ),
373 fine_dof_idx( 2 ),
374 fine_dof_idx( 3 ),
375 x1_idx_coarse,
376 y1_idx_coarse,
377 r_idx_coarse_top );
378 }
379 else
380 {
381 Kokkos::abort( "Unknown interpolation mode." );
382 }
383 }
384
386 fine_op_.get_local_matrix(
387 local_subdomain_id, fine_hex_idx( 1 ), fine_hex_idx( 2 ), fine_hex_idx( 3 ), wedge );
388
389 // core part: assemble local gca matrix by mapping from coarse wedge to current fine wedge,
390 // applying the corresponding local operator and mapping back.
392 if constexpr ( Operator::LocalMatrixDim == 18 )
393 {
394 // in a vectorial operator we need to setup a vectorial interpolation
395 for ( int dim = 0; dim < 3; ++dim )
396 {
397 for ( int i = 0; i < 6; ++i )
398 {
399 for ( int j = 0; j < 6; ++j )
400 {
401 P_vec( i + dim * num_nodes_per_wedge, j + dim * num_nodes_per_wedge ) = P( i, j );
402 }
403 }
404 }
405 }
406 else
407 {
408 // for scalar operators we just use the scalar interpolation
409 P_vec = P;
410 }
412 P_vec.transposed() * A_fine * P_vec;
413
414 // correctly add to gca coarsened matrix
415 // depending on the fine hex and wedge, we are located on the coarse 0 or 1 wedge
416 // and need to add to the corresponding coarse matrix
417 if ( ( wedge == 0 && ( fine_hex_lidx == 0 || fine_hex_lidx == 1 || fine_hex_lidx == 2 ||
418 fine_hex_lidx == 4 || fine_hex_lidx == 5 || fine_hex_lidx == 6 ) ) or
419 ( wedge == 1 && ( fine_hex_lidx == 0 || fine_hex_lidx == 4 ) ) )
420 {
421 A_coarse[0] += PTAP;
422 }
423 else if (
424 ( wedge == 1 && ( fine_hex_lidx == 1 || fine_hex_lidx == 2 || fine_hex_lidx == 3 ||
425 fine_hex_lidx == 5 || fine_hex_lidx == 6 || fine_hex_lidx == 7 ) ) or
426 ( wedge == 0 && ( fine_hex_lidx == 3 || fine_hex_lidx == 7 ) ) )
427 {
428 A_coarse[1] += PTAP;
429 }
430 else
431 {
432 Kokkos::abort( "Unexpected path." );
433 }
434 }
435 }
436
437 // bc treatment moved to ops, will be revisited during freeslip impl
438 if ( false )
439 {
441 boundary_mask.fill( 1.0 );
442
443 if constexpr ( Operator::LocalMatrixDim == 18 )
444 {
445 for ( int dimi = 0; dimi < 3; ++dimi )
446 {
447 for ( int dimj = 0; dimj < 3; ++dimj )
448 {
449 if ( coarse_op_.has_flag(
450 local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx, CMB ) )
451 {
452 // Inner boundary (CMB).
453 for ( int i = 0; i < num_nodes_per_wedge; i++ )
454 {
455 for ( int j = 0; j < num_nodes_per_wedge; j++ )
456 {
457 if ( ( dimi == dimj && i != j && ( i < 3 || j < 3 ) ) or
458 ( dimi != dimj && ( i < 3 || j < 3 ) ) )
459 {
460 boundary_mask(
461 i + dimi * num_nodes_per_wedge, j + dimj * num_nodes_per_wedge ) = 0.0;
462 }
463 }
464 }
465 }
466
467 if ( coarse_op_.has_flag(
468 local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx + 1, SURFACE ) )
469 {
470 // Outer boundary (surface).
471 for ( int i = 0; i < num_nodes_per_wedge; i++ )
472 {
473 for ( int j = 0; j < num_nodes_per_wedge; j++ )
474 {
475 if ( ( dimi == dimj && i != j && ( i >= 3 || j >= 3 ) ) or
476 ( dimi != dimj && ( i >= 3 || j >= 3 ) ) )
477 {
478 boundary_mask(
479 i + dimi * num_nodes_per_wedge, j + dimj * num_nodes_per_wedge ) = 0.0;
480 }
481 }
482 }
483 }
484 }
485 }
486 }
487 else
488 {
489 if ( coarse_op_.has_flag( local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx, CMB ) )
490 {
491 // Inner boundary (CMB).
492 for ( int i = 0; i < num_nodes_per_wedge; i++ )
493 {
494 for ( int j = 0; j < num_nodes_per_wedge; j++ )
495 {
496 if ( i != j && ( i < 3 || j < 3 ) )
497 {
498 boundary_mask( i, j ) = 0.0;
499 }
500 }
501 }
502 }
503
504 if ( coarse_op_.has_flag(
505 local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx + 1, SURFACE ) )
506 {
507 // Outer boundary (surface).
508 for ( int i = 0; i < num_nodes_per_wedge; i++ )
509 {
510 for ( int j = 0; j < num_nodes_per_wedge; j++ )
511 {
512 if ( i != j && ( i >= 3 || j >= 3 ) )
513 {
514 boundary_mask( i, j ) = 0.0;
515 }
516 }
517 }
518 }
519 }
520 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
521 {
522 A_coarse[wedge].hadamard_product( boundary_mask );
523 }
524 }
525
526 // store coarse matrices
527 coarse_op_.set_local_matrix( local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx, 0, A_coarse[0] );
528 coarse_op_.set_local_matrix( local_subdomain_id, x_coarse_idx, y_coarse_idx, r_coarse_idx, 1, A_coarse[1] );
529 }
530 }
531};
532} // namespace terra::linalg::solvers
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
Q1 scalar finite element vector on a distributed shell grid.
Definition vector_q1.hpp:21
: Galerkin coarse approximation (GCA). TwoGridGCA takes a coarser and a finer operator....
Definition gca.hpp:43
void operator()(const int local_subdomain_id, const int x_coarse_idx, const int y_coarse_idx, const int r_coarse_idx) const
Definition gca.hpp:154
ScalarT ScalarType
Definition gca.hpp:47
TwoGridGCA(Operator fine_op, Operator coarse_op, int level_range, grid::Grid4DDataScalar< ScalarType > GCAElements, bool treat_boundary=true, InterpolationMode interpolation_mode=InterpolationMode::Constant)
GCA Ctor Assembles Galerkin coarse-grid operators in the coarse-op passed.
Definition gca.hpp:72
void wedge_vertex_indices(dense::Vec< int, 4 > hex_idx, int wedge, dense::Vec< int, 4 >(&wedge_local_vertex_indices)[6]) const
Computes indices of vertices associated to a wedge in a hex cell.
Definition gca.hpp:129
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
constexpr int num_wedges_per_hex_cell
Definition kernel_helpers.hpp:5
constexpr int num_nodes_per_wedge
Definition kernel_helpers.hpp:7
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
Definition block_preconditioner_2x2.hpp:7
int map_to_coarse_element(const int fine_cell, const int level_range)
Definition gca_elements_collector.hpp:21
InterpolationMode
Modes for choosing interpolation weights.
Definition gca.hpp:27
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< T, Cols, Rows > transposed() const
Definition mat.hpp:187
Mat & hadamard_product(const Mat &mat)
Definition mat.hpp:213
Definition vec.hpp:9