Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed
program grbtocdf
C
C Purpose.
C --------
C
C Unpacks GRIB coded data (from the ECMWF) and
C writes the data to a NetCDF-file.
C
C Interface.
C ----------
C
C File of GRIB coded data attached as unit 11.
C NetCDF-filename and mdv read from unit 15.
C Varfile attached as unit 14.
C
C Reference.
C ----------
C
C WMO Manual on Codes for GRIB definition.
C WMO Publication No. 9, Volume B, for grid catalogue numbers.
C
C Author.
C -------
C
C H. Wernli 16.03.93
C Based on the programs grbtoxx.f by H.Wernli/D.Luethi and
C swmcdf.f by Ch.Schaer.
C
C Modifications.
C --------------
C
C H. Wernli 6.06.97
C Implementation of options close and onepertime
C
C -----------------------------------------------------------------
C
IMPLICIT NONE
INCLUDE 'grib_api_f77.h'
C Arrays are dimensioned to accommodate T213/N160 data volumes.
integer nxmax,nymax,nlevmax
parameter(nxmax=2881,nymax=1441,nlevmax=300)
integer jfield
PARAMETER(jfield=nxmax*nymax)
C Maximum number of variables (in varfile)
INTEGER maxvar
PARAMETER(maxvar=100)
C Local variables declarations
character*80 cdfnam,cdfname,varname,ifname,lastvar,var
character*80 cfn,wrcstflag
CHARACTER*10 vnshrt
CHARACTER*2 string2,string3,string4
CHARACTER*4 string1
CHARACTER*10 datestr,timestr
real field(jfield),dummy(jfield),zsec4(jfield)
real pvarr(2*nlevmax+4),mdv,tstep
real varmin(4),varmax(4),stag(4),dx,dy,y0,y1,lat,xmin,xmax
real level(nlevmax),aklev(nlevmax),bklev(nlevmax),
> aklay(nlevmax),bklay(nlevmax)
integer idate(5),idate2(5),stdate(5),datar(14),vardim(4)
integer nd,ndim,nvar,nvars,dim,idefine
integer numerr,irec,idata,ipos,iendf,ilev,nlev,nloop
integer glev,nvals,nlev2
integer ierr,iword,idgrb,ifile,lenout
INTEGER i,j,k,ind,ind1,ind2,j0,n,ishift,gltyp,nn
integer nx,ny,npv
integer ifilen,ipo
integer cstid,cdfid,grbednr
character*(15) vnam(maxvar)
character*(10) snames(maxvar)
character*(13) unit(maxvar)
character*(15) varnam(maxvar)
integer lnum(maxvar),
> stg(maxvar),tdep(maxvar),p(maxvar),lval(maxvar)
integer arrcnt(maxvar),idef(maxvar),levty(maxvar)
real factor(maxvar),bias(maxvar)
integer varcnt,pos
logical infile,opnfile,prelev,periodic
integer lastlev,version,onepertime,rotate,noclose
write(*,*)'*** start of program GRBTOCDF ***'
C Initialize some variables
numerr = 0 ! clear error counter
irec=0 ! # of record on unit 11
idata=0 ! # of words (not yet used) in array inbuff
ipos=0 ! # of words (already used) in array inbuff
iendf=0 ! flag to determine end of file on unit 11
nlev=0 ! # of levels on grib file
nloop=0 ! # of decoded fields
C Lengths of INBUFF and record length on unit 11
ifname = 'fort.11'
C Read the NetCDF filename, constants filename and the missing
C data flag from tape 15
read(15,'(a)')cdfnam
read(15,'(a)')wrcstflag
read(15,'(a)')cfn
read(15,*)mdv
read(15,*)version
read(15,*)rotate
read(15,*)noclose
read(15,*)onepertime
C Read the varfile
call rdvarfile(vnam,snames,levty,unit,
> factor,bias,lnum,stg,tdep,p,lval,varcnt,ierr)
if (ierr.ne.0) goto 994
C ====================================================
C Read the whole file in order to determine the levels
C loop 50 --> goto 50
C ====================================================
C Initialize level array with dummy value
C (otherwise ilev1=0 (surface data) will not be defined)
DO i=1,nlevmax
level(i)=-999.98999
ENDDO
C Open file with GRID coded data as direct access file
CALL grib_check(grib_open_file(ifile, ifname, 'r'))
50 CONTINUE
nloop=nloop+1 ! next field gets decoded
C Get new record from GRIB file
ierr = grib_new_from_file(ifile, idgrb)
IF (idgrb.EQ.-1) THEN
IF (ierr.NE.-1) THEN
CALL grib_check(ierr)
GOTO 9993
ELSE
GOTO 60 ! end of file is reached
ENDIF
ENDIF
C Loop to get all levels for the NetCDF file
CALL grib_check(grib_get_int(idgrb,'editionNumber',grbednr))
CALL grib_check(grib_get_string(idgrb,'shortName',vnshrt))
CALL grib_check(grib_get_int(idgrb,'level',glev))
IF (grbednr.EQ.1) THEN
CALL grib_check(grib_get_int(idgrb,'indicatorOfTypeOfLevel',
& gltyp))
ELSE
ierr = grib_get_int(idgrb,'typeOfFirstFixedSurface',
& gltyp)
IF (gltyp.ne.105) gltyp=1
ENDIF
C Test if variable is on varfile
IF (infile(vnshrt,gltyp,snames,levty,varcnt,pos)) THEN
C Test if level is desired for 2d fields (quit loop if not)
C Test if actual level (isec1(8)) is already defined (quit loop if yes)
DO i=1,nlevmax
IF (glev.EQ.level(i)) GOTO 24
ENDDO
C Define new level
nlev=nlev+1
C Special if to define the first level
IF (level(1).EQ.-999.98999) THEN
level(1)=glev
GOTO 24
ENDIF
C Get position for new level in level-array such that levels
C in the array are monotonically decreasing
DO i=1,nlevmax-1
IF ((glev.LT.level(i)).AND.(glev.GT.level(i+1))) THEN
DO j=nlevmax-1,i+1,-1
level(j+1)=level(j)
ENDDO
level(i+1)=glev
GOTO 24
ENDIF
ENDDO
IF (glev.GT.level(1)) THEN
DO j=nlevmax-1,1,-1
level(j+1)=level(j)
ENDDO
level(1)=glev
GOTO 24
ENDIF
ENDIF
24 CONTINUE
CALL grib_check(grib_release(idgrb))
GOTO 50
60 CONTINUE
CALL grib_check(grib_close_file(ifile))
C ======================================================
C Start of loop to write specified fields on NetCDF file
C loop 70 --> goto 70
C ======================================================
C Initialize some variables
numerr = 0 ! clear error counter
irec=1 ! # of record on unit 11
idata=0 ! # of words (not yet used) in array inbuff
ipos=0 ! # of words (already used) in array inbuff
iendf=0 ! flag to determine end of file on unit 11
nloop=0 ! # of decoded fields
ilev=0 ! # of actual level in time step
CALL grib_check(grib_open_file(ifile, ifname, 'r'))
PRINT *,'opened file'
65 ierr = grib_new_from_file(ifile, idgrb)
IF (idgrb.EQ.-1) THEN
IF (ierr.NE.-1) THEN
CALL grib_check(ierr)
ENDIF
STOP 2
ENDIF
CALL grib_check(grib_get_string(idgrb,'shortName',vnshrt))
CALL grib_check(grib_get_int(idgrb,'level',glev))
IF (grbednr.EQ.1) THEN
CALL grib_check(grib_get_int(idgrb,'indicatorOfTypeOfLevel',
& gltyp))
ELSE
ierr = grib_get_int(idgrb,'typeOfFirstFixedSurface',
& gltyp)
IF (gltyp.LT.100) gltyp=1
ENDIF
IF (.NOT. infile(vnshrt,gltyp,snames,levty,varcnt,pos)) THEN
PRINT *,'get next record'
CALL grib_check(grib_release(idgrb))
GOTO 65
ENDIF
C Define horizontal dimensions
CALL grib_check(grib_get_int(idgrb,'Ni',nx)) ! number of points along x
CALL grib_check(grib_get_int(idgrb,'Nj',ny)) ! number of points along y
C Decide if data is on pressure or model levels
prelev=.true.
IF (gltyp.NE.100) prelev=.false.
C Define staggering coefficients
stag(1)=0.
stag(2)=0.
stag(3)=-0.5
C Define data region
CALL grib_check(grib_get_real4(idgrb,
& 'longitudeOfFirstGridPointInDegrees',varmin(1)))
CALL grib_check(grib_get_real4(idgrb,
& 'latitudeOfLastGridPointInDegrees',varmin(2)))
CALL grib_check(grib_get_real4(idgrb,
& 'longitudeOfLastGridPointInDegrees',varmax(1)))
CALL grib_check(grib_get_real4(idgrb,
& 'latitudeOfFirstGridPointInDegrees',varmax(2)))
IF (varmin(1).GT.varmax(1)) THEN
IF (varmin(1).GE.180.) THEN
varmin(1) = varmin(1) - 360.
ELSE
varmax(1) = varmax(1) + 360.
ENDIF
ENDIF
IF (prelev) THEN
varmin(3)=level(1)
varmax(3)=level(nlev)
ELSE
varmin(3)=1050.
varmax(3)=0.
ENDIF
C Define dimensions
vardim(1)=nx
vardim(2)=ny
IF ((lnum(pos).EQ.3).OR.(lnum(pos).EQ.4)) THEN
vardim(3)=1
ELSE
vardim(3)=nlev
ENDIF
IF (tdep(pos).EQ.0) THEN
vardim(4)=1
ENDIF
C Calculate grid increments
dx=(varmax(1)-varmin(1))/real(vardim(1)-1)
dy=(varmax(2)-varmin(2))/real(vardim(2)-1)
C Check if the domain is (almost) periodic
C print*,'test ',varmin(1),varmax(1),dx,varmax(1)-varmin(1),360.-dx
IF (ABS((varmax(1)-varmin(1))-(360.-dx)).LT.0.1) THEN
periodic=.TRUE.
IF (noclose.EQ.0) THEN
varmax(1)=varmin(1)+360.
vardim(1)=vardim(1)+1
ENDIF
ENDIF
C print*,'test ',varmin(1),varmax(1),dx,varmax(1)-varmin(1),360.-dx
IF ((rotate.EQ.1).AND.(periodic)) THEN
xmin=varmin(1)
xmax=varmax(1)
varmin(1)=0.
varmax(1)=360.
ENDIF
C If one file per date then define the proper filename
C Define actual date as starting date
CALL grib_check(grib_get_string(idgrb,'dataDate',datestr))
CALL grib_check(grib_get_string(idgrb,'dataTime',timestr))
IF (onepertime.EQ.0) THEN
cdfname=trim(cdfnam)
ELSE
READ (datestr(1:4),'(I4.4)') idate(1)
READ (datestr(5:6),'(I2.2)') idate(2)
READ (datestr(7:8),'(I2.2)') idate(3)
READ (timestr(1:2),'(I2.2)') idate(4)
write(string1,'(i4)')idate(1)
if (idate(2).ge.10) then
write(string2,'(i2)')idate(2)
else
write(string2,'(a1,i1)')'0',idate(2)
endif
if (idate(3).ge.10) then
write(string3,'(i2)')idate(3)
else
write(string3,'(a1,i1)')'0',idate(3)
endif
if (idate(4).ge.10) then
write(string4,'(i2)')idate(4)
else
write(string4,'(a1,i1)')'0',idate(4)
endif
cdfname=trim(cdfnam)//
> string1//string2//string3//'_'//string4
cfn=TRIM(cdfname)//'_cst'
ENDIF
C Define the name of the constants file
if (cfn.eq.'default') then
cfn=cdfname//'_cst'
endif
C Open or create the NetCDF file, read or define the start date
if (.not.opnfile) then
call opncdf(cdfname,cdfid,varmin,varmax,nd,varnam,nvar,cfn,ierr)
if (ierr.ne.0) then
call crecdf(trim(cdfname),cdfid,varmin,varmax,
> 3,trim(cfn),ierr)
if (ierr.ne.0) goto 996
write(*,*)'*** NetCDF file ',trim(cdfname),' created'
C If requested write the constants file
if (wrcstflag.eq.'yes') then
C Define actual date as starting date
CALL grib_check(grib_get_string(idgrb,'dataDate',datestr))
CALL grib_check(grib_get_string(idgrb,'dataTime',timestr))
IF (grbednr.EQ.1) THEN
CALL grib_check(grib_get_int(idgrb,'startStep',
& stdate(5)))
ELSE
CALL grib_check(grib_get_int(idgrb,'forecastTime',
& stdate(5)))
ENDIF
READ (datestr(1:4),'(I4.4)') stdate(1)
READ (datestr(5:6),'(I2.2)') stdate(2)
READ (datestr(7:8),'(I2.2)') stdate(3)
READ (timestr(1:2),'(I2.2)') stdate(4)
C Define the datar array (used to define constants file)
datar(1)=vardim(1)
datar(2)=vardim(2)
datar(3)=nint(1000.*varmax(2)) ! latitude north
datar(4)=nint(1000.*varmin(1)) ! longitude west
datar(5)=nint(1000.*varmin(2)) ! latitude south
datar(6)=nint(1000.*varmax(1)) ! longitude east
datar(7)=nint(1000.*dx)
datar(8)=nint(1000.*dy)
datar(9)=vardim(3)
datar(10)=2 ! dattyp = forecast
datar(11)=0 ! data version
datar(12)=0 ! cstfile version
datar(13)=0 ! longitude of pole
datar(14)=90000 ! latitude of pole
C Get the 4 levels/layers arrays
IF (prelev) then
call prelevs(nlev,level,aklev,bklev,aklay,bklay)
ELSE
if (nlev.eq.1) nlev=60
nlev2=nlev
C nlev2 is quick&dirty for only 36 levels from 60 levels
if (nlev.eq.36) nlev2=60
if (nlev.eq.46) nlev2=60
* call modlevs(nlev2,aklev,bklev,aklay,bklay)
CALL grib_check(grib_get_size(idgrb,'pv',npv))
CALL grib_check(grib_get_real4_array(idgrb,'pv',
& pvarr,npv))
DO i=1,nlev
aklev(i) = pvarr(npv/2 - i)/100.
bklev(i) = pvarr(npv - i)
ENDDO
DO i=1,nlev-1
aklay(i+1) = 0.5*(aklev(i)+aklev(i+1))
bklay(i+1) = 0.5*(bklev(i)+bklev(i+1))
ENDDO
aklay(1)=0.5*(0. + aklev(1))
bklay(1)=0.5*(1. + bklev(1))
ENDIF
C Write the constants file
call wricst(cfn,datar,aklev,bklev,aklay,bklay,stdate)
write(*,*)'*** cst-file ',trim(cfn),' created'
else ! assume that the constants-file already exists
C Inquire start time
call cdfopn(cfn,cstid,ierr)
call getstart(cstid,stdate,ierr)
call clscdf(cstid,ierr)
nlev2=nlev
C nlev2 is quick&dirty for only 36 levels from 60 levels
if (nlev.eq.36) nlev2=60
if (nlev.eq.46) nlev2=60
endif
idef=0
else
write(*,*)'*** NetCDF file ',trim(cdfname),' opened'
C Inquire start time
call cdfopn(cfn,cstid,ierr)
call getstart(cstid,stdate,ierr)
call clscdf(cstid,ierr)
nlev2=nlev
C nlev2 is quick&dirty for only 36 levels from 60 levels
if (nlev.eq.36) nlev2=60
if (nlev.eq.46) nlev2=60
endif
* print*,'ilev nlev ',ilev,nlev
opnfile=.true.
idef=0
endif
* print*,idef
C Read file with predetermined variables
read(16,*)nvars
if (nvars.gt.0) then
do n=1,nvars
read(16,*)var
read(16,*)dim
if (dim.eq.3) then
vardim(3)=nlev
else
vardim(3)=1
endif
call putdef(cdfid,trim(var),
> 4,mdv,vardim,varmin,varmax,stag,ierr)
write(*,*)'*** variable ',trim(var),' created'
enddo
idefine=0
else
idefine=1
endif
70 continue
nloop=nloop+1 ! next field gets decoded
C Read next field if the actual one is not on the varfile
CALL grib_check(grib_get_string(idgrb,'shortName',vnshrt))
IF (grbednr.EQ.1) THEN
CALL grib_check(grib_get_int(idgrb,'indicatorOfTypeOfLevel',
& gltyp))
ELSE
ierr = grib_get_int(idgrb,'typeOfFirstFixedSurface',
& gltyp)
IF (gltyp.LT.100) gltyp=1
ENDIF
if (.not.infile(vnshrt,gltyp,snames,levty,varcnt,pos))
> goto 80
CALL grib_check(grib_get_int(idgrb,'level',glev))
C Don't write field if level is not desired
if ((lnum(pos).eq.3).or.(lnum(pos).eq.4)) then
if (glev.ne.lval(pos)) goto 80
endif
C Don't write field if variable is not time-dependent and it
C appears not the first time
IF ((tdep(pos).EQ.0).AND.(arrcnt(pos).NE.0)) GOTO 80
C Define the array containing the date information
CALL grib_check(grib_get_string(idgrb,'dataDate',datestr))
CALL grib_check(grib_get_string(idgrb,'dataTime',timestr))
IF (grbednr.EQ.1) THEN
CALL grib_check(grib_get_int(idgrb,'startStep',
& idate(5)))
ELSE
CALL grib_check(grib_get_int(idgrb,'forecastTime',
& idate(5)))
ENDIF
READ (datestr(1:4),'(I4.4)') idate(1)
READ (datestr(5:6),'(I2.2)') idate(2)
READ (datestr(7:8),'(I2.2)') idate(3)
READ (timestr(1:2),'(I2.2)') idate(4)
C Convert forecast step into normal date
* print*,idate(1),idate(2),idate(3),idate(4),idate(5)
call newdate(idate,0.,idate2)
idate(1)=idate2(1)
idate(2)=idate2(2)
idate(3)=idate2(3)
idate(4)=idate2(4)
idate(5)=idate2(5)
* print*,idate(1),idate(2),idate(3),idate(4),idate(5)
C Get index of actual level
if ((lnum(pos).eq.3).or.(lnum(pos).eq.4)) then
ilev=1
else
do k=1,nlev
if (glev.eq.level(k)) then
ilev=k
goto 22
endif
enddo
goto 995 ! actual level glev is not in array level
22 continue
endif
C Set variable name and dimension
CALL grib_check(grib_get_size(idgrb,'values',nvals))
CALL grib_check(grib_get_real4_array(idgrb,'values',zsec4,
& nvals))
print*,'nvals,nx*ny ',nvals,nx*ny
varname=vnam(pos)
ndim=4
C Get exponential of LNSP
if (varname.eq.'LNSP') then
varname='PS'
do i=1,nx
do j=1,ny
zsec4(i+(j-1)*nx)=exp(zsec4(i+(j-1)*nx))
enddo
enddo
endif
C Turn the array and scale/shift the data with factor/bias
do i=1,nx
do j=1,ny
field(i+(j-1)*nx)=(zsec4(i+(ny-j)*nx)+bias(pos))*factor(pos)
enddo
enddo
C Close periodic arrays
print*,'periodi,noclose ',periodic,noclose
if (periodic.and.(noclose.eq.0)) then
print*,'Hallo'
if (rotate.eq.1) then
ishift=nint(-xmin/dx)
do j=1,ny
do i=1+ishift,nx
ind1=i+(j-1)*nx
ind2=i-ishift+(j-1)*nx
dummy(ind2)=field(ind1)
enddo
do i=1,ishift
ind1=i+(j-1)*nx
ind2=nx-ishift+i+(j-1)*nx
dummy(ind2)=field(ind1)
enddo
enddo
do i=1,nx*ny
field(i)=dummy(i)
enddo
endif
do j=1,ny
do i=1,nx
ind1=i+(j-1)*(nx+1)
ind2=i+(j-1)*nx
dummy(ind1)=field(ind2)
enddo
dummy((nx+1)+(j-1)*(nx+1))=field(1+(j-1)*nx)
enddo
do i=1,(nx+1)*ny
field(i)=dummy(i)
enddo
endif
* print*,cdfname
C Calculate tstep for actual date
if (onepertime.eq.1) then
tstep=0.
else
call timediff(idate,stdate,tstep)
* print*,idate,stdate,tstep
endif
C If necessary define new variable
if ((onepertime.eq.1).or.
> ((arrcnt(pos).eq.0).and.(tdep(pos).eq.1))) then
do i=1,maxvar
if (onepertime.eq.0) then
if (trim(varname).eq.trim(varnam(i))) goto 40
endif
enddo
* print*,'ilev level ',ilev,level(ilev),nlev,prelev
* print*,pos,idef(pos)
if ((idefine.eq.1).and.(idef(pos).eq.0)) then
call putdef(cdfid,trim(varname),
> ndim,mdv,vardim,varmin,varmax,stag,ierr)
write(*,*)'*** variable ',trim(vnam(pos)),' created'
if (vardim(3).gt.1) idef(pos)=1
lastvar=varname
endif
endif
40 continue
arrcnt(pos)=arrcnt(pos)+1 ! counter for actual variable
C Put data on file
if (onepertime.eq.0) then
IF ((glev.LT.lastlev).AND.(.NOT.prelev)) THEN
C if is quick&dirty for only 36 levels from 60 levels
IF ((lastlev.NE.36).AND.(lastlev.NE.46).AND.
> (lastlev.NE.nlev)) THEN
WRITE(*,*)'unusual bug exit'
GOTO 9999
ENDIF
ENDIF
ENDIF
write(*,41)'*** var ',trim(vnam(pos)),
> ' at time ',tstep,' on level ',glev,
> ' written on cdffile'
41 format(a,a,a,f6.0,a,i4,a)
if (tdep(pos).eq.0) then
call putcdf(cdfid,trim(varname),ndim,
> mdv,vardim,varmin,varmax,stag,field,ierr)
else
print*,cdfid
print*,trim(varname)
print*,tstep
print*,ilev
do j=1,10
print*,j,field(j*nvals/10)
enddo
call putdat(cdfid,trim(varname),
> tstep,ilev,field,ierr)
endif
lastlev=glev ! bug correction q+d 17.Dec.93
C Close NetCDF file
if (prelev) then
if ((onepertime.eq.1).and.(ilev.eq.nlev)) then
call clscdf(cdfid,ierr)
opnfile=.false.
endif
else
* print*,ilev,nlev,level(ilev),nlev2
* print*,ilev,varname,lastvar
if ((onepertime.eq.1).and.(varname.eq.lastvar).and.
> ((level(ilev).eq.real(nlev2)).or.(level(ilev).eq.0.))) then
* print*,'closing file'
call clscdf(cdfid,ierr)
* print*,'file closed'
opnfile=.false.
endif
endif
80 continue
C Get new record from GRIB file
ierr = grib_new_from_file(ifile, idgrb)
IF (idgrb.EQ.-1) THEN
IF (ierr.NE.-1) THEN
CALL grib_check(ierr)
GOTO 9993
ELSE
GOTO 9999 ! end of file is reached
ENDIF
ELSE
GOTO 70
ENDIF
994 stop 'error from subroutine rvarfile: not proper varfile'
995 stop 'error: actual level not defined on constants file'
996 stop 'error: could not open NetCDF file'
999 stop 'date not found on tape 9'
9993 stop 'error from subroutine grib_new_from_file'
9999 continue
C Close NetCDF file
if (onepertime.eq.0) call clscdf(cdfid,ierr)
if (ierr.ne.0) stop 'error when closing file'
WRITE(*,*)'*** end of program FGRBTOCDF status: NORMAL ***'
END
LOGICAL FUNCTION infile (vnshrt,gltyp,snames,levtyp,varcnt,pos)
c ================================================================
c testet, ob die Kombination (ltyp,ivar) in den Arrays levtyp und
c gribnr vorkommen. varcnt ist die Anzahl Eintraege in den Arrays.
c pos gibt die Array-Position des gefundenen Eintrages zurueck.
IMPLICIT NONE
INTEGER maxvar
PARAMETER (maxvar=100)
INTEGER gltyp,levtyp(maxvar),varcnt,pos
CHARACTER*10 vnshrt,snames(maxvar)
INTEGER i, ltyp, ivar
i = 1
300 IF (i.LE.varcnt) THEN
C IF ((TRIM(snames(i)).EQ.TRIM(vnshrt)).AND.
C & (levtyp(i).EQ.gltyp)) THEN
IF (TRIM(snames(i)).EQ.TRIM(vnshrt)) THEN
pos = i
infile = .TRUE.
RETURN
ENDIF
i = i+1
ELSE
GOTO 301
ENDIF
GOTO 300
301 infile = .FALSE.
END
SUBROUTINE rdvarfile(vnam,snames,levty,unit,factor,bias,
> lnum,stg,tdep,p,lval,varcnt,ierr)
C =======================================================
C Variablen-File in Arrays einlesen
IMPLICIT NONE
INTEGER maxvar
PARAMETER(maxvar=100)
CHARACTER*(15) vnam(maxvar)
CHARACTER*(10) snames(maxvar)
CHARACTER*(13) unit(maxvar)
CHARACTER*(1) flag
INTEGER levty(maxvar),lnum(maxvar),
> stg(maxvar),tdep(maxvar),p(maxvar),lval(maxvar)
REAL factor(maxvar),bias(maxvar)
INTEGER i,varcnt,ierr,nt
nt=14 ! number of tape
i=1 ! initialize var-counter
C Read first character of row and decide if it is comment or not
100 READ(nt,10,ERR=123,END=126) flag
IF (flag.EQ."#") GOTO 100 ! don't bother about comments
BACKSPACE nt
121 READ(nt,122, ERR=123, END=126) vnam(i), snames(i), levty(i),
& unit(i), factor(i), bias(i), lnum(i), stg(i), tdep(i), p(i),
& lval(i)
i=i+1
GOTO 100
10 FORMAT(a1)
122 FORMAT(A14,A10,1X,I3,4X,A13,F7.5,2X,F7.2,I7,I4,I6,I3,I5)
123 GOTO 121
126 CONTINUE
varcnt=i-1 ! # of variables in varfile_i
C Check some things
ierr=0 ! initialize error flag
DO i=1,varcnt
IF ((lnum(i).NE.1).AND.(lnum(i).NE.2).AND.(lnum(i).NE.3)
> .AND.(lnum(i).NE.4)) ierr=1
IF ((stg(i).NE.0).AND.(stg(i).NE.1).AND.(stg(i).NE.10).AND.
> (stg(i).NE.11)) ierr=1
IF ((tdep(i).NE.0).AND.(tdep(i).NE.1)) ierr=1
IF ((p(i).NE.0).AND.(p(i).NE.1).AND.(p(i).NE.2)) ierr=1
IF ((lval(i).LT.0).OR.(lval(i).GT.1050)) ierr=1
ENDDO
RETURN
END