Gyselalib++
spline_foot_finder.hpp
1 // SPDX-License-Identifier: MIT
2 #pragma once
3 #include <functional>
4 
5 #include <sll/mapping/cartesian_to_pseudo_cartesian.hpp>
6 #include <sll/mapping/circular_to_cartesian.hpp>
7 
8 #include "ddc_alias_inline_functions.hpp"
9 #include "ddc_aliases.hpp"
10 #include "geometry_pseudo_cartesian.hpp"
11 #include "ifoot_finder.hpp"
12 #include "vector_mapper.hpp"
13 
24 template <class TimeStepper, class AdvectionDomain, class Mapping>
26 {
27 private:
31  using X_adv = typename AdvectionDomain::X_adv;
35  using Y_adv = typename AdvectionDomain::Y_adv;
36 
39 
40  TimeStepper const& m_time_stepper;
41 
42  AdvectionDomain const& m_advection_domain;
43  AdvectionMapping m_mapping;
44 
45  SplineRThetaBuilder const& m_builder_advection_field;
46  SplineRThetaEvaluatorConstBound const& m_evaluator_advection_field;
47 
48 
49 public:
79  TimeStepper const& time_stepper,
80  AdvectionDomain const& advection_domain,
81  Mapping const& mapping,
82  SplineRThetaBuilder const& builder_advection_field,
83  SplineRThetaEvaluatorConstBound const& evaluator_advection_field,
84  double epsilon = 1e-12)
85  : m_time_stepper(time_stepper)
86  , m_advection_domain(advection_domain)
87  , m_mapping(CircularToPseudoCartesian(), mapping, epsilon)
88  , m_builder_advection_field(builder_advection_field)
89  , m_evaluator_advection_field(evaluator_advection_field)
90  {
91  }
92 
110  host_t<FieldRTheta<CoordRTheta>> feet,
111  host_t<DConstVectorFieldRTheta<X, Y>> advection_field,
112  double dt) const final
113  {
114  host_t<VectorSplineCoeffsMem2D<X_adv, Y_adv>> advection_field_in_adv_domain_coefs(
115  get_spline_idx_range(m_builder_advection_field));
116 
117  // Compute the advection field in the advection domain.
118  auto advection_field_in_adv_domain = create_geometry_mirror_view(
119  Kokkos::DefaultHostExecutionSpace(),
120  advection_field,
121  m_mapping);
122 
123  // Get the coefficients of the advection field in the advection domain.
124  m_builder_advection_field(
125  ddcHelper::get<X_adv>(advection_field_in_adv_domain_coefs),
126  ddcHelper::get<X_adv>(get_const_field(advection_field_in_adv_domain)));
127  m_builder_advection_field(
128  ddcHelper::get<Y_adv>(advection_field_in_adv_domain_coefs),
129  ddcHelper::get<Y_adv>(get_const_field(advection_field_in_adv_domain)));
130 
131 
132  // The function describing how the derivative of the evolve function is calculated.
133  std::function<
135  host_t<ConstFieldRTheta<CoordRTheta>>)>
136  dy = [&](host_t<DVectorFieldRTheta<X_adv, Y_adv>> updated_advection_field,
137  host_t<ConstFieldRTheta<CoordRTheta>> feet) {
138  m_evaluator_advection_field(
139  get_field(ddcHelper::get<X_adv>(updated_advection_field)),
140  get_const_field(feet),
141  get_const_field(
142  ddcHelper::get<X_adv>(advection_field_in_adv_domain_coefs)));
143  m_evaluator_advection_field(
144  get_field(ddcHelper::get<Y_adv>(updated_advection_field)),
145  get_const_field(feet),
146  get_const_field(
147  ddcHelper::get<Y_adv>(advection_field_in_adv_domain_coefs)));
148  };
149 
150  // The function describing how the value(s) are updated using the derivative.
151  std::function<
152  void(host_t<FieldRTheta<CoordRTheta>>,
154  double)>
155  update_function = [&](host_t<FieldRTheta<CoordRTheta>> feet,
156  host_t<DConstVectorFieldRTheta<X_adv, Y_adv>> advection_field,
157  double dt) {
158  // Compute the characteristic feet at t^n:
159  m_advection_domain.advect_feet(feet, advection_field, dt);
160 
161  // Treatment to conserve the C0 property of the advected function:
162  unify_value_at_center_pt(feet);
163  // Test if the values are the same at the center point
164  is_unified(feet);
165  };
166 
167 
168  // Solve the characteristic equation
169  m_time_stepper.update(Kokkos::DefaultHostExecutionSpace(), feet, dt, dy, update_function);
170 
171  is_unified(feet);
172  }
173 
174 
175 
176 private:
189  template <class T>
190  void is_unified(Field<T, IdxRangeRTheta, Kokkos::HostSpace> const& values) const
191  {
192  IdxRangeR const r_idx_range = get_idx_range<GridR>(values);
193  IdxRangeTheta const theta_idx_range = get_idx_range<GridTheta>(values);
194  if (std::fabs(ddc::coordinate(r_idx_range.front())) < 1e-15) {
195  ddc::for_each(theta_idx_range, [&](const IdxTheta ip) {
196  if (norm_inf(
197  values(r_idx_range.front(), ip)
198  - values(r_idx_range.front(), theta_idx_range.front()))
199  > 1e-15) {
200  std::cout << "WARNING ! -> Discontinous at the center point." << std::endl;
201  }
202  assert(values(r_idx_range.front(), ip)
203  == values(r_idx_range.front(), theta_idx_range.front()));
204  });
205  }
206  }
207 
208 
222  template <class T>
223  void unify_value_at_center_pt(FieldRTheta<T> values) const
224  {
225  IdxRangeR const r_idx_range = get_idx_range<GridR>(values);
226  IdxRangeTheta const theta_idx_range = get_idx_range<GridTheta>(values);
227  if (std::fabs(ddc::coordinate(r_idx_range.front())) < 1e-15) {
228  ddc::for_each(theta_idx_range, [&](const IdxTheta ip) {
229  values(r_idx_range.front(), ip)
230  = values(r_idx_range.front(), theta_idx_range.front());
231  });
232  }
233  }
234 };
Define a domain for the advection.
Definition: advection_domain.hpp:40
A class for describing the circular 2D mapping.
Definition: circular_to_cartesian.hpp:45
Define a base class for all the time integration methods used for the advection.
Definition: ifoot_finder.hpp:14
Define a base class for all the time integration methods used for the advection.
Definition: spline_foot_finder.hpp:26
void operator()(host_t< FieldRTheta< CoordRTheta >> feet, host_t< DConstVectorFieldRTheta< X, Y >> advection_field, double dt) const final
Advect the feet over .
Definition: spline_foot_finder.hpp:109
SplineFootFinder(TimeStepper const &time_stepper, AdvectionDomain const &advection_domain, Mapping const &mapping, SplineRThetaBuilder const &builder_advection_field, SplineRThetaEvaluatorConstBound const &evaluator_advection_field, double epsilon=1e-12)
Instantiate a time integration method for the advection operator.
Definition: spline_foot_finder.hpp:78
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