吹是一個主文件在Fortran中使用r2c和c2r FFTW時,前向和後向維度是否相同?
PROGRAM SPHEROID
USE nrtype
USE SUB_INFO
INCLUDE "/usr/local/include/fftw3.f"
INTEGER(I8B) :: plan_forward, plan_backward
INTEGER(I4B) :: i, t, int_N
REAL(DP) :: cth_i, sth_i, real_i, perturbation
REAL(DP) :: PolarEffect, dummy, x1, x2, x3
REAL(DP), DIMENSION(4096) :: dummy1, dummy2, gam, th, ph
REAL(DP), DIMENSION(4096) :: k1, k2, k3, k4, l1, l2, l3, l4, f_in
COMPLEX(DPC), DIMENSION(2049) :: output1, output2, f_out
CHARACTER(1024) :: baseOutputFilename
CHARACTER(1024) :: outputFile, format_string
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int_N = 4096
! File Open Section
format_string = '(I5.5)'
! Write the coodinates at t = 0
do i = 1, N
real_i = real(i)
gam(i) = 2d0*pi/real_N
perturbation = 0.01d0*dsin(2d0*pi*real_i/real_N)
ph(i) = 2d0*pi*real_i/real_N + perturbation
th(i) = pi/3d0 + perturbation
end do
! Initialization Section for FFTW PLANS
call dfftw_plan_dft_r2c_1d(plan_forward, int_N, f_in, f_out, FFTW_ESTIMATE)
call dfftw_plan_dft_c2r_1d(plan_backward, int_N, f_out, f_in, FFTW_ESTIMATE)
! Runge-Kutta 4th Order Method Section
do t = 1, Iter_N
call integration(th, ph, gam, k1, l1)
do i = 1, N
dummy1(i) = th(i) + 0.5d0*dt*k1(i)
end do
do i = 1, N
dummy2(i) = ph(i) + 0.5d0*dt*l1(i)
end do
call integration(dummy1, dummy2, gam, k2, l2)
do i = 1, N
dummy1(i) = th(i) + 0.5d0*dt*k2(i)
end do
do i = 1, N
dummy2(i) = ph(i) + 0.5d0*dt*l2(i)
end do
call integration(dummy1, dummy2, gam, k3, l3)
do i = 1, N
dummy1(i) = th(i) + dt*k3(i)
end do
do i = 1, N
dummy2(i) = ph(i) + dt*l3(i)
end do
call integration(dummy1, dummy2, gam, k4, l4)
do i = 1, N
cth_i = dcos(th(i))
sth_i = dsin(th(i))
PolarEffect = (nv-sv)*dsqrt(1d0+a*sth_i**2) + (nv+sv)*cth_i
PolarEffect = PolarEffect/(sth_i**2)
th(i) = th(i) + dt*(k1(i) + 2d0*k2(i) + 2d0*k3(i) + k4(i))/6d0
ph(i) = ph(i) + dt*(l1(i) + 2d0*l2(i) + 2d0*l3(i) + l4(i))/6d0
ph(i) = ph(i) + dt*0.25d0*PolarEffect/pi
end do
!! Fourier Filtering Section
call dfftw_execute_dft_r2c(plan_forward, th, output1)
do i = 1, N/2+1
dummy = abs(output1(i))
if (dummy.lt.threshhold) then
output1(i) = dcmplx(0.0d0)
end if
end do
call dfftw_execute_dft_c2r(plan_backward, output1, th)
do i = 1, N
th(i) = th(i)/real_N
end do
call dfftw_execute_dft_r2c(plan_forward, ph, output2)
do i = 1, N/2+1
dummy = abs(output2(i))
if (dummy.lt.threshhold) then
output2(i) = dcmplx(0.0d0)
end if
end do
call dfftw_execute_dft_c2r(plan_backward, output2, ph)
do i = 1, N
ph(i) = ph(i)/real_N
end do
!! Data Writing Section
write(baseOutputFilename, format_string) t
outputFile = "xyz" // baseOutputFilename
open(unit=7, file=outputFile)
outputFile = "Fsptrm" // baseOutputFilename
open(unit=8, file=outputFile)
do i = 1, N
x1 = dsin(th(i))*dcos(ph(i))
x2 = dsin(th(i))*dsin(ph(i))
x3 = dsqrt(1d0+a)*dcos(th(i))
write(7,*) x1, x2, x3
end do
do i = 1, N/2+1
write(8,*) abs(output1(i)), abs(output2(i))
end do
close(7)
close(8)
do i = 1, N/2+1
output1(i) = dcmplx(0.0d0)
end do
do i = 1, N/2+1
output2(i) = dcmplx(0.0d0)
end do
end do
! Destroying Process for FFTW PLANS
call dfftw_destroy_plan(plan_forward)
call dfftw_destroy_plan(plan_backward)
END PROGRAM
下面是集成
! We implemented Shelly's spectrally accurate convergence method
SUBROUTINE integration(in1,in2,in3,out1,out2)
USE nrtype
USE SUB_INFO
INTEGER(I4B) :: i, j
REAL(DP) :: th_i, th_j, gi, ph_i, ph_j, gam_j, v1, v2
REAL(DP), DIMENSION(N), INTENT(INOUT) :: in1, in2, in3, out1, out2
REAL(DP) :: ui, uj, part1, part2, gj, cph, sph
REAL(DP) :: denom, numer, temp
do i = 1, N
out1(i) = 0d0
end do
do i = 1, N
out2(i) = 0d0
end do
do i = 1, N
th_i = in1(i)
ph_i = in2(i)
ui = dcos(th_i)
part1 = dsqrt(1d0+a)/(dsqrt(-a)*ui+dsqrt(1d0+a-a*ui*ui))
part1 = part1**(dsqrt(-a))
part2 = (dsqrt(1d0+a-a*ui*ui)+ui)/(dsqrt(1d0+a-a*ui*ui)-ui)
part2 = dsqrt(part2)
gi = dsqrt(1d0-ui*ui)*part1*part2
do j = 1, N
if (mod(i+j,2).eq.1) then
th_j = in1(j)
ph_j = in2(j)
gam_j = in3(j)
uj = dcos(th_j)
part1 = dsqrt(1d0+a)/(dsqrt(-a)*uj+dsqrt(1d0+a-a*uj*uj))
part1 = part1**(dsqrt(-a))
part2 = (dsqrt(1d0+a-a*uj*uj)+uj)/(dsqrt(1d0+a-a*uj*uj)-uj)
part2 = dsqrt(part2)
gj = dsqrt(1d0-ui*ui)*part1*part2
cph = dcos(ph_i-ph_j)
sph = dsin(ph_i-ph_j)
numer = dsqrt(1d0-uj*uj)*sph
denom = (gj/gi*(1d0-ui*ui) + gi/gj*(1d0-uj*uj))*0.5d0
denom = denom - dsqrt((1d0-ui*ui)*(1d0-uj*uj))*cph
denom = denom + krasny_delta
v1 = -0.25d0*gam_j*numer/denom/pi
temp = dsqrt(1d0+(1d0-ui*ui)*a)
numer = -(gj/gi)*(temp+ui)
numer = numer + (gi/gj)*((1d0-uj*uj)/(1d0-ui*ui))*(temp-ui)
numer = numer + 2d0*ui*dsqrt((1d0-uj*uj)/(1d0-ui*ui))*cph
numer = 0.5d0*numer
v2 = -0.25d0*gam_j*numer/denom/pi
out1(i) = out1(i) + 2d0*v1
out2(i) = out2(i) + 2d0*v2
end if
end do
end do
END
下面的子程序文件模塊文件
module nrtype
Implicit none
!integer
INTEGER, PARAMETER :: I8B = SELECTED_INT_KIND(20)
INTEGER, PARAMETER :: I4B = SELECTED_INT_KIND(9)
INTEGER, PARAMETER :: I2B = SELECTED_INT_KIND(4)
INTEGER, PARAMETER :: I1B = SELECTED_INT_KIND(2)
!real
INTEGER, PARAMETER :: SP = KIND(1.0)
INTEGER, PARAMETER :: DP = KIND(1.0D0)
!complex
INTEGER, PARAMETER :: SPC = KIND((1.0,1.0))
INTEGER, PARAMETER :: DPC = KIND((1.0D0,1.0D0))
!defualt logical
INTEGER, PARAMETER :: LGT = KIND(.true.)
!mathematical constants
REAL(DP), PARAMETER :: pi = 3.141592653589793238462643383279502884197_dp
!derived data type s for sparse matrices,single and double precision
!User-Defined Constants
INTEGER(I4B), PARAMETER :: N = 4096, Iter_N = 20000
REAL(DP), PARAMETER :: real_N = 4096d0
REAL(DP), PARAMETER :: a = -0.1d0, dt = 0.001d0, krasny_delta = 0.01d0
REAL(DP), PARAMETER :: nv = 0d0, sv = 0d0, threshhold = 0.00000000001d0
!N : The Number of Point Vortices, Iter_N * dt = Total time, dt : Time Step
!krasny_delta : Smoothing Parameter introduced by R.Krasny
!nv : Northern Vortex Strength, sv : Southern Vortex Strength
!a : The Eccentricity in the direction of z , threshhold : Filtering Threshhold
end module nrtype
下面是一個子程序信息文件
MODULE SUB_INFO
INTERFACE
SUBROUTINE integration(in1,in2,in3,out1,out2)
USE nrtype
INTEGER(I4B) :: i, j
REAL(DP) :: th_i, th_j, gi, ph_i, ph_j, gam_j, v1, v2
REAL(DP), DIMENSION(N), INTENT(INOUT) :: in1, in2, in3, out1, out2
REAL(DP) :: ui, uj, part1, part2, gj, cph, sph
REAL(DP) :: denom, numer, temp
END SUBROUTINE
END INTERFACE
END MODULE
我使用下面的命令編譯他們
gfortran -o p0 -fbounds-check nrtype.f90 spheroid_sub_info.f90 spheroid_sub_integration.f90 spheroid_main.f90 -lfftw3 -lm -Wall -pedantic -pg
nohup的./p0 &
注意,2049 = 4096/2 + 1
當製作plan_backward,是不是正確,我們使用2049而不是4096,因爲輸出的維數是2049?
但是當我這樣做的時候,它就爆炸了。 (爆炸意味着NAN錯誤)
如果我使用4096製作plan_backward,除了一些傅立葉係數異常大而不應該發生之外,一切都很好。
請幫助我正確使用Fortran中的FFTW。這個問題已經讓我感到很沮喪了。
我相信我的代碼非常小。並且我證實了這個代碼可以很好地通過繪製的結果xyz座標進行驗證。但傅立葉係數是不正常的。所以我懷疑使用FFTW –