我正在尝试将QUADPACK集成到我的Fortran90代码中。我尝试在我的主文件中调用子例程,但它工作得很好。
为了不把我的主文件弄得乱七八糟,我试着把代码的集成部分移到一个模块中。然而,当我把我的模块写成
module integrate
use ...
call dqage(params..)
contains
functions
end module 我收到以下消息
Unexpected CALL statement in MODULE at (1).我从另一篇文章中了解到,从模块进行这样的调用是违反Fortran标准的。因此,我尝试将故障诊断包代码封装到一个模块中,认为这会有所帮助。它没有像现在一样,我在编译时得到以下错误
/usr/bin/ld: quadpack_double.o: in function `__quadpack_MOD_dqc25s':
quadpack_double.f90:(.text+0xce29): undefined reference to `dqwgts_'所以,我的问题是,我如何集成QUADPACK,以便我可以在主文件之外的其他地方使用它?
发布于 2020-11-12 16:48:10
您需要编译所有故障诊断包文件并链接到它们。
一个用于连接故障诊断例程的模块将使您的编程工作更加轻松。下面的模块展示了一种方法
module quadpack_m
use, intrinsic :: ieee_arithmetic
implicit none
private
public :: QUADPACK_ERROR, quadpack_int
interface
function quadpack_integrand(x) result(f)
real, intent(in) :: x
real :: f
end function
end interface
character(*), parameter :: QUADPACK_ERROR(6) = [ &
"maximum number of subdivisions achieved", &
"roundoff error detected ", &
"extremely bad integrand behaviour ", &
"algorithm does not converge ", &
"integral is probably divergent ", &
"input is invalid " &
]
external :: dqags, dqagi
contains
subroutine quadpack_int(f, a, b, atol, rtol, result, aerr, neval, ier, limit, last)
procedure(quadpack_integrand) :: f
!! function to integrate
real, intent(in) :: a
!! lower integration limit
real, intent(in) :: b
!! upper integration limit
real, intent(in) :: atol
!! absolute tolerance
real, intent(in) :: rtol
!! relative tolerance
real, intent(out) :: result
!! output result of integration
real, optional, intent(out) :: aerr
!! optional: output estimate of the modulus of the absolute error, which should equal or exceed abs(i-result)
integer, optional, intent(out) :: neval
!! optional: output number of integrand evaluations
integer, optional, intent(out) :: ier
!! optional: output error code
integer, optional, intent(in) :: limit
!! optional: maximum number of subintervals (default: 4096)
integer, optional, intent(out) :: last
!! optional, output number of subintervals used
! local variables
integer :: neval_, ier_, limit_, lenw, last_, inf
integer, allocatable :: iwork(:)
real :: aerr_, bnd
real, allocatable :: work(:)
logical :: a_inf, b_inf
limit_ = 4096
if (present(limit)) limit_ = limit
lenw = limit_ * 4
allocate (iwork(limit_), work(lenw))
a_inf = (ieee_class(a) == IEEE_NEGATIVE_INF)
b_inf = (ieee_class(b) == IEEE_POSITIVE_INF)
bnd = 0
if (a_inf .and. b_inf) then
inf = 2
elseif (a_inf) then
bnd = b
inf = -1
elseif (b_inf) then
bnd = a
inf = +1
else
inf = 0
end if
if (inf == 0) then
call dqags(f, a, b, atol, rtol, result, aerr_, neval_, ier_, limit_, lenw, last_, iwork, work)
else
call dqagi(f, bnd, inf, atol, rtol, result, aerr_, neval_, ier_, limit_, lenw, last_, iwork, work)
end if
if (present(aerr )) aerr = aerr_
if (present(neval)) neval = neval_
if (present(ier )) ier = ier_
if (present(last )) last = last_
end subroutine
end module请注意,此代码假定在默认情况下编译为8字节的浮点数/整数,例如$ ifort -i8 -real-size 64或$ gfortran -fdefault-integer-8 -fdefault-real-8。如果可移植性是一个重要的问题,那么就不应该使用这些编译选项,而应该使用iso_fortran_env来指定数据类型,即INT64, REAL64。
https://stackoverflow.com/questions/64793582
复制相似问题