97 SUBROUTINE multi_fft(time_series, value_series, result_series, omega_series, &
98 damping_opt, t0_opt, subtract_initial_opt)
99 REAL(kind=
dp),
DIMENSION(:) :: time_series
100 COMPLEX(kind=dp),
DIMENSION(:, :) :: value_series
101 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: result_series
102 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL :: omega_series
103 REAL(kind=
dp),
OPTIONAL :: damping_opt, t0_opt
104 LOGICAL,
OPTIONAL :: subtract_initial_opt
106 CHARACTER(len=*),
PARAMETER :: routinen =
'multi_fft'
108 COMPLEX(kind=dp) :: subtract_value
109 COMPLEX(kind=dp),
CONTIGUOUS,
DIMENSION(:), &
110 POINTER :: ft_samples, samples, samples_input
111 INTEGER :: handle, i, i0, j, nsamples, nseries, stat
112 LOGICAL :: subtract_initial
113 REAL(kind=
dp) :: damping, delta_t, t0, t_total
121 IF (
PRESENT(t0_opt)) t0 = t0_opt
122 IF (
SIZE(time_series) < 2)
THEN
123 cpabort(
"multi_fft requires at least two time samples.")
127 DO i = 1,
SIZE(time_series)
128 IF (time_series(i) >= t0)
THEN
134 nsamples =
SIZE(time_series) - i0 + 1
135 IF (nsamples < 2)
THEN
136 cpabort(
"multi_fft requires at least two samples in the selected time window.")
139 t_total = time_series(
SIZE(time_series)) - time_series(i0)
140 delta_t = time_series(i0 + 1) - time_series(i0)
141 IF (t_total /= t_total .OR. abs(t_total) >= huge(t_total) .OR. t_total <= 0.0_dp)
THEN
142 cpabort(
"multi_fft detected an abnormal total time window (NaN/Inf/non-positive).")
144 IF (delta_t /= delta_t .OR. abs(delta_t) >= huge(delta_t) .OR. delta_t <= 0.0_dp)
THEN
145 cpabort(
"multi_fft detected an abnormal timestep (NaN/Inf/non-positive).")
148 damping = 4.0_dp/(t_total)
150 IF (
PRESENT(damping_opt))
THEN
151 IF (damping_opt > 0.0_dp)
THEN
152 damping = 1.0_dp/damping_opt
153 ELSE IF (damping_opt == 0.0_dp)
THEN
158 IF (damping /= damping .OR. abs(damping) >= huge(damping))
THEN
159 cpabort(
"multi_fft detected an abnormal damping factor (NaN/Inf).")
162 subtract_initial = .true.
163 subtract_value = 0.0_dp
164 IF (
PRESENT(subtract_initial_opt)) subtract_initial = subtract_initial_opt
167 nseries =
SIZE(value_series, 1)
169 IF (nsamples /=
SIZE(result_series, 2))
THEN
170 DEALLOCATE (result_series)
171 ALLOCATE (result_series(nseries, nsamples), source=cmplx(0.0, 0.0, kind=
dp))
175 IF (
PRESENT(omega_series))
THEN
176 CALL fft_freqs(nsamples, t_total, omega_series, fft_ordering_opt=.false.)
177 IF (any(omega_series /= omega_series) .OR. &
178 any(abs(omega_series) >= huge(omega_series)))
THEN
179 cpabort(
"multi_fft produced abnormal frequencies (NaN/Inf).")
185 CALL timeset(routinen, handle)
187 NULLIFY (samples_input)
189 CALL fft_alloc(samples, [nsamples*nseries])
190 CALL fft_alloc(samples_input, [nsamples*nseries])
191 CALL fft_alloc(ft_samples, [nsamples*nseries])
196 IF (subtract_initial)
THEN
197 subtract_value = value_series(i, 1)
199 samples_input(j + (i - 1)*nsamples) = value_series(i, i0 + j - 1) - subtract_value
201 samples_input(j + (i - 1)*nsamples) = samples_input(j + (i - 1)*nsamples)* &
202 exp(-damping*(time_series(i0 + j - 1) - time_series(i0)))
207 nsamples, nsamples, nsamples, nseries, samples, ft_samples)
216 IF (subtract_initial)
THEN
217 subtract_value = value_series(i, 1)
219 CALL ft_simple(time_series(i0:
SIZE(time_series)), &
220 value_series(i, i0:
SIZE(value_series, 2)), result_series(i, 1:nsamples), &
221 damping, subtract_value)
226 CALL fft_shift(ft_samples((i - 1)*nsamples + 1:i*nsamples))
227 result_series(i, :) = ft_samples((i - 1)*nsamples + 1:i*nsamples)
230 IF (any(real(result_series, kind=
dp) /= real(result_series, kind=
dp)) .OR. &
231 any(aimag(result_series) /= aimag(result_series)) .OR. &
232 any(abs(real(result_series, kind=
dp)) >= huge(1.0_dp)) .OR. &
233 any(abs(aimag(result_series)) >= huge(1.0_dp)))
THEN
234 cpabort(
"multi_fft produced abnormal Fourier amplitudes (NaN/Inf).")
237 CALL fft_dealloc(samples)
238 CALL fft_dealloc(ft_samples)
239 CALL fft_dealloc(samples_input)
241 CALL timestop(handle)