Gyselalib++
czarny_to_cartesian.hpp
1 // SPDX-License-Identifier: MIT
2 #pragma once
3 
4 #include <cmath>
5 
6 #include <ddc/ddc.hpp>
7 
8 #include <sll/view.hpp>
9 
10 #include "coordinate_converter.hpp"
11 #include "curvilinear2d_to_cartesian.hpp"
12 #include "mapping_tools.hpp"
13 #include "pseudo_cartesian_compatible_mapping.hpp"
14 
15 
48 template <class X, class Y, class R, class Theta>
50  : public CoordinateConverter<ddc::Coordinate<X, Y>, ddc::Coordinate<R, Theta>>
52  , public Curvilinear2DToCartesian<X, Y, R, Theta>
53 {
54 public:
64 
66  using CoordArg = ddc::Coordinate<R, Theta>;
68  using CoordResult = ddc::Coordinate<X, Y>;
69 
70 private:
71  double m_epsilon;
72  double m_e;
73 
74 public:
86  CzarnyToCartesian(double epsilon, double e) : m_epsilon(epsilon), m_e(e) {}
87 
94  KOKKOS_FUNCTION CzarnyToCartesian(CzarnyToCartesian const& other)
95  : m_epsilon(other.epsilon())
96  , m_e(other.e())
97  {
98  }
99 
107 
108  ~CzarnyToCartesian() = default;
109 
119 
129 
137  KOKKOS_FUNCTION double epsilon() const
138  {
139  return m_epsilon;
140  }
141 
149  KOKKOS_FUNCTION double e() const
150  {
151  return m_e;
152  }
153 
161  KOKKOS_FUNCTION ddc::Coordinate<X, Y> operator()(ddc::Coordinate<R, Theta> const& coord) const
162  {
163  const double r = ddc::get<R>(coord);
164  const double theta = ddc::get<Theta>(coord);
165  const double tmp1
166  = Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * Kokkos::cos(theta)) + 1.0);
167 
168  const double x = (1.0 - tmp1) / m_epsilon;
169  const double y = m_e * r * Kokkos::sin(theta)
170  / (Kokkos::sqrt(1.0 - 0.25 * m_epsilon * m_epsilon) * (2.0 - tmp1));
171 
172  return ddc::Coordinate<X, Y>(x, y);
173  }
174 
182  KOKKOS_FUNCTION ddc::Coordinate<R, Theta> operator()(
183  ddc::Coordinate<X, Y> const& coord) const final
184  {
185  const double x = ddc::get<X>(coord);
186  const double y = ddc::get<Y>(coord);
187  const double ex = 1. + m_epsilon * x;
188  const double ex2 = (m_epsilon * x * x - 2. * x - m_epsilon);
189  const double xi2 = 1. / (1. - m_epsilon * m_epsilon * 0.25);
190  const double xi = Kokkos::sqrt(xi2);
191  const double r = Kokkos::sqrt(y * y * ex * ex / (m_e * m_e * xi2) + ex2 * ex2 * 0.25);
192  double theta
193  = Kokkos::atan2(2. * y * ex, (m_e * xi * (m_epsilon * x * x - 2. * x - m_epsilon)));
194  if (theta < 0) {
195  theta = 2 * M_PI + theta;
196  }
197  return ddc::Coordinate<R, Theta>(r, theta);
198  }
199 
208  KOKKOS_FUNCTION double jacobian(ddc::Coordinate<R, Theta> const& coord) const
209  {
210  const double r = ddc::get<R>(coord);
211  const double theta = ddc::get<Theta>(coord);
212  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
213  return -r / Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * Kokkos::cos(theta))) * m_e
214  * xi
215  / (2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * Kokkos::cos(theta))));
216  }
217 
218 
238  KOKKOS_FUNCTION void jacobian_matrix(ddc::Coordinate<R, Theta> const& coord, Matrix_2x2& matrix)
239  const
240  {
241  const double r = ddc::get<R>(coord);
242  const double theta = ddc::get<Theta>(coord);
243 
244  const double sin_theta = Kokkos::sin(theta);
245  const double cos_theta = Kokkos::cos(theta);
246  const double xi2 = 1. / (1. - m_epsilon * m_epsilon * 0.25);
247  const double xi = Kokkos::sqrt(xi2);
248  const double sqrt_eps = Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * cos_theta) + 1.0);
249  const double sqrt_eps_2 = 2.0 - sqrt_eps;
250 
251  matrix[0][0] = -cos_theta / sqrt_eps;
252  matrix[0][1] = r * sin_theta / sqrt_eps;
253  matrix[1][0] = m_e * m_epsilon * r * sin_theta * cos_theta * xi
254  / (sqrt_eps_2 * sqrt_eps_2 * sqrt_eps)
255  + m_e * sin_theta * xi / sqrt_eps_2;
256  matrix[1][1] = r
257  * (-m_e * m_epsilon * r * sin_theta * sin_theta * xi
258  / (sqrt_eps_2 * sqrt_eps_2 * sqrt_eps)
259  + m_e * cos_theta * xi / sqrt_eps_2);
260  }
261 
273  KOKKOS_FUNCTION double jacobian_11(ddc::Coordinate<R, Theta> const& coord) const
274  {
275  const double r = ddc::get<R>(coord);
276  const double theta = ddc::get<Theta>(coord);
277  return -Kokkos::cos(theta)
278  / Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * Kokkos::cos(theta)) + 1.0);
279  }
280 
292  KOKKOS_FUNCTION double jacobian_12(ddc::Coordinate<R, Theta> const& coord) const
293  {
294  const double r = ddc::get<R>(coord);
295  const double theta = ddc::get<Theta>(coord);
296  return r * Kokkos::sin(theta)
297  / Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * Kokkos::cos(theta)) + 1.0);
298  }
299 
311  KOKKOS_FUNCTION double jacobian_21(ddc::Coordinate<R, Theta> const& coord) const
312  {
313  const double r = ddc::get<R>(coord);
314  const double theta = ddc::get<Theta>(coord);
315 
316  const double sin_theta = Kokkos::sin(theta);
317  const double cos_theta = Kokkos::cos(theta);
318  const double xi2 = 1. / (1. - m_epsilon * m_epsilon * 0.25);
319  const double xi = Kokkos::sqrt(xi2);
320  const double tmp1 = Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * cos_theta) + 1.0);
321  const double tmp2 = 2.0 - tmp1;
322  return m_e * m_epsilon * r * sin_theta * cos_theta * xi / (tmp2 * tmp2 * tmp1)
323  + m_e * sin_theta * xi / tmp2;
324  }
325 
337  KOKKOS_FUNCTION double jacobian_22(ddc::Coordinate<R, Theta> const& coord) const
338  {
339  const double r = ddc::get<R>(coord);
340  const double theta = ddc::get<Theta>(coord);
341 
342  const double sin_theta = Kokkos::sin(theta);
343  const double cos_theta = Kokkos::cos(theta);
344  const double xi2 = 1. / (1. - m_epsilon * m_epsilon * 0.25);
345  const double xi = Kokkos::sqrt(xi2);
346  const double tmp1 = Kokkos::sqrt(m_epsilon * (m_epsilon + 2.0 * r * cos_theta) + 1.0);
347  const double tmp2 = 2.0 - tmp1;
348  return r
349  * (-m_e * m_epsilon * r * sin_theta * sin_theta * xi / (tmp2 * tmp2 * tmp1)
350  + m_e * cos_theta * xi / tmp2);
351  }
352 
372  KOKKOS_FUNCTION void inv_jacobian_matrix(
373  ddc::Coordinate<R, Theta> const& coord,
374  Matrix_2x2& matrix) const
375  {
376  const double r = ddc::get<R>(coord);
377  const double theta = ddc::get<Theta>(coord);
378 
379  assert(r >= 1e-15);
380 
381  const double sin_theta = Kokkos::sin(theta);
382  const double cos_theta = Kokkos::cos(theta);
383  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
384  const double divisor = 2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
385 
386  const double fact_1 = 1 / Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
387  const double fact_2 = m_e * m_epsilon * xi * r * sin_theta * fact_1 / divisor / divisor;
388  const double fact_3 = m_e * xi / divisor;
389 
390  matrix[0][0] = -1 / fact_1 * (-sin_theta * fact_2 + cos_theta * fact_3) / fact_3;
391  matrix[0][1] = sin_theta / fact_3;
392  matrix[1][0] = 1 / r / fact_1 * (cos_theta * fact_2 + sin_theta * fact_3) / fact_3;
393  matrix[1][1] = 1 / r * cos_theta / fact_3;
394  }
395 
396 
397 
408  KOKKOS_FUNCTION double inv_jacobian_11(ddc::Coordinate<R, Theta> const& coord) const
409  {
410  const double r = ddc::get<R>(coord);
411  const double theta = ddc::get<Theta>(coord);
412 
413  const double sin_theta = Kokkos::sin(theta);
414  const double cos_theta = Kokkos::cos(theta);
415  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
416  const double divisor = 2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
417 
418  const double fact_1 = 1 / Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
419  const double fact_2 = m_e * m_epsilon * xi * r * sin_theta * fact_1 / divisor / divisor;
420  const double fact_3 = m_e * xi / divisor;
421 
422  return -1 / fact_1 * (-sin_theta * fact_2 + cos_theta * fact_3) / fact_3;
423  }
424 
435  KOKKOS_FUNCTION double inv_jacobian_12(ddc::Coordinate<R, Theta> const& coord) const
436  {
437  const double r = ddc::get<R>(coord);
438  const double theta = ddc::get<Theta>(coord);
439 
440  const double sin_theta = Kokkos::sin(theta);
441  const double cos_theta = Kokkos::cos(theta);
442  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
443  const double divisor = 2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
444 
445  const double fact_3 = m_e * xi / divisor;
446  return sin_theta / fact_3;
447  }
448 
459  KOKKOS_FUNCTION double inv_jacobian_21(ddc::Coordinate<R, Theta> const& coord) const
460  {
461  const double r = ddc::get<R>(coord);
462  const double theta = ddc::get<Theta>(coord);
463 
464  assert(r >= 1e-15);
465 
466  const double sin_theta = Kokkos::sin(theta);
467  const double cos_theta = Kokkos::cos(theta);
468  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
469  const double divisor = 2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
470 
471  const double fact_1 = 1 / Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
472  const double fact_2 = m_e * m_epsilon * xi * r * sin_theta * fact_1 / divisor / divisor;
473  const double fact_3 = m_e * xi / divisor;
474 
475  return 1 / r / fact_1 * (cos_theta * fact_2 + sin_theta * fact_3) / fact_3;
476  }
477 
488  KOKKOS_FUNCTION double inv_jacobian_22(ddc::Coordinate<R, Theta> const& coord) const
489  {
490  const double r = ddc::get<R>(coord);
491  const double theta = ddc::get<Theta>(coord);
492 
493  assert(r >= 1e-15);
494 
495  const double cos_theta = Kokkos::cos(theta);
496  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
497  const double divisor = 2 - Kokkos::sqrt(1 + m_epsilon * (m_epsilon + 2.0 * r * cos_theta));
498 
499  const double fact_3 = m_e * xi / divisor;
500  return 1 / r * cos_theta / fact_3;
501  }
502 
503 
523  KOKKOS_FUNCTION void to_pseudo_cartesian_jacobian_center_matrix(Matrix_2x2& matrix) const final
524  {
525  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
526  const double sqrt_eps_2 = Kokkos::sqrt(1. + m_epsilon * m_epsilon);
527  matrix[0][0] = -sqrt_eps_2;
528  matrix[0][1] = 0.;
529  matrix[1][0] = 0.;
530  matrix[1][1] = (2 - sqrt_eps_2) / m_e / xi;
531  }
532 
542  KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_11_center() const final
543  {
544  return -Kokkos::sqrt(1 + m_epsilon * m_epsilon);
545  }
546 
556  KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_12_center() const final
557  {
558  return 0;
559  }
560 
570  KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_21_center() const final
571  {
572  return 0;
573  }
574 
584  KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_22_center() const final
585  {
586  const double xi = Kokkos::sqrt(1. / (1. - m_epsilon * m_epsilon * 0.25));
587  return (2 - Kokkos::sqrt(1 + m_epsilon * m_epsilon)) / m_e / xi;
588  }
589 };
590 
591 namespace mapping_detail {
592 template <class X, class Y, class R, class Theta, class ExecSpace>
593 struct MappingAccessibility<ExecSpace, CzarnyToCartesian<X, Y, R, Theta>> : std::true_type
594 {
595 };
596 } // namespace mapping_detail
An operator to convert from the start coordinate type to the end coordinate type.
Definition: coordinate_converter.hpp:13
A class for describing curvilinear 2D mappings from the logical domain to the physical domain.
Definition: curvilinear2d_to_cartesian.hpp:9
A class for describing the Czarny 2D mapping.
Definition: czarny_to_cartesian.hpp:53
CzarnyToCartesian(CzarnyToCartesian &&x)=default
Instantiate a CzarnyToCartesian from another temporary CzarnyToCartesian (rvalue).
KOKKOS_FUNCTION double inv_jacobian_21(ddc::Coordinate< R, Theta > const &coord) const
Compute the (2,1) coefficient of the inverse Jacobian matrix.
Definition: czarny_to_cartesian.hpp:459
ddc::Coordinate< X, Y > CoordResult
The type of the result of the function described by this mapping.
Definition: czarny_to_cartesian.hpp:68
KOKKOS_FUNCTION ddc::Coordinate< R, Theta > operator()(ddc::Coordinate< X, Y > const &coord) const final
Convert the coordinate (x,y) to the equivalent coordinate.
Definition: czarny_to_cartesian.hpp:182
KOKKOS_FUNCTION ddc::Coordinate< X, Y > operator()(ddc::Coordinate< R, Theta > const &coord) const
Convert the coordinate to the equivalent (x,y) coordinate.
Definition: czarny_to_cartesian.hpp:161
KOKKOS_FUNCTION double jacobian_21(ddc::Coordinate< R, Theta > const &coord) const
Compute the (2,1) coefficient of the Jacobian matrix.
Definition: czarny_to_cartesian.hpp:311
CzarnyToCartesian & operator=(CzarnyToCartesian const &x)=default
Assign a CzarnyToCartesian from another CzarnyToCartesian (lvalue).
KOKKOS_FUNCTION double jacobian_11(ddc::Coordinate< R, Theta > const &coord) const
Compute the (1,1) coefficient of the Jacobian matrix.
Definition: czarny_to_cartesian.hpp:273
KOKKOS_FUNCTION void to_pseudo_cartesian_jacobian_center_matrix(Matrix_2x2 &matrix) const final
Compute the full Jacobian matrix from the mapping to the pseudo-Cartesian mapping at the central poin...
Definition: czarny_to_cartesian.hpp:523
CzarnyToCartesian & operator=(CzarnyToCartesian &&x)=default
Assign a CzarnyToCartesian from another temporary CzarnyToCartesian (rvalue).
KOKKOS_FUNCTION double inv_jacobian_11(ddc::Coordinate< R, Theta > const &coord) const
Compute the (1,1) coefficient of the inverse Jacobian matrix.
Definition: czarny_to_cartesian.hpp:408
KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_11_center() const final
Compute the (1,1) coefficient of the pseudo-Cartesian Jacobian matrix at the central point.
Definition: czarny_to_cartesian.hpp:542
ddc::Coordinate< R, Theta > CoordArg
The type of the argument of the function described by this mapping.
Definition: czarny_to_cartesian.hpp:66
KOKKOS_FUNCTION void inv_jacobian_matrix(ddc::Coordinate< R, Theta > const &coord, Matrix_2x2 &matrix) const
Compute full inverse Jacobian matrix.
Definition: czarny_to_cartesian.hpp:372
KOKKOS_FUNCTION CzarnyToCartesian(CzarnyToCartesian const &other)
Instantiate a CzarnyToCartesian from another CzarnyToCartesian (lvalue).
Definition: czarny_to_cartesian.hpp:94
KOKKOS_FUNCTION double epsilon() const
Return the parameter.
Definition: czarny_to_cartesian.hpp:137
KOKKOS_FUNCTION double jacobian_22(ddc::Coordinate< R, Theta > const &coord) const
Compute the (2,2) coefficient of the Jacobian matrix.
Definition: czarny_to_cartesian.hpp:337
KOKKOS_FUNCTION double e() const
Return the parameter.
Definition: czarny_to_cartesian.hpp:149
KOKKOS_FUNCTION double jacobian_12(ddc::Coordinate< R, Theta > const &coord) const
Compute the (1,2) coefficient of the Jacobian matrix.
Definition: czarny_to_cartesian.hpp:292
KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_21_center() const final
Compute the (2,1) coefficient of the pseudo-Cartesian Jacobian matrix at the central point.
Definition: czarny_to_cartesian.hpp:570
CzarnyToCartesian(double epsilon, double e)
Instantiate a CzarnyToCartesian from parameters.
Definition: czarny_to_cartesian.hpp:86
KOKKOS_FUNCTION double inv_jacobian_12(ddc::Coordinate< R, Theta > const &coord) const
Compute the (1,2) coefficient of the inverse Jacobian matrix.
Definition: czarny_to_cartesian.hpp:435
KOKKOS_FUNCTION double jacobian(ddc::Coordinate< R, Theta > const &coord) const
Compute the Jacobian, the determinant of the Jacobian matrix of the mapping.
Definition: czarny_to_cartesian.hpp:208
KOKKOS_FUNCTION void jacobian_matrix(ddc::Coordinate< R, Theta > const &coord, Matrix_2x2 &matrix) const
Compute full Jacobian matrix.
Definition: czarny_to_cartesian.hpp:238
KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_12_center() const final
Compute the (1,2) coefficient of the pseudo-Cartesian Jacobian matrix at the central point.
Definition: czarny_to_cartesian.hpp:556
KOKKOS_FUNCTION double inv_jacobian_22(ddc::Coordinate< R, Theta > const &coord) const
Compute the (2,2) coefficient of the inverse Jacobian matrix.
Definition: czarny_to_cartesian.hpp:488
KOKKOS_FUNCTION double to_pseudo_cartesian_jacobian_22_center() const final
Compute the (2,2) coefficient of the pseudo-Cartesian Jacobian matrix at the central point.
Definition: czarny_to_cartesian.hpp:584
An operator to calculate the Jacobian matrix of the mapping from the physical domain to the pseudo-Ca...
Definition: pseudo_cartesian_compatible_mapping.hpp:42
std::array< std::array< double, 2 >, 2 > Matrix_2x2
The type of the pseudo-Cartesian Jacobian matrix and its inverse.
Definition: pseudo_cartesian_compatible_mapping.hpp:45
Define non periodic real R dimension.
Definition: geometry.hpp:31
Define periodic real Theta dimension.
Definition: geometry.hpp:42
Define non periodic real X dimension.
Definition: geometry.hpp:278
Define non periodic real Y dimension.
Definition: geometry.hpp:289