3 #include "sll_assert.h"
4 #include "sll_memory.h"
5 #include "sll_working_precision.h"
16 sll_s_uniform_bsplines_eval_basis
46 sll_comp64,
parameter ::
ii_64 = (0.0_f64, 1.0_f64)
50 sll_int32 :: interpolator
52 sll_real64,
pointer :: eigenvalues_minv(:)
53 sll_comp64,
pointer :: eigenvalues_s(:)
54 sll_real64,
pointer :: wsave(:)
55 sll_comp64,
pointer :: modes(:)
56 sll_comp64,
pointer :: ufft(:)
57 sll_real64,
pointer :: buf(:)
66 sll_int32,
intent(in) :: n
67 sll_int32,
intent(in) :: interpolator
68 sll_int32,
intent(in) :: order
70 sll_int32 :: ierr, i, j
73 sll_real64 :: biatx(order)
76 this%interpolator = interpolator
80 sll_allocate(this%wsave(15 + 4*n), ierr)
81 sll_allocate(this%ufft(n), ierr)
82 sll_allocate(this%eigenvalues_Minv(n), ierr)
83 sll_allocate(this%eigenvalues_S(n), ierr)
84 sll_allocate(this%modes(0:n - 1), ierr)
87 if (iand(order, 1) /= 0)
then
88 print *,
'sll_s_periodic_interp_init: order of interpolators needs to be even.', &
89 'Order here is: ', order
95 call zffti(n, this%wsave)
97 select case (interpolator)
101 this%eigenvalues_Minv = 1.0_f64
105 this%eigenvalues_Minv = 1.0_f64
110 call sll_s_uniform_bsplines_eval_basis(p, 0.0_f64, biatx)
113 this%eigenvalues_Minv(i) = biatx((p + 1)/2)
115 this%eigenvalues_Minv(i) = this%eigenvalues_Minv(i) &
116 + biatx(j + (p + 1)/2)*2*cos(j*
sll_p_twopi*(i - 1)/n)
118 this%eigenvalues_Minv(i) = 1.0_f64/this%eigenvalues_Minv(i)
121 this%sizebuf = 3*n + 15
122 sll_allocate(this%buf(0:this%sizebuf - 1), ierr)
123 call dffti(n, this%buf(n:3*n + 14))
125 this%sizebuf = 2*n + 15
126 sll_allocate(this%buf(1:this%sizebuf), ierr)
127 call dffti(n, this%buf)
130 sll_allocate(this%buf(this%sizebuf), ierr)
135 sll_deallocate_array(this%buf, ierr)
137 print *,
'sll_m_periodic_interp:interpolator ', interpolator,
' not implemented'
148 sll_deallocate(this%wsave, ierr)
149 sll_deallocate(this%ufft, ierr)
150 sll_deallocate(this%eigenvalues_Minv, ierr)
151 sll_deallocate(this%eigenvalues_S, ierr)
152 sll_deallocate(this%modes, ierr)
153 if (
associated(this%buf))
then
154 sll_deallocate(this%buf, ierr)
163 sll_real64,
intent(out) :: u_out(:)
164 sll_real64,
intent(in) :: u(:)
165 sll_real64,
intent(in) :: alpha
167 sll_int32 :: i, j, k, p, ishift
168 sll_int32 :: imode, n
171 sll_comp64 :: tmp, tmp2
172 sll_real64 :: biatx(this%order)
174 sll_assert(
size(u_out) >= this%N)
175 sll_assert(
size(u) >= this%N)
178 select case (this%interpolator)
182 this%ufft(i) = cmplx(u(i), kind=f64)
184 call zfftf(this%N, this%ufft, this%wsave)
185 this%eigenvalues_S(1) = (1.0_f64, 0.0_f64)
186 this%eigenvalues_S(this%N/2 + 1) = exp(-
ii_64*
sll_p_pi*alpha)
187 do k = 1, this%N/2 - 1
191 filter = (1.0_f64, 0.0_f64)
194 this%eigenvalues_S(this%N - k + 1) = exp(
ii_64*
sll_p_twopi*k*alpha/this%N)*filter
196 this%ufft = this%ufft*this%eigenvalues_S
198 call zfftb(this%N, this%ufft, this%wsave)
200 u_out(i) = real(this%ufft(i), f64)/real(this%N, f64)
205 this%ufft(i) = cmplx(u(i), kind=f64)
207 call zfftf(this%N, this%ufft, this%wsave)
211 ishift = floor(-alpha)
212 beta = -ishift - alpha
213 call sll_s_uniform_bsplines_eval_basis(p, beta, biatx)
215 this%eigenvalues_S = (0.0_f64, 0.0_f64)
217 do j = -(p - 1)/2, (p + 1)/2
218 imode = modulo((ishift + j)*(i - 1), this%N)
219 this%eigenvalues_S(i) = this%eigenvalues_S(i) &
220 + biatx(j + (p + 1)/2)*this%modes(imode)
224 this%ufft = this%ufft*this%eigenvalues_S*this%eigenvalues_Minv
226 call zfftb(this%N, this%ufft, this%wsave)
228 u_out(i) = real(this%ufft(i), f64)/real(this%N, f64)
233 alpha/this%N, this%order/2 - 1)
239 call fourier1dper(this%buf, this%sizebuf, u_out, this%N, alpha/this%N)
248 tmp = cmplx(u_out(2*i + 1), u_out(2*i + 2), kind=f64)
249 tmp = tmp*exp(tmp2*cmplx(i, 0.0_f64, f64))
250 u_out(2*i + 1) = real(tmp, kind=f64)
251 u_out(2*i + 2) = aimag(tmp)
253 tmp = cmplx(u_out(n/2 + 1), 0.0_f64, kind=f64)
254 tmp = tmp*exp(tmp2*cmplx(0.5_f64*n, 0.0_f64, f64))
255 u_out(n/2 + 1) = real(tmp, kind=f64)
272 print *,
'sll_m_periodic_interp:interpolator ', this%interpolator,
' not implemented'
291 sll_int32,
intent(in) :: n, sizebuf, d
292 sll_real64,
intent(inout) :: buf(0:sizebuf - 1)
293 sll_real64,
intent(inout) :: e(1:n)
294 sll_real64,
intent(in) :: alpha
297 sll_real64 :: rea, ima, reb, imb, tmp, x, a
312 x = x - real(floor(x), f64)
321 x = x - real(ix, f64)
328 a = a*(x*x - real(i, f64)*real(i, f64))/(real(d, f64)*real(d, f64))
330 a = a*(x + 1._f64)/real(d, f64)
331 a = a*(x - real(d, f64) - 1._f64)/real(d, f64)
332 buf(ix) = a*(x - 1._f64)/real(d, f64)
333 buf(mod(ix + 1, n)) = a*x/real(d, f64)
334 a = a*x*(x - 1._f64)/(real(d, f64)*real(d, f64))
336 buf(mod(i + ix + n, n)) = a/((x - real(i, f64))/real(d, f64))
339 buf(mod(i + ix + n, n)) = a/((x - real(i, f64))/real(d, f64));
343 buf(mod(i + ix + n, n)) = buf(mod(i + ix + n, n))*a
344 a = a*real(d, f64)/real(d + i + 1, f64)
348 buf(mod(i + ix + n, n)) = buf(mod(i + ix + n, n))*a
349 a = a*real(d, f64)/real(i - 1 - d - 1, f64)
352 call dfftf(n, buf(0:n - 1), buf(n:3*n + 14))
354 call dfftf(n, e, buf(n:3*n + 14))
355 tmp = 1._f64/real(n, f64)
356 e(1) = e(1)*tmp*buf(0)
358 rea = e(2*i); ima = e(2*i + 1)
359 reb = tmp*buf(2*i - 1)
361 e(2*i) = rea*reb - ima*imb
362 e(2*i + 1) = rea*imb + reb*ima
364 if (mod(n, 2) == 0) e(n) = e(n)*tmp*buf(n - 1)
365 call dfftb(n, e, buf(n:3*n + 14))
369 sll_int32,
intent(in) :: n, ncoef
370 sll_real64,
intent(in) :: coefd(1:ncoef)
371 sll_real64,
intent(inout) :: e(1:n)
372 sll_real64,
intent(in) :: alpha
376 sll_real64 :: rea, ima, reb, imb, tmp, x
381 x = x - real(floor(x), f64)
387 call dfftf(n, e, coefd)
390 tmp = 1._f64/real(n, f64)
395 rea = e(2*i); ima = e(2*i + 1)
396 reb = tmp*cos(real(i, f64)*x)
397 imb = tmp*sin(real(i, f64)*x)
398 e(2*i) = rea*reb - ima*imb
399 e(2*i + 1) = rea*imb + reb*ima
401 if (mod(n, 2) == 0) e(n) = e(n)*tmp*cos(0.5_f64*real(n, f64)*x)
402 call dfftb(n, e, coefd)
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
real(kind=f64), parameter, public sll_p_twopi
integer, parameter, public sll_p_fft_forward
Flag to specify forward FFT (negative sign) [value -1].
subroutine, public sll_s_fft_init_r2r_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
Create new 1d real to real plan.
integer, parameter, public sll_p_fft_backward
Flag to specify backward FFT (positive sign) [value 1].
subroutine, public sll_s_fft_exec_r2r_1d(plan, array_in, array_out)
Compute fast Fourier transform in real to real mode.
Low level arbitrary degree splines.
integer(kind=i32), parameter, public sll_p_trigo_fft_selalib
subroutine fourier1dperlagodd(buf, sizebuf, E, N, alpha, d)
complex(kind=f64), parameter ii_64
subroutine fourier1dper(coefd, Ncoef, E, N, alpha)
subroutine, public sll_s_periodic_interp_free(this)
integer(kind=i32), parameter, public sll_p_spline
integer(kind=i32), parameter, public sll_p_lagrange
subroutine, public sll_s_periodic_interp_init(this, N, interpolator, order)
integer(kind=i32), parameter trigo_real
integer(kind=i32), parameter, public sll_p_trigo
subroutine, public sll_s_periodic_interp(this, u_out, u, alpha)
Type for FFT plan in SeLaLib.