C C
C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITIES REF:JRH:14:01:2001 * C * * C * SOURCE : forlib.f * C * TYPE : LIBRARY * C * * C * FUNCTION : Library of Fortran utility routines * C * * C * CONTENTS LATEST VERSION * C * ******** ************** * C * * C * aconv 12:05:89 * C * aread 07:09:89 * C * areadfil 17:06:88 * C * areadfil2 06:01:95 * C * banner 25:05:93 * C * banner2 04:04:95 * C * bisec 10:10:85 * C * caldat 23:05:91 * C * changecase 03:12:90 * C * clip 23:09:86 * C * clop 07:07:89 * C * datin 19:03:91 * C * degmin 22:08:89 * C * deg2degmin 24:03:91 * C * dgasdev3 31:03:95 * C * dheapsort 26:08:92 * C * div1d 01:04:87 * C * div2d 01:08:86 * C * dopen 31:12:86 * C * dran3 24:03:95 * C * dreadfil2 27:01:95 * C * dskopen 02:05:90 * C * dsvbksb 26:08:92 * C * dsvdcmp 26:08:92 * C * dte 04:07:85 * C * dtu 23:05:91 * C * d2rcalc 25:07:91 * C * error_handler 06:01:95 * C * etd 04:07:85 * C * fft 02:09:86 * C * fft2 25:11:87 * C * fit2d 07:07:89 * C * gasdev3 31:03:95 * C * geoginp 24:04:91 * C * geoginpbuff 21:05:90 * C * gsnumber 14:07:88 * C * gssymbol 07:11:90 * C * heapsort 29:08:91 * C * idint2 23:04:91 * C * idplace 18:11:91 * C * inbuf 15:09:93 * C * inilink 11:10:91 * C * inslink 23:03:91 * C * inslink2 05:08:93 * C * intpoint 17:08:94 * C * int2 23:04:91 * C * invmerc 14:10:88 * C * invrob 12:11:98 * C * iosproc 28:08:91 * C * ipdig 03:12:85 * C * iread 07:09:89 * C * ireadfil 07:09:89 * C * ireadfil2 06:01:95 * C * isearch 28:03:95 * C * julday 23:05:91 * C * lenchar 30:09:96 * C * lhschar 07:09:89 * C * lpclr 03:12:85 * C * lpload 30:12:86 * C * lpplot 30:12:86 * C * merc 14:10:88 * C * mxcopy 14:01:86 * C * mxgaus 14:01:86 * C * nchar 31:12:86 * C * newpen 13:07:89 * C * newton 23:07:86 * C * nnonspace 08:08:89 * C * number 17:07:89 * C * opdig 03:12:85 * C * overlayplot 05:06:90 * C * picalc 25:07:91 * C * pinsd 23:08:89 * C * plot 16:11:89 * C * plota 11:08:89 * C * plots 17:07:89 * C * ran3 24:03:95 * C * ra2xy 20:08:85 * C * remlink 11:10:91 * C * rostp 03:07:86 * C * rread 07:09:89 * C * rreadfil 07:09:89 * C * rreadfil2 06:01:95 * C * r2dcalc 25:07:91 * C * sim 23:07:86 * C * sima 15:05:86 * C * simb 15:05:86 * C * solvmx 14:01:86 (minor mod. 18:12:89) * C * srect 14:05:90 * C * svbksb 09:01:92 * C * svdcmp 08:01:92 * C * symbol 13:06:91 * C * timin 14:01:2001 * C * utd 23:05:91 * C * writearray 07:07:89 * C * writearray2 06:01:92 * C * xy2ra 02:07:85 * C * ydif 31:07:86 * C * ydif2d 29:09:86 * C * yesno 19:02:87 * C * yint 30:07:86 * C * yint2d 29:09:86 * C * yrect 22:09:86 * C * yrect2d 29:09:86 * C * * C ****************************************************************************** CBack up subroutine aconv(ain,aout,min,nin,mout,nout,mtrans,ntrans) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : TIDES REF:JRH:12:05:1989 * C * * C * REVISION : ------------- JRH:--:--:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: ACONV * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts array ain(min,nin) to aout(mout,nout) between * C * the limits (mtrans,ntrans) * C * * C ****************************************************************************** dimension ain(min,nin),aout(mout,nout) if(mtrans.gt.min.or.mtrans.gt.mout.or. $ ntrans.gt.nin.or.ntrans.gt.nout) stop ! Error condition do i=1,mout do j=1,nout aout(i,j)=0. ! Initially clear array end do end do do i=1,mtrans do j=1,ntrans aout(i,j)=ain(i,j) end do end do return end CBack up subroutine aread(nin,nout,nlog,anot,acc,aarray,istart,istop,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:04:09:1986 * C * * C * REVISION : Mod. for output of message only if * C * ISTART=0 or ISTOP=0 JRH:12:09:1986 * C * Minor mods. JRH:31:12:1986 * C * Minor mod. JRH:05:01:1987 * C * Minor mod. JRH:17:05:1988 * C * Mod. so that FORM is input without * C * brackets JRH:21:06:1988 * C * Mod. for compilation on transputer JRH:07:09:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: AREAD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads in a set of CHARACTER*40 variables * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Annotation (40 chars.) * C * ACC ..... Carriage-control character * C * (' ' for new line, '$' for same line) * C * AARRAY .. Resultant CHARACTER*40 array * C * ISTART .. Start index of AARRAY * C * ISTOP ... Stop index of AARRAY * C * FORM .... Format for output to log device (40 chars., * C * without brackets) * C * * C ****************************************************************************** character*40 aarray(*) character*40 anot,form character*1 acc character*42 formt ! @7/9/89 logical cont ! @31/12/86 save cont ! @31/12/86 character*12 formout ! &5/1/87 data cont/.false./ ! @11/5/88 if(cont) then ! Continuation of terminal text @31/12/86 write(formout,1) ' ',acc ! &31/12/86 1 format('(',a1,'X,A40,A1',a1,')') ! &5/1/87 else ! Normal text @31/12/86 write(formout,1) '/',acc ! @31/12/86 endif ! @31/12/86 write(nout,formout) anot,' ' ! &5/1/87 write(nlog,formout) anot,' ' ! &5/1/87 if(istart.ne.0..and.istop.ne.0) then ! &31/12/86 read(nin,2) (aarray(i),i=istart,istop) 2 format((a40)) formt='('//form//')' ! @7/9/89 write(nlog,formt) (aarray(i),i=istart,istop) ! &21/6/88 &7/9/89 cont=.false. ! Terminal text not to be continued @31/12/86 else ! @31/12/86 cont=.true. ! Terminal text to be continued @31/12/86 endif ! @12/9/86 return end CBack up subroutine areadfil(nin,nout,nlog,anot,nchar,avar,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1987 * C * * C * REVISION : Mod. for keyword checking JRH:19:01:1987 * C * Simplification JRH:17:06:1988 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: AREADFIL * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads CHARACTER*40 variable from file based on keyword. * C * * C * NIN ..... File input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Keyword in file * C * NCHAR ... Number of characters in ANOT (max. 40) * C * AVAR .... Resultant CHARACTER*40 variable * C * FORM .... Format for output (40 chars., without brackets) * C * * C ****************************************************************************** character*(*) anot character*40 avar character*40 form character*80 buff character*40 blank ! &17/6/88 character*51 formt2 character*14 formt3 data blank/' '/ write(formt2,6) nchar,form 6 format('(1X,A',i2,',A3,',a40,')') write(formt3,5) nchar 5 format('(/A9,A',i2,',A34/)') rewind(nin) 4 read(nin,2,end=3) buff 2 format(a80) if(buff(1:nchar).eq.anot.and. ! &17/6/88 $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found &19/1/87 avar(1:40)=buff(nchar+2:nchar+41) write(nout,formt2) anot,' = ',avar write(nlog,formt2) anot,' = ',avar return else go to 4 ! Read more data endif 3 write(nout,formt3) ' Keyword ',anot, $ ' not found .... program terminated' write(nlog,formt3) ' Keyword ',anot, $ ' not found .... program terminated' stop end CBack up subroutine areadfil2(nin,anot,nchar,avar,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: areadfil2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads CHARACTER*40 variable from file based on keyword. * C * (Modified version of areadfil, without output to operator * C * or log file) * C * * C * nin ..... File input device * C * anot .... Keyword in file * C * nchar ... Number of characters in ANOT (max. 40) * C * avar .... Resultant CHARACTER*40 variable * C * ifail ... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 nin,nchar,ifail character*(*) anot character*40 avar C integer*4 ios logical found character*80 buff C rewind(nin) ios=0 found=.false. do while(ios.eq.0.and..not.found) read(nin,1,iostat=ios) buff 1 format(a80) if(buff(1:nchar).eq.anot.and. $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found avar(1:40)=buff(nchar+2:nchar+41) found=.true. endif end do if(ios.eq.0) then ifail=0 ! Match found and no error else ifail=1 ! No match found endif end CBack up subroutine banner(nout,nlog,nline,lines) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:22:05:1987 * C * * C * REVISION : Changed JMG to CSIRO JRH:06:07:1989 * C * Mods. to licence conditions JRH:15:07:1992 * C * Mods. to make it more general JRH:25:05:1993 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: BANNER * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Writes program banner to terminal and to log file. * C * * C * NOUT ..... Operator output LU * C * NLOG ..... Log output LU * C * NLINE .... No. of input lines * C * LINES .... NLINE lines of text (each of 40 chars.) * C * * C ****************************************************************************** character*40 lines(*) write(nout,1) write(nlog,1) 1 format(////11x, $ '************************************************************' $ /11x, $ '* *') write(nout,2) (lines(i),i=1,nline) write(nlog,2) (lines(i),i=1,nline) 2 format((11x,'* ',a40,' *'/11x, $ '* *')) nline=0 write(nout,3) write(nlog,3) 3 format(11x, $ '* *' $ /11x, $ '* This software is supplied subject to the terms of the *'! &15/7/92 $ /11x, $ '* licence agreement supplied with it. The terms may be *'! &15/7/92 $ /11x, $ '* summarised as : *'! &15/7/92 $ /11x, $ '* *' $ /11x, $ '* 1. The software and associated manual(s) are *'! &15/7/92 $ /11x, $ '* supplied with no warranty, expressed or implied. *'! &15/7/92 $ /11x, $ '* *' $ /11x, C Following 5 lines removed 25/5/93 : C $ '* 2. The software is supplied for non-profit *'! &15/7/92 C $ /11x, C $ '* teaching and research purposes only. Sufficient *'! &15/7/92 C $ /11x, C $ '* copies may be made for these purposes only. *'! &15/7/92 $ '* 2. The software is supplied for the Licensee''s *'!@25/5/93 $ /11x, ! @25/5/93 $ '* computing activities only. Sufficient copies *'! @25/5/93 $ /11x, ! @25/5/93 $ '* may be made for these purposes only. *'! @25/5/93 $ /11x, $ '* *' $ /11x, C Following 5 lines removed 25/5/93 : C $ '* 3. Any modifications to the software source code *'! &15/7/92 C $ /11x, C $ '* should carry a prominent notice stating the *'! &15/7/92 C $ /11x, C $ '* change and the date of that change. *'! &15/7/92 $ '* 3. Any modifications to the software source code *'! @25/5/93 $ /11x, ! @25/5/93 $ '* should be approved by CSIRO and should carry a *'! @25/5/93 $ /11x, ! @25/5/93 $ '* prominent notice stating the change and the date *'! @25/5/93 $ /11x, ! @25/5/93 $ '* of that change. *'! @25/5/93 $ /11x, $ '* *' $ /11x, $ '* 4. This banner is not to be modified and its *'! &15/7/92 $ /11x, $ '* display is not to be inactivated. *'! &15/7/92 $ /11x, $ '* *' $ /11x, $ '* OCEAN MODELLING GROUP, *' ! &6/7/89 $ /11x, $ '* CSIRO DIVISION OF OCEANOGRAPHY, *' ! &6/7/89 $ /11x, $ '* HOBART, TASMANIA, 7000. *' ! &6/7/89 $ /11x, $ '* *' $ /11x, $ '************************************************************') return end CBack up subroutine banner2(nout,nline,lines) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:04:04:1995 * C * * C * REVISION : ---------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: banner2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Writes program banner to terminal. * C * * C * nout ..... Operator output LU * C * nline .... No. of input lines * C * lines .... NLINE lines of text (each of 40 chars.) * C * * C ****************************************************************************** integer*4 nout,nline character*40 lines(*) C write(nout,1) 1 format(////11x, $ '************************************************************' $ /11x, $ '* *') write(nout,2) (lines(i),i=1,nline) 2 format((11x,'* ',a40,' *'/11x, $ '* *')) nline=0 write(nout,3) 3 format(11x, $ '* *' $ /11x, $ '* This software is supplied subject to the terms of the *' $ /11x, $ '* licence agreement supplied with it. The terms may be *' $ /11x, $ '* summarised as : *' $ /11x, $ '* *' $ /11x, $ '* 1. The software and associated manual(s) are *' $ /11x, $ '* supplied with no warranty, expressed or implied. *' $ /11x, $ '* *' $ /11x, $ '* 2. The software is supplied for the Licensee''s *' $ /11x, $ '* computing activities only. Sufficient copies *' $ /11x, $ '* may be made for these purposes only. *' $ /11x, $ '* *' $ /11x, $ '* 3. Any modifications to the software source code *' $ /11x, $ '* should be approved by CSIRO and should carry a *' $ /11x, $ '* prominent notice stating the change and the date *' $ /11x, $ '* of that change. *' $ /11x, $ '* *' $ /11x, $ '* 4. This banner is not to be modified and its *' $ /11x, $ '* display is not to be inactivated. *' $ /11x, $ '* *' $ /11x, $ '* OCEAN MODELLING GROUP, *' $ /11x, $ '* CSIRO DIVISION OF OCEANOGRAPHY, *' $ /11x, $ '* HOBART, TASMANIA, 7000. *' $ /11x, $ '* *' $ /11x, $ '************************************************************') return end CBack up subroutine bisec(f,y,xmin,xmax,nit1,nit2,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:10:10:1986 * C * * C * REVISION : Speeded up JRH:29:06:1997 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: BISEC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Finds approximate solution of Y = F(X) using the ,method * C * of bisection. Initially range XMIN to XMAX is expanded * C * by a factor of 3, up to NIT1 times, until the range * C * brackets the required solution. The range XMIN to XMAX * C * is then reduced by a factor of 2, NIT2 times, ensuring * C * the range still brackets the required solution. * C * * C * F ..... FUNCTION of X * C * Y ..... Value of F(X) for solution * C * XMIN .. Min. value of initial range * C * XMAX .. Max. value of initial range * C * NIT1 .. Max. number of initial expansions * C * NIT2 .. Number of bisections * C * IFAIL . 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** do i=1,nit1 fmin=f(xmin) fmax=f(xmax) if((fmin.le.y.and.fmax.gt.y).or. $ (fmin.gt.y.and.fmax.le.y)) go to 1 xdum=2.*xmin-xmax xmax=2.*xmax-xmin xmin=xdum end do ifail=1 ! Could not find suitable range return 1 do i=1,nit2 xdum=(xmin+xmax)/2. fdum=f(xdum) if((fmin.le.y.and.fdum.gt.y).or. $ (fmin.gt.y.and.fdum.le.y)) then xmax=xdum C if(i.ne.nit2) fmax=f(xmax) ! &29/6/97 if(i.ne.nit2) fmax=fdum ! @29/6/97 else xmin=xdum C if(i.ne.nit2) fmin=f(xmin) ! &29/6/97 if(i.ne.nit2) fmin=fdum ! @29/6/97 endif end do ifail=0 return end CBack up subroutine caldat(iye,mon,idy,ihr,min,sec,julian,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:05:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: CALDAT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts Julian Day to (year, month, day, hour, minute, * C * second) (based on Numerical Recipes) * C * * C * IYE ........ Year * C * MON ........ Month * C * IDY ........ Day * C * IHR ........ Hour * C * MIN ........ Minute * C * SEC ........ Second * C * JULIAN ..... Julian Day (non-negative, but may be * C * non-integer) * C * IFAIL ...... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 julian real*4 sec integer*4 iye,mon,idy,ihr,min,ifail integer*4 igreg,jalpha,ja,jb,jc,jd,je,ijul parameter (igreg=2299161) ! Cross-over to Gregorian Calendar if(julian.lt.0.d0) then ! Negative Julian Day not allowed ifail=1 return endif ijul=idint(julian) ! Integral Julian Day sec=sngl((julian-dble(ijul))*86400.d0)! Seconds from beginning of Jul. Day if(sec.ge.43200.) then ! In next calendar day ijul=ijul+1 sec=sec-43200. ! Adjust from noon to midnight else ! In same calendar day sec=sec+43200. ! Adjust from noon to midnight endif if(sec.ge.86400.) then ! Final check to prevent time 24:00:00 ijul=ijul+1 sec=sec-86400. endif min=int(sec/60.) ! Integral minutes from beginning of day sec=sec-float(min*60) ! Seconds from beginning of minute ihr=min/60 ! Integral hours from beginning of day min=min-ihr*60 ! Integral minutes from beginning of hour if(ijul.ge.igreg)then ! Correction for Gregorian Calendar jalpha=idint((dble(ijul-1867216)-0.25d0)/36524.25d0) ja=ijul+1+jalpha-idint(0.25d0*dble(jalpha)) else ! No correction ja=ijul endif jb=ja+1524 jc=idint(6680.d0+(dble(jb-2439870)-122.1d0)/365.25d0) jd=365*jc+idint(0.25d0*dble(jc)) je=idint(dble(jb-jd)/30.6001d0) idy=jb-jd-idint(30.6001d0*dble(je)) mon=je-1 if(mon.gt.12)mon=mon-12 iye=jc-4715 if(mon.gt.2)iye=iye-1 if(iye.le.0)iye=iye-1 ifail=0 return end CBack up subroutine changecase(ain,aout,n,itype) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:03:12:1990 * C * * C * REVISION : ------------- JRH:--:--:1990 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: CHANGECASE * C * TYPE : MAIN * C * * C * FUNCTION : Changes case of character variable * C * * C * AIN ..... input variable * C * AOUT .... output variable * C * N ....... number of characters in AIN and AOUT * C * ITYPE ... 0 for change to lower case * C * 1 for change to upper case * C * * C ****************************************************************************** character*(*) ain,aout if(itype.eq.0) then ! Change to lower case do i=1,n idum=ichar(ain(i:i)) if(idum.ge.65.and.idum.le.90) then idum=idum+32 aout(i:i)=char(idum) else aout(i:i)=ain(i:i) endif end do return else if(itype.eq.1) then ! Change to upper case do i=1,n idum=ichar(ain(i:i)) if(idum.ge.97.and.idum.le.122) then idum=idum-32 aout(i:i)=char(idum) else aout(i:i)=ain(i:i) endif end do return else ! ITYPE out of range ..... do nothing do i=1,n aout(i:i)=ain(i:i) end do return endif end CBack up subroutine clip(x,y,xlc,xrc,ybc,ytc,lc,lplot) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:23:09:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : PLT1199.FOR * C * ROUTINE NAME: CLIP * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Clips line (X(1),Y(1)) to (X(2),Y(2)) to rectangular * C * window defined by X = XLC to XRC and Y = YBC to YTC. * C * If point clipped, LC() returned as .TRUE.. * C * If line completely off plot, LPLOT returned as .FALSE.. * C * * C ****************************************************************************** dimension x(2),y(2) logical lc(2),lplot logical lout(4,2) do i=1,2 lout(1,i)=(x(i).lt.xlc) lout(2,i)=(x(i).gt.xrc) lout(3,i)=(y(i).lt.ybc) lout(4,i)=(y(i).gt.ytc) lc(i)=.false. end do do i=1,2 3 if(lout(1,i).or.lout(2,i).or.lout(3,i).or.lout(4,i)) then if((lout(1,1).and.lout(1,2)).or. $ (lout(2,1).and.lout(2,2)).or. $ (lout(3,1).and.lout(3,2)).or. $ (lout(4,1).and.lout(4,2))) then lplot=.false. ! Off plot return endif if(lout(1,i)) then ! Crosses LH edge y(i)=y(1)+(y(2)-y(1))*(xlc-x(1))/(x(2)-x(1)) x(i)=xlc lc(i)=.true. else if(lout(2,i)) then ! Crosses RH edge y(i)=y(1)+(y(2)-y(1))*(xrc-x(1))/(x(2)-x(1)) x(i)=xrc lc(i)=.true. else if(lout(3,i)) then ! Crosses bottom edge x(i)=x(1)+(x(2)-x(1))*(ybc-y(1))/(y(2)-y(1)) y(i)=ybc lc(i)=.true. else if(lout(4,i)) then ! Crosses top edge x(i)=x(1)+(x(2)-x(1))*(ytc-y(1))/(y(2)-y(1)) y(i)=ytc lc(i)=.true. endif endif endif endif lout(1,i)=(x(i).lt.xlc) lout(2,i)=(x(i).gt.xrc) lout(3,i)=(y(i).lt.ybc) lout(4,i)=(y(i).gt.ytc) go to 3 endif end do lplot=.true. return ! Visible line is (X(1),Y(1)) to (X(2),Y(2)) end CBack up subroutine clop(ndev) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:09:11:1988 * C * * C * REVISION : Removal of "shared" option in "open" JRH:06:07:1989 * C * "name" changed to "file" in open * C * statement JRH:07:07:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: CLOP * C * TYPE : MAIN * C * * C * FUNCTION : Closes and re-opens file on device NDEV, so as to empty * C * buffer when sharing file. THIS SHOULD ONLY BE USED WITH * C * SEQUENTIAL FILES. * C * * C ****************************************************************************** character*10 formt character*80 filnam inquire(unit=ndev,form=formt,name=filnam,recl=nr) close(unit=ndev) open(unit=ndev,access='APPEND',form=formt,file=filnam,recl=nr, ! &7/7/89 $ status='UNKNOWN') ! &6/7/89 return end CBack up subroutine datin(nin,nout,nlog,anot,iye,mon,idy) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:19:03:1991 * C * * C * REVISION : Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: DATIN * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads in a date, in various formats * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Annotation (40 chars.) * C * IYE ..... Year * C * MON ..... Month * C * IDY ..... Day * C * * C * NOTE : Main constraint is that day is input BEFORE year * C * * C ****************************************************************************** integer*4 nin,nout,nlog,iye,mon,idy character*40 anot integer*4 idmon(12) integer*4 i,idum,ind logical alpha character*80 buff character*3 amon(12) data amon/'JAN','FEB','MAR','APR','MAY','JUN', $ 'JUL','AUG','SEP','OCT','NOV','DEC'/ data idmon/ 31 , 28 , 31 , 30 , 31 , 30 , $ 31 , 31 , 30 , 31 , 30 , 31 / 4 write(nout,1) anot write(nlog,1) anot 1 format(1x,a40) read(nin,2,err=4) buff(1:80) 2 format(a80) write(nlog,3) buff(1:80) 3 format(1x,a80) call changecase(buff(1:80),buff(1:80),80,1) ! Change to upper case alpha=.false. do i=1,12 ind=index(buff(1:80),amon(i)) if(ind.ne.0) then ! Found a matching month mon=i buff(ind:ind+2)=' ' ! Delete month alpha=.true. ! Alphabetic month go to 6 endif end do 6 do i=1,80 ! First remove all non-numeric characters idum=ichar(buff(i:i)) if(idum.lt.48.or.idum.gt.57) buff(i:i)=' ' end do if(alpha) then ! Alphabetic month read(buff(1:80),*,err=4) idy,iye else read(buff(1:80),*,err=4) idy,mon,iye endif if(iye.le.99) iye=iye+1900 ! Cope with two digit year (assume 20th C.) if(iye.le.1900.or.iye.ge.2100) go to 4 ! Set range of years if(mon.lt.1.or.mon.gt.12) go to 4 ! Check range of months if(mon.eq.2) then ! Special check for Feb. if((iye/4)*4.eq.iye) then ! Leap year if(idy.lt.1.or.idy.gt.29) go to 4 else ! Non-leap year if(idy.lt.1.or.idy.gt.28) go to 4 endif else if(idy.lt.1.or.idy.gt.idmon(mon)) go to 4 ! Error ..... re-input endif return end CBack up character*29 function degmin(ang) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:10:1988 * C * * C * REVISION : Calculation of ANG/D2R outside * C * intrinsic functions (otherwise Sun * C * sometimes gives different results for * C * IDINT(ANG/D2R) and DINT(ANG/D2R)) JRH:22:08:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DEGMIN * C * TYPE : CHARACTER*29 FUNCTION * C * * C * FUNCTION : Converts ANG (in radians) to DEGMIN (CHARACTER*29) as * C * degrees and decimal minutes. * C * * C ****************************************************************************** real*8 ang,d2r,ddum ! &22/8/89 character*1 asign d2r=datan(1.d0)/45.d0 ! Degrees to radians if(ang.ge.0.) then asign=' ' else asign='-' endif ddum=ang/d2r ! @22/8/89 write(degmin,1) asign,iabs(idint(ddum)), ! @22/8/89 $ (dabs(ddum)-dabs(dint(ddum)))*60.d0 ! @22/8/89 1 format(a1,i3,' degrees, ',f7.4,' minutes') return end CBack up subroutine deg2degmin(ang,atype,ndec,ideg,min1,min2,adir) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:24:03:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: DEG2DEGMIN * C * TYPE : SUBOUTINE * C * * C * FUNCTION : Converts lat. or long. (degrees) to degrees and decimal * C * minutes, and alphabetic direction * C * * C * ANG ..... input lat. or long. (degrees) * C * ATYPE ... "LONG" for longitude or "LAT " for latitude * C * NDEC .... required no. of decimal places for minutes * C * IDEG .... output degrees * C * MIN1 .... output integral minutes * C * MIN2 .... output fractional minutes * C * ADIR .... 'E' (+ve) or 'W' (-ve) for longitude or * C * 'N' (+ve) or 'S' (-ve) for latitude * C * * C ****************************************************************************** real*4 ang,rmin integer*4 ndec,ideg,min1,min2 character*4 atype character*1 adir ideg=int(abs(ang)) rmin=(abs(ang)-float(ideg))*60. min1=int(rmin) min2=nint((rmin-float(min1))*(10**ndec)) if(min2.eq.10**ndec) then min2=0 min1=min1+1 endif if(min1.eq.60) then min1=0 ideg=ideg+1 endif if(atype.eq.'LONG'.or.atype.eq.'long') then if(ang.gt.0.) then adir='E' else adir='W' endif else if(atype.eq.'LAT '.or.atype.eq.'lat ') then if(ang.gt.0.) then adir='N' else adir='S' endif else adir=' ' ! Leave as blank endif return end CBack up real*8 function dgasdev3(idum) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:31:03:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: dgasdev3 * C * TYPE : real*8 function * C * * C * FUNCTION : Random number generator yielding normal distribution * C * with zero mean and unit variance (real*8 version based on * C * Numerical Recipes). * C * * C ****************************************************************************** integer*4 idum C real*8 v1,v2,r,fac,gset real*8 dran3 integer*4 iset data iset/0/ save iset,gset if (iset.eq.0) then 1 v1=2.d0*dran3(idum)-1.d0 v2=2.d0*dran3(idum)-1.d0 r=v1**2+v2**2 if(r.ge.1.d0)go to 1 fac=dsqrt(-2.d0*dlog(r)/r) gset=v1*fac dgasdev3=v2*fac iset=1 else dgasdev3=gset iset=0 endif return end CBack up subroutine dheapsort(ain,aout,ind,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:26:08:1992 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB .FVS * C * ROUTINE NAME: DHEAPSORT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Heapsort based on Numerical Recipes subroutine SORT2 * C * - D.P. version * C * * C * AIN ..... Array to be sorted (unchanged on output) * C * AOUT .... Resultant sorted array (increasing) * C * IND ..... Array of sorted indices * C * N ....... Size of arrays AIN and AOUT * C * * C ****************************************************************************** real*8 ain(*),aout(*) integer*4 ind(*) integer*4 n real*8 rra integer*4 i,j,l,ir,idum l=n/2+1 ir=n do i=1,n aout(i)=ain(i) ! Copy input array to output array ind(i)=i ! Generate initial idum array end do if(n.eq.1) return ! Special for only one record 10 continue if(l.gt.1)then l=l-1 rra=aout(l) idum=ind(l) else rra=aout(ir) idum=ind(ir) aout(ir)=aout(1) ind(ir)=ind(1) ir=ir-1 if(ir.eq.1)then aout(1)=rra ind(1)=idum return endif endif i=l j=l+l 20 if(j.le.ir)then if(j.lt.ir)then if(aout(j).lt.aout(j+1))j=j+1 endif if(rra.lt.aout(j))then aout(i)=aout(j) ind(i)=ind(j) i=j j=j+j else j=ir+1 endif go to 20 endif aout(i)=rra ind(i)=idum go to 10 end CBack up subroutine div1d(ain,imaxin,aout,imaxout,ifac,zero,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:01:08:1986 * C * * C * REVISION : Minor mod. JRH:01:04:1987 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DIV1D * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Sub-divides 1-D array of data using parabolic * C * interpolation. * C * * C * AIN(I) ..... input array * C * IMAXIN ..... max. index of AIN for calculations * C * AOUT(I) .... output array * C * IMAXOUT .... max. index of AOUT for calculations * C * IFAC ....... division factor in I * C * ZERO ....... "base" level of AIN * C * IFAIL ...... 0 on exit if successful * C * 1 on exit if unsuccessful * C * * C ****************************************************************************** dimension ain(*),aout(*) do ii=1,imaxout aout(ii)=zero ! Clear AOUT to base level end do imaxd=(imaxin-1)*ifac+1 ! Required space in AOUT if(imaxd.gt.imaxout) then ifail=1 return endif do i=1,imaxin ! Step through I dum=ain(i)-zero ! Values relative to base if(dum.lt.0.) dum=0. ! Set values below base to base level ain(i)=dum end do aout(1)=ain(1)+zero do i=1,imaxin-1 ! Step through I in AIN d1l=d1r ! Use "old" RH derivative d2l=d2r ! " " " " if(i.ne.imaxin-1) then ! Not at RH end d1r=ain(i+2)-ain(i) ! 1st derivative, RH curve d2r=ain(i+2)+ain(i)-2*ain(i+1) ! 2nd " " " endif ioff=(i-1)*ifac+1 do ii=1,ifac ! Step within an interpolation interval xl=float(ii)/float(ifac) xr=xl-1. c1l=xl/2. c2l=xl*xl/2. c1r=xr/2. c2r=xr*xr/2. C Note checks for interpolation in vicinity of boundary of "real data" C and "no data" (the latter to be output at the level of the bottom of C the base) - following scheme preserves sharp step here ..... if(ain(i).eq.0..or.ain(i+1).eq.0.) then ! One end at bottom of base if(ii.ne.ifac) then dum=0. ! Set all to bottom of base else dum=ain(i+1) ! except for RH end endif else if(i.eq.1) then ! LH end dum=ain(i+1)+d1r*c1r+d2r*c2r ! RH parabola else if(i.eq.imaxin-1) then ! RH end dum=ain(i)+d1l*c1l+d2l*c2l ! LH parabola else ! Other if(ain(i-1).eq.0.) then ! Bottom of base is to left if(ain(i+2).eq.0.) then ! Bottom of base is also to right dum=-ain(i)*xr+ain(i+1)*xl ! Linear interp. else ! Bottom of base is not to right dum=ain(i+1)+d1r*c1r+d2r*c2r ! RH parabola endif else if(ain(i+2).eq.0.) then ! Bottom of base is to right dum=ain(i)+d1l*c1l+d2l*c2l ! LH parablola else dum=(ain(i)+d1l*c1l ! LH parabola $ +d2l*c2l)*(-xr) ! LH parabola $ +(ain(i+1)+d1r*c1r ! RH parabola $ +d2r*c2r)*xl ! RH parabola endif endif endif endif endif if(dum.lt.0.) dum=0. aout(ii+ioff)=dum+zero end do end do return end CBack up subroutine div2d(ain,imaxin,imaxina,jmaxin, $ aout,imaxout,imaxouta,jmaxout, $ ifac,jfac,zero,ifail, $ work1,work2,work3,work4,work5) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:01:08:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DIV2D * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Sub-divides 2-D array of data using parabolic * C * interpolation. * C * * C * AIN(I,J) ... input array * C * IMAXIN ..... max. index of AIN for calculations * C * IMAXINA .... first dimension of AIN * C * JMAXIN ..... max. index of AIN for calculations * C * AOUT(I,J) .. output array * C * IMAXOUT .... max. index of AOUT for calculations * C * IMAXOUTA ... first dimension of AOUT * C * JMAXOUT .... max. index of AOUT for calculations * C * IFAC ....... division factor in I * C * JFAC ....... division factor in J * C * ZERO ....... "base" level of AIN * C * IFAIL ...... 0 on exit if successful * C * 1 on exit if unsuccessful * C * WORK1 ...... workspace array (dim. at least IMAXIN) * C * WORK2 ...... workspace array (dim. at least IMAXOUT) * C * WORK3....... workspace array (dim. at least JMAXIN) * C * WORK4....... workspace array (dim. at least JMAXOUT) * C * WORK5 ...... workspace array (first dim. = IMAXOUTA, * C * second dim. at least JMAXIN) * C * * C ****************************************************************************** dimension ain(imaxina,*),aout(imaxouta,*) dimension work1(*),work2(*),work3(*) dimension work4(*),work5(imaxouta,*) do j=1,jmaxin do i=1,imaxin work1(i)=ain(i,j) end do call div1d(work1,imaxin,work2,imaxout,ifac,zero,ifail) if(ifail.eq.1) return do i=1,imaxout work5(i,j)=work2(i) end do end do do i=1,imaxout do j=1,jmaxin ! &4/9/86 work3(j)=work5(i,j) end do call div1d(work3,jmaxin,work4,jmaxout,jfac,zero,ifail) if(ifail.eq.1) return do j=1,jmaxout aout(i,j)=work4(j) end do end do return end CBack up subroutine dopen(nin,nout,ndev,anot,stat) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:02:07:1985 * C * * C * REVISION : Minor mod. JRH:31:12:1986 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DOPEN * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Interactive routine for opening disc file. * C * * C ****************************************************************************** character*40 anot character*10 stat character*20 filnam write(nout,1) anot 1 format(/1x,a40) read(nin,2) filnam 2 format(a20) open(unit=ndev,file=filnam,status=stat) return end CBack up real*8 function dran3(idum) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:24:03:1995 * C * * C * REVISION : Change in order of save and data * C * statements for safety JRH:29:03:2001 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: dran3 * C * TYPE : real*8 function * C * * C * FUNCTION : Random number generator (real*8 version based on * C * Numerical Recipes). * C * * C ****************************************************************************** integer*4 idum C real*8 fac integer*4 mbig,mseed,mz parameter (mbig=1000000000,mseed=161803398,mz=0,fac=1.d-9) integer*4 ma(55) integer*4 iff,inext,inextp,mj,mk,i,ii,k save inext,inextp,ma,iff ! Mod. to Numerical Recipes code data iff /0/ if(idum.lt.0.or.iff.eq.0)then iff=1 mj=mseed-iabs(idum) mj=mod(mj,mbig) ma(55)=mj mk=1 do 11 i=1,54 ii=mod(21*i,55) ma(ii)=mk mk=mj-mk if(mk.lt.mz)mk=mk+mbig mj=ma(ii) 11 continue do 13 k=1,4 do 12 i=1,55 ma(i)=ma(i)-ma(1+mod(i+30,55)) if(ma(i).lt.mz)ma(i)=ma(i)+mbig 12 continue 13 continue inext=0 inextp=31 idum=1 endif inext=inext+1 if(inext.eq.56)inext=1 inextp=inextp+1 if(inextp.eq.56)inextp=1 mj=ma(inext)-ma(inextp) if(mj.lt.mz)mj=mj+mbig ma(inext)=mj dran3=mj*fac return end CBack up subroutine dreadfil2(nin,anot,nchar,var,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:01:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: dreadfil2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads REAL*8 variable from file based on keyword. * C * (Modified version of areadfil2) * C * * C * nin ..... File input device * C * anot .... Keyword in file * C * nchar ... Number of characters in ANOT (max. 40) * C * var ..... Resultant REAL*8 variable * C * ifail ... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 var integer*4 nin,nchar,ifail character*(*) anot C integer*4 ios logical found character*80 buff C rewind(nin) ios=0 found=.false. do while(ios.eq.0.and..not.found) read(nin,1,iostat=ios) buff 1 format(a80) if(buff(1:nchar).eq.anot.and. $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found read(buff(nchar+2:80),*,iostat=ios) var found=.true. endif end do if(ios.eq.0) then ifail=0 ! Match found and no error else ifail=1 ! No match found endif end CBack up subroutine dskopen(nin,nout,nlog,ndev,nbt,anot,stat) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:12:01:1987 * C * * C * REVISION : Inclusion of binary file option JRH:21:01:1987 * C * Minor mod. JRH:24:01:1987 * C * Mod. to allow direct access for * C * binary file JRH:18:02:1987 * C * Mod. to include INQUIRE JRH:31:03:1987 * C * Mod. so that files are always SHARED JRH:09:11:1988 * C * Removal of "shared" option in "open" JRH:06:07:1989 * C * "recordsize" changed to "recl" JRH:12:07:1989 * C * Mods. for change from words to bytes * C * in "open" JRH:12:07:1989 * C * Mod. to INQUIRE option, since UNIX * C * direct-access binary files do not store * C * record length. It is now assumed that, * C * when this option is used, the file is * C * DIRECT ACCESS BINARY and that first 4 * C * bytes hold (no. bytes)/4 (ie. no. of * C * VMS words). JRH:19:07:1989 * C * Mod. (for SUN) so that record length * C * omitted for sequential direct-access * C * file JRH:22:08:1989 * C * Expansion of FILNAM to 30 characters JRH:22:09:1989 * C * Expansion of FILNAM to 40 characters JRH:02:05:1990 * C * Minor modification to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DSKOPEN * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Interactive routine for opening disc file. * C * Modified version of DOPEN with O/P to log file. * C * * C * NOTE : Log file must be first file to be openned. * C * * C * NIN ..... Operator input LU (5) * C * NOUT .... Operator output LU (6) * C * NLOG .... Log file LU * C * NDEV .... Device LU to be openned * C * NBT .... For ASCII file, 0 * C * For binary sequential access file, no. of * C * bytes per record * C * For binary direct access file, -(no. of * C * bytes per record) * C * ANOT .... Annotation to appear on operator's terminal * C * (40 chars.) * C * STAT .... (a) 'INQUIRE' .... File is understood to * C * exist and to be binary, and no. of bytes * C * per record is returned in NBT * C * (b) otherwise, STAT is status of file * C * * C ****************************************************************************** character*40 anot character*10 stat,status,acc ! &31/3/87 character*40 filnam ! &22/9/89 &2/5/90 write(nout,1) anot,' ' ! &24/1/87 1 format(/1x,a40,a1) ! &24/1/87 read(nin,2) filnam 2 format(a40) ! &22/9/89 &2/5/90 if(nbt.eq.0) then ! ASCII @21/1/87 &12/7/89 open(unit=ndev,file=filnam,status=stat) ! &9/11/88 &6/7/89 else ! Binary @21/1/87 if(nbt.gt.0) then ! Sequential access @31/3/87 &12/7/89 acc='SEQUENTIAL' ! @31/3/87 else ! Direct access @31/3/87 acc='DIRECT' ! @31/3/87 endif ! @31/3/87 if(stat.eq.'INQUIRE') then ! @31/3/87 status='OLD' ! @31/3/87 C inquire(file=filnam,recl=nbyte) ! Find record length @31/3/87 &19/7/89 C (Vax Note : record length is apparently given in bytes if file is not C openned) ! &12/7/89 open(unit=ndev,file=filnam,status=status, ! @19/7/89 $ form='UNFORMATTED',recl=4, ! @19/7/89 $ access='DIRECT') ! @19/7/89 read(ndev,rec=1) imax ! @19/7/89 nbyte=imax*4 ! @19/7/89 close(unit=ndev) ! @19/7/89 nbt=nbyte ! @31/3/87 &12/7/89 else ! @31/3/87 status=stat ! @31/3/87 nbyte=iabs(nbt) ! Record length given @31/3/87 &12/7/89 endif ! @31/3/87 if(acc.eq.'SEQUENTIAL') then ! @22/8/89 open(unit=ndev,file=filnam,status=status, ! @22/8/89 $ form='UNFORMATTED', ! @22/8/89 $ access=acc) ! @22/8/89 else ! @22/8/89 open(unit=ndev,file=filnam,status=status, ! @31/3/87 $ form='UNFORMATTED',recl=nbyte, ! @31/3/87 &12/7/89 $ access=acc) ! &31/3/87 &9/11/88 &6/7/89 endif ! @22/8/89 endif ! @21/1/87 write(nlog,3) anot,filnam ! &19/2/87 3 format(/1x,a40,1x,a40) ! &19/2/87 &22/9/89 &2/5/90 return end CBack up subroutine dsvbksb(u,w,v,m,n,mp,np,b,x,tmp) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:26:08:1992 * C * * C * REVISION : ------------- JRH:--:--:1992 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: DSVBKSB * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Singular value decomposition solution * C * (from Numerical Recipes - D.P. version of SVBKSB) * C * * C * U ..... Input M by N matrix * C * W ..... Input N element weight vector * C * V ..... Input N by N matrix ( NOT the transpose of "V") * C * M ..... Number of rows of U (M.ge.N) * C * N ..... Number of columns of U (M.ge.N) * C * MP .... Physical number of rows of U * C * NP .... Physical number of columns of U * C * B ..... Input M element vector (right hand side) * C * X ..... Output N element solution vector * C * TMP ... Workspace N element vector * C * * C ****************************************************************************** real*8 u(mp,np),w(np),v(np,np),b(mp),x(np),tmp(*) integer*4 m,n,mp,np real*8 s integer*4 i,j,jj do 12 j=1,n s=0. if(w(j).ne.0.)then do 11 i=1,m s=s+u(i,j)*b(i) 11 continue s=s/w(j) endif tmp(j)=s 12 continue do 14 j=1,n s=0. do 13 jj=1,n s=s+v(j,jj)*tmp(jj) 13 continue x(j)=s 14 continue return end CBack up subroutine dsvdcmp(a,m,n,mp,np,u,w,v,rv1,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:26:08:1992 * C * * C * REVISION : ------------- JRH:--:--:1992 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: DSVDCMP * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Singular value decomposition solution * C * (from Numerical Recipes - D.P. version of SVDCMP) * C * * C * A ..... Input M by N matrix * C * M ..... Number of rows of A (M.ge.N) * C * N ..... Number of columns of A (M.ge.N) * C * MP .... Physical number of rows of A * C * NP .... Physical number of columns of A * C * U ..... Output M by N matrix * C * W ..... Output N element weight vector * C * V ..... Output N by N matrix (NOT the transpose of "V") * C * RV1 ... Workspace N element vector * C * IFAIL . 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 a(mp,np),u(mp,np),w(np),v(np,np),rv1(*) integer*4 m,n,mp,np,ifail real*8 f,g,h,scale,anorm,s,c,x,y,z integer*4 i,j,k,l,its,nm if(m.lt.n) then ifail=1 return endif g=0.0 scale=0.0 anorm=0.0 do i=1,m ! Copy A to U do j=1,n u(i,j)=a(i,j) end do end do do 25 i=1,n l=i+1 rv1(i)=scale*g g=0.0 s=0.0 scale=0.0 if (i.le.m) then do 11 k=i,m scale=scale+abs(u(k,i)) 11 continue if (scale.ne.0.0) then do 12 k=i,m u(k,i)=u(k,i)/scale s=s+u(k,i)*u(k,i) 12 continue f=u(i,i) g=-sign(sqrt(s),f) h=f*g-s u(i,i)=f-g if (i.ne.n) then do 15 j=l,n s=0.0 do 13 k=i,m s=s+u(k,i)*u(k,j) 13 continue f=s/h do 14 k=i,m u(k,j)=u(k,j)+f*u(k,i) 14 continue 15 continue endif do 16 k= i,m u(k,i)=scale*u(k,i) 16 continue endif endif w(i)=scale *g g=0.0 s=0.0 scale=0.0 if ((i.le.m).and.(i.ne.n)) then do 17 k=l,n scale=scale+abs(u(i,k)) 17 continue if (scale.ne.0.0) then do 18 k=l,n u(i,k)=u(i,k)/scale s=s+u(i,k)*u(i,k) 18 continue f=u(i,l) g=-sign(sqrt(s),f) h=f*g-s u(i,l)=f-g do 19 k=l,n rv1(k)=u(i,k)/h 19 continue if (i.ne.m) then do 23 j=l,m s=0.0 do 21 k=l,n s=s+u(j,k)*u(i,k) 21 continue do 22 k=l,n u(j,k)=u(j,k)+s*rv1(k) 22 continue 23 continue endif do 24 k=l,n u(i,k)=scale*u(i,k) 24 continue endif endif anorm=max(anorm,(abs(w(i))+abs(rv1(i)))) 25 continue do 32 i=n,1,-1 if (i.lt.n) then if (g.ne.0.0) then do 26 j=l,n v(j,i)=(u(i,j)/u(i,l))/g 26 continue do 29 j=l,n s=0.0 do 27 k=l,n s=s+u(i,k)*v(k,j) 27 continue do 28 k=l,n v(k,j)=v(k,j)+s*v(k,i) 28 continue 29 continue endif do 31 j=l,n v(i,j)=0.0 v(j,i)=0.0 31 continue endif v(i,i)=1.0 g=rv1(i) l=i 32 continue do 39 i=n,1,-1 l=i+1 g=w(i) if (i.lt.n) then do 33 j=l,n u(i,j)=0.0 33 continue endif if (g.ne.0.0) then g=1.0/g if (i.ne.n) then do 36 j=l,n s=0.0 do 34 k=l,m s=s+u(k,i)*u(k,j) 34 continue f=(s/u(i,i))*g do 35 k=i,m u(k,j)=u(k,j)+f*u(k,i) 35 continue 36 continue endif do 37 j=i,m u(j,i)=u(j,i)*g 37 continue else do 38 j= i,m u(j,i)=0.0 38 continue endif u(i,i)=u(i,i)+1.0 39 continue do 49 k=n,1,-1 do 48 its=1,30 do 41 l=k,1,-1 nm=l-1 if ((abs(rv1(l))+anorm).eq.anorm) go to 2 if ((abs(w(nm))+anorm).eq.anorm) go to 1 41 continue 1 c=0.0 s=1.0 do 43 i=l,k f=s*rv1(i) if ((abs(f)+anorm).ne.anorm) then g=w(i) h=sqrt(f*f+g*g) w(i)=h h=1.0/h c= (g*h) s=-(f*h) do 42 j=1,m y=u(j,nm) z=u(j,i) u(j,nm)=(y*c)+(z*s) u(j,i)=-(y*s)+(z*c) 42 continue endif 43 continue 2 z=w(k) if (l.eq.k) then if (z.lt.0.0) then w(k)=-z do 44 j=1,n v(j,k)=-v(j,k) 44 continue endif go to 3 endif if (its.eq.30) then ifail=1 return endif x=w(l) nm=k-1 y=w(nm) g=rv1(nm) h=rv1(k) f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y) g=sqrt(f*f+1.0) f=((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x c=1.0 s=1.0 do 47 j=l,nm i=j+1 g=rv1(i) y=w(i) h=s*g g=c*g z=sqrt(f*f+h*h) rv1(j)=z c=f/z s=h/z f= (x*c)+(g*s) g=-(x*s)+(g*c) h=y*s y=y*c do 45 nm=1,n x=v(nm,j) z=v(nm,i) v(nm,j)= (x*c)+(z*s) v(nm,i)=-(x*s)+(z*c) 45 continue z=sqrt(f*f+h*h) w(j)=z if (z.ne.0.0) then z=1.0/z c=f*z s=h*z endif f= (c*g)+(s*y) x=-(s*g)+(c*y) do 46 nm=1,m y=u(nm,j) z=u(nm,i) u(nm,j)= (y*c)+(z*s) u(nm,i)=-(y*s)+(z*c) 46 continue 47 continue rv1(l)=0.0 rv1(k)=f w(k)=x 48 continue 3 continue 49 continue ifail=0 return end CBack up subroutine dte(iye,mon,idy,ihr,min,sec,tim) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : GENERAL REF:JRH:04:07:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: DTE * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts daytime to elapsed time * C * * C * Daytime : * C * IYE ..... Year * C * MON ..... Month * C * IDY ..... Day * C * IHR ..... Hour * C * MIN ..... Minute * C * SEC ..... Second * C * * C * Elapsed time : * C * TIM ..... Time in seconds from beginning of year * C * * C * NOTE that current version (with D.P. (64 bit) * C * internal computations, but S.P. (32 bit) TIM) will * C * generally be correct to +/- 2 secs. However, a time * C * in exact minutes (ie. SEC = 0.) is computed exactly. * C * * C ****************************************************************************** double precision dtim dimension nd(12) data nd/0,31,59,90,120,151,181,212,243,273,304,334/ dtim=((dble(float(nd(mon)+idy-1))*24.d0 $ +dble(float(ihr)))*60.d0 $ +dble(float(min)))*60.d0 $ +dble(sec) C Leap year correction ..... if((iye/4)*4.eq.iye.and.mon.gt.2) dtim=dtim+86400.d0 tim=sngl(dtim) return end CBack up subroutine dtu(iye,mon,idy,ihr,min,sec,utim,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:05:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: DTU * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts daytime to Unix Time * C * * C * (Unix Time starts at 0000 on 1 Jan. 1970) * C * * C * IYE ........ Year * C * MON ........ Month * C * IDY ........ Day * C * IHR ........ Hour * C * MIN ........ Minute * C * SEC ........ Second * C * UTIM ....... Unix time (seconds) * C * IFAIL ...... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 utim real*4 sec integer*4 iye,mon,idy,ihr,min,ifail real*8 jd0,julian logical first save jd0,first data first/.true./ if(first) then ! Compute zero of Unix Time in Julian days call julday(1970,1,1,0,0,0.,jd0,ifail) if(ifail.ne.0) return ! Error first=.false. endif call julday(iye,mon,idy,ihr,min,sec,julian,ifail) if(ifail.ne.0) return ! Error utim=(julian-jd0)*86400.d0 return end CBack up subroutine d2rcalc(d2r) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:25:07:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: D2RCALC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Returns the value of D2R (degrees to radians constant) * C * * C ****************************************************************************** real*4 d2r d2r=atan(1.)*4./180. return end CBack up subroutine error_handler(ifail,error_point) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:06:01:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: error_handler * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Handles error (ifail.ne.0) * C * * C ****************************************************************************** integer*4 ifail,error_point C if(ifail.ne.0) then write(6,1) ifail,error_point 1 format(/' ifail returned as ',i5,' at error point ',i5, $ ' ..... program terminated'/) stop endif return end CBack up subroutine etd(iye,mon,idy,ihr,min,sec,tim) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : GENERAL REF:JRH:04:07:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: ETD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts elapsed time to daytime. * C * Inputs are IYE and TIM. * C * IYE and TIM are modified if TIM is negative or * C * greater than year length. * C * * C * Daytime : * C * IYE ..... Year * C * MON ..... Month * C * IDY ..... Day * C * IHR ..... Hour * C * MIN ..... Minute * C * SEC ..... Second * C * * C * Elapsed time : * C * TIM ..... Time in seconds from beginning of year * C * * C * NOTE that current version (with D.P. (64 bit) * C * internal computations, but S.P. (32 bit) TIM) will * C * generally be correct to +/- 2 secs. However, a time * C * in exact minutes (ie. SEC = 0.) is computed exactly. * C * * C ****************************************************************************** double precision dtim,dyl,didy,dihr,dmin dimension nd(13,2) data nd/0,31,59,90,120,151,181,212,243,273,304,334,365, $ 0,31,60,91,121,152,182,213,244,274,305,335,366/ dtim=dble(tim) if(dtim.lt.0.d0) go to 3 5 l=1 C Leap year test ..... if((iye/4)*4.eq.iye) l=2 dyl=dble(float(nd(13,l)))*86400.d0 if(dtim.lt.dyl) go to 4 iye=iye+1 dtim=dtim-dyl go to 5 3 iye=iye-1 l=1 C Leap year test ..... if((iye/4)*4.eq.iye) l=2 dyl=dble(float(nd(13,l)))*86400.d0 dtim=dtim+dyl if(dtim.lt.0.d0) go to 3 4 dmin=dint(dtim/60.d0) sec=sngl(dtim-dmin*60.d0) dihr=dint(dmin/60.d0) min=idint(dmin-dihr*60.d0+0.5d0) didy=dint(dihr/24.d0) ihr=idint(dihr-didy*24.d0+0.5d0) idy=idint(didy+1.5d0) do 1 i=1,13 if(nd(i,l).ge.idy) go to 2 1 continue 2 mon=i-1 idy=idy-nd(mon,l) tim=sngl(dtim) return end CBack up subroutine fft(fin,fout,ln,itype) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:02:09:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: FFT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Fast Fourier Transform * C * * C * FIN .... Array to be transformed * C * FOUT ... Transformed array * C * LN ..... LOG2 of no. of data points * C * ITYPE .. +1 for forward transform * C * -1 for reverse transform * C * * C * Adapted from : * C * * C * Gonzalez, R.C. and Wintz, P., 1977. * C * Digital Image Procssing, Addison-Wesley Publishing Co. * C * * C ****************************************************************************** complex fin(*),fout(*),u,w,t pi=3.14159265 n=2**ln nv2=n/2 nm1=n-1 do i=1,n fout(i)=fin(i) end do j=1 do i=1,nm1 if(i.ge.j) go to 1 t=fout(j) fout(j)=fout(i) fout(i)=t 1 k=nv2 2 if(k.ge.j) go to 3 j=j-k k=k/2 go to 2 3 j=j+k end do do l=1,ln le=2**l le1=le/2 u=(1.0,0.0) w=cmplx(cos(pi/le1),-sin(pi/le1)*float(itype)) do j=1,le1 do i=j,n,le ip=i+le1 t=fout(ip)*u fout(ip)=fout(i)-t fout(i)=fout(i)+t end do u=u*w end do end do if(itype.eq.1) then ! Forward transform do i=1,n fout(i)=fout(i)/float(n) end do endif return end CBack up subroutine fft2(fin2,fout2,lnx,lny,nxmax,itype,fin1,fout1) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:02:09:1986 * C * * C * REVISION : Special code for square arrays * C * removed JRH:25:11:1987 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: FFT2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : 2-D fast Fourier transform * C * * C * FIN2 .... input 2-D COMPLEX array * C * FOUT2 ... output 2-D COMPLEX array * C * LNX ..... LOG2(no. values in X to be transformed) * C * LNY ..... LOG2(no. values in Y to be transformed) * C * NXMAX ... first dimension of FIN2, FOUT2 * C * ITYPE ... 1 .... forward transform * C * -1 ... reverse transform * C * FIN1 .... COMPLEX 1-D work array of dimension larger * C * than : 2**LNX AND 2**LNY * C * FOUT1 ... " " " " " " " * C * " " " " * C * * C ****************************************************************************** complex fin2(nxmax,*),fout2(nxmax,*) complex fin1(*),fout1(*) nx=2**lnx ny=2**lny do i=1,nx do j=1,ny fin1(j)=fin2(i,j) end do call fft(fin1,fout1,lny,itype) do j=1,ny fout2(i,j)=fout1(j) end do end do do j=1,ny do i=1,nx fin1(i)=fout2(i,j) end do call fft(fin1,fout1,lnx,itype) do i=1,nx fout2(i,j)=fout1(i) end do end do C Following code removed 25/11/87 : C IF(LNX.EQ.LNY) THEN ! Special for square arrays C DO I=1,NX C DO J=1,NY C IF(ITYPE.EQ.1) THEN ! Forward transform C FOUT2(I,J)=FOUT2(I,J)*CMPLX(FLOAT(NX)) C ELSE ! Reverse transform C FOUT2(I,J)=FOUT2(I,J)/CMPLX(FLOAT(NX)) C ENDIF C END DO C END DO C ENDIF return end CBack up subroutine fit2d(xa,ya,za,ca,ipow,ndata,nterm,error,x,y,z, $ imode,ixint,iyint,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILTY REF:JRH:15:04:1987 * C * * C * REVISION : Mod. to parameter JRH:07:07:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: FIT2D * C * TYPE : SUBROUTINE * C * * C * FUNCTION : 2-D polynomial fit subroutine. * C * * C * XA ..... Input array of X-coordinates * C * YA ..... Input array of Y-coordinates * C * ZA ..... Input array of Z-values * C * CA ..... Intermediate array of polynomial constants * C * IPOW ... Array of powers of X and Y (returned by FIT2D) * C * NDATA .. Number of input data points * C * NTERM .. Number of terms in polynomial * C * ERROR .. RMS deviation between data points and polynomial * C * X ...... Input X-coordinate for evaluation using * C * polynomial * C * Y ...... Input Y-coordinate for evaluation using * C * polynomial * C * Z ...... Output Z-value from evaluation using polynomial * C * IMODE .. Mode of operation : * C * 0 ..... Evaluate constants in polynomial * C * 1 ..... Evaluate Z(X,Y) * C * IXINT .. Level of integration to be applied in * C * X-direction (0 : no integration, * C * 1 : integrate, * C * -1 : differentiate) * C * IYINT .. Level of integration to be applied in * C * Y-direction (as for IXINT) * C * IFAIL .. 0 for successful execution, otherwise 1 * C * * C * Uses NAG. * C * * C ****************************************************************************** integer pndatmax ! @7/7/89 parameter (pndatmax=100) ! Max. no. of data points real xa(*),ya(*),za(*),ca(*),x,y,z integer ipow(2,*) real a(pndatmax,pndatmax),term(pndatmax,pndatmax),zz(pndatmax) dimension aa(pndatmax,pndatmax),wks1(pndatmax),wks2(pndatmax) ! For NAG data ndatmax/pndatmax/ if(n.gt.ndatmax) then ifail=1 return endif if(imode.eq.0) then ip=0 i=0 2 do j=0,i ip=ip+1 ipow(1,ip)=i-j ipow(2,ip)=j if(ip.eq.nterm) go to 1 end do i=i+1 go to 2 1 continue do i=1,ndata ! Set up array of dependant variable do j=1,nterm ipx=ipow(1,j) ipy=ipow(2,j) if(ipx.eq.0.) then facx=1. else facx=xa(i)**ipx endif if(ipy.eq.0.) then facy=1. else facy=ya(i)**ipy endif term(i,j)=facx*facy end do end do if(ndata.eq.nterm) then ! Exact fit call f04ate(term,ndatmax,za,nterm,ca,aa,ndatmax,wks1,wks2, $ ifail) if(ifail.ne.0) then ifail=1 return endif error=0. else ! Least squares fit do j=1,nterm zz(j)=0. do i=1,ndata ! Form right-hand side zz(j)=zz(j)+term(i,j)*za(i) end do do k=j,nterm ! Form left-hand square matrix a(j,k)=0. do i=1,ndata a(j,k)=a(j,k)+term(i,j)*term(i,k) if(j.ne.k) a(k,j)=a(j,k) ! Fill in other half of A end do end do end do call f04ase(a,ndatmax,zz,nterm,ca,wks1,wks2,ifail) if(ifail.ne.0) then ifail=1 return endif error=0. do i=1,ndata error=error+za(i)**2 end do do j=1,nterm error=error-ca(j)*zz(j) end do error=sqrt(error/float(ndata)) endif else if(imode.eq.1) then z=0. do j=1,nterm ipx=ipow(1,j)+ixint ipy=ipow(2,j)+iyint if(ixint.eq.1) then ! Integrate facx=1./float(ipx) else if(ixint.eq.0) then facx=1. else if(ixint.eq.-1) then ! Differentiate facx=float(ipx+1) else ifail=1 return endif endif endif if(iyint.eq.1) then ! Integrate facy=1./float(ipy) else if(iyint.eq.0) then facy=1. else if(iyint.eq.-1) then ! Differentiate facy=float(ipy+1) else ifail=1 return endif endif endif if(facx.ne.0..and.ipx.ne.0.) then facx=facx*(x**ipx) endif if(facy.ne.0..and.ipy.ne.0.) then facy=facy*(y**ipy) endif z=z+ca(j)*facx*facy end do else ifail=1 return endif endif ifail=0 return end CBack up real*4 function gasdev3(idum) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:31:03:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: gasdev3 * C * TYPE : real*4 function * C * * C * FUNCTION : Random number generator yielding normal distribution * C * with zero mean and unit variance (based on Numerical * C * Recipes). * C * * C ****************************************************************************** integer*4 idum C real*4 v1,v2,r,fac,gset real*4 ran3 integer*4 iset data iset/0/ save iset,gset if (iset.eq.0) then 1 v1=2.*ran3(idum)-1. v2=2.*ran3(idum)-1. r=v1**2+v2**2 if(r.ge.1.)go to 1 fac=sqrt(-2.*log(r)/r) gset=v1*fac gasdev3=v2*fac iset=1 else gasdev3=gset iset=0 endif return end CBack up subroutine geoginp(nin,nout,nlog,annot,ncoord,long,lat,x,y,atype) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:20:10:1988 * C * * C * REVISION : Mod. for null read after error to cope * C * with Sun bug JRH:25:07:1989 * C * Minor mods. to this header JRH:09:10:1989 * C * Mod. to accept lower case "e" and "n" JRH:24:04:1991 * C * Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: GEOGINP * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Inputs geographical coordinates (grid (X,Y) or longitude * C * and latitude (LONG,LAT)) and indicates which has been * C * input. Each grid coordinate must be preceded by "E" or * C * "N" (they may be in any order). LONG must be input before * C * LAT. West longitude or South latitude is indicated by a * C * negative sign prior any value in longitude or latitude. * C * NCOORD is the number of coordinates to be entered (ie. 1 * C * or 2). * C * * C * NIN ...... Operator input device * C * NOUT ..... Operator output device * C * NLOG ..... Log file device * C * ANNOT .... Annotation (40 chars.) * C * NCOORD ... Number of coordinates to be input : * C * 1 : only LONG or LAT, or X or Y to be input - * C * if LONG or LAT, result is output to both * C * LONG and LAT, * C * if X or Y, result is output to X or Y as * C * appropriate. * C * 2 : both LONG and LAT, or X and Y to be input. * C * LONG ..... Longitude (radians internally, * C * deg. * C * or (deg., min.) * C * or (deg., min., sec.) at input) * C * LAT ..... Latitude (radians internally, * C * deg. * C * or (deg., min.) * C * or (deg., min., sec.) at input) * C * X ........ East grid coordinates * C * Y ........ North grid coordinates * C * ATYPE .... 'L' for input of longitude and latitude * C * 'G' for input of grid coordinates, * C * * C ****************************************************************************** real*8 long,lat,x,y character*40 annot real*8 longd,longm,longs,latd,latm,lats,d2r,sig1,sig2 dimension ind(6) character*1 atype character*81 buff d2r=datan(1.d0)/45.d0 ! Degrees to radians buff(1:1)=' ' 7 write(nout,1) annot write(nlog,1) annot 1 format(1x,a40) read(nin,2) buff(2:81) 2 format(a80) write(nlog,3) buff(2:81) 3 format(1x,a80) do i=2,81 ! @24/4/91 if(buff(i:i).eq.'e') buff(i:i)='E' ! @24/4/91 if(buff(i:i).eq.'n') buff(i:i)='N' ! @24/4/91 end do ! @24/4/91 ie=index(buff,'E') in=index(buff,'N') if(ie.eq.0.and.in.eq.0) then ! Longitude and latitude nval=0 do i=1,80 ip1=i+1 if((buff(i:i).eq.' '.or.buff(i:i).eq.',').and. ! Data separator $ (buff(ip1:ip1).ne.' '.and.buff(ip1:ip1).ne.',')) then ! Data nval=nval+1 ! Number of values in buffer if((ncoord.eq.1.and.nval.gt.3).or. $ (ncoord.eq.2.and.nval.gt.6)) go to 7 ! Too many input values ind(nval)=ip1 ! Pointer to first character of value endif end do if(nval.eq.0) go to 7 ! No values input if(ncoord.eq.1) then if(index(buff,'-').eq.0) then ! No minus sign sig1=1.d0 else ! Minus sign sig1=-1.d0 endif if(nval.eq.3) then read(buff,*,err=4) longd,longm,longs ! NVAL = 3 C WRITE(NLOG,8) LONGD,LONGM,LONGS long=dsign(dabs(longd)+dabs(longm)/60.d0 $ +dabs(longs)/3600.d0, $ sig1)*d2r else if(nval.eq.2) then ! NVAL = 2 read(buff,*,err=4) longd,longm C WRITE(NLOG,9) LONGD,LONGM long=dsign(dabs(longd)+dabs(longm)/60.d0,sig1)*d2r else ! NVAL = 1 read(buff,*,err=4) longd C WRITE(NLOG,10) LONGD long=dsign(dabs(longd),sig1)*d2r endif lat=long else ! Assume NCOORD = 2 if((nval/2)*2.ne.nval) go to 7 ! Not even number of values idum=ind(nval/2+1) ! Pointer to first char. of first value of latitude if(index(buff(2:idum-1),'-').eq.0) then ! No minus sign sig1=1.d0 else ! Minus sign sig1=-1.d0 endif if(index(buff(idum:81),'-').eq.0) then ! No minus sign sig2=1.d0 else ! Minus sign sig2=-1.d0 endif if(nval.eq.6) then ! NVAL = 6 read(buff,*,err=4) longd,longm,longs,latd,latm,lats C WRITE(NLOG,8) LONGD,LONGM,LONGS,LATD,LATM,LATS C 8 FORMAT(1X,F5.0,X,F3.0,X,F7.4,X,F5.0,X,F3.0,X,F7.4) long=dsign(dabs(longd)+dabs(longm)/60.d0 $ +dabs(longs)/3600.d0, $ sig1)*d2r lat= dsign(dabs(latd) +dabs(latm)/60.d0 $ +dabs(lats)/3600.d0 , $ sig2)*d2r else if(nval.eq.4) then ! NVAL = 4 read(buff,*,err=4) longd,longm,latd,latm C WRITE(NLOG,9) LONGD,LONGM,LATD,LATM C 9 FORMAT(X,F5.0,X,F7.4,X,F5.0,X,F7.4) long=dsign(dabs(longd)+dabs(longm)/60.d0,sig1)*d2r lat= dsign(dabs(latd) +dabs(latm)/60.d0 ,sig2)*d2r else ! NVAL = 2 read(buff,*,err=4) longd,latd C WRITE(NLOG,10) LONGD,LATD C 10 FORMAT(1X,F11.6,X,F11.6) long=dsign(dabs(longd),sig1)*d2r lat= dsign(dabs(latd) ,sig2)*d2r endif endif atype='L' else if(ie.ne.0.or.in.ne.0) then ! Grid coordinates if(ncoord.eq.1) then if(ie.ne.0..and.in.ne.0) then ! Both grid coordinates - failure go to 7 else if(ie.ne.0) then ! Eastings read(buff(ie+1:80),*,err=4) x C WRITE(NLOG,15) ' E',X C 15 FORMAT(A2,F12.2) else ! Northings read(buff(in+1:80),*,err=4) y C WRITE(NLOG,15) ' N',Y endif endif else ! Assume NCOORD = 2 if(ie.ne.0..and.in.ne.0) then ! Both grid coordinates read(buff(ie+1:80),*,err=4) x read(buff(in+1:80),*,err=4) y C WRITE(NLOG,11) X,Y C 11 FORMAT(' E',F12.2,' N',F12.2) atype='G' else ! Failure go to 7 endif endif atype='G' endif return 4 read(buff,*) ! Null read to cope with Sun bug @25/7/89 go to 7 ! @25/7/89 end CBack up subroutine geoginpbuff(buffin,ncoord,long,lat,x,y,atype, $ ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:10:10:1989 * C * * C * REVISION : Correction to name in header JRH:21:05:1990 * C * Correction so that ifail is set to * C * zero for successful execution JRH:28:09:1995 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: GEOGINPBUFF * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Inputs geographical coordinates (grid (X,Y) or longitude * C * and latitude (LONG,LAT)) and indicates which has been * C * input. Each grid coordinate must be preceded by "E" or * C * "N" (they may be in any order). LONG must be input before * C * LAT. West longitude or South latitude is indicated by a * C * negative sign prior to any value in longitude or latitude.* C * NCOORD is the number of coordinates to be entered (ie. 1 * C * or 2). * C * * C * BUFFIN ... Input buffer * C * NCOORD ... Number of coordinates to be input : * C * 1 : only LONG or LAT, or X or Y to be input - * C * if LONG or LAT, result is output to both * C * LONG and LAT, * C * if X or Y, result is output to X or Y as * C * appropriate. * C * 2 : both LONG and LAT, or X and Y to be input. * C * LONG ..... Longitude (radians internally, * C * deg. * C * or (deg., min.) * C * or (deg., min., sec.) at input) * C * LAT ..... Latitude (radians internally, * C * deg. * C * or (deg., min.) * C * or (deg., min., sec.) at input) * C * X ........ East grid coordinates * C * Y ........ North grid coordinates * C * ATYPE .... 'L' for input of longitude and latitude * C * 'G' for input of grid coordinates, * C * IFAIL .... returned 0 if execution satisfactory, * C * otherwise 1 * C * * C * NOTE : This is a special version of subroutine GEOGINP, * C * for input from a buffer * C * * C ****************************************************************************** real*8 long,lat,x,y character*80 buffin real*8 longd,longm,longs,latd,latm,lats,d2r,sig1,sig2 dimension ind(6) character*1 atype character*81 buff d2r=datan(1.d0)/45.d0 ! Degrees to radians buff(1:1)=' ' buff(2:81)=buffin(1:80) ie=index(buff,'E') in=index(buff,'N') if(ie.eq.0.and.in.eq.0) then ! Longitude and latitude nval=0 do i=1,80 ip1=i+1 if((buff(i:i).eq.' '.or.buff(i:i).eq.',').and. ! Data separator $ (buff(ip1:ip1).ne.' '.and.buff(ip1:ip1).ne.',')) then ! Data nval=nval+1 ! Number of values in buffer if((ncoord.eq.1.and.nval.gt.3).or. $ (ncoord.eq.2.and.nval.gt.6)) then ! Too many input values ifail=1 return endif ind(nval)=ip1 ! Pointer to first character of value endif end do if(nval.eq.0) then ! No values input ifail=1 return endif if(ncoord.eq.1) then if(index(buff,'-').eq.0) then ! No minus sign sig1=1.d0 else ! Minus sign sig1=-1.d0 endif if(nval.eq.3) then read(buff,*,err=4) longd,longm,longs ! NVAL = 3 long=dsign(dabs(longd)+dabs(longm)/60.d0 $ +dabs(longs)/3600.d0, $ sig1)*d2r else if(nval.eq.2) then ! NVAL = 2 read(buff,*,err=4) longd,longm long=dsign(dabs(longd)+dabs(longm)/60.d0,sig1)*d2r else ! NVAL = 1 read(buff,*,err=4) longd long=dsign(dabs(longd),sig1)*d2r endif lat=long else ! Assume NCOORD = 2 if((nval/2)*2.ne.nval) then ! Not even number of values ifail=1 return endif idum=ind(nval/2+1) ! Pointer to first char. of first value of latitude if(index(buff(2:idum-1),'-').eq.0) then ! No minus sign sig1=1.d0 else ! Minus sign sig1=-1.d0 endif if(index(buff(idum:81),'-').eq.0) then ! No minus sign sig2=1.d0 else ! Minus sign sig2=-1.d0 endif if(nval.eq.6) then ! NVAL = 6 read(buff,*,err=4) longd,longm,longs,latd,latm,lats long=dsign(dabs(longd)+dabs(longm)/60.d0 $ +dabs(longs)/3600.d0, $ sig1)*d2r lat= dsign(dabs(latd) +dabs(latm)/60.d0 $ +dabs(lats)/3600.d0 , $ sig2)*d2r else if(nval.eq.4) then ! NVAL = 4 read(buff,*,err=4) longd,longm,latd,latm long=dsign(dabs(longd)+dabs(longm)/60.d0,sig1)*d2r lat= dsign(dabs(latd) +dabs(latm)/60.d0 ,sig2)*d2r else ! NVAL = 2 read(buff,*,err=4) longd,latd long=dsign(dabs(longd),sig1)*d2r lat= dsign(dabs(latd) ,sig2)*d2r endif endif atype='L' else if(ie.ne.0.or.in.ne.0) then ! Grid coordinates if(ncoord.eq.1) then if(ie.ne.0..and.in.ne.0) then ! Both grid coordinates - failure ifail=1 return else if(ie.ne.0) then ! Eastings read(buff(ie+1:80),*,err=4) x else ! Northings read(buff(in+1:80),*,err=4) y endif endif else ! Assume NCOORD = 2 if(ie.ne.0..and.in.ne.0) then ! Both grid coordinates read(buff(ie+1:80),*,err=4) x read(buff(in+1:80),*,err=4) y atype='G' else ! Failure ifail=1 return endif endif atype='G' endif ifail=0 ! @28/9/95 return 4 ifail=1 return end CBack up subroutine gsnumber(x,y,wid,r,ang,idplace) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:14:07:1988 * C * * C * REVISION : Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: GSNUMBER * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Version of NUMBER for GS software. * C * * C * Labelled COMMON GSCOM must be included in main program, * C * in which LUPLT, LULOG, NSET, NCHARP and NDPLP must be set.* C * * C * X,Y ...... coordinates of bottom LH corner of text * C * WID ...... character width * C * R ........ REAL number to be written * C * ANG ...... angle (deg.) of text anticlockwise from X-axis * C * IDPLACE ... no. of decimal places to be plotted * C * * C ****************************************************************************** character*10 form character*80 a common/gscom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ nset, ! Symbol set no. $ nopen, ! Current pen number $ ncharp, ! No. of chars. in coordinate output $ ndplp ! No. of decimal places in coordinate output if(idplace.ge.0.) then ! Output as REAL no. call nchar(r,idplace,n,nasc) ! Tot. chars. (incl. sign and dec. point) write(form,4) nasc,idplace 4 format('(F',i2,'.',i2,')') write(a,form) r else ! Output as INTEGER call nchar(r,0,n,ndum) ! Tot. chars. (incl. sign and dec. point) nasc=n+1 ! Total characters (incl. sign) write(form,5) nasc 5 format('(1X,I',i2,')') write(a,form) nint(r) endif call gssymbol(x,y,wid,a,ang,nasc) return end CBack up subroutine gssymbol(x,y,wid,a,ang,nasc) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:14:07:1988 * C * * C * REVISION : Reads font on 99 rather than 7 JRH:27:11:1988 * C * Reads font on 101 rather than 99 JRH:16:03:1989 * C * Mod. to parameter JRH:07:07:1989 * C * Mods. where byte variable used as * C * array index JRH:07:07:1989 * C * Mod. for use on Sun JRH:07:11:1990 * C * Minor mod. to format JRH:16:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: GSSYMBOL * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Version of SYMBOL for GS software. * C * * C * Labelled COMMON GSCOM must be included in main program, * C * in which LUPLT, LULOG, NSET, NCHARP and NDPLP must be set.* C * * C * X,Y ...... coordinates of bottom LH corner of text * C * WID ...... character width * C * A ........ text to be written * C * ANG ...... angle (deg.) of text anticlockwise from X-axis * C * NASC ..... no. of ASCII characters * C * * C ****************************************************************************** integer pbytemax ! @7/7/89 parameter(pbytemax=20000) ! Max. no. of bytes in file character*(*) a dimension xa(255),ya(255) dimension idir(0:255) byte byt(pbytemax) character*1 abyt(pbytemax),asc character*1 aset ! &7/11/90 character*512 adum ! &7/11/90 character*18 form common/gscom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ nset, ! Symbol set no. $ nopen, ! Current pen number $ ncharp, ! No. of chars. in coordinate output $ ndplp ! No. of decimal places in coordinate output equivalence (byt,abyt) save nsetlst,idir,byt data nsetlst/0/ dtr=3.14159265/180. write(form,8) ncharp,ndplp,ncharp,ndplp 8 format('(I3/(F',i1,'.',i1,',X,F',i1,'.',i1,'))') if(nsetlst.ne.nset) then ! Load symbol set NSET write(aset,7) nset 7 format(i1) ! &7/11/90 open(unit=101,file='set'//aset//'.bin',status='UNKNOWN', ! &7/11/90 $ form='UNFORMATTED',recl=512,access='DIRECT') ! &7/11/90 do i=0,255 idir(i)=0 ! Clear directory end do irec=0 2 irec=irec+1 read(101,rec=irec,iostat=ios) adum(1:512) ! &7/11/90 if(ios.ne.0) go to 1 ! End of file &7/11/90 do i=1,510 ind=(irec-1)*510+i if(ind.gt.pbytemax) then write(6,6) write(lulog,6) 6 format(' Array DIMENSIONs too small', $ ' ..... program terminated') stop endif abyt(ind)=adum(i:i) end do go to 2 1 ipoint=4 ! Pointer to BYT array 5 if(byt(ipoint+1).ne.32) then ! Space signifies end of data index=byt(ipoint) ! @7/7/89 idir(index)=ipoint ! Set up directory &7/7/89 idir(index+128)=ipoint ! Set up for either parity &7/7/89 ipoint=ipoint+3 nppoint=byt(ipoint) ! No. of plotting points ipoint=ipoint+nppoint*3+1 if(ipoint.lt.(irec-1)*510) go to 5 ! Not yet at end of data endif close(unit=101) ! &16/3/89 endif offset=0. do iasc=1,nasc ! Step through characters asc=a(iasc:iasc) ibyt=ichar(asc) ! Byte value ipoint=idir(ibyt) ! Pointer to character in BYT if(ipoint.eq.0) then ! Character not in font ibyt=32 ! Force a space ipoint=idir(ibyt) endif iwid=byt(ipoint+2) npt=byt(ipoint+3) j=0 do i=1,npt ! Step through plotting points xx= byt(ipoint+(i-1)*3+4) yy= byt(ipoint+(i-1)*3+5) ipen=byt(ipoint+(i-1)*3+6) if(ipen.eq.3) then ! IPEN = 3 if(i.ne.1) then ! Output last segment do k=1,j call xy2ra(xa(k)+offset,ya(k),r,az, $ .true.,.true.) ! Convert to polars az=az-ang*dtr ! Rotate by ANG anticlockwise r=r*wid/20. ! Scale (nominal width of 20 units) call ra2xy(r,az,xa(k),ya(k)) ! Convert to rectangulars xa(k)=xa(k)+x ya(k)=ya(k)+y end do if(j.eq.2) then ! GS software will not allow 2 point only j=3 xa(3)=xa(2) ya(3)=ya(2) endif write(luplt,form) j,(xa(k),ya(k),k=1,j) ! Output last segment endif j=1 xa(1)=xx ya(1)=yy else ! IPEN = 2 j=j+1 xa(j)=xx ya(j)=yy endif end do if(j.ne.0.) then do k=1,j call xy2ra(xa(k)+offset,ya(k),r,az, $ .true.,.true.) ! Convert to polars az=az-ang*dtr ! Rotate by ANG anticlockwise r=r*wid/20. ! Scale (nominal width of 20 units) call ra2xy(r,az,xa(k),ya(k)) ! Convert to rectangulars xa(k)=xa(k)+x ya(k)=ya(k)+y end do if(j.eq.2) then ! GS software will not allow 2 point only j=3 xa(3)=xa(2) ya(3)=ya(2) endif write(luplt,form) j,(xa(k),ya(k),k=1,j) ! Output last segment endif offset=offset+iwid end do return end CBack up subroutine heapsort(ain,aout,ind,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:29:08:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB .FVS * C * ROUTINE NAME: HEAPSORT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Heapsort based on Numerical Recipes subroutine SORT2 * C * * C * AIN ..... Array to be sorted (unchanged on output) * C * AOUT .... Resultant sorted array (increasing) * C * IND ..... Array of sorted indices * C * N ....... Size of arrays AIN and AOUT * C * * C ****************************************************************************** real*4 ain(*),aout(*) integer*4 ind(*) integer*4 n real*4 rra integer*4 i,j,l,ir,idum l=n/2+1 ir=n do i=1,n aout(i)=ain(i) ! Copy input array to output array ind(i)=i ! Generate initial idum array end do if(n.eq.1) return ! Special for only one record 10 continue if(l.gt.1)then l=l-1 rra=aout(l) idum=ind(l) else rra=aout(ir) idum=ind(ir) aout(ir)=aout(1) ind(ir)=ind(1) ir=ir-1 if(ir.eq.1)then aout(1)=rra ind(1)=idum return endif endif i=l j=l+l 20 if(j.le.ir)then if(j.lt.ir)then if(aout(j).lt.aout(j+1))j=j+1 endif if(rra.lt.aout(j))then aout(i)=aout(j) ind(i)=ind(j) i=j j=j+j else j=ir+1 endif go to 20 endif aout(i)=rra ind(i)=idum go to 10 end CBack up integer*4 function idint2(x) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:04:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: IDINT2 * C * TYPE : FUNCTION * C * * C * FUNCTION : As INT, but trunctates towards -(infinity) * C This is D.P. version of INT2 * C * * C ****************************************************************************** real*8 x idint2=idint(x) if(dble(idint2).eq.x) return if(x.lt.0.d0) idint2=idint2-1 return end CBack up integer*4 function idplace(r,isig) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:10:08:1989 * C * * C * REVISION : Mod. using INT2 so that values like * C * 0.1 are handled correctly JRH:18:11:1991 * C * Full declarations added JRH:18:11:1991 * C * Addition of external JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: IDPLACE * C * TYPE : INTEGER*4 FUNCTION * C * * C * FUNCTION : Returns required number of decimal places to output a * C * REAL number, R, to ISIG significant figures * C * * C ****************************************************************************** real*4 r ! @18/11/91 integer*4 isig ! @18/11/91 integer*4 nleft,int2 ! @18/11/91 external int2 if(r.ne.0.) then nleft=int2(alog10(abs(r))+1) ! No. of figs. to L of dec. pt. @18/11/91 else ! r = 0 nleft=1 endif idplace=isig-nleft ! ISIG significant figs if(idplace.lt.0) idplace=0 return end CBack up subroutine inbuf(type,key,buf,nbuf,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:15:09:1993 * C * * C * REVISION : ------------- JRH:--:--:1993 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INBUF * C * TYPE : MAIN * C * * C * FUNCTION : Inputs buffer from device 5, based on keyword. * C * * C * type ..... '+' for inclusion of matched record, * C * '-' for exclusion of matched record * C * key ...... Keyword * C * buf ...... Buffer selected * C * nbuf ..... Number of characters in buf * C * ifail .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 nbuf,ifail character*1 type character*(*) key character*(*) buf C integer*4 nkey,nbufin,lenchar,ios character*7 fmt C nkey=len(key) nbufin=len(buf) write(fmt,1) nbufin 1 format('(a',i4,')') 2 read(5,fmt,iostat=ios) buf(1:nbufin) if(ios.ne.0) then ! Error or end of file ifail=1 return endif if((type.eq.'+'.and. ! Inclusion required $ (buf(1:nkey).eq.key(1:nkey).and. ! Found a match $ buf(nkey+1:nkey+1).eq.' ')).or. ! followed by a space $ (type.eq.'-'.and..not. ! Exclusion required $ (buf(1:nkey).eq.key(1:nkey).and. ! Found a match $ buf(nkey+1:nkey+1).eq.' '))) then ! followed by a space nbuf=lenchar(buf) ifail=0 return endif go to 2 ! Try another record end CBack up subroutine inilink(prev,next,stack,ifirst,ilast,topstack,maxlink) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:11:10:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INILINK * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Initialises link list (to empty) * C * * C * PREV ..... array of pointers to previous item in list * C * NEXT ..... array of pointers to next item in list * C * STACK .... stack of unused list pointers * C * IFIRST ... pointer to first item in list * C * ILAST .... pointer to last item in list * C * TOPSTACK . pointer to top of stack * C * MAXLINK .. maximum number of items in list * C * * C ****************************************************************************** integer*4 prev(maxlink),next(maxlink),stack(maxlink) integer*4 ifirst,ilast,topstack,maxlink integer*4 i do i=1,maxlink ! Clear arrays prev(i)=0 next(i)=0 end do ifirst=0 ! Empty list ilast=0 topstack=maxlink do i=1,maxlink stack(i)=maxlink+1-i ! "1" is on top of stack end do return end CBack up subroutine inslink(prev,next,stack,ifirst,ilast,topstack,maxlink, $ ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:11:10:1991 * C * * C * REVISION : Correction to error return JRH:23:03:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INSLINK * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Inserts item in link list (at position ILAST) * C * * C * PREV ..... array of pointers to previous item in list * C * NEXT ..... array of pointers to next item in list * C * STACK .... stack of unused list pointers * C * IFIRST ... pointer to first item in list * C * ILAST .... pointer to last item in list * C * TOPSTACK . pointer to top of stack * C * MAXLINK .. maximum number of items in list * C * IFAIL .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 prev(maxlink),next(maxlink),stack(maxlink) integer*4 ifirst,ilast,topstack,maxlink,ifail integer*4 new if(topstack.eq.0) then ! No more room ifail=1 return endif new=stack(topstack) ! Take new pointer off stack if(new.eq.0) then ! Invalid pointer ifail=1 ! &23/3/93 return endif stack(topstack)=0 ! Clear pointer topstack=topstack-1 if(ilast.eq.0) then ! Empty list ifirst=new else next(ilast)=new endif prev(new)=ilast next(new)=0 ilast=new ifail=0 return end CBack up subroutine inslink2(iins,new, $ prev,next,stack,ifirst,ilast,topstack,maxlink, $ ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:05:08:1993 * C * * C * REVISION : -------------------------- JRH:--:--:1993 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INSLINK2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Inserts item in link list (at position IINS) * C * * C * IINS ..... pointer after which item to be inserted * C * (if IINS = 0, item is to be inserted at start * C * of link list) * C * NEW ...... pointer for new item * C * PREV ..... array of pointers to previous item in list * C * NEXT ..... array of pointers to next item in list * C * STACK .... stack of unused list pointers * C * IFIRST ... pointer to first item in list * C * ILAST .... pointer to last item in list * C * TOPSTACK . pointer to top of stack * C * MAXLINK .. maximum number of items in list * C * IFAIL .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 prev(maxlink),next(maxlink),stack(maxlink) integer*4 iins,new,ifirst,ilast,topstack,maxlink,ifail integer*4 idum if(topstack.eq.0) then ! No more room ifail=1 return endif new=stack(topstack) ! Take new pointer off stack if(new.eq.0) then ! Invalid pointer ifail=1 return endif stack(topstack)=0 ! Clear pointer topstack=topstack-1 if((iins.ne.0.and.ilast.eq.0)) then ! IINS is invalid pointer ifail=1 return endif if(ilast.eq.0) then ! Empty list ifirst=new ilast=new next(new)=0 prev(new)=0 else if(iins.eq.0) then ! Insert item at start of link list next(new)=ifirst prev(new)=0 prev(ifirst)=new ifirst=new else ! IINS cannot be zero idum=next(iins) if(idum.eq.0.and.iins.ne.ilast) then ! IINS is invalid pointer ifail=1 return endif next(iins)=new next(new)=idum prev(new)=iins if(idum.eq.0) then ! End of link list ilast=new else prev(idum)=new endif endif ifail=0 return end CBack up subroutine intpoint(xin,xout,n,m) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:29:12:1993 * C * * C * REVISION : Mod. for one- and two-point segments JRH:17:08:1994 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INTPOINT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Subroutine to interpolate point data * C * (simplified real*8 version of div1d in forlib). * C * * C * xin ..... array of n input values * C * xout .... array of nm output interpolated values * C * n ....... number of input values * C * m ....... interpolation factor * C * * C ****************************************************************************** real*8 xin(*),xout(*) integer*4 n,m C real*8 d1l,d2l,d1r,d2r,xl,xr,c1l,c2l,c1r,c2r integer*4 i,ioff,ii C xout(1)=xin(1) if(n.eq.1) then ! Only one point @17/8/94 return ! @17/8/94 else if(n.eq.2) then ! Two points @17/8/94 d1r=(xin(2)-xin(1))*2.d0 ! @17/8/94 d2r=0.d0 ! @17/8/94 endif ! @17/8/94 do i=1,n-1 ! Do "parabolic" interpolation if(i.ne.1) then d1l=d1r ! Use "old" RH derivative d2l=d2r ! " " " " endif if(i.ne.n-1) then ! Not at RH end d1r=xin(i+2)-xin(i) ! 1st derivative, RH curve d2r=xin(i+2)+xin(i)-2*xin(i+1) ! 2nd " " " endif ioff=(i-1)*m+1 do ii=1,m ! Step within an interpolation interval xl=dble(ii)/dble(m) xr=xl-1.d0 c1l=xl/2.d0 c2l=xl*xl/2.d0 c1r=xr/2.d0 c2r=xr*xr/2.d0 if(i.eq.1) then ! LH end xout(ii+ioff)=xin(i+1)+d1r*c1r+d2r*c2r ! RH parabola else if(i.eq.n-1) then ! RH end xout(ii+ioff)=xin(i)+d1l*c1l+d2l*c2l ! LH parabola else ! Other xout(ii+ioff)=(xin(i) +d1l*c1l+d2l*c2l)*(-xr) ! LH parabola $ +(xin(i+1)+d1r*c1r+d2r*c2r)*xl ! RH parabola endif endif end do end do C return end CBack up function int2(x) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:04:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: INT2 * C * TYPE : FUNCTION * C * * C * FUNCTION : As INT, but trunctates towards -(infinity) * C * * C ****************************************************************************** real*4 x int2=int(x) if(float(int2).eq.x) return if(x.lt.0.) int2=int2-1 return end CBack up subroutine invmerc(x,y,long,lat,ae,ecs,lat0,s0,longor,lator, $ eps,maxit,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:14:10:1988 * C * * C * REVISION : eps declared as real*8 JRH:09:06:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: INVMERC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts Mercator grid coordinates (X,Y) to longitude and * C * latitude (LONG,LAT). LAT is computed by Newton's method. * C * * C * X ........ East grid coordinates * C * Y ........ North grid coordinates * C * LONG ..... Longitude (radians) * C * LAT ..... Latitude (radians) * C * AE ....... Semi-major axis of Earth * C * ECS ...... Eccentricity squared of figure of Earth * C * LAT0 ..... Latitude at which scale of projection is * C * defined * C * S0 ....... Scale of projection at LAT0 * C * LONGOR ... Longitude of origin of projection * C * LATOR .... Latitude of origin of projection * C * EPS ...... Tolerance in Y * C * MAXIT .... Max. no. of iterations * C * IFAIL .... returned 0 if convergence satisfactory, * C * otherwise 1 * C * * C ****************************************************************************** real*8 long,lat,x,y,ae,ecs,lat0,s0,longor,lator real*8 alpha,e,slor,eslor,yor,yy,ee,sl,esl,diff,eps alpha=ae*s0/dsqrt(1.d0+(1.d0-ecs)*(dtan(lat0)**2)) e=dsqrt(ecs) slor=dsin(lator) eslor=e*slor yor=alpha*(dlog((1.d0+slor) $ /(1.d0-slor)) $ -e*dlog((1.d0+eslor) $ /(1.d0-eslor)))/2.d0 long=x/alpha+longor yy=y+yor ! Compute initial approximation to LAT ee=dexp(2.d0*yy/alpha) lat=dasin((ee-1.d0)/(ee+1.d0)) do i=1,maxit sl=dsin(lat) esl=e*sl diff=alpha*(dlog((1.d0+sl) $ /(1.d0-sl)) $ -e*dlog((1.d0+esl) $ /(1.d0-esl)))/2.-yy if(dabs(diff).lt.eps) then ifail=0 return endif lat=lat-diff*(1.d0-ecs*(dsin(lat)**2))*cos(lat) $ /(alpha*(1.d0-ecs)) end do ifail=1 return end CBack up double precision function invrob( $ x1,y1,z1,x2,y2,z2,saz,caz,a,ecs,eps) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : GEODESY JRH:18:02:1986 * C * * C * REVISION : Mod. to replace trig. functions for * C * greater accuracy for small ranges JRH:18:10:1988 * C * Removal of redundant variables JRH:27:11:1996 * C * Quickie for horizontal coincidence JRH:12:11:1998 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: INVROB * C * TYPE : DOUBLE PRECISION FUNCTION * C * * C * FUNCTION : Inverse Robbins computation for distance, and azimuth on * C * spheroid. * C * * C * (X1,Y1,Z1) ..... Long., lat., height of point (1) * C * (X2,Y2,Z2) ..... Long., lat., height of point (2) * C * SAZ ............ Sin of azimuth (1) to (2) * C * CAZ ............ Cos of azimuth (1) to (2) * C * A .............. Semi-major axis of Earth * C * ECS ............ First eccentricity squared of Earth * C * EPS ............ Second eccentricity squared of Earth * C * * C * No. of calls of various operators : * C * * C * Operator No. of calls * C * * C * + or - 25 * C * * or / 49 * C * ** 1 * C * SQRT 5 * C * TRIGS 7 * C * * C * Checked against example in "The Austalian Map Grid" * C * (National Mapping Council of Australia, Special * C * Publication 7), page 10, 18 Feb. 1986 - accurate to * C * +/- .001 metre, +/- .01 sec.. * C * * C ****************************************************************************** real z1,z2 double precision x1,y1,x2,y2,saz,caz,a,ecs,eps double precision eabs,eprop,sp1,sp2,cp1,cdl,sdl,t,tau1 double precision chi,sig,f1,f2,dum,dum1,dum2,dum3,dums,h2,gh,g2 double precision sigp ! &27/11/96 C data eabs,eprop/1.d-4,1.d-9/ ! Absolute and proportional errors C if(x1.eq.x2.and.y1.eq.y2) then ! Horizontal coincidence @12/11/98 saz=0.d0 ! Default to zero azimuth @12/11/98 caz=1.d0 ! Default to zero azimuth @12/11/98 invrob=dble(abs(z1-z2)) ! @12/11/98 return ! @12/11/98 endif ! @12/11/98 C sp1=dsin(y1) sp2=dsin(y2) f1=a/dsqrt(1.d0-ecs*sp1*sp1) f2=a/dsqrt(1.d0-ecs*sp2*sp2) C CP1=DSQRT(1.D0-SP1*SP1) ! Faster than DCOS &18/10/88 cp1=dcos(y1) ! @18/10/88 cdl=dcos(x2-x1) C SDL=DSIGN(DSQRT(1.D0-CDL*CDL),X2-X1) ! Faster than DSIN &18/10/88 sdl=dsin(x2-x1) ! @18/10/88 C T=((1.D0-ECS)*SP2+ECS*SP1*F1/F2)/DSQRT(1.D0-SP2*SP2) ! Faster &18/10/88 t=((1.d0-ecs)*sp2+ecs*sp1*f1/f2)/dcos(y2) ! @18/10/88 tau1=cp1*t-sp1*cdl chi=dsqrt(tau1*tau1+sdl*sdl) sig=dasin(chi/dsqrt(1.d0+t*t)) saz=sdl/chi caz=tau1/chi dum=cp1*caz h2=dum*dum*eps dum1=f1*sig ! Multiplier for brackets dums=dum1 ! Sum of terms sigp=sig*sig ! Sigma to required power dum3=-sigp*h2*(1.d0-h2)*0.16666666666666667 ! One term in brackets dum2=dum1*dum3 ! One term dums=dums+dum2 ! Sum of terms if(dabs(dum2).gt.eabs.and.dabs(dum3).gt.eprop) then ! Error too large sigp=sigp*sig ! Increase power of sigma by one gh=sp1*dum*eps ! We now need G*H dum3=sigp*gh*(1.d0-2.d0*h2)*0.125d0 ! One term in brackets dum2=dum1*dum3 ! One term dums=dums+dum2 ! Sum of terms if(dabs(dum2).gt.eabs.and.dabs(dum3).gt.eprop) then !Error too large sigp=sigp*sig ! Increase power of sigma by one g2=sp1*sp1*eps ! We now need G squared dum3=sigp*(h2*(4.d0-7.d0*h2)-3.d0*g2*(1.d0-7.d0*h2)) $ *8.3333333333333333d-3 dum2=dum1*dum3 ! One term dums=dums+dum2 ! Sum of terms if(dabs(dum2).gt.eabs.and.dabs(dum3).gt.eprop) then ! Error too large sigp=sigp*sig ! Increase power of sigma by one dum3=-sigp*gh*2.0833333333333333d-2 ! One term in brackets dum2=dum1*dum3 ! One term dums=dums+dum2 ! Sum of terms endif endif endif C Correction for heights above sea level ..... dums=dums*(1.d0+dble(z1+z2)/(f1+f2)) ! Mean height invrob=dsqrt(dums*dums+dble(z1-z2)**2) ! Slant return end CBack up subroutine iosproc(nout,nlog,ios,lfatal,lerr,leof) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:28:08:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: IOSPROC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Processes IOSTAT from READ * C * * C * NOUT ..... Operator output device number (6) * C * NLOG ..... Log file device number * C * IOS ...... Value returned by "IOSTAT=" in READ * C * LFATAL ... .TRUE. if termination required on error or end * C * of file, otherwise .FALSE. * C * LERR ..... (If LFATAL=.FALSE.) .TRUE. if read error, * C * otherwise .FALSE. * C * LEOF ..... (If LFATAL=.FALSE.) .TRUE. if end of file, * C * otherwise .FALSE. * C * * C ****************************************************************************** integer*4 nout,nlog,ios logical lfatal,lerr,leof if(ios.gt.0) then ! Read error if(lfatal) then write(nout,1) write(nlog,1) 1 format(/' Read error ..... program terminated'/) stop else lerr=.true. leof=.false. endif else if(ios.eq.-1) then ! End of file if(lfatal) then write(nout,2) write(nlog,2) 2 format(/' End of file ..... program terminated'/) stop else lerr=.false. leof=.true. endif else lerr=.false. leof=.false. endif return end CBack up subroutine ipdig(ilp,i,j,ic) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:03:12:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: IPDIG * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Inputs digit, IC, at (I,J) to array ILP * C * * C ****************************************************************************** integer ilp(33,100) i1=(i-1)/4+1 i2=5-i+(i1-1)*4 i3=ilp(i1,j) ip=i2-1 i4=i3/(10**ip) i5=i3/(10**i2) ii=i4-i5*10 i3=i3+(ic-ii)*(10**ip) ilp(i1,j)=i3 return end CBack up subroutine iread(nin,nout,nlog,anot,acc,iarray,istart,istop,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:08:1986 * C * * C * REVISION : Error trap included JRH:04:09:1986 * C * Mod. for output of message only if * C * ISTART=0 or ISTOP=0 JRH:12:09:1986 * C * Minor mods. JRH:31:12:1986 * C * Minor mod. JRH:05:01:1987 * C * Minor mod. JRH:17:05:1988 * C * Mod. so that FORM is input without * C * brackets JRH:21:06:1988 * C * Mod. for null read after error to cope * C * with Sun bug JRH:25:07:1989 * C * Mod. for compilation on transputer JRH:07:09:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: IREAD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads in a set of INTEGER numbers * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Annotation (40 chars.) * C * ACC ..... Carriage-control character * C * (' ' for new line, '$' for same line) * C * IARRAY .. Resultant INTEGER array * C * ISTART .. Start index of IARRAY * C * ISTOP ... Stop index of IARRAY * C * FORM .... Format for output to log device (40 chars., * C * without brackets) * C * * C ****************************************************************************** integer iarray(*) character*40 anot,form character*1 acc character*42 formt ! @7/9/89 logical cont ! @31/12/86 save cont ! @31/12/86 character*12 formout ! &5/11/86 data cont/.false./ ! @11/5/88 2 if(cont) then ! Continuation of terminal text @31/12/86 &25/7/89 write(formout,1) ' ',acc ! &31/12/86 1 format('(',a1,'X,A40,A1',a1,')') ! &5/11/87 else ! Normal text @31/12/86 write(formout,1) '/',acc ! @31/12/86 endif ! @31/12/86 write(nout,formout) anot,' ' ! &5/11/87 write(nlog,formout) anot,' ' ! &5/11/87 if(istart.ne.0.and.istop.ne.0) then ! &31/12/86 read(nin,*,err=3) (iarray(i),i=istart,istop) ! &4/9/86 formt='('//form//')' ! @7/9/89 write(nlog,formt) (iarray(i),i=istart,istop) ! &21/6/88 &7/9/89 cont=.false. ! Terminal text not to be continued @31/12/86 else ! @31/12/86 cont=.true. ! Terminal text to be continued @31/12/86 endif ! @12/9/86 return 3 read(nin,*) ! Null read to cope with Sun bug @25/7/89 go to 2 ! @25/7/89 end CBack up subroutine ireadfil(nin,nout,nlog,anot,nchar,ivar,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1987 * C * * C * REVISION : Mod. for keyword checking JRH:19:01:1987 * C * Simplification JRH:17:06:1988 * C * Mod. for compilation on transputer JRH:07:09:1989 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: IREADFIL * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads INTEGER variable from file based on keyword. * C * * C * NIN ..... File input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Keyword in file * C * NCHAR ... Number of characters in ANOT (max. 40) * C * IVAR .... Resultant INTEGER variable * C * FORM .... Format for output (40 chars., without brackets) * C * * C ****************************************************************************** character*(*) anot character*40 form character*80 buff character*40 blank ! &17/6/88 character*40 formt ! @7/9/89 character*51 formt2 character*14 formt3 data blank/' '/ write(formt2,6) nchar,form 6 format('(1X,A',i2,',A3,',a40,')') write(formt3,5) nchar 5 format('(/A9,A',i2,',A34/)') rewind(nin) 4 read(nin,2,end=3) buff 2 format(a80) if(buff(1:nchar).eq.anot.and. ! &17/6/88 $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found &19/1/87 buff(1:nchar)=blank(1:nchar) ! Delete keyword idum1=lhschar(buff) ! Index of first character of value @7/9/89 idum2=lenchar(buff) ! Index of last character of value @7/9/89 write(formt,7) idum2-idum1+1 ! @7/9/89 7 format('(i',i2,')') ! @7/9/89 read(buff(idum1:idum2),formt) ivar ! Read variable &7/9/89 write(nout,formt2) anot,' = ',ivar write(nlog,formt2) anot,' = ',ivar return else go to 4 ! Read more data endif 3 write(nout,formt3) ' Keyword ',anot, $ ' not found .... program terminated' write(nlog,formt3) ' Keyword ',anot, $ ' not found .... program terminated' stop end CBack up subroutine ireadfil2(nin,anot,nchar,ivar,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: ireadfil2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads INTEGER*4 variable from file based on keyword. * C * (Modified version of ireadfil, without output to operator * C * or log file) * C * * C * nin ..... File input device * C * anot .... Keyword in file * C * nchar ... Number of characters in ANOT (max. 40) * C * ivar .... Resultant INTEGER*4 variable * C * ifail ... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 nin,nchar,ivar,ifail character*(*) anot C integer*4 ios logical found character*80 buff C rewind(nin) ios=0 found=.false. do while(ios.eq.0.and..not.found) read(nin,1,iostat=ios) buff 1 format(a80) if(buff(1:nchar).eq.anot.and. $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found read(buff(nchar+2:80),*,iostat=ios) ivar found=.true. endif end do if(ios.eq.0) then ifail=0 ! Match found and no error else ifail=1 ! No match found endif end CBack up integer*4 function isearch(x,x0,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:28:03:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: isearch * C * TYPE : integer*4 function * C * * C * FUNCTION : Inputs array x(i) of n monotonically increasing real*8 * C * values and scalar x0, and returns lower index of bounding * C * pair. * C * * C * If x0 < x(1), returned value = 0 * C * If x0 >= x(n), returned value = n * C * * C * x ....... input array of monotonic values * C * x0 ...... required value of x * C * n ....... number of values in x * C * * C ****************************************************************************** real*8 x(*) real*8 x0 integer*4 n C C Local declarations: C integer*4 ilow,ihigh,imid C C Quickies: C if(x0.lt.x(1)) then isearch=0 return else if(x0.ge.x(n)) then isearch=n return endif C C Now we know x0 lies within x: C ilow=1 ihigh=n C do while(ihigh.ne.ilow+1) imid=(ilow+ihigh)/2 if(x0.lt.x(imid)) then ihigh=imid else ilow=imid endif end do isearch=ilow C return end CBack up subroutine julday(iye,mon,idy,ihr,min,sec,julian,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:05:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: JULDAY * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts (year, month, day, hour, minute, second) to * C * Julian Day (based on Numerical Recipes) * C * * C * IYE ........ Year * C * MON ........ Month * C * IDY ........ Day * C * IHR ........ Hour * C * MIN ........ Minute * C * SEC ........ Second * C * JULIAN ..... Julian Day (non-negative, but may be * C * non-integer) * C * IFAIL ...... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 julian real*4 sec integer*4 iye,mon,idy,ihr,min,ifail integer*4 iyyy,jy,jm,igreg,ja,ijul integer*4 idint2 parameter (igreg=15+31*(10+12*1582)) C ..... Gregorian Calendar was adopted 15 Oct. 1582 if(iye.eq.0.or. ! There is no year zero $ iye.lt.-4713) then ! Julian Day must be non-neagtive ifail=1 return endif if(iye.lt.0) then iyyy=iye+1 else iyyy=iye endif if(mon.gt.2) then jy=iyyy jm=mon+1 else jy=iyyy-1 jm=mon+13 endif ijul=idint2(365.25d0*dble(jy))+idint2(30.6001d0*dble(jm)) $ +idy+1720995 if(idy+31*(mon+12*iyyy).ge.igreg) then C ..... Test for change to Gregorian Calendar ja=idint(0.01d0*dble(jy)) ijul=ijul+2-ja+idint(0.25d0*dble(ja)) endif julian=dble(ijul) $ +dble(ihr)/24.d0+dble(min)/1440.d0+dble(sec)/86400.d0 $ -0.5d0 ! Correction from midnight to noon if(julian.lt.0.d0) then ! Julian Day must be non-negative ifail=1 return endif ifail=0 return end CBack up integer function lenchar(c) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:09:01:1986 * C * * C * REVISION : Variable declarations JRH:30:09:1996 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: LENCHAR * C * TYPE : INTEGER FUNCTION * C * * C * FUNCTION : Returns length of CHARACTER variable (defined by * C * removing blank characters from right-hand side). * C * * C ****************************************************************************** character*(*) c C integer*4 itot,i ! @30/9/96 C itot=len(c) do i=itot,1,-1 if(c(i:i).ne.' ') go to 1 end do lenchar=0 ! String is all blanks return 1 lenchar=i return end CBack up integer function lhschar(c) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:07:09:1989 * C * * C * REVISION : ------------- JRH:--:--:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: LHSCHAR * C * TYPE : INTEGER FUNCTION * C * * C * FUNCTION : Returns index of first non-blank character of CHARACTER * C * variable (defined by removing blank characters from * C * left-hand side). * C * * C ****************************************************************************** character*(*) c itot=len(c) do i=1,itot if(c(i:i).ne.' ') go to 1 end do lhschar=0 ! String is all blanks return 1 lhschar=i return end CBack up subroutine lpclr(ilp) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:03:12:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: LPCLR * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Clears array ILP * C * * C * NOTE : (1) ILP(33,100) must be declared externally * C * - this is a 16-bit integer variable * C * (2) LPCLR(ILP) must initially be called to clear * C * ILP * C * (3) LPLOAD loads ILP with superimposed data * C * (4) LPPLOT plots data * C * * C ****************************************************************************** integer ilp(33,100) do i=1,33 do j=1,100 ilp(i,j)=0 end do end do return end CBack up subroutine lpload(ilp,x,y,nip,xmin,xmax,ymin,ymax,iwid,ilen,ich,!&19/12/85 $ nout) ! @19/12/85 C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:03:12:1985 * C * * C * REVISION : Addition of NOUT to parameters JRH:19:12:1985 * C * Replacement of IROUND with NINT JRH:30:12:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: LPLOAD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Loads ILP with superimposed data * C * * C ****************************************************************************** integer ilp(33,100) dimension x(100),y(100) if(iwid.gt.131.or.ilen.gt.100) then write(nout,2) 2 format(' Output too large') return endif if(nip.gt.100) then write(nout,1) 1 format(' Too many input values') return endif rwid=iwid-1 ! Compute XSCL, YSCL rlen=ilen-1 nipm1=nip-1 xscl=rwid/(xmax-xmin) yscl=rlen/(ymax-ymin) do m=1,nipm1 ia=nint((x(m)-xmin)*xscl+1.) ! &30/12/86 ib=nint((x(m+1)-xmin)*xscl+1.) ! &30/12/86 ja=nint((y(m)-ymin)*yscl+1.) ! &30/12/86 jb=nint((y(m+1)-ymin)*yscl+1.) ! &30/12/86 idel=iabs(ia-ib)+1 jdel=iabs(ja-jb)+1 nlp=max0(idel,jdel)+1 rnlp=nlp do iilp=1,nlp riilp=iilp w1=(rnlp-riilp)/(rnlp-1.) w2=1.-w1 xi=x(m)*w1+x(m+1)*w2 yi=y(m)*w1+y(m+1)*w2 i=nint((xi-xmin)*xscl+1.) ! &30/12/86 j=nint((yi-ymin)*yscl+1.) ! &30/12/86 if(i.ge.1..and.i.le.iwid.and.j.ge.1..and.j.le.ilen) $ call ipdig(ilp,i,j,ich) end do end do return end CBack up subroutine lpplot(ilp,xmin,xmax,ymin,ymax,iwid,ilen,nout, $ ichar,index) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:03:12:1985 * C * * C * REVISION : Minor mod. to FORMAT JRH:11:12:1985 * C * Mod. so that ICHAR defined externally JRH:30:12:1986 * C * Minor mod. to FORMAT JRH:30:12:1986 * C * Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: LPPLOT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Plots data to file in form suitable for lineprinter * C * * C * Normal values for ICHAR : * C * /' ','1','2','3','4','5','6','7','8','9','+'/ * C * * C ****************************************************************************** integer ilp(33,100),ichar(11,*) ! &30/12/86 dimension idum(131) ! &30/12/86 character*39 fmt ! &11/12/85 if(iwid.gt.131.or.ilen.gt.100) then write(nout,2) 2 format(' Output too large') return endif write(fmt,11) iwid-14,iwid-14 11 format('(//',i3,'X,4HX = ,E11.4/',i3,'X,4HY = ,E11.4)') ! &11/12/85 write(nout,fmt) xmax,ymax do jj=1,ilen j=ilen-jj+1 do i=1,iwid call opdig(ilp,i,j,ic) ii=ic+1 idum(i)=ichar(ii,index) ! &30/12/86 if(i.eq.1.or.i.eq.iwid.or.j.eq.1.or.j.eq.ilen) then if(ii.eq.1) idum(i)=ichar(11,index) ! &30/12/86 endif end do write(nout,7) (idum(i),i=1,iwid) 7 format(1x,131a1) 5 end do write(nout,8) xmin,ymin 8 format(1x,4hx = ,e11.4/1x,4hy = ,e11.4) ! &30/12/ return end CBack up subroutine merc(long,lat,x,y,ae,ecs,lat0,s0,longor,lator) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:14:10:1988 * C * * C * REVISION : ------------- JRH:--:--:1988 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: MERC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts longitude and latitude (LONG,LAT) to Mercator * C * grid coordinates (X,Y). * C * * C * LONG ..... Longitude (radians) * C * LAT ..... Latitude (radians) * C * X ........ East grid coordinates * C * Y ........ North grid coordinates * C * AE ....... Semi-major axis of Earth * C * ECS ...... Eccentricity squared of figure of Earth * C * LAT0 ..... Latitude at which scale of projection is * C * defined * C * S0 ....... Scale of projection at LAT0 * C * LONGOR ... Longitude of origin of projection * C * LATOR .... Latitude of origin of projection * C * * C ****************************************************************************** real*8 long,lat,x,y,ae,ecs,lat0,s0,longor,lator real*8 alpha,e,sl,slor,esl,eslor alpha=ae*s0/dsqrt(1.d0+(1.d0-ecs)*(dtan(lat0)**2)) e=dsqrt(ecs) x=alpha*(long-longor) sl=dsin(lat) slor=dsin(lator) esl=e*sl eslor=e*slor y=alpha*(dlog(((1.d0+sl)*(1.d0-slor)) $ /((1.d0-sl)*(1.d0+slor))) $ -e*dlog(((1.d0+esl)*(1.d0-eslor)) $ /((1.d0-esl)*(1.d0+eslor))))/2.d0 return end CBack up subroutine mxcopy(a,b,m,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHS REF:JRH:14:01:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: MXCOPY * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Forms matrix equality A=B. * C * A and B both have M rows and N cols. (M*N). * C * * C ****************************************************************************** dimension a(m,n),b(m,n) do 1 i=1,m do 1 j=1,n a(i,j)=b(i,j) 1 continue return end CBack up subroutine mxgaus(a,ind,n,sing,det) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHS REF:JRH:14:01:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: MXGAUS * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Performs an in-situ reduction of an N*N matrix A into * C * quasi-triangular matrices L (a strictly lower triangle) * C * and U (an upper triangle) by the Gauss-Doolittle method. * C * The pivots are along the diagonal of U such that : * C * A=(L+I)*U * C * No permutations of rows or columns of A are performed and * C * the pivotal row subscripts are recorded in the non-local * C * vector IND(N). Because of this, this procedure is not * C * recommended for use separately, but is called by SOLVMX. * C * SING is assigned .TRUE. if A is ill-conditioned, * C * otherwise .FALSE.. * C * DET is determinant of A. * C * * C * Ref.: First Course in Numerical Analysis, Ralston, * C * Ch. 9, P. 394. * C * * C ****************************************************************************** dimension a(n,n),ind(n) C NOTE : C ****** C ARRAY D SHOULD HAVE DIMENSION AT LEAST N (OR "M" IN SOLVM) : C double precision d(140),dspace,x integer r,rr logical sing det=0. nrc=2 do 99 r=1,n do 1 k=1,n d(k)=dble(a(k,r)) 1 continue if (r.eq.1) goto 7 rr=r-1 do 2 j=1,rr jj=ind(j) dspace=d(jj) a(j,r)=sngl(dspace) d(jj)=d(j) jj=j+1 do 3 i=jj,n d(i)=d(i)-dble(a(i,j))*dspace 3 continue 2 continue 7 dspace=d(r) if (n.ne.r) goto 10 if (dspace.eq.0.d0) goto 81 ind(n)=n a(n,n)=sngl(dspace) goto 70 10 ii=r rr=r+1 do 4 i=rr,n if (dabs(dspace)-dabs(d(i))) 5,4,4 5 dspace=d(i) ii=i 4 continue if (dspace.eq.0.d0) goto 81 ind(r)=ii if (r.ne.ii) nrc=nrc+1 a(r,r)=sngl(dspace) jj=ind(r) d(jj)=d(r) do 6 i=rr,n x=d(i)/dspace a(i,r)=sngl(x) 6 continue 99 continue C THIS METHOD CAUSES THE LOWER TRIANGLE TO BE PERMUTATED WITH C RESPECT TO THE PIVOTAL ROW SUBCRIPTS. C REARRANGING LOWER TRIANGLE... 70 if (n.eq.2) goto 80 nn=n-1 do 8 i=2,nn ii=i-1 iii=ind(i) do 9 j=1,ii y=a(i,j) a(i,j)=a(iii,j) a(iii,j)=y 9 continue 8 continue 80 sing=.false. C CALCULATING DETERMINANT OF A C DET A=PRODUCT OF DIAGONAL TERMS OF UPPER TRI-ANGLE dspace=dble(a(1,1)) do 16 i=2,n dspace=dspace*dble(a(i,i)) 16 continue det=sngl(dspace) C CALCULATING SIGN OF DET A i=nrc-2*(nrc/2) if (i.ne.0) det=-det return 81 sing=.true. return end CBack up subroutine nchar(r,idplace,n,ntot) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:31:12:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: NCHAR * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns number of figs. to left of decimal point, N, and * C * and total no. of characters (including sign and decimal * C * point), NTOT, in real number, R, defined to IDPLACE * C * decimal places. * C * * C ****************************************************************************** if(r.ne.0.) then ! First find N, no. of figs. to left of decimal point n=int(alog10(abs(r)))+1 if(n.le.0) n=1 else n=1 endif ntot=n+idplace+2 ! Total no. of characters (including sign and dec. point) return end CBack up subroutine newpen(n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:12:1986 * C * * C * REVISION : Mods. for Sun JRH:13:07:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: NEWPEN * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simulates Calcomp plotting routine, directing data to * C * disc or plotter. * C * * C * Labelled COMMON PCOM must be included in main program, * C * in which LUPLT and LULOG must be set. * C * * C ****************************************************************************** character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number nopen=mod(n-1,9)+1 ! Pen number in range 1 to 9 call jnewpen(nopen) ! @13/7/89 return end CBack up subroutine newton(f,fprime,y,xguess,x,epsa,epsp,maxit,nit,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:23:07:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: NEWTON * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Function F(X), and it's derivative FPRIME(X) are defined * C * externally. * C * NEWTON uses Newton's method to return value of X, based * C * on initial guess, XGUESS, and input value, Y in : * C * * C * Y=F(X) * C * * C * EPSA ..... absolute tolerance in X * C * EPSP ..... proportional tolerance in X * C * MAXIT .... max. number of iterations * C * NIT ...... number of iterations at end * C * IFAIL .... returned 0 if convergence satisfactory, * C * otherwise 1 * C * * C ****************************************************************************** C WRITE(6,2) Y,XGUESS,EPSA,EPSP,MAXIT !!!!!!!!!! C 2 FORMAT(' Entering NEWTON with Y = ',F10.5/ C $ ' XGUESS = ',F10.5/ C $ ' EPSA = ',F10.8/ C $ ' EPSP = ',F10.8/ C $ ' MAXIT = ',I5) !!!!!!!!!! xold=xguess do i=1,maxit ! Step through iterations xnew=xold+(y-f(xold))/fprime(xold) if(abs(xnew-xold).lt.epsa) go to 1 if(xnew.ne.0.) then if(abs((xnew-xold)/xnew).lt.epsp) go to 1 endif xold=xnew end do x=0. ! Failure to converge nit=i-1 ! Failure to converge ifail=1 ! Failure to converge return 1 x=xnew ! Successful convergence nit=i ! Successful convergence ifail=0 ! Successful convergence return end CBack up function nnonspace(a,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:08:08:1989 * C * * C * REVISION : Minor mod. to test JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: NNONSPACE * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns the number of groups of "non-space" characters in * C * the character variable A from A(1:1) to A(N:N) * C * * C ****************************************************************************** character*(*) a logical lspace icount=0 lspace=.true. do i=1,n C if(a(i:i).ne.' '.and.lspace.eq..true.) icount=icount+1 if(a(i:i).ne.' '.and.lspace) icount=icount+1 lspace=(a(i:i).eq.' ') end do nnonspace=icount return end CBack up subroutine number(x,y,wid,r,ang,idplace) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:12:1986 * C * * C * REVISION : Minor correction JRH:31:01:1987 * C * Mods. for direct plotting JRH:03:04:1987 * C * Mods. for rotation JRH:07:04:1987 * C * Minor mods. JRH:07:04:1987 * C * Mod. to output format JRH:28:05:1987 * C * Mods. for Sun JRH:13:07:1989 * C * Mods. for Sun JRH:17:07:1989 * C * Mod. to clipping logic JRH:17:07:1989 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: NUMBER * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simulates Calcomp plotting routine, directing data to * C * disc or plotter. * C * * C * Labelled COMMON PCOM must be included in main program, * C * in which LUPLT and LULOG must be set. * C * * C * X,Y ...... coordinates of bottom LH corner of text * C * WID ...... character width * C * R ........ REAL number to be written * C * ANG ...... angle (deg.) of text anticlockwise from X-axis * C * IDPLACE .. no. of decimal places to be plotted * C * * C ****************************************************************************** character*10 form character*80 a ! @3/4/87 dimension xa(2),ya(2) ! @3/4/87 logical lc(2),lplot ! @3/4/87 character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number logical lrot ! @3/4/87 common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units @3/4/87 $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units @3/4/87 $ xoff,yoff, ! Plotter offsets @3/4/87 $ pfac, ! Plotter scale factor @3/4/87 $ cw,ch, ! Character width and height @3/4/87 $ lrot ! Rotation logical @3/4/87 if(luplt.eq.-1) then ! Direct plotting @3/4/87 if(idplace.ge.0.) then ! Output as REAL no. @3/4/87 call nchar(r,idplace,n,nasc)! Tot. chs. (incl. sign and dec. point) " write(form,4) nasc,idplace ! @3/4/87 4 format('(F',i2,'.',i2,')') ! @3/4/87 write(a,form) r ! @3/4/87 else ! Output as INTEGER @3/4/87 call nchar(r,0,n,ndum) ! Tot. chs. (incl. sign and dec. point) @3/4/87 nasc=n+1 ! Total characters (incl. sign) @3/4/87 write(form,5) nasc ! @3/4/87 5 format('(1X,I',i2,')') ! @3/4/87 write(a,form) nint(r) ! @3/4/87 endif ! @3/4/87 dtr=3.14159265/180. ! @3/4/87 widdum=wid*pfac ! @7/4/87 if(lrot) then ! Rotate plot @3/4/87 xdum=-y ! @7/4/87 ydum=x ! @7/4/87 iang=90+nint(ang) ! @3/4/87 else ! @3/4/87 xdum=x ! @7/4/87 ydum=y ! @7/4/87 iang=nint(ang) ! @3/4/87 endif ! @3/4/87 xa(1)=(xdum-xmin)*pfac+xoff ! &7/4/87 ya(1)=(ydum-ymin)*pfac+yoff ! &7/4/87 clen=float(nasc)*widdum !Length of string on plot (in.) @7/4/87 &13/7/89 xa(2)=xa(1)+clen*cos(float(iang)*dtr) ! @3/4/87 ya(2)=ya(1)+clen*sin(float(iang)*dtr) ! @3/4/87 call clip(xa,ya,xlc,xrc,ybc,ytc,lc,lplot) ! @3/4/87 if(.not.lc(1).and..not.lc(2).and.lplot) then C ..... All on plot @3/4/87 &17/7/89 C call move(xa(1),ya(1)) ! @3/4/87 &13/7/89 C call charot(iang) ! @3/4/87 &13/7/89 C call chasiz(widdum,widdum*1.5) ! @7/4/87 &13/7/89 C call chahol(a,nasc) ! @3/4/87 &13/7/89 call jsymbol(xa(1),ya(1),widdum*1.0,a,float(iang),nasc) ! @17/7/89 endif ! @3/4/87 else ! @3/4/87 az=90.-ang ! Azimuth of text if(az.lt.0.) az=az+360. if(idplace.ge.0.) then ! Output as REAL no. call nchar(r,idplace,n,nasc)! Total chars. (incl. sign and dec. point) write(form,1) nasc,idplace 1 format('(1X,F',i2,'.',i2,')') write(luplt,2) x,y,wid,az,nasc,nopen 2 format(' -3 ',2e12.4,e11.4,f7.1,i3,i2) ! &28/5/87 write(luplt,form) r else ! Output as INTEGER call nchar(r,0,n,ndum) ! Total chars. (incl. sign and dec. point) nasc=n+1 ! Total characters (incl. sign) write(form,3) nasc 3 format('(1X,I',i2,')') write(luplt,2) x,y,wid,az,nasc,nopen ! &31/1/87 idum=nint(r) write(luplt,form) idum endif endif ! @3/4/87 if(luplt.ne.6) ndata=ndata+1 ! Do not update if to user's terminal return end CBack up subroutine opdig(ilp,i,j,ic) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:03:12:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: OPDIG * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Outputs digit, IC, to (I,J) from array ILP * C * * C ****************************************************************************** integer ilp(33,100) i1=(i-1)/4+1 i2=5-i+(i1-1)*4 i3=ilp(i1,j) ip=i2-1 i4=i3/(10**ip) i5=i3/(10**i2) ic=i4-i5*10 return end CBack up subroutine overlayplot(nin,ngeo,nout,nlog,lgeo,scale,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:12:10:1989 * C * * C * REVISION : Correction to input format JRH:17:11:1989 * C * Mod. to this header JRH:05:06:1990 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: OVERLAYPLOT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Overlays a plot, using data in input file * C * * C * NIN ..... Overlay file input device * C * NGEO .... Geodesy file input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * LGEO .... .TRUE. if geographical conversion required, * C * otherwise .FALSE. * C * SCALE ... Plot scale ((true)/(plot)) * C * IFAIL ... returned 0 if execution satisfactory, * C * otherwise 1 * C * * C * Codes in overlay file : * C * * C * First column : * C * S or s ..... End of file * C * T or t ..... Textual data * C * P or p ..... Polygon data * C * N or n ..... Newpen data * C * W or w ..... New window * C * R or r ..... Reset original window * C * * C * Second column (for textual, polygon or new window data):* C * G or g ..... Grid coordinate data * C * L or l ..... Longitude and latitude data * C * * C * Above character(s) are then followed (in the same * C * record) by : * C * * C * (1) For textual data, WID,AZ,NASC * C * * C * (2) For polygon data, NPOINT, the number of points to * C * be plotted * C * * C * (3) For newpen data, the required pen number * C * * C * (1) For textual data, this is followed by a record of * C * the text (80 characters), followed by a record of * C * the coordinate pair for the text position * C * * C * (2) For polygon data, this is followed by a NPOINT * C * records of the point coordinate pairs * C * * C * (3) For new window data, this is followed by two * C * records of the bottom LH and top RH corner * C * coordinate pairs * C * * C ****************************************************************************** logical lgeo real*8 long,lat,xd,yd,xdumd real*8 ae,iflat,be,ecs,eps,lat0,s0,longor,lator,ang,sang,cang character*1 atype character*40 sname character*80 buffer,text logical lfirst,lorigwind logical lrot common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units $ xoff,yoff, ! Plotter offsets $ pfac, ! Plotter scale factor $ cw,ch, ! Character width and height $ lrot ! Rotation logical save lfirst data lfirst,lorigwind/.true.,.true./ if(lfirst.and.lgeo) then ! First time through and geog. conv. required lfirst=.false. rewind(ngeo) ! For safety read(ngeo,iostat=ios) sname,ae,iflat,be,ecs,eps, $ lat0,s0,longor,lator,ang if(ios.ne.0) then ! Read error or end of file write(nout,9) write(nlog,9) 9 format(/' Error in reading geodesy') ifail=0 return endif sang=dsin(ang) cang=dcos(ang) endif rewind(nin) ! For safety 4 read(nin,1,iostat=ios) buffer 1 format(a80) if(ios.eq.-1) then ! End of file rewind(nin) ifail=0 return else if(ios.gt.0) then ! Read error write(nout,5) write(nlog,5) 5 format(/' Read error in subroutine OVERLAYPLOT') ifail=1 return endif if(buffer(1:1).eq.'S'.or.buffer(1:1).eq.'s') then ! End of overlay rewind(nin) ifail=0 if(.not.lorigwind) then ! Not currently original window xlc=xlcold ! Reset original window ybc=ybcold ! " " " xrc=xrcold ! " " " ytc=ytcold ! " " " endif return else if(buffer(1:1).eq.'T'.or.buffer(1:1).eq.'t') then ! Textual data if(buffer(2:2).eq.'G'.or.buffer(2:2).eq.'g') then ! Grid coordinates buffer(1:2)=' ' read(buffer,*,iostat=ios) wid,az,nasc if(ios.ne.0) then write(nout,7) write(nlog,7) 7 format(/ $ ' Error reading textual data in subroutine OVERLAYPLOT') ifail=1 return endif read(nin,2,iostat=ios) text 2 format(a80) if(ios.ne.0) then write(nout,7) write(nlog,7) ifail=1 return endif read(nin,*,iostat=ios) x,y ! &17/11/89 if(ios.ne.0) then write(nout,7) write(nlog,7) ifail=1 return endif x=x/scale y=y/scale wid=wid/scale angle=90.-az C Note that WID is char. width in input units, C AZ is azimuth (deg.) of line of text : call symbol(x,y,wid,text,angle,nasc) else if(buffer(2:2).eq.'L'.or.buffer(2:2).eq.'l') then ! Long. and lat. if(.not.lgeo) then write(nout,10) write(nlog,10) 10 format(/ $ ' Geographical input without geodesy in OVERLAYPLOT') ifail=1 return endif buffer(1:2)=' ' read(buffer,*,iostat=ios) wid,az,nasc if(ios.ne.0) then write(nout,7) write(nlog,7) ifail=1 return endif read(nin,2,iostat=ios) text if(ios.ne.0) then write(nout,7) write(nlog,7) ifail=1 return endif read(nin,1,iostat=ios) buffer if(ios.ne.0) then write(nout,7) write(nlog,7) ifail=1 return endif call geoginpbuff(buffer,2,long,lat,xd,yd,atype,ifail) if(ifail.ne.0.or.atype.ne.'L') then write(nout,8) write(nlog,8) 8 format(/' GEOGINPBUFF error in subroutine OVERLAYPLOT') return endif call merc(long,lat,xd,yd,ae,ecs,lat0,s0,longor,lator) xdumd=xd*cang+yd*sang yd=-xd*sang+yd*cang xd=xdumd x=sngl(xd)/scale y=sngl(yd)/scale wid=wid/scale angle=90.-az C Note that WID is char. width in input units, C AZ is azimuth (deg.) of line of text : call symbol(x,y,wid,text,angle,nasc) else ! Invalid code write(nout,3) write(nlog,3) 3 format(/' Invalid code in subroutine OVERLAYPLOT') ifail=1 endif else if(buffer(1:1).eq.'P'.or.buffer(1:1).eq.'p') then ! Polygon data if(buffer(2:2).eq.'G'.or.buffer(2:2).eq.'g') then ! Grid coordinates buffer(1:2)=' ' read(buffer,*,iostat=ios) npoint if(ios.ne.0) then write(nout,6) write(nlog,6) 6 format(/ $ ' Error reading polygon data in subroutine OVERLAYPLOT') ifail=1 return endif do i=1,npoint read(nin,*,iostat=ios) x,y if(ios.ne.0) then write(nout,6) write(nlog,6) ifail=1 return endif x=x/scale y=y/scale if(i.eq.1) then call plot(x,y,3) else call plot(x,y,2) endif end do else if(buffer(2:2).eq.'L'.or.buffer(2:2).eq.'l') then ! Long. and lat. if(.not.lgeo) then write(nout,10) write(nlog,10) ifail=1 return endif buffer(1:2)=' ' read(buffer,*,iostat=ios) npoint if(ios.ne.0) then write(nout,6) write(nlog,6) ifail=1 return endif do i=1,npoint read(nin,1,iostat=ios) buffer if(ios.ne.0) then write(nout,6) write(nlog,6) ifail=1 return endif call geoginpbuff(buffer,2,long,lat,xd,yd,atype,ifail) if(ifail.ne.0.or.atype.ne.'L') then write(nout,8) write(nlog,8) return endif call merc(long,lat,xd,yd,ae,ecs,lat0,s0,longor,lator) xdumd=xd*cang+yd*sang yd=-xd*sang+yd*cang xd=xdumd x=sngl(xd)/scale y=sngl(yd)/scale if(i.eq.1) then call plot(x,y,3) else call plot(x,y,2) endif end do else ! Invalid code write(nout,3) write(nlog,3) ifail=1 endif else if(buffer(1:1).eq.'N'.or.buffer(1:1).eq.'n') then ! Newpen data buffer(1:1)=' ' read(buffer,*,iostat=ios) nopen if(ios.ne.0) then write(nout,11) write(nlog,11) 11 format(/ $ ' Error reading NEWPEN data in subroutine OVERLAYPLOT') ifail=1 return endif call newpen(nopen) else if(buffer(1:1).eq.'W'.or.buffer(1:1).eq.'w') then ! New window data if(lorigwind) then ! Currently uses original window xlcold=xlc ! Save original window ybcold=ybc ! " " " xrcold=xrc ! " " " ytcold=ytc ! " " " lorigwind=.false. endif if(buffer(2:2).eq.'G'.or.buffer(2:2).eq.'g') then ! Grid coordinates do i=1,2 read(nin,*,iostat=ios) x,y if(ios.ne.0) then write(nout,12) write(nlog,12) 12 format(/ $ ' Error reading window data in subroutine OVERLAYPLOT') ifail=1 return endif if(i.eq.1) then xlc=x ybc=y else xrc=x ytc=y endif end do else if(buffer(2:2).eq.'L'.or.buffer(2:2).eq.'l') then ! Long. and lat. do i=1,2 read(nin,1,iostat=ios) buffer if(ios.ne.0) then write(nout,12) write(nlog,12) ifail=1 return endif call geoginpbuff(buffer,2,long,lat,xd,yd,atype,ifail) if(ifail.ne.0.or.atype.ne.'L') then write(nout,8) write(nlog,8) return endif call merc(long,lat,xd,yd,ae,ecs,lat0,s0,longor,lator) xdumd=xd*cang+yd*sang yd=-xd*sang+yd*cang xd=xdumd if(i.eq.1) then xlc=sngl(xd) ybc=sngl(yd) else xrc=sngl(xd) ytc=sngl(yd) endif end do else ! Invalid code write(nout,3) write(nlog,3) ifail=1 endif if(lrot) then ! Rotate coordinates by 90 deg. xlcd=xlc xrcd=xrc xlc=-ytc xrc=-ybc ybc=xlcd ytc=xrcd endif xlc=(xlc/scale-xmin)*pfac+xoff xrc=(xrc/scale-xmin)*pfac+xoff ybc=(ybc/scale-ymin)*pfac+yoff ytc=(ytc/scale-ymin)*pfac+yoff else if(buffer(1:1).eq.'R'.or.buffer(1:1).eq.'r') then ! Original window if(.not.lorigwind) then ! Not currently original window xlc=xlcold ! Reset original window ybc=ybcold ! " " " xrc=xrcold ! " " " ytc=ytcold ! " " " lorigwind=.true. endif else write(nout,3) write(nlog,3) ifail=1 return endif go to 4 ! Read more data end CBack up subroutine picalc(pi) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:25:07:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: PICALC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Returns the value of PI * C * * C ****************************************************************************** real*4 pi pi=atan(1.)*4. return end CBack up logical function pinsd(xp,yp,n,x0,y0) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:23:08:1989 * C * * C * REVISION : Minor mod. to comment JRH:29:03:1993 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: PINSD * C * TYPE : LOGICAL FUNCTION * C * * C * FUNCTION : Returns .TRUE. if (X0,Y0) inside polygon, otherwise * C * returns .FALSE. * C * No. sides of polygon = N-1. * C * Total boundary of polygon is defined by N values in * C * arrays X and Y (XP(N)=XP(1), YP(N)=YP(1)) * C * * C ****************************************************************************** real*4 xp(1),yp(1) logical lxpos,lxneg ! Logicals for determining intersec. dir. on X=X0 m=0 do 2 i=1,n-1 ip1=i+1 C Do quickies first ...... if(xp(i).eq.x0.and.yp(i).eq.y0) go to 1 ! Point at start of segment if(xp(i).eq.x0.and.xp(ip1).eq.x0) then ! Segment N-S, alligned with pt. if((yp(i).ge.y0.and.yp(ip1).le.y0).or. $ (yp(i).le.y0.and.yp(ip1).ge.y0)) go to 1 ! Point on segment endif C Now do proper intersection test ...... lxpos=(xp(i).lt.x0.and.xp(ip1).ge.x0) lxneg=(xp(i).ge.x0.and.xp(ip1).lt.x0) if(lxpos.or.lxneg) then ! A valid intersection on X=X0 dum=yp(i)-y0-(xp(i)-x0)*(yp(ip1)-yp(i))/ $ (xp(ip1)-xp(i)) ! Intersection on X=X0 if(dum.eq.0.) go to 1 ! Point on segment if(dum.gt.0.) then ! Valid intersection N of point if(lxpos) then m=m+1 ! Positive intersection N of point else m=m-1 ! Negative intersection N of point endif endif endif 2 continue if(m.eq.0) then pinsd=.false. ! Equal no. of +ve and -ve intersects. on 0 deg. az. else pinsd=.true. ! Unequal no. of +ve and -ve intersects. on 0 deg. az. endif return C Exit point for point on boundary. C Put PINSD =.TRUE. if boundary point considered inside, C Put PINSD =.FALSE. if boundary point considered outside : 1 pinsd=.true. ! Boundary point considered inside return end CBack up subroutine plot(x,y,ipen) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:12:1986 * C * * C * REVISION : Terminal input of PTIT removed JRH:01:01:1987 * C * Mods. for direct plotting JRH:03:04:1987 * C * Minor mods. JRH:06:04:1987 * C * Mods. for rotation JRH:07:04:1987 * C * Minor mod. JRH:15:04:1987 * C * Mods. for Sun JRH:13:07:1989 * C * Mod. to pause at end of SUNCGI plot JRH:17:07:1989 * C * Mod. so that jplot(0.,0.,999) may * C * follow jplot(0.,0.,-999) JRH:18:07:1989 * C * Mod. for "sleep" option with CGI at * C * end of plot (for use with Unix script * C * files) JRH:15:11:1989 * C * Continuation of above mod. JRH:21:12:1989 * C * Mod. to "sleep" option JRH:08:11:1990 * C * Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: PLOT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simulates Calcomp plotting routine, directing data to * C * disc, or plotter. * C * * C * Labelled COMMON PCOM must be included in main program, * C * in which LUPLT and LULOG must be set. * C * * C * Values of IPEN : * C * * C * -3 ..... Terminate old plot, start new plot, set * C * default pen number, NOPEN, reset origin, move * C * pen to origin * C * * C * 2 ...... Draw line from current pen position to point * C * (X,Y) * C * * C * 3 ...... Move pen from current pen position to point * C * (X,Y) * C * * C * 99 ..... Terminate old plot only * C * * C * 999 .... Terminate plotting completely * C * * C ****************************************************************************** character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number logical lrot ! @3/4/87 common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units @3/4/87 $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units @3/4/87 $ xoff,yoff, ! Plotter offsets @3/4/87 $ pfac, ! Plotter scale factor @3/4/87 $ cw,ch, ! Character width and height @3/4/87 $ lrot ! Rotation logical @3/4/87 common/device/idevice ! For Andrewartha's plot routines @17/7/89 dimension rarray(2) ! @3/4/87 character*20 adum ! @15/11/89 &8/11/90 if(ipen.eq.999) then ! Terminate plotting completely if(luplt.eq.-1.) then ! Direct plotting @3/4/87 C if(ndata.ne.-2) call endgrf ! &13/7/89 if(ndata.ne.-2) then ! &17/7/89 if(idevice.eq.0) then ! SUNCGI @17/7/89 write(6,4) ! @17/7/89 4 format(/' Press RETURN to continue, ', ! &15/11/89 $ '''s'' RETURN to sleep') ! @15/11/89 read(5,5) adum ! @15/11/89 5 format(a20) ! @15/11/89 &8/11/90 if(adum(1:1).eq.'s'.or. ! @15/11/89 &8/11/90 $ adum(1:1).eq.'S') then ! @15/11/89 &8/11/90 read(adum(2:20),*) idum ! @8/11/90 call sleep(idum) ! @8/11/90 endif ! @8/11/90 endif ! @17/7/89 C Following mods. (next three lines) to allow call of jplot(0.,0.,-999) C followed by call of jplot(0.,0.,999), since jplots requires a previous C call of jplot(0.,0.,999) (rather than simply jplot(0.,0.,-999) &18/7/89 endif ! @18/7/89 call jplot(0.,0.,999) ! @13/7/89 C endif ! @17/7/89 &18/7/89 C ..... Terminate old plot (check that plot not previously terminated) @6/4/87 else ! @3/4/87 if(ndata.ne.-2) write(luplt,3) C ..... Terminate old plot (check that plot not previously terminated) @6/4/87 3 format(' -1 0 0 0') close(luplt) endif else if(ipen.eq.99) then ! Terminate plot only @3/4/87 if(luplt.eq.-1) then ! Direct plotting @6/4/87 if(idevice.eq.0) then ! SUNCGI @17/7/89 write(6,4) ! @17/7/89 read(5,5) adum ! @15/11/89 if(adum(1:1).eq.'s'.or. ! @15/11/89 &8/11/90 $ adum(1:1).eq.'S') then ! @15/11/89 &8/11/90 read(adum(2:20),*) idum ! @8/11/90 call sleep(idum) ! @8/11/90 endif ! @8/11/90 endif ! @17/7/89 C call endgrf ! &13/7/89 call jplot(0.,0.,-999) ! @13/7/89 else ! @6/4/87 write(luplt,3) ! @6/4/87 endif ! @6/4/87 ndata=-2 ! Flag that plot has been terminated @6/4/87 else if(ipen.eq.-3) then ! New plot nopen=1 ! @3/4/87 if(luplt.eq.-1) then ! Direct plotting @3/4/87 C if(ndata.ne.-1.and.ndata.ne.-2) call endgrf ! &13/7/89 if(ndata.ne.-1.and.ndata.ne.-2) then ! &17/7/89 if(idevice.eq.0) then ! SUNCGI @17/7/89 write(6,4) ! @17/7/89 read(5,5) adum ! @16/11/89 if(adum(1:1).eq.'s'.or. ! @15/11/89 &8/11/90 $ adum(1:1).eq.'S') then ! @15/11/89 &8/11/90 read(adum(2:20),*) idum ! @8/11/90 call sleep(idum) ! @8/11/90 endif ! @8/11/90 endif ! @17/7/89 call jplot(0.,0.,-3) ! @13/7/89 endif ! @17/7/89 C ..... Terminate old plot (check that this is not first plot and that C ..... plot not previously terminated) @6/4/87 call rread(5,6,lulog, ! @3/4/87 $ 'X and Y offsets of plot (metres) ? ','$',!@3/4/87 $ rarray,1,2, ! @3/4/87 $ '((1X,2F10.4)) ') ! &15/4/87 xoff=rarray(1) ! @3/4/87 yoff=rarray(2) ! @3/4/87 xoff=xoff*1000./25.4 ! Convert to in. @3/4/87 &13/7/89 yoff=yoff*1000./25.4 ! Convert to in. @3/4/87 &13/7/89 C call init(idum) ! @3/4/87 &13/7/89 xlc=xoff ! LH side of window @3/4/87 xrc=(xmax-xmin)*pfac+xoff ! RH side of window @3/4/87 ybc=yoff ! Bottom of window @3/4/87 ytc=(ymax-ymin)*pfac+yoff ! Top of window @3/4/87 C call move(xlc,ybc) ! @3/4/87 &13/7/89 call jplot(xlc,ybc,3) ! @13/7/89 C call draw(xrc,ybc) ! @3/4/87 &13/7/89 call jplot(xrc,ybc,2) ! @13/7/89 C call draw(xrc,ytc) ! @3/4/87 &13/7/89 call jplot(xrc,ytc,2) ! @13/7/89 C call draw(xlc,ytc) ! @3/4/87 &13/7/89 call jplot(xlc,ytc,2) ! @13/7/89 C call draw(xlc,ybc) ! @3/4/87 &13/7/89 call jplot(xlc,ybc,2) ! @13/7/89 C call move(10.+xlc,ytc+10.) ! @3/4/87 &13/7/89 C call charot(0) ! @3/4/87 &13/7/89 C call chasiz(cw,ch) ! Set character size @3/4/87 &13/7/89 C call chahol(ptit,40) ! @3/4/87 &13/7/89 call jsymbol(xlc+10./25.4,ytc+10./25.4,ch,ptit,0.,40) ! @13/7/89 C call move(xlc,ybc) ! Go to origin @3/4/87 &13/7/89 call jplot(xlc,ybc,3) ! Go to origin @13/7/89 else ! @3/4/87 if(ndata.ne.-1.and.ndata.ne.-2) write(luplt,3) C ..... Terminate old plot (check that this is not first plot and that C ..... plot not previously terminated) @6/4/87 write(luplt,1) ptit 1 format(1x,a40) write(luplt,2) 0.,0.,3,nopen ! Go to origin endif ! @3/4/87 ndata=0 ! @3/4/87 else ! Normal plot instruction if(luplt.eq.-1) then ! Direct plotting @3/4/87 if(lrot) then ! Rotation by 90 deg. required @3/4/87 xdum=-y ! @7/4/87 ydum=x ! @7/4/87 else ! @7/4/87 xdum=x ! @7/4/87 ydum=y ! @7/4/87 endif ! @3/4/87 if(ipen.eq.2.or.ipen.eq.3) then ! @3/4/87 call plota((xdum-xmin)*pfac+xoff, ! &7/4/87 $ (ydum-ymin)*pfac+yoff,ipen, ! &7/4/87 $ xlc,xrc,ybc,ytc) ! @3/4/87 endif else ! @3/4/87 write(luplt,2) x,y,ipen,nopen 2 format(1x,2e11.4,i4,i2) endif ! @3/4/87 if(luplt.ne.6) ndata=ndata+1 ! Do not update if to user's terminal endif endif ! @3/4/87 endif return end CBack up subroutine plota(xx,yy,ipen,xlc,xrc,ybc,ytc) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:23:09:1986 * C * * C * REVISION : Modification of name PLOT to PLOTA JRH:29:12:1986 * C * Mods. for Sun JRH:13:07:1989 * C * Mod. so that NEWPEN is called * C * regularly when IPEN = 2 (the purpose * C * of this is for Postcript plotting) JRH:18:07:1989 * C * Inclusion of additional call to * C * NEWPEN JRH:11:08:1989 * C * * C * SOURCE : PLT1199.FOR * C * ROUTINE NAME: PLOTA * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Calcomp-type plotting routine, with clipping to window * C * (XLC,YBC) to (XRC,YTC) * C * * C ****************************************************************************** C COMMON/PCOM/ added for regular calls of NEWPEN : @18/7/89 character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number dimension x(2),y(2) logical l3,lc(2),lplot save xlst,ylst,l3 if(ipen.eq.3) then ! IPEN = 3 xlst=xx ylst=yy l3=.true. if((ndata/100)*100.eq.ndata) call newpen(nopen) ! @11/8/89 else ! IPEN = 2 x(1)=xlst y(1)=ylst x(2)=xx y(2)=yy xlst=x(2) ylst=y(2) call clip(x,y,xlc,xrc,ybc,ytc,lc,lplot) if(lplot) then C if(l3.or.lc(1)) call move(x(1),y(1)) ! &13/7/89 if(l3.or.lc(1)) call jplot(x(1),y(1),3) ! @13/7/89 C call draw(x(2),y(2)) ! &13/7/89 call jplot(x(2),y(2),2) ! &13/7/89 if((ndata/100)*100.eq.ndata) then ! @18/7/89 call newpen(nopen) ! @18/7/89 call jplot(x(2),y(2),3)! Move back to point is now required @18/7/89 endif ! @18/7/89 endif l3=.false. ! Clear "move" flag endif return end CBack up subroutine plots(idum) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:12:1986 * C * * C * REVISION : DOPEN changed to DSKOPEN JRH:13:01:1987 * C * Mod. to DSKOPEN call JRH:22:01:1987 * C * Mods. for direct plotting JRH:03:04:1987 * C * Mods. for Sun JRH:13:07:1989 * C * Mods. for Sun JRH:17:07:1989 * C * Minor mod. to terminal O/P JRH:17:07:1989 * C * Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: PLOTS * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simulates Calcomp plotting routine, directing data to * C * disc or plotter. * C * * C * Labelled COMMON PCOM must be included in main program, * C * in which LUPLT and LULOG must be set. * C * * C ****************************************************************************** character*20 filnam ! @3/4/87 dimension rarray(4) ! @3/4/87 logical yesno ! @3/4/87 character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number logical lrot ! @3/4/87 common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units @3/4/87 $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units @3/4/87 $ xoff,yoff, ! Plotter offsets @3/4/87 $ pfac, ! Plotter scale factor @3/4/87 $ cw,ch, ! Character width and height @3/4/87 $ lrot ! Rotation logical @3/4/87 if(luplt.ne.6) then ! Only do following if unit no. not user's terminal filnam=' ' ! @13/7/89 if(luplt.ne.-1) then ! Check if already set for direct plotting @3/4/87 write(6,1) ! @3/4/87 1 format(/' Filename for plot file ' ! @3/4/87 $ /' ("DIRECT" for direct plotting) ? ') ! @13/7/89 C $ /' ("PLOTTER" for plotter) ? '$)!@3/4/87&13/7/89 read(5,2) filnam ! @3/4/87 2 format(a20) ! @3/4/87 write(lulog,3) filnam ! @3/4/87 3 format(/' Filename for plot file ' ! @3/4/87 $ /' ("DIRECT" for direct plotting) ? ',a20) C ..... @3/4/87 @13/7/89 C $ /' ("PLOTTER" for plotter) ? ',a20) C ..... @3/4/87 &13/7/89 endif ! @3/4/87 C if(filnam.eq.'PLOTTER'.or.filnam.eq.'plotter'.or. ! @3/4/87 &13/7/89 if(filnam.eq.'DIRECT'.or.filnam.eq.'direct'.or. ! @3/4/87 @13/7/89 $ luplt.eq.-1) then ! Direct plotting @3/4/87 luplt=-1 ! Flag direct plotting @3/4/87 iorient=0 ! Landscape @13/7/89 jfil=50 ! This unit number is generally unused @13/7/89 kdev=0 ! SUNCGI @13/7/89 if(yesno(5,6,lulog, ! @13/7/89 $ 'Postscript (Y) or SUNCGI (N) ? ')) ! @13/7/89 $ kdev=1 ! Postscript @13/7/89 call jplots(iorient,jfil,kdev) ! @13/7/89 call rread(5,6,lulog, ! @3/4/87 $ 'Units of input (eg. ".001" for mm.) ? ','$', ! @3/4/87 $ rarray,1,1, ! @3/4/87 $ '((1X,F10.4)) ') ! @3/4/87 units=rarray(1) ! @3/4/87 call rread(5,6,lulog, ! @17/7/89 $ 'Clipping boundaries : ',' ', ! @17/7/89 $ rarray,0,0, ! @17/7/89 $ '((1X,4F10.4)) ') ! @17/7/89 call rread(5,6,lulog, ! @3/4/87 $ 'XMIN,XMAX,YMIN,YMAX (in units of I/P) ? ','$', ! @3/4/87 $ rarray,1,4, ! @3/4/87 $ '((1X,4F10.4)) ') ! @3/4/87 xmin=rarray(1) ! @3/4/87 xmax=rarray(2) ! @3/4/87 ymin=rarray(3) ! @3/4/87 ymax=rarray(4) ! @3/4/87 lrot=yesno(5,6,lulog, ! @3/4/87 $ 'Rotate plot anticlockwise by 90 deg. ? ') ! @3/4/87 if(lrot) then ! Swop round XMIN,XMAX,YMIN,YMAX @3/4/87 xmind=xmin ! @3/4/87 xmaxd=xmax ! @3/4/87 xmin=-ymax ! @3/4/87 xmax=-ymin ! @3/4/87 ymin=xmind ! @3/4/87 ymax=xmaxd ! @3/4/87 endif ! @3/4/87 call rread(5,6,lulog, ! @3/4/87 $ 'Scale for plotter ',' ', ! &17/7/89 $ rarray,0,0, ! @3/4/87 $ '((1X,F10.0)) ') ! @3/4/87 call rread(5,6,lulog, ! @3/4/87 $ '(input size)/(plot size)) ? ','$', ! @3/4/87 $ rarray,1,1, ! @3/4/87 $ '((1X,F10.0)) ') ! @3/4/87 pscale=rarray(1) ! @3/4/87 pfac=units*1000./(pscale*25.4) ! Convert to in. @3/4/87 &13/7/89 cw=(xmax-xmin)*1000./(pscale*50.*25.4) ! Set character width C ..... @3/4/87 &13/7/89 C ch=cw*1.5 ! Set character height @3/4/87 &17/7/89 ch=cw*1.0 ! Set character height @17/7/89 else ! @3/4/87 open(unit=luplt,file=filnam,status='UNKNOWN') ! @3/4/87 endif ! @3/4/87 endif idum=0 ! For time being, do not check if disc OPEN O.K. ndata=-1 ! Flag call of PLOTS but not yet PLOT(*,*,-3) return end CBack up real*4 function ran3(idum) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:24:03:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: ran3 * C * TYPE : real*4 function * C * * C * FUNCTION : Random number generator (from Numerical Recipes). * C * * C ****************************************************************************** integer*4 idum C real*4 fac integer*4 mbig,mseed,mz parameter (mbig=1000000000,mseed=161803398,mz=0,fac=1.e-9) integer*4 ma(55) integer*4 iff,inext,inextp,mj,mk,i,ii,k data iff /0/ save inext,inextp,ma,iff ! Mod. to Numerical Recipes code if(idum.lt.0.or.iff.eq.0)then iff=1 mj=mseed-iabs(idum) mj=mod(mj,mbig) ma(55)=mj mk=1 do 11 i=1,54 ii=mod(21*i,55) ma(ii)=mk mk=mj-mk if(mk.lt.mz)mk=mk+mbig mj=ma(ii) 11 continue do 13 k=1,4 do 12 i=1,55 ma(i)=ma(i)-ma(1+mod(i+30,55)) if(ma(i).lt.mz)ma(i)=ma(i)+mbig 12 continue 13 continue inext=0 inextp=31 idum=1 endif inext=inext+1 if(inext.eq.56)inext=1 inextp=inextp+1 if(inextp.eq.56)inextp=1 mj=ma(inext)-ma(inextp) if(mj.lt.mz)mj=mj+mbig ma(inext)=mj ran3=mj*fac return end CBack up subroutine ra2xy(r,a,x,y) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:20:08:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: RA2XY * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts (R,A(azimuth) to (X,Y). * C * * C ****************************************************************************** x=r*sin(a) y=r*cos(a) return end CBack up subroutine remlink(irem, $ prev,next,stack,ifirst,ilast,topstack,maxlink, $ ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:11:10:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: REMLINK * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Removes item from link list * C * * C * IREM ..... pointer to item to be removed * C * PREV ..... array of pointers to previous item in list * C * NEXT ..... array of pointers to next item in list * C * STACK .... stack of unused list pointers * C * IFIRST ... pointer to first item in list * C * ILAST .... pointer to last item in list * C * TOPSTACK . pointer to top of stack * C * MAXLINK .. maximum number of items in list * C * IFAIL .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 prev(maxlink),next(maxlink),stack(maxlink) integer*4 irem,ifirst,ilast,topstack,maxlink,ifail integer*4 prevdum,nextdum if(irem.lt.1.or.irem.gt.maxlink) then ! Invalid pointer ifail=1 return endif if(topstack.eq.maxlink) then ! List must be empty ifail=1 return endif topstack=topstack+1 if(stack(topstack).ne.0) then ! Overwriting existing pointer ifail=1 return endif stack(topstack)=irem ! Put old pointer back on stack if(irem.eq.ifirst.and.irem.eq.ilast) then ! Do this easy one first ifirst=0 ilast=0 else prevdum=prev(irem) nextdum=next(irem) if(irem.eq.ifirst) then ! Remove first item in list if(nextdum.eq.0) then ! Invalid pointer ifail=1 return endif prev(nextdum)=0 ifirst=nextdum else if(irem.eq.ilast) then ! Remove last item in list if(prevdum.eq.0) then ! Invalid pointer ifail=1 return endif next(prevdum)=0 ilast=prevdum else if(nextdum.eq.0.or.prevdum.eq.0) then ! Invalid pointer ifail=1 return endif prev(nextdum)=prevdum next(prevdum)=nextdum endif endif prev(irem)=0 ! Clear link next(irem)=0 ! Clear link ifail=0 return end CBack up double precision function rostp(s,t,p) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:03:07:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: ROSTP * C * TYPE : DOUBLE PRECISION FUNCTION * C * * C * FUNCTION : Returns density of seawater as function of salinity * C * (Practical), temperature (degrees C) and pressure * C * (bars, above one standard atmosphere). * C * Reference : * C * UNESCO, 1981. Tenth report of the joint panel on * C * oceanographic tables and standards, UNESCO Technical * C * Papers in Marine Science No. 36, UNESCO, Paris. * C * * C ****************************************************************************** double precision s,t,p double precision b(0:4),c(0:2),d0,a(0:5),f(0:3),g(0:2),i(0:2) double precision j0,m(0:2),e(0:4),h(0:3),k(0:2) double precision row,rost0,kst0,kstp,kw,aw,bw,aa,bb,dum data b $/ 8.24493d-1, -4.0899d-3, 7.6438d-5, -8.2467d-7, 5.3875d-9/ data c $/ -5.72466d-3, 1.0227d-4, -1.6546d-6/ data d0 $/ 4.8314d-4/ data a $/ 999.842594, 6.793952d-2,-9.095290d-3, 1.001685d-4,-1.120083d-6, $ 6.536332d-9/ data f $/ 54.6746, -0.603459, 1.09987d-2, -6.1670d-5/ data g $/ 7.944d-2, 1.6483d-2, -5.3009d-4/ data i $/ 2.2838d-3, -1.0981d-5, -1.6078d-6/ data j0 $/ 1.91075d-4/ data m $/ -9.9348d-7, 2.0816d-8, 9.1697d-10/ data e $/ 19652.21, 148.4206, -2.327105, 1.360477d-2,-5.155288d-5/ data h $/ 3.239908, 1.43713d-3, 1.16092d-4, -5.77905d-7/ data k $/ 8.50935d-5, -6.12293d-6, 5.2787d-8/ C Calculate density of reference pure water : row=a(0) do ii=1,5 row=row+a(ii)*t**ii ! Density of reference pure water end do C Calculate density at one standard atmosphere : dum=b(0) do ii=1,4 dum=dum+b(ii)*t**ii end do rost0=row+dum*s dum=c(0) do ii=1,2 dum=dum+c(ii)*t**ii end do rost0=rost0+dum*dsqrt(s**3)+d0*s*s ! Density at one standard atmosphere C Calculate pure water terms of the secant bulk modulus : kw=e(0) do ii=1,4 kw=kw+e(ii)*t**ii end do aw=h(0) do ii=1,3 aw=aw+h(ii)*t**ii end do bw=k(0) do ii=1,2 bw=bw+k(ii)*t**ii end do C Calculate secant bulk modulus at one standard atmosphere : dum=f(0) do ii=1,3 dum=dum+f(ii)*t**ii end do kst0=kw+dum*s dum=g(0) do ii=1,2 dum=dum+g(ii)*t**ii end do kst0=kst0+dum*dsqrt(s**3) ! Secant bulk modulus at one standard atmosphere C Calculate secant bulk modulus : dum=i(0) do ii=1,2 dum=dum+i(ii)*t**ii end do aa=aw+dum*s+j0*dsqrt(s**3) dum=m(0) do ii=1,2 dum=dum+m(ii)*t**ii end do bb=bw+dum*s kstp=kst0+aa*p+bb*p*p ! Secant bulk modulus C Calculate density of seawater : rostp=rost0/(1.d0-p/kstp) ! Density of seawater return end CBack up subroutine rread(nin,nout,nlog,anot,acc,rarray,istart,istop,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:08:1986 * C * * C * REVISION : Error trap included JRH:04:09:1986 * C * Mod. for output of message only if * C * ISTART=0 or ISTOP=0 JRH:12:09:1986 * C * Minor mods. JRH:31:12:1986 * C * Minor mod. JRH:05:01:1987 * C * Minor mod. JRH:17:05:1988 * C * Mod. so that FORM is input without * C * brackets JRH:21:06:1988 * C * Mod. for null read after error to cope * C * with Sun bug JRH:25:07:1989 * C * Mod. for compilation on transputer JRH:07:09:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: RREAD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads in a set of REAL numbers * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Annotation (40 chars.) * C * ACC ..... Carriage-control character * C * (' ' for new line, '$' for same line) * C * RARRAY .. Resultant REAL array * C * ISTART .. Start index of RARRAY * C * ISTOP ... Stop index of RARRAY * C * FORM .... Format for output to log device (40 chars., * C * without brackets) * C * * C ****************************************************************************** real rarray(*) character*40 anot,form character*1 acc character*42 formt ! @7/9/89 logical cont ! @31/12/86 save cont ! @31/12/86 character*12 formout ! &5/1/87 data cont/.false./ ! @11/5/88 2 if(cont) then ! Continuation of terminal text @31/12/86 &25/7/89 write(formout,1) ' ',acc ! &31/12/86 1 format('(',a1,'X,A40,A1',a1,')') ! &5/1/87 else ! Normal text @31/12/86 write(formout,1) '/',acc ! @31/12/86 endif ! @31/12/86 write(nout,formout) anot,' ' ! &5/1/87 write(nlog,formout) anot,' ' ! @5/1/87 if(istart.ne.0.and.istop.ne.0) then ! &31/12/86 read(nin,*,err=3) (rarray(i),i=istart,istop) ! &4/9/86 formt='('//form//')' ! @7/9/89 write(nlog,formt) (rarray(i),i=istart,istop) ! &21/6/88 &7/9/89 cont=.false. ! Terminal text not to be continued @31/12/86 else ! @31/12/86 cont=.true. ! Terminal text to be continued @31/12/86 endif ! @12/9/86 return 3 read(nin,*) ! Null read to cope with Sun bug @25/7/89 go to 2 ! @25/7/89 end CBack up subroutine rreadfil(nin,nout,nlog,anot,nchar,rvar,form) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1987 * C * * C * REVISION : Mod. for keyword checking JRH:19:01:1987 * C * Simplification JRH:17:06:1988 * C * Minor correction JRH:07:07:1988 * C * Mod. for compilation on transputer JRH:07:09:1989 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: RREADFIL * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads REAL variable from file based on keyword. * C * * C * NIN ..... File input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Keyword in file * C * NCHAR ... Number of characters in ANOT (max. 40) * C * RVAR .... Resultant REAL variable * C * FORM .... Format for output (40 chars., without brackets) * C * * C ****************************************************************************** character*(*) anot character*40 form character*80 buff character*40 blank ! &17/6/88 character*40 formt ! @7/9/89 character*51 formt2 character*14 formt3 data blank/' '/ write(formt2,6) nchar,form 6 format('(1X,A',i2,',A3,',a40,')') write(formt3,5) nchar 5 format('(/A9,A',i2,',A34/)') rewind(nin) 4 read(nin,2,end=3) buff 2 format(a80) if(buff(1:nchar).eq.anot.and. ! &17/6/88 $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found &19/1/87 buff(1:nchar)=blank(1:nchar) ! Delete keyword idum1=lhschar(buff) ! Index of first character of value @7/9/89 idum2=lenchar(buff) ! Index of last character of value @7/9/89 write(formt,7) idum2-idum1+1 ! @7/9/89 7 format('(f',i2,'.0)') ! @7/9/89 read(buff(idum1:idum2),formt) rvar ! Read variable &7/9/89 write(nout,formt2) anot,' = ',rvar write(nlog,formt2) anot,' = ',rvar return else go to 4 ! Read more data endif 3 write(nout,formt3) ' Keyword ',anot, $ ' not found .... program terminated' write(nlog,formt3) ' Keyword ',anot, $ ' not found .... program terminated' stop end CBack up subroutine rreadfil2(nin,anot,nchar,var,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:06:01:1995 * C * * C * REVISION : ------------- JRH:--:--:1995 * C * * C * SOURCE : forlib.f * C * ROUTINE NAME: rreadfil2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads REAL*4 variable from file based on keyword. * C * (Modified version of rreadfil, without output to operator * C * or log file) * C * * C * nin ..... File input device * C * anot .... Keyword in file * C * nchar ... Number of characters in ANOT (max. 40) * C * var ..... Resultant REAL*4 variable * C * ifail ... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*4 var integer*4 nin,nchar,ifail character*(*) anot C integer*4 ios logical found character*80 buff C rewind(nin) ios=0 found=.false. do while(ios.eq.0.and..not.found) read(nin,1,iostat=ios) buff 1 format(a80) if(buff(1:nchar).eq.anot.and. $ buff(nchar+1:nchar+1).eq.' ') then ! Match has been found read(buff(nchar+2:80),*,iostat=ios) var found=.true. endif end do if(ios.eq.0) then ifail=0 ! Match found and no error else ifail=1 ! No match found endif end CBack up subroutine r2dcalc(r2d) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:25:07:1991 * C * * C * REVISION : ------------- JRH:--:--:1991 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: R2DCALC * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Returns the value of R2D (radians to degrees constant) * C * * C ****************************************************************************** real*4 r2d r2d=180./(atan(1.)*4.) return end CBack up subroutine sim(f,xl,xh,epsa,epsp,s,m4) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHEMATICS REF:JRH:23:07:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SIM * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Performs Simpson integration of function F between limits * C * limits XL and XH. * C * EPSA ..... required absolute difference between * C * successive approximations * C * EPSP ..... required proportional difference between * C * successive approximations * C * S ........ solution * C * M4 ....... final number of integration steps * C * * C ****************************************************************************** C WRITE(6,6) !!!!!!!!!! C 6 FORMAT(/) !!!!!!!!!! C WRITE(6,8) XL,XH,EPSA,EPSP !!!!!!!!!! C 8 FORMAT(' Entering SIM with XL = ',F10.5/ C $ ' XH = ',F10.5/ C $ ' EPSA = ',F10.8/ C $ ' EPSP = ',F10.8) !!!!!!!!!!! sold=0. fl=f(xl) fh=f(xh) m4=2 4 m2=m4-1 C WRITE(6,5) !!!!!!!!!! C 5 FORMAT('+.'$) !!!!!!!!!! rm=m4 del=(xh-xl)/rm s4=0. s2=0. do 1 i=1,m4 ri=i 1 s4=s4+f(xl+(ri-0.5)*del) do 2 i=1,m2 ri=i 2 s2=s2+f(xl+ri*del) s=(fl+fh+4.*s4+2.*s2)*del/6. if(abs(s-sold).lt.epsa) return if(s.ne.0.) then if(abs((s-sold)/s).lt.epsp) return endif sold=s m4=2*m4 go to 4 end CBack up subroutine sima(aa,s,m4,range) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:15:05:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SIMA * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simpson integration - definite - routine A * C * * C * AA .... Array to be integrated * C * S ..... Definite integral * C * M4 .... Number of "double" increments * C * RANGE . Integration range * C * * C ****************************************************************************** dimension aa(1) C WRITE(6,1000) C1000 FORMAT(' A'$) m2=m4-1 del=range/float(m4) s4=0. s2=0. do i=1,m4 ii=i*2 C WRITE(6,4000) S4 C4000 FORMAT(' S4 = ',E10.3) s4=s4+aa(ii) end do do i=1,m2 ii=i*2+1 C WRITE(6,5000) S2 C5000 FORMAT(' S2 = ',E10.3) s2=s2+aa(ii) end do idum=m4*2+1 s=(aa(1)+aa(idum)+4.*s4+2.*s2)*del/6. C WRITE(6,2000) S,M4,DEL C2000 FORMAT(' S,M4,DEL = ',F10.5,I5,F10.5) C WRITE(6,3000) AA(1),AA(IDUM),S4,S2 C3000 FORMAT(' AA(1),AA(IDUM),S4,S2 = ',4E10.3) return end CBack up subroutine simb(aa,bb,m4,range) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:15:05:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SIMB * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simpson integration - indefinite - routine B * C * * C * AA .... Input array * C * BB .... Indefinite integral array * C * M4 .... Numberof "double" increments * C * RANGE . Integration range * C * * C ****************************************************************************** dimension aa(1),bb(1) C WRITE(6,1000) C1000 FORMAT(' B'$) m2=m4-1 del=range/float(m4) ! Width of "double" increment f1=del*5./24. f2=del*8./24. f3=-del/24. g1=del/6. g2=del*4./6. g3=del/6. bb(1)=0. do i=1,m4 i2=i*2 i1=i2-1 i3=i2+1 bb(i2)=bb(i1)+aa(i1)*f1+aa(i2)*f2+aa(i3)*f3 bb(i3)=bb(i1)+aa(i1)*g1+aa(i2)*g2+aa(i3)*g3 end do return end CBack up subroutine solvmx(a,b,m,n,sing,det,dtnorm) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MATHS REF:JRH:14:01:1986 * C * * C * REVISION : Removal of spurious characters in * C * header JRH:18:12:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SOLVMX * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Solves the matrix equation AX=B writing the result in B. * C * A is destroyed, being left in the Gauss-Doolittle form. * C * A has M rows and M cols. (M*M). * C * B has M rows and N cols. (M*N). * C * A is M*M, B is M*N. * C * SING is assigned .TRUE. if A is ill-conditioned, * C * otherwise .FALSE.. * C * DET is determinant of A. * C * DTNORM is the normalised determinant of A. * C * Calls MXGAUS. * C * * C ****************************************************************************** C NOTE : C ****** C ARRAYS IND AND D SHOULD HAVE DIMENSION AT LEAST M : C dimension a(m,m),b(m,n),ind(140) double precision d(140),dspace logical sing C CALCULATING FACTOR FOR NORMALISING DETERMINANT OF A do 13 i=1,m dspace=0.d0 do 14 j=1,m dspace=dspace+dble(a(i,j))**2 14 continue d(i)=dspace 13 continue dspace=d(1) do 15 i=2,m dspace=dspace*d(i) 15 continue d(1)=dsqrt(dspace) C L,U TRANSFORMATION OF A call mxgaus(a,ind,m,sing,det) if (sing) goto 80 C NORMALISED DETERMINANT dspace=dble(det) dtnorm=sngl(dspace/d(1)) C PERMUTATING THE ROWS OF B mm=m-1 do 1 i=1,mm ii=ind(i) do 9 j=1,n x=b(i,j) b(i,j)=b(ii,j) b(ii,j)=x 9 continue 1 continue C CALCULATING Y AND INSERTING IT IN B. (I.E.LY=B) do 10 k=1,n do 4 i=1,m dspace=0.d0 if (i.eq.1) goto 3 ii=i-1 do 2 j=1,ii dspace=dspace+dble(a(i,j))*d(j) 2 continue 3 d(i)=dble(b(i,k))-dspace 4 continue do 11 i=1,m b(i,k)=sngl(d(i)) 11 continue 10 continue C CALCULATING X AND INSERTING IT IN B. (I.E. UX=Y) do 12 k=1,n do 7 i=1,m ii=m+1-i dspace=0.d0 if (ii.eq.m) goto 6 jj=ii+1 do 5 j=jj,m dspace=dspace+dble(a(ii,j))*d(j) 5 continue 6 d(ii)=(dble(b(ii,k))-dspace)/dble(a(ii,ii)) 7 continue do 8 i=1,m b(i,k)=sngl(d(i)) 8 continue 12 continue 80 return end CBack up subroutine srect(x,y,shade) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:07:1989 * C * * C * REVISION : Correction to declaration of PAT1 etc.JRH:16:08:1989 * C * Temporary mod. to cope with Sun 4 bug JRH:14:05:1990 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SRECT * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Shades a rectangle. * C * * C * (x(1),y(1)) ..... coordinates of bottom LH corner * C * (x(2),y(2)) ..... coordinates of top RH corner * C * shade ........... shade (0 = white, 1 = black) * C * (NOTE : the reverse of Postcript) * C * * C * NOTE : SRECT should be called with SHADE = 0 imediately * C * after PLOT(*,*,-3), in order to initialise system. * C * * C * NOTE : The last statement in this routine (NDATA=NDATA+1) * C * is not executed using the f68881 optimiser. Hence from * C * now on, I will not use f68881 optimiser. * C * JRH 16/8/89 * C * * C ****************************************************************************** dimension x(2),y(2) character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number logical lrot common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units $ xoff,yoff, ! Plotter offsets $ pfac, ! Plotter scale factor $ cw,ch, ! Character width and height $ lrot ! Rotation logical common/device/idevice ! (JRA common) common/scale/iscale ! (JRA common) common/plotpos/ifile,ipath,iorient,ihlast,iplast ! (JRA common) common/plotcgi/ix(2),iy(2),ixoff,iyoff ! (JRA common) dimension ipx(4),ipy(4),xdum(2),ydum(2) dimension ipxold(2),ipyold(2) save ipxold,ipyold dimension irxoff(2),iryoff(2),ixfig(2),iyfig(2) integer pat1(16), pat2(16), pat3(16), pat4(16), ! &16/8/89 $ pat5(16), pat6(16), pat7(16), pat8(16), $ pat9(16),pat10(16),pat11(16),pat12(16), $ pat13(16),pat14(16),pat15(16),pat16(16), $ pat17(16) character*29 formt ! @14/5/90 data pat1/0,0,0,0, $ 0,0,0,0, $ 0,0,0,0, $ 0,0,0,0/ data pat2/0,0,0,0, $ 0,0,1,0, $ 0,0,0,0, $ 0,0,0,0/ data pat3/0,0,0,0, $ 0,0,1,0, $ 0,1,0,0, $ 0,0,0,0/ data pat4/0,0,0,0, $ 0,0,1,0, $ 0,1,1,0, $ 0,0,0,0/ data pat5/0,0,0,0, $ 0,1,1,0, $ 0,1,1,0, $ 0,0,0,0/ data pat6/0,0,0,1, $ 0,1,1,0, $ 0,1,1,0, $ 0,0,0,0/ data pat7/0,0,0,1, $ 0,1,1,0, $ 0,1,1,0, $ 1,0,0,0/ data pat8/0,0,1,1, $ 0,1,1,0, $ 0,1,1,0, $ 1,0,0,0/ data pat9/0,0,1,1, $ 0,1,1,0, $ 0,1,1,0, $ 1,1,0,0/ data pat10/0,0,1,1, $ 0,1,1,0, $ 1,1,1,0, $ 1,1,0,0/ data pat11/0,0,1,1, $ 0,1,1,1, $ 1,1,1,0, $ 1,1,0,0/ data pat12/0,1,1,1, $ 0,1,1,1, $ 1,1,1,0, $ 1,1,0,0/ data pat13/0,1,1,1, $ 0,1,1,1, $ 1,1,1,0, $ 1,1,1,0/ data pat14/0,1,1,1, $ 1,1,1,1, $ 1,1,1,0, $ 1,1,1,0/ data pat15/0,1,1,1, $ 1,1,1,1, $ 1,1,1,1, $ 1,1,1,0/ data pat16/1,1,1,1, $ 1,1,1,1, $ 1,1,1,1, $ 1,1,1,0/ data pat17/1,1,1,1, $ 1,1,1,1, $ 1,1,1,1, $ 1,1,1,1/ if(ndata.eq.0) then ! Initialisation if(idevice.eq.1) then ! Postcript write(ifile,1) ! Write procedure "o" ("offset" rectangle) 1 format(' /o '/ $ ' {/sh exch 100 div def '/ $ ' /oy2 exch def '/ $ ' /ox2 exch def '/ $ ' /oy1 exch def '/ $ ' /ox1 exch def '/ $ ' /x1 x1 ox1 add def '/ $ ' /y1 y1 oy1 add def '/ $ ' /x2 x2 ox2 add def '/ $ ' /y2 y2 oy2 add def '/ $ ' newpath '/ $ ' x1 y1 moveto '/ $ ' x1 y2 lineto '/ $ ' x2 y2 lineto '/ $ ' x2 y1 lineto '/ $ ' closepath sh setgray fill '/ $ ' 0 setgray} def ') write(ifile,2) ! Set x1, y1, x2, y2 to zero 2 format(' /x1 0 def '/ $ ' /y1 0 def '/ $ ' /x2 0 def '/ $ ' /y2 0 def ') do i=1,2 ipxold(i)=0 ipyold(i)=0 end do else ! SunCGI call cfpattable(1,4,4,pat1) call cfpattable(2,4,4,pat2) call cfpattable(3,4,4,pat3) call cfpattable(4,4,4,pat4) call cfpattable(5,4,4,pat5) call cfpattable(6,4,4,pat6) call cfpattable(7,4,4,pat7) call cfpattable(8,4,4,pat8) call cfpattable(9,4,4,pat9) call cfpattable(10,4,4,pat10) call cfpattable(11,4,4,pat11) call cfpattable(12,4,4,pat12) call cfpattable(13,4,4,pat13) call cfpattable(14,4,4,pat14) call cfpattable(15,4,4,pat15) call cfpattable(16,4,4,pat16) call cfpattable(17,4,4,pat17) endif endif do i=1,2 if(lrot) then ! Rotation by 90 deg. required xdum(i)=-y(i) ydum(i)=x(i) else xdum(i)=x(i) ydum(i)=y(i) endif xdum(i)=(xdum(i)-xmin)*pfac+xoff ydum(i)=(ydum(i)-ymin)*pfac+yoff end do do i=1,2 if(xdum(i).lt.xlc) xdum(i)=xlc ! Clip onto plot if(xdum(i).gt.xrc) xdum(i)=xrc ! Clip onto plot if(ydum(i).lt.ybc) ydum(i)=ybc ! Clip onto plot if(ydum(i).gt.ytc) ydum(i)=ytc ! Clip onto plot end do if(xdum(1).ne.xdum(2).and.ydum(1).ne.ydum(2)) then if(idevice.eq.1) then ! Postcript do i=1,2 ipx(i)=xdum(i)*float(iscale) ipy(i)=ydum(i)*float(iscale) end do if(ipath.eq.1) then write(ifile,3) 3 format('stroke') ipath=0 endif grey=aint((1.-shade)*17.)/16. ! 17 shades if(grey.lt.0.) grey=0. if(grey.gt.1.) grey=1. igrey=nint(grey*100.) do i=1,2 irxoff(i)=ipx(i)-ipxold(i) iryoff(i)=ipy(i)-ipyold(i) if(irxoff(i).eq.0) then ixfig(i)=1 else if(irxoff(i).gt.0) then ixfig(i)=int(alog10(float(irxoff(i))))+1 else ixfig(i)=int(alog10(float(-irxoff(i))))+2 !To allow for minus sign endif if(iryoff(i).eq.0) then iyfig(i)=1 else if(iryoff(i).gt.0) then iyfig(i)=int(alog10(float(iryoff(i))))+1 else iyfig(i)=int(alog10(float(-iryoff(i))))+2 !To allow for minus sign endif end do if(igrey.eq.0) then igfig=1 else ! Note that IGREY must be positive igfig=int(alog10(float(igrey)))+1 endif write(formt,5) ixfig(1),iyfig(1),ixfig(2),iyfig(2),igfig ! @14/5/90 5 format('(i',i1,',x,i',i1,',x,i',i1,',x,i',i1,',x,i',i1, ! @14/4/90 $ ','' o'')') ! @14/5/90 C write(ifile,4) (irxoff(i),iryoff(i),i=1,2),igrey ! &14/5/90 write(ifile,formt) (irxoff(i),iryoff(i),i=1,2),igrey ! @14/5/90 C 4 format(iC C,x,i ,x, ! &14/5/90 C $ i ,x,i ,x, ! &14/5/90 C $ i ,' o') ! &14/5/90 do i=1,2 ipxold(i)=ipx(i) ipyold(i)=ipy(i) end do else ! SunCGI ind=aint(shade*17.+1.) if(ind.lt.1) ind=1 if(ind.gt.17) ind=17 call cfhatchix(ind) ipx(1)=xdum(1)*float(iscale)+float(ixoff) ipx(2)=ipx(1) ipx(3)=xdum(2)*float(iscale)+float(ixoff) ipx(4)=ipx(3) ipy(1)=ydum(1)*float(iscale)+float(iyoff) ipy(2)=ydum(2)*float(iscale)+float(iyoff) ipy(3)=ipy(2) ipy(4)=ipy(1) call cfpolygon(ipx,ipy,4) endif endif ndata=ndata+1 return end CBack up subroutine svbksb(u,w,v,m,n,mp,np,b,x,tmp) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:08:01:1992 * C * * C * REVISION : ------------- JRH:--:--:1992 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: SVBKSB * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Singular value decomposition solution * C * (from Numerical Recipes) * C * * C * U ..... Input M by N matrix * C * W ..... Input N element weight vector * C * V ..... Input N by N matrix ( NOT the transpose of "V") * C * M ..... Number of rows of U (M.ge.N) * C * N ..... Number of columns of U (M.ge.N) * C * MP .... Physical number of rows of U * C * NP .... Physical number of columns of U * C * B ..... Input M element vector (right hand side) * C * X ..... Output N element solution vector * C * TMP ... Workspace N element vector * C * * C ****************************************************************************** real*4 u(mp,np),w(np),v(np,np),b(mp),x(np),tmp(*) integer*4 m,n,mp,np real*4 s integer*4 i,j,jj do 12 j=1,n s=0. if(w(j).ne.0.)then do 11 i=1,m s=s+u(i,j)*b(i) 11 continue s=s/w(j) endif tmp(j)=s 12 continue do 14 j=1,n s=0. do 13 jj=1,n s=s+v(j,jj)*tmp(jj) 13 continue x(j)=s 14 continue return end CBack up subroutine svdcmp(a,m,n,mp,np,u,w,v,rv1,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:08:01:1992 * C * * C * REVISION : ------------- JRH:--:--:1992 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: SVDCMP * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Singular value decomposition solution * C * (from Numerical Recipes) * C * * C * A ..... Input M by N matrix * C * M ..... Number of rows of A (M.ge.N) * C * N ..... Number of columns of A (M.ge.N) * C * MP .... Physical number of rows of A * C * NP .... Physical number of columns of A * C * U ..... Output M by N matrix * C * W ..... Output N element weight vector * C * V ..... Output N by N matrix (NOT the transpose of "V") * C * RV1 ... Workspace N element vector * C * IFAIL . 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*4 a(mp,np),u(mp,np),w(np),v(np,np),rv1(*) integer*4 m,n,mp,np,ifail real*4 f,g,h,scale,anorm,s,c,x,y,z integer*4 i,j,k,l,its,nm if(m.lt.n) then ifail=1 return endif g=0.0 scale=0.0 anorm=0.0 do i=1,m ! Copy A to U do j=1,n u(i,j)=a(i,j) end do end do do 25 i=1,n l=i+1 rv1(i)=scale*g g=0.0 s=0.0 scale=0.0 if (i.le.m) then do 11 k=i,m scale=scale+abs(u(k,i)) 11 continue if (scale.ne.0.0) then do 12 k=i,m u(k,i)=u(k,i)/scale s=s+u(k,i)*u(k,i) 12 continue f=u(i,i) g=-sign(sqrt(s),f) h=f*g-s u(i,i)=f-g if (i.ne.n) then do 15 j=l,n s=0.0 do 13 k=i,m s=s+u(k,i)*u(k,j) 13 continue f=s/h do 14 k=i,m u(k,j)=u(k,j)+f*u(k,i) 14 continue 15 continue endif do 16 k= i,m u(k,i)=scale*u(k,i) 16 continue endif endif w(i)=scale *g g=0.0 s=0.0 scale=0.0 if ((i.le.m).and.(i.ne.n)) then do 17 k=l,n scale=scale+abs(u(i,k)) 17 continue if (scale.ne.0.0) then do 18 k=l,n u(i,k)=u(i,k)/scale s=s+u(i,k)*u(i,k) 18 continue f=u(i,l) g=-sign(sqrt(s),f) h=f*g-s u(i,l)=f-g do 19 k=l,n rv1(k)=u(i,k)/h 19 continue if (i.ne.m) then do 23 j=l,m s=0.0 do 21 k=l,n s=s+u(j,k)*u(i,k) 21 continue do 22 k=l,n u(j,k)=u(j,k)+s*rv1(k) 22 continue 23 continue endif do 24 k=l,n u(i,k)=scale*u(i,k) 24 continue endif endif anorm=max(anorm,(abs(w(i))+abs(rv1(i)))) 25 continue do 32 i=n,1,-1 if (i.lt.n) then if (g.ne.0.0) then do 26 j=l,n v(j,i)=(u(i,j)/u(i,l))/g 26 continue do 29 j=l,n s=0.0 do 27 k=l,n s=s+u(i,k)*v(k,j) 27 continue do 28 k=l,n v(k,j)=v(k,j)+s*v(k,i) 28 continue 29 continue endif do 31 j=l,n v(i,j)=0.0 v(j,i)=0.0 31 continue endif v(i,i)=1.0 g=rv1(i) l=i 32 continue do 39 i=n,1,-1 l=i+1 g=w(i) if (i.lt.n) then do 33 j=l,n u(i,j)=0.0 33 continue endif if (g.ne.0.0) then g=1.0/g if (i.ne.n) then do 36 j=l,n s=0.0 do 34 k=l,m s=s+u(k,i)*u(k,j) 34 continue f=(s/u(i,i))*g do 35 k=i,m u(k,j)=u(k,j)+f*u(k,i) 35 continue 36 continue endif do 37 j=i,m u(j,i)=u(j,i)*g 37 continue else do 38 j= i,m u(j,i)=0.0 38 continue endif u(i,i)=u(i,i)+1.0 39 continue do 49 k=n,1,-1 do 48 its=1,30 do 41 l=k,1,-1 nm=l-1 if ((abs(rv1(l))+anorm).eq.anorm) go to 2 if ((abs(w(nm))+anorm).eq.anorm) go to 1 41 continue 1 c=0.0 s=1.0 do 43 i=l,k f=s*rv1(i) if ((abs(f)+anorm).ne.anorm) then g=w(i) h=sqrt(f*f+g*g) w(i)=h h=1.0/h c= (g*h) s=-(f*h) do 42 j=1,m y=u(j,nm) z=u(j,i) u(j,nm)=(y*c)+(z*s) u(j,i)=-(y*s)+(z*c) 42 continue endif 43 continue 2 z=w(k) if (l.eq.k) then if (z.lt.0.0) then w(k)=-z do 44 j=1,n v(j,k)=-v(j,k) 44 continue endif go to 3 endif if (its.eq.30) then ifail=1 return endif x=w(l) nm=k-1 y=w(nm) g=rv1(nm) h=rv1(k) f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y) g=sqrt(f*f+1.0) f=((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x c=1.0 s=1.0 do 47 j=l,nm i=j+1 g=rv1(i) y=w(i) h=s*g g=c*g z=sqrt(f*f+h*h) rv1(j)=z c=f/z s=h/z f= (x*c)+(g*s) g=-(x*s)+(g*c) h=y*s y=y*c do 45 nm=1,n x=v(nm,j) z=v(nm,i) v(nm,j)= (x*c)+(z*s) v(nm,i)=-(x*s)+(z*c) 45 continue z=sqrt(f*f+h*h) w(j)=z if (z.ne.0.0) then z=1.0/z c=f*z s=h*z endif f= (c*g)+(s*y) x=-(s*g)+(c*y) do 46 nm=1,m y=u(nm,j) z=u(nm,i) u(nm,j)= (y*c)+(z*s) u(nm,i)=-(y*s)+(z*c) 46 continue 47 continue rv1(l)=0.0 rv1(k)=f w(k)=x 48 continue 3 continue 49 continue ifail=0 return end CBack up subroutine symbol(x,y,wid,a,ang,nasc) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : PLOTTING REF:JRH:31:12:1986 * C * * C * REVISION : Mods. for direct plotting JRH:03:04:1987 * C * Mods. for rotation JRH:07:04:1987 * C * Minor mods. JRH:07:04:1987 * C * Mod. to output format JRH:28:05:1987 * C * Mods. for Sun JRH:13:07:1989 * C * Mods. for Sun JRH:17:07:1989 * C * Mod. to clipping logic JRH:17:07:1989 * C * Mod. to cope with -ve NASC * C * (i.e. "symbol" plotting) JRH:13:03:1991 * C * Minor mod. to format JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: SYMBOL * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Simulates Calcomp plotting routine, directing data to * C * disc or plotter. * C * * C * Labelled COMMON PCOM must be included in main program, * C * in which LUPLT and LULOG must be set. * C * * C * X,Y ...... coordinates of bottom LH corner of text * C * WID ...... character width * C * A ........ text to be written * C * ANG ...... angle (deg.) of text anticlockwise from X-axis * C * NASC ..... no. of ASCII characters * C * * C ****************************************************************************** character*(*) a character*7 form dimension xa(2),ya(2) ! @3/4/87 logical lc(2),lplot ! @3/4/87 character*40 ptit(1) ! Plot title common/pcom/luplt, ! Plot file unit no. $ lulog, ! Log file unit no. $ ndata, ! No. instructions in plot $ ptit, ! Current plot title $ nopen ! Current pen number logical lrot ! @3/4/87 common/wcom/xmin,xmax,ymin,ymax, ! Plot bounds in input units @3/4/87 $ xlc, xrc, ybc, ytc, ! Plot bounds in plotter units @3/4/87 $ xoff,yoff, ! Plotter offsets @3/4/87 $ pfac, ! Plotter scale factor @3/4/87 $ cw,ch, ! Character width and height @3/4/87 $ lrot ! Rotation logical @3/4/87 if(luplt.eq.-1) then ! Direct plotting @3/4/87 dtr=3.14159265/180. ! @3/4/87 widdum=wid*pfac ! @7/4/87 if(lrot) then ! Rotate plot @3/4/87 xdum=-y ! @7/4/87 ydum=x ! @7/4/87 iang=90+nint(ang) ! @3/4/87 else ! @3/4/87 xdum=x ! @7/4/87 ydum=y ! @7/4/87 iang=nint(ang) ! @3/4/87 endif ! @3/4/87 xa(1)=(xdum-xmin)*pfac+xoff ! @7/4/87 ya(1)=(ydum-ymin)*pfac+yoff ! @7/4/87 if(nasc.ge.1) then ! String plotting &13/6/91 clen=float(nasc)*widdum ! Length of string on plot (mm.) @7/4/87 else ! &13/6/91 clen=widdum ! &13/6/91 endif ! &13/6/91 xa(2)=xa(1)+clen*cos(float(iang)*dtr) ! @3/4/87 ya(2)=ya(1)+clen*sin(float(iang)*dtr) ! @3/4/87 call clip(xa,ya,xlc,xrc,ybc,ytc,lc,lplot) ! @3/4/87 if(.not.lc(1).and..not.lc(2).and.lplot) then C ..... All on plot @3/4/87 &17/7/89 C call move(xa(1),ya(1)) ! @3/4/87 &13/7/89 C call charot(iang) ! @3/4/87 &13/7/89 C call chasiz(widdum,widdum*1.5) ! @7/4/87 &13/7/89 C call chahol(a,nasc) ! @3/4/87 &13/7/89 call jsymbol(xa(1),ya(1),widdum*1.0,a,float(iang),nasc) ! @17/7/89 endif ! @3/4/87 else ! @3/4/87 az=90.-ang ! Azimuth of text if(az.lt.0.) az=az+360. if(nasc.ge.1) then ! String plotting &13/6/91 write(form,1) nasc else ! &13/6/91 write(form,1) 1 ! &13/6/91 endif ! &13/6/91 1 format('(1X,A',i2,')') write(luplt,2) x,y,wid,az,nasc,nopen 2 format(' -3 ',2e12.4,e11.4,f7.1,i3,i2) ! &28/5/87 write(luplt,form) a endif ! @3/4/87 if(luplt.ne.6) ndata=ndata+1 ! Do not update if to user's terminal return end CBack up subroutine timin(nin,nout,nlog,anot,ihr,min,sec) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:20:03:1991 * C * * C * REVISION : Minor mod. to formats JRH:15:05:2000 * C * "end=" added to read JRH:14:01:2001 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: TIMIN * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Reads in a time, in various formats * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Annotation (40 chars.) * C * IHR ..... Hour * C * MIN ..... Minute * C * SEC ..... Second * C * * C * NOTE : Main constraint is that input order is hour, minute, second * C * * C ****************************************************************************** real*4 sec integer*4 nin,nout,nlog,ihr,min character*40 anot integer*4 idum,icount,isec character*80 buff 4 write(nout,1) anot write(nlog,1) anot 1 format(1x,a40) read(nin,2,err=4) buff(1:80) 2 format(a80) write(nlog,3) buff(1:80) 3 format(1x,a80) do i=1,80 ! First remove all non-numeric characters except '.' idum=ichar(buff(i:i)) if((idum.lt.48.or.idum.gt.57).and. $ buff(i:i).ne.'.') buff(i:i)=' ' end do icount=0 ! First look for 4-or 6-digit time do i=1,80 idum=ichar(buff(i:i)) if(idum.ge.48.and.idum.le.57) then ! A digit icount=icount+1 else icount=0 endif if(icount.eq.4.and. ! 4 digits $ (buff(i+1:i+1).eq.' '.or. ! Followed by space $ buff(i+1:i+1).eq.'.')) then ! or '.' read(buff(i-3:i),5,err=4) ihr,min 5 format(2i2) sec=0. go to 7 endif if(icount.eq.6.and. ! 6 digits $ (buff(i+1:i+1).eq.' '.or. ! Followed by space $ buff(i+1:i+1).eq.'.')) then ! or '.' read(buff(i-5:i),6,err=4) ihr,min,isec 6 format(3i2) sec=float(isec) go to 7 endif end do read(buff(1:80),*,err=8,end=8) ihr,min,sec C ..... Read with delimiters - first try HMS go to 7 8 read(buff(1:80),*,err=4) ihr,min ! Then try HM sec=0. 7 if(ihr.lt.0.or.ihr.gt.24) go to 4 if(min.lt.0.or.min.gt.59) go to 4 if(sec.lt.0..or.sec.gt.60.) go to 4 return end CBack up subroutine utd(iye,mon,idy,ihr,min,sec,utim,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:23:05:1991 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: UTD * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts Unix Time to daytime * C * * C * (Unix Time starts at 0000 on 1 Jan. 1970) * C * * C * IYE ........ Year * C * MON ........ Month * C * IDY ........ Day * C * IHR ........ Hour * C * MIN ........ Minute * C * SEC ........ Second * C * UTIM ....... Unix time (seconds) * C * IFAIL ...... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** real*8 utim real*4 sec integer*4 iye,mon,idy,ihr,min,ifail real*8 jd0,julian logical first save jd0,first data first/.true./ if(first) then ! Compute zero of Unix Time in Julian days call julday(1970,1,1,0,0,0.,jd0,ifail) if(ifail.ne.0) return ! Error first=.false. endif julian=utim/86400.d0+jd0 call caldat(iye,mon,idy,ihr,min,sec,julian,ifail) return end CBack up subroutine writearray(nout,a,athresh,imin,imax, $ form1,form2,nchar1,nchar2,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:11:1988 * C * * C * REVISION : Mod. to parameter JRH:07:07:1989 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: WRITEARRAY * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Writes array A from indices IMIN to IMAX in two possible * C * formats, depending on whether the value is smaller or * C * larger than a threshold, ATHRESH. 10 values are output * C * per record. * C * * C * NOUT ..... Output device * C * A ........ Array (NOTE that lower bound is 0) * C * ATHRESH .. Threshold value * C * IMIN ..... Minimum index of array, A * C * IMAX ..... Maximum index of array, A * C * FORM1 .... Format if (A.LT.ATHRESH) * C * FORM2 .... Format if (A.GE.ATHRESH) * C * NCHAR1 ... Number of characters in FORM1 * C * NCHAR2 ... Number of characters in FORM2 * C * IFAIL .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer pmax ! @7/7/89 parameter(pmax=160) dimension a(0:*) character*40 form1,form2 character*(pmax) formt data max/pmax/ nrec=(imax-imin)/10+1 do j=1,nrec i1=(j-1)*10+imin ! Index of first variable of record i2=i1+9 ! Index of last variable of record if(i2.gt.imax) i2=imax ! " " " " " formt(1:1)='(' index=2 do i=i1,i2 if(abs(a(i)).lt.athresh) then formt(index:index+nchar1-1)=form1(1:nchar1) index=index+nchar1 else formt(index:index+nchar2-1)=form2(1:nchar2) index=index+nchar2 endif if(i.ne.i2) then formt(index:index)=',' index=index+1 endif end do formt(index:index)=')' index=index+1 C WRITE(6,9999) INDEX !!! C9999 FORMAT(' INDEX = ',I3) !!! write(nout,formt(1:index)) (a(i),i=i1,i2) if(index.le.max) then ifail=0 else ifail=1 endif end do return end CBack up subroutine writearray2(nout,a,imin,imax,nwid,ifail) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:18:11:1991 * C * * C * REVISION : Minor mod. to header JRH:06:01:1992 * C * Addition of external JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FVS * C * ROUTINE NAME: WRITEARRAY2 * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Writes array A from indices IMIN to IMAX in "F" format, * C * adjusting the format according the size of each value. * C * 10 values are output per record. * C * * C * NOUT ..... Output device * C * A ........ Array (NOTE that lower bound is 1) * C * IMIN ..... Minimum index of array, A * C * IMAX ..... Maximum index of array, A * C * NWID ..... No. of characters to be occupied by each value * C * (including one seperator space and one sign * C * space) * C * IFAIL .... 0 for successful execution, otherwise 1 * C * * C ****************************************************************************** integer*4 pmax parameter(pmax=160) real*4 a(*) integer*4 nout,imin,imax,nwid,ifail integer*4 nrec,j,i1,i2,index,i,idp integer*4 int2,nleft external int2 character*(pmax) formt nrec=(imax-imin)/10+1 do j=1,nrec i1=(j-1)*10+imin ! Index of first variable of record i2=i1+9 ! Index of last variable of record if(i2.gt.imax) i2=imax ! " " " " " formt(1:1)='(' index=2 do i=i1,i2 if(a(i).ne.0.) then nleft=int2(alog10(abs(a(i)))+1) ! No. of figs. to L of dec. pt. else ! r = 0 nleft=1 endif if(nleft.lt.0) nleft=0 idp=nwid-nleft-3 ! No. of decimal places write(formt(index:index+6),1) nwid-1,idp 1 format('f',i2,'.',i2,'x') index=index+7 if(i.ne.i2) then formt(index:index)=',' index=index+1 endif end do formt(index:index)=')' index=index+1 C WRITE(6,9999) INDEX !!! C9999 FORMAT(' INDEX = ',I3) !!! write(nout,formt(1:index)) (a(i),i=i1,i2) if(index.le.pmax) then ifail=0 else ifail=1 endif end do return end CBack up subroutine xy2ra(x,y,r,a,lr,la) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:02:07:1985 * C * * C * REVISION : ------------- JRH:--:--:1985 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: XY2RA * C * TYPE : SUBROUTINE * C * * C * FUNCTION : Converts (X,Y) to (R,A(azimuth)). C * * C * LR = .TRUE. ..... Returns R * C * LA = .TRUE. ..... Returns A * C * * C ****************************************************************************** logical lr,la if(lr) then r=sqrt(x*x+y*y) else r=0. endif if(la) then if(x.ne.0..or.y.ne.0) then a=atan2(x,y) if(a.lt.0.) a=a+6.2831853 else a=0. endif endif return end CBack up function ydif(x,xa,ya,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:31:07:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YDIF * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns first derivative of function Y(X) defined * C * piecewise by arrays XA and YA, each containing N values. * C * * C * X ..... input X-value * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values * C * N ..... number of values in each array * C * * C ****************************************************************************** dimension xa(*),ya(*) if(x.lt.xa(1)) then ! X before start of data - use zero ydif=0. return else if(x.ge.xa(n)) then ! X after end of data - use zero ydif=0. return else ! Linearly interpolate do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I ydif=(ya(i)-ya(i-1))/(xa(i)-xa(i-1)) return endif end do endif endif end CBack up function ydif2d(x,iset,xa,ya,n,nmax) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:29:09:1986 * C * * C * REVISION : --------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YDIF2D * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns first derivative of function Y(X) defined * C * piecewise by arrays XA and YA, each containing N values. * C * * C * X ..... input X-value * C * ISET .. 2nd index of array YA * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values * C * N ..... number of values in each array * C * NMAX .. max. first index of array YA * C * * C * Special version for 2-D input array, YA * C * * C ****************************************************************************** dimension xa(*),ya(nmax,*) if(x.lt.xa(1)) then ! X before start of data - use zero ydif2d=0. return else if(x.ge.xa(n)) then ! X after end of data - use zero ydif2d=0. return else ! Linearly interpolate do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I ydif2d=(ya(i,iset)-ya(i-1,iset))/(xa(i)-xa(i-1)) return endif end do endif endif end CBack up logical function yesno(nin,nout,nlog,anot) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : UTILITY REF:JRH:27:08:1986 * C * * C * REVISION : Minor mod. to output JRH:19:02:1987 * C * Minor mod. to formats JRH:15:05:2000 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YESNO * C * TYPE : LOGICAL FUNCTION * C * * C * FUNCTION : Returns .TRUE. or .FALSE. depending on operator reply * C * (Y or N, respectively). * C * * C * NIN ..... Operator input device * C * NOUT .... Operator output device * C * NLOG .... Log device * C * ANOT .... Anotation (40 chars.) * C * * C ****************************************************************************** character*40 anot character*1 adum 4 write(nout,1) anot,' ' ! &19/2/87 write(nlog,1) anot,' ' ! &19/2/87 1 format(/1x,a40,a1) ! &19/2/87 read(nin,2) adum 2 format(a1) write(nlog,3) adum 3 format(1x,a1) if(adum.ne.'Y'.and.adum.ne.'N'.and. $ adum.ne.'y'.and.adum.ne.'n') go to 4 if(adum.eq.'Y'.or.adum.eq.'y') then yesno=.true. else yesno=.false. endif return end CBack up function yint(x,xa,ya,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:30:07:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YINT * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns value of function Y(X) defined piecewise by * C * arrays XA and YA, each containing N values, using linear * C * interpolation where possible. * C * * C * X ..... input X-value * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values * C * N ..... number of values in each array * C * * C ****************************************************************************** dimension xa(*),ya(*) if(x.lt.xa(1)) then ! X before start of data - use first value yint=ya(1) return else if(x.ge.xa(n)) then ! X after end of data - use last value yint=ya(n) return else ! Linearly interpolate do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I w1=(xa(i)-x)/(xa(i)-xa(i-1)) yint=w1*ya(i-1)+(1.-w1)*ya(i) return endif end do endif endif end CBack up function yint2d(x,iset,xa,ya,n,nmax) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:27:08:1986 * C * * C * REVISION : NMAX added JRH:29:09:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YINT2D * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns value of function Y(X) defined piecewise by * C * arrays XA and YA, each containing N values, using linear * C * interpolation where possible. * C * * C * X ..... input X-value * C * ISET .. 2nd index of array YA * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values (first dimension = N) * C * N ..... number of values in each array * C * NMAX .. max. first index of array YA * C * * C * Special version for 2-D input array, YA * C * * C ****************************************************************************** dimension xa(*),ya(nmax,*) ! &29/9/86 if(x.lt.xa(1)) then ! X before start of data - use first value yint2d=ya(1,iset) return else if(x.ge.xa(n)) then ! X after end of data - use last value yint2d=ya(n,iset) return else ! Linearly interpolate do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I w1=(xa(i)-x)/(xa(i)-xa(i-1)) yint2d=w1*ya(i-1,iset)+(1.-w1)*ya(i,iset) return endif end do endif endif end CBack up function yrect(x,xa,ya,n) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:22:09:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YRECT * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns value of function Y(X) defined as rectangular * C * elements by arrays XA and YA, XA containing N values, * C * YA containing N-1 values. * C * * C * X ..... input X-value * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values * C * N ..... number of values in each array * C * * C ****************************************************************************** dimension xa(*),ya(*) if(x.lt.xa(1)) then ! X before start of data - use first value yrect=ya(1) return else if(x.ge.xa(n)) then ! X after end of data - use last value yrect=ya(n-1) return else ! Select rectangular element do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I yrect=ya(i-1) return endif end do endif endif end CBack up function yrect2d(x,iset,xa,ya,n,nmax) C ****************************************************************************** C * * C * FORTRAN SOURCE CODE * C * * C * PROGRAM SET : MODELLING REF:JRH:29:09:1986 * C * * C * REVISION : ------------- JRH:--:--:1986 * C * * C * SOURCE : FORLIB.FOR * C * ROUTINE NAME: YRECT2D * C * TYPE : FUNCTION * C * * C * FUNCTION : Returns value of function Y(X) defined as rectangular * C * elements by arrays XA and YA, XA containing N values, * C * YA containing N-1 values. * C * * C * X ..... input X-value * C * ISET .. 2nd index of array YA * C * XA .... array of X-values (these must monotonically * C * increase with index) * C * YA .... array of Y-values * C * N ..... number of values in each array * C * NMAX .. max. first index of array YA * C * * C * Special version for 2-D input array, YA * C * * C ****************************************************************************** dimension xa(*),ya(nmax,*) if(x.lt.xa(1)) then ! X before start of data - use first value yrect2d=ya(1,iset) return else if(x.ge.xa(n)) then ! X after end of data - use last value yrect2d=ya(n-1,iset) return else ! Select rectangular element do i=2,n if(x.lt.xa(i)) then ! X must be in interval I-1 to I yrect2d=ya(i-1,iset) return endif end do endif endif end C# C