FaceNeighbor_OctreeMesh3D Subroutine

public recursive subroutine FaceNeighbor_OctreeMesh3D(this, node, s, nbr, ns, nf)

Find the equal-or-larger face neighbour of node across its local face s using the classic octree ascend/descend search. Returns: nbr - neighbour node id (0 = physical domain boundary). It is either a LEAF at any level <= level(node), or an INTERNAL node at exactly level(node) (meaning the shared face is subdivided on the neighbour side, i.e. finer neighbours exist). ns - the neighbour's local face that faces node. nf - the flip between the two shared faces (0..7, sideInfo(4) convention), inherited from the base-mesh face where the search crosses a root boundary. With this, a 2:1 hanging face is exactly "nbr is a leaf with level(nbr) = level(node)-1", and finer neighbours are exactly "nbr is internal".

Arguments

TypeIntentOptionalAttributesName
class(OctreeMesh3D), intent(in) :: this
integer, intent(in) :: node
integer, intent(in) :: s
integer, intent(out) :: nbr
integer, intent(out) :: ns
integer, intent(out) :: nf

Calls

proc~~faceneighbor_octreemesh3d~~CallsGraph proc~faceneighbor_octreemesh3d FaceNeighbor_OctreeMesh3D proc~faceneighbor_octreemesh3d->proc~faceneighbor_octreemesh3d proc~oc_internal oc_internal proc~faceneighbor_octreemesh3d->proc~oc_internal proc~oc_subpos oc_subpos proc~faceneighbor_octreemesh3d->proc~oc_subpos proc~oc_opposite oc_opposite proc~faceneighbor_octreemesh3d->proc~oc_opposite proc~oc_reflect oc_reflect proc~faceneighbor_octreemesh3d->proc~oc_reflect

Contents


Source Code

  recursive subroutine FaceNeighbor_OctreeMesh3D(this,node,s,nbr,ns,nf)
    !! Find the equal-or-larger face neighbour of `node` across its local face s using the
    !! classic octree ascend/descend search. Returns:
    !!   nbr - neighbour node id (0 = physical domain boundary). It is either a LEAF at
    !!         any level <= level(node), or an INTERNAL node at exactly level(node)
    !!         (meaning the shared face is subdivided on the neighbour side, i.e. finer
    !!         neighbours exist).
    !!   ns  - the neighbour's local face that faces `node`.
    !!   nf  - the flip between the two shared faces (0..7, sideInfo(4) convention),
    !!         inherited from the base-mesh face where the search crosses a root boundary.
    !! With this, a 2:1 hanging face is exactly "nbr is a leaf with level(nbr) =
    !! level(node)-1", and finer neighbours are exactly "nbr is internal".
    implicit none
    class(OctreeMesh3D),intent(in) :: this
    integer,intent(in) :: node,s
    integer,intent(out) :: nbr,ns,nf
    ! Local
    integer :: p,c,pnbr,ps,pf,t,tq

    if(this%level(node) == 0) then
      ! Cross a base-mesh face: neighbour root, its face, and the base flip.
      nbr = this%rootNbr(s,this%rootElem(node))
      ns = this%rootNbrSide(s,this%rootElem(node))
      nf = this%rootFlip(s,this%rootElem(node))
      return
    endif

    p = this%parent(node)
    c = this%octant(node)

    if(oc_internal(s,c)) then
      ! Neighbour is the sibling on the other side of an interior face of the parent.
      nbr = this%child(oc_reflect(s,c),p)
      ns = oc_opposite(s)
      nf = 0
      return
    endif

    ! Otherwise ascend: find the parent's neighbour across the same face, then descend.
    call FaceNeighbor_OctreeMesh3D(this,p,s,pnbr,ps,pf)
    if(pnbr == 0) then
      nbr = 0
      ns = 0
      nf = 0
      return
    endif

    if(this%child(1,pnbr) == 0) then
      ! Parent's neighbour is a leaf (equal or larger than the parent) -> our larger
      ! neighbour.
      nbr = pnbr
      ns = ps
      nf = pf
      return
    endif

    ! Parent's neighbour is internal (at level(node)-1): descend one level to the child
    ! that borders `node`, matching face quadrants across the face through the flip.
    t = oc_subpos(c,s)
    tq = faceQuadPerm(t,pf)
    nbr = this%child(childOfFace(tq,ps),pnbr)
    ns = ps
    nf = pf

  endsubroutine FaceNeighbor_OctreeMesh3D