! See copyright notice in the COPYRIGHT file.
! ****************************************************************************** !
!> This module provides the definition and methods for musubi-specific
!! communication.
!! It includes the wrapper functions for the actual communication, which is
!! defined in [[tem_comm_module]].
!!
module mus_comm_module

  ! include treelm modules
  use mpi
  use env_module,          only: rk
  use tem_comm_module,     only: tem_communication_type, tem_commpattern_type
  use tem_comm_env_module, only: tem_comm_env_type

  implicit none

  private

  ! public :: mus_exchange
  public :: mus_init_longBuffers

contains

! ****************************************************************************** !
  !> Wrapper around the actual communication, to avoid copy-in, copy-out by the
  !! Intel compiler. (At least the intel compiler on pigeon (v12.0) seems to do
  !! copying here, if a sub-array is passed to an assumed size dummy argument. 
  !! Therefore we use this wrapping with an assumed shape dummy argument, so we
  !! can pass a complete field to the actual exchange which has an assumed size 
  !! argument, without copying complete state field around, just for 
  !! communication. Ugly, but it doesn't seem to have an impact on performance, 
  !! and right it seems to be the most suitable solution.
  !!
  ! subroutine mus_exchange(send, recv, state, pattern, level, comm)
  !   ! ---------------------------------------------------------------------------
  !   !>
  !   type(tem_communication_type), intent(inout) :: send
  !   !>
  !   type(tem_communication_type), intent(inout) :: recv
  !   !>
  !   real(kind=rk), intent(inout) :: state(:)
  !   !>
  !   type(tem_commPattern_type), intent(in) :: pattern
  !   !>
  !   integer :: level
  !   !> MPI communicator
  !   integer, intent(in) :: comm
  !   ! ---------------------------------------------------------------------------

  !   call pattern%exchange_real( send = send, recv = recv, state = state,       &
  !     &                         message_flag = level, comm = comm )

  ! end subroutine mus_exchange
! ****************************************************************************** !


! ****************************************************************************** !
  !> Copy the element position in send and recv buffer to pos array
  !! in long type buffer
  !!
  subroutine mus_init_longBuffers( comm, pattern )
    ! ---------------------------------------------------------------------------
    !>
    type( tem_communication_type ), intent(inout) :: comm
    !>
    type( tem_commPattern_type ), intent(in) :: pattern
    ! ---------------------------------------------------------------------------
    integer :: iProc
    ! ---------------------------------------------------------------------------

    ! Allocate long buffers and initialize comm buffer
    if( allocated( comm%buf_long )) deallocate( comm%buf_long )
    allocate( comm%buf_long( comm%nProcs ) )
    do iProc = 1, comm%nProcs
      call pattern%initBuf_long( me    = comm%buf_long( iProc ),               &
        &                        pos   = comm%elemPos( iProc )%val,            &
        &                        nVals = comm%nElemsProc( iProc ))
    end do

  end subroutine mus_init_longBuffers
! ****************************************************************************** !


end module mus_comm_module
! ****************************************************************************** !
