Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_nufft_interpolation.F90
Go to the documentation of this file.
2 #include "sll_working_precision.h"
3 #include "sll_memory.h"
4 #include "sll_assert.h"
5  use sll_m_fft
7 
8  implicit none
9 
14  private
15  type(sll_t_fft) :: fft
16  sll_comp64, allocatable :: f1d(:)
17  sll_comp64, allocatable :: f1(:)
18  sll_comp64, allocatable :: f2(:)
19  sll_comp64, allocatable :: fcmplx(:, :)
20  sll_int32, allocatable :: i(:)
21  sll_int32, allocatable :: j(:)
22  sll_real64, allocatable :: x(:)
23  sll_real64, allocatable :: y(:)
24  sll_real64 :: epsnufft = 1.0d-9
25  sll_int32 :: nc_eta1
26  sll_int32 :: nc_eta2
27  sll_real64 :: eta1_min, eta1_max
28  sll_real64 :: eta2_min, eta2_max
29 
30  end type sll_t_nufft_2d
31 
32 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33 contains
34 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 
37  subroutine sll_s_nufft_2d_init(self, &
38  nc_eta1, eta1_min, eta1_max, &
39  nc_eta2, eta2_min, eta2_max)
40 
41  type(sll_t_nufft_2d) :: self
42  sll_int32, intent(in) :: nc_eta1
43  sll_int32, intent(in) :: nc_eta2
44  sll_real64, intent(in) :: eta1_min
45  sll_real64, intent(in) :: eta1_max
46  sll_real64, intent(in) :: eta2_min
47  sll_real64, intent(in) :: eta2_max
48  sll_int32 :: err
49 
50  self%nc_eta1 = nc_eta1
51  self%nc_eta2 = nc_eta2
52 
53  self%eta1_min = eta1_min
54  self%eta2_min = eta2_min
55  self%eta1_max = eta1_max
56  self%eta2_max = eta2_max
57 
58  sll_allocate(self%x(1:nc_eta1*nc_eta2), err)
59  sll_allocate(self%y(1:nc_eta1*nc_eta2), err)
60  sll_allocate(self%i(1:nc_eta1*nc_eta2), err)
61  sll_allocate(self%j(1:nc_eta1*nc_eta2), err)
62  sll_allocate(self%fcmplx(1:nc_eta1, 1:nc_eta2), err)
63  sll_allocate(self%f1(1:nc_eta1), err)
64  sll_allocate(self%f2(1:nc_eta2), err)
65  sll_allocate(self%f1d(1:nc_eta1*nc_eta2), err)
66 
67 !$OMP CRITICAL
68  call sll_s_fft_init_c2c_2d(self%fft, nc_eta1, nc_eta2, &
69  self%fcmplx, self%fcmplx, sll_p_fft_forward)
70 !$OMP END CRITICAL
71 
72  end subroutine sll_s_nufft_2d_init
73 
74 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
76  subroutine sll_s_nufft_2d_free(self)
77 
78  type(sll_t_nufft_2d) :: self
79 
80  DEALLOCATE (self%f1d)
81  DEALLOCATE (self%x)
82  DEALLOCATE (self%y)
83  DEALLOCATE (self%j)
84  DEALLOCATE (self%i)
85  DEALLOCATE (self%fcmplx)
86  DEALLOCATE (self%f1)
87  DEALLOCATE (self%f2)
88 
89  end subroutine sll_s_nufft_2d_free
90 
91 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
93  subroutine sll_s_nufft_2d_compute_fft(self, f_in)
94 
95  type(sll_t_nufft_2d) :: self
96  sll_real64, intent(in) :: f_in(:, :)
97 
98  sll_int32 :: i, j, m, n1, n2, p
99 
100  n1 = self%nc_eta1
101  n2 = self%nc_eta2
102 
103  self%fcmplx = cmplx(f_in(1:n1, 1:n2), 0., f64)
104  call sll_s_fft_exec_c2c_2d(self%fft, self%fcmplx, self%fcmplx)
105  self%fcmplx = self%fcmplx/cmplx(n1*n2, 0., f64)
106 
107  m = n2/2
108  do i = 1, n1
109  self%f2 = self%fcmplx(i, :)
110  self%fcmplx(i, :) = self%f2([[(p, p=m + 1, n2)], [(p, p=1, m)]])
111  end do
112  m = n1/2
113  do j = 1, n2
114  self%f1 = self%fcmplx(:, j)
115  self%fcmplx(:, j) = self%f1([[(p, p=m + 1, n1)], [(p, p=1, m)]])
116  end do
117 
118  end subroutine sll_s_nufft_2d_compute_fft
119 
120 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
122  function sll_f_nufft_2d_interpolate_value_from_fft(self, x, y) result(f_out)
123 
124  type(sll_t_nufft_2d) :: self
125  sll_real64, intent(in) :: x
126  sll_real64, intent(in) :: y
127  sll_real64 :: f_out
128  sll_int32 :: error
129  sll_real64 :: xij, yij
130 
131  xij = (x - self%eta1_min)/(self%eta1_max - self%eta1_min)
132  yij = (y - self%eta2_min)/(self%eta2_max - self%eta2_min)
133 
134  if (0.0_f64 < xij .and. xij < 1.0_f64 .and. &
135  0.0_f64 < yij .and. yij < 1.0_f64) then
136 
137  self%i(1) = 1
138  self%j(1) = 1
139  self%x(1) = xij*2.0*sll_p_pi
140  self%y(1) = yij*2.0*sll_p_pi
141 
142  call nufft2d2f90(1, &
143  self%x, &
144  self%y, &
145  self%f1d, &
146  1, &
147  self%epsnufft, &
148  1, &
149  1, &
150  self%fcmplx, &
151  error)
152 
153  f_out = real(self%f1d(1))
154 
155  else
156 
157  f_out = 0.0_f64
158 
159  end if
160 
162 
163 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
165  subroutine sll_s_nufft_2d_interpolate_array_values(self, f_in, x, y, f_out)
166 
167  type(sll_t_nufft_2d) :: self
168  sll_real64, intent(in) :: f_in(:, :)
169  sll_real64, intent(in) :: x(:, :)
170  sll_real64, intent(in) :: y(:, :)
171  sll_real64, intent(out) :: f_out(:, :)
172 
173  call sll_s_nufft_2d_compute_fft(self, f_in)
174  f_out = f_in
175  call sll_s_nufft_2d_interpolate_array_from_fft(self, x, y, f_out)
176 
178 
179 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
183 
184  type(sll_t_nufft_2d) :: self
185  sll_real64, intent(inout) :: f(:, :)
186  sll_real64, intent(in) :: x(:, :)
187  sll_real64, intent(in) :: y(:, :)
188  sll_int32 :: i, j, k, error
189  sll_int32 :: n1, n2, p
190  sll_real64 :: xij, yij
191 
192  n1 = self%nc_eta1
193  n2 = self%nc_eta2
194 
195  call sll_s_nufft_2d_compute_fft(self, f)
196 
197  p = 0
198  do j = 1, n2
199  do i = 1, n1
200  xij = (x(i, j) - self%eta1_min)/(self%eta1_max - self%eta1_min)
201  yij = (y(i, j) - self%eta2_min)/(self%eta2_max - self%eta2_min)
202  if (0.0_f64 < xij .and. xij < 1.0_f64 .and. &
203  0.0_f64 < yij .and. yij < 1.0_f64) then
204  p = p + 1
205  self%i(p) = i
206  self%j(p) = j
207  self%x(p) = xij*2.0*sll_p_pi
208  self%y(p) = yij*2.0*sll_p_pi
209  else
210  f(i, j) = 0.0_f64
211  end if
212  end do
213  end do
214 
215  call nufft2d2f90(p, &
216  self%x(1:p), &
217  self%y(1:p), &
218  self%f1d(1:p), &
219  1, &
220  self%epsnufft, &
221  n1, &
222  n2, &
223  self%fcmplx, &
224  error)
225 
226  do k = 1, p
227  f(self%i(k), self%j(k)) = real(self%f1d(k))
228  end do
229 
231 
232 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
236 
237  type(sll_t_nufft_2d) :: self
238  sll_real64, intent(in) :: x(:, :)
239  sll_real64, intent(in) :: y(:, :)
240  sll_real64, intent(out) :: f(:, :)
241  sll_int32 :: n1, n2
242  sll_int32 :: i, j
243  sll_int32 :: error
244 
245  n1 = self%nc_eta1
246  n2 = self%nc_eta2
247 
248  sll_assert(size(f, 1) == n1 .and. size(f, 2) == n2)
249  sll_assert(size(x, 1) == n1 .and. size(x, 2) == n2)
250  sll_assert(size(y, 1) == n1 .and. size(y, 2) == n2)
251 
252  do j = 1, n2
253  do i = 1, n1
254  self%x((j - 1)*n1 + i) = (-self%eta1_min + x(i, j))*2.0*sll_p_pi/(self%eta1_max - self%eta1_min)
255  self%y((j - 1)*n1 + i) = (-self%eta2_min + y(i, j))*2.0*sll_p_pi/(self%eta2_max - self%eta2_min)
256  end do
257  end do
258 
259  call nufft2d2f90(n1*n2, &
260  self%x, &
261  self%y, &
262  self%f1d, &
263  1, &
264  self%epsnufft, &
265  n1, &
266  n2, &
267  self%fcmplx, &
268  error)
269  do j = 1, n2
270  do i = 1, n1
271  f(i, j) = real(self%f1d((j - 1)*n1 + i))
272  end do
273  end do
274 
276 
277 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
278 end module sll_m_nufft_interpolation
279 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
FFT interface for FFTW.
subroutine, public sll_s_fft_init_c2c_2d(plan, nx, ny, array_in, array_out, direction, normalized, aligned, optimization)
Create new 2d complex to complex plan.
subroutine, public sll_s_fft_exec_c2c_2d(plan, array_in, array_out)
Compute fast Fourier transform in complex to complex mode.
integer, parameter, public sll_p_fft_forward
Flag to specify forward FFT (negative sign) [value -1].
subroutine sll_s_nufft_2d_compute_fft(self, f_in)
Compute the fft and prepare data for nufft call.
subroutine sll_s_nufft_2d_interpolate_array_values(self, f_in, x, y, f_out)
Compute the fft and interpolate array values.
subroutine sll_s_nufft_2d_interpolate_array_values_axi(self, f, x, y)
Compute the fft and interpolate array values when x and y could be outside the domaine....
subroutine sll_s_nufft_2d_free(self)
Delete the nufft object.
real(kind=f64) function sll_f_nufft_2d_interpolate_value_from_fft(self, x, y)
Interpolate single value when the fft is already compute.
subroutine sll_s_nufft_2d_init(self, nc_eta1, eta1_min, eta1_max, nc_eta2, eta2_min, eta2_max)
Allocate and initialize data and prepare the fft plan.
subroutine sll_s_nufft_2d_interpolate_array_from_fft(self, x, y, f)
Compute the fft and interpolate array values when x and y are surely inside the domain....
Nufft object for 2d interpolation. It contains fft plan and 1d array to pass data to nufft2d subrouti...
Type for FFT plan in SeLaLib.
    Report Typos and Errors