subroutine ESMF_FieldValidate(field, keywordEnforcer, rc)
!
! !ARGUMENTS:
type(ESMF_Field), intent(in) :: field
type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below
integer, intent(out), optional :: rc
!
! !STATUS:
! \begin{itemize}
! \item\apiStatusCompatibleVersion{5.2.0r}
! \end{itemize}
!
! !DESCRIPTION:
! Validates that the {\tt field} is internally consistent.
! Currently this method determines if the {\tt field} is uninitialized
! or already destroyed. It validates the contained array and grid objects.
! The code also checks if the array and grid sizes agree.
! This check compares the distgrid contained in array and grid;
! then it proceeds to compare the computational bounds contained
! in array and grid.
!
! The method returns an error code if problems are found.
!
! The arguments are:
! \begin{description}
! \item [field]
! {\tt ESMF\_Field} to validate.
! \item [{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if the {\tt field}
! is valid.
! \end{description}
!
!EOP
integer :: localrc
type(ESMF_FieldType), pointer :: ftypep
integer :: exclLBounds(ESMF_MAXDIM) ! exclusive grid lower bounds
integer :: exclUBounds(ESMF_MAXDIM) ! exclusive grid upper bounds
integer :: gridrank, arrayrank, gridrank_norep
integer :: i, lDE ! helper variables to verify bounds
integer :: localDECount, dimCount ! and distgrid
integer, allocatable :: distgridToGridMap(:)
integer, allocatable :: distgridToPackedArrayMap(:)
integer, allocatable :: arrayCompUBnd(:, :), arrayCompLBnd(:, :)
type(ESMF_DistGrid) :: arrayDistGrid, gridDistGrid
type(ESMF_GridDecompType) :: decompType
type(ESMF_GeomType_Flag) :: geomtype
type(ESMF_Grid) :: grid
type(ESMF_Status) :: basestatus
! Initialize
localrc = ESMF_RC_NOT_IMPL
if (present(rc)) rc = ESMF_RC_NOT_IMPL
! check variables
ESMF_INIT_CHECK_DEEP(ESMF_FieldGetInit,field,rc)
if (.not.associated(field%ftypep)) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Uninitialized or already destroyed Field: ftypep unassociated", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
ftypep => field%ftypep
! make sure the field is ready before trying to look at contents
call ESMF_BaseGetStatus(ftypep%base, basestatus, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
if (basestatus .ne. ESMF_STATUS_READY) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Uninitialized or already destroyed Field: fieldstatus not ready", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! make sure there is a grid before asking it questions.
if (ftypep%status .eq. ESMF_FIELDSTATUS_GRIDSET .or. &
ftypep%status .eq. ESMF_FIELDSTATUS_COMPLETE) then
call ESMF_GeomValidate(ftypep%geom, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! get the grid decomp type if geom is grid
decompType = ESMF_GRID_NONARBITRARY
call ESMF_GeomGet(ftypep%geom, geomtype=geomtype, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
if (geomtype .eq. ESMF_GEOMTYPE_GRID) then
call ESMF_GeomGet(ftypep%geom, grid=grid, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
call ESMF_GridGetDecompType(grid, decompType, rc=localrc)
if (ESMF_LogFoundError(localrc, &
ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
endif
! get grid dim and extents for the local piece
call ESMF_GeomGet(ftypep%geom, dimCount=gridrank, &
distgrid=gridDistGrid, localDECount=localDECount, rc=localrc)
if (localrc .ne. ESMF_SUCCESS) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Cannot retrieve distgrid, gridrank, localDECount from ftypep%grid", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! Bounds only valid if there are local DE's
do lDE=0, localDECount-1
call ESMF_GeomGetPLocalDe(ftypep%geom, localDE=lDE, &
exclusiveLBound=exclLBounds, &
exclusiveUBound=exclUBounds, &
rc=localrc)
if (localrc .ne. ESMF_SUCCESS) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Cannot retrieve exclusive bounds from ftypep%grid", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
enddo
endif
! make sure there is data before asking it questions.
if (ftypep%status .eq. ESMF_FIELDSTATUS_COMPLETE) then
call ESMF_ArrayValidate(array=ftypep%array, rc=localrc)
if (localrc .ne. ESMF_SUCCESS) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Cannot validate ftypep%array", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
call ESMF_ArrayGet(ftypep%array, dimCount=dimCount, localDECount=localDECount, &
distgrid=arrayDistGrid, rank=arrayrank, rc=localrc)
if (localrc .ne. ESMF_SUCCESS) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Cannot retrieve dimCount, localDECount, arrayDistGrid, arrayrank from ftypep%array", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! Verify the distgrids in array and grid match.
if(ESMF_DistGridMatch(gridDistGrid, arrayDistGrid, rc=localrc) &
< ESMF_DISTGRIDMATCH_EXACT) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="grid DistGrid does not match array DistGrid", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! cannot use distgridToGridMap to index arrayCompBnds and compare with
! gridCompBnds, skip the check for arb. array for now, need to figure
! out how to validate -- P.Li
if (decompType .eq. ESMF_GRID_NONARBITRARY) then
! Verify that array rank is greater than or equal to grid rank + ungridded bound rank
allocate(distgridToPackedArrayMap(dimCount))
call ESMF_ArrayGet(ftypep%array, &
distgridToPackedArrayMap=distgridToPackedArrayMap, &
rc=localrc)
if (localrc .ne. ESMF_SUCCESS) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="Cannot retrieve distgridToPackedArrayMap from ftypep%array", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! Verify that array rank is greater than or equal to grid rank + ungridded bound rank
gridrank_norep = gridrank
do i = 1, dimCount
if( distgridToPackedArrayMap(i) == 0) gridrank_norep = gridrank_norep - 1
enddo
if ( arrayrank .lt. gridrank_norep) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_BAD, &
msg="grid rank + ungridded Bound rank not equal to array rank", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
deallocate(distgridToPackedArrayMap)
endif
endif ! skip for arbitrary grid case
if (present(rc)) rc = ESMF_SUCCESS
end subroutine ESMF_FieldValidate