Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_jacobian_2d_pseudo_cartesian.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 
6 
7  use sll_m_constants, only: sll_p_pi
8 
10 
11  implicit none
12 
14 
15  private
16 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 
18  ! Working precision
19  integer, parameter :: wp = f64
20 
22 
23  ! Can be overwritten at initialization
24  real(wp) :: eps = 1.0e-12_wp
25 
26  type(sll_t_singular_mapping_discrete), pointer :: mapping => null()
27 
28  real(wp) :: jmat_pole(2, 2)
29 
30  contains
31 
34  procedure :: eval => s_jacobian_2d_pseudo_cartesian__eval
36 
38 
39 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
40 contains
41 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42 
43  subroutine s_jacobian_2d_pseudo_cartesian__init(self, mapping, eps)
44  class(sll_t_jacobian_2d_pseudo_cartesian), intent(inout) :: self
45  type(sll_t_singular_mapping_discrete), target, intent(in) :: mapping
46  real(wp), optional, intent(in) :: eps
47 
48  self%mapping => mapping
49 
50  if (present(eps)) self%eps = eps
51 
53 
54  !-----------------------------------------------------------------------------
55  ! Implements average over theta of inverse of equation (17) of https://doi.org/10.1016/j.jcp.2019.108889
56  !-----------------------------------------------------------------------------
57  subroutine s_jacobian_2d_pseudo_cartesian__pole(self, eta2_array)
58  class(sll_t_jacobian_2d_pseudo_cartesian), intent(inout) :: self
59  real(wp), intent(in) :: eta2_array(:)
60 
61  integer :: i2
62  real(wp) :: s, theta
63  real(wp) :: jmat_temp(2, 2)
64 
65  self%jmat_pole(:, :) = 0.0_wp
66 
67  s = 0.0_wp
68 
69  do i2 = 1, size(eta2_array)
70 
71  theta = eta2_array(i2)
72 
73  jmat_temp(2, 2) = self%mapping%spline_2d_x1%eval_deriv_x1(s, theta)*cos(theta) &
74  - self%mapping%spline_2d_x1%eval_deriv_x1x2(s, theta)*sin(theta)
75 
76  jmat_temp(1, 2) = -self%mapping%spline_2d_x1%eval_deriv_x1(s, theta)*sin(theta) &
77  - self%mapping%spline_2d_x1%eval_deriv_x1x2(s, theta)*cos(theta)
78 
79  jmat_temp(2, 1) = -self%mapping%spline_2d_x2%eval_deriv_x1(s, theta)*cos(theta) &
80  + self%mapping%spline_2d_x2%eval_deriv_x1x2(s, theta)*sin(theta)
81 
82  jmat_temp(1, 1) = self%mapping%spline_2d_x2%eval_deriv_x1(s, theta)*sin(theta) &
83  + self%mapping%spline_2d_x2%eval_deriv_x1x2(s, theta)*cos(theta)
84 
85  jmat_temp(:, :) = jmat_temp(:, :)/(jmat_temp(1, 1)*jmat_temp(2, 2) - jmat_temp(1, 2)*jmat_temp(2, 1))
86 
87  self%jmat_pole(:, :) = self%jmat_pole(:, :) + jmat_temp(:, :)
88 
89  end do
90 
91  ! Take average over all values of theta
92  self%jmat_pole(:, :) = self%jmat_pole(:, :)/size(eta2_array)
93 
95 
96  !-----------------------------------------------------------------------------
97  ! Implements strategy described in section 4 of https://doi.org/10.1016/j.jcp.2019.108889
98  !-----------------------------------------------------------------------------
99  sll_pure function s_jacobian_2d_pseudo_cartesian__eval(self, eta) result(jmat)
100  class(sll_t_jacobian_2d_pseudo_cartesian), intent(in) :: self
101  real(wp), intent(in) :: eta(2)
102  real(wp) :: jmat(2, 2) ! inverse of Jacobian
103 
104  real(wp) :: eps, jmat_pole(2, 2), jmat_eps(2, 2)
105 
106  eps = self%eps
107 
108  ! Implements average over theta of inverse of equation (17) of https://doi.org/10.1016/j.jcp.2019.108889
109  if (eta(1) == 0.0_wp) then
110 
111  jmat(:, :) = self%jmat_pole(:, :)
112 
113  ! Implements last equation on page 7 of https://doi.org/10.1016/j.jcp.2019.108889
114  else if (0.0_wp < eta(1) .and. eta(1) < eps) then
115 
116  jmat_pole(:, :) = self%jmat_pole(:, :)
117 
118  jmat_eps(2, 2) = self%mapping%spline_2d_x1%eval_deriv_x1(eps, eta(2))*cos(eta(2)) &
119  - self%mapping%spline_2d_x1%eval_deriv_x2(eps, eta(2))*sin(eta(2))/eps
120 
121  jmat_eps(1, 2) = -self%mapping%spline_2d_x1%eval_deriv_x1(eps, eta(2))*sin(eta(2)) &
122  - self%mapping%spline_2d_x1%eval_deriv_x2(eps, eta(2))*cos(eta(2))/eps
123 
124  jmat_eps(2, 1) = -self%mapping%spline_2d_x2%eval_deriv_x1(eps, eta(2))*cos(eta(2)) &
125  + self%mapping%spline_2d_x2%eval_deriv_x2(eps, eta(2))*sin(eta(2))/eps
126 
127  jmat_eps(1, 1) = self%mapping%spline_2d_x2%eval_deriv_x1(eps, eta(2))*sin(eta(2)) &
128  + self%mapping%spline_2d_x2%eval_deriv_x2(eps, eta(2))*cos(eta(2))/eps
129 
130  jmat_eps(:, :) = jmat_eps(:, :)/(jmat_eps(1, 1)*jmat_eps(2, 2) - jmat_eps(1, 2)*jmat_eps(2, 1))
131 
132  ! Linear interpolation between s = 0 and s = eps
133 
134  jmat(1, 1) = (1.0_wp - eta(1)/eps)*jmat_pole(1, 1) + eta(1)/eps*jmat_eps(1, 1)
135  jmat(1, 2) = (1.0_wp - eta(1)/eps)*jmat_pole(1, 2) + eta(1)/eps*jmat_eps(1, 2)
136  jmat(2, 1) = (1.0_wp - eta(1)/eps)*jmat_pole(2, 1) + eta(1)/eps*jmat_eps(2, 1)
137  jmat(2, 2) = (1.0_wp - eta(1)/eps)*jmat_pole(2, 2) + eta(1)/eps*jmat_eps(2, 2)
138 
139  ! Implements inverse of equation (16) of https://doi.org/10.1016/j.jcp.2019.108889
140  else if (eps <= eta(1)) then
141 
142  jmat(2, 2) = self%mapping%spline_2d_x1%eval_deriv_x1(eta(1), eta(2))*cos(eta(2)) &
143  - self%mapping%spline_2d_x1%eval_deriv_x2(eta(1), eta(2))*sin(eta(2))/eta(1)
144 
145  jmat(1, 2) = -self%mapping%spline_2d_x1%eval_deriv_x1(eta(1), eta(2))*sin(eta(2)) &
146  - self%mapping%spline_2d_x1%eval_deriv_x2(eta(1), eta(2))*cos(eta(2))/eta(1)
147 
148  jmat(2, 1) = -self%mapping%spline_2d_x2%eval_deriv_x1(eta(1), eta(2))*cos(eta(2)) &
149  + self%mapping%spline_2d_x2%eval_deriv_x2(eta(1), eta(2))*sin(eta(2))/eta(1)
150 
151  jmat(1, 1) = self%mapping%spline_2d_x2%eval_deriv_x1(eta(1), eta(2))*sin(eta(2)) &
152  + self%mapping%spline_2d_x2%eval_deriv_x2(eta(1), eta(2))*cos(eta(2))/eta(1)
153 
154  jmat(:, :) = jmat(:, :)/(jmat(1, 1)*jmat(2, 2) - jmat(1, 2)*jmat(2, 1))
155 
156  end if
157 
158  end function s_jacobian_2d_pseudo_cartesian__eval
159 
160  !-----------------------------------------------------------------------------
162  class(sll_t_jacobian_2d_pseudo_cartesian), intent(inout) :: self
163 
164  nullify (self%mapping)
165 
167 
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
subroutine s_jacobian_2d_pseudo_cartesian__pole(self, eta2_array)
subroutine s_jacobian_2d_pseudo_cartesian__init(self, mapping, eps)
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
    Report Typos and Errors