!===============================================================================
!
! cg_proj_xbound.F90
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2016 Hinnerk Stueben
!
! This file is part of BQCD -- Berlin Quantum ChromoDynamics program
!
! BQCD is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! BQCD is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with BQCD.  If not, see <http://www.gnu.org/licenses/>.
!
!-------------------------------------------------------------------------------
# define LANGUAGE_FORTRAN
# include "defs.h"
# include "cg_defs.h"

FOR _rrs in _r4 _r8 _r4s _r8s
# define xbound_spin_sc%%_rrs xbound_spin_sc
# define xbound_spin_sc22%%_rrs xbound_spin_sc22
# define xbound_count_sc22%%_rrs xbound_count_proj
ENDFOR

!-------------------------------------------------------------------------------
subroutine T(cg_proj_xbound)(out, proj, mu0, dag)

  use module_nnpe
  use module_lattice
  use module_cg_proj_xbound
  use typedef_simd
  use T(module_vol)
  use T(module_surface)
  implicit none
  spincol_FIELD, intent(out) :: out
  sc2_FIELD, intent(in) :: proj
  integer, intent(in) :: mu0
  integer, intent(in) :: dag
  integer :: mu, mu1, mu2, fb, spin, ierror, req

  if (mu0 == 0) then
     mu1 = 2
     mu2 = DIM
     TIMING_START(timing_bin_xbound_cg_proj)
  else
     mu1 = mu0
     mu2 = mu0
  endif
   
  do mu = mu1, mu2
     if (npe(mu) == 1) cycle

#ifdef TIMING
     select case (mu)
     case (1); TIMING_START(timing_bin_xbound_cg_proj_x)
     case (2); TIMING_START(timing_bin_xbound_cg_proj_y)
     case (3); TIMING_START(timing_bin_xbound_cg_proj_z)
     case (4); TIMING_START(timing_bin_xbound_cg_proj_t)
     end select
#endif

     do fb = FWD, BWD
        if (mu == 4) then
           spin = xbound_spin(fb, dag)
        else
           spin = 1
        endif
        call mpi_irecv(Spincol(out, 1, spin, 1, surface_halo2(mu)%i_start(fb)), &
                       T(xbound_count)(mu), &
                       T(xbound_type), &
                       recv_pe(fb, mu), &
                       xbound_tag, &
                       xbound_comm, &
                       xbound_request(recv, fb, mu), &
                       ierror)
     enddo
  enddo

  do mu = mu1, mu2
     if (npe(mu) == 1) cycle
     do fb = FWD, BWD
        if (mu == 4) then
           call mpi_isend(Spincol(out, 1, xbound_spin(fb, dag), 1, surface2(mu)%i_start(fb)), &
                          T(xbound_count)(mu), &
                          T(xbound_type), &
                          send_pe(fb, mu), &
                          xbound_tag, &
                          xbound_comm, &
                          xbound_request(send, fb, mu), &
                          ierror)
        else
           call mpi_isend(proj(1, 1, 1, mu, fb), &
                          xbound_count_proj(mu), &
                          BQCD_REAL, &        
                          send_pe(fb, mu), &
                          xbound_tag, &
                          xbound_comm, &
                          xbound_request(send, fb, mu), &
                          ierror)
        endif
     enddo
  enddo

end

!===============================================================================
