Fortran array Syntax error - syntax

Basically Fortran being vague about some error in my array. it says:
Newton_Interpolation_3D.f90:19.132:
0,-0.65364361d0,0.28366220d0, 0.27015114d0, -0.20807342d0, -0.49499625d0, -
nothing else. I checked my array and it looks fine. Can someone please tell me what's wrong with the xnodes array?
implicit none
double precision, allocatable, dimension(:,:) :: nt
double precision, allocatable, dimension(:) :: znodes, ynodes, xnodes, fval
double precision :: x, evalnewton
integer :: i,n,k
n = 24
allocate(xnodes(0:n), ynodes(0:n), znodes(0:n),fval(0:4) ,nt(0:n, 0:n))
xnodes = (/0.54030228d0 ,-0.41614684d0,-0.98999250d0,-0.65364361d0,0.28366220d0,
0.27015114d0, -0.20807342d0, -0.49499625d0, -0.32682180d0, 0.14183110d0,
0.18010077d0,-0.13871562d0,-0.32999751d0,-0.21788120d0,
9.45540667d0,0.13507557d0,-0.10403671d0,-0.24749812d0,
-0.16341090d0,7.09155500d0,0.10806046d0,-8.32293704d0,
-0.19799851d0,-0.13072872d0,5.67324422d0/)
!ynodes = (/0.84147102,0.90929741,0.14112000,-0.75680250,-0.95892429,0.42073551,0.45464870,7.05600008d-02,-0.37840125,-0.47946215,0.28049034,0.30309916, 4.70400006d-02,-0.25226751,-0.31964144,0.21036775,0.227324353,.52800004d-02,-0.18920062,-0.23973107 , -0.19178486 ,-0.15136050, 0.18185948, 2.82240007d-02 ,0.16829421/)
!znodes = (/ -0.41614693 , -0.65364355 , 0.96017027, -0.14550006, -0.83907157, -0.10403673, -0.16341089, 0.24004257 , -3.63750160d-02, -0.20976789, -4.62385453d-02, -7.26270750d-02, 0.10668559, -1.61666758d-02, -9.32301804d-02, -2.60091834d-02,-4.08527218d-02,6.00106418d-02,-9.09375399d-03,-5.24419732d-02, -1.66458786d-02,-2.61457413d-02,3.84068154d-02,-5.82000241d-03, -3.35628614d-02/)
fval = (/5.63,6.11,8.12,4.33,6.15/)
deallocate(xnodes,ynodes,znodes,nt,fval)

You are missing the free form line continuation sentinel (&) at the end of the lines of statements that continue onto the next line.

Related

Fortran code (.f95) compiles fine in Windows g95 compiler but incorrectly in Ubuntu gfortran

I am trying to compile an .f95 fortran script so it can run on Ubuntu. The script is available here -> Link to zip file containing .f95 script
It compiles and runs fine when I switch over to Windows and compile using g95 compiler. The .exe file produced also runs fine in Ubuntu through wine.
However if I try to compile to make an Ubuntu file, it does not work properly. I don't get a compile error, but if I run the resultant file, either the program gets stuck in an infinite loop, or the output is all wrong. It's difficult for me to see where it is going wrong because I did not write the original code and only have a shaky understanding of Fortran, but it seems to be something to do with the numbers being calculated wrong leading to very large/small/inappropriately negative output (sorry to be so vague).
I am running 16.04 xenial ubuntu and gfortran 5.4.0.
Any help/thoughts appreciated this is driving me up the wall! Thanks
Code below for quick reference:
! Seed dispersal model of of Duman et al. (2015)
! Instructions and expample are found in:
! https://nicholas.duke.edu/people/faculty/katul/research.html
! in 'Library of Functions and Utilities'
! Author: Tomer Duman
! Version: Version 2
! Date: October 22, 2015
! References: Duman, T., Trakhtenbrot, A., Poggi, D.,
! Cassiani, M., Katul, G., Dissipation
! Intermittency Increases Long-Distance
! Dispersal of Heavy Particles in the Canopy
! Sublayer,
! accepcted to Boundary-Layer Meteorology
program LSmodel
implicit none
real :: sec,ran,gasdev ! random generator variables
real :: x,y,z,u,v,w,ut,vt,wt,t,dt ! simulation variables
real :: wg ! seed parametes
real :: Um,sigma_u,sigma_v,sigma_w,uw ! wind statistics variables
real :: dvaru_dz,dvarv_dz,dvarw_dz,duw_dz ! wind statistics variables
real :: dissip_m,TL ! vector over the range of ustars
real :: zs,zg,zmax ! release height & boundaries
real :: Ainv,C0inv ! inverse parameters
real :: C0,A,b,au,av,aw,dt_on_TL ! LS model parameters
real :: dz_max,dt_max ! time step limit
real :: CT,beta ! Crossing Trajectories correction
real :: C_chi,chi,TKE,T_chi,omega ! DI parameters
real :: a_ln,b_ln,sigma_chi,dissip_s ! DI parameters
real :: rhop,rho,r,g,gt,Re,AIP,Cd,nu ! IP parameters
real :: up,vp,wp,upt,vpt,wpt,vr,dt_ip,alpha ! IP parameters
integer :: seed ! random generator variables
integer :: pnum ! simulation parameters
integer :: i,j,jj,n,ii ! counting parameters
integer :: n_ip,IP=1 ! IP parameters
character(len=80) :: filename
real, allocatable,dimension(:) :: z_vec,Um_vec,sigma_u_vec,sigma_v_vec,sigma_w_vec,uw_vec
real, allocatable,dimension(:) :: dvaru_dz_vec,dvarv_dz_vec,dvarw_dz_vec,duw_dz_vec,dissip_m_vec
! setting the random generator seed
seed=7654321
sec=0.0
seed=seed+2*int(secnds(sec))
! input
open (21,file='input_parameters.txt')
read (21, *), x,C0,wg,zs,zg,beta,dt_on_TL,y,sigma_chi,C_chi,r,rhop,alpha,rho,nu
close(21)
pnum = int(x) ! number of released seeds
n = int(y) ! size of the input flow stats
wg = -1.0*wg ! seed terminal velocity [m/s]
!zs ! seed release height [m]
!C0 ! universal constant
!beta ! crossing trajectories parameter
!zg ! ground height [m]
!sigma_chi ! the standard deviation of chi (dissipation intermittency)
!C_chi ! constant for T_chi calc
!r ! particle radium [m] - set to 0 for no IP
!rhop ! particle dry density [kg/m^3]
!alpha ! drag parameter (Cd = 24/Re_p*(1+alpha*Re_p))
!rho ! fluid density [kg/m^3]
!nu ! fluid viscosity [m^2/s]
C0inv = 1.0/C0
g = 9.81
if (r==0.0) then
IP = 0
end if
! limiting parameters to prevent too big jumps in a time-step
dz_max = 0.1
dt_max = 0.1
open(unit=12,file='res.dat', form='formatted')
open(unit=13,file='res_traj.dat', form='formatted')
! allocate
allocate(z_vec(n))
allocate(Um_vec(n))
allocate(sigma_u_vec(n))
allocate(sigma_v_vec(n))
allocate(sigma_w_vec(n))
allocate(uw_vec(n))
allocate(dvaru_dz_vec(n))
allocate(dvarv_dz_vec(n))
allocate(dvarw_dz_vec(n))
allocate(duw_dz_vec(n))
allocate(dissip_m_vec(n))
! load normalized stats
open (22,file='input_flow.txt',form='formatted')
read (22,*) z_vec
read (22,*) Um_vec
read (22,*) sigma_u_vec
read (22,*) sigma_v_vec
read (22,*) sigma_w_vec
read (22,*) uw_vec
read (22,*) dvaru_dz_vec
read (22,*) dvarv_dz_vec
read (22,*) dvarw_dz_vec
read (22,*) duw_dz_vec
read (22,*) dissip_m_vec
close(22)
zmax = z_vec(n)
do i=1,pnum
t=0.0 ! initiate time and location
x=0.0
y=0.0
z=zs
do j=2,n ! interpolate
if ((z>=z_vec(j-1)).and.(z<=z_vec(j))) then
sigma_u=((sigma_u_vec(j-1)-sigma_u_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_u_vec(j-1)
sigma_v=((sigma_v_vec(j-1)-sigma_v_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_v_vec(j-1)
sigma_w=((sigma_w_vec(j-1)-sigma_w_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_w_vec(j-1)
end if
end do
! velocity initiation
u=gasdev(seed)*sigma_u
v=gasdev(seed)*sigma_v
w=gasdev(seed)*sigma_w
chi=sigma_chi*gasdev(seed)-0.5*sigma_chi*sigma_chi
up=0.0 ! initiating particle velocity from rest
vp=0.0
wp=0.0
do ! time loop
do j=2,n ! interpolate
if ((z>=z_vec(j-1)).and.(z<=z_vec(j))) then
Um=((Um_vec(j-1)-Um_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+Um_vec(j-1)
uw=((uw_vec(j-1)-uw_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+uw_vec(j-1)
duw_dz=((duw_dz_vec(j-1)-duw_dz_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+duw_dz_vec(j-1)
sigma_u=((sigma_u_vec(j-1)-sigma_u_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_u_vec(j-1)
sigma_v=((sigma_v_vec(j-1)-sigma_v_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_v_vec(j-1)
sigma_w=((sigma_w_vec(j-1)-sigma_w_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+sigma_w_vec(j-1)
dvaru_dz=((dvaru_dz_vec(j-1)-dvaru_dz_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+dvaru_dz_vec(j-1)
dvarv_dz=((dvarv_dz_vec(j-1)-dvarv_dz_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+dvarv_dz_vec(j-1)
dvarw_dz=((dvarw_dz_vec(j-1)-dvarw_dz_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+dvarw_dz_vec(j-1)
dissip_m=((dissip_m_vec(j-1)-dissip_m_vec(j))/(z_vec(j-1)-z_vec(j)))*(z-z_vec(j-1))+dissip_m_vec(j-1)
end if
end do
CT = sqrt(1.0+beta*beta*wg*wg/sigma_w/sigma_w) ! crossing trajectories correction
TL = 2.0*sigma_w*sigma_w*C0inv/dissip_m/CT ! added CT effect
TKE = 0.5*(sigma_u*sigma_u+sigma_v*sigma_v+sigma_w*sigma_w)
! -------- Adding dissipation intermittency model --------
omega=dissip_m*CT/TKE ! added CT effect
T_chi=1.0/omega/C_chi
dt=min(dt_on_TL*TL,dt_on_TL*T_chi,dt_max)
a_ln = -(chi + 0.5*sigma_chi*sigma_chi)/T_chi
b_ln = sigma_chi*sqrt(2.0/T_chi)
chi = chi+a_ln*dt+b_ln*sqrt(dt)*gasdev(seed)
dissip_s = dissip_m*exp(chi)
! --------------------------------------------------------
A = 2.0*((sigma_u*sigma_u)*(sigma_w*sigma_w)- uw*uw)
Ainv = 1.0/A
b = sqrt(C0*dissip_s*CT) ! added CT effect
au = (b*b)*(uw*w - u*sigma_w*sigma_w)*Ainv + 0.5*duw_dz &
+ Ainv*(sigma_w*sigma_w*dvaru_dz*u*w - uw*dvaru_dz*w*w &
-uw*duw_dz*u*w + sigma_u*sigma_u*duw_dz*w*w)
av = (-(b*b)*v + dvarv_dz*v*w)/2.0/sigma_v/sigma_v
aw = (b*b)*(uw*u - w*sigma_u*sigma_u)*Ainv + 0.5*dvarw_dz &
+ Ainv*(sigma_w*sigma_w*duw_dz*u*w - uw*duw_dz*w*w &
-uw*dvarw_dz*u*w + sigma_u*sigma_u*dvarw_dz*w*w)
ut = u + au*dt + b*sqrt(dt)*gasdev(seed)
vt = v + av*dt + b*sqrt(dt)*gasdev(seed)
wt = w + aw*dt + b*sqrt(dt)*gasdev(seed)
u = ut
v = vt
w = wt
! -------- Adding IP model --------
if (IP==1) then
dt_ip = dt*0.01
n_ip = 100
upt = up
vpt = vp
wpt = wp
100 do ii=1,n_ip
vr = sqrt((u+Um-upt)*(u+Um-upt)+(v-vpt)*(v-vpt)+(w-wpt)*(w-wpt))
if (vr>1000.0) then
dt_ip = dt_ip*0.5
n_ip = n_ip*2
upt = up
vpt = vp
wpt = wp
goto 100
end if
Re = 2.0*r*vr/nu
Cd = 24.0*(1.0+alpha*Re)/Re
AIP = 3.0*rho*Cd/8.0/rhop/r
gt = g*(rhop - rho)/rhop
upt = upt + AIP*vr*(u+Um-upt)*dt_ip
vpt = vpt + AIP*vr*(v-vpt)*dt_ip
wpt = wpt + (AIP*vr*(w-wpt)-gt)*dt_ip
end do
up = upt
vp = vpt
wp = wpt
end if
! ----------------------------------
if (IP==0) then
up = Um+u
vp = v
wp = w+wg
end if
x = x + up*dt
y = y + vp*dt
z = z + wp*dt
if (i<50) then ! saving trajectories of 50 seeds
write(13,*) i,t,x,y,z
end if
if (z>zmax) then
exit
end if
if (z<zg) then
dt = (z-zg)/(w+wg)
z = z - (w+wg)*dt ! ensure that z = zg at landing
x = x - (u+Um)*dt
y = y - v*dt
write(12,*) i,x,y
exit
end if
dt_max = dz_max/abs(w+wg)
t = t+dt
end do
if (mod(i,100)==0) then
print *, 'wg = ',abs(wg),' zr = ',zs,' pp ',pnum-i
end if
end do
end program LSmodel
!***********************************************************************
! This function generates Gaussian Random Deviates from uniform deviates.
! The function is from Press et al. (1992 p. 280).
function gasdev(idum)
implicit none
integer :: idum, iset
real :: gasdev,fac, gset, rsq, v1, v2, ran
save :: iset, gset
data iset/0/
if (iset.eq.0) then
1 v1=2.*ran(idum)-1.
v2=2.*ran(idum)-1.
rsq=v1**2+v2**2
if (rsq.ge.1. .or. rsq .eq. 0) go to 1
fac =sqrt(-2.*log(rsq)/rsq)
gset=v1*fac
gasdev=v2*fac
iset=1
else
gasdev=gset
iset=0
end if
return
end function gasdev
!***********************************************************************
!uniform random generator between 0 and 1
function ran(idum)
implicit none
integer, parameter :: K4B=selected_int_kind(9)
integer(K4B), intent(inout) :: idum
real :: ran
integer(K4B), parameter :: IA=16807,IM=2147483647,IQ=127773,IR=2836
real, save :: am
integer(K4B), save :: ix=-1,iy=-1,k
if (idum <= 0 .or. iy < 0) then
am=nearest(1.0,-1.0)/IM
iy=ior(ieor(888889999,abs(idum)),1)
ix=ieor(777755555,abs(idum))
idum=abs(idum)+1
end if
ix=ieor(ix,ishft(ix,13))
ix=ieor(ix,ishft(ix,-17))
ix=ieor(ix,ishft(ix,5))
k=iy/IQ
iy=IA*(iy-k*IQ)-IR*k
if (iy < 0) iy=iy+IM
ran=am*ior(iand(IM,ieor(ix,iy)),1)
end function ran
The command I am using to compile in Ubuntu is
gfortran LSmodel.f95 -o LSmodel.o
There is no compile error, it compiles fine, but then on running the program afterwards the problems start.
I have included a typical expected output from running the program below (res.dat):
1 21.8583908 8.47351170
2 1.44100714 -8.78142548
3 1154.74109 -265.975677
4 8.41901588 2.71606803
5 84.5189209 -20.4699802
6 86.3176270 -18.4299908
7 133.826874 43.4905090
8 4.37516022 -2.50738835
9 1.31284332 -2.65105081
10 1.96412086 2.85013437
11 4.34823132 -3.83539009
12 40.1227837 -6.60268879
13 3.88699961 2.63749719
14 7.08872795 1.51467562
15 4.72280264 2.63384581
16 0.667112768 1.37209761
17 2.09094667 1.23296225
18 4.72298622 -1.43766475
19 1.04012501 -3.13314247
20 1.91324210 0.957163811
21 1.99065340 0.611227572
22 -2.09086251 -1.41756165
23 -1.46836996 -5.55722380
24 2.41403580 2.18929257E-02
25 3.96990728 -4.91323137
26 1.54687607 -0.527718127
27 8.24332428 -1.48289037
28 4.81600523 -8.87443924
29 2.39538932 0.323360980
30 192.294815 -36.7134209
31 24.6190643 21.7993126
32 -0.124062911 3.44432545
33 16.6237335 -8.54020786
34 50.0964355 -3.29175758
35 5.23409462 2.14592004
36 6.62141275 1.47515869
37 10.7572327 0.307090789
38 63.5973434 -47.7124138
39 74.9621201 2.11509633
40 4.46293068 -1.64074826
41 11.7773390 10.0654907
42 8.26941204 6.84578228
43 0.917451978 2.69560647
44 -2.21521306 15.0752039
45 8.18219483E-02 -2.06250334
46 0.279425710 -3.10328817
47 4.37736464 -1.37771702
48 -2.85058951 -1.79835165
49 5.08391476 2.68537569
50 -4.27199030 -0.642364025
Compiling your program with gfortran -Wall gives
test.f90:297:4:
function ran(idum)
1
Warning: 'ran' declared at (1) is also the name of an intrinsic.
It can only be called via an explicit interface or if declared
EXTERNAL. [-Wintrinsic-shadow]
which means that the user-defined routine ran() has the same name as intrinsic ran() in gfortran. So we need to declare it as an external routine (to tell the compiler that this is a user-defined one):
function gasdev(idum)
implicit none
integer :: idum, iset
real :: gasdev,fac, gset, rsq, v1, v2, ran
save :: iset, gset
data iset/0/
external ran !<--- here
...
It is necessary to include external ran in all routines that utilize the user-defined ran. (In this program, only the gasdev() routine is using it.) To avoid such interference, it is usually better to use a bit more specific name other than ran, rand, etc (for example, rand_uniform() or ranranran() might be good). It would also be very nice if the routine is included in a module to avoid such problems, so please search the net for how to use modules for more details (if necessary...)

Scattering matrix column by column in MPI using Fortran and contiguous datatype

I'm trying to generate a matrix full of random numbers, of dimensions (mysize)x(Np), where Np is a given number (say,5). Mysize comes from the number of processes. And then each processor should take its own column, of size 1xNp.
My first idea was to create a vector data type but then I realized this can be done by using the contiguous data type. The code runs with no errors, but it prints only some of the numbers that were supposed to be there. I'm quite sure the problem lies on the indicators (type_column, MPI_REAL, etc.) and how should they actually be but I can't figure this out. Anyone care to help?
The code:
program main
use mpi
integer :: ierr,myrank,mysize
integer :: Np=5, type_column
integer*8, external :: seedgen
real*8, dimension(:,:), allocatable :: x_init
real*8, dimension(:), allocatable :: block_x
character(4) :: rank
integer, dimension(1) :: new_seed
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,mysize,ierr)
allocate(block_x(0:Np-1))
if (myrank==0) then
allocate(x_init(0:Np-1,0:mysize-1))
new_seed = seedgen(myrank)
write(*,*) new_seed !This is to check if the seed changes each time
call random_seed(put=new_seed)
call random_number(x_init)
open(unit=1111, file='./x_tot.txt')
write(1111,*) x_init
close(1111) !Up to this point, everything works
end if
call MPI_TYPE_CONTIGUOUS(Np,MPI_REAL,type_column,ierr)
call MPI_TYPE_COMMIT(type_column,ierr)
call MPI_SCATTER(x_init(:,myrank),Np,MPI_REAL,block_x,Np,type_column,0,MPI_COMM_WORLD,ierr)
write(rank,'(I4)') myrank
write(*,*) 'I, process ',myrank,' received ', block_x(0:Np-1)
open(unit=myrank, file='./x_teste_'//trim(adjustl(rank))//'.txt')
write(myrank,*) block_x
close(myrank)
call MPI_TYPE_FREE(type_column,ierr)
call MPI_FINALIZE(ierr)
end program main
!!! You may ignore what is down below, just a function to generate random seeds.
function seedgen(myrank)
use iso_fortran_env
implicit none
integer(kind=int64) :: seedgen
integer, intent(IN) :: myrank
integer :: s
call system_clock(s)
seedgen = abs( mod((s*181)*((myrank-83)*359), 104729) )
end function seedgen
The output (after running with 3 processors, thus mysize=3)
I, process 0 received 0.247272870046176
0.386432141459887 8.816221414742263E-316 0.000000000000000E+000
0.000000000000000E+000
I, process 1 received 2.737792569698344E-008
I, process 2 received 5.231628354959370E-002
0.454932876242927 3.330771999738651E-315 0.000000000000000E+000
0.000000000000000E+000
3.352416881721526E+270 5.298272496856962E-315 0.000000000000000E+000
0.000000000000000E+000
The matrix x_tot:
0.247272870046176 0.386432141459887 0.473788032900533
0.239586263133600 0.851724848335892 5.231628354959370E-002
0.454932876242927 0.702720716936168 0.559915585253771
0.605745282251549 0.253298270763062 0.809867899324171
0.590174190311136 0.125210425650182 8.138975171285148E-002
So you can see that some numbers are the good ones, the rest is garbage.
Using MPI_DOUBLE as suggested above and changing the writing as below worked fine. Thanks again
open(unit=myrank, file='./x_teste_'//trim(adjustl(rank))//'.txt')
do i=0,Np-1
write(myrank,*) block_x(i)
end do
close(myrank)

Read and write tab-delimited text data

I have an excel output in the tab-delimited format:
temperature H2O CO2 N2 NH3
10 2.71539E+12 44374931376 7410673406 2570.560804
20 2.34216E+12 38494172272 6429230649 3148.699673
30 2.04242E+12 33759520581 5639029060 3856.866413
40 1.75491E+12 29172949817 4882467457 4724.305292
.
.
.
I need to convert these numbers to FORMAT(1X,F7.0,2X,1P4E11.3) readable for another code.
This is what I've come up with:
program fixformat
real temp, neuts(4)
integer i,j
character header
open(11,file='./unformatted.txt',status='old')
open(12,file='./formatted.txt',status='unknown')
read(11,*) header
write(12,*) header
do i = 1, 200
read(11,*) temp, (neuts(j),j=1,4)
write(12,23) temp, (neuts(j),j=1,4)
end do
23 FORMAT(1X,F7.0,2X,1P4E11.3)
close(11)
close(12)
return
end
I keep getting this error:
Fortran runtime error: Bad real number in item 1 of list input
Is there any other way to convert the data to that format?
You need a character string, not a single character for the header
character(80) header
other than that you program works for me. Make sure you have the right number of lines in your loop
Do i=1,200
Adjust 200 to the real number of your data lines.
If for some reason you still cannot read even a single line, you can also use the format:
read(11,'(f2.0,4(1x,f11.0))') temp, (neuts(j),j=1,4)
because the tab is just a character you can easily skip.
Notes:
Unformatted and formatted means something completely different in Fortran. Unformatted is what you may know as "binary".
Use some indentation and blank lines for your programs to make them readable.
There is no reason to explicitly use status=unknown. Just don't put anything there. In your case status=replace may be more appropriate.
The FORMAT statement is quite obsolete, in modern Fortran we use format strings:
write(12,'(1X,F7.0,2X,1P4E11.3)') temp, (neuts(j),j=1,4)
There is absolutely no reason for your return before the end. Returns is for early return from a procedure. Some put stop before the end program, but it is superfluous.
To read tab delimited data, I'd use a simple algorithm like the one below. NOTE: This is assuming that there is no tab character in any of your fields.
integer :: error_code, delim_index, line_index
character*500 :: data_line, field_data_string
double precision :: dp_value
Open(Unit=1001,File="C:\\MY\\PATH\\Data.txt")
DO
Read(UNIT=1001,End=106, FMT='(A)' ) data_line
line_length = LEN(TRIM(data_line))
delim_index = SCAN(data_line, achar(9) )
line_index = 0
DO WHILE ( delim_index .NE. 0 )
line_index = line_index + delim_index
IF (delim_index .EQ. 1 ) THEN ! found a NULL (no value), so skip
GOTO 101
END IF
field_data_string = data_line( (line_index-delim_index+1) : line_index )
READ( field_data_string, FMT=*, ERR=100) dp_value
PRINT *, "Is a double precision ", dp_value
GOTO 101
100 Continue
PRINT *, "Not a double precision"
101 Continue
IF ( (line_index+1) .GT. line_length ) THEN
GOTO 104 ! found end of line prematurely
END IF
delim_index = SCAN( data_line( line_index + 1 : ), achar(9) )
END DO
field_data_string = data_line( line_index + 1 : )
READ( field_data_string, FMT=*, ERR=102) dp_value
PRINT *, "Is a double precision ", dp_value
GOTO 103
102 Continue
PRINT *, "Not a double precision"
103 Continue
PRINT *, "Is a double precision ", dp_value
104 Continue
END DO
104 Continue
PRINT *, "Error opening file"
105 Continue
Close(1001)

Getting fortran runtime error: end of file

I have recently learned how to work with basic files in Fortran
and I assumed it was as simple as:
open(unit=10,file="data.dat")
read(10,*) some_variable, somevar2
close(10)
So I can't understand why this function I wrote is not working.
It compiles fine but when I run it it prints:
fortran runtime error:end of file
Code:
Function Load_Names()
character(len=30) :: Staff_Name(65)
integer :: i = 1
open(unit=10, file="Staff_Names.txt")
do while(i < 65)
read(10,*) Staff_Name(i)
print*, Staff_Name(i)
i = i + 1
end do
close(10)
end Function Load_Names
I am using Fortran 2008 with gfortran.
A common reason for the error you report is that the program doesn't find the file it is trying to open. Sometimes your assumptions about the directory in which the program looks for files at run-time will be wrong.
Try:
using the err= option in the open statement to write code to deal gracefully with a missing file; without this the program crashes, as you have observed;
or
using the inquire statement to figure out whether the file exists where your program is looking for it.
You can check when a file has ended. It is done with the option IOSTAT for read statement.
Try:
Function Load_Names()
character(len=30) :: Staff_Name(65)
integer :: i = 1
integer :: iostat
open(unit=10, file="Staff_Names.txt")
do while(i < 65)
read(10,*, IOSTAT=iostat) Staff_Name(i)
if( iostat < 0 )then
write(6,'(A)') 'Warning: File containts less than 65 entries'
exit
else if( iostat > 0 )then
write(6,'(A)') 'Error: error reading file'
stop
end if
print*, Staff_Name(i)
i = i + 1
end do
close(10)
end Function Load_Names
Using Fortran 2003 standard, one can do the following to check if the end of file is reached:
use :: iso_fortran_env
character(len=1024) :: line
integer :: u1,stat
open (newunit=u1,action='read',file='input.dat',status='old')
ef: do
read(u1,'A',iostat=stat) line
if (stat == iostat_end) exit ef ! end of file
...
end do ef
close(u1)
Thanks for all your help i did fix the code:
Function Load_Names(Staff_Name(65))!Loads Staff Names
character(len=30) :: Staff_Name(65)
integer :: i = 1
open(unit=10, file="Staff_Names.txt", status='old', action='read')!opens file for reading
do while(i < 66)!Sets Set_Name() equal to the file one string at a time
read(10,*,end=100) Staff_Name(i)
i = i + 1
end do
100 close(10)!closes file
return!returns Value
end Function Load_Names
I needed to change read(10,*) to read(10,*,END=100)
so it knew what to do when it came to the end the file
as it was in a loop I assume.
Then your problem was that your file was a row vector, and it was likely
giving you this error immediately after reading the first element, as #M.S.B. was suggesting.
If you have a file with a NxM matrix and you read it in this way (F77):
DO i=1,N
DO j=1,M
READ(UNIT,*) Matrix(i,j)
ENDDO
ENDDO
it will load the first column of your file in the first row of your matrix and will give you an error as soon as it reaches the end of the file's first column, because the loop enforces it to read further lines and there are no more lines (if N<M when j=N+1 for example). To read the different columns you should use an implicit loop, which is why your solution worked:
DO i=1,N
READ(UNIT,*) (Matrix(i,j), j=1,M)
ENDDO
I am using GNU Fortran 5.4.0 on the Ubuntu system 16.04. Please check your file if it is the right one you are looking for, because sometimes files of the same name are confusing, and maybe one of them is blank. As you may check the file path if it is in the same working directory.

Simple debugging in Haskell

I am new to Haskell. Previously I have programmed in Python and Java. When I am debugging some code I have a habit of littering it with print statements in the middle of code. However doing so in Haskell will change semantics, and I will have to change my function signatures to those with IO stuff. How do Haskellers deal with this? I might be missing something obvious. Please enlighten.
Other answers link the official doco and the Haskell wiki but if you've made it to this answer let's assume you bounced off those for whatever reason. The wikibook also has an example using Fibonacci which I found more accessible. This is a deliberately basic example which might hopefully help.
Let's say we start with this very simple function, which for important business reasons, adds "bob" to a string, then reverses it.
bobreverse x = reverse ("bob" ++ x)
Output in GHCI:
> bobreverse "jill"
"llijbob"
We don't see how this could possibly be going wrong, but something near it is, so we add debug.
import Debug.Trace
bobreverse x = trace ("DEBUG: bobreverse" ++ show x) (reverse ("bob" ++ x))
Output:
> bobreverse "jill"
"DEBUG: bobreverse "jill"
llijbob"
We are using show just to ensure x is converted to a string correctly before output. We also added some parenthesis to make sure the arguments were grouped correctly.
In summary, the trace function is a decorator which prints the first argument and returns the second. It looks like a pure function, so you don't need to bring IO or other signatures into the functions to use it. It does this by cheating, which is explained further in the linked documentation above, if you are curious.
Read this. You can use Debug.Trace.trace in place of print statements.
I was able to create a dual personality IO / ST monad typeclass, which will print debug statements when a monadic computation is typed as IO, them when it's typed as ST. Demonstration and code here: Haskell -- dual personality IO / ST monad? .
Of course Debug.Trace is more of a swiss army knife, especially when wrapped with a useful special case,
trace2 :: Show a => [Char] -> a -> a
trace2 name x = trace (name ++ ": " ++ show x) x
which can be used like (trace2 "first arg" 3) + 4
edit
You can make this even fancier if you want source locations
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Language.Haskell.TH.Syntax as TH
import Debug.Trace
withLocation :: Q Exp -> Q Exp
withLocation f = do
let error = locationString =<< location
appE f error
where
locationString :: Loc -> Q Exp
locationString loc = do
litE $ stringL $ formatLoc loc
formatLoc :: Loc -> String
formatLoc loc = let file = loc_filename loc
(line, col) = loc_start loc
in concat [file, ":", show line, ":", show col]
trace3' (loc :: String) msg x =
trace2 ('[' : loc ++ "] " ++ msg) x
trace3 = withLocation [| trace3' |]
then, in a separate file [from the definition above], you can write
{-# LANGUAGE TemplateHaskell #-}
tr3 x = $trace3 "hello" x
and test it out
> tr3 4
[MyFile.hs:2:9] hello: 4
You can use Debug.Trace for that.
I really liked Dons short blog about it:
https://donsbot.wordpress.com/2007/11/14/no-more-exceptions-debugging-haskell-code-with-ghci/
In short: use ghci, example with a program with code called HsColour.hs
$ ghci HsColour.hs
*Main> :set -fbreak-on-exception
*Main> :set args "source.hs"
Now run your program with tracing on, and GHCi will stop your program at the call to error:
*Main> :trace main
Stopped at (exception thrown)
Ok, good. We had an exception… Let’s just back up a bit and see where we are. Watch now as we travel backwards in time through our program, using the (bizarre, I know) “:back” command:
[(exception thrown)] *Main> :back
Logged breakpoint at Language/Haskell/HsColour/Classify.hs:(19,0)-(31,46)
_result :: [String]
This tells us that immediately before hitting error, we were in the file Language/Haskell/HsColour/Classify.hs, at line 19. We’re in pretty good shape now. Let’s see where exactly:
[-1: Language/Haskell/HsColour/Classify.hs:(19,0)-(31,46)] *Main> :list
18 chunk :: String -> [String]
vv
19 chunk [] = head []
20 chunk ('\r':s) = chunk s -- get rid of DOS newline stuff
21 chunk ('\n':s) = "\n": chunk s
^^

Resources