98 SUBROUTINE multi_fft(time_series, value_series, result_series, omega_series, &
99 damping_opt, t0_opt, subtract_initial_opt)
100 REAL(kind=
dp),
DIMENSION(:) :: time_series
101 COMPLEX(kind=dp),
DIMENSION(:, :) :: value_series
102 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: result_series
103 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL :: omega_series
104 REAL(kind=
dp),
OPTIONAL :: damping_opt, t0_opt
105 LOGICAL,
OPTIONAL :: subtract_initial_opt
107 CHARACTER(len=*),
PARAMETER :: routinen =
'multi_fft'
109 COMPLEX(kind=dp) :: subtract_value
110 COMPLEX(kind=dp),
CONTIGUOUS,
DIMENSION(:), &
111 POINTER :: ft_samples, samples, samples_input
112 INTEGER :: handle, i, i0, j, nsamples, nseries, stat
113 LOGICAL :: subtract_initial
114 REAL(kind=
dp) :: damping, delta_t, t0, t_total
122 IF (
PRESENT(t0_opt)) t0 = t0_opt
123 IF (
SIZE(time_series) < 2)
THEN
124 cpabort(
"multi_fft requires at least two time samples.")
128 DO i = 1,
SIZE(time_series)
129 IF (time_series(i) >= t0)
THEN
135 nsamples =
SIZE(time_series) - i0 + 1
136 IF (nsamples < 2)
THEN
137 cpabort(
"multi_fft requires at least two samples in the selected time window.")
140 t_total = time_series(
SIZE(time_series)) - time_series(i0)
141 delta_t = time_series(i0 + 1) - time_series(i0)
142 IF (t_total /= t_total .OR. abs(t_total) >= huge(t_total) .OR. t_total <= 0.0_dp)
THEN
143 cpabort(
"multi_fft detected an abnormal total time window (NaN/Inf/non-positive).")
145 IF (delta_t /= delta_t .OR. abs(delta_t) >= huge(delta_t) .OR. delta_t <= 0.0_dp)
THEN
146 cpabort(
"multi_fft detected an abnormal timestep (NaN/Inf/non-positive).")
149 damping = 4.0_dp/(t_total)
151 IF (
PRESENT(damping_opt))
THEN
152 IF (damping_opt > 0.0_dp)
THEN
153 damping = 1.0_dp/damping_opt
154 ELSE IF (damping_opt == 0.0_dp)
THEN
159 IF (damping /= damping .OR. abs(damping) >= huge(damping))
THEN
160 cpabort(
"multi_fft detected an abnormal damping factor (NaN/Inf).")
163 subtract_initial = .true.
164 subtract_value = 0.0_dp
165 IF (
PRESENT(subtract_initial_opt)) subtract_initial = subtract_initial_opt
168 nseries =
SIZE(value_series, 1)
170 IF (nsamples /=
SIZE(result_series, 2))
THEN
171 DEALLOCATE (result_series)
172 ALLOCATE (result_series(nseries, nsamples), source=cmplx(0.0, 0.0, kind=
dp))
176 IF (
PRESENT(omega_series))
THEN
177 CALL fft_freqs(nsamples, t_total, omega_series, fft_ordering_opt=.false.)
178 IF (any(omega_series /= omega_series) .OR. &
179 any(abs(omega_series) >= huge(omega_series)))
THEN
180 cpabort(
"multi_fft produced abnormal frequencies (NaN/Inf).")
186 CALL timeset(routinen, handle)
188 NULLIFY (samples_input)
190 CALL fft_alloc(samples, [nsamples*nseries])
191 CALL fft_alloc(samples_input, [nsamples*nseries])
192 CALL fft_alloc(ft_samples, [nsamples*nseries])
197 IF (subtract_initial)
THEN
198 subtract_value = value_series(i, 1)
200 samples_input(j + (i - 1)*nsamples) = value_series(i, i0 + j - 1) - subtract_value
202 samples_input(j + (i - 1)*nsamples) = samples_input(j + (i - 1)*nsamples)* &
203 exp(-damping*(time_series(i0 + j - 1) - time_series(i0)))
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)
subroutine, public multi_fft(time_series, value_series, result_series, omega_series, damping_opt, t0_opt, subtract_initial_opt)
Calculates the Fourier transform - couples to FFT libraries in CP2K, if available.