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()
79 integer(c_int) function finufft_makeplan(type_, dim, n_modes, iflag, n_transf, tol, plan, opts) &
80 bind(c, name=
'finufft_makeplan')
81 import :: c_int, c_int64_t, c_double, c_ptr
82 integer(c_int),
value :: type_
83 integer(c_int),
value :: dim
84 integer(c_int64_t),
intent(in) :: n_modes(*)
85 integer(c_int),
value :: iflag
86 integer(c_int),
value :: n_transf
87 real(c_double),
value :: tol
88 type(c_ptr),
intent(out) :: plan
89 type(c_ptr),
value :: opts
90 end function finufft_makeplan
92 integer(c_int) function finufft_setpts(plan, M, xj, yj, zj, N, s, t, u) &
93 bind(c, name=
'finufft_setpts')
94 import :: c_int, c_int64_t, c_ptr
95 type(c_ptr),
value :: plan
96 integer(c_int64_t),
value :: M
97 type(c_ptr),
value :: xj, yj, zj
98 integer(c_int64_t),
value :: N
99 type(c_ptr),
value :: s, t, u
100 end function finufft_setpts
102 integer(c_int) function finufft_execute(plan, cj, fk) bind(c, name='finufft_execute')
103 import :: c_int, c_ptr, c_double_complex
104 type(c_ptr),
value :: plan
105 complex(c_double_complex),
intent(inout) :: cj(*)
106 complex(c_double_complex),
intent(in) :: fk(*)
107 end function finufft_execute
109 integer(c_int) function finufft_execute_adjoint(plan, cj, fk) bind(c, name='finufft_execute_adjoint')
110 import :: c_int, c_ptr, c_double_complex
111 type(c_ptr),
value :: plan
112 complex(c_double_complex),
intent(in) :: cj(*)
113 complex(c_double_complex),
intent(inout) :: fk(*)
114 end function finufft_execute_adjoint
116 integer(c_int) function finufft_destroy(plan) bind(c, name='finufft_destroy')
117 import :: c_int, c_ptr
118 type(c_ptr),
value :: plan
119 end function finufft_destroy
129 type(finufft_t),
intent(inout) :: finufft
130 type(namespace_t),
intent(in) :: namespace
144 if (finufft%tol <=
m_zero)
then
153 type(
finufft_t),
intent(inout) :: finufft
154 type(
finufft_t),
intent(in) :: finufft_options
155 integer,
intent(in) :: n(3)
156 integer,
intent(in) :: dim
157 integer,
intent(in) :: m(3)
160 integer(c_int64_t) :: n_modes(3)
161 integer(c_int) :: ier
162 type(c_ptr) :: default_opts
173 finufft%N(dim+1:3) = 1
174 finufft%M(dim+1:3) = 1
176 finufft%tol = finufft_options%tol
179 n_modes(1:3) = int(finufft%N(1:3), c_int64_t)
183 default_opts = c_null_ptr
185 ier = finufft_makeplan(int(finufft_type2, c_int), int(dim, c_int), n_modes, &
186 int(finufft_iflag, c_int), 1_c_int, real(finufft%tol, c_double), finufft%plan, default_opts)
187 call finufft_check(ier,
'finufft_makeplan')
202 type(
finufft_t),
intent(inout) :: finufft
203 real(real64),
intent(in) :: x1(:)
204 real(real64),
optional,
intent(in) :: x2(:)
205 real(real64),
optional,
intent(in) :: x3(:)
207 real(real64) :: v1(1:finufft%m(1)), v2(1:finufft%m(2)), v3(1:finufft%m(3))
208 real(real64) :: inv_spacing
209 integer(c_int64_t) :: nj
210 integer :: i1, i2, i3, jj
212 integer(c_int) :: ier
213 type(c_ptr) :: yj_ptr, zj_ptr
222 assert(
size(x1) == finufft%M(1))
224 finufft%norm = finufft%norm * inv_spacing
227 if (finufft%dim >= 2)
then
229 assert(
size(x2) == finufft%M(2))
231 finufft%norm = finufft%norm * inv_spacing
235 if (finufft%dim >= 3)
then
237 assert(
size(x3) == finufft%M(3))
239 finufft%norm = finufft%norm * inv_spacing
242 nj = int(finufft%M(1), c_int64_t)*int(finufft%M(2), c_int64_t)*int(finufft%M(3), c_int64_t)
244 safe_deallocate_p(finufft%xj)
245 safe_deallocate_p(finufft%yj)
246 safe_deallocate_p(finufft%zj)
247 safe_allocate(finufft%xj(1:nj))
248 if (finufft%dim >= 2)
then
249 safe_allocate(finufft%yj(1:nj))
251 if (finufft%dim >= 3)
then
252 safe_allocate(finufft%zj(1:nj))
257 do i3 = 1, finufft%M(3)
258 do i2 = 1, finufft%M(2)
259 do i1 = 1, finufft%M(1)
262 if (finufft%dim >= 2) finufft%yj(jj) =
m_two*
m_pi*v2(i2)
263 if (finufft%dim >= 3) finufft%zj(jj) =
m_two*
m_pi*v3(i3)
271 if (finufft%dim >= 2) yj_ptr = c_loc(finufft%yj)
272 if (finufft%dim >= 3) zj_ptr = c_loc(finufft%zj)
275 ier = finufft_setpts(finufft%plan, nj, c_loc(finufft%xj), yj_ptr, zj_ptr, &
276 0_c_int64_t, c_null_ptr, c_null_ptr, c_null_ptr)
277 call finufft_check(ier,
'finufft_setpts')
282 write(
message(1),
'(a)')
"Info: FINUFFT plan precomputed."
292 real(real64),
intent(in) :: x(:)
293 real(real64),
intent(out) :: v(:)
294 real(real64),
intent(out) :: inv_spacing
296 real(real64) :: length, cc
297 real(real64) :: spacing(size(v) - 1)
302 assert(
size(x) ==
size(v))
307 cc = (minval(x) + maxval(x))/
m_two
310 spacing = [(v(i+1) - v(i), i = 1,
size(v)-1)]
311 inv_spacing =
m_one/minval(abs(spacing))
328 do idir = 1, finufft%dim
335 do idir = 1, finufft%dim
352 type(
finufft_t),
intent(inout) :: finufft
355 integer(c_int) :: ier
361 if (c_associated(finufft%plan))
then
362 ier = finufft_destroy(finufft%plan)
363 call finufft_check(ier,
'finufft_destroy')
364 finufft%plan = c_null_ptr
368 safe_deallocate_p(finufft%xj)
369 safe_deallocate_p(finufft%yj)
370 safe_deallocate_p(finufft%zj)
378 subroutine finufft_check(ier, routine)
379 integer(c_int),
intent(in) :: ier
380 character(*),
intent(in) :: routine
384 write(
message(1),
'(3a,i0,a)')
"FINUFFT routine ", trim(routine), &
385 " failed with error code ", ier,
"."
387 end subroutine finufft_check
392#include "finufft_inc.F90"
395#include "complex.F90"
396#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_init(finufft, finufft_options, N, dim, M)
subroutine, public finufft_read_options(finufft, namespace)
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.