具有更多参数和集成的函数 [英] Function with more arguments and integration
问题描述
我有一个简单的问题,但我无法在任何地方找到解决方案.我必须集成一个函数(例如使用 Simpson 的规则子例程),但我必须将多个参数传递给我的函数:一个是我稍后要集成的变量,另一个只是来自不同的值我无法在函数内部执行的计算.
I have I simple problem but I cannot find a solution anywhere. I have to integrate a function (for example using a Simpson's rule subroutine) but I am obliged to pass to my function more than one argument: one is the variable that I want to integrate later and another one is just a value coming from a different calculation which I cannot perform inside the function.
问题在于 Simpson 子例程只接受 f(x) 来执行积分,而不接受 f(x,y).
The problem is that the Simpson subroutine only accept f(x) to perform the integral and not f(x,y).
根据 Vladimir 的建议,我修改了代码.
After Vladimir suggestions I modified the code.
下面的例子:
Program main2
!------------------------------------------------------------------
! Integration of a function using Simpson rule
! with doubling number of intervals
!------------------------------------------------------------------
! to compile:
! gfortran main2.f90 -o simp2
implicit none
double precision r, rb, rmin, rmax, rstep, integral, eps
double precision F_int
integer nint, i, rbins
double precision t
rbins = 4
rmin = 0.0
rmax = 4.0
rstep = (rmax-rmin)/rbins
rb = rmin
eps = 1.0e-8
func = 0.0
t=2.0
do i=1,rbins
call func(rb,t,res)
write(*,*)'r, f(rb) (in main) = ', rb, res
!test = F_int(rb)
!write(*,*)'test F_int (in loop) = ', test
call simpson2(F_int(rb),rmin,rb,eps,integral,nint)
write(*,*)'r, integral = ', rb, integral
rb = rb+rstep
end do
end program main2
subroutine func(x,y,res)
!----------------------------------------
! Real Function
!----------------------------------------
implicit none
double precision res
double precision, intent(in) :: x
double precision y
res = 2.0*x + y
write(*,*)'f(x,y) (in func) = ',res
return
end subroutine func
function F_int(x)
!Function to integrate
implicit none
double precision F_int, res
double precision, intent(in) :: x
double precision y
call func(x,y,res)
F_int = res
end function F_int
Subroutine simpson2(f,a,b,eps,integral,nint)
!==========================================================
! Integration of f(x) on [a,b]
! Method: Simpson rule with doubling number of intervals
! till error = coeff*|I_n - I_2n| < eps
! written by: Alex Godunov (October 2009)
!----------------------------------------------------------
! IN:
! f - Function to integrate (supplied by a user)
! a - Lower limit of integration
! b - Upper limit of integration
! eps - tolerance
! OUT:
! integral - Result of integration
! nint - number of intervals to achieve accuracy
!==========================================================
implicit none
double precision f, a, b, eps, integral
double precision sn, s2n, h, x
integer nint
double precision, parameter :: coeff = 1.0/15.0 ! error estimate coeff
integer, parameter :: nmax=1048576 ! max number of intervals
integer n, i
! evaluate integral for 2 intervals (three points)
h = (b-a)/2.0
sn = (1.0/3.0)*h*(f(a)+4.0*f(a+h)+f(b))
write(*,*)'a, b, h, sn (in simp) = ', a, b, h, sn
! loop over number of intervals (starting from 4 intervals)
n=4
do while (n <= nmax)
s2n = 0.0
h = (b-a)/dfloat(n)
do i=2, n-2, 2
x = a+dfloat(i)*h
s2n = s2n + 2.0*f(x) + 4.0*f(x+h)
end do
s2n = (s2n + f(a) + f(b) + 4.0*f(a+h))*h/3.0
if(coeff*abs(s2n-sn) <= eps) then
integral = s2n + coeff*(s2n-sn)
nint = n
exit
end if
sn = s2n
n = n*2
end do
return
end subroutine simpson2
我认为我非常接近解决方案,但我无法弄清楚......如果我在没有将参数放入 F_int 的情况下调用 simpson2(F_int, ..) 我会收到以下消息:
I think I'm pretty close to the solution but I cannot figure it out... If I call simpson2(F_int, ..) without putting the argument in F_int I receive this message:
call simpson2(F_int,rmin,rb,eps,integral,nint)
1
Warning: Expected a procedure for argument 'f' at (1)
有什么帮助吗?提前致谢!
Any help? Thanks in advance!
推荐答案
现在你有一个我们可以使用的代码,干得好!
Now you have a code we can work with, good job!
你需要告诉编译器,F_int
是一个函数.这可以通过
You need to tell the compiler, that F_int
is a function. That can be done by
external F_int
但学习 Fortran 90 并使用模块或至少使用接口块要好得多.
but it is much better to learn Fortran 90 and use modules or at least interface blocks.
module my_functions
implicit none
contains
subroutine func(x,y,res)
!----------------------------------------
! Real Function
!----------------------------------------
implicit none
double precision res
double precision, intent(in) :: x
double precision y
res = 2.0*x + y
write(*,*)'f(x,y) (in func) = ',res
return
end subroutine func
function F_int(x)
!Function to integrate
implicit none
double precision F_int, res
double precision, intent(in) :: x
double precision y
call func(x,y,res)
F_int = res
end function F_int
end module
现在您可以轻松使用模块并集成功能
Now you can easily use the module and integrate the function
use my_functions
call simpson2(F_int,rmin,rb,eps,integral,nint)
但是你会发现F_int
还是不知道y
是什么!它有自己的 y
值未定义!你应该把 y
放到模块中,这样每个人都可以看到它.
But you will find that F_int
still does not know what y
is! It has it's own y
with undefined value! You should put y
into the module instead so that everyone can see it.
module my_functions
implicit none
double precision :: y
contains
不要忘记删除 y
的所有其他声明!在函数 F_int
和主程序中.或许换个名字也更好.
Don't forget to remove all other declarations of y
! Both in function F_int
and in the main program. Probably it is also better to call it differently.
不要忘记在主循环中的某处设置 y
的值!
Don't forget to set the value of y
somewhere inside your main loop!
这篇关于具有更多参数和集成的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!