c
c     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c     *                                                               *
c     *                  copyright (c) 1998 by UCAR                   *
c     *                                                               *
c     *       University Corporation for Atmospheric Research         *
c     *                                                               *
c     *                      all rights reserved                      *
c     *                                                               *
c     *                      SPHEREPACK version 3.2                   *
c     *                                                               *
c     *       A Package of Fortran77 Subroutines and Programs         *
c     *                                                               *
c     *              for Modeling Geophysical Processes               *
c     *                                                               *
c     *                             by                                *
c     *                                                               *
c     *                  John Adams and Paul Swarztrauber             *
c     *                                                               *
c     *                             of                                *
c     *                                                               *
c     *         the National Center for Atmospheric Research          *
c     *                                                               *
c     *                Boulder, Colorado  (80307)  U.S.A.             *
c     *                                                               *
c     *                   which is sponsored by                       *
c     *                                                               *
c     *              the National Science Foundation                  *
c     *                                                               *
c     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c
c
c ... file testrvsph.f
c
c     this file contains a test program for trvsph.f
c
c ... required files
c
c     trvsph.f, sphcom.f, hrfft.f, gaqd.f, vhaec.f, vhsec.f, vhagc.f, vhsgc.f
c
c ... description (see documentation in file trvsph.f)
c
c     Subroutine trvsph is used to demonstrate vector data transfer between a coarse
c     ten degree equally spaced grid and a higher resolution T42 Global Spectral
c     Gaussian grid.
c
c     Ten Degree Grid (Mathematical Spherical Coordinates)
c
c     The equally spaced vector data, given in mathematical spherical
c     coordinates,  is stored in 19 X 36 colatitude-longitude arrays (ue,ve).  The
c     colatitudinal values are stored north to south with increasing colatitude
c     subscript values.  ue is the east longitudinal component and ve is the
c     colatitudinal component of the vector.
c
c     Gaussian Grid (Geophysical Spherical Coordinates)
c
c     The T42 Gaussian grid vector data is in geophysical spherical coordinates.
c     It is stored in 128 X 64 longitude-latitude arrays (ug,vg).  Values are
c     stored south to north with increasing latitude subscript value.  ug
c     is the longitudinal component and vg is the latitudinal componenet of the
c     vector data.
c
c     For testing purposes we use an analytic vector field (u,v).  Let t and p
c     be colatitude and longitude and x=sin(t)cos(p), y=sint(t)*sin(p), z=cos(t)
c     be the cartesian coordinates restricted to the sphere in mathematical
c     coordinates. We derive the vector field (u,v) from the stream function
c     S and velocity function P given by
c
c               y    -z           x    z
c          S = e  + e  ,     P = e  + e
c
c     The corresponding vector field has the form
c
c                x          -z          y
c          u = -e sin(p) + e  sin(t) + e cos(t)sin(p)
c
c                y          z          x
c          v = -e cos(p) - e sin(t) + e cos(t)cos(p)
c
c
c     in mathematical spherical coordinates.  Values in geophysical
c     coordinates can be obtained by negating v.
c
c     In the code below, (ue,ve) is set equal to (u,v) and trvsph is used to
c     transfer (ue,ve) to (ug,vg).  (ug,vg) is then compared with (u,v) in
c     geophysical coordinates on the T42 Gaussian grid.  Finally, trvsph is
c     used to transfer (ug,vg) back to (ue,vg) and this is compared with (u,v).
c     Output from executing the test program on separate platforms with 32 bit
c     and 64 bit floating point arithmetic is listed below.  The minimum required
c     saved and unsaved work space lengths were predetermined by an earlier call
c     trvsph with nlone=36,nlate=19,nlong=128,nlatg=64,lsave=0,lwork=0 and printout
c     of lsvmin and lwkmin.
c
c
c **********************************************************************
c
c     OUTPUT FROM EXECUTING CODE IN THIS FILE
C
c **********************************************************************
c
c      EQUALLY SPACED TO GAUSSIAN GRID TRANSFER
c      trvsph input arguments:
c      intl =  0
c      igride(1) = -1   igride(2) =  1
c      nlone =  36   nlate =  19
c      ive =  1
c      igridg(1) =  2   igridg(2) =  0
c      nlong = 128   nlatg =  64
c      ivg =  0
c      lsave =   21814   lwork =   75173
c
c      trvsph output:
c      ier =        0  lsvmin =   21792  lwkmin =   75173
C ***  32 BIT FLOATING POINT ARITHMETIC
c      least squares error in u =  0.307E-06
c      least squares error in v =  0.272E-06
C ***  64 BIT FLOATING POINT ARITHMETIC
c      least squares error in u =  0.841E-12
c      least squares error in v =  0.603E-12
c
c      GAUSSIAN TO EQUALLY SPACED GRID TRANSFER
c      trvsph input arguments:
c      intl =  0
c      igridg(1) =  2   igridg(2) =  0
c      nlong = 128   nlatg =  64
c      ivg =  0
c      igride(1) = -1   igride(2) =  1
c      nlone =  36   nlate =  19
c      ive =  1
c      lsave =   21814   lwork =   75173
c
c      trvsph output:
c      ier =        0  lsvmin =   21814  lwkmin =   75173
C ***  32 BIT FLOATING POINT ARITHMETIC
c      least squares error in u =  0.374E-06
c      least squares error in v =  0.364E-06
C ***  64 BIT FLOATING POINT ARITHMETIC
c      least squares error in u =  0.170E-12
c      least squares error in v =  0.161E-12
c
C **********************************************************************
c
c     END OF OUTPUT ... CODE FOLLOWS
c
c **********************************************************************
      program testrvsph
      implicit none
c
c     set grid sizes with parameter statements
c
      integer nnlatg,nnlong,nnlate,nnlone,llwork,llsave,lldwork
      parameter (nnlatg=64, nnlong=128, nnlate=19,nnlone=36)
c
c     set predetermined minimum saved and unsaved work space lengths
c
      parameter (llwork =  76000)
      parameter (llsave = 21814)
c
c     set double precision work space length
c
      parameter (lldwork = 2*nnlatg*(nnlatg+1)+1)
c
c     dimension and type data arrays and grid vectors and internal variables
c
      real ue(nnlate,nnlone), ve(nnlate,nnlone)
      real ug(nnlong,nnlatg), vg(nnlong,nnlatg)
      real work(llwork),wsave(llsave),thetag(nnlatg)
      DOUBLE PRECISION DTHETA(NNLATG),DWTS(NNLATG),DWORK(LLDWORK)
      integer igride(2),igridg(2),ive,ivg
      integer nlatg,nlong,nlate,nlone,lwork,lsave,ldwork
      real pi,dlate,dlone,dlong,t,p,cosp,sinp,cost,sint,x,y,z
      real erru2,errv2,ex,ey,ez,emz,uee,vee
      integer i,j,ib,intl,ier,lsvmin,lwkmin
c
c     set grid sizes and dimensions from parameter statements
c
      nlatg = nnlatg
      nlong = nnlong
      nlate = nnlate
      nlone = nnlone
      lwork = llwork
      lsave = llsave
      ldwork = lldwork
c
c     set equally spaced grid increments
c
      pi = 4.0*atan(1.0)
      dlate = pi/(nlate-1)
      dlone = (pi+pi)/nlone
      dlong = (pi+pi)/nlong
c
c     set vector data in (ue,ve)
c
      do  j=1,nlone
	p = (j-1)*dlone
	cosp = cos(p)
	sinp = sin(p)
	do i=1,nlate
	  t = (i-1)*dlate
	  cost = cos(t)
	  sint = sin(t)
	  x = sint*cosp
	  y = sint*sinp
	  z = cost
	  ex = exp(x)
	  ey = exp(y)
	  ez = exp(z)
	  emz = exp(-z)
	  ve(i,j) = ex*cost*cosp-ey*cosp-ez*sint
	  ue(i,j) = -ex*sinp + emz*sint + ey*cost*sinp
	end do
      end do
c
c     set initial call flag
c
      intl = 0
c
c     flag (ue,ve) grid as north to south equally spaced
c
      igride(1) = -1
c
c     flag (ue,ve) as nlate by nlone arrays
c
      igride(2) = 1
c
c     flag ve as colatitude component of vector
      ive = 1
c
c     flag (ug,vg) as south to north gaussian
c
      igridg(1) = +2
c
c     flag (ug,vg) as nlong by nlatg arrays
c
      igridg(2) = 0
c
c     flag vg as latitude component of vector
      ivg = 0
c
c     print trvsph input arguments
c
      write(*,100) intl,igride(1),igride(2),nlone,nlate,ive,
     +igridg(1),igridg(2),nlong,nlatg,ivg,lsave,lwork,ldwork
  100 format(//' EQUALLY SPACED TO GAUSSIAN GRID TRANSFER ' ,
     +/' trvsph input arguments: ' ,
     +/' intl = ',i2,
     +/' igride(1) = ',i2,2x,' igride(2) = ',i2,
     +/' nlone = ',i3,2x,' nlate = ',i3,
     +/' ive = ',i2,
     +/' igridg(1) = ',i2,2x,' igridg(2) = ',i2,
     +/' nlong = ',i3,2x,' nlatg = ',i3,
     +/' ivg = ',i2
     +/' lsave = ',i7,2x,' lwork = ',i7,2x,' ldwork = ',i5)
c
c     transfer  (ue,ve) to (ug,vg)
c
      call trvsph(intl,igride,nlone,nlate,ive,ue,ve,igridg,nlong,
     +nlatg,ivg,ug,vg,wsave,lsave,lsvmin,work,lwork,lwkmin,dwork,
     +ldwork,ier)
c
c     print output arguments
c
      write (*,200) ier, lsvmin, lwkmin
  200 format(//' trvsph output: '
     +/ ' ier = ', i8,2x, 'lsvmin = ',i7, 2x,'lwkmin = ',i7)

      if (ier .eq. 0) then
c
c     compute nlatg gaussian colatitude points and
c     set with south to north orientation in thetag
c
      call gaqd(nlatg,dtheta,dwts,dwork,ldwork,ier)
      do  i=1,nlatg
	ib = nlatg-i+1
	thetag(i) = dtheta(ib)
      end do
c
c     compute the least squares error in (ug,vg)
c     by comparing with exact geophysical vector
c
      errv2 = 0.0
      erru2 = 0.0
      do  j=1,nlong
	p = (j-1)*dlong
	cosp = cos(p)
	sinp = sin(p)
	do i=1,nlatg
	  t = thetag(i)
	  cost = cos(t)
	  sint = sin(t)
	  x = sint*cosp
	  y = sint*sinp
	  z = cost
	  ex = exp(x)
	  ey = exp(y)
	  ez = exp(z)
	  emz = exp(-z)
	  vee = -ex*cost*cosp+ey*cosp+ez*sint
	  uee = -ex*sinp + emz*sint + ey*cost*sinp
	  erru2 = erru2 + (ug(j,i)-uee)**2
	  errv2 = errv2 + (vg(j,i)-vee)**2
	end do
      end do
      erru2 = sqrt(erru2/(nlong*nlatg))
      errv2 = sqrt(errv2/(nlong*nlatg))
      write (6,300) erru2, errv2
  300 format(' least squares error in u = ', e10.3
     +      /' least squares error in v = ', e10.3)
      end if
c
c     now transfer (ug,vg) back to (ue,ve)
c
      do j=1,nlone
	do i=1,nlate
	  ue(i,j) = 0.0
	  ve(i,j) = 0.0
      end do
      end do
      write(*,101) intl,igridg(1),igridg(2),nlong,nlatg,ivg,
     +igride(1),igride(2),nlone,nlate,ive,lsave,lwork,ldwork
  101 format(//' GAUSSIAN TO EQUALLY SPACED GRID TRANSFER ' ,
     +/' trvsph input arguments: ' ,
     +/' intl = ',i2,
     +/' igridg(1) = ',i2,2x,' igridg(2) = ',i2,
     +/' nlong = ',i3,2x,' nlatg = ',i3,
     +/' ivg = ',i2,
     +/' igride(1) = ',i2,2x,' igride(2) = ',i2,
     +/' nlone = ',i3,2x,' nlate = ',i3,
     +/' ive = ',i2
     +/' lsave = ',i7,2x,' lwork = ',i7,2x,' ldwork = ',i5)
      call trvsph(intl,igridg,nlong,nlatg,ivg,ug,vg,igride,nlone,nlate,
     +ive,ue,ve,wsave,lsave,lsvmin,work,lwork,lwkmin,dwork,ldwork,ier)
c
c     print output arguments
c
      write (*,200) ier, lsvmin, lwkmin
      if (ier .eq. 0) then
c
c     compute the least squares error in (ue,ve)
c     by comparing with exact mathematical vector
c
      errv2 = 0.0
      erru2 = 0.0
      do  j=1,nlone
	p = (j-1)*dlone
	cosp = cos(p)
	sinp = sin(p)
	do i=1,nlate
	  t = (i-1)*dlate
	  cost = cos(t)
	  sint = sin(t)
	  x = sint*cosp
	  y = sint*sinp
	  z = cost
	  ex = exp(x)
	  ey = exp(y)
	  ez = exp(z)
	  emz = exp(-z)
	  vee =  ex*cost*cosp-ey*cosp-ez*sint
	  uee = -ex*sinp + emz*sint + ey*cost*sinp
	  erru2 = erru2 + (ue(i,j)-uee)**2
	  errv2 = errv2 + (ve(i,j)-vee)**2
	end do
      end do
      erru2 = sqrt(erru2/(nlone*nlate))
      errv2 = sqrt(errv2/(nlone*nlate))
      write (6,300) erru2, errv2
      end if
      end
