Loading...
Searching...
No Matches
helpers.hpp
Go to the documentation of this file.
1
2#pragma once
11#include "linalg/vector.hpp"
12#include "linalg/vector_fv.hpp"
13#include "linalg/vector_q1.hpp"
14
15namespace terra::fv::hex {
16
17// ============================================================================
18// Dirichlet boundary conditions for radial shell boundaries
19// ============================================================================
20
21/// @brief Constant Dirichlet boundary conditions for the inner (CMB) and outer (surface)
22/// radial boundaries of the spherical shell.
23///
24/// Used by `apply_dirichlet_bcs` to enforce prescribed temperatures after each time step.
25/// The BCs are applied as a strong (pointwise) enforcement — boundary cells are overwritten
26/// with the prescribed value at the end of each explicit or implicit step.
27///
28/// @tparam ScalarT Floating-point scalar type.
29template < typename ScalarT >
31{
32 ScalarT T_cmb = ScalarT( 0 ); ///< Prescribed temperature at the core-mantle boundary.
33 ScalarT T_surface = ScalarT( 0 ); ///< Prescribed temperature at the outer surface.
34 bool apply_cmb = false; ///< Enforce CMB Dirichlet BC when true.
35 bool apply_surface = false; ///< Enforce surface Dirichlet BC when true.
36};
37
38/// @brief Strongly enforce Dirichlet boundary conditions on the radial shell boundaries.
39///
40/// For each FV cell that lies on the CMB (\f$r = 1\f$, innermost real cell of the innermost
41/// radial subdomain) or on the outer surface (\f$r = N_r - 1\f$, outermost real cell of the
42/// outermost radial subdomain), the scalar field is overwritten with the prescribed value.
43///
44/// Boundary cells are identified via the `boundary_mask`:
45/// - CMB cells: `r_cell == 1` and `boundary_mask(id, 0, 0, 0) == ShellBoundaryFlag::CMB`.
46/// - Surface cells: `r_cell == last` and `boundary_mask(id, 0, 0, last_q1) == ShellBoundaryFlag::SURFACE`.
47///
48/// This strong enforcement is first-order in time (the boundary value is fixed after each step).
49/// For cells *adjacent* to the boundary the scheme is spatially consistent: the next time step's
50/// stencil will see the correct Dirichlet value at the boundary cell.
51///
52/// @param T [in/out] Transported scalar field (boundary cells overwritten).
53/// @param boundary_mask Node-based boundary flag array (Q1 layout, CMB at r=0, SURFACE at r=last).
54/// @param bcs Prescribed BC values and flags.
55/// @param domain Distributed domain (used for the loop range policy).
56/// @brief Apply Dirichlet BCs directly to a raw FV grid view.
57///
58/// Sets both the real boundary cell and the adjacent ghost cell outside the physical domain.
59/// The ghost cell is never filled by `update_fv_ghost_layers` (no subdomain neighbour exists
60/// beyond a physical boundary) so it must be set here to give the correct inflow/diffusion
61/// BC when FCT predictor stencils read across the boundary face.
62///
63/// This overload is the low-level implementation; the `VectorFVScalar` overload delegates to it.
64/// It can also be called directly on intermediate FCT buffers (e.g. `T_L`) that are raw views.
65template < typename ScalarT >
69 const DirichletBCs< ScalarT >& bcs,
70 const grid::shell::DistributedDomain& domain )
71{
73
74 const int fv_r_last = static_cast< int >( data.extent( 3 ) ) - 2;
75 const int mask_r_last = static_cast< int >( boundary_mask.extent( 3 ) ) - 1;
76
77 const ScalarT T_cmb = bcs.T_cmb;
78 const ScalarT T_surf = bcs.T_surface;
79 const bool do_cmb = bcs.apply_cmb;
80 const bool do_surf = bcs.apply_surface;
81
82 Kokkos::parallel_for(
83 "apply_dirichlet_bcs",
85 KOKKOS_LAMBDA( const int id, const int x, const int y, const int r ) {
86 if ( do_cmb && r == 1 && util::has_flag( boundary_mask( id, 0, 0, 0 ), Flag::CMB ) )
87 {
88 data( id, x, y, 1 ) = T_cmb;
89 data( id, x, y, 0 ) = T_cmb;
90 }
91 if ( do_surf && r == fv_r_last && util::has_flag( boundary_mask( id, 0, 0, mask_r_last ), Flag::SURFACE ) )
92 {
93 data( id, x, y, fv_r_last ) = T_surf;
94 data( id, x, y, fv_r_last + 1 ) = T_surf;
95 }
96 } );
97
98 Kokkos::fence();
99}
100
101template < typename ScalarT >
105 const DirichletBCs< ScalarT >& bcs,
106 const grid::shell::DistributedDomain& domain )
107{
108 apply_dirichlet_bcs( T.grid_data(), boundary_mask, bcs, domain );
109}
110
111/// @brief Computes cell centers and writes to a vector valued finite volume function.
112///
113///
114/// This function computes for every finite volume cell \f$K\f$ the value
115/// \f[
116/// u_K = \frac{1}{|K|} \int_K x \ dx
117/// \f]
118/// with
119/// \f[
120/// |K| = \int_K 1 \ dx
121/// \f]
122/// and writes \f$u_K\f$ into the respective finite volume cell.
123///
124///
125/// @param dst [out] finite volume function that is being written to
126/// @param coords_shell coords of the unit shell
127/// @param coords_radii radii of all shells
128template < typename ScalarType, typename GridScalarType >
132 const grid::Grid2DDataScalar< GridScalarType >& coords_radii )
133{
135 Kokkos::parallel_for(
136 "l2_project_into_fv_function",
137 Kokkos::MDRangePolicy(
138 { 0, 1, 1, 1 },
139 { fv_grid.extent( 0 ), fv_grid.extent( 1 ) - 1, fv_grid.extent( 2 ) - 1, fv_grid.extent( 3 ) - 1 } ),
140 KOKKOS_LAMBDA(
141 const int local_subdomain_id, const int hex_cell_x, const int hex_cell_y, const int hex_cell_r ) {
142 constexpr auto num_quad_points = fe::wedge::quadrature::quad_felippa_3x2_num_quad_points;
143 dense::Vec< ScalarType, 3 > quad_points[num_quad_points];
144 ScalarType quad_weights[num_quad_points];
147
148 ScalarType volume = 0.0;
149 dense::Vec< ScalarType, 3 > integral = {};
150
154 wedge_phy_surf, coords_shell, local_subdomain_id, hex_cell_x - 1, hex_cell_y - 1 );
155
156 const auto r_1 = coords_radii( local_subdomain_id, hex_cell_r - 1 );
157 const auto r_2 = coords_radii( local_subdomain_id, hex_cell_r );
158
159 for ( int wedge = 0; wedge < fe::wedge::num_wedges_per_hex_cell; ++wedge )
160 {
161 for ( int q = 0; q < num_quad_points; ++q )
162 {
163 const auto J = fe::wedge::jac( wedge_phy_surf[wedge], r_1, r_2, quad_points[q] );
164 const auto det = J.det();
165 const auto abs_det = Kokkos::abs( det );
166 const auto Jw = abs_det * quad_weights[q];
167 volume = volume + Jw;
168
169 const auto x = fe::wedge::forward_map(
170 wedge_phy_surf[wedge][0],
171 wedge_phy_surf[wedge][1],
172 wedge_phy_surf[wedge][2],
173 r_1,
174 r_2,
175 quad_points[q]( 0 ),
176 quad_points[q]( 1 ),
177 quad_points[q]( 2 ) );
178
179 integral = integral + x * Jw;
180 }
181 }
182
183 for ( int d = 0; d < 3; ++d )
184 {
185 fv_grid( local_subdomain_id, hex_cell_x, hex_cell_y, hex_cell_r, d ) = integral( d ) / volume;
186 }
187 } );
188}
189
190/// @brief Computes cell center positions once and populates ghost layers via MPI communication.
191///
192/// This is the recommended one-time initialization for cell centers at application startup.
193/// After this call, `dst` contains valid cell centers in both real cells and all ghost layers,
194/// so kernels can look up neighbour cell centers without recomputing geometry.
195///
196/// @param dst [out] FV vector field receiving cell centers (real cells + ghost layers).
197/// @param domain Distributed domain (used for ghost layer communication).
198/// @param coords_shell Lateral node coordinates of the unit sphere surface.
199/// @param coords_radii Radial shell radii.
200template < typename ScalarType, typename GridScalarType >
203 const grid::shell::DistributedDomain& domain,
205 const grid::Grid2DDataScalar< GridScalarType >& coords_radii )
206{
207 compute_cell_centers( dst, coords_shell, coords_radii );
208 Kokkos::fence();
210}
211
212} // namespace terra::fv::hex
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2518
Finite volume vector on distributed shell grid with one DoF per hex (merging 2 wedges) and ghost-laye...
Definition vector_fv.hpp:23
const grid::Grid4DDataScalar< ScalarType > & grid_data() const
Get const reference to grid data.
Definition vector_fv.hpp:145
Static assertion: VectorQ1Scalar satisfies VectorLike concept.
Definition vector_fv.hpp:170
const grid::Grid4DDataVec< ScalarType, VecDim > & grid_data() const
Get const reference to grid data.
Definition vector_fv.hpp:292
Ghost layer communication for scalar finite volume (FV) fields on the shell grid.
void update_fv_ghost_layers(const grid::shell::DistributedDomain &domain, const grid::Grid4DDataScalar< ScalarType > &data, FVGhostLayerBuffers< ScalarType > &bufs)
Fills all ghost layers of a scalar FV field from neighbouring subdomains.
Definition fv_communication.hpp:316
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
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 int num_wedges_per_hex_cell
Definition kernel_helpers.hpp:5
constexpr dense::Vec< T, 3 > forward_map(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:596
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:657
Definition conversion.hpp:13
void apply_dirichlet_bcs(grid::Grid4DDataScalar< ScalarT > data, const grid::Grid4DDataScalar< grid::shell::ShellBoundaryFlag > &boundary_mask, const DirichletBCs< ScalarT > &bcs, const grid::shell::DistributedDomain &domain)
Strongly enforce Dirichlet boundary conditions on the radial shell boundaries.
Definition helpers.hpp:66
void initialize_cell_centers(linalg::VectorFVVec< ScalarType, 3 > &dst, const grid::shell::DistributedDomain &domain, const grid::Grid3DDataVec< GridScalarType, 3 > &coords_shell, const grid::Grid2DDataScalar< GridScalarType > &coords_radii)
Computes cell center positions once and populates ghost layers via MPI communication.
Definition helpers.hpp:201
void compute_cell_centers(linalg::VectorFVVec< ScalarType, 3 > &dst, const grid::Grid3DDataVec< GridScalarType, 3 > &coords_shell, const grid::Grid2DDataScalar< GridScalarType > &coords_radii)
Computes cell centers and writes to a vector valued finite volume function.
Definition helpers.hpp:129
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_fv_skip_ghost_layers(const DistributedDomain &distributed_domain)
Definition spherical_shell.hpp:2763
Kokkos::View< ScalarType ***[VecDim], Layout > Grid3DDataVec
Definition grid_types.hpp:42
Kokkos::View< ScalarType ****, Layout > Grid4DDataScalar
Definition grid_types.hpp:27
Kokkos::View< ScalarType **, Layout > Grid2DDataScalar
Definition grid_types.hpp:21
constexpr bool has_flag(E mask_value, E flag) noexcept
Checks if a bitmask value contains a specific flag.
Definition bit_masking.hpp:43
Constant Dirichlet boundary conditions for the inner (CMB) and outer (surface) radial boundaries of t...
Definition helpers.hpp:31
ScalarT T_cmb
Prescribed temperature at the core-mantle boundary.
Definition helpers.hpp:32
ScalarT T_surface
Prescribed temperature at the outer surface.
Definition helpers.hpp:33
bool apply_surface
Enforce surface Dirichlet BC when true.
Definition helpers.hpp:35
bool apply_cmb
Enforce CMB Dirichlet BC when true.
Definition helpers.hpp:34
auto extent(int i) const
Definition grid_types.hpp:75