DO loop increment problem in Fortran - fortran

I have a problem while using a do loop in fortran,
REAL W,V,X
DO 50 W = 0.5,5.0,0.5
DO 50 V = 10.0,1000.0,10.0
DO 50 X = 1.0,10,1.0
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END
If I gave this it is showing that only integers needs to be used in do loop, is there any way to give integers in do loop or any other way to do it?

Use integers as your looping indices
REAL W,V,X
INTEGER I,J,K
DO 50 I = 1,10
DO 50 J = 1,100
DO 50 K = 1,10
W = 0.5 * I
V = 10.0 * J
X = 1.0 * K
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END

You should be able to accomplish the same thing by incrementing a real variable by adding your step value, and using an if then to exit the loop. Clunky, but should work.
The last time I programmed in Fortran, I used punch cards and an IBM-360, so I'm not going to pretend I remember the syntax.

Related

Problems with do while implementation

I am having problems with a do while implementation for a sine taylor series. Editing the do loop to do bb = 1, 10 , 2 gives an expected result well within the margin of error, however when running the desired implementation of the do loop (do while(abs(sineseries) - accuracy > 0), will always give an answer equal to 1. So I have narrowed the possibilities down to the do while loop implementation being faulty.
program taylor
implicit none
real :: x
real :: sineseries, nfactsine
real, parameter :: accuracy = 1.e-10
integer :: signum, bb
nfactsine = 1
signum = 1
write(*,*) "Write your input value"
read(*,*) x
sineseries = 0
do while(abs(sineseries) - accuracy > 0)
sineseries = sineseries + (signum*x**bb)/nfactsine
nfactsine = nfactsine*(bb+1)*(bb+2)
signum = -signum
end do
write(*,*) sineseries, sin(x)
end program taylor
The two types of loops are not doing the same thing.
In the loop
do bb=1, 10, 2
...
end do
you have loop control with variable bb. This variable takes the values 1, 3, ..., 9 at iterations as the loop proceeds.
The do while does not have this control: you must replicate the increment of bb manually:
bb=1
do while (...)
...
bb=bb+2
end do
As Pierre de Buyl commented, you also have an error in the termination condition for the indefinite iteration count. The condition initially evaluates as false, so the loop body isn't executed even once.

Code to Sum up the first 1234 multiples of 3 and 5 does not print anything

I'm trying to write some Fortran 90 code to sum up the first 1234 multiples of 3 and 5 (including multiples of both). Here is my code so far:
program sum
implicit none
integer :: x
integer :: y = 5
integer :: z = 3
integer :: n
if (mod(x,y) == 0 .or. mod(x,z) ==0) then
print *, x
n = x
n = x + x
end if
end program sum
However, this code does not print anything to the terminal.
Your code tests the value of x in the if condition:
if (mod(x,y) == 0 .or. mod(x,z) ==0
but the value of x is not set at all. Therefore the result of the program is completely undefined. You need to create some kind of loop. Better two loops.
The most naive approach is to loop from 1 and test all numbers with the above if condition and stop when you have found the desired number of multiples.

Monte Carlo using Fortran

I am attempting to do a Monte Carlo simulation using RANDOM_NUMBER. I am using gFortran. I want to perform the following:
Calculate monteNum (fixed number) and generate a random number, monteTest.
If monteNum >= monteTest, then generate another random number randPos which is used to select a row from an array.
Otherwise, generate a new monteTest until step 2 is satisfied.
Firstly, I tried to use a DO loop.
CALL RANDOM_SEED()
monteNum = (count_up + count_dn)/(nReal**2) ! This is just a number in [0,1].
DO i = 1, 100
CALL RANDOM_NUMBER (monteTest)
! monteTest is a randomly generated number used in Monte Carlo simulation
IF (monteNum >= monteTest) THEN
CALL RANDOM_NUMBER (randPos)
! randPos will be used to select one flippable position randomly
Vpos = INT(randPos*count)
! position of the chosen vertex; count is the length of fList
flipVertex(1,:) = fList(Vpos,:)
ELSE
i = i+1
END IF
END DO
An error arises from the ELSE statement. Since it is not known that the IF statement will produce TRUE in 100 loops, I thought a DO WHILE was a better choice.
monteTest = 0.5 ! Setting the initial value. But ideally it should be random
DO WHILE (monteNum < monteTest)
CALL RANDOM_NUMBER (monteTest)
CALL RANDOM_NUMBER (randPos)
Vpos = INT(randPos*count)
flipVertex(1,:) = fList(Vpos,:)
END DO
But it didn't work either.
The problem is that randPos is always zero for initial monteTest = 0.2 and randPos = 5.35517931E-03 for initial monteTest = 0.5. Here, the correct value of monteNum is 0.22222.
I was expecting outputs to change every time I run it, but I am getting the same output every time. Why would that be? Am I using the RANDOM_NUMBER in a wrong way?
Any help would be appreciated!
In Fortran it is forbidden to (try to) update the index variable inside a loop. So the lines
DO i = 1, 100
...
ELSE
i = i+1
END IF
won't compile.
As for your second snippet, I see no syntax errors, explain what you mean by it didn't work.

How to exit "repeat until loop" in fortran?

I have defined two 2D arrays h and hh.I want to assign hh with new values. For a specific k', I want hh(k',j)=1, if the condition
h(k',j)>0
is true; and once the condition is false, i.e., h(k',j')<0, then for any j>j', hh(k',j)=0. I used the following DO WHILE loop:
do k=1, npair
do j =1, movie
hh(k,j)=0.0
enddo
enddo
do k=1, npair
do j =1, nmovie
do while (h(k,j)>0)
hh(k,j)=h(k,j)
enddo
enddo
But if the condition (h(k,j)>0) is always true, there will be a infinite loop! Could you please suggest how can implement it?
It seems to me that you can set each value of hh given the value of h. I'm also assuming hh and h are the same size. So you should do something for each element in hh. I recommend the following:
do k=1,N1 ! N1 and N2 are the limits of the hh and h array.
do j=1,N2
if ( h(k,j) > 0) then ! Check the condition for a specific element in h
hh(k,j) = 1
else
! -- We need to set *all* values in the desired range
hh(k,j:N2) = 0
! -- And we need to stop loop from overwriting values hh(k,j+1), for example
! -- So we break out of the j loop
exit
endif
enddo
enddo
You should check to make sure this does what you think it will. Note that I'm using colon notation to assign a range of values in the hh array.
Also, you're unclear on what happens if h(k,j) is 0 exactly.

Fortran Error: Unexpected STATEMENT FUNCTION statement at (1)

I'm doing a fortran code to find the radial distribution function (RDF) with hard spheres in a cell model.
It's not finished yet, and now I have an error. I'm implementing the histogram. This is my code.
implicit double precision (a-h,o-z)
parameter(npart=3000)
dimension x(0:npart),y(0:npart),z(0:npart)
c n=Number of particules
c rcel=Radius of the cell
c rpart=Radius of the particules
pi=3.1415927
write(*,*)'n,rcel,rpart,dr?'
read(*,*)n,rcel,rpart,dr
write(*,*)'nstep,dp'
read(*,*)nstep,dp
rpart2=(2*rpart)
nfatmax=rcel/dr ! Number of bins
vtotal=(4/3)*pi*rcel*rcel*rcel
dentotal=n/vtotal
write(*,*)'Density of particles, volume and bins = '
write(*,*)dentotal,vtotal,nfatmax
x(0)=0
y(0)=0
z(0)=0
write(*,'(a,/)')'Generating start configurations'
counter1=0
counter2=0
counter3=0
k=0
do i=1,n
21 xx=rcel*(ran()-0.5)*2
yy=rcel*(ran()-0.5)*2
zz=rcel*(ran()-0.5)*2
rr=xx**2+yy**2+zz**2
dist=sqrt(rr)
if(dist.gt.(rcel-rpart2))then !Avoid particles outside the cell
counter1=counter1+1
go to 21
end if
if(dist.lt.rpart2)then ! Avoid overlap with central particle
counter2=counter2+1
go to 21
end if
if(i.ge.1)then
do j=1,i-1,1
sep2=(x(i)-x(j))**2+(y(i)-y(j))**2+(z(i)-z(j))**2
sep=sqrt(sep2)
if(sep.lt.rpart2)then
counter3=counter3+1
go to 21
end if
end do
end if
k=k+1
x(k)=xx
y(k)=yy
z(k)=zz
end do
write(*,*)'Starting config'
write(*,'(3f8.3)')(x(i),y(i),z(i),i=1,n)
counterA=counter1+counter2+counter3
write(*,*)'Rejection = '
write(*,*)counterA
c Monte Carlo loop
counter4=0
counter5=0
counter6=0
do i = 1,nfatmax
h(i) = 0 !!!! Error here!!!!!!
end do
nobs = 0
naccept = 0
do i=1,nstep
do j=1,n
nobs = nobs + 1
xil=x(j)+dp*(ran()-0.5)
yil=y(j)+dp*(ran()-0.5)
zil=z(j)+dp*(ran()-0.5)
r2=(xil**2)+(yil**2)+(zil**2)
r=sqrt(r2)
if(r.gt.(rcel-rpart2))then
counter4=counter4+1
go to 444 ! Avoid particles outside the cell
end if
if(r.lt.rpart2)then
counter5=counter5+1
go to 444 ! Avoid overlap with central particle
end if
do ii=1,j-1
dist2=(x(ii)-xil)**2+(y(ii)-yil)**2+(z(ii)-zil)**2
dist=sqrt(dist2)
if(dist.lt.rpart2)then
counter6=counter6+1
go to 444 ! Avoid overlap wit particles
end if
end do
c Accepted configuration
x(j)=xil
y(j)=yil
z(j)=zil
naccept = naccept + 1
c Rejected configuration
444 continue
do jj=1,n
dist2=(x(jj))**2+(y(jj))**2+(z(jj))**2
dist=sqrt(dist2)
k=(dist/dr)+1
h(k) = h(k)+1 !!!!!!!! Error here!!!!!!!!!
end do
enddo
end do
write(*,*)'Final config'
write(*,'(3f8.3)')(x(j),y(j),z(j),j=1,n)
counterB=counter4+counter5+counter6
write(*,*)'Rejection ='
write(*,*)counterB
stop
end
In your code, h is not declared...
From
do i = 1,nfatmax
h(i) = 0
end do
I assume it should be an array of length nfatmax:
dimension h(nfatmax)
As stated in High Performance Mark's comment, you could have found this error by using implicit none...
I see you dimensioning x, y and z but I see no such beastie for h.
Perhaps you might want to create the array before trying to put values into it.