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