!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!       NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS      !
!BOP -------------------------------------------------------------------
!
! !MODULE: m_fvAnaGrid - An analysis for GSI on a FV model grid.
!
! !DESCRIPTION:
!
! !INTERFACE:


    module m_fvAnaGrid 12,35
#ifdef _GMAO_FVGSI_
      use m_dyn,only : dyn_vect
#endif
      implicit none
      private	! except

      public :: fvAnaGrid_nmlread
		! Read a namelist if there is one, for a collection of
		! GMAO gsiGuess grid configuration data.

      public :: fvAnaGrid_setup
      		! Define analysis grid attributes

      public :: fvAnaGrid_allgetlist
      public :: fvAnaGrid_getlist
      		! Define a list of input file numbers.  This is a hack.
		! It needs to be improved once we make the module
		! working as expected.

      public :: fvAnaGrid_read
      		! Read, if not already in memory, background state on a
		! fv-eta grid as the guess state; then interpolate the
		! guess state on to a distributed sigma-Gaussian grid,
		! defined in module guess_grids.  Additional diagnostic
		! variables are derived from the basic guess_grids.

      public :: fvAnaGrid_surface_read
      		! Read surface variables from a fv-surface file and from
		! a ncep-surface file.

      public :: fvAnaGrid_surface_getvar
      		! Read a single surface variable from a fv-surface file
		! or a ncep-surface file.

      public :: fvAnaGrid_write
		! (un)interpolate data in guess_grids as the up-to-date
		! analysis state onto a fv-eta grid.  Compute analysis
		! increments and write out the analysis.

      interface fvAnaGrid_nmlread; module procedure;
		nmlread_; end interface

      interface fvAnaGrid_setup; module procedure; end interface
      interface fvAnaGrid_allgetlist ; module procedure;
      		allgetlist_; end interface
      interface fvAnaGrid_getlist ; module procedure;
      		getlist_; end interface

      interface fvAnaGrid_read ; module procedure; end interface
      interface fvAnaGrid_surface_read ; module procedure;
      		surface_read_; end interface
      interface fvAnaGrid_surface_getvar ; module procedure;
      		surface_getvar_; end interface

      interface fvAnaGrid_write; module procedure; end interface

! !REVISION HISTORY:
! 	17Sep04	- Jing Guo <guo@dao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!       08Jan06  -Banglin Zhang - updated for analysis of satellite rain rate data
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname='m_fvAnaGrid'

! This module is a singleton object.

  			! File tag of FV surface variables
  character(len=*),parameter :: FV_SFC="fv-sfc"
  integer,parameter :: IFILE_FV=6
  			! File tag of NCEP surface variables
  character(len=*),parameter :: NC_SFC="nc-sfc"
  integer,parameter :: IFILE_NC=6

  			! File tag of the first guess in "dyn" format.

  character(len=*),parameter :: FV_DYN="fv-dyn"

  			! File tag of the analysis  in "dyn" format.

  character(len=*),parameter :: AN_DYN="an-dyn"

  			! "dyn" file tag of the analysis increments.

  character(len=*),parameter :: AI_DYN="ai-dyn"

#ifdef _IGNORE_GRIDVERIFY_
  logical,parameter :: GRIDVERIFY_=.false.
#else
  logical,parameter :: GRIDVERIFY_=.true.
#endif
#ifdef _GMAO_FVGSI_
#include "mytrace.H"
#endif
contains
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! NASA/GSFC, Global Modeling and Assimilation Office, 900.3, GEOS/DAS  !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: nmlread_ - read NAMELIST/gsiGuess/
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine nmlread_(lu)
#ifdef _GMAO_FVGSI_
      use m_gsiGuess,only : gsiGuessGrid_nmlread
      use m_mpout,only : mpout_log
      use m_die,only : die
#endif
      implicit none
      integer,intent(in) :: lu	! input is opened on this unit

! !REVISION HISTORY:
! 	26Jan06	- Jing Guo <guo@gmao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::nmlread_'
  integer :: ier
#ifdef _GMAO_FVGSI_
_ALLENTRY_
	! This is a thin layer to pass the control to gsiGuess_nmlread()
	! to read user defined grid options.
  call gsiGuessGrid_nmlread(lu)
_ALLEXIT_
#endif
end subroutine nmlread_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! NASA/GSFC, Global Modeling and Assimilation Office, 900.3, GEOS/DAS  !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: setup_ - configure the global grid
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine setup_(ifile,iyr,imo,idy,ihr,freq, comm)
#ifdef _GMAO_FVGSI_
      use m_gsiGuess,only : gsiGuessGrid_setup
      use m_mpout,only : mpout_log
#endif
      implicit none
      integer,intent(in) :: ifile
      integer,intent(out):: iyr,imo,idy,ihr
      integer,intent(out):: freq	! increment in hhmmss
      integer,intent(in) :: comm

! !REVISION HISTORY:
! 	07Apr05	- Jing Guo <guo@gmao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::setup_'
  character(len=len(FV_DYN)+4) :: fvdynName
  integer,parameter :: ROOT=0
  integer :: ier,myPE
!________________________________________
#ifdef _GMAO_FVGSI_
_ALLENTRY_
! read the header of the guess

  write(fvdynName,'(2a,i2.2)') trim(FV_DYN),'.',ifile
		call mpout_log(myname_,	&
			'reading from "'//trim(fvdynName)//'"')
  call gsiGuessGrid_setup(fvdynName,iyr,imo,idy,ihr,freq,comm,ROOT)
_ALLEXIT_
#else
	iyr=-1;imo=-1;idy=-1;ihr=-1;freq=-1
#endif
end subroutine setup_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! NASA/GSFC, Global Modeling and Assimilation Office, 900.3, GEOS/DAS  !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: allgetlist_ - get a list of input files
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine allgetlist_(comm)
      use guess_grids,only : nfldsig,ntguessig,ifilesig,hrdifsig
      use guess_grids,only : nfldsfc,ntguessfc,ifilesfc,hrdifsfc
#ifdef _GMAO_FVGSI_
      use m_mpout,only : mpout_log,mpout,mpout_ison
      use m_mpif90,only : MP_comm_rank,MP_type
      use m_die   ,only : MP_die
#endif
      implicit none
      integer,intent(in) :: comm

! !REVISION HISTORY:
! 	02Aug05	- Jing Guo <guo@gmao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::allgetlist_'
  integer :: itime
  integer :: ier
  integer :: myPE
  integer,parameter :: ROOT=0
#ifdef _GMAO_FVGSI_
_ALLENTRY_

  call MP_comm_rank(comm,myPE,ier)
	if(ier/=0) call MP_die(myname_,'MP_comm_rank()',ier)

  if(myPE==ROOT) call getlist_()
  
  call mpi_bcast(ntguessig,1,MP_type(ntguessig),ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(ntguessig)',ier)
  call mpi_bcast(nfldsig,1,MP_type(nfldsig),ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(nfldsig)',ier)
  call mpi_bcast(ifilesig,size(ifilesig),MP_type(ifilesig),	&
  	ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(ifilesig)',ier)
  call mpi_bcast(hrdifsig,size(hrdifsig),MP_type(hrdifsig),	&
  	ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(hrdifsig)',ier)

  call mpi_bcast(ntguessfc,1,MP_type(ntguessfc),ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(ntguessfc)',ier)
  call mpi_bcast(nfldsfc,1,MP_type(nfldsfc),ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(nfldsfc)',ier)
  call mpi_bcast(ifilesfc,size(ifilesfc),MP_type(ifilesfc),	&
  	ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(ifilesfc)',ier)
  call mpi_bcast(hrdifsfc,size(hrdifsfc),MP_type(hrdifsfc),	&
  	ROOT,comm,ier)
  	if(ier/=0) call MP_die(myname_,'MPI_bcast(hrdifsfc)',ier)

  if(mpout_ison().or.(mod(myPE,10)==0)) then
    do itime=1,nfldsig
      write(mpout,'(1x,2a,i3.2,2(i4.2,a,f7.3,a))')		&
      		myname_,': state #',itime,			&
      		ifilesig(itime),'(',hrdifsig(itime),' hr)',	&
      		ifilesfc(itime),'(',hrdifsfc(itime),' hr)'
    end do
  endif

_ALLEXIT_
#endif
end subroutine allgetlist_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! NASA/GSFC, Global Modeling and Assimilation Office, 900.3, GEOS/DAS  !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: getlist_ - get a list of input files
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine getlist_()
      use guess_grids,only : nfldsig,ntguessig,ifilesig,hrdifsig
      use guess_grids,only : nfldsfc,ntguessfc,ifilesfc,hrdifsfc
      use obsmod     ,only : iadate
      use gridmod    ,only : nhr_assimilation
#ifdef _GMAO_FVGSI_
      use m_fvGrid,only : fvGrid
      use m_fvGrid,only : fvGrid_get
      use m_fvGrid,only : clean
      use m_fvGridHeader,only : fvGridHeader_read

      use m_fvSurface,only : fvSurface
      use m_fvSurface,only : fvSurface_getheader
      use m_fvSurface,only : get, clean

      use m_ncSurface,only : ncSurface
      use m_ncSurface,only : ncSurface_getheader
      use m_ncSurface,only : get, clean

      use m_mpout ,only : mpout_log
      use m_die   ,only : perr,die
#endif
      implicit none

! !REVISION HISTORY:
! 	02Aug05	- Jing Guo <guo@gmao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!   16Aug05 - Russ Treadon <russ.treadon@noaa.gov>
!       - move h_fvG, h_fvS, h_ncS declarations inside "ifdef _GMAO_FVGSI_" construct
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::getlist_'
  integer :: ier,i,ifile
  integer :: iyr,imo,idy,ihr,inc
  logical :: fexist
  integer :: nmin,nmin_an,nmin_df,nmin_half
  character(len=max(len(FV_DYN),len(FV_SFC),len(NC_SFC))+4) :: fname
  character(len=8) :: cymd
  character(len=6) :: chms

#ifdef _GMAO_FVGSI_
  type(fvGrid)    :: h_fvG
  type(fvSurface) :: h_fvS
  type(ncSurface) :: h_ncS
_ENTRY_

  ifilesig(:)=-100
  hrdifsig(:)=   0
  nfldsig=1
  ntguessig=1
  ifilesig(1:nfldsig)=6
  hrdifsig(1:nfldsig)=0.

	! Set the list for surface data files by copying the list for
  	! upperair data files.

  nfldsfc=nfldsig
  ntguessfc=ntguessig
  ifilesfc(1:nfldsfc)=ifilesig(1:nfldsig)
  ifilesfc(nfldsfc+1:)=ifilesig(nfldsig+1:)
  hrdifsfc(1:nfldsfc)=hrdifsig(1:nfldsig)
  hrdifsfc(nfldsfc+1:)=hrdifsig(nfldsig+1:)

  	! Set the time baseline (analysis time)

  call w3fs21(iadate,nmin_an)
	! w3fs21(NCEP-w3) converts analysis time to minutes relative to
	! a fixed date.

  write(cymd,'(i4.4,i2.2,i2.2)') iadate(1),iadate(2),iadate(3)
  write(chms,'(i2.2,i2.2,i2.2)') iadate(4),0,0
  call mpout_log(myname_,'analysis yyyymmdd:hhmmss = '//cymd//':'//chms)
  call mpout_log(myname_,'analysis time in minutes =',nmin_an)

  	! Set the time range (half) in minutes

  nmin_half=(nhr_assimilation+1)/2*60
!________________________________________
    	! Check the list for fv-dyn files (GMAO GEOS/DAS)
    i=0
    ntguessig=-1
    do ifile=00,99
      write(fname,'(2a,i2.2)') trim(FV_DYN),'.',ifile
      inquire(file=fname,exist=fexist)
      if(fexist) then

        call fvGridHeader_read(fname,h_fvG,gridverify=GRIDVERIFY_)
        call fvGrid_get(h_fvG,year=iyr,month=imo,day=idy,	&
	  hour=ihr,freq=inc)
	call clean(h_fvG)

		! covert the data time to minutes
	call w3fs21((/iyr,imo,idy,ihr,0/),nmin)

	write(cymd,'(i4.4,i2.2,i2.2)') iyr,imo,idy
	write(chms,'(i2.2,i2.2,i2.2)') ihr,  0,  0
        call mpout_log(myname_,'"'//trim(fname)//	&
		'", yyyymmdd:hhmmss = '//cymd//':'//chms)

	nmin_df=nmin-nmin_an
	call mpout_log(myname_,'time in minutes =',nmin)
	call mpout_log(myname_,'diff in minutes =',nmin_df)

	if(abs(nmin_df) <= nmin_half) then
          i=i+1				! count it in
          ifilesig(i)=ifile		! file number
	  hrdifsig(i)=nmin_df/60.	! time offset in hours

	  if(nmin_df==0) then		! 1 min >> 1hr*.001, comparing
	  				! to r0_001 in read_files()
	    call mpout_log(myname_,	&
	    	'set ntguessig to file "'//trim(fname)//'",',i)

	    if(ntguessig/=-1) call die(myname_,	&
	    	'already defined, ntguessig',ntguessig)

	    ntguessig=i
	  endif
	endif
      endif
    end do
    nfldsig=i
    if(ntguessig==-1) call die(myname_,'undefined, ntguessig')
    if(nfldsig  == 0) call die(myname_,'no background file included')
!________________________________________
    	! Check the list for fv-sfc files (GMAO GEOS/DAS).  The list
	! should be all match, until I am sure what the rest of the
	! GSI is expecting.

    nfldsfc  =nfldsig
    ntguessfc=ntguessig
    ifilesfc(:)=ifilesig(:)
    hrdifsfc(:)=hrdifsig(:)

    ier=0
    do i=1,nfldsfc
      ifile=ifilesfc(i)

      write(fname,'(2a,i2.2)') trim(FV_SFC),'.',ifile
      inquire(file=fname,exist=fexist)

      if(.not.fexist) then
	ier=1
        call perr(myname_,'file not found, "'//trim(fname)//'"')

      else
        call fvSurface_getheader(fname,h_fvS)
        call get(h_fvS,year=iyr,month=imo,day=idy,hour=ihr,freq=inc)
	call clean(h_fvS)

		! covert the data time to minutes
	call w3fs21((/iyr,imo,idy,ihr,0/),nmin)

	write(cymd,'(i4.4,i2.2,i2.2)') iyr,imo,idy
	write(chms,'(i2.2,i2.2,i2.2)') ihr,  0,  0
        call mpout_log(myname_,'"'//trim(fname)//	&
		'", yyyymmdd:hhmmss = '//cymd//':'//chms)

	nmin_df=nmin-nmin_an
	call mpout_log(myname_,'time in minutes =',nmin)
	call mpout_log(myname_,'diff in minutes =',nmin_df)

	if(nint(hrdifsfc(i)*60)/=nmin_df) then
	  ier=1
	  call perr(myname_,'inconsistent hrdifsfc("'//trim(fname)// &
	  	'"), expecting',nint(hrdifsfc(i)*60),	&
		'get',nmin_df)
	endif
      endif
    end do

    if(ier/=0) call die(myname_,'inconsistent input files')
!________________________________________

    	! Check the list for nc-sfc files (NCEP)
    ier=-1
    do i=1,nfldsfc
      write(fname,'(2a,i2.2)') trim(NC_SFC),'.',ifilesfc(i)
      inquire(file=fname,exist=fexist)
      if(fexist) then
        call ncSurface_getheader(fname,h_ncS)
        call get(h_ncS,year=iyr,month=imo,day=idy,hour=ihr,freq=inc)
	call clean(h_ncS)

		! (iyr,imo,idy,ihr) += inc; inc=0
	call movdate_(iyr,imo,idy,ihr,inc)

		! convert the data time to minutes
	call w3fs21((/iyr,imo,idy,ihr,0/),nmin)

	write(cymd,'(i4.4,i2.2,i2.2)') iyr,imo,idy
	write(chms,'(i2.2,i2.2,i2.2)') ihr,  0,  0
        call mpout_log(myname_,'"'//trim(fname)//	&
		'", yyyymmdd:hhmmss = '//cymd//':'//chms)

	nmin_df=nmin-nmin_an
	call mpout_log(myname_,'time in minutes =',nmin)
	call mpout_log(myname_,'diff in minutes =',nmin_df)

	ier=ier+1
      endif
    end do

    if(ier<0) call die(myname_,'no ncSurface file')
    ier=0
_EXIT_
contains
subroutine movdate_(iyr,imo,idy,ihr,inc)
  use m_gsiGuess,only : gsiREAL,gsiINTG
  implicit none
  integer,intent(inout) :: iyr,imo,idy,ihr,inc	! y,m,d,h, hhmmss

  integer(gsiINTG),dimension(8) :: idate,odate
  real(gsiREAL),dimension(5) :: xtime

  idate(1)=iyr; idate(2)=imo		! year; month
  idate(3)=idy; idate(4)=0		! day ; time-zone
  idate(5)=ihr; idate(6)=0		! hour; min
  idate(7)=0  ; idate(8)=0		! sec ; milsec.

  xtime(1)=0  ; xtime(2)=inc/10000	! day; hour
  xtime(3)=mod(inc/100,100)		! min
  xtime(4)=0  ; xtime(5)=0		! sec; milsec

  call w3movdat(xtime,idate,odate)
  iyr=odate(1); imo=odate(2)		! year; month
  idy=odate(3); ihr=odate(5)		! day ; hour
  inc=0					! hhmmss
end subroutine movdate_
#endif
end subroutine getlist_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!       NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS      !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: read_ - interpolate fvGriddedState to GSI guess fields.
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine read_(itime,ifile,				&
	zsfc,lnps,vorx,divx,uwnd,vwnd,tv  ,q   ,cwmr,oz  ,	&
	sfct, comm)

      use m_gsiGuess,only : gsiREAL
      use m_gsiGuess,only : ntguessig

#ifdef _GMAO_FVGSI_
      use m_gsiGuess,only : gsiGuess_intp
      use m_gsiGuess,only : gsiGuess_unintp
      use m_gsiGuess,only : phisfile
      use m_gsiCheck,only : gsiCheck_show

      use m_fvGriddedState,only : fvGriddedState
      use m_fvGriddedState,only : fvGriddedState_read
      use m_fvGriddedState,only : fvGriddedState_write
      use m_fvGriddedState,only : ptr_phis
      use m_fvGriddedState,only : clean
      use m_checksums,only : checksums_show

      use m_interleavedObject,only : interleavedObject
      use m_interleavedObject,only : clean
      use m_fvGrid,only : fvGrid
      use m_fvGrid,only : clean

      use m_mpout,only : mpout_log
#endif
      implicit none

      integer,intent(in) :: itime	! state index
      integer,intent(in) :: ifile	! file index

      real(gsiREAL),dimension(:,:),intent(out) :: zsfc	! elevation
      real(gsiREAL),dimension(:,:),intent(out) :: lnps	! log(ps) in kPa
      real(gsiREAL),dimension(:,:,:),intent(out) :: vorx ! 2d-vor
      real(gsiREAL),dimension(:,:,:),intent(out) :: divx ! 2d-div
      real(gsiREAL),dimension(:,:,:),intent(out) :: uwnd ! u-wind
      real(gsiREAL),dimension(:,:,:),intent(out) :: vwnd ! v-wind
      real(gsiREAL),dimension(:,:,:),intent(out) :: tv   ! virt. temp.
      real(gsiREAL),dimension(:,:,:),intent(out) :: q    ! virt. temp.
      real(gsiREAL),dimension(:,:,:),intent(out) :: cwmr ! cld.wat.m.r.
      real(gsiREAL),dimension(:,:,:),intent(out) :: oz   ! ozone
      real(gsiREAL),dimension(:,:),intent(out) :: sfct	  ! sfc. tv

      integer,intent(in) :: comm	! communicator

! !REVISION HISTORY:
! 	17Sep04	- Jing Guo <guo@dao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::read_'
  integer,parameter :: ROOT=0

  character(len=len(FV_DYN)+4) :: fvdynName
  character(len=len(AN_DYN)+4) :: andynName

  integer :: ier

#ifdef _GMAO_FVGSI_
  type(fvGriddedState) :: w_fv,w_sv
  type(fvGrid) :: h_fv
  type(interleavedObject) :: etaLev1,etaLevs
!________________________________________
 	! Read a file at a given time
_ALLENTRY_
      write(fvdynName,'(2a,i2.2)') trim(FV_DYN),'.',ifile
		call mpout_log(myname_,	&
			'reading from "'//trim(fvdynName)//'"')

      call fvGriddedState_read(fvdynName,			&
      		w_fv,h_fv,etaLev1,etaLevs,comm,root,		&
		gridverify=GRIDVERIFY_)

      	! derives background state variables (plus divergence and
	! vorticity) on the GSI guess grid by interpolation, from,
	! for example, the FV grid.
      call gsiGuess_intp(w_fv, h_fv,etaLev1,etaLevs,	&
		phisfile,				&
		zsfc,lnps,uwnd,vwnd,tv,q,cwmr,oz,sfct,	&
		comm,vor=vorx,div=divx)

#ifdef DEBUG_CHECKSUMS
	call gsiCheck_show(myname_,			&
		zsfc,lnps,uwnd,vwnd,tv,q,cwmr,oz,sfct,	&
		vorx,divx, comm)
#endif
	!________________________________________
      if(itime==ntguessig) then
	call mpout_log(myname_,'itime(ntguessig) =',itime)
	call mpout_log(myname_,'ifile(ntguessig) =',ifile)

      		! do an inverse-interpolation if the time is the
		! analysis time.

        call gsiGuess_unintp(w_sv, w_fv,h_fv,etaLev1,etaLevs,	&
		phisfile,				&
		zsfc,lnps,uwnd,vwnd,tv,q,cwmr,oz,sfct,	&
		comm)

		! write out the inversely-interpolated state for
		! future use.

        write(andynName,'(2a,i2.2)') trim(AN_DYN),'.',0
		call mpout_log(myname_,	&
			'writing to "'//trim(andynName)//'"')

	call fvGriddedState_write(andynName,		&
			w_sv,h_fv,etaLev1,etaLevs,comm,root )

	call clean(w_sv)
      endif
      call clean(w_fv)
	!________________________________________
      call clean(h_fv)
      call clean(etaLev1)
      call clean(etaLevs)

!*** It is not clear, thus yet to be implemented, the mechanism of ***
!*** bias correction.						   ***

_ALLEXIT_
#else
	zsfc=0.; lnps=0.; vorx=0.; divx=0.; uwnd=0.
	vwnd=0.; tv  =0.; q   =0.; cwmr=0.; oz  =0.
	sfct=0.
#endif
end subroutine read_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!       NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS      !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: surface_read_ - interpolate surface parameters to GSI grid
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine surface_read_(itime,ifile, ws10,tskn,		&
    	snow_dep,veg_type,veg_frac,soil_type,soil_temp,		&
	soil_mois,isli_mask,isli_glbl, comm )

      use m_gsiGuess,only : gsiREAL
      use m_gsiGuess,only : ntguessig

#ifdef _GMAO_FVGSI_
      use m_gsiGuess,only : gsiGuess_surface_intp

      use m_fvSurface,only : fvSurface
      use m_fvSurface,only : fvSurface_read
      use m_fvSurface,only : ptr_isli_mask
      use m_fvSurface,only : clean

      use m_ncSurface,only : ncSurface
      use m_ncSurface,only : ncSurface_read
      use m_ncSurface,only : clean

      use m_mpout,only : mpout_log
      use m_mpif90,only : MP_type,MP_comm_rank
      use m_die,only : MP_die

      use m_gsiCheck,only : gsiCheck_surface_show
#endif
      implicit none

      integer,intent(in) :: itime	! state index, not used
      integer,intent(in) :: ifile	! file index, not used

      real(gsiREAL),dimension(:,:),intent(out) :: ws10	! 10m wind speed
      real(gsiREAL),dimension(:,:),intent(out) :: tskn	! T skin
      real(gsiREAL),dimension(:,:),intent(out) :: snow_dep ! snow depth
      real(gsiREAL),dimension(:,:),intent(out) :: veg_type ! veg. type
      real(gsiREAL),dimension(:,:),intent(out) :: veg_frac ! veg. cover.
      real(gsiREAL),dimension(:,:),intent(out) :: soil_type ! soil type
      real(gsiREAL),dimension(:,:),intent(out) :: soil_temp ! soil temp.
      real(gsiREAL),dimension(:,:),intent(out) :: soil_mois ! soil mois.

      integer,dimension(:,:),intent(out) :: isli_mask ! island/land/ice
      integer,dimension(:,:),intent(out) :: isli_glbl ! island/land/ice

      	! isli_mask is in subdomains, while isli_glbl is global on
	! every PE.

      integer,intent(in) :: comm	! communicator

! !REVISION HISTORY:
! 	17Sep04	- Jing Guo <guo@dao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::surface_read_'
  integer,parameter :: ROOT=0

  character(len=len(FV_SFC)+4) :: fvSfcName
  character(len=len(NC_SFC)+4) :: ncSfcName
  integer :: ier,myPE
  integer :: isize,jsize
#ifdef _GMAO_FVGSI_
  type(fvSurface) :: w_fv
  type(ncSurface) :: w_nc
  real(gsiREAL),pointer,dimension(:,:,:) :: ptr
!________________________________________
	! Read a file at a given time
_ALLENTRY_
	call MP_comm_rank(comm,myPE,ier)
		if(ier/=0) call MP_die(myname_,'MP_comm_ranl()',ier)

      write(fvSfcName,'(2a,i2.2)') trim(FV_SFC),'.',ifile
		call mpout_log(myname_,	&
			'reading from "'//trim(fvSfcName)//'"')
	!________________________________________
      	! Derive surface variables from a FV file.  First, read the
	! file and put the data into a distributed data structure.

      call fvSurface_read(fvsfcName,w_fv,comm,root)
      call gsiGuess_surface_intp(w_fv, ws10,tskn,snow_dep,	&
      	soil_temp,soil_mois,isli_mask,isli_glbl, comm)
	call clean(w_fv)
!_______________________________________________________________________
	! Read a file at a given time

      write(ncSfcName,'(2a,i2.2)') trim(NC_SFC),'.',IFILE_NC
		call mpout_log(myname_,	&
			'reading from "'//trim(ncSfcName)//'"')
	!________________________________________
      	! Derive surface variables from a NCEP sfcio file

      call ncSurface_read(ncSfcName,w_nc,comm,root)
      call gsiGuess_surface_intp(w_nc,veg_frac,veg_type,soil_type,comm)
	call clean(w_nc)

#ifdef DEBUG_CHECKSUMS
      call gsiCheck_surface_show(myname_, ws10,tskn,		&
    	snow_dep , veg_type, veg_frac,				&
	soil_type,soil_temp, soil_mois,isli_mask,isli_glbl, comm )
#endif
_ALLEXIT_
#endif
end subroutine surface_read_
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!       NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS      !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: surface_getvar_ - get/interpolate a fv-surface variable
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine surface_getvar_(var, tag, ifile)
      use m_gsiGuess,only : gsiREAL
#ifdef _GMAO_FVGSI_
      use m_fvSurface,only : fvSurface_alloc_getvar
      use m_llInterp,only : llInterp
      use m_llInterp,only : llInterp_l2ginit,clean
      use m_llInterp,only : llInterp_lh2rh
      use m_swapij,only : swapij

      use m_mpout,only : mpout_log
      use m_die,only : die
#endif
      implicit none

      		! below is a selected global variable stored locally
      real(gsiREAL),dimension(:,:),intent(out) :: var
      character(len=*),intent(in) :: tag	! name of the variable.
      integer,optional,intent(in) :: ifile	! file index, not used

! !REVISION HISTORY:
! 	17Sep04	- Jing Guo <guo@dao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!   16Aug05 - Russ Treadon <russ.treadon@noaa.gov>
!       - move "type(llInterp) :: llintp" inside "ifdef _GMAO_FVGSI_" construct
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::surface_getvar_'

  character(len=len(FV_SFC)+4) :: fvSfcName
  character(len=len(NC_SFC)+4) :: ncSfcName
  integer :: ier
  integer :: isize,jsize
  integer :: mlon,mlat
  integer :: nlon,nlat
  real(gsiREAL),pointer    ,dimension(:,:) :: pvar
  real(gsiREAL),allocatable,dimension(:,:) :: qvar
#ifdef _GMAO_FVGSI_
  type(llInterp) :: llintp
!________________________________________
	! Read a file at a given time
_ENTRY_
	!________________________________________
      	! Derive surface variables from a FV file.

      nlon=size(var,2)
      nlat=size(var,1)

      select case(tag)
      case('tsea','sheleg','slmsk')
if(present(ifile)) then
        write(fvSfcName,'(2a,i2.2)') trim(FV_SFC),'.',ifile
		call mpout_log(myname_,'reading from "'//	&
			trim(fvSfcName)//'" for "'//		&
			trim(tag)//'"' )
else
	! I have to hardwired this filename to a fixed number, not
	! from ifilesfc(:), since this called before getlist().

        write(fvSfcName,'(2a,i2.2)') trim(FV_SFC),'.',IFILE_FV
		call mpout_log(myname_,'reading from "'//	&
			trim(fvSfcName)//'" for "'//		&
			trim(tag)//'"' )
endif
        select case(tag)
	case('tsea')
          call fvSurface_alloc_getvar(fvsfcName,pvar,'TSKIN')
	case('sheleg')
          call fvSurface_alloc_getvar(fvsfcName,pvar,'SNOWDP')
	case('slmsk')
          call fvSurface_alloc_getvar(fvsfcName,pvar,'ORO')
	end select

	mlon=size(pvar,1)
	mlat=size(pvar,2)

	call llInterp_l2ginit(llintp,mlon,mlat,nlon,nlat)

				allocate(qvar(nlon,nlat))
	call llInterp_lh2rh(llintp,pvar, qvar)
			deallocate(pvar)

	call swapij(	   qvar,var)
		deallocate(qvar)

        call clean(llintp)
      case default
      	call die(myname_,'unsupported variable, "'//trim(tag)//'"')
      end select
!_______________________________________________________________________
_EXIT_
#endif
end subroutine surface_getvar_

!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!       NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS      !
!BOP -------------------------------------------------------------------
!
! !IROUTINE: write_ - interpolate guess_grid as analysis and write out.
!
! !DESCRIPTION:
!
! !INTERFACE:

    subroutine write_(itime,ifile,			&
	zsfc,lnps,uwnd,vwnd,tv  ,q   ,cwmr,oz  ,	&
	sfct, comm)

      use m_gsiGuess,only : gsiREAL
      use m_gsiGuess,only : ntguessig
#ifdef _GMAO_FVGSI_
      use m_gsiGuess,only : gsiGuess_unintp
      use m_gsiGuess,only : aincout
      use m_gsiGuess,only : aincfile
      use m_gsiGuess,only : phisfile
      use m_gsiCheck,only : gsiCheck_show

      use m_fvGriddedState,only : fvGriddedState
      use m_fvGriddedState,only : fvGriddedState_read
      use m_fvGriddedState,only : fvGriddedState_incr
      use m_fvGriddedState,only : fvGriddedState_write
      use m_fvGriddedState,only : fvGriddedState_bdump
      use m_fvGriddedState,only : ptr_phis
      use m_fvGriddedState,only : clean

      use m_interleavedObject,only : interleavedObject
      use m_interleavedObject,only : clean
      use m_fvGrid,only : fvGrid
      use m_fvGrid,only : clean

      use m_mpout,only : mpout_log
      use m_die,only : die
#endif
      implicit none

      integer,intent(in) :: itime	! state index
      integer,intent(in) :: ifile	! file index

      real(gsiREAL),dimension(:,:),intent(in) :: zsfc	! elevation
      real(gsiREAL),dimension(:,:),intent(in) :: lnps	! log(ps) in kPa
      real(gsiREAL),dimension(:,:,:),intent(in) :: uwnd ! u-wind
      real(gsiREAL),dimension(:,:,:),intent(in) :: vwnd ! v-wind
      real(gsiREAL),dimension(:,:,:),intent(in) :: tv   ! virt. temp.
      real(gsiREAL),dimension(:,:,:),intent(in) :: q    ! virt. temp.
      real(gsiREAL),dimension(:,:,:),intent(in) :: cwmr ! cld.wat.m.r.
      real(gsiREAL),dimension(:,:,:),intent(in) :: oz   ! ozone
      real(gsiREAL),dimension(:,:),intent(in) :: sfct	  ! sfc. tv

      integer,intent(in) :: comm	! communicator

! !REVISION HISTORY:
! 	17Sep04	- Jing Guo <guo@dao.gsfc.nasa.gov>
!		- initial prototype/prolog/code
!EOP ___________________________________________________________________

  character(len=*),parameter :: myname_=myname//'::write_'

  integer,parameter :: ROOT=0

  character(len=len(FV_DYN)+4) :: fvdynName
  character(len=len(AN_DYN)+4) :: andynName
  character(len=len(AN_DYN)+4) :: aidynName

#ifdef _GMAO_FVGSI_
  type(fvGriddedState) :: w_fv,w_sv,w_an
  type(fvGrid) :: h_fv,h_sv
  type(interleavedObject) :: etaLev1,etaLevs
  integer :: ier
!________________________________________
_ALLENTRY_

if(itime/=ntguessig)	&
	call die(myname_,'itime',itime,'ntguessig',ntguessig)

! read in the first guess

  write(fvdynName,'(2a,i2.2)') trim(FV_DYN),'.',ifile
		call mpout_log(myname_,	&
			'reading from "'//trim(fvdynName)//'"')

  call fvGriddedState_read(fvdynName,		&
  			w_fv,h_fv,etaLev1,etaLevs,comm,ROOT,	&
			gridverify=GRIDVERIFY_)

	call clean(etaLev1)
	call clean(etaLevs)

! read in the saved inversely-interpolated interpolatetd-first-guess

	call mpout_log(myname_,'itime(ntguessig) =',itime)
	call mpout_log(myname_,'ifile(ntguessig) =',ifile)

  write(andynName,'(2a,i2.2)') trim(AN_DYN),'.',0
		call mpout_log(myname_,	&
			'reading from "'//trim(andynName)//'"')

  		call fvGriddedState_read(andynName,		&
  			w_sv,h_sv,etaLev1,etaLevs,comm,ROOT,	&
			gridverify=GRIDVERIFY_)
		call clean(h_sv)	! use h_fv instead

! inversely interpolate the current analysis

#ifdef DEBUG_CHECKSUMS
	call gsiCheck_show(myname_,			&
		zsfc,lnps,uwnd,vwnd,tv,q,cwmr,oz,sfct,	&
		comm)
#endif

  call gsiGuess_unintp(w_an, w_fv,h_fv,etaLev1,etaLevs,	&
		phisfile,				&
		zsfc,lnps,uwnd,vwnd,tv,q,cwmr,oz,sfct,	&
		comm)

! write out new w_an for verification

  write(andynName,'(2a,i2.2)') trim(AN_DYN),'.',98
 	call mpout_log(myname_,	&
			'writing to "'//trim(andynName)//'"')
	call fvGriddedState_write(andynName,		&
			w_an,h_fv,etaLev1,etaLevs,comm,ROOT )

! update the first guess, w_fv += w_an-w_sv

  call fvGriddedState_incr(w_fv,w_an,w_sv)
	call clean(w_sv)

! write out new w_fv as analysis

  write(andynName,'(2a,i2.2)') trim(AN_DYN),'.',99
	 	call mpout_log(myname_,	&
			'writing to "'//trim(andynName)//'"')
   call fvGriddedState_write(andynName,		&
			w_fv,h_fv,etaLev1,etaLevs,comm,ROOT )

! write out w_an as analysis increment

  if(aincout) then
    write(aidynName,'(2a,i2.2)') trim(AI_DYN),'.',99
	 	call mpout_log(myname_,	&
			'writing to "'//trim(aidynName)//'"')
    call fvGriddedState_write(aidynName,		&
			w_an,h_fv,etaLev1,etaLevs,comm,ROOT )
  endif

  if(aincfile/='.none.') then
    call mpout_log(myname_,'write a-grid increments to "'// &
        trim(aincfile)//'"')
    call fvGriddedState_bdump(aincfile,w_an,h_fv,etaLev1,etalevs, &
        comm,ROOT)
  endif

	call clean(etaLev1)
	call clean(etaLevs)
	call clean(h_fv)
  	call clean(w_fv)
  	call clean(w_an)

_ALLEXIT_
#endif
end subroutine write_
end module m_fvAnaGrid