implicit none
character*20 fflname,oflname
integer length_sgnl
real*8 pi, dt, m, n, theta
parameter ( length_sgnl=11900, dt=0.01d0, m=1, n=1, pi=3.1416
& ,theta=0.2 )
integer i
complex*16 cj, coeff ,sgnl(1 : length_sgnl)
real*8 t(1 : length_sgnl)
parameter ( cj = dcmplx(0, 1) )
real*8 time, real_sgnl, imag_sgnl
oflname="filtered.data"
fflname="artificial"
open(11, file = oflname)
do i=1, length_sgnl
read(11, *) time, real_sgnl, imag_sgnl
sgnl(i) = dcmplx(real_sgnl, imag_sgnl)
t(i) = (i*dt - m) / (2**n)
enddo
coeff = 0
do i=1, length_sgnl
coeff = coeff
& + sgnl(i) * sinc (t(i)) * exp (-cj*2*pi*t(i))
enddo
do i=1, length_sgnl
sgnl(i) = sgnl(i)
& - coeff * sinc (t(i)) * exp (-cj*2*pi*t(i))
& + coeff * sinc (t(i)) * exp (-cj*2*pi*t(i))
& * exp (cj*theta)
enddo
open(12, file = fflname)
do i=1, length_sgnl
write(12, *) i*dt, sgnl(i)
enddo
close(12)
real*8 function sinc (a)
real*8 :: sinc, a
if (abs(a) < 1.0d-6) then
sinc = 1
else
sinc = sin(pi*a) / (pi*a)
end if
end function
stop
end
在子定义函数sinc的最后一部分,我假设问题存在,但我不确定它究竟是什么。 gfortran注意到我没有定义sinc和a,而“end function”应该是“end program”?
答案 0 :(得分:1)
我尝试将您的程序更新为符合标准的现代Fortran:
program sinctest
use :: iso_fortran_env
implicit none
! Declare parameters
integer, parameter :: length_sgnl=11900
real(real64), parameter :: pi=3.1416, dt=0.01, m=1, n=1, theta=0.2
complex(real64), parameter :: cj = cmplx(0, 1)
! Declare variables
character(len=20) :: fflname, oflname
complex(real64) :: coeff, sgnl(length_sgnl)
real(real64) :: time, real_sgnl, imag_sgnl, t(length_sgnl)
integer :: i, ofl, ffl
! Define filenames
oflname="filtered.data"
fflname="artificial"
! Read the input file
open(newunit = ofl, file = oflname)
do i=1, length_sgnl
read(ofl, *) time, real_sgnl, imag_sgnl
sgnl(i) = cmplx(real_sgnl, imag_sgnl, kind=real64)
t(i) = (i*dt - m) / (2**n)
end do
close(ofl)
! Process the input signal
coeff = 0
do i=1, length_sgnl
coeff = coeff &
+ sgnl(i) * sinc(t(i)) * exp(-cj*2*pi*t(i))
end do
do i=1, length_sgnl
sgnl(i) = sgnl(i) &
- coeff * sinc(t(i)) * exp(-cj*2*pi*t(i)) &
+ coeff * sinc(t(i)) * exp(-cj*2*pi*t(i)) &
* exp(cj*theta)
end do
! Save the output file
open(newunit = ffl, file = fflname)
do i=1, length_sgnl
write(ffl, *) i*dt, sgnl(i)
enddo
close(ffl)
contains
pure function sinc(a) result(r)
! This function calculates sinc(a)=sin(pi*a)/(pi*a).
real(real64), intent(in) :: a
real(real64) :: r
if (abs(a) < 1.0e-6) then
r = 1
else
r = sin(pi*a) / (pi*a)
end if
end function
end program
使用例如编译它GFortran:
gfortran -std=f2008 -ffree-form sinctest.f
这些是我修复的语法错误:
contains
部分; &
)从续行的开头移到上一行的末尾; 这些不是必需的更改,仅仅是样式建议:
iso_fortran_env
获取real64
变量,这样您就可以将变量定义为real(real64)
而不是real*8
,因为前者是可移植的,而后者是不; real
)和parameter
的规范合并为一行; newunit
参数用于open
而不是单位数字中的硬编码,因为如果您编写大型程序并拥有现代编译器,这会让您感到头疼; pure
,因为它没有副作用; result
表示法,这样您就不必在函数名前面指定类型real*8
; program...end program
而非...stop end
。修改强>
我还想注意,使用现代Fortran,数学本身可以使用&#39;数组符号来更加简洁地编写。和&#39;元素功能&#39;。例如,如果你定义了sinc-function:
elemental function sinc(a) result(r)
! This function calculates sinc(a)=sin(pi*a)/(pi*a).
real(real64), intent(in) :: a
real(real64) :: r
if (abs(a) < 1.0e-6) then
r = 1
else
r = sin(pi*a) / (pi*a)
end if
end function
然后elemental
关键字表示如果将sinc函数应用于数组,它应返回一个新数组,其中已为每个元素计算sinc函数。所以这段代码:
coeff = 0
do i=1, length_sgnl
coeff = coeff &
+ sgnl(i) * sinc(t(i)) * exp(-cj*2*pi*t(i))
end do
然后可以实际写成一行:
coeff = sum(sgnl * sinc(t) * exp(-2*pi*cj*t))
所以我强烈建议您查看现代数组符号:)。
编辑2: 试图强调哪些变化与修正错误有关,哪些变化只是风格建议(感谢Vladimir F)。