!
! This file is part of SACAMOS, State of the Art CAble MOdels in Spice.
! It was developed by the University of Nottingham and the Netherlands Aerospace
! Centre (NLR) for ESA under contract number 4000112765/14/NL/HK.
!
! Copyright (C) 2016-2017 University of Nottingham
!
! SACAMOS is free software: you can redistribute it and/or modify it under the
! terms of the GNU General Public License as published by the Free Software
! Foundation, either version 3 of the License, or (at your option) any later
! version.
!
! SACAMOS is distributed in the hope that it will be useful, but
! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! for more details.
!
! A copy of the GNU General Public License version 3 can be found in the
! file GNU_GPL_v3 in the root or at .
!
! SACAMOS uses the EISPACK library (in /SRC/EISPACK). EISPACK is subject to
! the GNU Lesser General Public License. A copy of the GNU Lesser General Public
! License version can be found in the file GNU_LGPL in the root of EISPACK
! (/SRC/EISPACK ) or at .
!
! The University of Nottingham can be contacted at: ggiemr@nottingham.ac.uk
!
! File Contents:
! SUBROUTINE FFT_TIME_TO_FREQ
! SUBROUTINE FFT_FREQ_TO_TIME
! SUBROUTINE FFT
!
! NAME
! FFT_TIME_TO_FREQ
!
! DESCRIPTION
! wrapper for Forward Fast Fourier Transform routine
!
! COMMENTS
!
!
! HISTORY
!
! started 24/4/2015 CJS
!
!
SUBROUTINE FFT_TIME_TO_FREQ(n,time,f_time,freq,f_freq)
USE type_specifications
USE constants
IMPLICIT NONE
! variables passed to subroutine
integer,intent(IN) :: n ! number of samples
real(dp),intent(IN) :: time(n) ! input time values
real(dp),intent(OUT) :: freq(n) ! output frequency values
complex(dp),intent(IN) :: f_time(n) ! input function of time to transform
complex(dp),intent(OUT) :: f_freq(n) ! output function of frequency
! local variables
complex(dp) :: x(n)
integer :: n2
complex(dp),allocatable :: xe(:)
complex(dp),allocatable :: xo(:)
complex(dp) :: const
real(dp) :: dt
real(dp) :: fmin,fmax,fstep
integer :: i
! START
! No action required for n=1
if(n .LE. 1) RETURN
! get the timestep
dt=time(2)-time(1)
! set the frequency values
fmin=0d0
fstep=1d0/(n*dt)
fmax=fstep*(n-1)
! Generate the frequency list
do i=1,n
freq(i)=fmin+(i-1)*fstep
end do
! copy input function of time to x
x(:)=f_time(:)
! Calculate FFT
CALL FFT(x,N)
! copy x to the output function of frequency
f_freq(:)=x(:)
RETURN
END SUBROUTINE FFT_TIME_TO_FREQ
!
! NAME
! INVERSE_FFT_FREQ_TO_TIME
!
! DESCRIPTION
! Inverse Fast Fourier Transform routine
!
! COMMENTS
!
!
! HISTORY
!
! started 24/4/2015 CJS
!
!
SUBROUTINE FFT_FREQ_TO_TIME(n,time,f_time,freq,f_freq)
USE type_specifications
USE constants
IMPLICIT NONE
! variables passed to subroutine
integer,intent(IN) :: n ! number of samples
real(dp),intent(OUT) :: time(n) ! output time values
real(dp),intent(IN) :: freq(n) ! input frequency values
complex(dp),intent(OUT) :: f_time(n) ! output function of time to transform
complex(dp),intent(IN) :: f_freq(n) ! input function of frequency
! local variables
complex(dp) :: x(n)
integer :: n2
complex(dp),allocatable :: xe(:)
complex(dp),allocatable :: xo(:)
complex(dp) :: const
complex(dp) :: swap
real(dp) :: df
real(dp) :: tmin,tmax,tstep
integer :: i
! START
! get the frequency step
df=freq(2)-freq(1)
! set the time values
tmin=0d0
tstep=1d0/(n*df)
tmax=tstep*(n-1)
! Generate the time list
do i=1,n
time(i)=tmin+(i-1)*tstep
end do
! copy the dataset into a local array
do i=1,n
x(i)=f_freq(i)
end do
! Call the forward FFT routine
CALL FFT(x,n)
do i=1,n
x(i)=x(i)/n
end do
! loop over the result dividing by n and reversing the imaginary part
f_time(1)=x(1)
do i=2,n
f_time(i)=x(n-i+2)
end do
RETURN
END SUBROUTINE FFT_FREQ_TO_TIME
!
! SUBROUTINE FFT
!
! NAME
! FFT
!
! DESCRIPTION
! Fast Fourier Transform routine
! This is a simple recursive implementation of the fast fourier transform
! not the most efficient but very compact.
!
! COMMENTS
!
!
! HISTORY
!
! started 20/11/2013 CJS
!
!
RECURSIVE SUBROUTINE FFT(x,N)
USE type_specifications
USE constants
IMPLICIT NONE
! variables passed to subroutine
integer,intent(IN) :: n ! number of samples
complex(dp),intent(INOUT) :: x(n) ! sample values
! local variables
integer :: n2
complex(dp),allocatable :: xe(:)
complex(dp),allocatable :: xo(:)
complex(dp) :: const
integer :: i
! START
! No action required for n=1
if(n .LE. 1) RETURN
n2=n/2
ALLOCATE(xe(1:n2))
ALLOCATE(xo(1:n2))
! fill odd and even data
do i=1,n2
xo(i)=x(2*i-1)
xe(i)=x(2*i)
end do
! FFT odd and even sequences
CALL FFT(xo,n2)
CALL FFT(xe,n2)
! combine odd and even FFTs
do i=1,n2
const=exp(-2d0*pi*j*(i-1)/n)
x(i) = xo(i)+xe(i)*const
x(i+N2)= xo(i)-xe(i)*const
end do
DEALLOCATE(xo)
DEALLOCATE(xe)
RETURN
END SUBROUTINE FFT