!-----------------------------------------------------------------------
!
      PROGRAM PREPROC_LATLON_SM
!
!-----------------------------------------------------------------------
!***  Dmitry's coupler needs to read in the geographic lat/lon of
!***  the H and V points on the B-grid that spans the upper parent 
!***  domain and is at the resolution of an outer nest.  It needs
!***  the sea mask on that grid as well.  
!-----------------------------------------------------------------------
!
      USE netcdf
!
!-----------------------------------------------------------------------
      IMPLICIT NONE
!-----------------------------------------------------------------------
!
      INTEGER,PARAMETER :: SINGLE=SELECTED_REAL_KIND(P=6 ,R=37)
      INTEGER,PARAMETER :: DOUBLE=SELECTED_REAL_KIND(P=13,R=200)
!
!-----------------------------------------------------------------------
!
!-----------------------
!***  Set the following
!-----------------------
!
      INTEGER,PARAMETER :: IM_PARENT=451                                &  !<-- I extent of the upper parent domain's grid
                          ,JM_PARENT=451                                &  !<-- J extent of the upper parent domain's grid
                          ,PARENT_CHILD_SPACE_RATIO=3                      !<-- Ratio of parent grid increment to its child's 
!
!!      REAL(kind=DOUBLE),PARAMETER :: TPH0D= 18.4_double, TLM0D=-94.3_double &  !<-- Geographic lat/lon (deg) of domain's center
      REAL(kind=DOUBLE):: TPH0D, TLM0D     !<-- Geographic lat/lon (deg) of domain's center
      REAL(kind=DOUBLE), PARAMETER :: SBD  =-40.5_double ,WBD  =-40.5_double    !<-- Rotate lat/lon (deg) of domain's south/west boundaries
!
      LOGICAL :: WRITE_SINGLE=.FALSE.                                       !<-- Write lat/lon in single (true) / double (false) precision
!
!-----------------------
!
      INTEGER,PARAMETER :: IM=(IM_PARENT-1)*PARENT_CHILD_SPACE_RATIO+1  &  !<-- I extent of parent domain at child resolution
                          ,JM=(JM_PARENT-1)*PARENT_CHILD_SPACE_RATIO+1     !<-- J extent of parent domain at child resolution
!
      CHARACTER(len=17) :: OUTPUT_FILENAME='coupler_grid_data'             !<-- The file that will hold the final data.
!
      INTEGER :: I,IRTN,J,N,NUNIT
!
      REAL(kind=DOUBLE) :: DEG2RAD,DLM,DLM_HALF,DPH,DPH_HALF            &
                          ,I_MID,J_MID,PI,RAD2DEG,TLM0,TPH0
!
      REAL(kind=DOUBLE),DIMENSION(IM,JM) :: GLAT_H,GLON_H               &  !<-- Geographic lat/lon (deg) of H points on child res grid
                                           ,GLAT_V,GLON_V               &  !<-- Geographic lat/lon (deg) of V points on child res grid
                                           ,TLAT_H,TLON_H               &  !<-- Rotated lat/lon (deg) of H points on child res grid
                                           ,TLAT_V,TLON_V                  !<-- Rotated lat/lon (deg) of V points on child res grid
!
      REAL(kind=SINGLE),DIMENSION(:,:),ALLOCATABLE :: GLAT_H_S,GLON_H_S &
                                                     ,GLAT_V_S,GLON_V_S 
!
      REAL,DIMENSION(IM,JM) :: SEA_MASK                                    !<-- Sea mask (sea=1.) on child res grid
!
      LOGICAL :: OPENED
!
!------------------------------------------------------------------------
!read center latitude and longitude
!-----------------------------------------------------------------------
      OPEN(100,FILE='storm_center',form='FORMATTED')
      READ(100,*)TPH0D
      READ(100,*)TLM0D
      CLOSE(100)
!-----------------------------------------------------------------------
!***********************************************************************
!-----------------------------------------------------------------------
!
      PI=ACOS(-1._double)
      DEG2RAD=PI/180._double
      RAD2DEG=180._double/PI
!
      TPH0=TPH0D*DEG2RAD
      TLM0=TLM0D*DEG2RAD
!
!-----------------------------------------------------------------------
!***  Compute the constant grid increments (deg) in rotated lat/lon.
!-----------------------------------------------------------------------
!
      DPH=-2._double*SBD/REAL(JM-1)
      DLM=-2._double*WBD/REAL(IM-1)
!
!-----------------------------------------------------------------------
!***  Compute the rotated lat/lon of all H and V points.
!-----------------------------------------------------------------------
!
      I_MID=(IM+1)*0.5_double
      J_MID=(JM+1)*0.5_double
      DPH_HALF=0.5_double*DPH
      DLM_HALF=0.5_double*DLM
!
      DO J=1,JM
      DO I=1,IM
        TLAT_H(I,J)=(J-J_MID)*DPH
        TLAT_V(I,J)=TLAT_H(I,J)+DPH_HALF
        TLON_H(I,J)=(I-I_MID)*DLM
        TLON_V(I,J)=TLON_H(I,J)+DLM_HALF
      ENDDO
      ENDDO
!
!-----------------------------------------------------------------------
!***  Compute the geographic lat/lon of all H and V points.
!-----------------------------------------------------------------------
!
      CALL GEO(TLAT_H,TLON_H,GLAT_H,GLON_H)
      CALL GEO(TLAT_V,TLON_V,GLAT_V,GLON_V)
!
!-----------------------------------------------------------------------
!***  The sea mask field that spans the upper parent domain at the
!***  outer nest's resolution is already available in the NetCDF
!***  file generated for that nest by NPS so read it in.
!-----------------------------------------------------------------------
!
      CALL READ_NETCDF
!
!-----------------------------------------------------------------------
!***  Write out the data.
!-----------------------------------------------------------------------
!
      select_unit: DO N=51,59
        INQUIRE(N,OPENED=OPENED)
        IF(.NOT.OPENED)THEN
          NUNIT=N
          EXIT select_unit
        ENDIF
      ENDDO select_unit
!
      OPEN(unit=NUNIT,file=OUTPUT_FILENAME,status='REPLACE'             &
          ,form='UNFORMATTED',iostat=IRTN)
!
      IF(WRITE_SINGLE)THEN
        ALLOCATE(GLAT_H_S(IM,JM))
        ALLOCATE(GLON_H_S(IM,JM))
        ALLOCATE(GLAT_V_S(IM,JM))
        ALLOCATE(GLON_V_S(IM,JM))
!
        DO J=1,JM
        DO I=1,IM
          GLAT_H_S(I,J)=GLAT_H(I,J)
          GLON_H_S(I,J)=GLON_H(I,J)
          GLAT_V_S(I,J)=GLAT_V(I,J)
          GLON_V_S(I,J)=GLON_V(I,J)
        ENDDO
        ENDDO
!
        WRITE(NUNIT)GLAT_H_S
        WRITE(NUNIT)GLON_H_S
        WRITE(NUNIT)GLAT_V_S
        WRITE(NUNIT)GLON_V_S
        WRITE(NUNIT)SEA_MASK
!
      ELSE
        WRITE(NUNIT)GLAT_H
        WRITE(NUNIT)GLON_H
        WRITE(NUNIT)GLAT_V
        WRITE(NUNIT)GLON_V
        WRITE(NUNIT)SEA_MASK
!
      ENDIF
!
      CLOSE(NUNIT)
!
!-----------------------------------------------------------------------
!
      CONTAINS
!
!-----------------------------------------------------------------------
!
      SUBROUTINE GEO(TLAT,TLON,GLAT,GLON)
!
!-----------------------------------------------------------------------
!***  Given the grid specifications and the rotated lat/lon of each
!***  point compute the geographic lat/lon of each point.
!-----------------------------------------------------------------------
      IMPLICIT NONE
!-----------------------------------------------------------------------
!
      INTEGER,PARAMETER :: DOUBLE=SELECTED_REAL_KIND(P=13,R=200)
!
      REAL(kind=DOUBLE),DIMENSION(IM,JM),INTENT(IN) :: TLAT,TLON
      REAL(kind=DOUBLE),DIMENSION(IM,JM),INTENT(OUT) :: GLAT,GLON
!
      REAL(kind=DOUBLE) :: ANUM,ARG1,DENOM,GLATR,GLONR,RELM,TLATR,TLONR
!
!-----------------------------------------------------------------------
!***********************************************************************
!-----------------------------------------------------------------------
!
      DO J=1,JM
      DO I=1,IM
        TLATR=TLAT(I,J)*DEG2RAD
        TLONR=TLON(I,J)*DEG2RAD
        ARG1=SIN(TLATR)*COS(TPH0)+COS(TLATR)*SIN(TPH0)*COS(TLONR)
        IF(ABS(ARG1)>1._double)THEN
          ARG1=SIGN(1._double,ARG1)
        ENDIF
        GLATR=ASIN(ARG1)
!
        ANUM=COS(TLATR)*SIN(TLONR)
        DENOM=(COS(TLONR)*COS(TLATR)-SIN(TPH0)*ARG1)/COS(TPH0)
        RELM=ATAN2(ANUM,DENOM)
        GLONR=RELM+TLM0
        IF(GLONR<-PI)GLONR=GLONR+PI*2._double
        IF(GLONR> PI)GLONR=GLONR-PI*2._double
!
        GLAT(I,J)=GLATR*RAD2DEG
        GLON(I,J)=GLONR*RAD2DEG
      ENDDO
      ENDDO
!
!-----------------------------------------------------------------------
      END SUBROUTINE GEO
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
      SUBROUTINE READ_NETCDF
!
!-----------------------------------------------------------------------
!***  Read the sea mask data from the NPS-generated file. 
!-----------------------------------------------------------------------
      IMPLICIT NONE
!-----------------------------------------------------------------------
!
      INTEGER :: I_COUNT_DATA,I_END,I_START                             &
                ,J_COUNT_DATA,J_END,J_START                             &
                ,NCID,NCTYPE,NDIMS,VAR_ID
!
      INTEGER,DIMENSION(1:2) :: DIM_IDS
!
      CHARACTER(len=2) :: SPACE_RATIO
      CHARACTER(len=8) :: FILENAME
      CHARACTER(len=15) :: VNAME
!
!-----------------------------------------------------------------------
!***********************************************************************
!-----------------------------------------------------------------------
!
      I_START=1
      I_END=IM
      J_START=1
      J_END=JM
!
      I_COUNT_DATA=I_END-I_START+1
      J_COUNT_DATA=J_END-J_START+1
!
      IF(PARENT_CHILD_SPACE_RATIO<=9)THEN
        WRITE(SPACE_RATIO,'(I1.1)')PARENT_CHILD_SPACE_RATIO
      ELSEIF(PARENT_CHILD_SPACE_RATIO>=10)THEN
        WRITE(SPACE_RATIO,'(I2.2)')PARENT_CHILD_SPACE_RATIO
      ENDIF
!
      FILENAME='SM_'//TRIM(SPACE_RATIO)//'.nc'                             !<-- Name of the existing sea mask NetCDF file
!
      CALL CHECK(NF90_OPEN(FILENAME,NF90_NOWRITE,NCID))                    !<-- Open the external NetCDF file with sea mask values.
!
      CALL CHECK(NF90_INQUIRE_VARIABLE(NCID,3,VNAME,NCTYPE              &  !<-- The sea mask is the 3rd variable in the file.
                                      ,NDIMS,DIM_IDS))
!
      CALL CHECK(NF90_INQ_VARID(NCID,VNAME,VAR_ID))
!
      CALL CHECK(NF90_GET_VAR(NCID,VAR_ID                               &  !<-- Extract the 
                             ,SEA_MASK(I_START:I_END,J_START:J_END)     &  !    sea mask values
                             ,start=(/I_START,J_START/)                 &  !    from the external
                             ,count=(/I_COUNT_DATA,J_COUNT_DATA/)))        !    NetCDF file.
!
!-----------------------------------------------------------------------
      END SUBROUTINE READ_NETCDF
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
      SUBROUTINE CHECK(RC)
!
!-----------------------------------------------------------------------
      IMPLICIT NONE
!-----------------------------------------------------------------------
!
      INTEGER,INTENT(IN) :: RC
!
!-----------------------------------------------------------------------
!***********************************************************************
!-----------------------------------------------------------------------
!
      IF(RC/=NF90_NOERR)THEN
        WRITE(*,*)TRIM(ADJUSTL(NF90_STRERROR(RC)))
!       WRITE(0,11101)RC
11101   FORMAT(' ERROR: RC=',I5)
      ENDIF
!
!-----------------------------------------------------------------------
!
      END SUBROUTINE CHECK
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
!
      END PROGRAM PREPROC_LATLON_SM
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------