2016-07-12 2 views
1

간단한 문제가 있지만 어디서나 솔루션을 찾을 수 없습니다. 함수를 통합해야합니다 (예 : Simpson의 규칙 서브 루틴 사용).하지만 하나 이상의 인수에 함수를 전달해야합니다. 하나는 나중에 통합하려는 변수이고 다른 하나는 함수에서 오는 값입니다. 내가 함수 안에서 수행 할 수없는 다른 계산.더 많은 인수와 통합 기능이 있습니다.

Simpson 서브 루틴은 f (x) 만 받아 들여 f (x, y)가 아닌 적분을 수행 할 수 있습니다.

블라디미르 제안 후에 코드를 수정했습니다.

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 

내가 솔루션에 아주 가까이 있어요하지만 난에 인수를주지 않고 simpson2 (F_int ..)를 호출하면 내가 ... 그것을 알아낼 수 있다고 생각 : 예 아래

F_int 다음 메시지가 나타납니다.

call simpson2(F_int,rmin,rb,eps,integral,nint) 
       1 
Warning: Expected a procedure for argument 'f' at (1) 

어떤 도움이 필요합니까? 미리 감사드립니다.

+3

비슷한 질문이 많이있었습니다. 먼저 읽어보십시오. http://stackoverflow.com/questions/24127313/passing-external-function-of-multiple-variables-as-a-function-of-one- variable-in? noredirect = 1 & lq = 1 http://stackoverflow.com/questions/26297170/fortran-minimization-of-a-function-with-additional-arguments http://stackoverflow.com/questions/37714406/implementing- 익명 - 기능 - 포트란? noredirect = 1 & lq = 1 http://stackoverflow.com/questions/24391991/in-fortran-90-how-do-i-program-the-equivalent-of-a-handle-in -matlab? noredirect = 1 & lq = 1 –

+0

더 많은 것들이 있습니다. 링크 된 각 질문에서 "관련"및 "링크 된"열을 참조하십시오. –

+0

힌트를 가져 주셔서 감사합니다. 그러나 저는 여전히 그것을 얻지 못합니다 ... 나는 프로 시저 g (x, y)를 호출하는 다른 함수 F (x)를 만들었지 만, 심슨 루틴에 F를 주려고 할 때 (이것은 함수가 1 개의 인수 만있는 경우)이 메시지가 표시됩니다. (1)에서 인수 'f'에 대한 프로 시저가 필요합니다.나는 f (r)로 simpson을 호출하려고 시도했지만 컴파일은되지만 세그먼테이션 오류가 발생합니다 : 11 – Syph

답변

3

이제 작업 할 수있는 코드가 있습니다!

컴파일러에게 F_int이 기능이라고 말해야합니다. 즉

external F_int 

에 의해 수행하지만, 포트란 90 및 사용 모듈 또는 적어도 인터페이스 블록을 배울 훨씬 더 할 수 있습니다.

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 

지금 당신은 쉽게 모듈을 사용하고 기능

use my_functions 

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

을 통합하지만 당신은 F_int 여전히 y가 무엇인지하지 않는 것을 발견 할 수 있습니다! 정의되지 않은 값을 가진 자신의 y입니다! 모든 사람이 볼 수 있도록 대신 y을 모듈에 넣어야합니다.

module my_functions 

    implicit none 

    double precision :: y 

contains 

y의 다른 선언을 모두 삭제해야합니다. 기능이 모두 F_int이고 주 프로그램에 있습니다. 아마도 다르게 호출하는 것이 좋습니다.

메인 루프 내부에 y의 값을 설정하는 것을 잊지 마세요!

+0

Vladuimir 대단히 감사합니다 !! 이제 작동합니다! 그리고 내 실제 코드에서는 이미 모듈을 광범위하게 사용하므로 더 좋습니다! – Syph

관련 문제