Check for neighboring elements to a given point.
This routine can be used to find close by elements for points that just lie outside the domain and for which values can be extrapolated, though they do not strictly reside in the computational domain described by inTree. The closest neighboring element is identified globally and added to the map2global if any is found. This only works for points, and none of the points in the given list should have been found inside the domain.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(tem_canonicalND_type), | intent(in) | :: | me(:) |
canonicalND objects to check, only points will be considered |
||
type(treelmesh_type), | intent(in) | :: | inTree |
Global tree |
||
integer, | intent(inout) | :: | countElems(globalMaxLevels) |
How many elements there will be for each level in the track |
||
type(dyn_intarray_type), | intent(inout) | :: | map2global |
growing array for the map2global |
subroutine tem_cano_checkNeigh(me, inTree, countElems, map2global)
! --------------------------------------------------------------------------
!> canonicalND objects to check, only points will be considered
type(tem_canonicalND_type ),intent(in) :: me(:)
!> Global tree
type(treelmesh_type), intent(in) :: inTree
!> How many elements there will be for each level in the track
integer, intent( inout ) :: countElems( globalMaxLevels )
!> growing array for the map2global
type(dyn_intArray_type), intent(inout) :: map2global
! --------------------------------------------------------------------------
integer :: iCano, tLevel, elemPos, dPos, maxLevel, iQQN
integer :: closest_neigh(size(me))
logical :: wasAdded
integer :: coordOfId(4)
integer :: nCanoNDs
integer :: iError
integer(kind=long_k) :: treeID, tOffset, neighID
integer :: minproc(size(me))
real(kind=rk) :: mindist(size(me)), dist
real(kind=rk) :: minglobdist(size(me))
real(kind=rk) :: elemcenter(3)
! --------------------------------------------------------------------------
maxLevel = inTree%global%maxLevel
mindist = huge(dist)
closest_neigh = 0
nCanoNDs = size(me)
! Create subTree by intersecting canoND objects with the inTree
do iCano=1,nCanoNDs
if (trim(me(iCano)%kind) == 'point') then
treeID = tem_IdOfCoord( tem_CoordOfReal(inTree, &
& me(iCano)%point%coord(1:3), &
& maxLevel) )
! add a neighbor element of this point if any of the neighbor exist to
! interpolate to a point
coordOfId = tem_CoordOfId( treeID )
tOffset = tem_FirstIdAtLevel( coordOfId(4) )
directionLoop: do iQQN = 1, qQQQ
neighID = tem_IdOfCoord( &
& [ coordOfId(1) + qOffset( iQQN, 1 ), &
& coordOfId(2) + qOffset( iQQN, 2 ), &
& coordOfId(3) + qOffset( iQQN, 3 ), &
& coordOfId(4) ], tOffset)
elemPos = tem_PosOfId(neighID, inTree%treeID)
if (elemPos > 0) then
elemcenter = tem_BaryOfId(inTree, neighID)
dist = sqrt( (me(iCano)%point%coord(1) - elemcenter(1))**2 &
& + (me(iCano)%point%coord(2) - elemcenter(2))**2 &
& + (me(iCano)%point%coord(3) - elemcenter(3))**2 )
if (dist < mindist(iCano)) then
mindist(iCano) = dist
closest_neigh(iCano) = elemPos
else if (dist <= mindist(iCano)) then
! Make sure to pick the first element in the SFC ordering
! as the nearest neighbor, if there are multiple with the
! same distance (<= comparison to avoid == comparison for
! reals)
closest_neigh(iCano) = min(elemPos, closest_neigh(iCano))
end if
end if
end do directionLoop
end if
end do
call MPI_Allreduce( mindist, minglobdist, nCanoNDs, &
& rk_mpi, MPI_MIN, inTree%global%comm, iError )
minproc = inTree%global%nParts
do iCano=1,nCanoNDs
if ( minglobdist(iCano) < huge(dist) ) then
if ( mindist(iCano) <= minglobdist(iCano) ) then
minproc(iCano) = inTree%global%myPart
end if
end if
end do
call MPI_Allreduce( MPI_IN_PLACE, minproc, nCanoNDs, &
& MPI_INTEGER, MPI_MIN, inTree%global%comm, iError )
do iCano=1,nCanoNDs
if (trim(me(iCano)%kind) == 'point') then
found_elem: if (minproc(iCano) == inTree%global%myPart) then
! append the position in inTree to the map (note that already existing
! ones are omitted)
call append( me = map2global, &
& pos = dpos, &
& val = closest_neigh(iCano), &
& wasAdded = wasAdded )
! Count up if it was added
if (wasAdded) then
tLevel = tem_levelOf( inTree%treeID(closest_neigh(iCano)) )
countElems( tLevel ) = countElems( tLevel ) + 1
end if ! wasAdded
end if found_elem
end if
end do
end subroutine tem_cano_checkNeigh