subroutine ESMF_MeshAddElements(mesh, elementIds, elementTypes, &
elementConn, elementMask, elementArea, elementCoords, &
elementDistgrid, rc)
!
! !ARGUMENTS:
type(ESMF_Mesh), intent(inout) :: mesh
integer, intent(in) :: elementIds(:)
integer, intent(in) :: elementTypes(:)
integer, intent(in) :: elementConn(:)
integer, intent(in), optional :: elementMask(:)
real(ESMF_KIND_R8), intent(in), optional :: elementArea(:)
real(ESMF_KIND_R8), intent(in), optional :: elementCoords(:)
type(ESMF_DistGrid), intent(in), optional :: elementDistgrid
integer, intent(out), optional :: rc
!
! !DESCRIPTION:
! This call is the third and last part of the three part mesh create
! sequence and should be called after the mesh is created with {\tt ESMF\_MeshCreate()}
! (\ref{sec:mesh:api:meshcreate})
! and after the nodes are added with {\tt ESMF\_MeshAddNodes()} (\ref{sec:mesh:api:meshaddnodes}).
! This call adds the elements to the
! mesh and finalizes the create. After this call the Mesh is usable, for
! example a Field may be built on the created Mesh object and
! this Field may be used in a {\tt ESMF\_FieldRegridStore()} call.
!
! The parameters to this call {\tt elementIds}, {\tt elementTypes}, and
! {\tt elementConn} describe the elements to be created. The description
! for a particular element lies at the same index location in {\tt elementIds}
! and {\tt elementTypes}. Each entry in {\tt elementConn} consists of the list of
! nodes used to create that element, so the connections for element $e$ in the
! {\tt elementIds} array will start at $number\_of\_nodes\_in\_element(1) + number\_of\_nodes\_in\_element(2) +
! \cdots + number\_of\_nodes\_in\_element(e-1) + 1$ in {\tt elementConn}.
!
! This call is {\em collective} across the current VM.
!
! \begin{description}
! \item [elementIds]
! An array containing the global ids of the elements to be created on this PET.
! This input consists of a 1D array the size of the number of elements on this PET.
! Each element id must be a number equal to or greater than 1. An id should be
! unique in the sense that different elements must have different ids (the same element
! that appears on different processors must have the same id). There may be gaps in the sequence
! of ids, but if these gaps are the same scale as the length of the sequence it can lead to
! inefficiencies when the Mesh is used (e.g. in {\tt ESMF\_FieldRegridStore()}).
! \item[elementTypes]
! An array containing the types of the elements to be created on this PET. The types used
! must be appropriate for the parametric dimension of the Mesh. Please see
! Section~\ref{const:meshelemtype} for the list of options. This input consists of
! a 1D array the size of the number of elements on this PET.
! \item[elementConn]
! An array containing the indexes of the sets of nodes to be connected together to form the
! elements to be created on this PET. The entries in this list are NOT node global ids,
! but rather each entry is a local index (1 based) into the list of nodes which were
! created on this PET by the previous {\tt ESMF\_MeshAddNodes()} call.
! In other words, an entry of 1 indicates that this element contains the node
! described by {\tt nodeIds(1)}, {\tt nodeCoords(1)}, etc. passed into the
! {\tt ESMF\_MeshAddNodes()} call on this PET. It is also
! important to note that the order of the nodes in an element connectivity list
! matters. Please see Section~\ref{const:meshelemtype} for diagrams illustrating
! the correct order of nodes in a element. This input consists of a 1D array with
! a total size equal to the sum of the number of nodes in each element on
! this PET. The number of nodes in each element is implied by its element type in
! {\tt elementTypes}. The nodes for each element
! are in sequence in this array (e.g. the nodes for element 1 are elementConn(1),
! elementConn(2), etc.).
! \item [{[elementMask]}]
! An array containing values which can be used for element masking. Which values indicate
! masking are chosen via the {\tt srcMaskValues} or {\tt dstMaskValues} arguments to
! {\tt ESMF\_FieldRegridStore()} call. This input consists of a 1D array the
! size of the number of elements on this PET.
! \item [{[elementArea]}]
! An array containing element areas. If not specified, the element areas are internally calculated.
! This input consists of a 1D array the size of the number of elements on this PET.
! {\bf NOTE:} ESMF doesn't currently do unit conversion on areas. If these areas are going to be used
! in a process that also involves the areas of another Grid or Mesh (e.g. conservative regridding), then
! it is the user's responsibility to make sure that the area units are consistent between the two sides.
! If ESMF calculates an area on the surface of a sphere, then it is in units of square radians. If
! it calculates the area for a Cartesian grid, then it is in the same units as the coordinates, but squared.
! \item[{[elementCoords]}]
! An array containing the physical coordinates of the elements to be created on this
! PET. This input consists of a 1D array the size of the number of elements on this PET times the Mesh's
! spatial dimension. The coordinates in this array are ordered
! so that the coordinates for an element lie in sequence in memory. (e.g. for a
! Mesh with spatial dimension 2, the coordinates for element 1 are in elementCoords(1) and
! elementCoords(2), the coordinates for element 2 are in elementCoords(3) and elementCoords(4),
! etc.).
! \item [{[elementDistgrid]}]
! If present, use this as the element Distgrid for the Mesh.
! The passed in Distgrid
! needs to contain a local set of sequence indices matching the set of local element ids (i.e. those in {\tt elementIds}).
! However, specifying an externally created Distgrid gives the user more control over aspects of
! the Distgrid containing those sequence indices (e.g. how they are broken into DEs).
! If not present, a 1D Distgrid will be created internally consisting of one DE per PET.
! \item [{[rc]}]
! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
! \end{description}
!
!EOP
!------------------------------------------------------------------------------
integer :: localrc
type(ESMF_Logical) :: isfree
type(ESMF_MeshStatus_Flag) :: status
integer :: sdim, pdim
integer :: numNode, numElem
type(ESMF_CoordSys_Flag):: coordSys
integer :: num_elems, num_elementConn
type(ESMF_InterArray) :: elementMaskII
real(ESMF_KIND_R8) :: tmpArea(2)
integer :: areaPresent
real(ESMF_KIND_R8) :: tmpCoords(2)
integer :: coordsPresent
! initialize return code; assume routine not implemented
localrc = ESMF_RC_NOT_IMPL
if (present(rc)) rc = ESMF_RC_NOT_IMPL
! Check init status of arguments
ESMF_INIT_CHECK_DEEP(ESMF_MeshGetInit, mesh, rc)
ESMF_INIT_CHECK_DEEP(ESMF_DistgridGetInit, elementDistgrid, rc)
call C_ESMC_MeshGetIsFree(mesh, isfree)
if (isfree == ESMF_TRUE) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_WRONG, &
msg="- the mesh internals have been freed", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! If we're at the wrong stage then complain
call C_ESMC_MeshGetStatus(mesh, status)
if (status .ne. ESMF_MESHSTATUS_NODESADDED) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_OBJ_WRONG, &
msg="- MeshAddNodes() should be called before this", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
! get sizes of lists
num_elems = size(elementIds)
num_elementConn = size(elementConn)
call C_ESMC_MeshGetDimensions(mesh, sdim, pdim, coordSys, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! If present make sure that elementCoords has the correct size
if (present(elementCoords)) then
if (size(elementCoords) .ne. sdim*num_elems) then
call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_WRONG, &
msg="- elementCoords input array is the wrong size.", &
ESMF_CONTEXT, rcToReturn=rc)
return
endif
endif
! Create interface int to wrap optional element mask
elementMaskII = ESMF_InterArrayCreate(elementMask, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! set element area if it's present.
if (present(elementCoords)) then
if (present(elementArea)) then
areaPresent=1
coordsPresent=1
call C_ESMC_MeshAddElements(mesh%this, num_elems, &
elementIds, elementTypes, elementMaskII, &
areaPresent, elementArea, &
coordsPresent, elementCoords, &
num_elementConn, elementConn, &
coordSys, sdim, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
else
areaPresent=0
coordsPresent=1
call C_ESMC_MeshAddElements(mesh%this, num_elems, &
elementIds, elementTypes, elementMaskII, &
areaPresent, tmpArea, &
coordsPresent, elementCoords, &
num_elementConn, elementConn, &
coordSys, sdim, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
endif
else
if (present(elementArea)) then
areaPresent=1
coordsPresent=0
call C_ESMC_MeshAddElements(mesh%this, num_elems, &
elementIds, elementTypes, elementMaskII, &
areaPresent, elementArea, &
coordsPresent, tmpCoords, &
num_elementConn, elementConn, &
coordSys, sdim, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
else
areaPresent=0
coordsPresent=0
call C_ESMC_MeshAddElements(mesh%this, num_elems, &
elementIds, elementTypes, elementMaskII, &
areaPresent, tmpArea, &
coordsPresent, tmpCoords, &
num_elementConn, elementConn, &
coordSys, sdim, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
endif
endif
! create node distgrid if it hasn't been set in ESMF_MeshAddNodes()
call C_ESMC_MeshCreateNodeDistGrid(mesh, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! Set Element Distgrid
if (.not. present(elementDistgrid)) then
call C_ESMC_MeshCreateElemDistGrid(mesh, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
else
call C_ESMC_MeshSetElemDistGrid(mesh, elementDistgrid, localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
endif
! Get rid of interface Int wrapper
call ESMF_InterArrayDestroy(elementMaskII, rc=localrc)
if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
ESMF_CONTEXT, rcToReturn=rc)) return
! Change status
call C_ESMC_MeshSetStatus(mesh, ESMF_MESHSTATUS_COMPLETE)
if (present (rc)) rc = localrc
end subroutine ESMF_MeshAddElements