Fortran read SIGSEGV segmentation fault - fortran

I'm not familiar with Fortran, but I had to use my advisor's old code but it didn't work, and I could track down it to a minimal working example.
hello.f is following:
implicit none
character*200 rec
integer var,idum
real*4 rdum
call xparse('-t0',1,1,'required',rec,idum,rdum)
print *, rec
read(rec,'(i6)') var
print *, var
END
And extra.f is following:
c------------------------------------------------------------------
subroutine xparse(cc,nth,ifo,req,carg,iarg,rarg)
c------------------------------------------------------------------
character*(*) cc,req,carg
character*256 rec
c
iver=0
lcc=len(cc)
na=iargc()
ith=0
do 100 ia=1,na
call getarg(ia,rec)
if(rec(1:15).eq.'-xparse_verbose') iver=1
lrec=ilen(rec,256)
if(lrec.eq.lcc) then
if(rec(1:lcc).eq.cc(1:lcc)) then
if(iver.eq.1)write(0,'(a,a)')'xparse ,parsing:',rec(1:lcc)
c
if(nth.le.0) then
iarg=1
return
endif
c
ith=ith+1
if(ith.eq.nth) then
c
if(ia.eq.na) then
write(0,*)'parse error : missing value for ',cc
endif
call getarg(ia+1,rec)
lrec=ilen(rec,256)
if(iver.eq.1)write(0,'(a,a)')'xparse, string:',rec(1:lrec)
if(ifo.eq.1) then
if(iver.eq.1)write(0,'(a,a)')'xparse, character:',rec(1:lrec)
carg=rec
else if(ifo.eq.2) then
s=gets(rec)
if(s.ge.0.0)iarg=s+0.1
if(s.lt.0.0)iarg=s-0.1
if(iver.eq.1)write(0,*)'xparse, integer:',iarg
else if(ifo.eq.3) then
rarg=gets(rec)
if(iver.eq.1)write(0,*)'xparse, real:',rarg
endif
return
c
endif
endif
endif
100 continue
c
if(req(1:8).eq.'required') then
write(0,*)'parse error : cant find required arg: ',cc
stop
endif
end
c------------------------------------------
real function gets(cc)
c------------------------------------------
c
c decodes integer or floating f format
c from character string
c
character*(*) cc
nn=len(cc)
c
gets=0.0
fak=1.
ief=0
l1=0
l2=0
do 200 i=1,nn
if(cc(i:i).eq.'e'.or.cc(i:i).eq.'E')ief=i
if(cc(i:i).eq.'d'.or.cc(i:i).eq.'D')ief=i
if(l1.eq.0.and.cc(i:i).ne.' ')l1=i
if(cc(i:i).ne.' ')l2=i
if(cc(i:i).eq.' '.and.l2.gt.0) goto 201
200 continue
201 continue
nn=l2
if(ief.gt.0) then
lex=l2-ief
iex=-9999999
if(lex.eq.1)read(cc(ief+1:l2),'(i1)',err=900) iex
if(lex.eq.2)read(cc(ief+1:l2),'(i2)',err=900) iex
if(lex.eq.3)read(cc(ief+1:l2),'(i3)',err=900) iex
if(lex.eq.4)read(cc(ief+1:l2),'(i4)',err=900) iex
if(lex.eq.5)read(cc(ief+1:l2),'(i5)',err=900) iex
if(iex.gt.-999999) then
if(iex.lt.0)fak=1./( 10.**(-iex) )
if(iex.gt.0)fak=10.**iex
else
write(0,*)'gets: cannot read ',cc
endif
nn=ief-1
endif
c
sig=1.
ss=0.
tt=1.
ip=0
do 100 l=1,nn
if(cc(l:l).ne.' ') then
if(cc(l:l).eq.'.') then
ip=1
else if(cc(l:l).eq.'-') then
sig=-1.
else
c read(cc(l:l),'(i1)',err=900) ii
ii=ichar(cc(l:l))-48
if(ii.lt.0.or.ii.gt.9) goto 109
if(ip.eq.0) then
ss=10.*ss+float(ii)
else
tt=0.1*tt
ss=ss+tt*float(ii)
endif
endif
endif
100 continue
109 continue
gets=ss*sig*fak
return
900 continue
write(0,*)' gets: error reading formatted integer:'
write(0,*)nn
write(0,'(a,a,a)')'$',cc,'$'
return
end
c-------------------------------------
integer function ilen(c,m)
c-------------------------------------
character*80 c
k=1
do 100 i=1,m
if(c(i:i).ne.' '.and.c(i:i).ne.char(0))k=i
100 continue
ilen=k
jlen=k
return
end
If I do
gfortran hello.f extra.f
./a.out -t0 10800
I get the error
10800
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x10a01735c
#1 0x10a0166f3
#2 0x7fff7376cb5c
#3 0x10a15b340
#4 0x10a15bd2d
#5 0x10a15978f
#6 0x10a00c917
#7 0x10a00c9e5
Segmentation fault: 11
That read function(?) is the one frequently used in the code to read user input (like Python's sys.argv) but I can't see why it fails.
I'm using
GNU Fortran (Homebrew GCC 9.3.0_1) 9.3.0, MacOS Mojave 10.14.6.

There is a bug in the function ilen. Consider
character*80 c
k=1
do 100 i=1,m
if(c(i:i).ne.' '.and.c(i:i).ne.char(0))k=i
100 continue
The variable (dummy argument) c is declared to be of length 80, but in the loop the substring c(81:81) is surely attempted to be accessed if m is bigger than 80 (which it is when called in the program). This is incorrect.
You can index c up to position 80 with
do 100 i=1,80
...
or up to its length:
do 100 i=1,len(c)
...
Alternatively, you can make c have length 256 or not (necessarily) 80:
c Have the length of the dummy argument assumed
character*(*) c
or
c Have the length given by the argument m
character*(m) c
There are also the modern ways to write character declarations such as
character(len=*) c
and
character(len=m) c

Related

how can we call a subroutine in main program and taking its output in main program?

I want to call a subroutine in the main program and also want to get the output of that subroutine in the main program but when I write the output in the subroutine its different than when I write it in the main program someone can tell me where I am wrong? while writing yy in subroutine and in main program gives different values.
subroutine zlamda(lamdaroot)
INTEGER N,NBMAX
REAL X1,X2
PARAMETER(N=100,NBMAX=20,X1=0.0,X2=3.141592/2.)
INTEGER i,nb
REAL zbrent,root,tol,xb1(NBMAX),xb2(NBMAX)
EXTERNAL zbrak,bess
REAL bess,lamdaroot,lamda
COMMON /flamda/ eL,z
nb=NBMAX
call zbrak(bess,X1,X2,N,xb1,xb2,nb)
do 200 i=1,nb
tol=(1.0e-6)*(xb1(i)+xb2(i))/2.0
lamdaroot=zbrent(bess,xb1(i),xb2(i),tol)
yy=lamdaroot
write(*,*)yy,'=lamdaroot=yy'
200 continue
return
END
FUNCTION bess(lamda)
REAL bss,lamda,zz,x
bess=0.5*sin(lamda)*sqrt(1.+3.*sin(lamda)**2)+(0.5/sqrt(3.))
+ *log(abs(sqrt(3.)*sin(lamda)+sqrt(1.+3.*sin(lamda)**2)))
+ -abs(zz)/4685.0
return
END
SUBROUTINE zbrak(fx,x1,x2,n,xb1,xb2,nb)
INTEGER n,nb
REAL x1,x2,xb1(nb),xb2(nb),fx
EXTERNAL fx
INTEGER i,nbb
REAL dx,fc,fp,x
nbb=0
x=x1
dx=(x2-x1)/n
fp=fx(x)
do 11 i=1,n
x=x+dx
fc=fx(x)
if(fc*fp.le.0.) then
nbb=nbb+1
xb1(nbb)=x-dx
xb2(nbb)=x
if(nbb.eq.nb)goto 1
endif
fp=fc
11 continue
1 continue
nb=nbb
return
END
FUNCTION zbrent(func,x1,x2,tol)
INTEGER ITMAX
REAL zbrent,tol,x1,x2,func,EPS
EXTERNAL func
PARAMETER (ITMAX=100,EPS=3.e-8)
INTEGER iter
REAL a,b,c,d,e,fa,fb,fc,p,q,r,s,tol1,xm
a=x1
b=x2
fa=func(a)
fb=func(b)
if((fa.gt.0..and.fb.gt.0.).or.(fa.lt.0..and.fb.lt.0.))pause
*'root must be bracketed for zbrent'
c=b
fc=fb
do 11 iter=1,ITMAX
if((fb.gt.0..and.fc.gt.0.).or.(fb.lt.0..and.fc.lt.0.))then
c=a
fc=fa
d=b-a
e=d
endif
if(abs(fc).lt.abs(fb)) then
a=b
b=c
c=a
fa=fb
fb=fc
fc=fa
endif
tol1=2.*EPS*abs(b)+0.5*tol
xm=.5*(c-b)
if(abs(xm).le.tol1 .or. fb.eq.0.)then
zbrent=b
return
endif
if(abs(e).ge.tol1 .and. abs(fa).gt.abs(fb)) then
s=fb/fa
if(a.eq.c) then
p=2.*xm*s
q=1.-s
else
q=fa/fc
r=fb/fc
p=s*(2.*xm*q*(q-r)-(b-a)*(r-1.))
q=(q-1.)*(r-1.)*(s-1.)
endif
if(p.gt.0.) q=-q
p=abs(p)
if(2.*p .lt. min(3.*xm*q-abs(tol1*q),abs(e*q))) then
e=d
d=p/q
else
d=xm
e=d
endif
else
d=xm
e=d
endif
a=b
fa=fb
if(abs(d) .gt. tol1) then
b=b+d
else
b=b+sign(tol1,xm)
endif
fb=func(b)
11 continue
pause 'zbrent exceeding maximum iterations'
zbrent=b
return
END
and main program is
program main
implicit none
real yy,lamdaroot
call zlamda(lamdaroot)
write(*,*)yy
stop
endprogram main

Fortran - Jump other subroutine

I am trying to jump other subroutine in Fortran code. I used the return function but it is not working in some cases. Is there any way to jump to other subroutine. I made a simple example to define the problem. If the condition is in the same subroutine, I can use goto label but I need to jump different subroutine. If the condition is correct (case = .True.), I don't want to calculate that subroutine so I will skip that subroutine, I will start to use the new data. For example, if i=3 and case=true, the program shouldn't print a=8 in the 3rd loop and jump the do loop in subroutine abc.
----------------------------------------------
subroutine abc()
do i=1, 5
!if case is true, start to program from here.
call vector ()
end do
end subroutine
-------------------------------------
subroutine vector()
if (case = .True.)then
*****JUMP call vector in main program *****
print *,"skip and jump "
return
a= 8
print *, a
else
b= 9
print *, b
print *, "continue the process "
end if
end subroutine
------------------------------------------------
-----output should be-------
9
9
skip and jump
9
9

Fortran rank mismatch error

I receive the following error
Compiling file: tropic.f
Warning: Extension: Tab character in format at (1)
C:\Users\Marchant\Desktop\tropic.f(432) : error - Expected a right parenthesis in expression at column 72
Warning: Rank mismatch in argument 'tk' at (1) (scalar and rank-1)
Warning: Rank mismatch in argument 't' at (1) (scalar and rank-1)
Warning: Rank mismatch in argument 'tk' at (1) (scalar and rank-1)
Warning: Rank mismatch in argument 't' at (1) (scalar and rank-1)
Compilation failed.
in this program,
dimension ts1(3),ts2(3),ta1(3),ta2(3),out(14,300)
real lwc, lambda
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
common /param2/ pbot,ptop,dp,gam, bt,ct,tao,a21,lambda,lwc
common /heat/ beta,olr1,olr2,alb0,albgr,expo1,expo2,alb1,alb2
pbot=1.0e5
ptop=2.0e4
dp=pbot-ptop
open(12,file='tropic.in',form='formatted')
read(12,*) itermx, delt, iprint
read(12,*) lambda, gam, bt, ct, a1
read(12,*) beta,olr1,olr2,alb0,albgr,expo1,expo2
write(*,*) 'olr1=',olr1,', olr2=',olr2,', expo1=',expo1,', expo2='
1 ,expo2
c ** Set relative areas of convecting a1 and nonconvecting a2 regions.
c a1=.3
tao=265.
alpha=0.06
alpha2=alpha/2.
alpha1=1.-alpha
c expo1=80.
c expo2=80.
expa1=0.
expa2=0.
co=4.2e7
ca=1.0e7
xkap=0.288
rvap=461.
cp=1004.
rgas=287.
grav=9.81
c gam=1.0e-3
c lambda=1.0e3
pr=1.0e5
tr=300.
xl=2.5e6
write(*,*) ' gam=',gam
c** structure of output array
c out(1)=a1; 2=gam; 3=lambda
c 4=ts1 5=ts2 6=alb1 7=alb2
c 8=r1 9=r2 10=ts1tend 11=ts2tend
c 13=thet1 14=thet2
ikase=0
c ********* BIG LOOP ****************
do 888 nn=1,2
a1=0.1+0.2*nn
do 888 ll=1,7
c gam=1.0e-3*facg
gam=1/1024.*2.0**(ll-1)
do 888 mm=1,7
c lambda=1.0e+3*facl
lambda=64*2.0**(mm-1)
c write(*,*) '*******************************'
c write(*,*) 'GAM=',gam,', LAMBDA=',lambda,', A1=',a1
a2=1.-a1
a21=a2/a1
a12=a1/a2
c initialize variables
do i = 1,3
ts1(i)=301.
ts2(i)=300.
ta1(i)=302.
ta2(i)=300.
end do
is=1
js=2
tdelto=2.*delt/co
tdelta=2.*delt/ca
c write(*,999) ts1(js),ts2(js),ta1(js),ta2(js),r1,r2,ra1,ra2
999 format(1x,9f8.1)
c write(*,*) pbot,ptop,dp,pr,gam,bt,ct,tao,a21,lambda,lwc
ikase=ikase+1
c*** Time Loop *****
do 1000 it=1,itermx
dta=ta1(js)-ta2(js)
dto=ts1(js)-ts2(js)
call radiat(ts1(js),ts2(js),ta1(js),ta2(js),r1,r2,ra1,ra2)
call theta(ts1(js),ts2(js),ta1(js),ta2(js),demdp,demd2,deddp)
c** Note that demdp = del(theta)/grav
ts1(3)=ts1(is)+tdelto*(r1-gam*dto*cp*demdp-expo1)
ts2(3)=ts2(is)+tdelto*(r2+a12*gam*dto*cp*demdp-expo2)
c ta1(3)=ta1(is)+tdelta*(ra1-a21*gam*dto*cp*demdp-expa1)
c ta2(3)=ta2(is)+tdelta*(ra2+gam*dto*cp*deddp-expa2)
c apply Robert/Asselin filter
ts1(js)=ts1(js)*alpha1 +alpha2*(ts1(3)+ts1(is))
ts2(js)=ts2(js)*alpha1 +alpha2*(ts2(3)+ts2(is))
c if((it-1)/iprint*iprint.eq.it-1) then
if((it.eq.itermx)) then
time=(it-1)*delt/86400.
ts1tend=(r1-gam*dto*cp*demdp-expo1)*86400./co
ts2tend=(r2+a12*gam*dto*cp*demdp-expo2)*86400./co
c ta1tend=(-a21*gam*dto*cp*demdp)
c ta2tend=( gam*dto*cp*demdp)
thet1=thet(ts1,qsat(ts1,pbot),pbot)
thet2=thet(ts2,qsat(ts2,pbot),pbot)
c** structure of output array
c out(1)=a1; 2=gam; 3=lambda
c 4=ts1 5=ts2 6=alb1 7=alb2
c 8=r1 9=r2 10=ts1tend 11=ts2tend
c 12=thet1 13=thet2
c Set up array
out(1,ikase)=a1
out(2,ikase)=gam
out(3,ikase)=lambda
out(4,ikase)=ts1(js)
out(5,ikase)=ts2(js)
out(6,ikase)=alb1
out(7,ikase)=alb2
out(8,ikase)=r1
out(9,ikase)=r2
out(10,ikase)=ts1tend
out(11,ikase)=ts2tend
out(12,ikase)=thet1
out(13,ikase)=thet2
out(14,ikase)=qsat(ts1(js),pr)
c write(*,*) 'Day=',time, ', iter=',it
c write(*,*) a21,gam,dto,cp,demdp
c write(*,*) 'demdp, demd2,deddp', demdp, demd2,deddp
c write(*,*) 'lwc=',lwc,alb1, alb2
c*********x*********x*********x*********x*********x*********x*********x**********
c write(*,*) ' ts1, ts2, ta1, ta2, r1, r2, ra1,
c 1 ra2'
c write(*,999) ts1(3),ts2(3),ta1(3),ta2(3),r1,r2,ra1,ra2
c write(*,999) ts1(js),ts2(js),ta1(js),ta2(js),r1,r2,ra1,ra2
c write(*,998) ts1tend,ts2tend,ta1tend,ta2tend, thet1, thet2
998 format(1x,8f10.5)
endif
c ** Update Variables
is=3-is
js=3-js
ts1(js)=ts1(3)
ts2(js)=ts2(3)
ta1(js)=ta1(3)
ta2(js)=ta2(3)
1000 continue
888 continue
open(13,file='tropic.out',form='formatted')
c*********x*********x*********x*********x*********x*********x*********x**********
write(*,*) ' A1 gam lambda ts1 ts2 alb1
1alb2 r1 r2 ts1tend ts2tend thet1 thet2 qsat'
write(13,*) ' A1 gam lambda ts1 ts2 alb1
1alb2 r1 r2 ts1tend ts2tend thet1 thet2 qsat'
do ii=1,ikase
xkrap=out(2,ii)*out(3,ii)
write(*,789) (out(j,ii),j=1,14),xkrap
write(13,789) (out(j,ii),j=1,14),xkrap
789 format(1x,f6.1,f9.5,7f9.2,2f9.5,2f8.2,2f8.4)
enddo
stop
end
c ******************************************************
subroutine theta(ts1,ts2,ta1,ta2,demdp,demd2,deddp)
c ** This subroutine finds the theta gradients
real lwc, lambda
common /param2/ pbot,ptop,dp,gam, bt,ct,tao,a21,lambda,lwc
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
demdp=(thet(ts1,qsat(ts1,pbot),pbot)-thet(ts2,qsat(ts2,pbot),
1 pbot))/9.81
c 1 pbot))/dp
demd2=(thet(ta1,0.001,ptop)-thet(ts1,qsat(ts1,pbot),pbot))
1 /9.81
c 1 /dp
deddp=(thet(ts1,0.00001,ptop)-thet(ts2,0.00001,pbot))/9.81
c 1 /dp
return
end
c ******************************************************
subroutine radiat(ts1,ts2,ta1,ta2,r1,r2,ra1,ra2)
real lwc, lambda
common /param2/ pbot,ptop,dp,gam, bt,ct,tao,a21,lambda,lwc
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
common /heat/ beta,olr1,olr2,alb0,albgr,expo1,expo2,alb1,alb2
dta=ta1-ta2
dto=ts1-ts2
if(dto.gt.0.0) then
c ** radiation parameterization for atmosphere
ra1=-40-bt*(ta1-tao)+ct*(ts1-(ta1+29))
ra2=-200-bt*(ta2-tao)+ct*(ts2-(ta2+29))
c ** Get liquid water content
c lwc=lambda*a21*gam*abs(dto)*qsat(ts1,pr)
c ** Get albedo as function of LWC
alb2=alb0
alb1=alb0+lambda*gam*abs(dto)*qsat(ts1,pr)
if(alb1.gt.0.75) alb1=0.75
r1=400.*(1.-alb1)-olr1-beta*(ts1-300.)
r2=400.*(1.-alb2)-olr2-beta*(ts2-300.)
else
c ** here ts2 is hotter than ts1
c ** radiation parameterization for atmosphere
ra1=-200-bt*(ta1-tao)+ct*(ts1-(ta1+29))
ra2=-40-bt*(ta2-tao)+ct*(ts2-(ta2+29))
c ** Get liquid water content
c lwc=lambda*gam*abs(dto)*qsat(ts2,pr)
c ** Get albedo as function of LWC
alb1=alb0
alb2=alb0+lambda*gam*abs(dto)*qsat(ts2,pr)
if(alb2.gt.0.75) alb2=0.75
r1=400.*(1.-alb1)-olr2-beta*(ts1-300.)
r2=400.*(1.-alb2)-olr1-beta*(ts2-300.)
endif
c write(*,*) 'lwc=',lwc,', alb1,2=',alb1,alb2,', r,ra-',r1,r2,ra1,ra2
return
end
c*********x*********x*********x*********x*********x*********x*********x**********
c*************************************************************
function temp(the,rv,p)
c** Function calculates temperature given thetaE, rv and p
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
temp=the/((pr/p)**xkap*exp(xl*rv/(cp*tr)))
return
end
c*************************************************************
function thet(t,rv,p)
c** Function calculates thetaE given t, rv and p
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
thet=t*(pr/p)**xkap*exp(xl*rv/(cp*tr))
return
end
c*************************************************************
function thets(t,p)
c** Function calculates thetaEsaturate given t and p
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
if(t.lt.273.15) then
es=esice(t)
else
es=esat(t)
endif
rs=0.622*es/(p-es)
thets=t*(pr/p)**xkap*exp(xl*rs/(cp*tr))
return
end
c*************************************************************
subroutine plevs(p,xlp,dlp,dp)
c** Subroutine to set pressure levels
parameter(ilx=25)
dimension p(ilx),xlp(ilx),dlp(ilx),dp(ilx)
write(*,*) 'Setting Pressure Levels'
write(*,*) ' i p(i) dp(i) logp dlogp'
pmin=2000.
pmax=101300.
delpo=pmax-pmin
delp=delpo/(ilx-1)
do i=1,ilx
p(i)=pmin+(i-1.)*delp
xlp(i)=alog(p(i))
end do
do i=1,ilx-1
dlp(i)=xlp(i+1)-xlp(i)
dp(i)=p(i+1)-p(i)
end do
dlp(ilx)=0.0
do i=1,ilx
write(*,*) i,p(i),dp(i),xlp(i),dlp(i)
end do
return
end
c*************************************************************
subroutine radini(teq,p,t,sst)
c** Calculates variables needed by radiation relaxation code
parameter (ilx=25)
dimension p(ilx),t(ilx),teq(ilx)
do i=1,ilx
if(p(i).lt.12000.) then
teq(i)=t(i)
c elseif(p(i).gt.80000.) then
else
teq(i)=t(i)-10.
c teq(i)=t(i)-(p(ilx)/10000.)*2.
endif
end do
return
end
c*************************************************************
subroutine initlz(the,rt,rs,t,rv,p,sst)
c** Subroutine to set initial values of all variables
parameter (ilx=25)
dimension the(ilx),rt(ilx),rs(ilx),t(ilx),rv(ilx),
1 p(ilx)
common /params/xkap,pr,tr,xl,cp,rgas,grav,taue,taus,taup,tauc
ttrop=200.
tsurf=300.
ptrop=10000.
dtdp=(tsurf-ttrop)/(p(ilx)-ptrop)
relhum=0.80
c** Set T(p)
do i=1,ilx
if(p(i).lt.ptrop) then
t(i)=200.+10.*(ptrop-p(i))/(ptrop-p(1))
else
t(i)=200.+dtdp*(p(i)-ptrop)
endif
end do
c** Next calculate vapor mixing ratio and thetaE
write(*,*) 'index, pressure, temp., vapor mr, thetaE'
do i=1,ilx
if(p(i).lt.ptrop) then
rfrac=0.05
else
rfrac=relhum
endif
if(t(i).lt.273.) then
es=esice(t(i))
else
es=esat(t(i))
endif
rv(i)=rfrac*0.622*es/(p(i)-es)
rs(i)=0.622*es/(p(i)-es)
rt(i)=rv(i)
the(i)=t(i)*(pr/p(i))**xkap*exp(xl*rv(i)/(cp*tr))
write(*,100) i,p(i),t(i),rv(i),the(i)
100 format(1x,i3,f12.1,f7.1,e13.3,f7.1)
end do
return
end
c*************************************************************
function signum(x)
c** Hankel function
if(x.eq.0) then
signum=1.
else
signum=(abs(x)+x)*0.5/abs(x)
endif
return
end
c*************************************************************
subroutine zero(x,n)
dimension x(n)
do i=1,n
x(i)=0.0
end do
return
end
C#######################################################################
FUNCTION ESICE(TK)
C THIS FUNCTION RETURNS THE SATURATION VAPOR PRESSURE WITH RESPECT TO
C ICE ESICE (Pascals) GIVEN THE TEMPERATURE T (Kelvin). DLH 11.19.97
C THE FORMULA USED IS BASED UPON THE INTEGRATION OF THE CLAUSIUS-
C CLAPEYRON EQUATION BY GOFF AND GRATCH. THE FORMULA APPEARS ON P.350
C OF THE SMITHSONIAN METEOROLOGICAL TABLES, SIXTH REVISED EDITION,
C 1963.
DATA CTA,EIS/273.15,6.1071/
C CTA = DIFFERENCE BETWEEN KELVIN AND CELSIUS TEMPERATURE
C EIS = SATURATION VAPOR PRESSURE (MB) OVER A WATER-ICE MIXTURE AT 0C
DATA C1,C2,C3/9.09718,3.56654,0.876793/
C C1,C2,C3 = EMPIRICAL COEFFICIENTS IN THE GOFF-GRATCH FORMULA
c**** Convert to Celsius
c tc=t-273.15
IF (TK.LE.CTA) GO TO 5
ESICE = 99999.
WRITE(6,3)ESICE
3 FORMAT(' SATURATION VAPOR PRESSURE FOR ICE CANNOT BE COMPUTED',
1 /' FOR TEMPERATURE > 0C. ESICE =',F7.0)
RETURN
5 CONTINUE
C FREEZING POINT OF WATER (K)
TF = CTA
C GOFF-GRATCH FORMULA
RHS = -C1*(TF/TK-1.)-C2*ALOG10(TF/TK)+C3*(1.-TK/TF)+ALOG10(EIS)
ESI = 10.**RHS
IF (ESI.LT.0.) ESI = 0.
ESICE = ESI*100.
RETURN
END
C#######################################################################
FUNCTION ESAT(TK)
C THIS FUNCTION RETURNS THE SATURATION VAPOR PRESSURE OVER
C WATER (Pa) GIVEN THE TEMPERATURE (Kelvin). DLH 11.19.97
C THE ALGORITHM IS DUE TO NORDQUIST, W.S.,1973: "NUMERICAL APPROXIMA-
C TIONS OF SELECTED METEORLOLGICAL PARAMETERS FOR CLOUD PHYSICS PROB-
C LEMS," ECOM-5475, ATMOSPHERIC SCIENCES LABORATORY, U.S. ARMY
C ELECTRONICS COMMAND, WHITE SANDS MISSILE RANGE, NEW MEXICO 88002.
IF (TD.NE. 99999.0) THEN
C IF (TD.NE.-1001.0) THEN
c**** Convert to Celsius
c TK = TD+273.15
P1 = 11.344-0.0303998*TK
P2 = 3.49149-1302.8844/TK
C1 = 23.832241-5.02808*ALOG10(TK)
ESAT = 100.*10.**(C1-1.3816E-7*10.**P1+8.1328E-3*10.**P2-2949.076/TK)
else
esat = 0.
END IF
RETURN
END
C#######################################################################
function qsat(tk,p)
qsat=esat(tk)*0.622/p
return
end
Can someone show me how to fix this? its a fortran77 file being compiled in mingw gfortran
At least the line
ESAT = 100.*10.**(C1-1.3816E-7*10.**P1+8.1328E-3*10.**P2-2949.076/TK)
is too long for FORTRAN 77 standard. At least when the statement starts at column 7. In your code it appears to start earlier, but that is wrong.
Break it,
ESAT = 100.*10.**(C1-1.3816E-7*10.**P1+
* 8.1328E-3*10.**P2-2949.076/TK)
or use an option like
-ffixed-line-length-132
to make the limit larger (it is non-standard!).
Also many of your statements appear to start on earlier column than 7. This may be a copy-paste error to this page, it may be due to the non-conforming tab characters the compiler warns about. If it is not the case, correct it too, they must start at column 7 or further. For example, this is very strange:
IF (TD.NE. 99999.0) THEN
C IF (TD.NE.-1001.0) THEN
There may be other errors, but your code is simply too long and cannot be compiled by copy-paste.

Intel Fortran: write multi-item namelist to internal file?

I want to write a namelist with multiple items (hence multiple lines) to a character variable. The following code runs well when compiled with gfortran, but returns a write error when compiled with ifort:
program test
implicit none
type testtype
real*8 :: x
character(len=32) :: str
logical :: tf
end type testtype
type(testtype) :: thetype
integer :: iostat
character(len=1000) :: mystr(10)
namelist /THENAMELIST/ thetype
integer :: i
thetype%x = 1.0d0
thetype%str="This is a string."
thetype%tf = .true.
mystr=""
write(*,nml=THENAMELIST,delim="QUOTE")
write(mystr,THENAMELIST,iostat=iostat,delim="QUOTE")
write(*,*)"Iostat:",iostat
do i = 1, size(mystr)
write(*,*)i,trim(mystr(i))
end do
end program test
The output is the following:
> ifort -o test test.f90 ; ./test
&THENAMELIST
THETYPE%X = 1.00000000000000 ,
THETYPE%STR = "This is a string. ",
THETYPE%TF = T
/
Iostat: 66
1 &THENAMELIST THETYPE%X= 1.00000000000000 ,
2
3
4
5
6
7
8
9
10
Intel's list of run-time error messages tells me: "severe (66): Output statement overflows record".
For over completeness, using gfortran I of course get
> gfortran -o test test.f90 ; ./test
&THENAMELIST
THETYPE%X= 1.0000000000000000 ,
THETYPE%STR="This is a string. ",
THETYPE%TF=T,
/
Iostat: 0
1 &THENAMELIST
2 THETYPE%X= 1.0000000000000000 ,
3 THETYPE%STR="This is a string. ",
4 THETYPE%TF=T,
5 /
6
7
8
9
10
I have searched all over the internet, and learned that the internal file cannot be a scalar character variable, but that's about as much as I found. GFortran does accept a scalar variable and just writes newlines in that variable, but that, I guess, is non-standard fortran.
The compilers I used are:
gfortran GNU Fortran (MacPorts gcc48 4.8-20130411_0) 4.8.1 20130411 (prerelease)
ifort (IFORT) 12.0.5 20110719 (on mac)
ifort (IFORT) 13.1.1 20130313 (on GNU/Linux)
My question is: what is the error in my syntax, or how else can I write a namelist to an internal file, without having to patch the problem by writing to an actual external scratch file and read that into my variable (which is what I do now, but which is slow for large namelists)?

How to write output to a string in fortran?

I need to write a formated output to a string DTSTR. It use to work under layhe fortran but not gfortran
INTEGER*2 MON,DAY,YEAR,HR,MINUTE,SEC,HUND
CHARACTER DY*2
CHARACTER DTSTR*24
COMMON /RD/ DTSTR
...
...
WRITE(DTSTR,10)MON,DAY,YEAR,HR,MINUTE,DY,' ]'
10 FORMAT('[ ',I2,'-',I2.2,'-',I4,2X,I2,':',I2.2,1X,2A2)
it empty just a empty line. If i use following it correctly output. But i want to store this string. Is it possible to do that with gnu fortran.
WRITE(*,10)MON,DAY,YEAR,HR,MINUTE,DY,' ]'
update
I am trying to compile following file. I think the problem might be with the COMMON.
PROGRAM HELO
CALL DOTIME
WRITE(*,5700)DTSTR
5700 FORMAT(24X,A24/)
END
SUBROUTINE DOTIME
C
IMPLICIT NONE
INTEGER*2 MON,DAY,YEAR,HR,MINUTE,SEC,HUND
CHARACTER DY*2
CHARACTER DTSTR*24
COMMON /RD/ DTSTR
integer values(8)
call date_and_time(VALUES=values)
YEAR = values(1)
MON = values(2)
DAY = values(3)
HR = values(5)
MINUTE = values(6)
SEC = values(7)
HUND = values(8)
C =================================================
C
C Incompitable function => CALL GETDAT(YEAR,MON,DAY)
C Incompitable function => GETTIM(HR,MINUTE,SEC,HUND)
IF(HR .GE. 12)THEN
IF(HR .NE. 12)HR=HR-12
DY='PM'
ELSE
DY='AM'
ENDIF
WRITE(DTSTR,10)MON,DAY,YEAR,HR,MINUTE,DY,' ]'
10 FORMAT('[ ',I2,'-',I2.2,'-',I4,2X,I2,':',I2.2,1X,2A2)
RETURN
END
Hmm? It works just fine for me:
program testwrite
implicit none
INTEGER :: MON,DAY,YEAR,HR,MINUTE,SEC,HUND
CHARACTER(LEN=2) :: DY
CHARACTER(LEN=24) :: DTSTR
MON = 4
DAY = 27
YEAR= 2010
HR = 13
MINUTE = 27
SEC = 0
HUND = 0
DY ='WE'
WRITE(DTSTR,10)MON,DAY,YEAR,HR,MINUTE,DY,' ]'
10 FORMAT('[ ',I2,'-',I2.2,'-',I4,2X,I2,':',I2.2,1X,2A2)
print *,'<',trim(DTSTR),'>'
end program testwrite
gives
<[ 4-27-2010 13:27 WE ]>
just as one would expect. Works with several versions of gfortran I have kicking around.
Update: Yes, the problem is in your common block. The common block isn't declared in the main program. But really, it's much simpler and much, much better practice just to pass the string as an argument:
PROGRAM HELO
IMPLICIT NONE
CHARACTER(LEN=24) :: DTSTR
CALL DOTIME(DTSTR)
WRITE(*,5700)DTSTR
5700 FORMAT(24X,A24/)
END
SUBROUTINE DOTIME(DTSTR)
C
IMPLICIT NONE
INTEGER*2 MON,DAY,YEAR,HR,MINUTE,SEC,HUND
CHARACTER DY*2
CHARACTER(LEN=24), INTENT(OUT) :: DTSTR