SELF_SetInterface_3D.f90 Source File


This file depends on

sourcefile~~self_setinterface_3d.f90~~EfferentGraph sourcefile~self_setinterface_3d.f90 SELF_SetInterface_3D.f90 sourcefile~self_constants.f90 SELF_Constants.f90 sourcefile~self_setinterface_3d.f90->sourcefile~self_constants.f90 sourcefile~self_gpu.f90 SELF_GPU.f90 sourcefile~self_setinterface_3d.f90->sourcefile~self_gpu.f90 sourcefile~self_setinterface_3d_t.f90 SELF_SetInterface_3D_t.f90 sourcefile~self_setinterface_3d.f90->sourcefile~self_setinterface_3d_t.f90 sourcefile~self_mesh_3d.f90 SELF_Mesh_3D.f90 sourcefile~self_setinterface_3d.f90->sourcefile~self_mesh_3d.f90 sourcefile~self_gpu_enums.f90 SELF_GPU_enums.f90 sourcefile~self_gpu.f90->sourcefile~self_gpu_enums.f90 sourcefile~self_setinterface_3d_t.f90->sourcefile~self_constants.f90 sourcefile~self_setinterface_3d_t.f90->sourcefile~self_mesh_3d.f90 sourcefile~self_mesh_3d.f90->sourcefile~self_gpu.f90 sourcefile~self_mesh_3d_t.f90 SELF_Mesh_3D_t.f90 sourcefile~self_mesh_3d.f90->sourcefile~self_mesh_3d_t.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_constants.f90 sourcefile~self_quadrature.f90 SELF_Quadrature.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_quadrature.f90 sourcefile~self_mesh.f90 SELF_Mesh.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_mesh.f90 sourcefile~self_hdf5.f90 SELF_HDF5.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_hdf5.f90 sourcefile~self_lagrange.f90 SELF_Lagrange.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_lagrange.f90 sourcefile~self_supportroutines.f90 SELF_SupportRoutines.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_supportroutines.f90 sourcefile~self_mesh_2d_t.f90 SELF_Mesh_2D_t.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_mesh_2d_t.f90 sourcefile~self_domaindecomposition.f90 SELF_DomainDecomposition.f90 sourcefile~self_mesh_3d_t.f90->sourcefile~self_domaindecomposition.f90 sourcefile~self_quadrature.f90->sourcefile~self_constants.f90 sourcefile~self_mesh.f90->sourcefile~self_constants.f90 sourcefile~self_mesh.f90->sourcefile~self_domaindecomposition.f90 sourcefile~self_hdf5.f90->sourcefile~self_constants.f90 sourcefile~self_lagrange.f90->sourcefile~self_constants.f90 sourcefile~self_lagrange.f90->sourcefile~self_gpu.f90 sourcefile~self_lagrange_t.f90 SELF_Lagrange_t.f90 sourcefile~self_lagrange.f90->sourcefile~self_lagrange_t.f90 sourcefile~self_supportroutines.f90->sourcefile~self_constants.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_constants.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_quadrature.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_mesh.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_hdf5.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_lagrange.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_supportroutines.f90 sourcefile~self_mesh_2d_t.f90->sourcefile~self_domaindecomposition.f90 sourcefile~self_domaindecomposition_t.f90 SELF_DomainDecomposition_t.f90 sourcefile~self_domaindecomposition.f90->sourcefile~self_domaindecomposition_t.f90 sourcefile~self_lagrange_t.f90->sourcefile~self_constants.f90 sourcefile~self_lagrange_t.f90->sourcefile~self_quadrature.f90 sourcefile~self_lagrange_t.f90->sourcefile~self_hdf5.f90 sourcefile~self_lagrange_t.f90->sourcefile~self_supportroutines.f90 sourcefile~self_domaindecomposition_t.f90->sourcefile~self_constants.f90 sourcefile~self_domaindecomposition_t.f90->sourcefile~self_lagrange.f90 sourcefile~self_domaindecomposition_t.f90->sourcefile~self_supportroutines.f90

Files dependent on this one

sourcefile~~self_setinterface_3d.f90~~AfferentGraph sourcefile~self_setinterface_3d.f90 SELF_SetInterface_3D.f90 sourcefile~self_multisetmodel3d_t.f90 SELF_MultiSetModel3D_t.f90 sourcefile~self_multisetmodel3d_t.f90->sourcefile~self_setinterface_3d.f90 sourcefile~self_multisetmodel3d.f90 SELF_MultiSetModel3D.f90 sourcefile~self_multisetmodel3d.f90->sourcefile~self_setinterface_3d.f90 sourcefile~self_multisetmodel3d.f90->sourcefile~self_multisetmodel3d_t.f90 sourcefile~self_multisetmodel3d.f90~2 SELF_MultiSetModel3D.f90 sourcefile~self_multisetmodel3d.f90~2->sourcefile~self_multisetmodel3d_t.f90

Contents


Source Code

! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// !
!
! Maintainers : support@fluidnumerics.com
! Official Repository : https://github.com/FluidNumerics/self/
!
! Copyright © 2024 Fluid Numerics LLC
!
! Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
!    the documentation and/or other materials provided with the distribution.
!
! 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from
!    this software without specific prior written permission.
!
! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
! HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
! LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
!
! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// !

module SELF_SetInterface_3D
!! GPU backend of the element-set interface exchange. When every set with interface
!! faces supplies a device trace (SetTraceRef%trace_gpu), the face traces are gathered on
!! the device and copied to the host in one transfer; the host exchange then runs as on
!! the CPU, and the ghost traces are copied back to the device for
!! FillSetInterfaceBoundary_gpu. Without device traces the host path runs unchanged.

  use SELF_Constants
  use SELF_Mesh_3D
  use SELF_SetInterface_3D_t
  use SELF_GPU
  use iso_c_binding

  implicit none

  type,extends(SetInterface3D_t) :: SetInterface3D
    type(c_ptr) :: faceElem_gpu = c_null_ptr
    type(c_ptr) :: faceSide_gpu = c_null_ptr
    type(c_ptr) :: outbox_gpu = c_null_ptr
    type(c_ptr) :: ghost_gpu = c_null_ptr

  contains

    procedure :: BuildMap => BuildMap_SetInterface3D
    procedure :: Exchange => Exchange_SetInterface3D
    procedure :: Free => Free_SetInterface3D

  endtype SetInterface3D

  interface
    subroutine GatherSetInterfaceOutbox_gpu(outbox,trace,elems,sides,f0,nFaces,nvar,nvarMax,N,nel) &
      bind(c,name="GatherSetInterfaceOutbox_gpu")
      use iso_c_binding
      type(c_ptr),value :: outbox,trace,elems,sides
      integer(c_int),value :: f0,nFaces,nvar,nvarMax,N,nel
    endsubroutine GatherSetInterfaceOutbox_gpu
  endinterface

  interface
    subroutine FillSetInterfaceBoundary_gpu(extBoundary,ghost,elems,sides,f0,nFaces,nvar,nvarMax,N,nel) &
      bind(c,name="FillSetInterfaceBoundary_gpu")
      use iso_c_binding
      type(c_ptr),value :: extBoundary,ghost,elems,sides
      integer(c_int),value :: f0,nFaces,nvar,nvarMax,N,nel
    endsubroutine FillSetInterfaceBoundary_gpu
  endinterface

contains

  subroutine BuildMap_SetInterface3D(this,globalMesh,setOfElem,setGlobalId, &
                                     setOffsetThisRank,nvarOfSet,N)
    !! Build the map on the host (BuildMap_SetInterface3D_t), then copy the face element
    !! and side lists to the device and allocate device outbox and ghost buffers.
    implicit none
    class(SetInterface3D),intent(inout) :: this
    type(Mesh3D),intent(in) :: globalMesh
    integer,intent(in) :: setOfElem(1:)
    integer,intent(in) :: setGlobalId(1:)
    integer,intent(in) :: setOffsetThisRank(1:)
    integer,intent(in) :: nvarOfSet(1:)
    integer,intent(in) :: N
    ! Local
    integer(c_int),allocatable,target :: buf(:)

    call BuildMap_SetInterface3D_t(this,globalMesh,setOfElem,setGlobalId, &
                                   setOffsetThisRank,nvarOfSet,N)
    if(this%nFaces == 0) return

    allocate(buf(1:this%nFaces))
    buf = this%faceElem
    call gpuCheck(hipMalloc(this%faceElem_gpu,sizeof(buf)))
    call gpuCheck(hipMemcpy(this%faceElem_gpu,c_loc(buf),sizeof(buf),hipMemcpyHostToDevice))
    buf = this%faceSide
    call gpuCheck(hipMalloc(this%faceSide_gpu,sizeof(buf)))
    call gpuCheck(hipMemcpy(this%faceSide_gpu,c_loc(buf),sizeof(buf),hipMemcpyHostToDevice))
    deallocate(buf)

    call gpuCheck(hipMalloc(this%outbox_gpu,sizeof(this%outbox)))
    call gpuCheck(hipMalloc(this%ghost_gpu,sizeof(this%ghost)))

  endsubroutine BuildMap_SetInterface3D

  subroutine Exchange_SetInterface3D(this,traces)
    !! As Exchange_SetInterface3D_t. If every set with local interface faces has a device
    !! trace, the outbox is gathered on the device; either way ghost is copied to the
    !! device afterwards, so FillSetInterfaceBoundary_gpu reads the current exchange.
    implicit none
    class(SetInterface3D),intent(inout) :: this
    type(SetTraceRef),intent(in) :: traces(1:)
    ! Local
    integer :: k,nk
    logical :: onDevice

    if(this%nFaces == 0) then
      call this%ExchangeOutbox()
      return
    endif

    onDevice = .true.
    do k = 1,this%nSets
      nk = this%setFaceStart(k+1)-this%setFaceStart(k)
      if(nk > 0 .and. .not. c_associated(traces(k)%trace_gpu)) onDevice = .false.
    enddo

    if(onDevice) then
      do k = 1,this%nSets
        nk = this%setFaceStart(k+1)-this%setFaceStart(k)
        if(nk == 0) cycle
        call GatherSetInterfaceOutbox_gpu(this%outbox_gpu,traces(k)%trace_gpu, &
                                          this%faceElem_gpu,this%faceSide_gpu, &
                                          this%setFaceStart(k)-1,nk,this%nvarOfSet(k), &
                                          this%nvarMax,this%N,size(traces(k)%trace,4))
      enddo
      call gpuCheck(hipMemcpy(c_loc(this%outbox),this%outbox_gpu,sizeof(this%outbox), &
                              hipMemcpyDeviceToHost))
    else
      call this%GatherOutbox(traces)
    endif

    call this%ExchangeOutbox()

    call gpuCheck(hipMemcpy(this%ghost_gpu,c_loc(this%ghost),sizeof(this%ghost), &
                            hipMemcpyHostToDevice))

  endsubroutine Exchange_SetInterface3D

  subroutine Free_SetInterface3D(this)
    !! Free the device buffers, then the host map. Collective.
    implicit none
    class(SetInterface3D),intent(inout) :: this

    if(c_associated(this%faceElem_gpu)) call gpuCheck(hipFree(this%faceElem_gpu))
    if(c_associated(this%faceSide_gpu)) call gpuCheck(hipFree(this%faceSide_gpu))
    if(c_associated(this%outbox_gpu)) call gpuCheck(hipFree(this%outbox_gpu))
    if(c_associated(this%ghost_gpu)) call gpuCheck(hipFree(this%ghost_gpu))
    this%faceElem_gpu = c_null_ptr
    this%faceSide_gpu = c_null_ptr
    this%outbox_gpu = c_null_ptr
    this%ghost_gpu = c_null_ptr

    call Free_SetInterface3D_t(this)

  endsubroutine Free_SetInterface3D

endmodule SELF_SetInterface_3D