Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_singular_mapping_advector_base.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_errors.h"
5 
7 
9 
11 
13 
15 
16  implicit none
17 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18 
19  ! Working precision
20  integer, parameter :: wp = f64
21 
23 
24  contains
25 
26  ! Deferred procedures
27  procedure(i_sub_velocity_field), deferred :: velocity_field
28  procedure(i_fun_flow_field), deferred :: flow_field
29  procedure(i_sub_free), deferred :: free
30 
31  ! Non-deferred procedures
32  procedure :: advect_cart => f_singular_mapping_advector__advect_cart
33  procedure :: advect_pseudo_cart => f_singular_mapping_advector__advect_pseudo_cart
34 
36 
37  ! Interfaces for deferred procedures
38  abstract interface
39 
40  sll_pure subroutine i_sub_velocity_field(self, x, a)
42  class(sll_c_singular_mapping_advector), intent(in) :: self
43  real(wp), intent(in) :: x(2)
44  real(wp), intent(out) :: a(2)
45  end subroutine i_sub_velocity_field
46 
47  sll_pure function i_fun_flow_field(self, x, h) result(y)
49  class(sll_c_singular_mapping_advector), intent(in) :: self
50  real(wp), intent(in) :: x(2)
51  real(wp), intent(in) :: h
52  real(wp) :: y(2)
53  end function i_fun_flow_field
54 
55  subroutine i_sub_free(self)
57  class(sll_c_singular_mapping_advector), intent(inout) :: self
58  end subroutine i_sub_free
59 
60  end interface
61 
62 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63 contains
64 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
65 
66  ! Advector (Runge-Kutta 3rd-order) using Cartesian coordinates
67  function f_singular_mapping_advector__advect_cart(self, eta, h, mapping, spline_2d_a1, spline_2d_a2) result(eta_new)
68  class(sll_c_singular_mapping_advector), intent(in) :: self
69  real(wp), intent(in) :: eta(2)
70  real(wp), intent(in) :: h
71  class(sll_c_singular_mapping), intent(in) :: mapping
72  type(sll_t_spline_2d), intent(in) :: spline_2d_a1
73  type(sll_t_spline_2d), intent(in) :: spline_2d_a2
74  real(wp) :: eta_new(2)
75 
76  integer, parameter :: maxiter = 100
77  real(wp), parameter :: tol = 1.0e-14_wp
78 
79  real(wp) :: x(2), tmp(2), k1(2), k2(2), k3(2) ! x are Cartesian coordinates
80 
81  ! Initial position
82  x = mapping%eval(eta)
83 
84  ! step #1
85  k1(1) = spline_2d_a1%eval(eta(1), eta(2))
86  k1(2) = spline_2d_a2%eval(eta(1), eta(2))
87 
88  ! step #2
89  tmp = mapping%eval_inverse(x + 0.5_wp*h*k1, eta, tol, maxiter)
90 
91  k2(1) = spline_2d_a1%eval(tmp(1), tmp(2))
92  k2(2) = spline_2d_a2%eval(tmp(1), tmp(2))
93 
94  ! step #3
95  tmp = mapping%eval_inverse(x + h*(2.0_wp*k2 - k1), eta, tol, maxiter)
96 
97  k3(1) = spline_2d_a1%eval(tmp(1), tmp(2))
98  k3(2) = spline_2d_a2%eval(tmp(1), tmp(2))
99 
100  ! Final position
101  x = x + h*(k1 + 4.0_wp*k2 + k3)/6.0_wp
102 
103  eta_new = mapping%eval_inverse(x, eta, tol, maxiter)
104 
106 
107  ! Advector (Runge-Kutta 3rd-order) using pseudo-Cartesian coordinates
108  function f_singular_mapping_advector__advect_pseudo_cart(self, eta, h, jac_2d_pcart, spline_2d_a1, spline_2d_a2) result(eta_new)
109  class(sll_c_singular_mapping_advector), intent(in) :: self
110  real(wp), intent(in) :: eta(2)
111  real(wp), intent(in) :: h
112  type(sll_t_jacobian_2d_pseudo_cartesian), intent(in) :: jac_2d_pcart
113  type(sll_t_spline_2d), intent(in) :: spline_2d_a1
114  type(sll_t_spline_2d), intent(in) :: spline_2d_a2
115  real(wp) :: eta_new(2)
116 
117 ! !---------------------------------------------------------------------------
118 ! ! Implicit trapezoidal
119 ! !---------------------------------------------------------------------------
120 !
121 ! integer :: j
122 ! real(wp) :: tol_sqr
123 ! real(wp) :: y0(2), y(2), dy(2), temp(2), k2(2), a0(2)
124 ! real(wp) :: jmat_comp(2,2)
125 !
126 ! y0 = polar_map( eta )
127 !
128 ! tol_sqr = ( abs_tol + rel_tol * norm2( y0 ) )**2
129 !
130 ! jmat_comp = jac_2d_pcart % eval( eta )
131 !
132 ! ! Pseudo-Cartesian components of advection field
133 ! a0(1) = jmat_comp(1,1) * spline_2d_a1 % eval( eta(1), eta(2) ) &
134 ! + jmat_comp(1,2) * spline_2d_a2 % eval( eta(1), eta(2) )
135 ! a0(2) = jmat_comp(2,1) * spline_2d_a1 % eval( eta(1), eta(2) ) &
136 ! + jmat_comp(2,2) * spline_2d_a2 % eval( eta(1), eta(2) )
137 !
138 ! ! First iteration
139 ! dy = h * a0
140 ! y = y0 + dy
141 ! eta_new = polar_map_inverse( y )
142 !
143 ! ! Successive iterations if first iteration did not converge
144 ! if ( dot_product( dy, dy ) > tol_sqr ) then
145 !
146 ! associate( k1 => a0, h_half => 0.5_wp*h, dy_old => temp, error => temp )
147 !
148 ! do j = 2, maxiter
149 !
150 ! jmat_comp = jac_2d_pcart % eval( eta_new )
151 !
152 ! ! k2 = f(t,x_{i-1})
153 ! k2(1) = jmat_comp(1,1) * spline_2d_a1 % eval( eta_new(1), eta_new(2) ) &
154 ! + jmat_comp(1,2) * spline_2d_a2 % eval( eta_new(1), eta_new(2) )
155 ! k2(2) = jmat_comp(2,1) * spline_2d_a1 % eval( eta_new(1), eta_new(2) ) &
156 ! + jmat_comp(2,2) * spline_2d_a2 % eval( eta_new(1), eta_new(2) )
157 !
158 ! dy_old = dy
159 ! dy = h_half*(k1+k2)
160 ! error = dy_old - dy
161 ! y = y0 + dy
162 ! eta_new = polar_map_inverse( y )
163 !
164 ! if ( dot_product( error, error ) <= tol_sqr ) exit
165 !
166 ! end do
167 !
168 ! end associate
169 !
170 ! end if
171 
172  !---------------------------------------------------------------------------
173  ! Runge-Kutta 3rd-order
174  !---------------------------------------------------------------------------
175 
176  real(wp) :: a_x1, a_x2
177  real(wp) :: x(2), tmp(2), k1(2), k2(2), k3(2) ! x are pseudo-Cartesian coordinates
178  real(wp) :: jmat_comp(2, 2)
179 
180  ! Initial position
181  x = polar_map(eta)
182 
183  ! step #1
184  a_x1 = spline_2d_a1%eval(eta(1), eta(2))
185  a_x2 = spline_2d_a2%eval(eta(1), eta(2))
186 
187  jmat_comp = jac_2d_pcart%eval(eta)
188 
189  k1(1) = jmat_comp(1, 1)*a_x1 + jmat_comp(1, 2)*a_x2
190  k1(2) = jmat_comp(2, 1)*a_x1 + jmat_comp(2, 2)*a_x2
191 
192  ! step #2
193  tmp = polar_map_inverse(x + 0.5_wp*h*k1)
194 
195  a_x1 = spline_2d_a1%eval(tmp(1), tmp(2))
196  a_x2 = spline_2d_a2%eval(tmp(1), tmp(2))
197 
198  jmat_comp = jac_2d_pcart%eval(tmp)
199 
200  k2(1) = jmat_comp(1, 1)*a_x1 + jmat_comp(1, 2)*a_x2
201  k2(2) = jmat_comp(2, 1)*a_x1 + jmat_comp(2, 2)*a_x2
202 
203  ! step #3
204  tmp = polar_map_inverse(x + h*(2.0_wp*k2 - k1))
205 
206  a_x1 = spline_2d_a1%eval(tmp(1), tmp(2))
207  a_x2 = spline_2d_a2%eval(tmp(1), tmp(2))
208 
209  jmat_comp = jac_2d_pcart%eval(tmp)
210 
211  k3(1) = jmat_comp(1, 1)*a_x1 + jmat_comp(1, 2)*a_x2
212  k3(2) = jmat_comp(2, 1)*a_x1 + jmat_comp(2, 2)*a_x2
213 
214  ! Final position
215  x = x + h*(k1 + 4.0_wp*k2 + k3)/6.0_wp
216 
217  eta_new = polar_map_inverse(x)
218 
219  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
220  contains
221  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
222 
223  sll_pure function polar_map(eta) result(y)
224  real(wp), intent(in) :: eta(2)
225  real(wp) :: y(2)
226 
227  y(1) = eta(1)*cos(eta(2))
228  y(2) = eta(1)*sin(eta(2))
229 
230  end function polar_map
231 
232  sll_pure function polar_map_inverse(y) result(eta)
233  real(wp), intent(in) :: y(2)
234  real(wp) :: eta(2)
235 
236  eta(1) = norm2(y)
237  eta(2) = modulo(atan2(y(2), y(1)), sll_p_twopi)
238 
239  if (eta(1) > 1.0_wp) eta(1) = 1.0_wp
240 
241  end function polar_map_inverse
242 
244 
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_twopi
real(wp) function, dimension(2) f_singular_mapping_advector__advect_cart(self, eta, h, mapping, spline_2d_a1, spline_2d_a2)
real(wp) function, dimension(2) f_singular_mapping_advector__advect_pseudo_cart(self, eta, h, jac_2d_pcart, spline_2d_a1, spline_2d_a2)
Module for tensor-product 2D splines.
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
2D tensor-product spline
    Report Typos and Errors