26 use,
intrinsic :: iso_c_binding
51 integer,
parameter :: FINUFFT_TYPE2 = 2
52 integer,
parameter :: FINUFFT_IFLAG = -1
61 real(real64),
public :: norm
65 type(c_ptr) :: plan = c_null_ptr
69 real(real64),
pointer :: xj(:) => null()
70 real(real64),
pointer :: yj(:) => null()
71 real(real64),
pointer :: zj(:) => null()
80 type(c_ptr) function oct_finufft_opts_init(nthreads) bind(c, name=
'oct_finufft_opts_init')
81 import :: c_ptr, c_int
82 integer(c_int),
value :: nthreads
83 end function oct_finufft_opts_init
85 subroutine oct_finufft_opts_end(opts) bind(c, name='oct_finufft_opts_end')
87 type(c_ptr),
value :: opts
88 end subroutine oct_finufft_opts_end
90 integer(c_int) function finufft_makeplan(type_, dim, n_modes, iflag, n_transf, tol, plan, opts) &
91 bind(c, name=
'finufft_makeplan')
92 import :: c_int, c_int64_t, c_double, c_ptr
93 integer(c_int),
value :: type_
94 integer(c_int),
value :: dim
95 integer(c_int64_t),
intent(in) :: n_modes(*)
96 integer(c_int),
value :: iflag
97 integer(c_int),
value :: n_transf
98 real(c_double),
value :: tol
99 type(c_ptr),
intent(out) :: plan
100 type(c_ptr),
value :: opts
101 end function finufft_makeplan
103 integer(c_int) function finufft_setpts(plan, M, xj, yj, zj, N, s, t, u) &
104 bind(c, name=
'finufft_setpts')
105 import :: c_int, c_int64_t, c_ptr
106 type(c_ptr),
value :: plan
107 integer(c_int64_t),
value :: M
108 type(c_ptr),
value :: xj, yj, zj
109 integer(c_int64_t),
value :: N
110 type(c_ptr),
value :: s, t, u
111 end function finufft_setpts
113 integer(c_int) function finufft_execute(plan, cj, fk) bind(c, name='finufft_execute')
114 import :: c_int, c_ptr, c_double_complex
115 type(c_ptr),
value :: plan
116 complex(c_double_complex),
intent(inout) :: cj(*)
117 complex(c_double_complex),
intent(in) :: fk(*)
118 end function finufft_execute
120 integer(c_int) function finufft_execute_adjoint(plan, cj, fk) bind(c, name='finufft_execute_adjoint')
121 import :: c_int, c_ptr, c_double_complex
122 type(c_ptr),
value :: plan
123 complex(c_double_complex),
intent(in) :: cj(*)
124 complex(c_double_complex),
intent(inout) :: fk(*)
125 end function finufft_execute_adjoint
127 integer(c_int) function finufft_destroy(plan) bind(c, name='finufft_destroy')
128 import :: c_int, c_ptr
129 type(c_ptr),
value :: plan
130 end function finufft_destroy
140 type(finufft_t),
intent(inout) :: finufft
141 type(namespace_t),
intent(in) :: namespace
153 call parse_variable(namespace,
'FINUFFTTolerance', 1.0e-8_real64, finufft%tol)
155 if (finufft%tol <=
m_zero)
then
163 subroutine finufft_init(finufft, finufft_options, N, dim, M, nthreads)
164 type(
finufft_t),
intent(inout) :: finufft
166 integer,
intent(in) :: n(3)
167 integer,
intent(in) :: dim
168 integer,
intent(in) :: m(3)
169 integer,
intent(in),
optional :: nthreads
172 integer(c_int64_t) :: n_modes(3)
173 integer(c_int) :: ier
174 type(c_ptr) :: finufft_opts
175 integer(c_int) :: n_threads
186 finufft%N(dim+1:3) = 1
187 finufft%M(dim+1:3) = 1
189 finufft%tol = finufft_options%tol
192 n_modes(1:3) = int(finufft%N(1:3), c_int64_t)
197 finufft_opts = oct_finufft_opts_init(n_threads)
198 if (.not. c_associated(finufft_opts))
then
199 message(1) =
"Could not allocate the FINUFFT options."
203 ier = finufft_makeplan(int(finufft_type2, c_int), int(dim, c_int), n_modes, &
204 int(finufft_iflag, c_int), 1_c_int, real(finufft%tol, c_double), finufft%plan, finufft_opts)
205 call finufft_check(ier,
'finufft_makeplan')
207 call oct_finufft_opts_end(finufft_opts)
222 type(
finufft_t),
intent(inout) :: finufft
223 real(real64),
intent(in) :: x1(:)
224 real(real64),
optional,
intent(in) :: x2(:)
225 real(real64),
optional,
intent(in) :: x3(:)
227 real(real64) :: v1(1:finufft%m(1)), v2(1:finufft%m(2)), v3(1:finufft%m(3))
228 real(real64) :: inv_spacing
229 integer(c_int64_t) :: nj
230 integer :: i1, i2, i3, jj
232 integer(c_int) :: ier
233 type(c_ptr) :: yj_ptr, zj_ptr
242 assert(
size(x1) == finufft%M(1))
244 finufft%norm = finufft%norm * inv_spacing
247 if (finufft%dim >= 2)
then
249 assert(
size(x2) == finufft%M(2))
251 finufft%norm = finufft%norm * inv_spacing
255 if (finufft%dim >= 3)
then
257 assert(
size(x3) == finufft%M(3))
259 finufft%norm = finufft%norm * inv_spacing
262 nj = int(finufft%M(1), c_int64_t)*int(finufft%M(2), c_int64_t)*int(finufft%M(3), c_int64_t)
264 safe_deallocate_p(finufft%xj)
265 safe_deallocate_p(finufft%yj)
266 safe_deallocate_p(finufft%zj)
267 safe_allocate(finufft%xj(1:nj))
268 if (finufft%dim >= 2)
then
269 safe_allocate(finufft%yj(1:nj))
271 if (finufft%dim >= 3)
then
272 safe_allocate(finufft%zj(1:nj))
277 do i3 = 1, finufft%M(3)
278 do i2 = 1, finufft%M(2)
279 do i1 = 1, finufft%M(1)
282 if (finufft%dim >= 2) finufft%yj(jj) =
m_two*
m_pi*v2(i2)
283 if (finufft%dim >= 3) finufft%zj(jj) =
m_two*
m_pi*v3(i3)
291 if (finufft%dim >= 2) yj_ptr = c_loc(finufft%yj)
292 if (finufft%dim >= 3) zj_ptr = c_loc(finufft%zj)
295 ier = finufft_setpts(finufft%plan, nj, c_loc(finufft%xj), yj_ptr, zj_ptr, &
296 0_c_int64_t, c_null_ptr, c_null_ptr, c_null_ptr)
297 call finufft_check(ier,
'finufft_setpts')
302 write(
message(1),
'(a)')
"Info: FINUFFT plan precomputed."
312 real(real64),
intent(in) :: X(:)
313 real(real64),
intent(out) :: v(:)
314 real(real64),
intent(out) :: inv_spacing
316 real(real64) :: length, cc
317 real(real64) :: spacing(size(v) - 1)
322 assert(
size(x) ==
size(v))
327 cc = (minval(x) + maxval(x))/
m_two
330 spacing = [(v(i+1) - v(i), i = 1,
size(v)-1)]
331 inv_spacing =
m_one/minval(abs(spacing))
348 do idir = 1, finufft%dim
355 do idir = 1, finufft%dim
372 type(
finufft_t),
intent(inout) :: finufft
375 integer(c_int) :: ier
381 if (c_associated(finufft%plan))
then
382 ier = finufft_destroy(finufft%plan)
383 call finufft_check(ier,
'finufft_destroy')
384 finufft%plan = c_null_ptr
388 safe_deallocate_p(finufft%xj)
389 safe_deallocate_p(finufft%yj)
390 safe_deallocate_p(finufft%zj)
398 subroutine finufft_check(ier, routine)
399 integer(c_int),
intent(in) :: ier
400 character(*),
intent(in) :: routine
404 write(
message(1),
'(3a,i0,a)')
"FINUFFT routine ", trim(routine), &
405 " failed with error code ", ier,
"."
407 end subroutine finufft_check
412#include "finufft_inc.F90"
415#include "complex.F90"
416#include "finufft_inc.F90"
Non-equispaced FFTs through the C interface of the FINUFFT library.
subroutine, public finufft_write_info(finufft)
subroutine, public zfinufft_forward(finufft, in, out)
Evaluate the Fourier modes on the non-equispaced nodes.
subroutine, public zfinufft_backward(finufft, in, out)
Project the non-equispaced nodes back onto the Fourier modes.
subroutine finufft_scale_nodes(X, v, inv_spacing)
Map the nodes onto [-1/2, 1/2) and return the reciprocal of the smallest scaled spacing.
subroutine, public finufft_read_options(finufft, namespace)
subroutine, public finufft_init(finufft, finufft_options, N, dim, M, nthreads)
subroutine, public finufft_end(finufft)
subroutine, public dfinufft_backward(finufft, in, out)
Project the non-equispaced nodes back onto the Fourier modes.
subroutine, public dfinufft_forward(finufft, in, out)
Evaluate the Fourier modes on the non-equispaced nodes.
subroutine, public finufft_precompute(finufft, X1, X2, X3)
Hand the spatial nodes to FINUFFT.
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_one
subroutine, public messages_new_line()
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.