功能更多的参数和整合 [英] Function with more arguments and integration

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

问题描述

我有我简单的问题,但我无法在任何地方找到解决方案。
我必须集成一个函数(例如使用辛普森规则子例程),但我不得不将一个以上的参数传递给我的函数:其中一个是我稍后要整合的变量,而另一个只是一个值来自另一个我不能在函数内执行的计算。



问题是Simpson子程序只接受f(x)执行积分而不是f(x ,y)。

在弗拉基米尔建议后,我修改了代码。



下面的例子:

 程序main2 
!----------------------- -------------------------------------------
!使用Simpson规则集成一个函数
!间隔数加倍
!---------------------------------------- --------------------------
!编译:
! gfortran main2.f90 -o simp2

隐式无
双精度r,rb,rmin,rmax,rstep,积分,eps
双精度F_int
整数nint, i,rbins
双精度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

子程序func(x,y,res)
!--------------------------------- -------
!实数函数
!----------------------------------------
隐式无
双精度res
双精度,意图(in):: x
双精度y
res = 2.0 * x + y
写(* *)'f(x,y)(in func)=',res
return
end子程序func


函数F_int(x)
!函数集成

隐式无
双精度F_int,res
双精度,意图(in):: x
双精度y
调用func (x,y,res)
F_int = res
结束函数F_int



子程序simpson2(f,a,b,eps,integral, nint)
!=========================================== ===============
!在[a,b]
上集成f(x)!方法:辛普森规则与倍数间隔
!直到error = coeff * | I_n - I_2n | < eps
!撰写人:Alex Godunov(2009年10月)
!------------------------------------ ----------------------
! IN:
! f - 集成功能(由用户提供)
! a - 集成的下限
! b - 积分上限
! eps - 容差
! OUT:
!积分 - 积分结果
! nint - 实现精度的间隔数量
!===================================== =====================
隐式无
双精度f,a,b,eps,整数
双精度sn, s2n,h,x
整数nint
双精度,参数:: coeff = 1.0 / 15.0!误差估计coeff
整数,参数:: nmax = 1048576!最大间隔数
整数n,i



! (a)+ f(a + h)+ f(a)评估2个区间(3点)的积分bb = (*,*)'a,b,h,sn(in simp)=',a,b,h,sn

! (n <= nmax)
s2n = 0.0
h =(ba)/ dfloat(n)循环多次(从4个区间开始)
n = 4

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 = s2n $ b,那么
积分= s2n + coeff *(s2n-sn)
nint = n
出口
结束$ bn = n * 2
end do
return
end subroutine simpson2

我认为我非常接近解决方案,但我无法弄清楚......
如果我在不将参数放入F_int中的情况下致电simpson2(F_int,..),我会收到以下消息:

 调用simpson2(F_int,rmin,rb,eps,integral,nint)
1
警告: (1)

的参数'f'有帮助吗?
在此先感谢!

解决方案

现在您有了一个可以使用的代码,做得很好!



您需要告诉编译器, F_int 是一个函数。这可以通过

 外部F_int 

$来完成b
$ b

,但学习Fortran 90并使用模块或至少使用接口块会更好。

  module my_functions 

implicit none

包含


子程序func(x,y,res)
! - ---------------------------------------
!实数函数
!----------------------------------------
隐式无
双精度res
双精度,意图(in):: x
双精度y
res = 2.0 * x + y
写(* *)'f(x,y)(in func)=',res
return
end子程序func


函数F_int(x)
!函数集成

隐式无
双精度F_int,res
双精度,意图(in):: x
双精度y
调用func (x,y,res)
F_int = res
end function F_int

end module

现在您可以轻松使用该模块并集成该功能

pre $ $ $ $ c $ use my_functions

call simpson2(F_int,rmin,rb,eps,integral,nint)

但是你会发现 F_int 仍然不知道 y 是什么!它有它自己的 y ,其中未定义的值!您应该将 y 放入模块中,以便每个人都可以看到它。

  module my_functions 

隐式无

双精度:: y

包含

不要忘记删除 y 的所有其他声明!在函数 F_int 和主程序中。也许最好以不同的方式来调用它。



不要忘记在里面设置 y 的值你的主循环!

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.

The problem is that the Simpson subroutine only accept f(x) to perform the integral and not f(x,y).

After Vladimir suggestions I modified the code.

Below the example:

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

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!

You need to tell the compiler, that F_int is a function. That can be done by

external F_int

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)

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

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.

Don't forget to set the value of y somewhere inside your main loop!

这篇关于功能更多的参数和整合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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