module boundarymod use config, only: periodicb, reflection, outflow, & & boundary_xin, boundary_xout, & & boundary_yin, boundary_yout, & & boundary_zin, boundary_zout use basicmod implicit none integer,parameter :: nv1 = 3, nv2 = 4, nv3 = 5 integer,parameter :: nbc = 9 + ncomp real(8),dimension(mgn,jn,kn,nbc):: BsXstt,BsXend real(8),dimension(in,mgn,kn,nbc):: BsYstt,BsYend real(8),dimension(in,jn,mgn,nbc):: BsZstt,BsZend real(8),dimension(mgn,jn,kn,nbc):: BrXstt,BrXend real(8),dimension(in,mgn,kn,nbc):: BrYstt,BrYend real(8),dimension(in,jn,mgn,nbc):: BrZstt,BrZend contains subroutine BoundaryCondition implicit none integer :: i,j,k !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do j=1,jn-1 do i=1,mgn BsXend(i,j,k,1) = d(ie-mgn+i,j,k) BsXend(i,j,k,2) = ei(ie-mgn+i,j,k) BsXend(i,j,k,nv1) = v1(ie-mgn+i,j,k) BsXend(i,j,k,nv2) = v2(ie-mgn+i,j,k) BsXend(i,j,k,nv3) = v3(ie-mgn+i,j,k) BsXend(i,j,k,6) = b1(ie-mgn+i,j,k) BsXend(i,j,k,7) = b2(ie-mgn+i,j,k) BsXend(i,j,k,8) = b3(ie-mgn+i,j,k) BsXend(i,j,k,9) = bp(ie-mgn+i,j,k) BsXend(i,j,k,10:nbc) = Xcomp(1:ncomp,ie-mgn+i,j,k) BsXstt(i,j,k,1) = d(is+i-1,j,k) BsXstt(i,j,k,2) = ei(is+i-1,j,k) BsXstt(i,j,k,nv1) = v1(is+i-1,j,k) BsXstt(i,j,k,nv2) = v2(is+i-1,j,k) BsXstt(i,j,k,nv3) = v3(is+i-1,j,k) BsXstt(i,j,k,6) = b1(is+i-1,j,k) BsXstt(i,j,k,7) = b2(is+i-1,j,k) BsXstt(i,j,k,8) = b3(is+i-1,j,k) BsXstt(i,j,k,9) = bp(is+i-1,j,k) BsXstt(i,j,k,10:nbc) = Xcomp(1:ncomp,is+i-1,j,k) end do end do end do !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do i=1,in-1 do j=1,mgn BsYend(i,j,k,1) = d(i,je-mgn+j,k) BsYend(i,j,k,2) = ei(i,je-mgn+j,k) BsYend(i,j,k,nv1) = v1(i,je-mgn+j,k) BsYend(i,j,k,nv2) = v2(i,je-mgn+j,k) BsYend(i,j,k,nv3) = v3(i,je-mgn+j,k) BsYend(i,j,k,6) = b1(i,je-mgn+j,k) BsYend(i,j,k,7) = b2(i,je-mgn+j,k) BsYend(i,j,k,8) = b3(i,je-mgn+j,k) BsYend(i,j,k,9) = bp(i,je-mgn+j,k) BsYend(i,j,k,10:nbc) = Xcomp(1:ncomp,i,je-mgn+j,k) BsYstt(i,j,k,1) = d(i,js+j-1,k) BsYstt(i,j,k,2) = ei(i,js+j-1,k) BsYstt(i,j,k,nv1) = v1(i,js+j-1,k) BsYstt(i,j,k,nv2) = v2(i,js+j-1,k) BsYstt(i,j,k,nv3) = v3(i,js+j-1,k) BsYstt(i,j,k,6) = b1(i,js+j-1,k) BsYstt(i,j,k,7) = b2(i,js+j-1,k) BsYstt(i,j,k,8) = b3(i,js+j-1,k) BsYstt(i,j,k,9) = bp(i,js+j-1,k) BsYstt(i,j,k,10:nbc) = Xcomp(1:ncomp,i,js+j-1,k) end do end do end do !$omp target teams distribute parallel do collapse(3) do j=1,jn-1 do i=1,in-1 do k=1,mgn BsZend(i,j,k,1) = d(i,j,ke-mgn+k) BsZend(i,j,k,2) = ei(i,j,ke-mgn+k) BsZend(i,j,k,nv1) = v1(i,j,ke-mgn+k) BsZend(i,j,k,nv2) = v2(i,j,ke-mgn+k) BsZend(i,j,k,nv3) = v3(i,j,ke-mgn+k) BsZend(i,j,k,6) = b1(i,j,ke-mgn+k) BsZend(i,j,k,7) = b2(i,j,ke-mgn+k) BsZend(i,j,k,8) = b3(i,j,ke-mgn+k) BsZend(i,j,k,9) = bp(i,j,ke-mgn+k) BsZend(i,j,k,10:nbc) = Xcomp(1:ncomp,i,j,ke-mgn+k) BsZstt(i,j,k,1) = d(i,j,ks+k-1) BsZstt(i,j,k,2) = ei(i,j,ks+k-1) BsZstt(i,j,k,nv1) = v1(i,j,ks+k-1) BsZstt(i,j,k,nv2) = v2(i,j,ks+k-1) BsZstt(i,j,k,nv3) = v3(i,j,ks+k-1) BsZstt(i,j,k,6) = b1(i,j,ks+k-1) BsZstt(i,j,k,7) = b2(i,j,ks+k-1) BsZstt(i,j,k,8) = b3(i,j,ks+k-1) BsZstt(i,j,k,9) = bp(i,j,ks+k-1) BsZstt(i,j,k,10:nbc) = Xcomp(1:ncomp,i,j,ks+k-1) end do end do end do ! ---------------------- ! Exchange / apply physical BCs (MPI on host, BC possibly on device) ! ---------------------- call XbcSendRecv() call YbcSendRecv() call ZbcSendRecv() ! ---------------------- ! Unpack from receive buffers on device ! ---------------------- !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do j=1,jn-1 do i=1,mgn d(i,j,k) = BrXstt(i,j,k,1) ei(i,j,k) = BrXstt(i,j,k,2) v1(i,j,k) = BrXstt(i,j,k,nv1) v2(i,j,k) = BrXstt(i,j,k,nv2) v3(i,j,k) = BrXstt(i,j,k,nv3) b1(i,j,k) = BrXstt(i,j,k,6) b2(i,j,k) = BrXstt(i,j,k,7) b3(i,j,k) = BrXstt(i,j,k,8) bp(i,j,k) = BrXstt(i,j,k,9) Xcomp(1:ncomp,i,j,k) = BrXstt(i,j,k,10:nbc) d(ie+i,j,k) = BrXend(i,j,k,1) ei(ie+i,j,k) = BrXend(i,j,k,2) v1(ie+i,j,k) = BrXend(i,j,k,nv1) v2(ie+i,j,k) = BrXend(i,j,k,nv2) v3(ie+i,j,k) = BrXend(i,j,k,nv3) b1(ie+i,j,k) = BrXend(i,j,k,6) b2(ie+i,j,k) = BrXend(i,j,k,7) b3(ie+i,j,k) = BrXend(i,j,k,8) bp(ie+i,j,k) = BrXend(i,j,k,9) Xcomp(1:ncomp,ie+i,j,k) = BrXend(i,j,k,10:nbc) end do end do end do !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do j=1,mgn do i=1,in-1 d(i,j,k) = BrYstt(i,j,k,1) ei(i,j,k) = BrYstt(i,j,k,2) v1(i,j,k) = BrYstt(i,j,k,nv1) v2(i,j,k) = BrYstt(i,j,k,nv2) v3(i,j,k) = BrYstt(i,j,k,nv3) b1(i,j,k) = BrYstt(i,j,k,6) b2(i,j,k) = BrYstt(i,j,k,7) b3(i,j,k) = BrYstt(i,j,k,8) bp(i,j,k) = BrYstt(i,j,k,9) Xcomp(1:ncomp,i,j,k) = BrYstt(i,j,k,10:nbc) d(i,je+j,k) = BrYend(i,j,k,1) ei(i,je+j,k) = BrYend(i,j,k,2) v1(i,je+j,k) = BrYend(i,j,k,nv1) v2(i,je+j,k) = BrYend(i,j,k,nv2) v3(i,je+j,k) = BrYend(i,j,k,nv3) b1(i,je+j,k) = BrYend(i,j,k,6) b2(i,je+j,k) = BrYend(i,j,k,7) b3(i,je+j,k) = BrYend(i,j,k,8) bp(i,je+j,k) = BrYend(i,j,k,9) Xcomp(1:ncomp,i,je+j,k) = BrYend(i,j,k,10:nbc) end do end do end do !$omp target teams distribute parallel do collapse(3) do k=1,mgn do j=1,jn-1 do i=1,in-1 d(i,j,k) = BrZstt(i,j,k,1) ei(i,j,k) = BrZstt(i,j,k,2) v1(i,j,k) = BrZstt(i,j,k,nv1) v2(i,j,k) = BrZstt(i,j,k,nv2) v3(i,j,k) = BrZstt(i,j,k,nv3) b1(i,j,k) = BrZstt(i,j,k,6) b2(i,j,k) = BrZstt(i,j,k,7) b3(i,j,k) = BrZstt(i,j,k,8) bp(i,j,k) = BrZstt(i,j,k,9) Xcomp(1:ncomp,i,j,k) = BrZstt(i,j,k,10:nbc) d(i,j,ke+k) = BrZend(i,j,k,1) ei(i,j,ke+k) = BrZend(i,j,k,2) v1(i,j,ke+k) = BrZend(i,j,k,nv1) v2(i,j,ke+k) = BrZend(i,j,k,nv2) v3(i,j,ke+k) = BrZend(i,j,k,nv3) b1(i,j,ke+k) = BrZend(i,j,k,6) b2(i,j,ke+k) = BrZend(i,j,k,7) b3(i,j,ke+k) = BrZend(i,j,k,8) bp(i,j,ke+k) = BrZend(i,j,k,9) Xcomp(1:ncomp,i,j,ke+k) = BrZend(i,j,k,10:nbc) end do end do end do end subroutine BoundaryCondition subroutine XbcSendRecv() use mpimod implicit none integer :: i,j,k,n single: if (ntiles(1) == 1) then ! Local-only: compute halos on device !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do j=1,jn-1 do i=1,mgn select case(boundary_xin) case(periodicb) BrXstt(i,j,k,1:nbc) = BsXend(i,j,k,1:nbc) case(reflection) BrXstt(i,j,k,1:nbc) = BsXstt(mgn-i+1,j,k,1:nbc) BrXstt(i,j,k,nv1) = -BrXstt(i,j,k,nv1) case(outflow) BrXstt(i,j,k,1:nbc) = BsXstt(1,j,k,1:nbc) end select select case(boundary_xout) case(periodicb) BrXend(i,j,k,1:nbc) = BsXstt(i,j,k,1:nbc) case(reflection) BrXend(i,j,k,1:nbc) = BsXend(mgn-i+1,j,k,1:nbc) BrXend(i,j,k,nv1) = -BrXend(i,j,k,nv1) case(outflow) BrXend(i,j,k,1:nbc) = BsXend(mgn,j,k,1:nbc) end select end do end do end do return end if single ! Ensure host has latest send buffers !$omp target update from(BsXstt, BsXend) ! Post receives/sends where neighbors exist. Physical BC when MPI_PROC_NULL. if (n1m /= MPI_PROC_NULL) then call MPI_IRECV(BrXstt, size(BrXstt), MPI_DOUBLE_PRECISION, n1m, 1100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsXstt, size(BsXstt), MPI_DOUBLE_PRECISION, n1m, 1200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_xin == reflection) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,jn-1; do i=1,mgn BrXstt(i,j,k,1:nbc) = BsXstt(mgn-i+1,j,k,1:nbc) BrXstt(i,j,k,nv1) = -BrXstt(i,j,k,nv1) end do; end do; end do else if (boundary_xin == outflow) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,jn-1; do i=1,mgn BrXstt(i,j,k,1:nbc) = BsXstt(1,j,k,1:nbc) end do; end do; end do end if end if if (n1p /= MPI_PROC_NULL) then call MPI_IRECV(BrXend, size(BrXend), MPI_DOUBLE_PRECISION, n1p, 1200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsXend, size(BsXend), MPI_DOUBLE_PRECISION, n1p, 1100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_xout == reflection) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,jn-1; do i=1,mgn BrXend(i,j,k,1:nbc) = BsXend(mgn-i+1,j,k,1:nbc) BrXend(i,j,k,nv1) = -BrXend(i,j,k,nv1) end do; end do; end do else if (boundary_xout == outflow) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,jn-1; do i=1,mgn BrXend(i,j,k,1:nbc) = BsXend(mgn,j,k,1:nbc) end do; end do; end do end if end if if (nreq /= 0) then call MPI_WAITALL(nreq, req, stat, ierr) ! Push only faces that came from MPI if (n1m /= MPI_PROC_NULL) then !$omp target update to(BrXstt) end if if (n1p /= MPI_PROC_NULL) then !$omp target update to(BrXend) end if nreq = 0 end if end subroutine XbcSendRecv subroutine YbcSendRecv() use mpimod implicit none integer :: i,j,k if (ntiles(2) == 1) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1 do j=1,mgn do i=1,in-1 select case(boundary_yin) case(periodicb) BrYstt(i,j,k,1:nbc) = BsYend(i,j,k,1:nbc) case(reflection) BrYstt(i,j,k,1:nbc) = BsYstt(i,mgn-j+1,k,1:nbc) BrYstt(i,j,k,nv2) = -BrYstt(i,j,k,nv2) case(outflow) BrYstt(i,j,k,1:nbc) = BsYstt(i,1,k,1:nbc) end select select case(boundary_yout) case(periodicb) BrYend(i,j,k,1:nbc) = BsYstt(i,j,k,1:nbc) case(reflection) BrYend(i,j,k,1:nbc) = BsYend(i,mgn-j+1,k,1:nbc) BrYend(i,j,k,nv2) = -BrYend(i,j,k,nv2) case(outflow) BrYend(i,j,k,1:nbc) = BsYend(i,mgn,k,1:nbc) end select end do end do end do return end if !$omp target update from(BsYstt, BsYend) if (n2m /= MPI_PROC_NULL) then call MPI_IRECV(BrYstt, size(BrYstt), MPI_DOUBLE_PRECISION, n2m, 2100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsYstt, size(BsYstt), MPI_DOUBLE_PRECISION, n2m, 2200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_yin == reflection) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,mgn; do i=1,in-1 BrYstt(i,j,k,1:nbc) = BsYstt(i,mgn-j+1,k,1:nbc) BrYstt(i,j,k,nv2) = -BrYstt(i,j,k,nv2) end do; end do; end do else if (boundary_yin == outflow) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,mgn; do i=1,in-1 BrYstt(i,j,k,1:nbc) = BsYstt(i,1,k,1:nbc) end do; end do; end do end if end if if (n2p /= MPI_PROC_NULL) then call MPI_IRECV(BrYend, size(BrYend), MPI_DOUBLE_PRECISION, n2p, 2200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsYend, size(BsYend), MPI_DOUBLE_PRECISION, n2p, 2100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_yout == reflection) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,mgn; do i=1,in-1 BrYend(i,j,k,1:nbc) = BsYend(i,mgn-j+1,k,1:nbc) BrYend(i,j,k,nv2) = -BrYend(i,j,k,nv2) end do; end do; end do else if (boundary_yout == outflow) then !$omp target teams distribute parallel do collapse(3) do k=1,kn-1; do j=1,mgn; do i=1,in-1 BrYend(i,j,k,1:nbc) = BsYend(i,mgn,k,1:nbc) end do; end do; end do end if end if if (nreq /= 0) then call MPI_WAITALL(nreq, req, stat, ierr) if (n2m /= MPI_PROC_NULL) then !$omp target update to(BrYstt) end if if (n2p /= MPI_PROC_NULL) then !$omp target update to(BrYend) end if nreq = 0 end if end subroutine YbcSendRecv subroutine ZbcSendRecv() use mpimod implicit none integer :: i,j,k if (ntiles(3) == 1) then !$omp target teams distribute parallel do collapse(3) do j=1,jn-1 do i=1,in-1 do k=1,mgn select case(boundary_zin) case(periodicb) BrZstt(i,j,k,1:nbc) = BsZend(i,j,k,1:nbc) case(reflection) BrZstt(i,j,k,1:nbc) = BsZstt(i,j,mgn-k+1,1:nbc) BrZstt(i,j,k,nv3) = -BrZstt(i,j,k,nv3) case(outflow) BrZstt(i,j,k,1:nbc) = BsZstt(i,j,1,1:nbc) end select select case(boundary_zout) case(periodicb) BrZend(i,j,k,1:nbc) = BsZstt(i,j,k,1:nbc) case(reflection) BrZend(i,j,k,1:nbc) = BsZend(i,j,mgn-k+1,1:nbc) BrZend(i,j,k,nv3) = -BrZend(i,j,k,nv3) case(outflow) BrZend(i,j,k,1:nbc) = BsZend(i,j,mgn,1:nbc) end select end do end do end do return end if !$omp target update from(BsZstt, BsZend) if (n3m /= MPI_PROC_NULL) then call MPI_IRECV(BrZstt, size(BrZstt), MPI_DOUBLE_PRECISION, n3m, 3100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsZstt, size(BsZstt), MPI_DOUBLE_PRECISION, n3m, 3200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_zin == reflection) then !$omp target teams distribute parallel do collapse(3) do j=1,jn-1; do i=1,in-1; do k=1,mgn BrZstt(i,j,k,1:nbc) = BsZstt(i,j,mgn-k+1,1:nbc) BrZstt(i,j,k,nv3) = -BrZstt(i,j,k,nv3) end do; end do; end do else if (boundary_zin == outflow) then !$omp target teams distribute parallel do collapse(3) do j=1,jn-1; do i=1,in-1; do k=1,mgn BrZstt(i,j,k,1:nbc) = BsZstt(i,j,1,1:nbc) end do; end do; end do end if end if if (n3p /= MPI_PROC_NULL) then call MPI_IRECV(BrZend, size(BrZend), MPI_DOUBLE_PRECISION, n3p, 3200, comm3d, req(nreq+1), ierr) nreq = nreq + 1 call MPI_ISEND(BsZend, size(BsZend), MPI_DOUBLE_PRECISION, n3p, 3100, comm3d, req(nreq+1), ierr) nreq = nreq + 1 else if (boundary_zout == reflection) then !$omp target teams distribute parallel do collapse(3) do j=1,jn-1; do i=1,in-1; do k=1,mgn BrZend(i,j,k,1:nbc) = BsZend(i,j,mgn-k+1,1:nbc) BrZend(i,j,k,nv3) = -BrZend(i,j,k,nv3) end do; end do; end do else if (boundary_zout == outflow) then !$omp target teams distribute parallel do collapse(3) do j=1,jn-1; do i=1,in-1; do k=1,mgn BrZend(i,j,k,1:nbc) = BsZend(i,j,mgn,1:nbc) end do; end do; end do end if end if if (nreq /= 0) then call MPI_WAITALL(nreq, req, stat, ierr) if (n3m /= MPI_PROC_NULL) then !$omp target update to(BrZstt) end if if (n3p /= MPI_PROC_NULL) then !$omp target update to(BrZend) end if nreq = 0 end if end subroutine ZbcSendRecv end module boundarymod