Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_singular_mapping_discrete.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 
6 
8 
10 
12 
14  sll_p_greville, &
15  sll_p_periodic
16 
17  use sll_m_bsplines, only: sll_c_bsplines
18 
20 
22 
23  use sll_m_hdf5_io_serial, only: &
28 
30 
31  private
32 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33 
35  integer, parameter :: wp = f64
36 
39 
40  ! Number of basis functions along eta1 and eta2
41  integer :: nbasis_eta1
42  integer :: nbasis_eta2
43 
44  ! Number of basis functions along eta1 and eta2
45  integer :: degree_eta1
46  integer :: degree_eta2
47 
48  ! Interpolation points
49  real(wp), allocatable :: tau_eta1(:)
50  real(wp), allocatable :: tau_eta2(:)
51 
52  real(wp), allocatable :: gtau_x1(:, :)
53  real(wp), allocatable :: gtau_x2(:, :)
54 
55  ! 2D splines
56  type(sll_t_spline_2d) :: spline_2d_x1
57  type(sll_t_spline_2d) :: spline_2d_x2
58 
59  ! 2D spline interpolator
60  type(sll_t_spline_interpolator_2d) :: spline_interp_eta12
61 
62  contains
63 
64  procedure :: init => s_singular_mapping_discrete__init
65  procedure :: pole => f_singular_mapping_discrete__pole
66  procedure :: eval => f_singular_mapping_discrete__eval
67  procedure :: jmat => f_singular_mapping_discrete__jmat ! Jacobian matrix
68  procedure :: store_data => s_singular_mapping_discrete__store_data
69  procedure :: free => s_singular_mapping_discrete__free
70 
72 
73 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
74 contains
75 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
76 
77  subroutine s_singular_mapping_discrete__init(self, spline_basis_eta1, spline_basis_eta2, mapping_analytic)
78  class(sll_t_singular_mapping_discrete), intent(inout) :: self
79  class(sll_c_bsplines), intent(in) :: spline_basis_eta1
80  class(sll_c_bsplines), intent(in) :: spline_basis_eta2
81  class(sll_c_singular_mapping_analytic), intent(in) :: mapping_analytic
82 
83  integer :: i1, i2
84  real(wp) :: eta(2), x(2)
85 
86  ! Store number of basis functions along eta1 and eta2
87  self%nbasis_eta1 = spline_basis_eta1%nbasis
88  self%nbasis_eta2 = spline_basis_eta2%nbasis
89 
90  ! Store degree of basis functions along eta1 and eta2
91  self%degree_eta1 = spline_basis_eta1%degree
92  self%degree_eta2 = spline_basis_eta2%degree
93 
94  ! Initialize 2D spline along x1
95  call self%spline_2d_x1%init( &
96  bsplines_x1=spline_basis_eta1, &
97  bsplines_x2=spline_basis_eta2)
98 
99  ! Initialize 2D spline along x2
100  call self%spline_2d_x2%init( &
101  bsplines_x1=spline_basis_eta1, &
102  bsplines_x2=spline_basis_eta2)
103 
104  ! Initialize 2D spline interpolator
105  call self%spline_interp_eta12%init( &
106  bspl1=spline_basis_eta1, &
107  bspl2=spline_basis_eta2, &
108  bc_xmin=[sll_p_greville, sll_p_periodic], &
109  bc_xmax=[sll_p_greville, sll_p_periodic])
110 
111  ! Get interpolation points from spline interpolator
112  call self%spline_interp_eta12%get_interp_points( &
113  tau1=self%tau_eta1, &
114  tau2=self%tau_eta2)
115 
116  allocate (self%gtau_x1(size(self%tau_eta1), size(self%tau_eta2)))
117  allocate (self%gtau_x2(size(self%tau_eta1), size(self%tau_eta2)))
118 
119  associate(ntau1 => size(self%tau_eta1), ntau2 => size(self%tau_eta2))
120 
121  ! Evaluate analytical mapping on interpolation points
122  do i2 = 1, ntau2
123  do i1 = 1, ntau1
124  eta(1) = self%tau_eta1(i1)
125  eta(2) = self%tau_eta2(i2)
126  x(:) = mapping_analytic%eval(eta)
127  self%gtau_x1(i1, i2) = x(1)
128  self%gtau_x2(i1, i2) = x(2)
129  end do
130  end do
131 
132  end associate
133 
134  ! Compute interpolant 2D spline along x1
135  call self%spline_interp_eta12%compute_interpolant( &
136  spline=self%spline_2d_x1, &
137  gtau=self%gtau_x1)
138 
139  ! Compute interpolant 2D spline along x2
140  call self%spline_interp_eta12%compute_interpolant( &
141  spline=self%spline_2d_x2, &
142  gtau=self%gtau_x2)
143 
144  end subroutine s_singular_mapping_discrete__init
145 
146  !-----------------------------------------------------------------------------
147  sll_pure function f_singular_mapping_discrete__pole(self) result(pole)
148  class(sll_t_singular_mapping_discrete), intent(in) :: self
149  real(wp) :: pole(2)
150 
151  pole(1) = self%spline_2d_x1%bcoef(1, 1)
152  pole(2) = self%spline_2d_x2%bcoef(1, 1)
153 
154  end function f_singular_mapping_discrete__pole
155 
156  !-----------------------------------------------------------------------------
157  sll_pure function f_singular_mapping_discrete__eval(self, eta) result(x)
158  class(sll_t_singular_mapping_discrete), intent(in) :: self
159  real(wp), intent(in) :: eta(2)
160  real(wp) :: x(2)
161 
162  x(1) = self%spline_2d_x1%eval(eta(1), eta(2))
163  x(2) = self%spline_2d_x2%eval(eta(1), eta(2))
164 
165  end function f_singular_mapping_discrete__eval
166 
167  !-----------------------------------------------------------------------------
168  sll_pure function f_singular_mapping_discrete__jmat(self, eta) result(jmat)
169  class(sll_t_singular_mapping_discrete), intent(in) :: self
170  real(wp), intent(in) :: eta(2)
171  real(wp) :: jmat(2, 2)
172 
173  ! J_11 = d(x1)/d(eta1)
174  ! J_12 = d(x1)/d(eta2)
175  ! J_21 = d(x2)/d(eta1)
176  ! J_22 = d(x2)/d(eta2)
177  jmat(1, 1) = self%spline_2d_x1%eval_deriv_x1(eta(1), eta(2))
178  jmat(1, 2) = self%spline_2d_x1%eval_deriv_x2(eta(1), eta(2))
179  jmat(2, 1) = self%spline_2d_x2%eval_deriv_x1(eta(1), eta(2))
180  jmat(2, 2) = self%spline_2d_x2%eval_deriv_x2(eta(1), eta(2))
181 
182  end function f_singular_mapping_discrete__jmat
183 
184  !-----------------------------------------------------------------------------
185  subroutine s_singular_mapping_discrete__store_data(self, n1, n2, file_id)
186  class(sll_t_singular_mapping_discrete), intent(in) :: self
187  integer, intent(in) :: n1
188  integer, intent(in) :: n2
189  type(sll_t_hdf5_ser_handle), intent(in) :: file_id
190 
191  integer :: i1, i2
192  real(wp) :: eta(2), x(2)
193 
194  real(wp), allocatable :: x1(:, :), x2(:, :), jacobian(:, :)
195 
196  ! For hdf5 I/O
197  integer :: error
198 
199  ! Allocate physical mesh
200  allocate (x1(n1, n2 + 1)) ! repeated point along eta2
201  allocate (x2(n1, n2 + 1)) ! repeated point along eta2
202 
203  ! Allocate Jacobian determinant
204  allocate (jacobian(n1, n2 + 1)) ! repeated point along eta2
205 
206  ! Compute physical mesh and Jacobian determinant
207  do i2 = 1, n2 + 1 ! repeated point along eta2
208  do i1 = 1, n1
209  eta(1) = real(i1 - 1, wp)/real(n1 - 1, wp)
210  eta(2) = real(i2 - 1, wp)*sll_p_twopi/real(n2, wp)
211  x(:) = self%eval(eta)
212  x1(i1, i2) = x(1)
213  x2(i1, i2) = x(2)
214  jacobian(i1, i2) = self%jdet(eta)
215  end do
216  end do
217 
218  ! Store physical mesh
219  call sll_o_hdf5_ser_write_array(file_id, x1, "/x1", error)
220  call sll_o_hdf5_ser_write_array(file_id, x2, "/x2", error)
221 
222  ! Store Jacobian determinant
223  call sll_o_hdf5_ser_write_array(file_id, jacobian, "/jacobian", error)
224 
225  ! Store control points
226  associate(nb1 => self%nbasis_eta1, nb2 => self%nbasis_eta2)
227  call sll_o_hdf5_ser_write_array(file_id, self%spline_2d_x1%bcoef(1:nb1, 1:nb2), "/c_x1", error)
228  call sll_o_hdf5_ser_write_array(file_id, self%spline_2d_x2%bcoef(1:nb1, 1:nb2), "/c_x2", error)
229  end associate
230 
232 
233  !-----------------------------------------------------------------------------
235  class(sll_t_singular_mapping_discrete), intent(inout) :: self
236 
237  deallocate (self%tau_eta1)
238  deallocate (self%tau_eta2)
239  deallocate (self%gtau_x1)
240  deallocate (self%gtau_x2)
241 
242  call self%spline_2d_x1%free()
243  call self%spline_2d_x2%free()
244 
245  call self%spline_interp_eta12%free()
246 
247  end subroutine s_singular_mapping_discrete__free
248 
Write nD array of double precision floats or integers into HDF5 file.
Access point to B-splines of arbitrary degree providing factory function.
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_twopi
Implements the functions to write hdf5 file to store heavy data.
subroutine, public sll_s_hdf5_ser_file_create(filename, handle, error)
Create new HDF5 file.
subroutine, public sll_s_hdf5_ser_file_close(handle, error)
Close existing HDF5 file.
subroutine s_singular_mapping_discrete__init(self, spline_basis_eta1, spline_basis_eta2, mapping_analytic)
integer, parameter wp
Working precision.
subroutine s_singular_mapping_discrete__store_data(self, n1, n2, file_id)
Module for tensor-product 2D splines.
Interpolator for 2D tensor-product splines of arbitrary degree, on uniform and non-uniform grids (dir...
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