我正在努力学习Fortran(遗憾的是我的研究小组的必要性) - 我自己设定的任务之一是将一个必要的函数(Associated Legendre多项式)从Numerical Recipes一书打包成fortran 03模块。原始程序(f77)以下列形式进行了一些错误处理:
if(m.lt.0.or.m.gt.1.or.abs(x).gt.1)pause 'bad arguments in plgndr'
自从f77以来,暂停似乎已被弃用,因为使用此行会给我一个编译错误,所以我尝试了以下内容:
module sha_helper
implicit none
public :: plgndr, factorial!, ylm
contains
! numerical recipes Associated Legendre Polynomials rewritten for f03
function plgndr(l,m,x) result(res_plgndr)
integer, intent(in) :: l, m
real, intent(in) :: x
real :: res_plgndr, fact, pll, pmm, pmmp1, somx2
integer :: i,ll
if (m.lt.0.or.m.gt.l.or.abs(x).gt.1) then
write (*, *) "bad arguments to plgndr, aborting", m, x
res_plgndr=-10e6 !return a ridiculous value
else
pmm = 1.
if (m.gt.0) then
somx2 = sqrt((1.-x)*(1.+x))
fact = 1.
do i = 1, m
pmm = -pmm*fact*somx2
fact = fact+2
end do
end if
if (l.eq.m) then
res_plgndr = pmm
else
pmmp1 = x*(2*m+1)*pmm
if(l.eq.m+1) then
res_plgndr = pmmp1
else
do ll = m+2, l
pll = (x*(2*ll-1)*pmmp1-(ll+m-1)*pmm)/(ll-m)
pmm = pmmp1
pmmp1 = pll
end do
res_plgndr = pll
end if
end if
end if
end function plgndr
recursive function factorial(n) result(factorial_result)
integer, intent(in) :: n
integer, parameter :: RegInt_K = selected_int_kind(20) !should be enough for the factorials I am using
integer (kind = RegInt_K) :: factorial_result
if (n <= 0) then
factorial_result = 1
else
factorial_result = n * factorial(n-1)
end if
end function factorial
! function ylm(l,m,theta,phi) result(res_ylm)
! integer, intent(in) :: l, m
! real, intent(in) :: theta, phi
! real :: res_ylm, front_block
! real, parameter :: pi = 3.1415926536
! front_block = sqrt((2*l+1)*factorial(l-abs(m))/(4*pi*))
! end function ylm
end module sha_helper
else之后的主代码工作,但如果我执行我的主程序并调用具有错误值的函数,程序会在执行print语句之前冻结。我知道print语句是问题,因为将其注释掉允许函数正常执行,返回-10e6作为值。理想情况下,我希望程序在给出用户可读的错误消息后崩溃,因为为plgndr函数赋予错误值是程序的致命错误。函数plgndr由程序sha_lmc使用。目前所有这一切都是读取一些数组,然后打印plgndr值进行测试(早期)。模块sha_helper中的函数ylm也没有完成,因此它被注释掉了。代码使用gfortran sha_helper.f03 sha_lmc.f03 -o sha_lmc进行编译, gfortran --version GNU Fortran(GCC)4.8.2
!Spherical Harmonic Bayesian Analysis testbed for Lagrangian Dynamical Monte Carlo
program sha_analysis
use sha_helper
implicit none
!Analysis Parameters
integer, parameter :: harm_order = 6
integer, parameter :: harm_array_length = (harm_order+1)**2
real, parameter :: coeff_lo = -0.1, coeff_hi = 0.1, data_err = 0.01 !for now, data_err fixed rather than heirarchical
!Monte Carlo Parameters
integer, parameter :: run = 100000, burn = 50000, thin = 100
real, parameter :: L = 1.0, e = 1.0
!Variables needed by the program
integer :: points, r, h, p, counter = 1
real, dimension(:), allocatable :: x, y, z
real, dimension(harm_array_length) :: l_index_list, m_index_list
real, dimension(:,:), allocatable :: g_matrix
!Open the file, allocate the x,y,z arrays and read the file
open(1, file = 'Average_H_M_C_PcP_boschi_1200.xyz', status = 'old')
read(1,*) points
allocate(x(points))
allocate(y(points))
allocate(z(points))
print *, "Number of Points: ", points
readloop: do r = 1, points
read(1,*) x(r), y(r), z(r)
end do readloop
!Set up the forwards model
allocate(g_matrix(harm_array_length,points))
!Generate the l and m values of spherical harmonics
hloop: do h = 0, harm_order
ploop: do p = -h,h
l_index_list(counter) = h
m_index_list(counter) = p
counter = counter + 1
end do ploop
end do hloop
print *, plgndr(1,2,0.1)
!print *, ylm(1,1,0.1,0.1)
end program sha_analysis
答案 0 :(得分:6)
您的程序执行所谓的递归IO - 对plgndr
的初始调用位于IO语句的输出项列表中(打印语句)[将输出定向到控制台] - 然后在该函数内部还尝试执行另一个IO语句[输出到控制台]。这是不允许的 - 见F2003的9.11p2和p3或F2008的9.12p2。
解决方案是将函数调用与主程序中的io语句分开,即
REAL :: a_temporary
...
a_temporary = plgndr(1,2,0.1)
PRINT *, a_temporary
F2008中的其他替代方案(但不是F2003 - 因此第一段中的[]部分)包括将函数的输出定向到不同的逻辑单元(请注意WRITE (*, ...
和PRINT ...
引用同一单位)。
在F2008中,您还可以将WRITE语句替换为带有消息的STOP语句(该消息必须是常量 - 这不会让您报告有问题的值)。
无意中调用递归IO的可能性是某些编程风格不鼓励在函数中执行IO的部分原因。
答案 1 :(得分:0)
尝试:
if (m.lt.0.or.m.gt.l.or.abs(x).gt.1) then
write (*, *) "bad arguments to plgndr, aborting", m, x
stop
else
...
end if