DoubleMortarMesh_Mesh2D_t Subroutine

public subroutine DoubleMortarMesh_Mesh2D_t(this, dx, bcids)

Create a six-element mesh with two 2:1 mortar interfaces, used to validate the mortar machinery in configurations the SimpleMortarMesh cannot reach:

 y = 4*dx  ______________ ______
          |              | e6 R |   R : element 6 is rotated 180 degrees, so
          |     e2       |______|       its side facing e2 has flip = 1, and
          |              |  e5  |       its side facing e5 is a conforming
 y = 2*dx |______________|______|       interior side with flip = 1
          |              |  e4  |
          |     e1       |______|
          |              |  e3  |
          |______________|______|
        x = 0          2*dx   3*dx
  • Two mortar interfaces (element ordering exercises the mortar-index strides in the exchange buffers).
  • Mortar 2's second sub-edge has flip = 1 (element 6's edge coordinate runs opposite the big side's), exercising every trace-reorientation branch.
  • With two ranks (elements 1-3 | 4-6), mortar 1 splits big/small across ranks while mortar 2 places BOTH small elements remote from the big element's rank, so the big-side trace is received independently for each sub-edge.

Input - this : Fresh/empty mesh2d_t object - dx : Edge length of the small elements; big elements have edge length 2*dx - bcids(1:4) : Boundary condition flags for the south, east, north, and west sides of the domain

Arguments

TypeIntentOptionalAttributesName
class(Mesh2D_t), intent(out) :: this
real(kind=prec), intent(in) :: dx
integer, intent(in) :: bcids(1:4)

Contents


Source Code

  subroutine DoubleMortarMesh_Mesh2D_t(this,dx,bcids)
  !!
  !! Create a six-element mesh with two 2:1 mortar interfaces, used to validate the
  !! mortar machinery in configurations the SimpleMortarMesh cannot reach:
  !!
  !!      y = 4*dx  ______________ ______
  !!               |              | e6 R |   R : element 6 is rotated 180 degrees, so
  !!               |     e2       |______|       its side facing e2 has flip = 1, and
  !!               |              |  e5  |       its side facing e5 is a conforming
  !!      y = 2*dx |______________|______|       interior side with flip = 1
  !!               |              |  e4  |
  !!               |     e1       |______|
  !!               |              |  e3  |
  !!               |______________|______|
  !!             x = 0          2*dx   3*dx
  !!
  !!  - Two mortar interfaces (element ordering exercises the mortar-index strides
  !!    in the exchange buffers).
  !!  - Mortar 2's second sub-edge has flip = 1 (element 6's edge coordinate runs
  !!    opposite the big side's), exercising every trace-reorientation branch.
  !!  - With two ranks (elements 1-3 | 4-6), mortar 1 splits big/small across ranks
  !!    while mortar 2 places BOTH small elements remote from the big element's
  !!    rank, so the big-side trace is received independently for each sub-edge.
  !!
  !!  Input
  !!    - this : Fresh/empty mesh2d_t object
  !!    - dx : Edge length of the small elements; big elements have edge length 2*dx
  !!    - bcids(1:4) : Boundary condition flags for the south, east, north, and west
  !!                   sides of the domain
  !!
    implicit none
    class(Mesh2D_t),intent(out) :: this
    real(prec),intent(in) :: dx
    integer,intent(in) :: bcids(1:4)
    ! Local
    integer,parameter :: nGlobalElem = 6
    integer,parameter :: nUniqueSides = 18
    real(prec) :: nodeCoords(1:2,1:2,1:2,1:nGlobalElem)
    integer :: globalNodeIDs(1:2,1:2,1:nGlobalElem)
    integer :: sideInfo(1:5,1:4,1:nGlobalElem)
    integer :: e1,e2
    integer :: nLocalElems
    integer :: nGeo,nBCs

    call this%decomp%init()

    nGeo = 1 ! Bilinear element geometry
    nBCs = 4

    ! Element 1 (big) : [0,2dx] x [0,2dx]
    nodeCoords(1:2,1,1,1) = [0.0_prec,0.0_prec]
    nodeCoords(1:2,2,1,1) = [2.0_prec*dx,0.0_prec]
    nodeCoords(1:2,1,2,1) = [0.0_prec,2.0_prec*dx]
    nodeCoords(1:2,2,2,1) = [2.0_prec*dx,2.0_prec*dx]
    globalNodeIDs(1:2,1,1) = [1,2]
    globalNodeIDs(1:2,2,1) = [6,7]

    ! Element 2 (big) : [0,2dx] x [2dx,4dx]
    nodeCoords(1:2,1,1,2) = [0.0_prec,2.0_prec*dx]
    nodeCoords(1:2,2,1,2) = [2.0_prec*dx,2.0_prec*dx]
    nodeCoords(1:2,1,2,2) = [0.0_prec,4.0_prec*dx]
    nodeCoords(1:2,2,2,2) = [2.0_prec*dx,4.0_prec*dx]
    globalNodeIDs(1:2,1,2) = [6,7]
    globalNodeIDs(1:2,2,2) = [11,12]

    ! Element 3 (small) : [2dx,3dx] x [0,dx]
    nodeCoords(1:2,1,1,3) = [2.0_prec*dx,0.0_prec]
    nodeCoords(1:2,2,1,3) = [3.0_prec*dx,0.0_prec]
    nodeCoords(1:2,1,2,3) = [2.0_prec*dx,dx]
    nodeCoords(1:2,2,2,3) = [3.0_prec*dx,dx]
    globalNodeIDs(1:2,1,3) = [2,3]
    globalNodeIDs(1:2,2,3) = [4,5]

    ! Element 4 (small) : [2dx,3dx] x [dx,2dx]
    nodeCoords(1:2,1,1,4) = [2.0_prec*dx,dx]
    nodeCoords(1:2,2,1,4) = [3.0_prec*dx,dx]
    nodeCoords(1:2,1,2,4) = [2.0_prec*dx,2.0_prec*dx]
    nodeCoords(1:2,2,2,4) = [3.0_prec*dx,2.0_prec*dx]
    globalNodeIDs(1:2,1,4) = [4,5]
    globalNodeIDs(1:2,2,4) = [7,8]

    ! Element 5 (small) : [2dx,3dx] x [2dx,3dx]
    nodeCoords(1:2,1,1,5) = [2.0_prec*dx,2.0_prec*dx]
    nodeCoords(1:2,2,1,5) = [3.0_prec*dx,2.0_prec*dx]
    nodeCoords(1:2,1,2,5) = [2.0_prec*dx,3.0_prec*dx]
    nodeCoords(1:2,2,2,5) = [3.0_prec*dx,3.0_prec*dx]
    globalNodeIDs(1:2,1,5) = [7,8]
    globalNodeIDs(1:2,2,5) = [9,10]

    ! Element 6 (small, rotated 180 degrees) : [2dx,3dx] x [3dx,4dx]
    ! Corner 1 sits at the physical northeast corner, so the element's local
    ! coordinate directions run opposite the physical x and y directions. The
    ! corner ordering remains counterclockwise (positive Jacobian).
    nodeCoords(1:2,1,1,6) = [3.0_prec*dx,4.0_prec*dx]
    nodeCoords(1:2,2,1,6) = [2.0_prec*dx,4.0_prec*dx]
    nodeCoords(1:2,1,2,6) = [3.0_prec*dx,3.0_prec*dx]
    nodeCoords(1:2,2,2,6) = [2.0_prec*dx,3.0_prec*dx]
    globalNodeIDs(1:2,1,6) = [13,12]
    globalNodeIDs(1:2,2,6) = [10,9]

    ! Side connectivity. Global side ids:
    !  1: e1-S, 2: mortar 1 sub-edge 1 (e1-E lower / e3-W), 3: mortar 1 sub-edge 2
    !  (e1-E upper / e4-W), 4: e1-N/e2-S, 5: e1-W, 6: mortar 2 sub-edge 1
    !  (e2-E lower / e5-W), 7: mortar 2 sub-edge 2 (e2-E upper / e6 local side 2,
    !  flip 1), 8: e2-N, 9: e2-W, 10: e3-S, 11: e3-E, 12: e3-N/e4-S, 13: e4-E,
    !  14: e4-N/e5-S, 15: e5-E, 16: e5-N/e6 local side 3 (flip 1), 17: e6 local
    !  side 4 (domain east), 18: e6 local side 1 (domain north)
    sideInfo = 0

    ! Element 1 (big, lower)
    sideInfo(2,1,1) = 1
    sideInfo(5,1,1) = bcids(1) ! south -> domain south
    sideInfo(1,2,1) = 1 ! east -> mortar 1, big side
    sideInfo(2,2,1) = 2
    sideInfo(2,3,1) = 4 ! north -> conforming interior side shared with element 2
    sideInfo(3,3,1) = 2
    sideInfo(4,3,1) = 10*1 ! neighbor's south side, flip 0
    sideInfo(2,4,1) = 5
    sideInfo(5,4,1) = bcids(4) ! west -> domain west

    ! Element 2 (big, upper)
    sideInfo(2,1,2) = 4 ! south -> conforming interior side shared with element 1
    sideInfo(3,1,2) = 1
    sideInfo(4,1,2) = 10*3 ! neighbor's north side, flip 0
    sideInfo(1,2,2) = 2 ! east -> mortar 2, big side
    sideInfo(2,2,2) = 6
    sideInfo(2,3,2) = 8
    sideInfo(5,3,2) = bcids(3) ! north -> domain north
    sideInfo(2,4,2) = 9
    sideInfo(5,4,2) = bcids(4) ! west -> domain west

    ! Element 3 (small, lower-right)
    sideInfo(2,1,3) = 10
    sideInfo(5,1,3) = bcids(1) ! south -> domain south
    sideInfo(2,2,3) = 11
    sideInfo(5,2,3) = bcids(2) ! east -> domain east
    sideInfo(2,3,3) = 12 ! north -> conforming interior side shared with element 4
    sideInfo(3,3,3) = 4
    sideInfo(4,3,3) = 10*1 ! neighbor's south side, flip 0
    sideInfo(1,4,3) = 1 ! west -> mortar 1, small side on sub-edge 1
    sideInfo(2,4,3) = 2

    ! Element 4 (small)
    sideInfo(2,1,4) = 12 ! south -> conforming interior side shared with element 3
    sideInfo(3,1,4) = 3
    sideInfo(4,1,4) = 10*3 ! neighbor's north side, flip 0
    sideInfo(2,2,4) = 13
    sideInfo(5,2,4) = bcids(2) ! east -> domain east
    sideInfo(2,3,4) = 14 ! north -> conforming interior side shared with element 5
    sideInfo(3,3,4) = 5
    sideInfo(4,3,4) = 10*1 ! neighbor's south side, flip 0
    sideInfo(1,4,4) = 1 ! west -> mortar 1, small side on sub-edge 2
    sideInfo(2,4,4) = 3

    ! Element 5 (small)
    sideInfo(2,1,5) = 14 ! south -> conforming interior side shared with element 4
    sideInfo(3,1,5) = 4
    sideInfo(4,1,5) = 10*3 ! neighbor's north side, flip 0
    sideInfo(2,2,5) = 15
    sideInfo(5,2,5) = bcids(2) ! east -> domain east
    sideInfo(2,3,5) = 16 ! north -> conforming side shared with element 6; element
    sideInfo(3,3,5) = 6 ! 6's edge coordinate runs opposite this element's
    sideInfo(4,3,5) = 10*3+1 ! neighbor's local north side, flip 1
    sideInfo(1,4,5) = 2 ! west -> mortar 2, small side on sub-edge 1
    sideInfo(2,4,5) = 6

    ! Element 6 (small, rotated). Local sides map to physical directions as:
    ! side 1 -> domain north, side 2 -> mortar 2 (faces element 2), side 3 ->
    ! conforming side shared with element 5, side 4 -> domain east.
    sideInfo(2,1,6) = 18
    sideInfo(5,1,6) = bcids(3) ! local south -> domain north
    sideInfo(1,2,6) = 2 ! local east -> mortar 2, small side on sub-edge 2
    sideInfo(2,2,6) = 7
    sideInfo(2,3,6) = 16 ! local north -> conforming side shared with element 5
    sideInfo(3,3,6) = 5
    sideInfo(4,3,6) = 10*3+1 ! neighbor's north side, flip 1
    sideInfo(2,4,6) = 17
    sideInfo(5,4,6) = bcids(2) ! local west -> domain east

    ! Domain decomposition; oversized message bound as in SimpleMortarMesh
    call this%decomp%GenerateDecomposition(nGlobalElem,64*nUniqueSides)

    e1 = this%decomp%offsetElem(this%decomp%rankId+1)+1
    e2 = this%decomp%offsetElem(this%decomp%rankId+2)
    nLocalElems = e2-e1+1

    call this%Init(nGeo,nLocalElems,nLocalElems*4,nLocalElems*4,nBCs)
    this%nUniqueSides = nUniqueSides
    this%quadrature = UNIFORM
    this%BCType = 0
    this%elemInfo = 0

    this%nodeCoords(1:2,1:2,1:2,1:nLocalElems) = nodeCoords(1:2,1:2,1:2,e1:e2)
    this%globalNodeIDs(1:2,1:2,1:nLocalElems) = globalNodeIDs(1:2,1:2,e1:e2)
    this%sideInfo(1:5,1:4,1:nLocalElems) = sideInfo(1:5,1:4,e1:e2)

    ! The mortar table is replicated on all ranks; element ids are global
    this%nMortars = 2
    allocate(this%mortarInfo(1:8,1:2))
    this%mortarInfo(1:8,1) = [1,2, & ! big element 1, east side
                              3,10*4, & ! sub-edge 1 : element 3, west side, flip 0
                              4,10*4, & ! sub-edge 2 : element 4, west side, flip 0
                              2,3] ! global side ids for the two sub-edges
    this%mortarInfo(1:8,2) = [2,2, & ! big element 2, east side
                              5,10*4, & ! sub-edge 1 : element 5, west side, flip 0
                              6,10*2+1, & ! sub-edge 2 : element 6, local east side, flip 1
                              6,7] ! global side ids for the two sub-edges

    call this%UpdateDevice()

  endsubroutine DoubleMortarMesh_Mesh2D_t