Gyselalib++
bsl_advection_rp.hpp
1 // SPDX-License-Identifier: MIT
2 
3 #pragma once
4 #include <sll/mapping/curvilinear2d_to_cartesian.hpp>
5 #include <sll/mapping/metric_tensor.hpp>
6 
7 #include "advection_domain.hpp"
8 #include "ddc_alias_inline_functions.hpp"
9 #include "ddc_aliases.hpp"
10 #include "directional_tag.hpp"
11 #include "geometry.hpp"
12 #include "i_interpolator_2d_rp.hpp"
13 #include "iadvectionrp.hpp"
14 #include "spline_foot_finder.hpp"
15 #include "spline_interpolator_2d_rp.hpp"
16 #include "vector_field.hpp"
17 #include "vector_field_mem.hpp"
18 
19 
20 
58 template <class FootFinder, class Mapping>
60 {
61 private:
63 
64  FootFinder const& m_find_feet;
65 
66  Mapping const& m_mapping;
67 
68 
69 public:
87  function_interpolator,
88  FootFinder const& foot_finder,
89  Mapping const& mapping)
90  : m_interpolator(function_interpolator)
91  , m_find_feet(foot_finder)
92  , m_mapping(mapping)
93  {
94  }
95 
96  ~BslAdvectionRTheta() override = default;
97 
98 
112  host_t<DFieldRTheta> operator()(
113  host_t<DFieldRTheta> allfdistribu,
114  host_t<DConstVectorFieldRTheta<X, Y>> advection_field_xy,
115  double dt) const
116  {
117  // Pre-allocate some memory to prevent allocation later in loop
118  std::unique_ptr<IInterpolatorRTheta> const interpolator_ptr = m_interpolator.preallocate();
119 
120  // Initialise the feet
121  host_t<FieldMemRTheta<CoordRTheta>> feet_rp(get_idx_range(advection_field_xy));
122  ddc::for_each(get_idx_range(advection_field_xy), [&](IdxRTheta const irp) {
123  feet_rp(irp) = ddc::coordinate(irp);
124  });
125 
126  // Compute the characteristic feet at tn ----------------------------------------------------
127  m_find_feet(get_field(feet_rp), advection_field_xy, dt);
128 
129  // Interpolate the function on the characteristic feet. -------------------------------------
130  (*interpolator_ptr)(allfdistribu, get_const_field(feet_rp));
131 
132  return allfdistribu;
133  }
134 
135 
152  host_t<DFieldRTheta> operator()(
153  host_t<DFieldRTheta> allfdistribu,
154  host_t<DConstVectorFieldRTheta<R, Theta>> advection_field_rp,
155  CoordXY const& advection_field_xy_center,
156  double dt) const
157  {
158  IdxRangeRTheta grid(get_idx_range<GridR, GridTheta>(allfdistribu));
159 
160  const int npoints_p = IdxRangeTheta(grid).size();
161  IdxRangeRTheta const grid_without_Opoint(grid.remove_first(IdxStepRTheta(1, 0)));
162  IdxRangeRTheta const Opoint_grid(grid.take_first(IdxStepRTheta(1, npoints_p)));
163 
164 
165  // Convert advection field on RTheta to advection field on XY
166  host_t<DVectorFieldMemRTheta<X, Y>> advection_field_xy(grid);
167 
168  MetricTensor<Mapping, CoordRTheta> metric_tensor(m_mapping);
169 
170  ddc::for_each(grid_without_Opoint, [&](IdxRTheta const irp) {
171  CoordRTheta const coord_rp(ddc::coordinate(irp));
172 
173  std::array<std::array<double, 2>, 2> J; // Jacobian matrix
174  m_mapping.jacobian_matrix(coord_rp, J);
175  std::array<std::array<double, 2>, 2> G; // Metric tensor
176  metric_tensor(G, coord_rp);
177 
178  ddcHelper::get<X>(advection_field_xy)(irp)
179  = ddcHelper::get<R>(advection_field_rp)(irp) * J[1][1] / std::sqrt(G[1][1])
180  + ddcHelper::get<Theta>(advection_field_rp)(irp) * -J[1][0]
181  / std::sqrt(G[0][0]);
182  ddcHelper::get<Y>(advection_field_xy)(irp)
183  = ddcHelper::get<R>(advection_field_rp)(irp) * -J[0][1] / std::sqrt(G[1][1])
184  + ddcHelper::get<Theta>(advection_field_rp)(irp) * J[0][0]
185  / std::sqrt(G[0][0]);
186  });
187 
188  ddc::for_each(Opoint_grid, [&](IdxRTheta const irp) {
189  ddcHelper::get<X>(advection_field_xy)(irp) = CoordX(advection_field_xy_center);
190  ddcHelper::get<Y>(advection_field_xy)(irp) = CoordY(advection_field_xy_center);
191  });
192 
193  // Pre-allocate some memory to prevent allocation later in loop
194  std::unique_ptr<IInterpolatorRTheta> const interpolator_ptr = m_interpolator.preallocate();
195 
196  // Initialise the feet
197  host_t<FieldMemRTheta<CoordRTheta>> feet_rp(grid);
198  ddc::for_each(grid, [&](IdxRTheta const irp) { feet_rp(irp) = ddc::coordinate(irp); });
199 
200  // Compute the characteristic feet at tn ----------------------------------------------------
201  m_find_feet(get_field(feet_rp), get_const_field(advection_field_xy), dt);
202 
203  // Interpolate the function on the characteristic feet. -------------------------------------
204  (*interpolator_ptr)(allfdistribu, get_const_field(feet_rp));
205 
206  return allfdistribu;
207  }
208 };
Define an advection operator on 2D index range.
Definition: bsl_advection_rp.hpp:60
host_t< DFieldRTheta > operator()(host_t< DFieldRTheta > allfdistribu, host_t< DConstVectorFieldRTheta< R, Theta >> advection_field_rp, CoordXY const &advection_field_xy_center, double dt) const
Allocate a Field to the advected function.
Definition: bsl_advection_rp.hpp:152
host_t< DFieldRTheta > operator()(host_t< DFieldRTheta > allfdistribu, host_t< DConstVectorFieldRTheta< X, Y >> advection_field_xy, double dt) const
Allocate a Field of the advected function.
Definition: bsl_advection_rp.hpp:112
BslAdvectionRTheta(PreallocatableSplineInterpolatorRTheta< ddc::NullExtrapolationRule > const &function_interpolator, FootFinder const &foot_finder, Mapping const &mapping)
Instantiate an advection operator.
Definition: bsl_advection_rp.hpp:85
A class for describing the circular 2D mapping.
Definition: circular_to_cartesian.hpp:45
KOKKOS_FUNCTION void jacobian_matrix(ddc::Coordinate< R, Theta > const &coord, Matrix_2x2 &matrix) const
Compute full Jacobian matrix.
Definition: circular_to_cartesian.hpp:164
Define the base class of 2D advection operators in polar index range.
Definition: iadvectionrp.hpp:13
An operator for calculating the metric tensor.
Definition: metric_tensor.hpp:15
std::unique_ptr< IInterpolatorRTheta > preallocate() const override
Create a pointer to an instance of the SplineInterpolatorRTheta class.
Definition: spline_interpolator_2d_rp.hpp:153
A class which holds multiple (scalar) fields in order to represent a vector field.
Definition: vector_field.hpp:64