!------------------------------------------------------------------------------ ! Global Modeling and Assimilation Office (GMAO) ! ! Goddard Earth Observing System (GEOS) ! ! MAPL Component ! !------------------------------------------------------------------------------ ! #include "unused_dummy.H" ! !> !### MODULE: `ESMF_CFIOGridMod` ! ! Author: GMAO SI-Team ! ! `ESMF_CFIOGridMod` - Source file for CFIO Grid ! ! The code in this file provides grid data type definitions and interface ! specifications. ! !#### History !- Feb2007 Baoyu Yin Separated from ESMF_CFIOMod ! module ESMF_CFIOGridMod !------------------------------------------------------------------------------ ! !USES: use ESMF_CFIOUtilMod, only : MLEN, MVARLEN use, intrinsic :: ISO_FORTRAN_ENV, only: REAL64 implicit none !------------------------------------------------------------------------------ ! !PRIVATE TYPES: private !------------------------------------------------------------------------------ ! !PUBLIC DATA TYPES: ! public :: ESMF_CFIOGrid ! A CFIO grid object public :: ESMF_CFIOGridCreate ! constructor public :: ESMF_CFIOGridSet ! set a CFIO grid public :: ESMF_CFIOGridGet ! get a CFIO grid public :: ESMF_CFIOGridDestroy ! destructor ! !EOP !------------------------------------------------------------------------------ ! !> ! Define a new data type "CFIO_Grid" -- contains grid information type ESMF_CFIOGrid ! private character(len=MVARLEN) :: gName !! name for this grid integer :: im !! size of longitudinal dimension integer :: jm !! size of latitudinal dimension integer :: km !! size of vertical dimension integer :: tm !! size of time dimension real(kind=REAL64), pointer :: lon(:) => NULL() !! longitude of center of gridbox in !! degrees east of Greenwich (can be !! -180 -> 180 or 0 -> 360) real(kind=REAL64), pointer :: lat(:) => NULL() !! latitude of center of gridbox in !! degrees north of equator real(kind=REAL64), pointer :: lev(:) => NULL() !! Level (units given by levUnits) of !! center of gridbox character(len=MLEN) :: levUnits !! units of level dimension, e.g., !! "hPa", "sigma_level" character(len=MLEN) :: coordinate !! string to indicate vertical coord !! (pressure, sigma, pressure_sigma) character(len=MLEN) :: standardName !! string for CF standard name character(len=MLEN) :: formulaTerm !! string for CF formula terms real, pointer :: ak(:) => NULL() !! parameter for hybrid sigma prs coord. real, pointer :: bk(:) => NULL() !! parameter for hybrid sigma prs coord. real, pointer :: sigma(:) => NULL() !! parameter for sigma coordinate real :: ptop !! parameter for sigma/eta coordinate character(len=MVARLEN) :: ptopUnit !! unit of ptop logical :: twoDimLat !! support 2D lat/lon or not logical :: reduceGrid !! support for reduced grid logical :: stnGrid !! support for station data end type ESMF_CFIOGrid !------------------------------------------------------------------------------ contains !------------------------------------------------------------------------------ !> ! `ESMF_CFIOGridCreate` -- ESMF_Grid object constructor ! ! Create a CFIO grid object and initialize vars ! type(ESMF_CFIOGrid) function ESMF_CFIOGridCreate (gName, rc) ! ! !INPUT PARAMETERS: ! character(len=*), intent(in), OPTIONAL :: gName !! grid object name integer, intent(out), OPTIONAL :: rc !! Error return code: !! 0 all is well ! !------------------------------------------------------------------------------ type(ESMF_CFIOGrid) :: grid ! a CFIO grid object grid%im = 0 grid%jm = 0 grid%km = 0 grid%tm = 0 grid%levUnits = 'unknown' grid%coordinate = 'unknown' grid%standardName = 'unknown' grid%formulaTerm = 'unknown' grid%ptop = 0 grid%ptopUnit = 'Pa' grid%twoDimLat = .false. grid%reduceGrid = .false. grid%stnGrid = .false. nullify(grid%lon) nullify(grid%lat) nullify(grid%lev) nullify(grid%ak) nullify(grid%bk) nullify(grid%sigma) if ( present(gName) ) grid%gName = gName if ( present(rc) ) rc = 0 ESMF_CFIOGridCreate = grid end function ESMF_CFIOGridCreate !------------------------------------------------------------------------------ !> ! `ESMF_CFIOGridSet` -- set up a grid ! subroutine ESMF_CFIOGridSet (grid, gName, im, jm, km, tm, lat, lon, lev,& coordinate, standardName, formulaTerm, & levUnit, ak, bk, sigma, ptop, ptopUnit, & lat2, lon2, & twoDimLat, reduceGrid, stnGrid, rc) ! ! !INPUT PARAMETERS: ! character(len=*), intent(in), OPTIONAL :: gName !! grid name integer, intent(in), OPTIONAL :: im !! size of longitudinal dimension integer, intent(in), OPTIONAL :: jm !! size of latitudinal dimension integer, intent(in), OPTIONAL :: km !! size of vertical dimension integer, intent(in), OPTIONAL :: tm !! size of time dimension real, intent(in), OPTIONAL :: lon(:) !! longitude real, intent(in), OPTIONAL :: lat(:) !! latitude real, intent(in), OPTIONAL :: lev(:) !! Level real(KIND=REAL64), pointer, OPTIONAL :: lon2(:) !! longitude 2d real(KIND=REAL64), pointer, OPTIONAL :: lat2(:) !! latitude 2d character(len=*), intent(in), OPTIONAL :: levUnit !! units of level dimension, e.g., "hPa". character(len=*), intent(in), OPTIONAL :: coordinate !! string to indicate vertical coord !! (pressure, sigma, pressure_sigma) character(len=*), intent(in), OPTIONAL :: standardName !! string for standard name character(len=*), intent(in), OPTIONAL :: formulaTerm !! formula terms real, intent(in), OPTIONAL :: ak(:) !! parameter for hybrid sigma prs coord. real, intent(in), OPTIONAL :: bk(:) !! parameter for hybrid sigma prs coord. real, intent(in), OPTIONAL :: sigma(:) !! parameter for sigma coordinate real, intent(in), OPTIONAL :: ptop !! parameter for sigma coordinate character(len=*), intent(in), OPTIONAL :: ptopUnit !! unit of ptop logical, intent(in), OPTIONAL :: twoDimLat !! support 2D lat/lon or not logical, intent(in), OPTIONAL :: reduceGrid !! support for reduced grid logical, intent(in), OPTIONAL :: stnGrid !! support for statio grid ! !OUTPUT PARAMETERS: ! integer, intent(out), OPTIONAL :: rc !! Error return code: !! 0 all is well !! -1 Problem in setting lon !! -2 Problem in setting lat !! -3 Problem in setting lev ! !INPUT/OUTPUT PARAMETERS: ! type(ESMF_CFIOGrid), intent(inout) :: grid ! CFIO grid ! !------------------------------------------------------------------------------ integer :: rtcode = 0 integer :: i, j !integer :: sz _UNUSED_DUMMY(sigma) _UNUSED_DUMMY(reduceGrid) if ( present(gName) ) grid%gName = gName if ( present(im) ) grid%im = im if ( present(jm) ) grid%jm = jm if ( present(km) ) grid%km = km if ( present(tm) ) grid%tm = tm if (present(twoDimLat)) then grid%twoDimLat = twoDimLat if (.not. (present(im) .and. present(jm) .and. & present(lon2) .and. present(lat2))) then rtcode = -1 else !sz = im*jm ! ALT: for "true" 2d coordinates we save memory ! and just point to the original coordinate arrays !allocate(grid%lon(sz), grid%lat(sz), stat = rtcode) grid%lon => lon2 grid%lat => lat2 end if !if (rtcode .ne. 0) then ! print *, "problem in setting ESMF_CFIOGridSet:lat" ! rtcode = -2 ! if ( present(rc) ) rc = rtcode ! return !end if else if ( present(lon) ) then grid%im = size(lon) allocate(grid%lon(grid%im), stat = rtcode) grid%lon = lon else if ( present(im) ) then allocate(grid%lon(im), stat = rtcode) do i = 1, im grid%lon(i) = 360./im * (i-1) end do end if if (rtcode .ne. 0) then print *, "problem in setting ESMF_CFIOGridSet:lon" rtcode = -1 if ( present(rc) ) rc = rtcode return end if if ( present(lat) ) then grid%jm = size(lat) allocate(grid%lat(grid%jm), stat = rtcode) grid%lat = lat else if ( present(jm) ) then allocate(grid%lat(jm), stat = rtcode) do j = 1, jm grid%lat(j) = 180./(jm-1) * (j-1) - 90 end do end if if (rtcode .ne. 0) then print *, "problem in setting ESMF_CFIOGridSet:lat" rtcode = -2 if ( present(rc) ) rc = rtcode return end if end if ! if (usableTwoDimLat)... if ( present(lev) ) then grid%km = size(lev) allocate(grid%lev(grid%km), stat = rtcode) grid%lev = lev if (rtcode .ne. 0) then print *, "problem in setting ESMF_CFIOGridSet:lev" rtcode = -3 if ( present(rc) ) rc = rtcode return end if end if if ( present(levUnit) ) grid%levUnits = levUnit if ( present(coordinate) ) grid%coordinate = coordinate if ( present(standardName) ) grid%standardName = standardName if ( present(formulaTerm) ) grid%formulaTerm = formulaTerm if ( present(ak) ) then allocate(grid%ak(size(ak)), stat=rtcode) grid%ak = ak end if if ( present(bk) ) then allocate(grid%bk(size(bk)), stat=rtcode) grid%bk = bk end if if ( present(ptop) ) then grid%ptop = ptop end if if ( present(ptopUnit) ) grid%ptopUnit = ptopUnit if ( present(stnGrid) ) then grid%stnGrid = stnGrid end if if ( present(rc) ) rc = rtcode end subroutine ESMF_CFIOGridSet !------------------------------------------------------------------------------ !> ! `ESMF_CFIOGridGet` -- get grid info ! subroutine ESMF_CFIOGridGet (grid, gName, im, jm, km, tm, lat, lon, lev,& coordinate, standardName, formulaTerm, & levUnit, ak, bk, sigma, ptop, twoDimLat, & reduceGrid, stnGrid, rc) ! ! !INPUT PARAMETERS: ! type(ESMF_CFIOGrid), intent(in) :: grid !! CFIO grid ! !OUTPUT PARAMETERS: ! character(len=*), intent(out), OPTIONAL :: gName !! grid name integer, intent(out), OPTIONAL :: im !! size of longitudinal dimension integer, intent(out), OPTIONAL :: jm !! size of latitudinal dimension integer, intent(out), OPTIONAL :: km !! size of vertical dimension integer, intent(out), OPTIONAL :: tm !! size of time dimension real, pointer, OPTIONAL :: lon(:) !! longitude real, pointer, OPTIONAL :: lat(:) !! latitude real, pointer, OPTIONAL :: lev(:) !! Level character(len=*), intent(out), OPTIONAL :: levUnit !! units of level dimension, e.g., "hPa". character(len=*), intent(out), OPTIONAL :: coordinate !! string to indicate vertical coord !! (pressure, sigma, pressure_sigma) character(len=*), intent(out), OPTIONAL :: standardName !! string for standard name character(len=*), intent(out), OPTIONAL :: formulaTerm !! formula terms real, intent(out), OPTIONAL :: ak(:) !! parameter for hybrid sigma prs coord. real, intent(out), OPTIONAL :: bk(:) !! parameter for hybrid sigma prs coord. real, intent(out), OPTIONAL :: sigma(:) !! parameter for sigma coordinate real, intent(out), OPTIONAL :: ptop !! parameter for sigma coordinate logical, intent(out), OPTIONAL :: twoDimLat !! support 2D lat/lon or not logical, intent(out), OPTIONAL :: reduceGrid !! support for reduced grid logical, intent(out), OPTIONAL :: stnGrid !! support for station grid integer, intent(out), OPTIONAL :: rc !! Error return code: !! 0 all is well !! -1 problem in getting lon !! -2 problem in getting lat !! -3 problem in getting lev ! !------------------------------------------------------------------------------ integer :: rtcode = 0 if ( present(gName) ) gName = grid%gName if ( present(im) ) im = grid%im if ( present(jm) ) jm = grid%jm if ( present(km) ) km = grid%km if ( present(tm) ) tm = grid%tm if ( present(lon) ) then allocate(lon(size(grid%lon)), stat=rtcode) lon = grid%lon if (rtcode .ne. 0) then print *, "problem in getting ESMF_CFIOGridGet:lon" rtcode = -1 if ( present(rc) ) rc = rtcode return end if end if if ( present(lat) ) then allocate(lat(size(grid%lat)), stat=rtcode) lat = grid%lat if (rtcode .ne. 0) then print *, "problem in getting ESMF_CFIOGridGet:lat" rtcode = -2 if ( present(rc) ) rc = rtcode return end if end if if ( present(lev) ) then allocate(lev(size(grid%lev)), stat=rtcode) if (rtcode .ne. 0) then print *, "problem in getting ESMF_CFIOGridGet:lev" rtcode = -3 if ( present(rc) ) rc = rtcode return end if lev = grid%lev end if if ( present(ak) ) then if ( associated(grid%ak) ) then ak = grid%ak else print *, "ak was not defined in the input file" end if end if if ( present(bk) ) then if ( associated(grid%bk) ) then bk = grid%bk else print *, "bk was not defined in the input file" end if end if if ( present(sigma) ) then if ( associated(grid%sigma) ) then sigma = grid%sigma else print *, "sigam was not defined in the input file" end if end if if ( present(ptop) ) then ptop = grid%ptop end if if ( present(twoDimLat) ) then twoDimLat = grid%twoDimLat end if if ( present(reduceGrid) ) then reduceGrid = grid%reduceGrid end if if ( present(standardName) ) standardName = grid%standardName if ( present(coordinate) ) coordinate = grid%coordinate if ( present(formulaTerm) ) formulaTerm = grid%formulaTerm if ( present(levUnit) ) levUnit = grid%levUnits if ( present(stnGrid) ) stnGrid = grid%stnGrid if ( present(rc) ) rc = rtcode end subroutine ESMF_CFIOGridGet !------------------------------------------------------------------------------ !> ! `ESMF_CFIOGridDestroy` -- destructor for a CFIO grid object ! subroutine ESMF_CFIOGridDestroy (grid, rc) ! ! !INPUT PARAMETERS: ! integer, intent(out), OPTIONAL :: rc !! Error return code: !! 0 all is well ! ! !INPUT/OUTPUT PARAMETERS: ! type(ESMF_CFIOGrid), intent(inout) :: grid !! CFIOGrid object ! !------------------------------------------------------------------------------ integer :: rtcode = 0 if (.not. grid%twoDimLat) then if ( associated(grid%lon) ) deallocate(grid%lon, stat=rtcode) if ( associated(grid%lat) ) deallocate(grid%lat, stat=rtcode) end if if ( associated(grid%lev) ) deallocate(grid%lev, stat=rtcode) if ( associated(grid%ak) ) deallocate(grid%ak, stat=rtcode) if ( associated(grid%bk) ) deallocate(grid%bk, stat=rtcode) if ( associated(grid%sigma) ) deallocate(grid%sigma, stat=rtcode) if ( present(rc) ) rc = rtcode end subroutine ESMF_CFIOGridDestroy end module ESMF_CFIOGridMod