📄 module spharmt.f90
字号:
real :: c, s
nh=n/2
nx=n+1
ink=inc+inc
! a(0) and a(n/2)
ia=1
ib=n*inc+1
ja=1
jb=2
do L=1,lot
work(ja)=a(ia)+a(ib)
work(jb)=a(ia)-a(ib)
ia=ia+jump
ib=ib+jump
ja=ja+nx
jb=jb+nx
enddo
! remaining wavenumbers
iabase=2*inc+1
ibbase=(n-2)*inc+1
jabase=3
jbbase=n-1
do k=3,nh,2
ia=iabase
ib=ibbase
ja=jabase
jb=jbbase
c=trigs(n+k)
s=trigs(n+k+1)
do L=1,lot
work(ja)=(a(ia)+a(ib))- &
(s*(a(ia)-a(ib))+c*(a(ia+inc)+a(ib+inc)))
work(jb)=(a(ia)+a(ib))+ &
(s*(a(ia)-a(ib))+c*(a(ia+inc)+a(ib+inc)))
work(ja+1)=(c*(a(ia)-a(ib))-s*(a(ia+inc)+a(ib+inc)))+ &
(a(ia+inc)-a(ib+inc))
work(jb+1)=(c*(a(ia)-a(ib))-s*(a(ia+inc)+a(ib+inc)))- &
(a(ia+inc)-a(ib+inc))
ia=ia+jump
ib=ib+jump
ja=ja+nx
jb=jb+nx
enddo
iabase=iabase+ink
ibbase=ibbase-ink
jabase=jabase+2
jbbase=jbbase-2
enddo
! wavenumber n/4 (if it exists)
if (iabase.eq.ibbase) then
ia=iabase
ja=jabase
do L=1,lot
work(ja)=2.0*a(ia)
work(ja+1)=-2.0*a(ia+inc)
ia=ia+jump
ja=ja+nx
enddo
endif
end subroutine fft99a
!##########################################################################
subroutine fft99b (work,a,trigs,inc,jump,n,lot)
integer, intent(in) :: inc,jump,n,lot
real, intent(in) :: trigs(:)
real, intent(inout) :: a(*),work(*)
! dimension work(n),a(n),trigs(n)
!
! subroutine fft99b - postprocessing step for fft99, isign=-1
! (gridpoint to spectral transform)
integer :: nh, nx, ink, k, L
integer :: ia, ib, ja, jb, iabase, ibbase, jabase, jbbase
real :: scale, c, s
nh=n/2
nx=n+1
ink=inc+inc
! a(0) and a(n/2)
scale=1.0/real(n)
ia=1
ib=2
ja=1
jb=n*inc+1
do L=1,lot
a(ja)=scale*(work(ia)+work(ib))
a(jb)=scale*(work(ia)-work(ib))
a(ja+inc)=0.0
a(jb+inc)=0.0
ia=ia+nx
ib=ib+nx
ja=ja+jump
jb=jb+jump
enddo
! remaining wavenumbers
scale=0.5*scale
iabase=3
ibbase=n-1
jabase=2*inc+1
jbbase=(n-2)*inc+1
do k=3,nh,2
ia=iabase
ib=ibbase
ja=jabase
jb=jbbase
c=trigs(n+k)
s=trigs(n+k+1)
do L=1,lot
a(ja)=scale*((work(ia)+work(ib)) &
+(c*(work(ia+1)+work(ib+1))+s*(work(ia)-work(ib))))
a(jb)=scale*((work(ia)+work(ib)) &
-(c*(work(ia+1)+work(ib+1))+s*(work(ia)-work(ib))))
a(ja+inc)=scale*((c*(work(ia)-work(ib))-s*(work(ia+1)+work(ib+1))) &
+(work(ib+1)-work(ia+1)))
a(jb+inc)=scale*((c*(work(ia)-work(ib))-s*(work(ia+1)+work(ib+1))) &
-(work(ib+1)-work(ia+1)))
ia=ia+nx
ib=ib+nx
ja=ja+jump
jb=jb+jump
enddo
iabase=iabase+2
ibbase=ibbase-2
jabase=jabase+ink
jbbase=jbbase-ink
enddo
! wavenumber n/4 (if it exists)
if (iabase.eq.ibbase) then
ia=iabase
ja=jabase
scale=2.0*scale
do L=1,lot
a(ja)=scale*work(ia)
a(ja+inc)=-scale*work(ia+1)
ia=ia+nx
ja=ja+jump
enddo
endif
end subroutine fft99b
!##########################################################################
subroutine fft991(a,work,trigs,ifax,inc,jump,n,lot,isign)
integer, intent(in) :: inc,jump,n,lot,isign
integer, intent(in) :: ifax(:)
real, intent(in) :: trigs(:)
real, intent(inout) :: a(*),work(*)
! dimension a(n),work(n),trigs(n),ifax(1)
!
! subroutine "fft991" - multiple real/half-complex periodic
! fast fourier transform
!
! same as fft99 except that ordering of data corresponds to
! that in mrfft2
!
! procedure used to convert to half-length complex transform
! is given by cooley, lewis and welch (j. sound vib., vol. 12
! (1970), 315-337)
!
! a is the array containing input and output data
! work is an area of size (n+1)*lot
! trigs is a previously prepared list of trig function values
! ifax is a previously prepared list of factors of n/2
! inc is the increment within each data 'vector'
! (e.g. inc=1 for consecutively stored data)
! jump is the increment between the start of each data vector
! n is the length of the data vectors
! lot is the number of data vectors
! isign = +1 for transform from spectral to gridpoint
! = -1 for transform from gridpoint to spectral
!
! ordering of coefficients:
! a(0),b(0),a(1),b(1),a(2),b(2),...,a(n/2),b(n/2)
! where b(0)=b(n/2)=0; (n+2) locations required
!
! ordering of data:
! x(0),x(1),x(2),...,x(n-1)
!
! vectorization is achieved on cray by doing the transforms in
! parallel
!
! *** n.b. n is assumed to be an even number
!
! definition of transforms:
! -------------------------
!
! isign=+1: x(j)=sum(k=0,...,n-1)(c(k)*exp(2*i*j*k*pi/n))
! where c(k)=a(k)+i*b(k) and c(n-k)=a(k)-i*b(k)
!
! isign=-1: a(k)=(1/n)*sum(j=0,...,n-1)(x(j)*cos(2*j*k*pi/n))
! b(k)=-(1/n)*sum(j=0,...,n-1)(x(j)*sin(2*j*k*pi/n))
!
integer :: nfax, nx, nh, ink, igo, ibase, jbase
integer :: i, j, k, L, m, ia, la, ib
nfax=ifax(1)
nx=n+1
nh=n/2
ink=inc+inc
if (isign.eq.+1) go to 30
! if necessary, transfer data to work area
igo=50
if (mod(nfax,2).eq.1) goto 40
ibase=1
jbase=1
do L=1,lot
i=ibase
j=jbase
do m=1,n
work(j)=a(i)
i=i+inc
j=j+1
enddo
ibase=ibase+jump
jbase=jbase+nx
enddo
!
igo=60
go to 40
!
! preprocessing (isign=+1)
! ------------------------
!
30 continue
call fft99a(a,work,trigs,inc,jump,n,lot)
igo=60
!
! complex transform
! -----------------
!
40 continue
ia=1
la=1
do k=1,nfax
if (igo.eq.60) go to 60
50 continue
call vpassm (a(ia),a(ia+inc),work(1),work(2),trigs, &
ink,2,jump,nx,lot,nh,ifax(k+1),la)
igo=60
go to 70
60 continue
call vpassm (work(1),work(2),a(ia),a(ia+inc),trigs, &
2,ink,nx,jump,lot,nh,ifax(k+1),la)
igo=50
70 continue
la=la*ifax(k+1)
enddo
if (isign.eq.-1) go to 130
! if necessary, transfer data from work area
if (mod(nfax,2).ne.1) then
ibase=1
jbase=1
do L=1,lot
i=ibase
j=jbase
do m=1,n
a(j)=work(i)
i=i+1
j=j+inc
enddo
ibase=ibase+nx
jbase=jbase+jump
enddo
endif
! fill in zeros at end
ib=n*inc+1
do L=1,lot
a(ib)=0.0
a(ib+inc)=0.0
ib=ib+jump
enddo
go to 140
! postprocessing (isign=-1):
! --------------------------
130 continue
call fft99b (work,a,trigs,inc,jump,n,lot)
140 continue
end subroutine fft991
!##########################################################################
subroutine set99 (trigs, ifax, n)
integer, intent(in) :: n
integer, intent(out) :: ifax(:)
real, intent(out) :: trigs(:)
! dimension ifax(13),trigs(1)
!
! mode 3 is used for real/half-complex transforms. it is possible
! to do complex/complex transforms with other values of mode, but
! documentation of the details were not available when this routine
! was written.
!
integer :: mode = 3
integer :: i
call fax (ifax, n, mode)
i = ifax(1)
if (ifax(i+1) .gt. 5 .or. n .le. 4) ifax(1) = -99
if (ifax(1) .le. 0 ) then
write(6,*) ' set99 -- invalid n'
stop
endif
call fftrig (trigs, n, mode)
end subroutine set99
!##########################################################################
subroutine fax (ifax,n,mode)
integer, intent(out) :: ifax(:)
integer, intent(in) :: n, mode
integer :: nn, k, L, inc, nfax, ii, istop, i, item
nn=n
if (iabs(mode).eq.1) go to 10
if (iabs(mode).eq.8) go to 10
nn=n/2
if ((nn+nn).eq.n) go to 10
ifax(1)=-99
return
10 k=1
! test for factors of 4
20 if (mod(nn,4).ne.0) go to 30
k=k+1
ifax(k)=4
nn=nn/4
if (nn.eq.1) go to 80
go to 20
! test for extra factor of 2
30 if (mod(nn,2).ne.0) go to 40
k=k+1
ifax(k)=2
nn=nn/2
if (nn.eq.1) go to 80
! test for factors of 3
40 if (mod(nn,3).ne.0) go to 50
k=k+1
ifax(k)=3
nn=nn/3
if (nn.eq.1) go to 80
go to 40
! now find remaining factors
50 L=5
inc=2
! inc alternately takes on values 2 and 4
60 if (mod(nn,L).ne.0) go to 70
k=k+1
ifax(k)=L
nn=nn/L
if (nn.eq.1) go to 80
go to 60
70 L=L+inc
inc=6-inc
go to 60
80 ifax(1)=k-1
! ifax(1) contains number of factors
nfax=ifax(1)
! sort factors into ascending order
if (nfax.eq.1) go to 110
do 100 ii=2,nfax
istop=nfax+2-ii
do 90 i=2,istop
if (ifax(i+1).ge.ifax(i)) go to 90
item=ifax(i)
ifax(i)=ifax(i+1)
ifax(i+1)=item
90 continue
100 continue
110 continue
end subroutine fax
!##########################################################################
subroutine fftrig (trigs,n,mode)
real, intent(out) :: trigs(:)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -