C C FORTRAN LIBRARY SOURCE CODE 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(i,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 
C C