Loading...
Searching...
No Matches
kernel_helpers.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace terra::fe::wedge {
4
5constexpr int num_wedges_per_hex_cell = 2;
7constexpr int num_nodes_per_wedge = 6;
8
9/// @brief Extracts the (unit sphere) surface vertex coords of the two wedges of a hex cell.
10///
11/// Useful for wedge-based kernels that update two wedges that make up a hex cell at once.
12///
13/// \code
14/// 2--3
15/// |\ |
16/// | \| => [(p0, p1, p2), (p3, p2, p1)]
17/// 0--1
18/// \endcode
19///
20/// @param wedge_surf_phy_coords [out] first dim: wedge/triangle index, second dim: vertex index
21/// @param lateral_grid [in] the unit sphere vertex coordinates
22/// @param local_subdomain_id [in] shell subdomain id on this process
23/// @param x_cell [in] hex cell x-coordinate
24/// @param y_cell [in] hex cell y-coordinate
25template < std::floating_point T >
26KOKKOS_INLINE_FUNCTION void wedge_surface_physical_coords(
28 const grid::Grid3DDataVec< T, 3 >& lateral_grid,
29 const int local_subdomain_id,
30 const int x_cell,
31 const int y_cell )
32{
33 // Extract vertex positions of quad
34 // (0, 0), (1, 0), (0, 1), (1, 1).
35 dense::Vec< T, 3 > quad_surface_coords[2][2];
36
37 for ( int x = x_cell; x <= x_cell + 1; x++ )
38 {
39 for ( int y = y_cell; y <= y_cell + 1; y++ )
40 {
41 for ( int d = 0; d < 3; d++ )
42 {
43 quad_surface_coords[x - x_cell][y - y_cell]( d ) = lateral_grid( local_subdomain_id, x, y, d );
44 }
45 }
46 }
47
48 // Sort coords for the two wedge surfaces.
49 wedge_surf_phy_coords[0][0] = quad_surface_coords[0][0];
50 wedge_surf_phy_coords[0][1] = quad_surface_coords[1][0];
51 wedge_surf_phy_coords[0][2] = quad_surface_coords[0][1];
52
53 wedge_surf_phy_coords[1][0] = quad_surface_coords[1][1];
54 wedge_surf_phy_coords[1][1] = quad_surface_coords[0][1];
55 wedge_surf_phy_coords[1][2] = quad_surface_coords[1][0];
56}
57
58template < std::floating_point T >
59KOKKOS_INLINE_FUNCTION void wedge_0_surface_physical_coords(
60 dense::Vec< T, 3 >* wedge_surf_phy_coords,
61 const grid::Grid3DDataVec< T, 3 >& lateral_grid,
62 const int local_subdomain_id,
63 const int x_cell,
64 const int y_cell )
65{
66 // Extract vertex positions of quad
67 // (0, 0), (1, 0), (0, 1), (1, 1).
68 dense::Vec< T, 3 > quad_surface_coords[2][2];
69
70 for ( int x = x_cell; x <= x_cell + 1; x++ )
71 {
72 for ( int y = y_cell; y <= y_cell + 1; y++ )
73 {
74 for ( int d = 0; d < 3; d++ )
75 {
76 quad_surface_coords[x - x_cell][y - y_cell]( d ) = lateral_grid( local_subdomain_id, x, y, d );
77 }
78 }
79 }
80
81 // Sort coords for the two wedge surfaces.
82 wedge_surf_phy_coords[0] = quad_surface_coords[0][0];
83 wedge_surf_phy_coords[1] = quad_surface_coords[1][0];
84 wedge_surf_phy_coords[2] = quad_surface_coords[0][1];
85}
86
87template < std::floating_point T >
88KOKKOS_INLINE_FUNCTION void wedge_1_surface_physical_coords(
89 dense::Vec< T, 3 >* wedge_surf_phy_coords,
90 const grid::Grid3DDataVec< T, 3 >& lateral_grid,
91 const int local_subdomain_id,
92 const int x_cell,
93 const int y_cell )
94{
95 // Extract vertex positions of quad
96 // (0, 0), (1, 0), (0, 1), (1, 1).
97 dense::Vec< T, 3 > quad_surface_coords[2][2];
98
99 for ( int x = x_cell; x <= x_cell + 1; x++ )
100 {
101 for ( int y = y_cell; y <= y_cell + 1; y++ )
102 {
103 for ( int d = 0; d < 3; d++ )
104 {
105 quad_surface_coords[x - x_cell][y - y_cell]( d ) = lateral_grid( local_subdomain_id, x, y, d );
106 }
107 }
108 }
109
110 // Sort coords for the two wedge surfaces.
111 wedge_surf_phy_coords[0] = quad_surface_coords[1][1];
112 wedge_surf_phy_coords[1] = quad_surface_coords[0][1];
113 wedge_surf_phy_coords[2] = quad_surface_coords[1][0];
114}
115
116/// @brief Computes the transposed inverse of the Jacobian of the lateral forward map from the reference triangle
117/// to the triangle on the unit sphere and the absolute determinant of that Jacobian at the passed quadrature
118/// points.
119///
120/// @param jac_lat_inv_t [out] transposed inverse of the Jacobian of the lateral map
121/// @param det_jac_lat [out] absolute of the determinant of the Jacobian of the lateral map
122/// @param wedge_surf_phy_coords [in] coords of the triangular wedge surfaces on the unit sphere (compute via
123/// wedge_surface_physical_coords())
124/// @param quad_points [in] the quadrature points
125template < std::floating_point T, int NumQuadPoints >
126KOKKOS_INLINE_FUNCTION constexpr void jacobian_lat_inverse_transposed_and_determinant(
127 dense::Mat< T, 3, 3 > ( &jac_lat_inv_t )[num_wedges_per_hex_cell][NumQuadPoints],
128 T ( &det_jac_lat )[num_wedges_per_hex_cell][NumQuadPoints],
130 const dense::Vec< T, 3 > quad_points[NumQuadPoints] )
131{
132 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
133 {
134 for ( int q = 0; q < NumQuadPoints; q++ )
135 {
136 const auto jac_lat = wedge::jac_lat(
137 wedge_surf_phy_coords[wedge][0],
138 wedge_surf_phy_coords[wedge][1],
139 wedge_surf_phy_coords[wedge][2],
140 quad_points[q]( 0 ),
141 quad_points[q]( 1 ) );
142
143 det_jac_lat[wedge][q] = Kokkos::abs( jac_lat.det() );
144
145 jac_lat_inv_t[wedge][q] = jac_lat.inv().transposed();
146 }
147 }
148}
149
150/// @brief Like jacobian_lat_inverse_transposed_and_determinant() but only computes the determinant (cheaper if the
151/// transposed inverse of the Jacobian is not required).
152///
153/// @param det_jac_lat [out] absolute of the determinant of the Jacobian of the lateral map
154/// @param wedge_surf_phy_coords [in] coords of the triangular wedge surfaces on the unit sphere (compute via
155/// wedge_surface_physical_coords())
156/// @param quad_points [in] the quadrature points
157template < std::floating_point T, int NumQuadPoints >
158KOKKOS_INLINE_FUNCTION constexpr void jacobian_lat_determinant(
159 T ( &det_jac_lat )[num_wedges_per_hex_cell][NumQuadPoints],
161 const dense::Vec< T, 3 > quad_points[NumQuadPoints] )
162{
163 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
164 {
165 for ( int q = 0; q < NumQuadPoints; q++ )
166 {
167 const auto jac_lat = wedge::jac_lat(
168 wedge_surf_phy_coords[wedge][0],
169 wedge_surf_phy_coords[wedge][1],
170 wedge_surf_phy_coords[wedge][2],
171 quad_points[q]( 0 ),
172 quad_points[q]( 1 ) );
173
174 det_jac_lat[wedge][q] = Kokkos::abs( jac_lat.det() );
175 }
176 }
177}
178
179/// @brief Computes the radially independent parts of the physical shape function gradients
180///
181/// \code
182/// g_rad_j = jac_lat_inv_t * ( (∂/∂xi N_lat_j) N_rad_j, (∂/∂eta N_lat_j) N_rad_j, 0 )^T
183/// g_lat_j = jac_lat_inv_t * ( 0, 0, N_lat_j )^T
184/// \endcode
185///
186/// where j is a node of the wedge. Computes those for all 6 nodes j = 0, ..., 5 of a wedge.
187///
188/// Those terms can technically be precomputed and are independent of r (identical for all wedges on a radial beam).
189///
190/// From thes we can later compute
191///
192/// \code
193/// jac_inv_t * grad_N_j
194/// \endcode
195///
196/// via
197///
198/// \code
199/// jac_inv_t * grad_N_j = (1 / r(zeta)) g_rad_j + (∂ N_rad_j / ∂zeta) * (1 / (∂r / ∂zeta)) * g_lat_j
200/// \endcode
201///
202/// @param g_rad [out] g_rad - see above
203/// @param g_lat [out] g_lat - see above
204/// @param jac_lat_inv_t [in] transposed inverse of lateral Jacobian - see
205/// jacobian_lat_inverse_transposed_and_determinant()
206/// @param quad_points [in] the quadrature points
207template < std::floating_point T, int NumQuadPoints >
208KOKKOS_INLINE_FUNCTION constexpr void lateral_parts_of_grad_phi(
211 const dense::Mat< T, 3, 3 > jac_lat_inv_t[num_wedges_per_hex_cell][NumQuadPoints],
212 const dense::Vec< T, 3 > quad_points[NumQuadPoints] )
213{
214 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
215 {
216 for ( int node_idx = 0; node_idx < num_nodes_per_wedge; node_idx++ )
217 {
218 for ( int q = 0; q < NumQuadPoints; q++ )
219 {
220 g_rad[wedge][node_idx][q] =
221 jac_lat_inv_t[wedge][q] *
223 grad_shape_lat_xi< T >( node_idx ) * shape_rad( node_idx, quad_points[q]( 2 ) ),
224 grad_shape_lat_eta< T >( node_idx ) * shape_rad( node_idx, quad_points[q]( 2 ) ),
225 0.0 };
226
227 g_lat[wedge][node_idx][q] =
228 jac_lat_inv_t[wedge][q] *
229 dense::Vec< T, 3 >{ 0.0, 0.0, shape_lat( node_idx, quad_points[q]( 0 ), quad_points[q]( 1 ) ) };
230 }
231 }
232 }
233}
234
235/// @brief Computes and returns J^-T grad(N_j).
236///
237/// @param g_rad [in] see lateral_parts_of_grad_phi()
238/// @param g_lat [in] see lateral_parts_of_grad_phi()
239/// @param r_inv [in] 1 / r (where r is the physical radius of the quadrature point - compute with
240/// forward_map_rad())
241/// @param grad_r_inv [in] 1 / grad_r (where grad_r is the radial component of the gradient of the forward map in
242/// radial direction - compute with grad_forward_map_rad())
243/// @param wedge_idx [in] wedge index of the hex cell (0 or 1)
244/// @param node_idx [in] node index in the wedge (0, 1, ..., 5)
245/// @param quad_point_idx [in] index of the quadrature point
246template < std::floating_point T, int NumQuadPoints >
247KOKKOS_INLINE_FUNCTION constexpr dense::Vec< T, 3 > grad_shape_full(
250 const T r_inv,
251 const T grad_r_inv,
252 const int wedge_idx,
253 const int node_idx,
254 const int quad_point_idx )
255{
256 return r_inv * g_rad[wedge_idx][node_idx][quad_point_idx] +
257 grad_shape_rad< T >( node_idx ) * grad_r_inv * g_lat[wedge_idx][node_idx][quad_point_idx];
258}
259
260/// @brief Computes |det(J)|.
261///
262/// @param det_jac_lat [in] see jacobian_lat_determinant()
263/// @param r [in] the physical radius of the quadrature point - compute with
264/// forward_map_rad()
265/// @param grad_r [in] the radial component of the gradient of the forward map in
266/// radial direction - compute with grad_forward_map_rad())
267/// @param wedge_idx [in] wedge index of the hex cell (0 or 1)
268/// @param quad_point_idx [in] index of the quadrature point
269template < std::floating_point T, int NumQuadPoints >
270KOKKOS_INLINE_FUNCTION constexpr T det_full(
271 const T det_jac_lat[num_wedges_per_hex_cell][NumQuadPoints],
272 const T r,
273 const T grad_r,
274 const int wedge_idx,
275 const int quad_point_idx )
276{
277 return r * r * grad_r * det_jac_lat[wedge_idx][quad_point_idx];
278}
279
280/// @brief Extracts the local vector coefficients for the two wedges of a hex cell from the global coefficient vector.
281///
282/// \code
283/// r = r_cell + 1 (outer)
284/// 6--7
285/// |\ |
286/// | \|
287/// 4--5
288///
289/// r = r_cell (inner)
290/// 2--3
291/// |\ |
292/// | \|
293/// 0--1
294///
295/// v0 = (0, 1, 2, 4, 5, 6)
296/// v1 = (3, 2, 1, 7, 6, 5)
297/// \endcode
298///
299/// @param local_coefficients [out] the local coefficient vector
300/// @param local_subdomain_id [in] shell subdomain id on this process
301/// @param x_cell [in] hex cell x-coordinate
302/// @param y_cell [in] hex cell y-coordinate
303/// @param r_cell [in] hex cell r-coordinate
304/// @param global_coefficients [in] the global coefficient vector
305template < std::floating_point T >
306KOKKOS_INLINE_FUNCTION void extract_local_wedge_scalar_coefficients(
307 dense::Vec< T, 6 > ( &local_coefficients )[2],
308 const int local_subdomain_id,
309 const int x_cell,
310 const int y_cell,
311 const int r_cell,
312 const grid::Grid4DDataScalar< T >& global_coefficients )
313{
314 local_coefficients[0]( 0 ) = global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell );
315 local_coefficients[0]( 1 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell );
316 local_coefficients[0]( 2 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell );
317 local_coefficients[0]( 3 ) = global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell + 1 );
318 local_coefficients[0]( 4 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1 );
319 local_coefficients[0]( 5 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1 );
320
321 local_coefficients[1]( 0 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell );
322 local_coefficients[1]( 1 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell );
323 local_coefficients[1]( 2 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell );
324 local_coefficients[1]( 3 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell + 1 );
325 local_coefficients[1]( 4 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1 );
326 local_coefficients[1]( 5 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1 );
327}
328
329/// @brief Extracts the local vector coefficients for the two wedges of a hex cell from the global coefficient vector.
330///
331/// \code
332/// r = r_cell + 1 (outer)
333/// 6--7
334/// |\ |
335/// | \|
336/// 4--5
337///
338/// r = r_cell (inner)
339/// 2--3
340/// |\ |
341/// | \|
342/// 0--1
343///
344/// v0 = (0, 1, 2, 4, 5, 6)
345/// v1 = (3, 2, 1, 7, 6, 5)
346/// \endcode
347///
348/// @param local_coefficients [out] the local coefficient vector
349/// @param local_subdomain_id [in] shell subdomain id on this process
350/// @param x_cell [in] hex cell x-coordinate
351/// @param y_cell [in] hex cell y-coordinate
352/// @param r_cell [in] hex cell r-coordinate
353/// @param d [in] vector-element of the vector-valued global view
354/// @param global_coefficients [in] the global coefficient vector
355template < std::floating_point T, int VecDim >
356KOKKOS_INLINE_FUNCTION void extract_local_wedge_vector_coefficients(
357 dense::Vec< T, 6 > ( &local_coefficients )[2],
358 const int local_subdomain_id,
359 const int x_cell,
360 const int y_cell,
361 const int r_cell,
362 const int d,
363 const grid::Grid4DDataVec< T, VecDim >& global_coefficients )
364{
365 local_coefficients[0]( 0 ) = global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell, d );
366 local_coefficients[0]( 1 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell, d );
367 local_coefficients[0]( 2 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell, d );
368 local_coefficients[0]( 3 ) = global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell + 1, d );
369 local_coefficients[0]( 4 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1, d );
370 local_coefficients[0]( 5 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1, d );
371
372 local_coefficients[1]( 0 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell, d );
373 local_coefficients[1]( 1 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell, d );
374 local_coefficients[1]( 2 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell, d );
375 local_coefficients[1]( 3 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell + 1, d );
376 local_coefficients[1]( 4 ) = global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1, d );
377 local_coefficients[1]( 5 ) = global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1, d );
378}
379
380/// @brief Performs an atomic add of the two local wedge coefficient vectors of a hex cell into the global coefficient
381/// vector.
382///
383/// \code
384/// r = r_cell + 1 (outer)
385/// 6--7
386/// |\ |
387/// | \|
388/// 4--5
389///
390/// r = r_cell (inner)
391/// 2--3
392/// |\ |
393/// | \|
394/// 0--1
395///
396/// v0 = (0, 1, 2, 4, 5, 6)
397/// v1 = (3, 2, 1, 7, 6, 5)
398/// \endcode
399///
400/// @param global_coefficients [inout] the global coefficient vector
401/// @param local_subdomain_id [in] shell subdomain id on this process
402/// @param x_cell [in] hex cell x-coordinate
403/// @param y_cell [in] hex cell y-coordinate
404/// @param r_cell [in] hex cell r-coordinate
405/// @param local_coefficients [in] the local coefficient vector
406template < std::floating_point T >
408 const grid::Grid4DDataScalar< T >& global_coefficients,
409 const int local_subdomain_id,
410 const int x_cell,
411 const int y_cell,
412 const int r_cell,
413 const dense::Vec< T, 6 > ( &local_coefficients )[2] )
414{
415 Kokkos::atomic_add(
416 &global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell ), local_coefficients[0]( 0 ) );
417 Kokkos::atomic_add(
418 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell ),
419 local_coefficients[0]( 1 ) + local_coefficients[1]( 2 ) );
420 Kokkos::atomic_add(
421 &global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell ),
422 local_coefficients[0]( 2 ) + local_coefficients[1]( 1 ) );
423 Kokkos::atomic_add(
424 &global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell + 1 ), local_coefficients[0]( 3 ) );
425 Kokkos::atomic_add(
426 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1 ),
427 local_coefficients[0]( 4 ) + local_coefficients[1]( 5 ) );
428 Kokkos::atomic_add(
429 &global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1 ),
430 local_coefficients[0]( 5 ) + local_coefficients[1]( 4 ) );
431 Kokkos::atomic_add(
432 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell ), local_coefficients[1]( 0 ) );
433 Kokkos::atomic_add(
434 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell + 1 ), local_coefficients[1]( 3 ) );
435}
436
437/// @brief Performs an atomic add of the two local wedge coefficient vectors of a hex cell into the global coefficient
438/// vector.
439///
440/// \code
441/// r = r_cell + 1 (outer)
442/// 6--7
443/// |\ |
444/// | \|
445/// 4--5
446///
447/// r = r_cell (inner)
448/// 2--3
449/// |\ |
450/// | \|
451/// 0--1
452///
453/// v0 = (0, 1, 2, 4, 5, 6)
454/// v1 = (3, 2, 1, 7, 6, 5)
455/// \endcode
456///
457/// @param global_coefficients [inout] the global coefficient vector
458/// @param local_subdomain_id [in] shell subdomain id on this process
459/// @param x_cell [in] hex cell x-coordinate
460/// @param y_cell [in] hex cell y-coordinate
461/// @param r_cell [in] hex cell r-coordinate
462/// @param d [in] vector-element of the vector-valued global view
463/// @param local_coefficients [in] the local coefficient vector
464template < std::floating_point T, int VecDim >
466 const grid::Grid4DDataVec< T, VecDim >& global_coefficients,
467 const int local_subdomain_id,
468 const int x_cell,
469 const int y_cell,
470 const int r_cell,
471 const int d,
472 const dense::Vec< T, 6 > local_coefficients[2] )
473{
474 Kokkos::atomic_add(
475 &global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell, d ), local_coefficients[0]( 0 ) );
476 Kokkos::atomic_add(
477 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell, d ),
478 local_coefficients[0]( 1 ) + local_coefficients[1]( 2 ) );
479 Kokkos::atomic_add(
480 &global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell, d ),
481 local_coefficients[0]( 2 ) + local_coefficients[1]( 1 ) );
482 Kokkos::atomic_add(
483 &global_coefficients( local_subdomain_id, x_cell, y_cell, r_cell + 1, d ), local_coefficients[0]( 3 ) );
484 Kokkos::atomic_add(
485 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell, r_cell + 1, d ),
486 local_coefficients[0]( 4 ) + local_coefficients[1]( 5 ) );
487 Kokkos::atomic_add(
488 &global_coefficients( local_subdomain_id, x_cell, y_cell + 1, r_cell + 1, d ),
489 local_coefficients[0]( 5 ) + local_coefficients[1]( 4 ) );
490 Kokkos::atomic_add(
491 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell, d ), local_coefficients[1]( 0 ) );
492 Kokkos::atomic_add(
493 &global_coefficients( local_subdomain_id, x_cell + 1, y_cell + 1, r_cell + 1, d ), local_coefficients[1]( 3 ) );
494}
495
496/// @brief Returns the lateral wedge index with respect to a coarse grid wedge from the fine wedge indices.
497///
498/// Each coarse grid wedge is laterally divided into four fine wedges (radially into two).
499/// The lateral four fine wedges are enumerated from 0 to 3.
500///
501/// This function returns that lateral index given a fine grid index of a wedge.
502///
503/// Here are two coarse wedges (view from the "top"), each with four fine grid wedges (enumerated from 0 to 3).
504///
505/// @code
506///
507/// Coarse wedge idx = 0
508///
509/// +
510/// |\
511/// | \
512/// | \
513/// | 2 \
514/// +----+
515/// |\ 3 |\
516/// | \ | \
517/// | \ | \
518/// | 0 \| 1 \
519/// +----+----+
520///
521/// Coarse wedge idx = 1
522///
523/// +----+----+
524/// \ 1 |\ 0 |
525/// \ | \ |
526/// \ | \ |
527/// \| 3 \|
528/// +----+
529/// \ 2 |
530/// \ |
531/// \ |
532/// \|
533/// +
534///
535/// @endcode
536///
537/// This function now computes the indices from a grid of fine wedges that looks like this:
538///
539/// @code
540///
541/// x_cell_fine % 1:
542///
543/// +----+----+
544/// |\ 0 |\ 1 |
545/// | \ | \ |
546/// | \ | \ |
547/// | 0 \| 1 \|
548/// +----+----+
549/// |\ 0 |\ 1 |
550/// | \ | \ |
551/// | \ | \ |
552/// | 0 \| 1 \|
553/// +----+----+
554///
555/// y_cell_fine % 1:
556///
557/// +----+----+
558/// |\ 1 |\ 1 |
559/// | \ | \ |
560/// | \ | \ |
561/// | 1 \| 1 \|
562/// +----+----+
563/// |\ 0 |\ 0 |
564/// | \ | \ |
565/// | \ | \ |
566/// | 0 \| 0 \|
567/// +----+----+
568///
569/// wedge_idx_fine:
570///
571/// +----+----+
572/// |\ 1 |\ 1 |
573/// | \ | \ |
574/// | \ | \ |
575/// | 0 \| 0 \|
576/// +----+----+
577/// |\ 1 |\ 1 |
578/// | \ | \ |
579/// | \ | \ |
580/// | 0 \| 0 \|
581/// +----+----+
582///
583/// Resulting/returned values:
584///
585/// +----+----+
586/// |\ 1 |\ 0 |
587/// | \ | \ |
588/// | \ | \ |
589/// | 2 \| 3 \|
590/// +----+----+
591/// |\ 3 |\ 2 |
592/// | \ | \ |
593/// | \ | \ |
594/// | 0 \| 1 \|
595/// +----+----+
596///
597/// @endcode
598///
599///
600KOKKOS_INLINE_FUNCTION
601constexpr int fine_lateral_wedge_idx( const int x_cell_fine, const int y_cell_fine, const int wedge_idx_fine )
602{
603 // wedge, y, x
604 constexpr int indices[2][2][2] = { { { 0, 1 }, { 2, 3 } }, { { 3, 2 }, { 1, 0 } } };
605 const int x_mod = x_cell_fine % 2;
606 const int y_mod = y_cell_fine % 2;
607 return indices[wedge_idx_fine][y_mod][x_mod];
608}
609
610enum class DoFOrdering
611{
612 NODEWISE,
614};
615
616
617template < typename ScalarT > KOKKOS_INLINE_FUNCTION
618constexpr void
620{
621 if ( doo_from == doo_to )
622 {
623 return;
624 }
625
627 if ( (doo_from == DoFOrdering::NODEWISE) && (doo_to == DoFOrdering::DIMENSIONWISE) )
628 {
629 for ( int dim = 0; dim < 3; ++dim )
630 {
631 for ( int node_idx = 0; node_idx < num_nodes_per_wedge; node_idx++ )
632 {
633 tmp_dofs(node_idx + dim * num_nodes_per_wedge) = dofs(node_idx * 3 + dim);
634 }
635 }
636 }
637 else if ( (doo_from == DoFOrdering::DIMENSIONWISE) && (doo_to == DoFOrdering::NODEWISE) )
638 {
639 for ( int dim = 0; dim < 3; ++dim )
640 {
641 for ( int node_idx = 0; node_idx < num_nodes_per_wedge; node_idx++ )
642 {
643 tmp_dofs(node_idx * 3 + dim) = dofs(node_idx + dim * num_nodes_per_wedge);
644 }
645 }
646 }
647
648 for (int i = 0; i < 18; ++i) {
649 dofs(i) = tmp_dofs(i);
650 }
651}
652
653} // namespace terra::fe::wedge
Features for wedge elements.
constexpr int num_nodes_per_wedge_surface
Definition kernel_helpers.hpp:6
void atomically_add_local_wedge_scalar_coefficients(const grid::Grid4DDataScalar< T > &global_coefficients, const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, 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:407
constexpr void lateral_parts_of_grad_phi(dense::Vec< T, 3 >(&g_rad)[num_wedges_per_hex_cell][num_nodes_per_wedge][NumQuadPoints], dense::Vec< T, 3 >(&g_lat)[num_wedges_per_hex_cell][num_nodes_per_wedge][NumQuadPoints], const dense::Mat< T, 3, 3 > jac_lat_inv_t[num_wedges_per_hex_cell][NumQuadPoints], const dense::Vec< T, 3 > quad_points[NumQuadPoints])
Computes the radially independent parts of the physical shape function gradients.
Definition kernel_helpers.hpp:208
constexpr int fine_lateral_wedge_idx(const int x_cell_fine, const int y_cell_fine, const int wedge_idx_fine)
Returns the lateral wedge index with respect to a coarse grid wedge from the fine wedge indices.
Definition kernel_helpers.hpp:601
constexpr dense::Vec< T, 3 > grad_shape_full(const dense::Vec< T, 3 > g_rad[num_wedges_per_hex_cell][num_nodes_per_wedge][NumQuadPoints], const dense::Vec< T, 3 > g_lat[num_wedges_per_hex_cell][num_nodes_per_wedge][NumQuadPoints], const T r_inv, const T grad_r_inv, const int wedge_idx, const int node_idx, const int quad_point_idx)
Computes and returns J^-T grad(N_j).
Definition kernel_helpers.hpp:247
constexpr T det_full(const T det_jac_lat[num_wedges_per_hex_cell][NumQuadPoints], const T r, const T grad_r, const int wedge_idx, const int quad_point_idx)
Computes |det(J)|.
Definition kernel_helpers.hpp:270
constexpr T shape_rad(const int node_idx, const T zeta)
Radial shape function.
Definition integrands.hpp:86
void wedge_0_surface_physical_coords(dense::Vec< T, 3 > *wedge_surf_phy_coords, const grid::Grid3DDataVec< T, 3 > &lateral_grid, const int local_subdomain_id, const int x_cell, const int y_cell)
Definition kernel_helpers.hpp:59
constexpr void jacobian_lat_inverse_transposed_and_determinant(dense::Mat< T, 3, 3 >(&jac_lat_inv_t)[num_wedges_per_hex_cell][NumQuadPoints], T(&det_jac_lat)[num_wedges_per_hex_cell][NumQuadPoints], const dense::Vec< T, 3 > wedge_surf_phy_coords[num_wedges_per_hex_cell][num_nodes_per_wedge_surface], const dense::Vec< T, 3 > quad_points[NumQuadPoints])
Computes the transposed inverse of the Jacobian of the lateral forward map from the reference triangl...
Definition kernel_helpers.hpp:126
DoFOrdering
Definition kernel_helpers.hpp:611
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
constexpr void reorder_local_dofs(const DoFOrdering doo_from, const DoFOrdering doo_to, dense::Vec< ScalarT, 18 > &dofs)
Definition kernel_helpers.hpp:619
constexpr T shape_lat(const int node_idx, const T xi, const T eta)
Lateral shape function.
Definition integrands.hpp:118
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 dense::Mat< T, 3, 3 > jac_lat(const dense::Vec< T, 3 > &p1_phy, const dense::Vec< T, 3 > &p2_phy, const dense::Vec< T, 3 > &p3_phy, const T xi, const T eta)
Definition integrands.hpp:620
constexpr void jacobian_lat_determinant(T(&det_jac_lat)[num_wedges_per_hex_cell][NumQuadPoints], const dense::Vec< T, 3 > wedge_surf_phy_coords[num_wedges_per_hex_cell][num_nodes_per_wedge_surface], const dense::Vec< T, 3 > quad_points[NumQuadPoints])
Like jacobian_lat_inverse_transposed_and_determinant() but only computes the determinant (cheaper if ...
Definition kernel_helpers.hpp:158
void wedge_1_surface_physical_coords(dense::Vec< T, 3 > *wedge_surf_phy_coords, const grid::Grid3DDataVec< T, 3 > &lateral_grid, const int local_subdomain_id, const int x_cell, const int y_cell)
Definition kernel_helpers.hpp:88
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
Definition mat.hpp:10