具有更多参数和集成的函数 [英] Function with more arguments and integration

查看:19
本文介绍了具有更多参数和集成的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的问题,但我无法在任何地方找到解决方案.我必须集成一个函数(例如使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆