!=======================================================================
!
!  PROGRAM  PHASE/0 2015.01 ($Rev: 440 $)
!
!  SUBROUINE: ChargeDensity_Mixing
!
!  AUTHOR(S): T. Yamasaki   August/20/2003
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!  
!
!
!=======================================================================
!
!     The original version of this set of the computer programs "PHASE"
!  was developed by the members of the Theory Group of Joint Research
!  Center for Atom Technology (JRCAT), based in Tsukuba, in the period
!  1993-2001.
!
!     Since 2002, this set has been tuned and new functions have been
!  added to it as a part of the national project "Frontier Simulation 
!  Software for Industrial Science (FSIS)",  which is supported by
!  the IT program of the Ministry of Education, Culture, Sports,
!  Science and Technology (MEXT) of Japan. 
!     Since 2006, this program set has been developed as a part of the
!  national project "Revolutionary Simulation Software (RSS21)", which
!  is supported by the next-generation IT program of MEXT of Japan.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium.
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
subroutine ChargeDensity_Mixing
! $Id: ChargeDensity_Mixing.F90 440 2015-08-03 07:18:01Z ktagami $
  use m_Const_Parameters,    only : DP,SIMPLE,BROYD1,BROYD2,DFP,PULAY,RMM2P,ON &
       &                          , FIXED_CHARGE, FIXED_CHARGE_CONTINUATION, CONTINUATION, SKIP
  use m_Charge_Density,      only : m_CD_check
  use m_CD_mixing,           only : m_CD_simple_mixing, m_CD_prepare_precon &
       &                           ,m_CD_mix_broyden1,m_CD_mix_broyden2,m_CD_mix_DFP &
       &                           ,m_CD_mix_pulay, m_CD_simple_mixing_hsr
  use m_Ionic_System,        only : natm
  use m_Total_Energy,        only : m_TE_what_is_edeltb_now
  use m_Control_Parameters,  only : c_precon,waymix,intzaj,icond &
       &                          , tag_solver_of_WF_is_found &
       &                          , tag_charge_mixing_is_found &
       &                          , iprichargemixing, nspin, af &
       &                          , m_CtrlP_rmx_now &
       &                          , m_CtrlP_solver_for_WFs_now &
       &                          , m_CtrlP_set_rmx &
       &                          , m_CtrlP_waymix_now &
       &                          , m_CtrlP_set_mix_parameter &
       &                          , sw_hubbard
  use m_Files,               only : nfout
  use m_IterationNumbers,    only : iteration_electronic, iteration_ionic &
       &                          , m_Iter_cmix_reset
  use m_Orbital_Population,  only : m_OP_simple_mixing, m_OP_mix_broyden1 &
       &                          , m_OP_mix_broyden2, m_OP_mix_DFP, m_OP_mix_pulay
  use m_PseudoPotential,     only : flg_paw, modnrm
! ================================= added by K. Tagami =============== 5.0
  use m_Const_Parameters,    only : OFF
  use m_Control_Parameters,  only : sw_update_charge_total, &
       &                            sw_mix_charge_hardpart, occ_matrix_mixfactor
  use m_Charge_Density,      only : m_CD_cp_hsr_to_hsro
  use m_CD_mixing,           only : m_CD_mix_broyden2_with_hsr, m_CD_mix_pulay_with_hsr &
                                  , m_CD_simple_mixing_hard
  use m_IterationNumbers,     only : iteration, iteration_for_cmix
  use m_Orbital_Population,    only :  m_OP_cp_om_to_ommix
! ==================================================================== 5.0


! ================================= added by K. Tagami ================== 11.0
  use m_Control_Parameters,   only : noncol,hardpart_mixfactor
!!  use m_Charge_Density,      only : m_CD_check_noncl,  &
!!       &                            m_CD_estim_magmom_local
! ======================================================================== 11.0


  implicit none

  real(kind=DP) :: rmxt
  real(kind=DP) :: edeltb_per_atom
  integer,save  :: waymix_at_CDmix_previous = 0
  integer       :: waymix_at_CDmix
  logical       :: ini = .false.
  real(kind=DP) :: rmxt_tot, rmxt_hard, rmxt_occmat
#ifdef __TIMER_SUB__
    call timer_sta(1101)
#endif
  if(icond == FIXED_CHARGE .or. icond == FIXED_CHARGE_CONTINUATION) return

  edeltb_per_atom = m_TE_what_is_edeltb_now()/natm 
  waymix_at_CDmix = m_CtrlP_waymix_now(iteration_electronic, iteration_ionic &
       &                             , edeltb_per_atom)
  if(tag_solver_of_WF_is_found .and. tag_charge_mixing_is_found) then
     if(waymix_at_CDmix_previous /= waymix_at_CDmix) call m_Iter_cmix_reset()
  end if

  rmxt = m_CtrlP_rmx_now(iteration_electronic, iteration_ionic)
  call m_CtrlP_set_mix_parameter()
  if(c_precon) call m_CD_prepare_precon(nfout,rmxt)
  if(iprichargemixing >= 2) &
       & write(6,'(" waymix_at_CDmix = ",i4," rmxt = ",f8.4)') waymix_at_CDmix, rmxt

! ===================== added by K. Tagami========================= 5.0
  if ( sw_update_charge_total == OFF ) then
     iteration_for_cmix = iteration_for_cmix -1
  endif
  if ( iteration <= 1 .or. (icond==CONTINUATION .and. .not.ini))then
     call m_CD_cp_hsr_to_hsro
     ini = .true.
  endif
!
  rmxt_tot = rmxt
  rmxt_hard = rmxt *hardpart_mixfactor
!
  rmxt_occmat = rmxt *occ_matrix_mixfactor
!

     if ( sw_update_charge_total == ON ) then
        if ( modnrm == SKIP .or. sw_mix_charge_hardpart == OFF ) then
           call mix_charge_total()
           if ( flg_paw ) call mix_charge_only_hsr          !! only exception
           if ( sw_hubbard == ON ) call mix_charge_only_occmat
        else
           call mix_charge_total_with_hsr()
        endif
     endif
! ================================================================= 5.0


  call m_CD_check(nfout)

  if(tag_solver_of_WF_is_found .and. tag_charge_mixing_is_found) then
     waymix_at_CDmix_previous = waymix_at_CDmix
  end if

#ifdef __TIMER_SUB__
    call timer_end(1101)
#endif


contains

  subroutine mix_charge_total()
    mixing_way: select case(waymix_at_CDmix)
    case (SIMPLE)
       call m_CD_simple_mixing(nfout,rmxt_tot)
    case (BROYD1)
       call m_CD_mix_broyden1(rmxt_tot)
    case (BROYD2)
       call m_CD_mix_broyden2(nfout,rmxt_tot)
    case (DFP)
       call m_CD_mix_DFP(rmxt_tot)
    case (PULAY)
       call m_CD_mix_pulay(nfout,rmxt_tot)
    case default
       stop ' ! waymix is invalid'
    end select mixing_way

  end subroutine mix_charge_total

  subroutine mix_charge_only_hsr
     call m_CD_simple_mixing_hsr(nfout,rmxt)
  end subroutine mix_charge_only_hsr

  subroutine mix_charge_only_occmat
    mixing_way: select case(waymix_at_CDmix)
    case (SIMPLE)
        call m_OP_simple_mixing(nfout,rmxt_occmat)
    case (BROYD1)
        call m_OP_mix_broyden1(rmxt_occmat)
    case (BROYD2)
        call m_OP_mix_broyden2(rmxt_occmat)
    case (DFP)
        call m_OP_mix_DFP(rmxt_occmat)
    case (PULAY)
        call m_OP_mix_Pulay(rmxt_occmat)
    case default
       stop ' ! waymix is invalid'
    end select mixing_way

  end subroutine mix_charge_only_occmat

  subroutine mix_charge_total_with_hsr()
    mixing_way: select case(waymix_at_CDmix)

    case (SIMPLE)
       call m_CD_simple_mixing( nfout,rmxt_tot )
       call m_CD_simple_mixing_hard( nfout, rmxt_hard )
       if ( sw_hubbard == ON ) then
          call Renewal_of_OccMat( .false., ON )           ! hsr --> om 
          call m_OP_cp_om_to_ommix( nfout, rmxt_hard )       ! om --> ommix
       endif

    case (BROYD1)
!       call m_CD_mix_broyden1_with_hsr(rmxt_tot)
       write(*,*) 'Not supported '
       stop

    case (BROYD2)
       call m_CD_mix_broyden2_with_hsr(nfout,rmxt_tot)
       if ( sw_hubbard == ON ) then
          call Renewal_of_OccMat(.false., ON )           ! hsr --> om 
          call m_OP_cp_om_to_ommix( nfout, rmxt_hard )       ! om --> ommix
       endif

    case (DFP)
!       call m_CD_mix_DFP(rmxt_tot)
       write(*,*) 'Not supported '
       stop
    case (PULAY)
       call m_CD_mix_pulay_with_hsr(nfout,rmxt_tot)
       if ( sw_hubbard == ON ) then
          call Renewal_of_OccMat(.false., ON )           ! hsr --> om 
          call m_OP_cp_om_to_ommix( nfout, rmxt_hard )       ! om --> ommix
       endif
    case default
       stop ' ! waymix is invalid'
    end select mixing_way
  end subroutine mix_charge_total_with_hsr


end subroutine ChargeDensity_Mixing
