Why is fortran not computing correctly? - fortran

program partOne
integer hit, i
real x, y, equation, finalE, compE, finalHit
parameter (pi = 3.1415926535)
c This program computes pi using the Monte Carlo method
do 10 i = 1, 1000000
x = rand()
y = rand()
equation = sqrt((x*x) + (y*y))
if (equation .LE. 1.0) hit = hit + 1
10 continue
write(*,*) 'hits = ', hit
finalHit = hit
write(*,*) 'finalHits = ', finalHit
finalE = ((finaHit/1000000) * 4)
write(*,*) 'pi = ', pi
write(*,*) 'Computed pi = ', finalE
END PROGRAM partOne
Why does finalE not calculate correctly? Everything seems to assign correctly, but when the equation is done it comes out completely wrong. It should be close to pi.
Updated:
program partOne
integer hit, i
real x, y, equation, finalE, compE, finalHit
parameter (pi = 3.1415926535)
c This program computes pi using the Monte Carlo method
hit = 0
do 10 i = 1, 1000000
x = rand()
y = rand()
equation = sqrt((x*x) + (y*y))
if (equation .LE. 1.0) hit = hit + 1
10 continue
write(*,*) 'hits = ', hit
finalHit = hit
write(*,*) 'finalHits = ', finalHit
finalE = ((finaHit/1000000.0) * 4.0)
write(*,*) 'pi = ', pi
write(*,*) 'Computed pi = ', finalE
END PROGRAM partOne
Results after update:
hits = 785524
finalHits = 785524.00
pi = 3.1415927
Computed pi = -5.21399923E+23

hit = hit + 1. hit can be initialized to 0 or some other value depending on your compiler and other options. Add hit = 0 before the loop where you increment it.
finalE = ((finaHit/1000000) * 4) should be finalE = ((finalHit/1000000.0) * 4.0). finaHit is not defined so change it to finalHit. real values should be multiplied and added to real values, add the .0 to make them real.
Making these changes:
$ a.out
hits = 785524
finalHits = 785524.000
pi = 3.14159274
Computed pi = 3.14209604

Related

Unhandled exception at 0x001D6653 in Lid.exe: 0xc0000094: integer division by zero

I am trying to write the code for Lid-Driven Cavity in Fortran.
When I want to run the code, suddenly the integer division by zero errors appears.
I know what is the problem but I don't know how I can solve it. I even changed some numbers in order to avoid this issue but again happened.
I uploaded the photo of the error
I searched about it and there are some answers for C++ but I could not find anything for Fortran.
Program Lid
implicit none
Integer :: I,J,nx, ny, dx, dy, L, W, Iteration, Max_Iteration , Re, M, N, dt
Real :: Delta
Real, allocatable :: u(:,:), v(:,:), p(:,:), u_old(:,:), v_old(:,:), p_old(:,:), X(:), Y(:)
!***************************************************!
PRINT *, "ENTER THE DESIRED POINTS ..."
PRINT *, "... IN X DIRECTION: SUGGESTED RANGE (20-200)"
READ*, M
PRINT *, "... IN Y DIRECTION: SUGGESTED RANGE (10-100)"
READ*, N
! Define Geometry
dt = 0.001
Delta = 2
Re = 100
L = 10
W = 10
dx = L /Real(M-1)
dy = W /Real(N-1)
ALLOCATE (X(M),Y(N),u(M,N),u_old(M,N),v(M,N),v_old(M,N),p(M,N),p_old(M,N))
! Grid Generation
Do I = 1, M
x(I) = (I-1)* dx
End Do
Do J=1 , N
y(J) = (J-1) * dy
End Do
! Boundray Condition
Do I=1 , M
u(I,1) = 0
u(1,I) = 0
u(M,I) = 0
u(I,M) = 1 ! Lid Velocity
End Do
Do J=1, N
v(J,1) = 0
v(1,J) = 0
v(J,N) = 0
v(M,J) = 0
End Do
! Initialization
Do I=2, M-1
Do J=2, N-1
u(I,J) = 0
v(I,J) = 0
p(I,J) = 0
End Do
End Do
! Solver
Do I=2, M-1
Do J=2, N-1
u_old(I,J) = u(I,J)
v_old(I,J) = v(I,J)
p_old(I,J) = p(I,J)
u(I,J) = - dt / 4* dx * (( u(I, J+1)+ u_old(I,J))**2 - (u_old(I, J)+u(I,J-1))**2) - dt / 4* dy * ((u_old(I,J)+ u(I-1,J)) &
* (v(I-1,J) + v(I-1, J+1)) - (u_old(I,J) + u(I+1,J)) * (v_old(I,J) + v(I,J+1))) - dt / dx *(p(I, J+1) - p(I,J)) &
+ dt / Re * ((u(I+1,J) - 2 * u_old(I,J) + u(I-1,J)) / dx**2 + (u(I,J+1) - 2 * u_old(I,J) + u(I,J+1)) / dy**2) + u_old(I,J)
v(I,J) = - dt / 4* dy * (( v(I-1, J)+ v(I-1,J+1))**2 - (v_old(I, J)+v(I,J+1))**2) - dt / 4* dx * ((u_old(I,J)+ u(I,J+1)) &
* (v(I,J+1) + v(I-1, J+1)) - (u_old(I,J) + u(I,J-1)) * (v_old(I,J) + v(I-1,J))) - dt / dy *(p(I, J+1) - p(I,J)) &
+ dt / Re * ((v(I+1,J) - 2 * v_old(I,J) + v(I-1,J)) / dx**2 + (v(I,J+1) - 2 * v_old(I,J) + v(I,J+1)) / dy**2) + v_old(I,J)
p(I,J) = - Delta * dt / 2 * ((u(I,J+1)+ u_old(I,J)) - (u_old(I,J) + u(I,J-1))) - Delta * dt / 2 &
* ((v(I-1,J)+ v(I-1,J+1)) - (v_old(I,J) + v(I,J+1)))
End Do
End Do
!-----------------------OUTPUTS GENERATION-----------------------------
OPEN (1,FILE='FIELD.PLT')
WRITE (1,*) 'VARIABLES=X,Y,u,v,p'
WRITE (1,*) 'ZONE I=',M,' J=',N
DO J=1,N
DO I=1,M
WRITE (1,*) X(I),Y(J),u(I,J),v(I,J),p(I,J)
END DO
END DO
End Program Lid
Assuming that the yellow arrow shown on the image indicates the line (72) where the exception occurred:
Apparently dx is or becomes zero, because that's the only devision done on that line.
You must know what it means when dx is zero or what causes it, unless it's a programming or data input issue that causes it.
In any case you must make sure that you don't execute that part of your code that divides by zero.
What you need to do to prevent this, fully depends on what your code is supposed to do. I can't help you with that.

N-body simulation on Fortran leap frog algorithm

I am using a simple 'leapfrog algorithm I am aiming to simulate the orbits of the earth a Jupiter around the sun. I am unable to get them to orbit despite being fairly sure the maths is correct. It appears that gravity is acting too weekly and the planet merely floats away from the sun, interestingly if I adjust the Newtonian acceleration due to gravity term by multiplying it by rad2 I find that the system does indeed produce fairly stable orbits but at much much too large radii.
program physim
Implicit none
integer :: i,j,n,day ! Integer variables
doubleprecision :: G , r(1:3,1:10) , a(1:3, 1:10) , v(1:3, 1:10) , m(1:3), dt, Au, dr(1:3),
rad2(1:3), t, tcount, tend, tout
! constants
day = 86400
tout = 10*day
tend = 20*day
Au = 15e11
n = 3
G = 6.67e-11
!n = 2
dt = 100
!sun
r(1,1) = 0.
r(2,1) = 0.
r(3,1) = 0.
v(1,1) = 0.
v(2,1) = 0.
v(3,1) = 0.
m(1) = 1.9898e30
!earth
r(1,2) = Au
r(2,2) = 0.
r(3,2) = 0.
v(1,2) = 0.
v(2,2) = 30000
v(3,2) = 0.
m(2) = 6e24
!jupiter
r(1,3) = 5.2*Au
r(2,3) = 0.
r(3,3) = 0.
v(1,3) = 0.
v(2,3) = 13070
v(3,3) = 0.
m(3) = 2e27
do
a = 0
tcount = 0
do i = 1, n
do j = 1, n
!calculating acceleration
if (i==j)cycle
dr(1:3) = r(1:3, j) - r(1:3, i)
rad2 = dr(1)**2 + dr(2)**2 + dr(3)**2
a(1:3, i) = a(1:3, i) + G*m(j)*dr(1:3)/(rad2*sqrt(rad2))
end do
end do
do i = 1, n
r(1:3 ,i) = r(1:3, i) + v(1:3, i)*dt
v(1:3, i) = v(1:3, i) + a(1:3, i)*dt
end do
t = t + dt
tcount = t + dt
if(tcount>tout) then
!write(6,*) a(1,2)
!write(6,*) rad2
write(6,*) a(1,1) , a(2,1), a(3, 2)
end if
end do
end program
Your most fundamental problem was that 1 A.U. = 1.5e11 m, not 15e11. Then you were doing stuff like resetting tcount every trip through the loop. Set it before the start of the main loop and then only reset when you print out a line of output. It should be updated as tcount=tcount+dt and then you probably want to print out r(1,2) , r(2,2), r(1,3) , r(2,3) so you can plot the positions of jupiter and earth. Also you should maybe go for more time so you can see a few full orbits of earth, and finally put a test at the bottom of the loop so it will exit when t>tend. Making these changes I got output that looked like this:

Fortran NBody sim code won't run for high year values

The program is as follows.
The issue occurs when I try to run the code for >~80 years, at which point the code apparently 'runs' instantly, generating an empty text file. The code runs fine for smaller timescales.
PROGRAM NBody
IMPLICIT NONE
DOUBLE PRECISION:: m(1:10), deltaR(1:3)
DOUBLE PRECISION:: G, r
DOUBLE PRECISION, DIMENSION(10,3):: pos, v, a0, a1 !x, y, z
INTEGER:: n,i,j,k,stepsize, year, zero, length
CHARACTER(len=13):: fname !xxxyrxxpl.txt
zero = 0
m(1) = 1988500e24 !sun
m(2) = 0.33e24 !mercury
m(3) = 4.87e24 !venus
m(4) = 5.97e24 !earth
m(5) = 0.642e24 !mars
m(6) = 1898e24 !jupiter
m(7) = 568e24 !saturn
m(8) = 86.8e24 !uranus
m(9) = 102e24 !!neptune
m(10) = 0.0146e24 !pluto
!Initial POS
pos = zero
pos(2,1) = 57.9e9
pos(3,1) = 108e9
pos(4,1) = 149e9
pos(5,1) = 227e9
pos(6,1) = 778e9
pos(7,1) = 1352.6e9
pos(8,1) = 2741.3e9
pos(9,1) = 4444.5e9
pos(10,1) = 4436.8e9
!FORTRAN works column,row: (particle,x/y/z)
!Momentum is initially non-zero due to planet and velocity starting points. Figure out a solution.
!Initial velocity
v = zero
v(2,2) = 47.4e3
v(3,2) = 35e3
v(4,2) = 29.8e3
v(5,2) = 24.1e3
v(6,2) = 13.1e3
v(7,2) = 9.7e3
v(8,2) = 6.8e3
v(9,2) = 5.4e3
v(10,2) = 4.7e3
g = 6.67e-11
stepsize = 1800 !3600 = 1 hour
year = 3.154e+7
!Calculate initial values
a0 = 0
a1 = 0
do i = 1,10
do j = 1,10
if(i==j) cycle
deltaR(:) = (pos(i,:)-pos(j,:))
r = -sqrt((pos(i,1)-pos(j,1))**2+(pos(i,2)-pos(j,2))**2+(pos(i,3)-pos(j,3))**2)
a0(i,:) = a0(i,:) + g*M(j)*deltaR*r**(-3)
END DO
END DO
write(6,*) "Specify length in years"
read (*,*) length
write(6,*) "Specify file name (xxxYRzzPL.txt)"
read(*,*) fname
!Just above is where I call for a length in the terminal, values of 40 will work, much higher do not. I don't know the exact cut-off.
open (unit = 2, file = fname)
!Do loop over time, planet and partners to step positions
do k=0, length*year,stepsize
write(2,*) pos
pos = pos + v*stepsize + 0.5*a0*stepsize**2
do i = 1,10
do j = 1,10
if(i==j) cycle
deltaR(:) = (pos(i,:)-pos(j,:))
r = -sqrt((pos(i,1)-pos(j,1))**2+(pos(i,2)-pos(j,2))**2+(pos(i,3)-pos(j,3))**2)
a1(i,:) = a1(i,:) + G*M(j)*deltaR/r**3
END DO
END DO
v = v + 0.5*(a0+a1)*stepsize
a0=a1
a1=0
END DO
close (2)
END PROGRAM
I suspected it could be an issue with variable storage but I can't see any problems there.
Using an iterator like this can be dubious. Even an 8 byte integer will overflow if you go long enough. Considering how this code is set up, I would do something like this:
do iYear = 1, length
do k = 0, year, stepsize
....
enddo
enddo
Inner do loop loops over one year. Outer do loop loops over the years. Could go Gigayears like this with just 4 byte integers if you want to wait that long.
I would likely rename your variables too to make more sense. This would look better:
do iYear = 1, nYears
do k = 0, YearLength, stepsize
....
enddo
enddo
Expanding on #francescalus, you may need to specify your integers as 8-bytes rather than the default 4:
integer, parameter :: c_int8 = selected_int_kind (10)
integer(kind = c_int8) :: n,i,j,k,stepsize, year, zero, length
EDIT I added a parameter to determine the correct value for a 64-bit integer intrinsically.

How to calculate Pi using Monte Carlo Simulation?

I'm attempting to write a FORTRAN 90 program that calculates Pi using random numbers. These are the steps I know I need to undertake:
Create a randomly placed point on a 2D surface within the range [−1, 1] for x and y, using call random_number(x).
calculate how far away the point is from the origin, i'll need to do both of these steps for N points.
for each N value work out the total amount of points that are less than 1 away from origin. Calculate pi with A=4pir^2
use a do loop to calculate pi as a function of N and output it to a data file. then plot it in a graphing package.
This is what I have:
program pi
implicit none
integer :: count, n, i
real :: r, x, y
count = 0
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
I know i've missed out printing the results to the data file, i'm not sure on how to implement this.
This program gives me a nice value for pi (3.149..), but how can I implement step 4, so that it outputs values for pi as a function of N?
Thanks.
Here is an attempt to further #meowgoesthedog effort...
Program pi
implicit none
integer :: count, n, i
real :: r, x, y
count = 0
Integer, parameter :: Slice_o_Pie = 8
Integer :: Don_McLean
Logical :: Purr = .FALSE.
OPEN(NEWUNIT=Don_McLean, FILE='American.Pie')
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
Purr = .FALSE.
IF(MODULO(I, Slice_o_Pie) == 0) Purr = .TRUE.
IF (Purr) THEN
r = 4 * REAL(count)/i
print *, i, r
WRITE(LUN,*) 'I=',I,'Pi=',Pi
END IF
END DO
CLOSE(Don_McLean)
end program pi
Simply put the final calculation step inside the outer loop, and replace n with i. Also maybe add a condition to limit the number of results printed, e.g. i % 100 = 0 to print every 100 iterations.
program pi
implicit none
integer :: count, n, i
real :: r, x, y
count = 0
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
IF ([condition])
r = 4 * REAL(count)/i
print *, i, r
END IF
END DO
end program pi

Rutherford scattering experiment error

I'm very new to Fortran and have to simulate the Rutherford Scattering experiment for an assignment. In the code, there is a gold nucleus assumed to be at the center (x,y) = (0,0). I'm trying to find the acceleration, velocity and then distance of the alpha particle based on the Coloumb's Law. r_lim is meant to be the boundary condition which, when the particle passes, the loop is meant to stop successfully. Please let me know if I can explain anything else.
PROGRAM rutherford_scatter
IMPLICIT NONE
TYPE particle
REAL:: x,y
END TYPE particle
TYPE(particle):: r_alpha, v_alpha, a_alpha
REAL:: x_0,y_0, v_0, q_gold, q_alpha, k_e, m_alpha, c, c_frac, time_step, r_lim
LOGICAL :: check = .FALSE.
k_e = 1.0
c = 137.053999
time_step = 1.0 *10.0**(-5.0)
q_alpha = 2.0
q_gold = 79.0
m_alpha = 7294.3
WRITE (*,*) 'Enter initial value for x distance.'
READ (*,*) x_0
y_0 = -0.005
WRITE (*,*) 'Enter initial value for velocity (fraction of speed of light).'
READ (*,*) c_frac
v_0 = c_frac * c
r_alpha%x = x_0
r_alpha%y = y_0
r_lim = 1.1 * SQRT(r_alpha%x**2+r_alpha%y**2)
v_alpha%x = 0
v_alpha%y = ABS(v_0)
OPEN (11, FILE = 'assign_11.out')
DO WHILE (check)
a_alpha = acceleration(k_e, m_alpha, q_gold, q_alpha, r_alpha)
v_alpha = velocity (v_alpha, a_alpha)
r_alpha = distance (r_alpha, v_alpha)
WRITE (11,*) r_alpha
IF (r_alpha%x .GT. r_lim .OR. r_alpha%y .GT. r_lim) THEN
check =.TRUE.
END IF
END DO
CLOSE(11)
CONTAINS
TYPE (particle) FUNCTION acceleration (k_e, m_alpha, q_gold, q_alpha,r_alpha)
TYPE (particle), INTENT(IN):: r_alpha
REAL, INTENT (IN)::k_e, m_alpha, q_gold, q_alpha
acceleration%x = (k_e/m_alpha) * ((q_gold * q_alpha)/(ABS(r_alpha%x))**2 )* (r_alpha%x/SQRT(r_alpha%x**2+r_alpha%y**2))
acceleration%y = (k_e/m_alpha) * ((q_gold * q_alpha)/(ABS(r_alpha%y))**2 )*(r_alpha%y/SQRT(r_alpha%x**2+r_alpha%y**2))
END FUNCTION
TYPE (particle) FUNCTION velocity (v_alpha, a_alpha)
TYPE (particle), INTENT (IN):: a_alpha, v_alpha
velocity%x = v_alpha%x + a_alpha%x*time_step
velocity%y = v_alpha%y + a_alpha%y* time_step
END FUNCTION
TYPE(particle) FUNCTION distance (r_alpha, v_alpha)
TYPE (particle), INTENT (IN):: r_alpha, v_alpha
distance%x = r_alpha%x + v_alpha%x * time_step
distance%y = r_alpha%y + v_alpha%y * time_step
END FUNCTION
END PROGRAM rutherford_scatter