ESMF_GridCreateFrmNCFileDG Function

private function ESMF_GridCreateFrmNCFileDG(filename, fileformat, distgrid, keywordEnforcer, isSphere, polekindflag, addCornerStagger, coordTypeKind, addUserArea, indexflag, addMask, varname, coordNames, rc)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: filename
type(ESMF_FileFormat_Flag), intent(in), optional :: fileformat
type(ESMF_DistGrid), intent(in) :: distgrid
type(ESMF_KeywordEnforcer), optional :: keywordEnforcer
logical, intent(in), optional :: isSphere
type(ESMF_PoleKind_Flag), intent(in), optional :: polekindflag(2)
logical, intent(in), optional :: addCornerStagger
type(ESMF_TypeKind_Flag), intent(in), optional :: coordTypeKind
logical, intent(in), optional :: addUserArea
type(ESMF_Index_Flag), intent(in), optional :: indexflag
logical, intent(in), optional :: addMask
character(len=*), intent(in), optional :: varname
character(len=*), intent(in), optional :: coordNames(:)
integer, intent(out), optional :: rc

Return Value type(ESMF_Grid)


Source Code

     function ESMF_GridCreateFrmNCFileDG(filename, fileformat, distgrid, keywordEnforcer, &
       isSphere, polekindflag, addCornerStagger, coordTypeKind, addUserArea, indexflag, &
       addMask, varname, coordNames, rc)

! !RETURN VALUE:
      type(ESMF_Grid) :: ESMF_GridCreateFrmNCFileDG
!
! !ARGUMENTS:

    character(len=*),       intent(in)             :: filename
    type(ESMF_FileFormat_Flag), intent(in), optional :: fileformat
    type(ESMF_DistGrid),    intent(in)             :: distgrid
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
    logical,                intent(in),  optional  :: isSphere
    type(ESMF_PoleKind_Flag),  intent(in),  optional :: polekindflag(2)
    logical,                intent(in),  optional  :: addCornerStagger
    type(ESMF_TypeKind_Flag),intent(in), optional  :: coordTypeKind
    logical,                intent(in),  optional  :: addUserArea
    type(ESMF_Index_Flag),  intent(in),  optional  :: indexflag
    logical,                intent(in),  optional  :: addMask
    character(len=*),       intent(in),  optional  :: varname
    character(len=*),       intent(in),  optional  :: coordNames(:)
    integer,                intent(out), optional  :: rc

! !DESCRIPTION:
! This function creates a {\tt ESMF\_Grid} object using the grid definition from
! a grid file in NetCDF that is either in the SCRIP format or in the CF convention.
! To specify the distribution, the user passes in a {\tt distGrid}.
! The grid defined in the file has to be a 2D logically rectangular grid.
! This function first call {\tt ESMF\_GridCreateFrmNCFile()} to create a {\tt ESMF\_Grid}
! object using a pre-calculated block distribution, then redistribute the Grid to
! create a new Grid object using the user specified {\tt distGrid}.
!
! This call is {\em collective} across the current VM.
!
! The arguments are:
! \begin{description}
! \item[filename]
!     The NetCDF Grid filename.
! \item[{[fileformat]}]
!     The file format.  The valid options are {\tt ESMF\_FILEFORMAT\_SCRIP} and {\tt ESMF\_FILEFORMAT\_GRIDSPEC}.
!     If it is the SCRIP format, the dimension {\tt grid\_rank} in the file has to be equal to 2.
!      Please see section~\ref{const:fileformatflag} for a detailed description of the options.  
!      If not specified, the file type will be detected automatically.
! \item[distGrid]
!      A distGrid defines how the grid is distributed
! \item[{[isSphere]}]
!      If .true., create a periodic Grid. If .false., create a regional Grid. Defaults to .true.
! \item[{[polekindflag]}]
!      Two item array which specifies the type of connection which occurs at the pole. The value in polekindflag(1)
!      specifies the connection that occurs at the minimum end of the pole dimension. The value in polekindflag(2)
!      specifies the connection that occurs at the maximum end of the pole dimension. Please see
!      Section~\ref{const:polekind} for a full list of options. If not specified,
!      the default is {\tt ESMF\_POLEKIND\_MONOPOLE} for both.
! \item[{[addCornerStagger]}]
!      Uses the information in the grid file to add the Corner stagger to
!      the Grid. The coordinates for the corner stagger is required for conservative
!      regridding. If not specified, defaults to false.
! \item[{[coordTypeKind]}]
!          The type/kind of the grid coordinate data. Only ESMF\_TYPEKIND\_R4
!          and ESMF\_TYPEKIND\_R8 are allowed.  Currently, ESMF\_TYPEKIND\_R4 is only
!          supported for the GRIDSPEC fileformat. 
!          If not specified then defaults to ESMF\_TYPEKIND\_R8.
! \item[{[addUserArea]}]
!      If .true., read in the cell area from the Grid file, otherwise, ESMF will calculate it. The feature
!      is only supported when the grid file is in the SCRIP format.  If not set, the default value is
!      .false.
! \item[{[indexflag]}]
!      Indicates the indexing scheme to be used in the new Grid. Please see
!      section~\ref{const:indexflag} for the list of options. If not present,
!      defaults to {\tt ESMF\_INDEX\_DELOCAL}.
! \item[{[addMask]}]
!      If .true., generate the mask using the missing\_value attribute defined in 'varname'.
!      This flag is only needed for the GRIDSPEC file format.  If not set, the default value is .false.
! \item[{[varname]}]
!      If addMask is true, provide a variable name stored in the grid file and
!      the mask will be generated using the missing value of the data value of
!      this variable.  The first two dimensions of the variable has to be the
!      the longitude and the latitude dimension and the mask is derived from the
!      first 2D values of this variable even if this data is 3D, or 4D array.
!\item[{[coordNames]}]
!      a two-element array containing the longitude and latitude variable names in a
!      GRIDSPEC file if there are multiple coordinates defined in the file
! \item[{[rc]}]
!      Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP

    type(ESMF_Grid) :: grid
    integer         :: localrc
    logical         :: localIsSphere, localAddCorner
    type(ESMF_Decomp_Flag) :: localDEcompFlag(2)
    type(ESMF_vm)   :: vm
    integer         :: i, PetCnt, PetNo
    integer         :: xpart, ypart, bigFac
    integer         :: xpets, ypets
    integer         :: xdim, ydim
    integer         :: srcrank
    integer, pointer:: griddims(:)
    type(ESMF_Index_Flag) :: localIndexFlag
    type(ESMF_FileFormat_Flag)  :: localFileformat
    type(ESMF_TypeKind_Flag)    :: localCoordTypeKind

    if (present(rc)) rc=ESMF_FAILURE

    call ESMF_VMGetCurrent(vm, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
                           ESMF_ERR_PASSTHRU, &
                           ESMF_CONTEXT, rcToReturn=rc)) return

    ! set up local pet info
    call ESMF_VMGet(vm, localPet=PetNo, petCount=PetCnt, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
                           ESMF_ERR_PASSTHRU, &
                           ESMF_CONTEXT, rcToReturn=rc)) return

    if (present(fileformat)) then
       localFileformat = fileformat
    else
       call ESMF_FileTypeCheck(filename, localFileformat, rc=localrc)
       if (ESMF_LogFoundError(localrc, &
              ESMF_ERR_PASSTHRU, &
              ESMF_CONTEXT, rcToReturn=rc)) return
    endif

    if (present(indexflag)) then
        localIndexFlag = indexflag
    else
        localIndexFlag = ESMF_INDEX_DELOCAL
    endif

    if (present(isSphere)) then
        localIsSphere = isSphere
    else
        localIsSphere = .true.
    endif

    if (present(addCornerStagger)) then
        localAddCorner = AddCornerStagger
    else
        localAddCorner = .false.
    endif

   ! Set Default coordTypeKind
   if (present(coordTypeKind)) then
      if (coordTypeKind .ne. ESMF_TYPEKIND_R4 .and. &
          coordTypeKind .ne. ESMF_TYPEKIND_R8) then
         call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
            msg="- only ESMF_TYPEKIND_R4 and ESMF_TYPEKIND_R8 are allowed", &
            ESMF_CONTEXT, rcToReturn=rc)
         return
      endif      
      localCoordTypeKind=coordTypeKind
   else
      localCoordTypeKind=ESMF_TYPEKIND_R8
   endif

   ! Only allow ESMF_TYPEKIND_R4 for GRIDSPEC filetye for now
   if (localCoordTypeKind .eq. ESMF_TYPEKIND_R4 .and. &
       localFileformat .ne. ESMF_FILEFORMAT_GRIDSPEC) then
       call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
          msg="- Currently coordTypeKind == ESMF_TYPEKIND_R4 is only supported for the GRIDSPEC format", &
          ESMF_CONTEXT, rcToReturn=rc)
       return
   endif

    allocate(griddims(2))
    if (PetNo == 0) then
       if (localFileformat == ESMF_FILEFORMAT_SCRIP) then
           call ESMF_ScripInq(filename, grid_dims=griddims, rc=localrc)
           if (ESMF_LogFoundError(localrc, &
                                     ESMF_ERR_PASSTHRU, &
                                     ESMF_CONTEXT, rcToReturn=rc)) return
        elseif (localFileformat == ESMF_FILEFORMAT_GRIDSPEC) then
           if (present(coordNames)) then
              call ESMF_GridspecInq(filename, srcrank, griddims, coord_names=coordNames, rc=localrc)
           else
              call ESMF_GridspecInq(filename, srcrank, griddims, rc=localrc)
           endif
           if (ESMF_LogFoundError(localrc, &
                                     ESMF_ERR_PASSTHRU, &
                                     ESMF_CONTEXT, rcToReturn=rc)) return
        elseif (localFileformat == ESMF_FILEFORMAT_TILE) then
           ! this returns the size of the center stagger, not the supergrid
           call ESMF_GridSpecQueryTileSize(filename, griddims(1),griddims(2), rc=localrc)
           if (ESMF_LogFoundError(localrc, &
                                     ESMF_ERR_PASSTHRU, &
                                     ESMF_CONTEXT, rcToReturn=rc)) return
        endif
     endif
     call ESMF_VMBroadcast(vm, griddims, 2, 0, rc=localrc)

    ! Create a decomposition such that each PET will contain at least 2 column and 2 row of data
    ! otherwise, regrid will not work
    if (PetCnt == 1) then
        xpart = 1
        ypart = 1
    else
        bigFac = 1
        do i=2, int(sqrt(float(PetCnt)))
           if ((PetCnt/i)*i == PetCnt) then
              bigFac = i
           endif
        enddo
        xpets = bigFac
        ypets = PetCnt/xpets
        if ((griddims(1) <= griddims(2) .and. xpets <= ypets) .or. &
               (griddims(1) > griddims(2) .and. xpets > ypets)) then
               xpart = xpets
               ypart = ypets
        else
               xpart = ypets
               ypart = xpets
        endif
        xdim = griddims(1)/xpart
        ydim = griddims(2)/ypart
        do while (xdim <= 1 .and. xpart>1)
              xpart = xpart-1
              xdim = griddims(1)/xpart
        enddo
        do while (ydim <= 1 .and. ypart>1)
              ypart = ypart-1
              ydim = griddims(2)/ypart
        enddo
    endif
    deallocate(griddims)

    localDEcompFlag(:) = ESMF_DECOMP_BALANCED

    if (localFileformat == ESMF_FILEFORMAT_SCRIP) then
        grid = ESMF_GridCreateFrmScrip(trim(filename), (/xpart,ypart/), &
                localIndexFlag, decompflag=localDEcompflag, &
                isSphere=localIsSphere, polekindflag=polekindflag, &
                addCornerStagger=localAddCorner, &
                addUserArea=addUserArea, rc=localrc)
    else if (localfileformat == ESMF_FILEFORMAT_GRIDSPEC .or. &
             localfileformat == ESMF_FILEFORMAT_TILE) then
        ! Right now, we call ESMF_GridCreateFrmGridspec() for both supergrid
        ! or regular CF Grid, eventually we will separate it into two routines
        ! Warning about user area in GridSpec
        if (present(addUserArea)) then
           if (addUserArea) then
              call ESMF_LogWrite("ESMF does not currently support " // &
                   "user areas in GRIDSPEC format, so user areas will " // &
                   "not be used for the GRIDSPEC file.", &
                   ESMF_LOGMSG_WARNING, rc=localrc)
              if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
                   ESMF_CONTEXT, rcToReturn=rc)) return
           endif
        endif

        if (present(addMask)) then
          grid = ESMF_GridCreateFrmGridspec(trim(filename), (/xpart,ypart/), &
                localIndexFlag, decompflag=localDEcompflag, &
                isSphere=localIsSphere, polekindflag=polekindflag, &
                addCornerStagger=localAddCorner, &
                coordTypeKind = localCoordTypeKind, &
                addMask=addMask, varname=varname, coordNames=coordNames, rc=localrc)
        else
          grid = ESMF_GridCreateFrmGridspec(trim(filename), (/xpart,ypart/), &
                localIndexFlag, decompflag=localDEcompflag, &
                isSphere=localIsSphere, polekindflag=polekindflag, &
                addCornerStagger=localAddCorner, &
                coordTypeKind = localCoordTypeKind, &
                coordNames = coordNames, rc=localrc)
        endif
    else
        call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
            msg="- The fileformat has to be either ESMF_FILEFORMAT_SCRIP or ESMF_FILEFORMAT_GRIDSPEC", &
          ESMF_CONTEXT, rcToReturn=rc)
        return
    endif
    if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
       ESMF_CONTEXT, rcToReturn=rc)) return

    ! create the final grid from intermediate grid by replacing DistGrid
    ESMF_GridCreateFrmNCFileDG = ESMF_GridCreateCopyFromNewDG(grid, distGrid, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    ! destroy the intermediate grid
    call ESMF_GridDestroy(grid, noGarbage=.true., rc=localrc)
    if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    if (present(rc)) rc=ESMF_SUCCESS
    return

end function ESMF_GridCreateFrmNCFileDG