Gyselalib++
advection_domain.hpp
1 // SPDX-License-Identifier: MIT
2 #pragma once
3 #include <cassert>
4 #include <typeinfo>
5 
6 #include <sll/mapping/circular_to_cartesian.hpp>
7 #include <sll/mapping/curvilinear2d_to_cartesian.hpp>
8 
9 #include "advection_domain.hpp"
10 #include "ddc_alias_inline_functions.hpp"
11 #include "ddc_aliases.hpp"
12 #include "ddc_helper.hpp"
13 #include "directional_tag.hpp"
14 #include "geometry.hpp"
15 #include "geometry_pseudo_cartesian.hpp"
16 #include "math_tools.hpp"
17 #include "vector_field.hpp"
18 #include "vector_field_mem.hpp"
19 
38 template <class Mapping>
40 {
41 public:
42  virtual ~AdvectionDomain() {};
43 };
44 
45 
65 template <class Mapping>
67 {
68 public:
72  using X_adv = X;
76  using Y_adv = Y;
80  using CoordXY_adv = Coord<X_adv, Y_adv>;
81 
82 private:
83  Mapping const& m_mapping;
84 
85 public:
92  AdvectionPhysicalDomain(Mapping const& mapping) : m_mapping(mapping) {};
94 
132  host_t<FieldRTheta<CoordRTheta>> feet_coords_rp,
133  host_t<DConstVectorFieldRTheta<X_adv, Y_adv>> advection_field,
134  double dt) const
135  {
136  using namespace ddc;
137 
138  IdxRangeRTheta const idx_range_rp = get_idx_range<GridR, GridTheta>(feet_coords_rp);
139  CoordXY coord_center(m_mapping(CoordRTheta(0, 0)));
140 
141  ddc::for_each(idx_range_rp, [&](IdxRTheta const irp) {
142  CoordRTheta const coord_rp(feet_coords_rp(irp));
143  CoordXY const coord_xy = m_mapping(coord_rp);
144 
145  CoordXY const feet_xy = coord_xy - dt * advection_field(irp);
146 
147  if (norm_inf(feet_xy - coord_center) < 1e-15) {
148  feet_coords_rp(irp) = CoordRTheta(0, 0);
149  } else {
150  feet_coords_rp(irp) = m_mapping(feet_xy);
151  ddc::select<Theta>(feet_coords_rp(irp)) = ddcHelper::restrict_to_idx_range(
152  ddc::select<Theta>(feet_coords_rp(irp)),
153  IdxRangeTheta(idx_range_rp));
154  }
155  });
156  }
157 };
158 
159 
206 template <class Mapping>
208 {
209 public:
213  using Matrix2x2 = std::array<std::array<double, 2>, 2>;
214 
218  using X_adv = DimX_pC;
222  using Y_adv = DimY_pC;
226  using CoordXY_adv = Coord<X_adv, Y_adv>;
227 
228 
229 private:
230  Mapping const& m_mapping;
231  double m_epsilon;
232 
233 public:
243  AdvectionPseudoCartesianDomain(Mapping const& mapping, double epsilon = 1e-12)
244  : m_mapping(mapping)
245  , m_epsilon(epsilon) {};
247 
285  host_t<FieldRTheta<CoordRTheta>> feet_coords_rp,
286  host_t<DConstVectorFieldRTheta<X_adv, Y_adv>> const& advection_field,
287  double const dt) const
288  {
289  static_assert(!std::is_same_v<Mapping, CircularToCartesian<X, Y, R, Theta>>);
290  IdxRangeRTheta const idx_range_rp = get_idx_range(advection_field);
291 
292  CircularToCartesian<X_adv, Y_adv, R, Theta> const pseudo_Cartesian_mapping;
293  CoordXY_adv const center_xy_pseudo_cart
294  = CoordXY_adv(pseudo_Cartesian_mapping(CoordRTheta(0., 0.)));
295 
296  ddc::for_each(idx_range_rp, [&](IdxRTheta const irp) {
297  CoordRTheta const coord_rp(feet_coords_rp(irp));
298  CoordXY_adv const coord_xy_pseudo_cart = pseudo_Cartesian_mapping(coord_rp);
299  CoordXY_adv const feet_xy_pseudo_cart
300  = coord_xy_pseudo_cart - dt * advection_field(irp);
301 
302  if (norm_inf(feet_xy_pseudo_cart - center_xy_pseudo_cart) < 1e-15) {
303  feet_coords_rp(irp) = CoordRTheta(0, 0);
304  } else {
305  feet_coords_rp(irp) = pseudo_Cartesian_mapping(feet_xy_pseudo_cart);
306  ddc::select<Theta>(feet_coords_rp(irp)) = ddcHelper::restrict_to_idx_range(
307  ddc::select<Theta>(feet_coords_rp(irp)),
308  IdxRangeTheta(idx_range_rp));
309  }
310  });
311  }
312 };
Define a domain for the advection.
Definition: advection_domain.hpp:40
Define the physical domain for the advection.
Definition: advection_domain.hpp:67
Coord< X_adv, Y_adv > CoordXY_adv
The coordinate type associated to the dimensions in the advection domain.
Definition: advection_domain.hpp:80
void advect_feet(host_t< FieldRTheta< CoordRTheta >> feet_coords_rp, host_t< DConstVectorFieldRTheta< X_adv, Y_adv >> advection_field, double dt) const
Advect the characteristic feet.
Definition: advection_domain.hpp:131
AdvectionPhysicalDomain(Mapping const &mapping)
Instantiate a AdvectionPhysicalDomain advection domain.
Definition: advection_domain.hpp:92
Define the pseudo-Cartesian domain for the advection.
Definition: advection_domain.hpp:208
AdvectionPseudoCartesianDomain(Mapping const &mapping, double epsilon=1e-12)
Instantiate an AdvectionPseudoCartesianDomain advection domain.
Definition: advection_domain.hpp:243
void advect_feet(host_t< FieldRTheta< CoordRTheta >> feet_coords_rp, host_t< DConstVectorFieldRTheta< X_adv, Y_adv >> const &advection_field, double const dt) const
Advect the characteristic feet.
Definition: advection_domain.hpp:284
std::array< std::array< double, 2 >, 2 > Matrix2x2
Define a 2x2 matrix with an 2D array of an 2D array.
Definition: advection_domain.hpp:213
Coord< X_adv, Y_adv > CoordXY_adv
The coordinate type associated to the dimensions in the advection domain.
Definition: advection_domain.hpp:226
A class for describing the circular 2D mapping.
Definition: circular_to_cartesian.hpp:45
A class which holds multiple (scalar) fields in order to represent a vector field.
Definition: vector_field.hpp:64
KOKKOS_FUNCTION double norm_inf(ddc::Coordinate< Tags... > coord)
Compute the infinity norm.
Definition: math_tools.hpp:25
Tag the first non periodic dimension in the pseudo_Cartesian index range.
Definition: geometry_pseudo_cartesian.hpp:13
Tag the second non periodic dimension in the pseudo_Cartesian index range.
Definition: geometry_pseudo_cartesian.hpp:25
Define non periodic real X dimension.
Definition: geometry.hpp:278
Define non periodic real Y dimension.
Definition: geometry.hpp:289