Loading...
Searching...
No Matches
grid_transfer_linear.hpp
Go to the documentation of this file.
1
2#pragma once
3#include "dense/vec.hpp"
5
7
8/// @brief Computes prolongation weights for the spherical shell.
9///
10/// @note See overload of this function for details.
11///
12/// This covers the (simpler) case that the fine node index and the corresponding coarse grid nodes are radially aligned.
13template < typename ScalarType >
15 const dense::Vec< int, 4 >& idx_fine,
16 const dense::Vec< int, 4 >& idx_coarse_bot,
17 const grid::Grid3DDataVec< ScalarType, 3 >& subdomain_shell_coords_fine,
18 const grid::Grid2DDataScalar< ScalarType > subdomain_radii_fine )
19{
21
22 const auto idx_coarse_top = idx_coarse_bot + dense::Vec< int, 4 >{ 0, 0, 0, 1 };
23
24 const auto local_subdomain = idx_fine( 0 );
25
26 const auto idx_coarse_bot_fine = dense::Vec< int, 4 >{
27 local_subdomain, 2 * idx_coarse_bot( 1 ), 2 * idx_coarse_bot( 2 ), 2 * idx_coarse_bot( 3 ) };
28 const auto idx_coarse_top_fine = dense::Vec< int, 4 >{
29 local_subdomain, 2 * idx_coarse_top( 1 ), 2 * idx_coarse_top( 2 ), 2 * idx_coarse_top( 3 ) };
30
31 // First we find the two points we want to interpolate between.
32
33 // Compute bottom point.
34
35 const auto coarse_bot =
36 grid::shell::coords( idx_coarse_bot_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
37
38 // Compute top point.
39
40 const auto coarse_top =
41 grid::shell::coords( idx_coarse_top_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
42
43 // Now find the linear interpolation coefficient of the fine point with respect to the two points.
44
45 const auto fine = grid::shell::coords( idx_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
46
47 const auto fine_norm = fine.norm();
48 const auto coarse_bot_norm = coarse_bot.norm();
49 const auto coarse_top_norm = coarse_top.norm();
50
51 const auto nu = ( fine_norm - coarse_bot_norm ) / ( coarse_top_norm - coarse_bot_norm );
52
53 weights( 0 ) = 1.0 - nu;
54 weights( 1 ) = nu;
55
56 return weights;
57}
58
59/// @brief Computes prolongation weights for the spherical shell.
60///
61/// Ensures that affine scalar functions (f(x) = a_1 * x_1 + a_2 * x_2 + a_3 * x_3 + c) are interpolated exactly.
62///
63/// Returns the non-zero columns of the prolongation matrix, i.e., the weights have to be multiplied with corresponding
64/// coarse grid values, summed, and written to the fine grid node. Therefore, this function is best used in a loop
65/// over the fine grid points.
66///
67/// A fine grid node is either located exactly at a coarse grid node, or between a pair of coarse grid nodes.
68/// There are three cases to consider overall:
69///
70/// a) fine grid node is at same position as coarse grid point => weight is 1.0
71/// b) fine grid node is between two radially aligned coarse grid points (the projection of the two coarse grid points
72/// onto the unit sphere is equal) => call the other overload of this function
73/// c) otherwise => CALL THIS FUNCTION
74///
75/// We can in that last case find four (distinct) coarse grid nodes bot_0, bot_1, top_0, top_1 with top_j and bot_j
76/// being aligned on a radial layer for j = 0, 1, such that all these nodes are aligned on a plane that also contains
77/// the fine grid node.
78///
79/// (Technically, that fine grid node is located on one facet of a spherical wedge element. We can therefore ignore the
80/// contributions from the other two wedge nodes that are not part of that facet).
81///
82/// It is required to specify the two bottom indices of those coarse nodes. The top ones are computed within this
83/// function.
84///
85/// @note Due to the refinement algorithm, negative prolongation weights are possible (and required) since in some cases
86/// at the boundary (largely the entire outer boundary) during refinement new nodes are created that are not
87/// contained in the "affine" coarse grid mesh.
88///
89/// @param idx_fine index (local_subdomain_id, x, y, r) of the fine grid node
90/// @param idx_coarse_bot_0 coarse grid index (local_subdomain_id, x_coarse, y_coarse, r_coarse) of one of the nodes at
91/// the bottom of the wedge's plane that contains the fine-grid node.
92/// @param idx_coarse_bot_1 coarse grid index (local_subdomain_id, x_coarse, y_coarse, r_coarse) of the other node at
93/// the bottom of the wedge's plane that contains the fine-grid node.
94/// @param subdomain_shell_coords_fine the coords of the nodes on the unit sphere
95/// @param subdomain_radii_fine the node radii
96///
97/// @return (weight_bot, weight_top) to scale the four coarse grid nodes:
98/// fine = weight_bot * ( coarse(bot_0) + coarse(bot_1) ) + weight_top * ( coarse(top_0) + coarse(top_1) )
99template < typename ScalarType >
101 const dense::Vec< int, 4 >& idx_fine,
102 const dense::Vec< int, 4 >& idx_coarse_bot_0,
103 const dense::Vec< int, 4 >& idx_coarse_bot_1,
104 const grid::Grid3DDataVec< ScalarType, 3 >& subdomain_shell_coords_fine,
105 const grid::Grid2DDataScalar< ScalarType > subdomain_radii_fine )
106{
108
109 const auto idx_coarse_top_0 = idx_coarse_bot_0 + dense::Vec< int, 4 >{ 0, 0, 0, 1 };
110 const auto idx_coarse_top_1 = idx_coarse_bot_1 + dense::Vec< int, 4 >{ 0, 0, 0, 1 };
111
112 const auto local_subdomain = idx_fine( 0 );
113
114 const auto idx_coarse_bot_0_fine = dense::Vec< int, 4 >{
115 local_subdomain, 2 * idx_coarse_bot_0( 1 ), 2 * idx_coarse_bot_0( 2 ), 2 * idx_coarse_bot_0( 3 ) };
116 const auto idx_coarse_bot_1_fine = dense::Vec< int, 4 >{
117 local_subdomain, 2 * idx_coarse_bot_1( 1 ), 2 * idx_coarse_bot_1( 2 ), 2 * idx_coarse_bot_1( 3 ) };
118 const auto idx_coarse_top_0_fine = dense::Vec< int, 4 >{
119 local_subdomain, 2 * idx_coarse_top_0( 1 ), 2 * idx_coarse_top_0( 2 ), 2 * idx_coarse_top_0( 3 ) };
120 const auto idx_coarse_top_1_fine = dense::Vec< int, 4 >{
121 local_subdomain, 2 * idx_coarse_top_1( 1 ), 2 * idx_coarse_top_1( 2 ), 2 * idx_coarse_top_1( 3 ) };
122
123 // First we find the two points we want to interpolate between.
124 // For that we compute the corresponding two points on the chords.
125 // This also captures the case that we are exactly located on a coarse point.
126
127 // Compute bottom point on chord.
128
129 const auto coarse_bot_0 =
130 grid::shell::coords( idx_coarse_bot_0_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
131 const auto coarse_bot_1 =
132 grid::shell::coords( idx_coarse_bot_1_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
133 const auto coarse_bot_chord = 0.5 * ( coarse_bot_0 + coarse_bot_1 );
134
135 // Compute top point on chord.
136
137 const auto coarse_top_0 =
138 grid::shell::coords( idx_coarse_top_0_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
139 const auto coarse_top_1 =
140 grid::shell::coords( idx_coarse_top_1_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
141 const auto coarse_top_chord = 0.5 * ( coarse_top_0 + coarse_top_1 );
142
143 // Now find the linear interpolation coefficient of the fine point with respect to the two chord points.
144
145 const auto fine = grid::shell::coords( idx_fine, subdomain_shell_coords_fine, subdomain_radii_fine );
146
147 const auto fine_norm = fine.norm();
148 const auto coarse_bot_norm = coarse_bot_chord.norm();
149 const auto coarse_top_norm = coarse_top_chord.norm();
150
151 const auto nu = ( fine_norm - coarse_bot_norm ) / ( coarse_top_norm - coarse_bot_norm );
152
153 weights( 0 ) = 0.5 * ( 1.0 - nu );
154 weights( 1 ) = 0.5 * nu;
155
156 return weights;
157}
158
159} // namespace terra::fe::wedge::shell
Definition grid_transfer_constant.hpp:6
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
dense::Vec< typename CoordsShellType::value_type, 3 > coords(const int subdomain, const int x, const int y, const int r, const CoordsShellType &coords_shell, const CoordsRadiiType &coords_radii)
Definition spherical_shell.hpp:2789
Kokkos::View< ScalarType ***[VecDim], Layout > Grid3DDataVec
Definition grid_types.hpp:40
Kokkos::View< ScalarType **, Layout > Grid2DDataScalar
Definition grid_types.hpp:19
Definition vec.hpp:9