!===============================================================================
!
! cg_wrapper_mcg.F90 - wrapper for multi_shift_cg in BQCDi
!
!-------------------------------------------------------------------------------
!
! 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"

!-------------------------------------------------------------------------------
# define TRACE_NAME cg_wrapper_mcg
!-------------------------------------------------------------------------------
subroutine cg_wrapper_mcg(matrix, id, n, shift_switch, betabar, b, iterations, niter_shift, res) 

  use module_vol
  use module_action
  use module_field  ! contains sco
  use module_input
  use module_p_interface
  use module_cg_conf
  use module_cg_procs
  implicit none

  external                         :: matrix
  integer,             intent(in)  :: id
  integer,             intent(in)  :: n
  integer,             intent(in)  :: shift_switch(n)
  REAL,                intent(in)  :: betabar(n)
  SPINCOL_OVERINDEXED, intent(in)  :: b
  integer,             intent(out) :: iterations
  integer,             intent(out) :: niter_shift(n)
  DOUBLE,              intent(in)  :: res(n)

  integer :: i, j, cid

  P_SPINCOL_OVERINDEXED :: tmp => null()
  P_SPINCOL_OVERINDEXED :: tmp2 => null()

!-------------------------------------------------------------------------------

  TRACE_ENTRY

  CHECK(input%tuning_cg_precision == 64)

  call cg_init_modules()

  ! initialise sco:

  do j = 1, n
     call sc_zero(sco(1,j)%sco(1))
     call sc_zero_halo(sco(1,j)%sco(1))
  enddo

  do j = 1, n
     call cg_procs%copyin_spincol(sco(2,j)%sco(1), b)
  enddo

  ! standard wrapper:

  cid = action%mtilde(id)%cid

  call cg_procs%copyin_gauge(cg_conf%u, gauge(2)%u)

  call cg_procs%copyin_spincol(cg_conf%in, b)

  call cg_procs%copyin_clover(cg_conf%c_even, clover(cid)%cfield%i(1,1,EVEN))
  call cg_procs%copyin_clover(cg_conf%c_odd, clover(cid)%cfield%i(1,1,ODD))

  call cg_procs%kernel_mcg(matrix, id, n, shift_switch, betabar, cg_conf%in, iterations, niter_shift, res) 

  ! store output sco in the usual order:

  call allocate_sc_overindexed(tmp) ! this memory location will be kept in sco(1,1)%sco

  do i = 1, 2
     do j = 1, n
        tmp2         => sco(i,j)%sco
        sco(i,j)%sco => tmp
        tmp          => tmp2
        call cg_procs%copyout_spincol(sco(i,j)%sco(1), tmp(1)) 
     enddo
  enddo

  deallocate(tmp)  ! deallocates memory that sco(2,n)%sco pointed to

  TRACE_RETURN

end

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