26 use,
intrinsic :: iso_c_binding
55 integer,
parameter :: FINUFFT_TYPE2 = 2
56 integer,
parameter :: FINUFFT_IFLAG = -1
65 real(real64),
public :: norm
69 type(c_ptr) :: plan = c_null_ptr
73 real(real64),
pointer :: xj(:) => null()
74 real(real64),
pointer :: yj(:) => null()
75 real(real64),
pointer :: zj(:) => null()
84 type(c_ptr) function oct_finufft_opts_init(nthreads) bind(c, name=
'oct_finufft_opts_init')
85 import :: c_ptr, c_int
86 integer(c_int),
value :: nthreads
87 end function oct_finufft_opts_init
89 subroutine oct_finufft_opts_end(opts) bind(c, name='oct_finufft_opts_end')
91 type(c_ptr),
value :: opts
92 end subroutine oct_finufft_opts_end
94 integer(c_int) function finufft_makeplan(type_, dim, n_modes, iflag, n_transf, tol, plan, opts) &
95 bind(c, name=
'finufft_makeplan')
96 import :: c_int, c_int64_t, c_double, c_ptr
97 integer(c_int),
value :: type_
98 integer(c_int),
value :: dim
99 integer(c_int64_t),
intent(in) :: n_modes(*)
100 integer(c_int),
value :: iflag
101 integer(c_int),
value :: n_transf
102 real(c_double),
value :: tol
103 type(c_ptr),
intent(out) :: plan
104 type(c_ptr),
value :: opts
105 end function finufft_makeplan
107 integer(c_int) function finufft_setpts(plan, M, xj, yj, zj, N, s, t, u) &
108 bind(c, name=
'finufft_setpts')
109 import :: c_int, c_int64_t, c_ptr
110 type(c_ptr),
value :: plan
111 integer(c_int64_t),
value :: M
112 type(c_ptr),
value :: xj, yj, zj
113 integer(c_int64_t),
value :: N
114 type(c_ptr),
value :: s, t, u
115 end function finufft_setpts
117 integer(c_int) function finufft_execute(plan, cj, fk) bind(c, name='finufft_execute')
118 import :: c_int, c_ptr, c_double_complex
119 type(c_ptr),
value :: plan
120 complex(c_double_complex),
intent(inout) :: cj(*)
121 complex(c_double_complex),
intent(in) :: fk(*)
122 end function finufft_execute
124 integer(c_int) function finufft_execute_adjoint(plan, cj, fk) bind(c, name='finufft_execute_adjoint')
125 import :: c_int, c_ptr, c_double_complex
126 type(c_ptr),
value :: plan
127 complex(c_double_complex),
intent(in) :: cj(*)
128 complex(c_double_complex),
intent(inout) :: fk(*)
129 end function finufft_execute_adjoint
131 integer(c_int) function finufft_destroy(plan) bind(c, name='finufft_destroy')
132 import :: c_int, c_ptr
133 type(c_ptr),
value :: plan
134 end function finufft_destroy
144 type(finufft_t),
intent(inout) :: finufft
145 type(namespace_t),
intent(in) :: namespace
157 call parse_variable(namespace,
'FINUFFTTolerance', 1.0e-8_real64, finufft%tol)
159 if (finufft%tol <=
m_zero)
then
170 type(
finufft_t),
intent(inout) :: finufft
171 real(real64),
intent(in) :: tol
181 subroutine finufft_init(finufft, finufft_options, N, dim, M, nthreads)
182 type(
finufft_t),
intent(inout) :: finufft
183 type(
finufft_t),
intent(in) :: finufft_options
184 integer,
intent(in) :: n(3)
185 integer,
intent(in) :: dim
186 integer,
intent(in) :: m(3)
187 integer,
intent(in),
optional :: nthreads
190 integer(c_int64_t) :: n_modes(3)
191 integer(c_int) :: ier
192 type(c_ptr) :: finufft_opts
193 integer(c_int) :: n_threads
204 finufft%N(dim+1:3) = 1
205 finufft%M(dim+1:3) = 1
207 finufft%tol = finufft_options%tol
210 n_modes(1:3) = int(finufft%N(1:3), c_int64_t)
215 finufft_opts = oct_finufft_opts_init(n_threads)
216 if (.not. c_associated(finufft_opts))
then
217 message(1) =
"Could not allocate the FINUFFT options."
221 ier = finufft_makeplan(int(finufft_type2, c_int), int(dim, c_int), n_modes, &
222 int(finufft_iflag, c_int), 1_c_int, real(finufft%tol, c_double), finufft%plan, finufft_opts)
223 call finufft_check(ier,
'finufft_makeplan')
225 call oct_finufft_opts_end(finufft_opts)
240 type(
finufft_t),
intent(inout) :: finufft
241 real(real64),
contiguous,
intent(in) :: x1(:)
242 real(real64),
contiguous,
optional,
intent(in) :: x2(:)
243 real(real64),
contiguous,
optional,
intent(in) :: x3(:)
245 real(real64),
optional,
intent(in) :: period(:)
247 real(real64) :: v1(1:finufft%m(1)), v2(1:finufft%m(2)), v3(1:finufft%m(3))
248 real(real64) :: inv_spacing, period_(3)
249 integer(c_int64_t) :: nj
250 integer :: i1, i2, i3, jj
252 integer(c_int) :: ier
253 type(c_ptr) :: yj_ptr, zj_ptr
263 if (
present(period)) period_(1:3) = period(1:3)
265 assert(
size(x1) == finufft%M(1))
267 finufft%norm = finufft%norm * inv_spacing
270 if (finufft%dim >= 2)
then
272 assert(
size(x2) == finufft%M(2))
274 finufft%norm = finufft%norm * inv_spacing
278 if (finufft%dim >= 3)
then
280 assert(
size(x3) == finufft%M(3))
282 finufft%norm = finufft%norm * inv_spacing
285 nj = int(finufft%M(1), c_int64_t)*int(finufft%M(2), c_int64_t)*int(finufft%M(3), c_int64_t)
287 safe_deallocate_p(finufft%xj)
288 safe_deallocate_p(finufft%yj)
289 safe_deallocate_p(finufft%zj)
290 safe_allocate(finufft%xj(1:nj))
291 if (finufft%dim >= 2)
then
292 safe_allocate(finufft%yj(1:nj))
294 if (finufft%dim >= 3)
then
295 safe_allocate(finufft%zj(1:nj))
300 do i3 = 1, finufft%M(3)
301 do i2 = 1, finufft%M(2)
302 do i1 = 1, finufft%M(1)
305 if (finufft%dim >= 2) finufft%yj(jj) =
m_two*
m_pi*v2(i2)
306 if (finufft%dim >= 3) finufft%zj(jj) =
m_two*
m_pi*v3(i3)
314 if (finufft%dim >= 2) yj_ptr = c_loc(finufft%yj)
315 if (finufft%dim >= 3) zj_ptr = c_loc(finufft%zj)
318 ier = finufft_setpts(finufft%plan, nj, c_loc(finufft%xj), yj_ptr, zj_ptr, &
319 0_c_int64_t, c_null_ptr, c_null_ptr, c_null_ptr)
320 call finufft_check(ier,
'finufft_setpts')
325 write(
message(1),
'(a)')
"Info: FINUFFT plan precomputed."
336 type(
finufft_t),
intent(inout) :: finufft
337 real(real64),
contiguous,
intent(in) :: xj(:)
338 real(real64),
contiguous,
intent(in) :: yj(:)
339 real(real64),
contiguous,
intent(in) :: zj(:)
340 real(real64),
contiguous,
intent(in) :: period(:)
342 integer(c_int64_t) :: nj
344 integer(c_int) :: ier
351 assert(finufft%dim == 3)
353 nj = int(finufft%M(1), c_int64_t)
354 assert(
size(xj) == nj)
355 assert(
size(yj) == nj)
356 assert(
size(zj) == nj)
360 safe_deallocate_p(finufft%xj)
361 safe_deallocate_p(finufft%yj)
362 safe_deallocate_p(finufft%zj)
363 safe_allocate(finufft%xj(1:nj))
364 safe_allocate(finufft%yj(1:nj))
365 safe_allocate(finufft%zj(1:nj))
372 ier = finufft_setpts(finufft%plan, nj, c_loc(finufft%xj), c_loc(finufft%yj), c_loc(finufft%zj), &
373 0_c_int64_t, c_null_ptr, c_null_ptr, c_null_ptr)
374 call finufft_check(ier,
'finufft_setpts')
386 complex(real64),
contiguous,
intent(in) :: modes(:,:,:)
387 complex(real64),
contiguous,
intent(out) :: values(:)
390 integer(c_int) :: ier
398 ier = finufft_execute(finufft%plan, values, modes)
399 call finufft_check(ier,
'finufft_execute')
413 complex(real64),
contiguous,
intent(in) :: values(:)
414 complex(real64),
contiguous,
intent(out) :: modes(:,:,:)
417 integer(c_int) :: ier
425 ier = finufft_execute_adjoint(finufft%plan, values, modes)
426 call finufft_check(ier,
'finufft_execute_adjoint')
442 real(real64),
contiguous,
intent(in) :: X(:)
443 real(real64),
contiguous,
intent(out) :: v(:)
444 real(real64),
intent(out) :: inv_spacing
445 real(real64),
intent(in) :: period
447 real(real64) :: length, cc
448 real(real64) :: spacing(size(v) - 1)
453 assert(
size(x) ==
size(v))
458 inv_spacing = real(
size(v), real64)
462 cc = (minval(x) + maxval(x))/
m_two
465 spacing = [(v(i+1) - v(i), i = 1,
size(v)-1)]
466 inv_spacing =
m_one/minval(abs(spacing))
484 do idir = 1, finufft%dim
491 do idir = 1, finufft%dim
508 type(
finufft_t),
intent(inout) :: finufft
511 integer(c_int) :: ier
517 if (c_associated(finufft%plan))
then
518 ier = finufft_destroy(finufft%plan)
519 call finufft_check(ier,
'finufft_destroy')
520 finufft%plan = c_null_ptr
524 safe_deallocate_p(finufft%xj)
525 safe_deallocate_p(finufft%yj)
526 safe_deallocate_p(finufft%zj)
534 subroutine finufft_check(ier, routine)
535 integer(c_int),
intent(in) :: ier
536 character(*),
intent(in) :: routine
540 write(
message(1),
'(3a,i0,a)')
"FINUFFT routine ", trim(routine), &
541 " failed with error code ", ier,
"."
543 end subroutine finufft_check
548#include "finufft_inc.F90"
551#include "complex.F90"
552#include "finufft_inc.F90"
Non-equispaced FFTs through the C interface of the FINUFFT library.
subroutine, public finufft_write_info(finufft)
subroutine, public finufft_set_nodes(finufft, xj, yj, zj, period)
Hand scattered nodes to FINUFFT, mapping one period of the mode grid onto the [-1/2,...
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, public finufft_precompute(finufft, X1, X2, X3, period)
Hand the spatial nodes to FINUFFT.
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 finufft_nodes_to_modes(finufft, values, modes)
Project the scattered nodes onto the Fourier modes.
subroutine, public finufft_modes_to_nodes(finufft, modes, values)
Evaluate the Fourier modes on the scattered nodes.
subroutine finufft_scale_nodes(X, v, inv_spacing, period)
Map the nodes onto [-1/2, 1/2) and return the reciprocal of the smallest scaled spacing....
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_set_tolerance(finufft, tol)
Set the requested tolerance directly, for callers that take it from an input variable of their own ra...
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
complex(real64), parameter, public m_z0
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.