AnisoMortarExchange_MappedScalar3D_t Subroutine

public subroutine AnisoMortarExchange_MappedScalar3D_t(this, mesh)

Fills the extBoundary attribute on all faces that participate in an anisotropic (2-subface) mortar interface (see mesh%anisoMortarInfo).

With s the split coordinate of the big face and h = 1,2 its halves, each small face receives the big face's trace restricted (exactly) to its half, with the 1-D mortarR(:,:,h) applied along s and the identity along the other coordinate. The big face receives the L2 projection of the two small-face traces onto its trace space, sum_h P_h u_h with mortarP(:,:,h) along s (carrying the 1/2 sub-face Jacobian). Traces are staged in anisoMortarBuff in the big face's coordinates: slots 1,2 - big-face trace, used for the external state of half 1, 2 slots 3,4 - small-face traces on halves 1, 2 Must be called after BoundaryInterp; the faces it touches are disjoint from the conforming faces and from the 2x2 mortar faces.

Arguments

TypeIntentOptionalAttributesName
class(MappedScalar3D_t), intent(inout) :: this
type(Mesh3D), intent(inout) :: mesh

Calls

proc~~anisomortarexchange_mappedscalar3d_t~~CallsGraph proc~anisomortarexchange_mappedscalar3d_t AnisoMortarExchange_MappedScalar3D_t proc~mortarfacemap MortarFaceMap proc~anisomortarexchange_mappedscalar3d_t->proc~mortarfacemap acc acc proc~anisomortarexchange_mappedscalar3d_t->acc

Contents


Source Code

  subroutine AnisoMortarExchange_MappedScalar3D_t(this,mesh)
    !! Fills the extBoundary attribute on all faces that participate in an anisotropic
    !! (2-subface) mortar interface (see mesh%anisoMortarInfo).
    !!
    !! With s the split coordinate of the big face and h = 1,2 its halves, each small
    !! face receives the big face's trace restricted (exactly) to its half, with the 1-D
    !! mortarR(:,:,h) applied along s and the identity along the other coordinate. The
    !! big face receives the L2 projection of the two small-face traces onto its trace
    !! space, sum_h P_h u_h with mortarP(:,:,h) along s (carrying the 1/2 sub-face
    !! Jacobian). Traces are staged in anisoMortarBuff in the big face's coordinates:
    !!   slots 1,2 - big-face trace, used for the external state of half 1, 2
    !!   slots 3,4 - small-face traces on halves 1, 2
    !! Must be called after BoundaryInterp; the faces it touches are disjoint from the
    !! conforming faces and from the 2x2 mortar faces.
    implicit none
    class(MappedScalar3D_t),intent(inout) :: this
    type(Mesh3D),intent(inout) :: mesh
    ! Local
    integer :: m,h,ivar,i,j,i2,j2
    integer :: eB,eS,sS,flip
    integer :: rankId,offset,N
    integer,pointer :: elemtorank(:)
    real(prec) :: extBuff(1:this%interp%N+1,1:this%interp%N+1)

    ! See https://github.com/FluidNumerics/SELF/issues/54 for the reason behind
    ! this pointer alias
    elemtorank => mesh%decomp%elemToRank(:)
    rankId = mesh%decomp%rankId
    offset = mesh%decomp%offsetElem(rankId+1)
    N = this%interp%N

    if(.not. allocated(this%anisoMortarBuff)) then
      allocate(this%anisoMortarBuff(1:N+1,1:N+1,1:4,1:mesh%nAnisoMortars,1:this%nvar))
      this%anisoMortarBuff = 0.0_prec
    endif

    if(mesh%decomp%mpiEnabled) then
      call this%MPIAnisoMortarExchangeAsync(mesh)
    endif

    ! Stage rank-local traces in the big face's coordinates
    do concurrent(m=1:mesh%nAnisoMortars,ivar=1:this%nvar)
      block
        integer :: i,j,i2,j2,h
        integer :: eB,sB,eS,sS,flip

        eB = mesh%anisoMortarInfo(1,m)
        if(elemtorank(eB) == rankId) then
          sB = mesh%anisoMortarInfo(2,m)
          do h = 1,2
            do j = 1,N+1
              do i = 1,N+1
                this%anisoMortarBuff(i,j,h,m,ivar) = this%boundary(i,j,sB,eB-offset,ivar)
              enddo
            enddo
          enddo
        endif

        do h = 1,2
          eS = mesh%anisoMortarInfo(2*h+1,m)
          if(elemtorank(eS) == rankId) then
            sS = mesh%anisoMortarInfo(2*h+2,m)/10
            flip = mesh%anisoMortarInfo(2*h+2,m)-10*sS
            do j = 1,N+1
              do i = 1,N+1
                call MortarFaceMap(i,j,N,flip,i2,j2)
                this%anisoMortarBuff(i,j,2+h,m,ivar) = this%boundary(i2,j2,sS,eS-offset,ivar)
              enddo
            enddo
          endif
        enddo
      endblock
    enddo

    if(mesh%decomp%mpiEnabled) then
      call mesh%decomp%FinalizeMPIExchangeAsync()

      ! Reorient small-face traces received over MPI into the big face's coordinates
      do ivar = 1,this%nvar
        do m = 1,mesh%nAnisoMortars
          eB = mesh%anisoMortarInfo(1,m)
          if(elemtorank(eB) == rankId) then
            do h = 1,2
              eS = mesh%anisoMortarInfo(2*h+1,m)
              sS = mesh%anisoMortarInfo(2*h+2,m)/10
              flip = mesh%anisoMortarInfo(2*h+2,m)-10*sS
              if(elemtorank(eS) /= rankId .and. flip /= 0) then
                do j = 1,N+1
                  do i = 1,N+1
                    call MortarFaceMap(i,j,N,flip,i2,j2)
                    extBuff(i,j) = this%anisoMortarBuff(i2,j2,2+h,m,ivar)
                  enddo
                enddo
                do j = 1,N+1
                  do i = 1,N+1
                    this%anisoMortarBuff(i,j,2+h,m,ivar) = extBuff(i,j)
                  enddo
                enddo
              endif
            enddo
          endif
        enddo
      enddo
    endif

    ! Compute external states :
    !  small faces get the restricted big-face trace (exact),
    !  the big face gets the L2 projection of the small-face traces
    do concurrent(m=1:mesh%nAnisoMortars,ivar=1:this%nvar)
      block
        integer :: i,j,ii,i2,j2,h,split
        integer :: eB,sB,eS,sS,flip
        real(prec) :: fm
        real(prec) :: acc(1:N+1,1:N+1)

        split = mesh%anisoMortarInfo(9,m)

        do h = 1,2
          eS = mesh%anisoMortarInfo(2*h+1,m)
          if(elemtorank(eS) == rankId) then
            sS = mesh%anisoMortarInfo(2*h+2,m)/10
            flip = mesh%anisoMortarInfo(2*h+2,m)-10*sS
            do j = 1,N+1
              do i = 1,N+1
                fm = 0.0_prec
                if(split == 1) then
                  do ii = 1,N+1
                    fm = fm+this%interp%mortarR(ii,i,h)*this%anisoMortarBuff(ii,j,h,m,ivar)
                  enddo
                else
                  do ii = 1,N+1
                    fm = fm+this%interp%mortarR(ii,j,h)*this%anisoMortarBuff(i,ii,h,m,ivar)
                  enddo
                endif
                call MortarFaceMap(i,j,N,flip,i2,j2)
                this%extBoundary(i2,j2,sS,eS-offset,ivar) = fm
              enddo
            enddo
          endif
        enddo

        eB = mesh%anisoMortarInfo(1,m)
        if(elemtorank(eB) == rankId) then
          sB = mesh%anisoMortarInfo(2,m)
          acc = 0.0_prec
          do h = 1,2
            do j = 1,N+1
              do i = 1,N+1
                fm = 0.0_prec
                if(split == 1) then
                  do ii = 1,N+1
                    fm = fm+this%interp%mortarP(ii,i,h)*this%anisoMortarBuff(ii,j,2+h,m,ivar)
                  enddo
                else
                  do ii = 1,N+1
                    fm = fm+this%interp%mortarP(ii,j,h)*this%anisoMortarBuff(i,ii,2+h,m,ivar)
                  enddo
                endif
                acc(i,j) = acc(i,j)+fm
              enddo
            enddo
          enddo
          do j = 1,N+1
            do i = 1,N+1
              this%extBoundary(i,j,sB,eB-offset,ivar) = acc(i,j)
            enddo
          enddo
        endif
      endblock
    enddo

  endsubroutine AnisoMortarExchange_MappedScalar3D_t