!===============================================================================
!
! cg_dd_mix.F90 - mixed precision cg
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2009 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 cg_dd_mix(matrix, x, b, id, ip, iter, res) 
  use module_function_decl
  use module_check_solution
  use module_dd
  use module_action
  use module_mre2
  use mre2_get_interface  
  use module_cg
  use vec
  implicit none
  type(type_mre2), save :: solutions

  complex(8), dimension(12*ld%lat%volh),         intent(inout):: x
  complex(8), dimension(12*ld%lat%volh), target, intent(in)   :: b
  integer, intent(out):: iter
  integer, intent(in) :: id, ip, matrix
  REAL,    intent(in) :: res

  complex(8),pointer :: tmp(:)
  complex(8),target  :: r(size(x)),p(size(b))
  REAL    :: rtr, rtr0, bb
  integer :: niter,iter4
  integer, external :: cg_dd_inner
  external :: wtmul_dd, mtmul_dd

!-------------------------------------------------------------------------------
  DEBUG2S("Start: cg_dd_mix")

  iter4 = 0
  tmp=>b
  bb = vec_norm2_c8(tmp)
  if (matrix == WTDAGWT_DD) then
     call wtdagwt_dd(r, x, id, ip)
  else
     call mtdagmt_dd(r, x, id, ip)
  endif
  niter = 1
  tmp=>r
  rtr=vec_norm2_c8(tmp)
  if (stop_condition(rtr, res, bb)) goto 9999
  rtr0=rtr

  do niter = 1, outer_steps
     if (matrix == WTDAGWT_DD) then
        call mre2_get(wtmul_dd, solutions, p, r, id, ip)
     else
        call mre2_get(mtmul_dd, solutions, p, r, id, ip)
     endif
     iter4 = iter4 + cg_dd_inner(matrix, p, r, id, ip, res_cg_inner(res, rtr0, bb, niter))
     call mre2_put(solutions, p, 0, size(p))
     x = x + p


     if (matrix == WTDAGWT_DD) then
        call wtdagwt_dd(r, x, id, ip)
     else
        call mtdagmt_dd(r, x, id, ip)
     endif
     r = b - r

     tmp=>r
     rtr=vec_norm2_c8(tmp)
     if (stop_condition(rtr, res, bb)) goto 9999

#ifdef DEBUG2
     if(my_pe()==0)write(0,*)niter,"ddmixrtr",rtr
#endif
  enddo

  call cg_dd(matrix, x, b, id, ip, niter, res)
  niter = niter + outer_steps + 1

9999 continue
  call mre2_put(solutions, p, 1, size(p))
  iter = niter
  call update_cg_stat(dd_stat, iter, 0)
  DEBUG2S("End: cg_dd_mix")
end

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