!===============================================================================
!
! clover_action.F90
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2007-2008 Yoshifumi Nakamura
!
! 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/>.
!
!-------------------------------------------------------------------------------
# include "defs.h"

!-------------------------------------------------------------------------------
subroutine clover_action_sum(sum)
  use module_switches
  use module_action
  use module_input
  implicit none
  REAL, intent(out) :: sum
  REAL :: tmp

  sum=0

  if (.not. switches%clover) return
  if (input%hmc_dsd == 0 )   return

#ifdef OMTDTD
  call clover_action_sum_eo(tmp, se)
  call clover_action_sum_eo(sum, so)
  sum = sum + tmp
#else
  call clover_action_sum_eo(sum, so)
#endif
end

!-------------------------------------------------------------------------------
subroutine clover_action_sum_eo(sum, eo)
  use module_field
  use module_action 
  use module_vol
  implicit none
  REAL, intent(out) :: sum
  integer, intent(in) :: eo
  REAL, external    :: clover_action
  REAL, external    :: clover_action12
  integer           :: i, cid
  REAL :: diff, lambda, nf

  sum = ZERO
#ifdef GAMMAC
  diff = dble(volume) * log(64.0_8)
#else
  diff = ZERO
#endif

  do i = 1, n_logdet
     cid    = action%logdet(i)%cid
     nf     = clvpar(cid)%nf
     lambda = clvpar(cid)%lambda
     call init_clover(cid)
     if (lambda == ZERO .and. finv_axion == ZERO) then
     sum = sum + ( &
                   clover_action(clover(cid)%cfield%b(1,1,eo))/dble(2) - diff &
                 ) * nf
     else
     diff = dble(volume) * log(16.0_8)
     sum = sum + ( &
                   clover_action12(clover(cid)%cfield12%det(1,eo))/dble(2) - diff &
                 ) * nf
     endif
  enddo
end

!-------------------------------------------------------------------------------
subroutine dsd(p, p_axion, step)
  use module_vol
  use module_switches
  use module_action
  implicit none
  GENERATOR_FIELD,  intent(inout) :: p
  AXION_MOMENTUM_FIELD, intent(inout) :: p_axion
  REAL,             intent(in)    :: step

  !!if (switches%qed) then
  !!   p = ZERO
  !!   return
  !!endif

  if (step == ZERO .or. (.not. switches%clover)) return

  TIMING_START(timing_bin_clover_dsd)
  DEBUG2S("Start: dsd")

  call hmc_forces_old(p)
#ifdef OMTDTD
  call dsd_eo(p, p_axion, step, se)
  call dsd_eo(p, p_axion, step, so)
#else
  call dsd_eo(p, p_axion, step, so)
#endif
#ifdef BQCD_DDHMC
  call nonactive(p) !! for ddhmc
#endif
  call hmc_forces_new(p, step, action%logdet(1)%fid)

  DEBUG2S("End: dsd")
  TIMING_STOP(timing_bin_clover_dsd)

end

!-------------------------------------------------------------------------------
subroutine dsd_eo(p, p_axion, step, eo)
  use module_field
  use module_action
  use module_vol
  implicit none

  GENERATOR_FIELD, intent(inout) :: p
  AXION_MOMENTUM_FIELD, intent(inout) :: p_axion
  REAL,            intent(in)    :: step
  integer, intent(in) :: eo
  REAL :: s, sa
  integer :: i, cid
  COMPLEX, dimension(NDIRAC, NDIRAC, NCOL, NCOL, volh) :: t

  COMPLEX, allocatable :: w(:, :, :, :, :)
  COMPLEX, allocatable :: ww(:, :, :, :, :)

  allocate(w(NCOL, NCOL, volh_tot, EVEN:ODD, DIM))
  allocate(ww(NCOL, NCOL, volh_tot, EVEN:ODD, DIM))

  w = ZERO
  do i = 1, n_logdet
     cid = action%logdet(i)%cid
     call init_clover(cid)
     s = -step * clvpar(cid)%cswkappa * dble(clvpar(cid)%nf) / EIGHT
     sa=  step * finv_axion           * dble(clvpar(cid)%nf)
     call clover_dsd_w(eo, w, cid, s, t)
     if (finv_axion /= ZERO)call clover_dsd_axion(p_axion, eo, sa, t)
  enddo

  call clover_d_w(ww, gauge(3)%u(1,1,1,0,1), w, eo)
  if (gauge(3)%sid /= 0) call dstout(ww, 1)
  call gen_m_force(p, ww, gauge(1)%u)

  deallocate(w, ww)

end

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