rhooutnew.f90 Source File


Source Code

!-----------------------------------------------------------------------------------------!
! Copyright (c) 2018 Peter Grünberg Institut, Forschungszentrum Jülich, Germany           !
! This file is part of Jülich KKR code and available as free software under the conditions!
! of the MIT license as expressed in the LICENSE.md file in more detail.                  !
!-----------------------------------------------------------------------------------------!

!------------------------------------------------------------------------------------
!> Summary: Calculation of the density for the new solver
!> Author:
!> Calculation of the density for the new solver
!------------------------------------------------------------------------------------
module mod_rhooutnew

contains

  !> Summary: Calculation of the density for the new solver
  !> Author: 
  !> Category: physical-observables, KKRhost
  !> Deprecated: False 
  !> Calculation of the density for the new solver
  subroutine rhooutnew(nsra, lmax, gmatll, ek, lmpot, df, npan_tot, ncheb, cleb, icleb, iend, irmdnew, thetasnew, ifunm, imt1, lmsp, &
     rll, sll, ull, rllleft, sllleft, ullleft, cden, cdenlm, cdenns, rho2nsc, corbital, gflle_part, rpan_intervall, ipan_intervall, nspin)

    use :: mod_constants, only: cone,czero,pi
    use :: mod_runoptions, only: calc_gmat_lm_full, use_ldau, decouple_spin_cheby, calc_onsite_only
    use :: mod_profiling, only: memocc
    use :: global_variables, only: lmmaxd, ncleb, ntotd, nfund, korbit
    use :: mod_datatypes, only: dp
    use :: mod_orbitalmoment, only: calc_orbitalmoment
    use :: mod_intcheb_cell, only: intcheb_cell 

    implicit none

    integer, intent (in) :: nsra
    integer, intent (in) :: nspin
    integer, intent (in) :: lmax   !! Maximum l component in wave function expansion
    integer, intent (in) :: iend   !! Number of nonzero gaunt coefficients
    integer, intent (in) :: imt1
    integer, intent (in) :: ncheb  !! Number of Chebychev pannels for the new solver
    integer, intent (in) :: lmpot  !! (LPOT+1)**2
    integer, intent (in) :: irmdnew
    integer, intent (in) :: corbital
    integer, intent (in) :: npan_tot
    complex (kind=dp), intent (in) :: ek
    complex (kind=dp), intent (in) :: df
    integer, dimension (*), intent (in) :: lmsp !! 0,1 : non/-vanishing lm=(l,m) component of non-spherical potential
    integer, dimension (*), intent (in) :: ifunm
    integer, dimension (0:ntotd), intent (in) :: ipan_intervall
    integer, dimension (ncleb, 4), intent (in) :: icleb !! Pointer array
    real (kind=dp), dimension (*), intent (in) :: cleb !! GAUNT coefficients (GAUNT)
    real (kind=dp), dimension (0:ntotd), intent (in) :: rpan_intervall
    real (kind=dp), dimension (ntotd*(ncheb+1), nfund), intent (in) :: thetasnew
    complex (kind=dp), dimension (lmmaxd, lmmaxd), intent (in) :: gmatll !! GMATLL=diagonal elements of the G matrix (system) Note that SLL is not needed for calculation of density, only needed for calculation of Green function
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: rll
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: sll
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: ull
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: rllleft
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: sllleft
    complex (kind=dp), dimension (nsra*lmmaxd, lmmaxd, irmdnew), intent (in) :: ullleft

    ! .. Output variables
    complex (kind=dp), dimension (irmdnew, nspin*(1+korbit)), intent (out) :: cdenns
    complex (kind=dp), dimension (lmmaxd, lmmaxd), intent (out) :: gflle_part
    ! lmlm-dos
    complex (kind=dp), dimension (irmdnew, 0:lmax, nspin*(1+korbit)), intent (out) :: cden
    complex (kind=dp), dimension (irmdnew, lmmaxd/(1+korbit), nspin*(1+korbit)), intent (out) :: cdenlm

    ! .. In/Out variables
    complex (kind=dp), dimension (irmdnew, lmpot, nspin*(1+korbit)), intent (out) :: rho2nsc

    ! .. Local variables
    integer :: lmmax0d !! lm matrix size without spin doubling
    integer :: ir, jspin, lm1, lm2, lm3, m1, l1, j, ifun
    integer :: i_stat, i_all
    real (kind=dp) :: c0ll
    complex (kind=dp) :: cltdf, alpha
    integer, dimension (4) :: lmshift1
    integer, dimension (4) :: lmshift2
    complex (kind=dp), dimension (lmmaxd, lmmaxd, 3) :: loperator

    ! .. Local allocatable arrays
    complex (kind=dp), dimension (:), allocatable :: cwr ! lmlm-dos
    complex (kind=dp), dimension (:, :), allocatable :: qnsi
    complex (kind=dp), dimension (:, :), allocatable :: pnsi
    complex (kind=dp), dimension (:, :, :), allocatable :: wr
    complex (kind=dp), dimension (:, :, :), allocatable :: wr1 ! LDAU
    ! .. External routines

    lmmax0d = lmmaxd/(1+korbit)

    allocate (wr(lmmaxd,lmmaxd,irmdnew), stat=i_stat)
    call memocc(i_stat, product(shape(wr))*kind(wr), 'WR', 'RHOOUTNEW')
    wr = czero
    allocate (cwr(irmdnew), stat=i_stat)
    call memocc(i_stat, product(shape(cwr))*kind(cwr), 'CWR', 'RHOOUTNEW')
    cwr = czero
    allocate (wr1(lmmaxd,lmmaxd,irmdnew), stat=i_stat)
    call memocc(i_stat, product(shape(wr1))*kind(wr1), 'WR1', 'RHOOUTNEW')
    wr1 = czero
    allocate (qnsi(lmmaxd,lmmaxd), stat=i_stat)
    call memocc(i_stat, product(shape(qnsi))*kind(qnsi), 'QNSI', 'RHOOUTNEW')
    qnsi = czero
    allocate (pnsi(lmmaxd,lmmaxd), stat=i_stat)
    call memocc(i_stat, product(shape(pnsi))*kind(pnsi), 'PNSI', 'RHOOUTNEW')
    pnsi = czero

    ! set LMSHIFT value which is need to construct CDEN
    if (decouple_spin_cheby) then
      lmshift1(:) = 0 
      lmshift2(:) = 0 
    else
      lmshift1(1) = 0
      lmshift1(2) = lmmax0d
      lmshift1(3) = 0
      lmshift1(4) = lmmax0d
      lmshift2(1) = 0
      lmshift2(2) = lmmax0d
      lmshift2(3) = lmmax0d
      lmshift2(4) = 0
    end if

    ! for orbital moment
    if (corbital/=0) then
      call calc_orbitalmoment(lmax, lmmaxd, loperator)
    end if

    c0ll = 1e0_dp/sqrt(4e0_dp*pi)
    cden = czero
    cdenlm = czero

    ! big component of Dirac spinor
    do ir = 1, irmdnew

      ! this is the prefactor for the gmatll*rllleft term in the first zgemm
      ! if the onsite densit is calculated alone we set this to zero
      alpha = cone
      if (calc_onsite_only) alpha = czero

      do lm1 = 1, lmmaxd
        do lm2 = 1, lmmaxd
          qnsi(lm1, lm2) = sllleft(lm1, lm2, ir)
          ! PNSI(LM1,LM2)=RLL(LM1,LM2,IR)
          pnsi(lm1, lm2) = ull(lm1, lm2, ir)
        end do ! lm2
      end do ! lm1
!     call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, cone, pnsi, lmmaxd, gmatll, lmmaxd, ek, qnsi, lmmaxd)
      call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, ek, pnsi, lmmaxd, qnsi, lmmaxd, czero, wr(1,1,ir), lmmaxd)
      do lm1 = 1, lmmaxd
        do lm2 = 1, lmmaxd
          pnsi(lm1, lm2) = rllleft(lm1, lm2, ir)
        end do ! lm2
      end do ! lm1
      ! MdSD: note that this transpose is followed by another transpose in the next zgemm
      call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, alpha, pnsi, lmmaxd, gmatll, lmmaxd, czero, qnsi, lmmaxd)
      do lm1 = 1, lmmaxd
        do lm2 = 1, lmmaxd
          pnsi(lm1, lm2) = rll(lm1, lm2, ir)
        end do ! lm2
      end do ! lm1
!     call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, cone, pnsi, lmmaxd, qnsi, lmmaxd, czero, wr(1,1,ir), lmmaxd)
      call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, cone, pnsi, lmmaxd, qnsi, lmmaxd, cone, wr(1,1,ir), lmmaxd)

      ! small component of Dirac spinor
      if (nsra==2) then
        do lm1 = 1, lmmaxd
          do lm2 = 1, lmmaxd
            ! QNSI(LM1,LM2)=SLLLEFT(LM1+lmmaxd,LM2,IR)
            qnsi(lm1, lm2) = -sllleft(lm1+lmmaxd, lm2, ir)
            ! PNSI(LM1,LM2)=RLLLEFT(LM1+lmmaxd,LM2,IR)
            pnsi(lm1, lm2) = ull(lm1+lmmaxd, lm2, ir)
          end do ! lm2
        end do ! lm1
        ! CALL ZGEMM('N','N',lmmaxd,lmmaxd,lmmaxd,CONE,PNSI,
        ! +             lmmaxd,GMATLL,lmmaxd,EK,QNSI,lmmaxd)
!       call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, cone, pnsi, lmmaxd, gmatll, lmmaxd, ek, qnsi, lmmaxd)
        call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, ek, pnsi, lmmaxd, qnsi, lmmaxd, cone, wr(1,1,ir), lmmaxd)
        do lm1 = 1, lmmaxd
          do lm2 = 1, lmmaxd
              pnsi(lm1, lm2) = -rllleft(lm1+lmmaxd, lm2, ir)
          end do ! lm2
        end do ! lm1
        call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, alpha, pnsi, lmmaxd, gmatll, lmmaxd, czero, qnsi, lmmaxd)
        do lm1 = 1, lmmaxd
          do lm2 = 1, lmmaxd
            pnsi(lm1, lm2) = rll(lm1+lmmaxd, lm2, ir)
          end do ! lm2
        end do ! lm1
        call zgemm('N', 'T', lmmaxd, lmmaxd, lmmaxd, cone, pnsi, lmmaxd, qnsi, lmmaxd, cone, wr(1,1,ir), lmmaxd)
      end if ! small component

      ! For orbital moment
      if (corbital/=0) then
        call zgemm('N', 'N', lmmaxd, lmmaxd, lmmaxd, cone, loperator(1,1,corbital), lmmaxd, wr(1,1,ir), lmmaxd, czero, pnsi, lmmaxd)
        do lm1 = 1, lmmaxd
          do lm2 = 1, lmmaxd
            wr(lm1, lm2, ir) = pnsi(lm1, lm2)
          end do
        end do
      end if ! corbital/=0

      ! copy wr to wr1 and sum upper half onto lower half (only the latter is used for ldau)
      if (calc_gmat_lm_full .and. use_ldau) stop 'LDAU and gflle writeout do not work together'
      do lm1 = 1, lmmaxd
        do lm2 = 1, lmmaxd
          wr1(lm1, lm2, ir) = wr(lm1, lm2, ir)
        end do ! lm2
      end do ! lm1
      if (use_ldau) then
        ! sum the upper onto the lower half only for ldau, gflle writeout should have the unchanged array!
        do lm1 = 1, lmmaxd
          do lm2 = 1, lm1 - 1
            wr1(lm1, lm2, ir) = wr1(lm1, lm2, ir) + wr1(lm2, lm1, ir)
          end do ! lm2
        end do ! lm1
      end if ! use_ldau

      do jspin = 1, nspin*(1+korbit)
        do lm1 = 1, lmmax0d
          do lm2 = 1, lm1 - 1
            wr(lm1+lmshift1(jspin), lm2+lmshift2(jspin), ir) =                      &
              wr(lm1+lmshift1(jspin), lm2+lmshift2(jspin), ir) +                    &
              wr(lm2+lmshift1(jspin), lm1+lmshift2(jspin), ir)
          end do ! lm2
        end do ! lm1
      end do ! JSPIN

    end do ! IR


    ! IF lmdos or LDAU
    if (calc_gmat_lm_full .or. use_ldau) then ! lmlm-dos
      ! Integrate only up to muffin-tin radius.
      ! ! lmlm-dos
      gflle_part = czero           ! lmlm-dos
      do lm2 = 1, lmmaxd          ! lmlm-dos
        do lm1 = 1, lmmaxd        ! lmlm-dos
          ! For integration up to MT radius do this:                    ! lmlm-dos
          ! CWR(1:IMT1) = WR(LM1,LM2,1:IMT1)                            ! lmlm-dos
          ! CWR(IMT1+1:IRMDNEW) = CZERO                                 ! lmlm-dos
          ! CALL INTCHEB_CELL(CWR,GFLLE_PART(LM1,LM2),RPAN_INTERVALL, & ! lmlm-dos
          ! IPAN_INTERVALL,NPAN_TOT,NCHEB,IRMDNEW)                      ! lmlm-dos
          ! For full cell integration replace loop content with this:   ! lmlm-dos
          cwr(1:irmdnew) = wr1(lm1, lm2, 1:irmdnew) ! lmlm-dos
          ! If LDAU, integrate only up to MT
          do ir = imt1 + 1, irmdnew
            if (use_ldau) then
              cwr(ir) = czero      ! LDAU
            else
              cwr(ir) = cwr(ir)*thetasnew(ir, 1)*c0ll ! lmlm-dos
            end if
          end do
          call intcheb_cell(cwr, gflle_part(lm1,lm2), rpan_intervall, ipan_intervall, npan_tot, ncheb, irmdnew)
        end do
      end do
    end if                         ! calc_gmat_lm_full .or. use_ldau


    ! DO IR = 1,IRMDNEW
    ! DO JSPIN = 1,4
    ! DO LM1 = 1,lmmax0d
    ! DO LM2 = 1,LM1-1
    ! WR(LM1+LMSHIFT1(JSPIN),LM2+LMSHIFT2(JSPIN),IR)=
    ! +           WR(LM1+LMSHIFT1(JSPIN),LM2+LMSHIFT2(JSPIN),IR)+
    ! +           WR(LM2+LMSHIFT1(JSPIN),LM1+LMSHIFT2(JSPIN),IR)
    ! ENDDO
    ! ENDDO
    ! ENDDO ! JSPIN
    ! ENDDO !IR

    ! First calculate the spherical symmetric contribution

    do l1 = 0, lmax
      do m1 = -l1, l1
        lm1 = l1*(l1+1) + m1 + 1
        do ir = 1, irmdnew
          do jspin = 1, nspin*(1+korbit)
            cden(ir, l1, jspin) = cden(ir, l1, jspin) + wr(lm1+lmshift1(jspin), lm1+lmshift2(jspin), ir)
            cdenlm(ir, lm1, jspin) = wr(lm1+lmshift1(jspin), lm1+lmshift2(jspin), ir)
          end do                   ! JPSIN
        end do                     ! IR
      end do                       ! M1

      do jspin = 1, nspin*(1+korbit)
        do ir = 1, irmdnew
          rho2nsc(ir, 1, jspin) = rho2nsc(ir, 1, jspin) + c0ll*(cden(ir,l1,jspin)*df)
        end do                     ! IR

        do ir = imt1 + 1, irmdnew
          cden(ir, l1, jspin) = cden(ir, l1, jspin)*thetasnew(ir, 1)*c0ll
          do m1 = -l1, l1
            lm1 = l1*(l1+1) + m1 + 1
            cdenlm(ir, lm1, jspin) = cdenlm(ir, lm1, jspin)*thetasnew(ir, 1)*c0ll
          end do                   ! M1
        end do                     ! IR
      end do                       ! JSPIN
    end do                         ! L1

    ! Then the non-spherical part

    cdenns = czero
    do j = 1, iend
      lm1 = icleb(j, 1)
      lm2 = icleb(j, 2)
      lm3 = icleb(j, 3)
      cltdf = df*cleb(j)
      do jspin = 1, nspin*(1+korbit)
        do ir = 1, irmdnew
          rho2nsc(ir, lm3, jspin) = rho2nsc(ir, lm3, jspin) + (cltdf*wr(lm1+lmshift1(jspin),lm2+lmshift2(jspin),ir))
        end do

        if (lmsp(lm3)>0) then
          ifun = ifunm(lm3)
          do ir = imt1 + 1, irmdnew
            cdenns(ir, jspin) = cdenns(ir, jspin) + cleb(j)*wr(lm1+lmshift1(jspin), lm2+lmshift2(jspin), ir)*thetasnew(ir, ifun)
          end do
        end if
      end do                       ! JSPIN
    end do                         ! J


    i_all = -product(shape(wr))*kind(wr)
    deallocate (wr, stat=i_stat)
    call memocc(i_stat, i_all, 'WR', 'RHOOUTNEW')
    i_all = -product(shape(wr1))*kind(wr1)
    deallocate (wr1, stat=i_stat)
    call memocc(i_stat, i_all, 'WR1', 'RHOOUTNEW')
    i_all = -product(shape(cwr))*kind(cwr)
    deallocate (cwr, stat=i_stat)
    call memocc(i_stat, i_all, 'CWR', 'RHOOUTNEW')
    i_all = -product(shape(qnsi))*kind(qnsi)
    deallocate (qnsi, stat=i_stat)
    call memocc(i_stat, i_all, 'QNSI', 'RHOOUTNEW')
    i_all = -product(shape(pnsi))*kind(pnsi)
    deallocate (pnsi, stat=i_stat)
    call memocc(i_stat, i_all, 'PNSI', 'RHOOUTNEW')

  end subroutine rhooutnew

end module mod_rhooutnew