fortrangfortranfortran90fortran77

Fortan code for Monte Carlo Integration within boundary point a and b


I understand Monte carlo simulation is for estimating area by plotting random points and calculating the ration between the points outside the curve and inside the curve.

I have well calculated the value of pi assuming radius of curve to be unity.

Here is the code

program pi
implicit none

integer :: count, n, i
real :: r, x, y
count = 0
n=500
CALL RANDOM_SEED
DO i = 1, n
 CALL RANDOM_NUMBER(x)
 CALL RANDOM_NUMBER(y)
 IF (x*x + y*Y <1.0) count = count + 1
END DO
r = 4 * REAL(count)/n
print *, r
end program pi

But to find integration , Textbook says to apply same idea. But I'm lost on How to write a code if I want to find the integration of

f(x)=sqrt(1+x**2) over a = 1 and b = 5

Before when radius was one, I did assume point falling inside by condition x*2+y**2 but How can I solve above one?enter image description here

Any help is extremely helpful


Solution

  • I will write the code first and then explain:

    Program integral
    implicit none
    real f
    integer, parameter:: a=1, b=5, Nmc=10000000   !a the lower bound, b the upper bound, Nmc the size of the sampling (the higher, the more accurate the result)
    real:: x, SUM=0
    
    do i=1,Nmc                  !Starting MC sampling
      call RANDOM_NUMBER(x)     !generating random number x in range [0,1]
      x=a+x*(b-a)               !converting x to be in range [a,b]
      SUM=SUM+f(x)              !summing all values of f(x). EDIT: SUM is also an instrinsic function in Fortran so don't call your variable this, I named it so, to illustrate its purpose
    enddo
    
    print*, (b-a)*(SUM/Nmc)     !final result of your integral
    end program integral
    
    function f(x)           !defining your function
      implicit none
      real, intent(in):: x
      real:: f
    
      f=sqrt(1+x**2)
    end function f
    

    So what's happening:

    The integral integ can be written as integ2. where:

    g(x)

    (this g(x) is a uniform probability distribution of the variable x in [a,b]). And we can write the integral as:

    inter3

    where this.

    So, finally, we get that the integral should be:

    final

    So, all you have to do is generate a random number in the range [a,b] and then calcualte the value of your function for this x. Then do this lots of times (Nmc times), and calculate the sum. Then just divide with Nmc, to find the average and then multiply with (b-a). And this is what the code does.

    There's lots of stuff on the internet for this. here's one example that visualizes it pretty nice

    EDIT: Second way, that is the same as the Pi method:

    Nin=0                    !Number of points inside the function (under the curve)
    do i=1,Nmc
      call random_number(x)
      call random_number(y)
      x=a+x*(b-a)
      y=f_min+y(f_max-f_min)
      if (f(x)<y) Nin=Nin+1
    enddo
    print*, (f_max-f_min)*(b-a)*(real(Nin)/Nmc)
    

    All of this, you could then enclose it in an outer do loop summing the (f_max-f_min)(b-a)(real(Nin)/Nmc) and in the end printing its average. For this example, what you do is essentially creating an enclosing box from a to b (x dimension) and from f_min to f_max (y dimension) and then doing a sampling of points inside this area and counting the points that are in the function (Nin).Obviously you will have to know the minimum (f_min) and maximum (f_max) value of your function in the range [a,b]. Alternatively you could use arbitrarily low/high values for your f_min f_max but then you will be wasting a lot of points and your error will be bigger.