function ESMF_LocStreamCreateFromFile(filename, keywordEnforcer, &
fileformat, varname, indexflag, centerflag, name, rc)
!
! !RETURN VALUE:
type(ESMF_LocStream) :: ESMF_LocStreamCreateFromFile
!
! !ARGUMENTS:
character (len=*), intent(in) :: filename
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
type(ESMF_FileFormat_Flag), intent(in), optional :: fileformat
character(len=*), intent(in), optional :: varname
type(ESMF_Index_Flag), intent(in), optional :: indexflag
logical, intent(in), optional :: centerflag
character (len=*), intent(in), optional :: name
integer, intent(out),optional :: rc
! !DESCRIPTION:
! Create a new {\tt ESMF\_LocStream} object and add the coordinate keys and mask key
! to the LocStream using the coordinates defined in a grid file. Currently, it
! supports the SCRIP format, the ESMF unstructured grid format and the UGRID format.
! For a 2D or 3D grid in ESMF or UGRID format, it can construct the LocStream using either
! the center coordinates or the corner coordinates. For a SCRIP format grid file, the
! LocStream can only be constructed using the center coordinates. In
! addition, it supports 1D network topology in UGRID format. When
! construction a LocStream using a 1D UGRID, it always uses node
! coordinates (i.e., corner coordinates).
!
! The arguments are:
! \begin{description}
! \item[filename]
! Name of grid file to be used to create the location stream.
! \item[{[fileformat]}]
! The file format. The valid options are {\tt ESMF\_FILEFORMAT\_SCRIP},
! {\tt ESMF\_FILEFORMAT\_ESMFMESH}, and {\tt ESMF\_FILEFORMAT\_UGRID}.
! Please see section~\ref{const:fileformatflag} for a detailed description of the options.
! If not specified, the default is {\tt ESMF\_FILEFORMAT\_SCRIP}.
! \item[{[varname]}]
! An optional variable name stored in the UGRID file to be used to
! generate the mask 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. If not
! specified, no mask is used for a UGRID file.
! \item[{[indexflag]}]
! Flag that indicates how the DE-local indices are to be defined.
! Defaults to {\tt ESMF\_INDEX\_DELOCAL}, which indicates
! that the index range on each DE starts at 1. See Section~\ref{const:indexflag}
! for the full range of options.
! \item[{[centerflag]}]
! Flag that indicates whether to use the center coordinates to construct the location stream.
! If true, use center coordinates, otherwise, use the corner coordinates. If not specified,
! use center coordinates as default. For SCRIP files, only center coordinate
! is supported.
! \item[{[name]}]
! Name of the location stream
! \item[{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
#ifdef ESMF_NETCDF
integer :: totalpoints,totaldims
type(ESMF_VM) :: vm
integer :: numDim, buf(1), msgbuf(3)
integer :: localrc
integer :: PetNo, PetCnt
type(ESMF_Index_Flag) :: indexflagLocal
real(ESMF_KIND_R8), pointer :: coordX(:), coordY(:), coordZ(:)
real(ESMF_KIND_R8), pointer :: coord2D(:,:), varbuffer(:)
integer(ESMF_KIND_I4), pointer :: imask(:)
integer :: starti, count, localcount, index
integer :: remain, i
integer :: meshid
real(ESMF_KIND_R8) :: missingvalue
type(ESMF_CoordSys_Flag) :: coordSys
type(ESMF_LocStream) :: locStream
type(ESMF_FileFormat_Flag) :: localfileformat
logical :: localcenterflag, haveface
character(len=16) :: units, location
if (present(indexflag)) then
indexflagLocal=indexflag
else
indexflagLocal=ESMF_INDEX_DELOCAL
endif
if (present(fileformat)) then
localfileformat = fileformat
else
localfileformat = ESMF_FILEFORMAT_SCRIP
endif
if (present(centerflag)) then
localcenterflag = centerflag
else
localcenterflag = .TRUE.
endif
if (localcenterflag) then
location = 'face'
else
location = 'node'
endif
if (localfileformat == ESMF_FILEFORMAT_GRIDSPEC) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
msg="Create LocStream from a GRIDSPEC file is not supported.", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
if ( localfileformat == ESMF_FILEFORMAT_SCRIP .and. &
.NOT. localcenterflag) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
msg="Only allow center coordinates if the file is in SCRIP format", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
#if 0
if (localfileformat /= ESMF_FILEFORMAT_UGRID .and. &
(present(meshname) .or. present(varname))) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
msg="Only UGRID file need the optional arguments meshname or varname", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
#endif
! Initialize return code; assume failure until success is certain
localrc = ESMF_RC_NOT_IMPL
if (present(rc)) rc = ESMF_RC_NOT_IMPL
! get global vm information
!
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 (localfileformat == ESMF_FILEFORMAT_SCRIP) then
! totaldims represent grid_ranks in SCRIP - 1 for unstructured and
! 2 for logically rectangular
call ESMF_ScripInq(filename, grid_rank=totaldims, &
grid_size=totalpoints, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
call ESMF_ScripInqUnits(filename, units=units, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
if (units == 'degrees') then
coordSys = ESMF_COORDSYS_SPH_DEG
else
coordSys = ESMF_COORDSYS_SPH_RAD
endif
#if 0
elseif (localfileformat == ESMF_FILEFORMAT_GRIDSPEC) then
! totaldims is the dimension of the lat/lon variable: 1 for regular
! grid and 2 for curvilinear
call ESMF_GridspecInq(filename, ndims=totaldims, &
grid_dims = grid_dims, &
coordids=varids, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
totalpoints=grid_dims(1)*grid_dims(2)
#endif
elseif (localfileformat == ESMF_FILEFORMAT_ESMFMESH) then
! totaldims is the coordDim, 2 for 2D and 3 for 3D
if (localcenterflag) then
call ESMF_EsmfInq(filename, elementCount=totalpoints, &
coordDim=totaldims, rc=localrc)
else
call ESMF_EsmfInq(filename, nodeCount=totalpoints, &
coordDim=totaldims, rc=localrc)
endif
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
call ESMF_EsmfInqUnits(filename, units, rc=localrc)
if (units == 'degrees') then
coordSys = ESMF_COORDSYS_SPH_DEG
elseif (units == 'radians') then
coordSys = ESMF_COORDSYS_SPH_RAD
else
coordSys = ESMF_COORDSYS_CART
endif
elseif (localfileformat == ESMF_FILEFORMAT_UGRID) then
! totaldims is the mesh_dimension (2 for 2D and 3 for 3D)
if (localcenterflag) then
call ESMF_UGridInq(filename, elementCount=totalpoints, &
meshid=meshid, nodeCoordDim=totaldims, &
faceCoordFlag=haveface, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
if (totaldims == 1) then
call ESMF_LogSetError(rcToCheck=ESMF_FAILURE, &
msg="1D grid does not have face coordinates", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
if (.not. haveface) then
call ESMF_LogSetError(rcToCheck=ESMF_FAILURE, &
msg="The grid file does not have face coordinates", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
else
call ESMF_UGridInq(filename, nodeCount=totalpoints, &
meshid=meshid, nodeCoordDim=totaldims, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
endif
coordSys = ESMF_COORDSYS_SPH_DEG
endif
localcount = totalpoints/PetCnt
remain = totalpoints - (localcount*PetCnt)
if (PetNo < remain) then
localcount = localcount+1
starti = localcount*PetNo+1
else
starti = localcount*PetNo+1+remain
endif
allocate(coordX(localcount), coordY(localcount),imask(localcount))
if (localcount > 0) then
if (localfileformat == ESMF_FILEFORMAT_SCRIP) then
call ESMF_ScripGetVar(filename, grid_center_lon=coordX, grid_center_lat=coordY, &
grid_imask=imask, start=starti, count=localcount, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
#if 0
elseif (localfileformat == ESMF_FILEFORMAT_GRIDSPEC) then
if (totaldims == 1) then
call ESMF_GridspecGetVar1D(filename, varids, coordX, coordY, rc=localrc)
!construct 2D arrays and do the distribution
xdim=size(coordX)
ydim=size(coordY)
#endif
elseif (localfileformat == ESMF_FILEFORMAT_ESMFMESH) then
allocate(coord2D(totaldims,localcount))
call ESMF_EsmfGetCoords(filename, coord2D, imask, &
starti, localcount, localcenterflag, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
coordX(:) = coord2D(1,:)
coordY(:) = coord2D(2,:)
if (totaldims == 3) then
allocate(coordZ(localcount))
coordZ(:) = coord2D(3,:)
endif
deallocate(coord2D)
elseif (localfileformat == ESMF_FILEFORMAT_UGRID) then
if (totaldims == 1) then
allocate(coord2D(localcount, 2))
else
allocate(coord2D(localcount, totaldims))
endif
call ESMF_UGridGetCoords(filename, meshid, coord2D, &
starti, localcount, localcenterflag, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
coordX(:) = coord2D(:,1)
coordY(:) = coord2D(:,2)
if (totaldims == 3) then
allocate(coordZ(localcount))
coordZ(:) = coord2D(:,3)
endif
deallocate(coord2D)
! Get mask from varname
imask(:)=1
if (present(varname)) then
allocate(varbuffer(localcount))
call ESMF_UGridGetVarByName(filename, varname, varbuffer, &
startind=starti, count=localcount, &
location=location, &
missingvalue=missingvalue, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
do i=1,localcount
if (varbuffer(i)==missingvalue) imask(i)=0
enddo
deallocate(varbuffer)
endif
endif
endif
! create Location Stream
locStream = ESMF_LocStreamCreate(name=name, localcount=localcount, indexflag=indexflagLocal,&
coordSys = coordSys, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
!print *, PetNo, starti, localcount, coordX(1), coordY(1)
! Add coordinate keys based on coordSys
if ((coordSys == ESMF_COORDSYS_SPH_DEG) .or. (coordSys == ESMF_COORDSYS_SPH_RAD)) then
call ESMF_LocStreamAddKey(locStream, 'ESMF:Lon',coordX, keyUnits=units, &
keyLongName='Longitude', &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
call ESMF_LocStreamAddKey(locStream, 'ESMF:Lat',coordY, keyUnits=units, &
keyLongName='Latitude', &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
!If 3D grid, add the height coordinates
if (totaldims == 3) then
if (localcount == 0) allocate(coordZ(localcount))
call ESMF_LocStreamAddKey(locStream, 'ESMF:Radius',coordZ, &
keyUnits='radius', &
keyLongName='Height', &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
deallocate(coordZ)
endif
else if (coordSys == ESMF_COORDSYS_CART) then
call ESMF_LocStreamAddKey(locStream, 'ESMF:X',coordX, keyUnits=units, &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
call ESMF_LocStreamAddKey(locStream, 'ESMF:Y',coordY, keyUnits=units, &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
!If 3D grid, add the height coordinates
if (totaldims == 3) then
if (localcount == 0) allocate(coordZ(localcount))
call ESMF_LocStreamAddKey(locStream, 'ESMF:Z',coordZ, &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
deallocate(coordZ)
endif
else
call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_BAD, &
msg="Unrecognized coordinate system.", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
!Add mask key
call ESMF_LocStreamAddKey(locStream, 'ESMF:Mask',imask, &
keyLongName='Mask', &
datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! local garbage collection
deallocate(coordX, coordY, imask)
ESMF_LocStreamCreateFromFile = locStream
if (present(rc)) rc=ESMF_SUCCESS
return
#else
if (present(rc)) rc = ESMF_RC_LIB_NOT_PRESENT
#endif
end function ESMF_LocStreamCreateFromFile