torque.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 magnetic torque methods
!> Author: Sascha Brinker
!> 
!> 
!> 
!> 
!> 
!------------------------------------------------------------------------------------
module mod_torque

contains

  !-------------------------------------------------------------------------------
  !> Summary: Calculation of the density for the new solver
  !> Author: Sascha Brinker
  !> Category: KKRhost
  !> Deprecated: False 
  !> Calculation of the magnetic torque in the new solver
  !> The routine uses rho2nsc to calculate the magnetic moment in the global
  !> frame from which the torque is calculated using the xc magnetic field.
  !> The XC magnetic field is extracted from the potential (convoluted with the
  !> shape function) thus rho2nsc has to be used instead of cden and cdenns!
  !-------------------------------------------------------------------------------
  subroutine calc_torque(iatom, lmax, irmdnew, nspin, bfield, rpan_intervall, &
                         ipan_intervall, npan_log, npan_eq, npan_tot, ncheb, &
                         theta, phi, rho2nsc, vpot, ifunm, iend, icleb, cleb, &
                         thetasnew, bconstr, fix_direction, icell)
    
    use :: global_variables, only: lmmaxd, ncleb, ntotd, nfund, korbit, lmpotd
    use :: mod_datatypes, only: dp
    use :: mod_bfield, only: type_bfield
    use :: mod_intcheb_cell, only: intcheb_cell
    use :: mod_rotatespinframe, only: rotatematrix!, rotatevector
    use :: mod_types, only: t_inc

    implicit none

    integer, intent (in)                                                        :: iatom  !! Currently treated atom index
    integer, intent (in)                                                        :: lmax   !! Maximum l component in wave function expansion
    integer, intent (in)                                                        :: irmdnew
    integer, intent (in)                                                        :: nspin
    type(type_bfield), intent(inout)                                            :: bfield !! Information about the external and constraint magnetic fields
    real (kind=dp), dimension (0:ntotd), intent (in)                            :: rpan_intervall
    integer, dimension (0:ntotd), intent (in)                                   :: ipan_intervall
    integer, intent (in)                                                        :: npan_log
    integer, intent (in)                                                        :: npan_eq
    integer, intent (in)                                                        :: npan_tot
    integer, intent (in)                                                        :: ncheb  !! Number of Chebychev pannels for the new solver
    real (kind=dp), intent(in)                                                  :: theta ! polar angle of the local frame
    real (kind=dp), intent(in)                                                  :: phi   ! azimuthal angle of the local frame
    complex (kind=dp), dimension (irmdnew,lmpotd        , 2*nspin), intent (in) :: rho2nsc ! complex density matrix (does not contain the shapefun!)
    real (kind=dp), dimension (irmdnew,lmpotd       ,nspin)                     :: vpot  ! vpot in the new mesh!! corresponds to the vinsnew in main1c but only for the two spin channels and vins in rhovalnew!
    integer              , dimension (1:(2*lmax+1)**2)            , intent (in) :: ifunm        ! pointer array for shapefun     ! Check index and dimensions!!!!!
    integer              , intent (in)                                          :: iend         ! Number of nonzero gaunt coefficients
    integer, dimension (ncleb, 4), intent (in)                                  :: icleb !! Pointer array
    real (kind=dp), dimension (ncleb), intent (in)                              :: cleb !! GAUNT coefficients (GAUNT)    ! CHECK THE DIMENSION AND HOW IT IS USED!!!
    real (kind=dp)       , dimension (irmdnew, nfund)   , intent (in)           :: thetasnew    ! shapefun on the Cheby mesh
    real (kind=dp)       , dimension (4)   , intent (out)                       :: bconstr    ! variables to be saved
    logical, intent(in)                                                         :: fix_direction ! Constrain the direction of the magnetic moment of the current atom
    integer, intent(in)                                                         :: icell
    
    !------------------------------------------------------------------------------------
    ! local variables
    !------------------------------------------------------------------------------------
    integer                      :: ispin
    integer                      :: ir
    integer                      :: ilm
    integer                      :: i
    integer                      :: j
    integer                      :: lm1
    integer                      :: lm2
    integer                      :: lm3
    integer                      :: ifun
    integer                      :: imt1  ! muffin-tin radius in the new mesh
    integer                      :: lmmax
    real(kind=dp),    parameter  :: small = 1.d-6
    real(kind=dp)                :: tempreal
    real(kind=dp)                :: tot_mag_moment
    double complex               :: cone
    double complex               :: temp
    double complex               :: temp2
    real(kind=dp),parameter      :: rfpi=3.5449077018110318
    real(kind=dp)                :: totmag  !! total magnetic moment
    real(kind=dp)                :: totmagmoment  !! total magnetic moment
    real(kind=dp)                :: bfac
    double complex,dimension(2,2)                               :: rho2ns_temp
    double complex,dimension(2,2)                               :: vpot_tmp
    real(kind=dp),dimension(3)                                  :: torque    ! magnetic torque
    real(kind=dp),dimension(3)                                  :: torque_mt ! magnetic torque calcualte from mt only
    real(kind=dp),dimension(3)                                  :: magdir !initial magnetization direction
    real(kind=dp),dimension(3)                                  :: magmoment  !! magnetic moment in local frame
    real(kind=dp),dimension(3)                                  :: c_old
    real(kind=dp),dimension(3)                                  :: magdir_it
    real(kind=dp),dimension(3)                                  :: magdir_old
    real(kind=dp),dimension(1:irmdnew,1:lmpotd)          :: bxc
    real(kind=dp),dimension(1:irmdnew,1:lmpotd,1:3)      :: mag_den_glob ! magnetization density in in the global frame (no shapefun)
    real(kind=dp),dimension(1:irmdnew,1:(lmax+1)**2 ,1:3)      :: mag_den_convol ! magnetization density convoluted with the shapefunction
    real(kind=dp),dimension(1:(lmax+1)**2 ,1:3)                :: mag ! integrated lm-resolved magnetic moment
    real(kind=dp),dimension(1:(lmax+1)**2 ,1:3)                :: mag_mt ! integrated lm-resolved magnetic moment in the muffin-tin
    double complex,dimension(1:irmdnew)                         :: integrand
    !------------------------------------------------------------------------------------
    
    !write(*,'(" >>>>>> entering calctorque >>>>>>>>>")')
    if (t_inc%i_write>1) write(1337,'("===============================================================================")')
    if (t_inc%i_write>1) write(1337,'("                      Magnetic torques for atom ",i4)') iatom
    if (t_inc%i_write>1) write(1337,'("===============================================================================")')
    
    lmmax=(lmax+1)**2
    cone  = (1d0,0d0)
    imt1 = ipan_intervall(npan_log + npan_eq) + 1
    
    !write(*,'(" imt1, irmdnew, lmmax",2i4)') imt1, irmdnew, lmmax
    
    ! bxc is constructed from the potential in the new mesh 
    bxc(:,:) = 0.d0
    bxc(:,:) = (vpot(:,:,1)-vpot(:,:,2))/2.d0
    !do ilm= 1,lmpotd
    !  write(*,'("ilm,vpot1=",i4,1000es16.8)') ilm, vpot(:,ilm,1)
    !  write(*,'("ilm,vpot2=",i4,1000es16.8)') ilm, vpot(:,ilm,2)
    !end do
    !do ilm= 1,lmpotd
    !  write(*,'("ilm,bxc=",i4,1000es16.8)') ilm, bxc(:,ilm)
    !end do
    
    !rotate rho2nsc to the global frame and calculate the magnetization density
    mag_den_glob(:,:,:) = 0.d0
    do ilm=1,lmpotd
      do ir=1,irmdnew
        rho2ns_temp(1,1)            = rho2nsc(ir,ilm,1)
        rho2ns_temp(2,2)            = rho2nsc(ir,ilm,2)
        rho2ns_temp(1,2)            = rho2nsc(ir,ilm,3)
        rho2ns_temp(2,1)            = rho2nsc(ir,ilm,4)
        call rotatematrix(rho2ns_temp, theta, phi, 1, 0)
        mag_den_glob(ir,ilm,1)      = aimag( rho2ns_temp(1,2) + rho2ns_temp(2,1) ) 
        mag_den_glob(ir,ilm,2)      = real( rho2ns_temp(2,1) - rho2ns_temp(1,2) )
        mag_den_glob(ir,ilm,3)      = aimag( rho2ns_temp(2,2) - rho2ns_temp(1,1) )
      end do !ir
    end do !ilm

    ! --------------------------------------------------------------------------------------
    ! Mangetic moment in the new mesh (mainly to separate the moment in r<rmt
    ! and get acess to lm components
    mag_den_convol(:,:,:)=0.d0
    call calc_magmom_newmesh(lmax,imt1,irmdnew,icell,iend,ifunm,icleb,cleb,thetasnew,mag_den_glob,mag_den_convol)
    do i= 1,3
      do ilm=1,lmmax 
          integrand(:) = (0.d0,0.d0)
          temp= (0.d0,0.d0)
          integrand(:) = mag_den_convol(:,ilm,i)*cone
          call intcheb_cell(integrand(:),temp,rpan_intervall,ipan_intervall,npan_tot,ncheb,irmdnew)
          mag(ilm,i) = real(temp*rfpi)    
          ! same for mt only
          integrand(:) = (0.d0,0.d0)
          temp= (0.d0,0.d0)
          integrand(:imt1) = mag_den_convol(:imt1,ilm,i)*cone
          call intcheb_cell(integrand(:),temp,rpan_intervall,ipan_intervall,npan_tot,ncheb,irmdnew)
          mag_mt(ilm,i) = real(temp*rfpi)    
      end do
    end do

    if (t_inc%i_write>1) then
      write(1337,'("Magnetic moment")') 
      do ilm=1,lmmax  
        write(1337,'("iatom, ilm, mag, mag_mt",2i4,6es16.8)') iatom, ilm, mag(ilm,:), mag_mt(ilm,:)
      end do
    end if

    ! MdSD: muffin-tin or full cell, these will be used below
    if (bfield%lbfield_mt) then
      totmag = sqrt(dot_product(mag_mt(1,:),mag_mt(1,:)))
      magdir_it = mag_mt(1,:)/totmag
    else
      totmag = sqrt(dot_product(mag(1,:),mag(1,:)))
      magdir_it = mag(1,:)/totmag
    end if
    ! MdSD: constraining fields
    bconstr(1:3) = 0.0_dp; bconstr(4) = totmag

    ! --------------------------------------------------------------------------------------
    
    !do ilm= 1,lmpotd
    !  !write(*,'("ilm,mag_den_glob1=",i4,1000es16.8)') ilm, mag_den_glob(:,ilm,1)
    !  !write(*,'("ilm,mag_den_glob2=",i4,1000es16.8)') ilm, mag_den_glob(:,ilm,2)
    !  write(*,'("ilm,mag_den_glob3=",i4,1000es16.8)') ilm, mag_den_glob(:,ilm,3)
    !end do

    ! calculate the torque
    ! sum_L int dr r^2 m_L(r) B_L^xc(r)
    torque(:)=0.d0
    torque_mt(:)=0.d0
    do i=1,3
      if ( .False. ) then
        integrand(:) = (0.d0,0.d0)
        integrand(:) = bxc(:,1)*mag_den_glob(:,1,i)*cone
        call intcheb_cell(integrand(:),temp,rpan_intervall,ipan_intervall,npan_tot,ncheb,irmdnew)
        torque(i) = Dreal(temp*rfpi) ! this is a spherical quantity =>sqrt(4*pi)
      else
        do ilm=1,lmmaxd
          integrand(:) = (0.d0,0.d0)
          temp= (0.d0,0.d0)
          integrand(:) = bxc(:,ilm)*mag_den_glob(:,ilm,i)*cone
          call intcheb_cell(integrand(:),temp,rpan_intervall,ipan_intervall,npan_tot,ncheb,irmdnew)
          torque(i) = torque(i) + real(temp*rfpi) ! rfpi only contained in convoluted quantities 
          integrand(:) = (0.d0,0.d0)
          temp= (0.d0,0.d0)
          integrand(:imt1) = bxc(:imt1,ilm)*mag_den_glob(:imt1,ilm,i)*cone
          call intcheb_cell(integrand(:),temp,rpan_intervall,ipan_intervall,npan_tot,ncheb,irmdnew)
          torque_mt(i) = torque_mt(i) + real(temp*rfpi) ! rfpi only contained in convoluted quantities 
        end do !ilm
      end if
    end do !i
    
    if (t_inc%i_write>1) write(1337,'("iatom, torque, torque_mt = ",i4,6es16.8)') iatom, torque(:), torque_mt(:)
    
    
    ! --------------------------------------------------------------------------------------
    ! calculate the perpendicular component of the torque
    ! MdSD: here theta and phi are the input/fixed angles
    magdir(1) = sin(theta)*cos(phi)
    magdir(2) = sin(theta)*sin(phi)
    magdir(3) = cos(theta)
    torque(:) = torque(:) - magdir*dot_product(magdir(:),torque(:))
    torque_mt(:) = torque_mt(:) - magdir*dot_product(magdir(:),torque_mt(:))
    if (t_inc%i_write>1) write(1337,'("iatom, torque_perp, torque_mt_perp = ",i4,6es16.8)') iatom, torque(:), torque_mt(:)

    ! MdSD: muffin-tin or full cell
    if (bfield%lbfield_mt) then
      bfield%mag_torque(iatom,:) = torque_mt(:)
      torque(:) = torque_mt(:)  ! to use below and avoid another if-statement
    else
      bfield%mag_torque(iatom,:) = torque(:)
    end if

    if(bfield%lbfield_constr .and. t_inc%i_iteration>=bfield%itscf0 .and. t_inc%i_iteration<=bfield%itscf1) then !constraining fields
      if(bfield%ibfield_constr == 0 ) then ! constraining fields based on magnetic torques
        ! sum up the torques for all iterations, which yields a scf with constraining fields
        bfac = 1.d0
        if(fix_direction) then
          bfield%bfield_constr(iatom,:) = bfield%bfield_constr(iatom,:) - torque(:)/totmag*bfac
        end if
        !bfield%bfield_strength_constr         = sqrt(dot_product(bfield%bfield_constr(:),bfield%bfield_constr(:))) 
        !bfield%theta_constr                   = acos(bfield%bfield_constr(3)/bfield%bfield_strength_constr)
        !bfield%phi_constr                     = datan2(bfield%bfield_constr(2),bfield%bfield_constr(1))
        if (t_inc%i_write>1) write(1337,'(" itscf, iatom, ibfield_constr, bfield_constr= ",3i4,100f16.8)') t_inc%i_iteration, iatom ,bfield%ibfield_constr , bfield%bfield_constr(iatom,:)
      end if
      if(bfield%ibfield_constr == 1) then ! constraining fields to constrain scf cycle
        c_old                = bfield%bfield_constr(iatom,:)
        bfac                 = 0.030d0
        ! magdir_old(1)         = cos(t_params%phi(iatom))*sin(t_params%theta(iatom))
        ! magdir_old(2)         = sin(t_params%phi(iatom))*sin(t_params%theta(iatom))
        ! magdir_old(3)         = cos(t_params%theta(iatom))
        magdir_old(1)         = cos(phi)*sin(theta)
        magdir_old(2)         = sin(phi)*sin(theta)
        magdir_old(3)         = cos(theta)
        if (t_inc%i_write>1) write(1337,'(" itscf, iatom, magdir, magdir_old = ",2i4,100f16.8)') t_inc%i_iteration, iatom , magdir_it(:), magdir_old(:)
        if(fix_direction) then
          bfield%bfield_constr(iatom,:) = c_old - dot_product(c_old,magdir_old)*magdir_old - (magdir_it - dot_product(magdir_it,magdir_old)*magdir_old)*bfac
        end if
        if (t_inc%i_write>1) write(1337,'(" itscf, iatom, ibfield_constr, bfield_constr= ",3i4,100f16.8)') t_inc%i_iteration, iatom ,bfield%ibfield_constr , bfield%bfield_constr(iatom,:)
      end if
      ! MdSD: constraining fields
      bconstr(1:3) = bfield%bfield_constr(iatom,:)
      !if(density%magmomentfixed == 6) then ! constraining fields
      !  temp2 = 0.d0
      !  do ilm=1,lmmax
      !    integrand(:) = cone*bxc(:,ilm)*(density%rho2ns_complexnew(:,ilm,2)-density%rho2ns_complexnew(:,ilm,1))
      !    call intcheb_cell(integrand,cellnew,temp)
      !    !call simpk(integrand,temp,cell%npan,cell%nrcut(:),cell%drmeshdi(:),cell%npan)
      !    temp2    = temp2 + Dreal(temp*rfpi) ! this is a spherical quantity =>sqrt(4*pi)
      !  end do !ilm
      !end if
    end if

  end subroutine calc_torque
  


  subroutine calc_magmom_newmesh(lmax,imt1,irmdnew,icell,iend,ifunm,icleb,cleb,thetasnew,mag_den,mag_den_convol)
    
    use :: global_variables, only: ncleb, nfund, lmmaxd, lmpotd
    use :: mod_datatypes, only: dp

    implicit none



    integer                                                       , intent (in) :: lmax     
    integer                                                       , intent (in) :: imt1
    integer                                                       , intent (in) :: irmdnew
    integer              , intent (in)                                          :: icell
    integer              , intent (in)                                          :: iend         ! Number of nonzero gaunt coefficients
    integer              , dimension (1:(2*lmax+1)**2)            , intent (in) :: ifunm        ! pointer array for shapefun     ! Check index and dimensions!!!!!
    integer, dimension (ncleb, 4), intent (in)                                  :: icleb        !! Pointer array
    real (kind=dp), dimension (ncleb), intent (in)                              :: cleb         !! GAUNT coefficients (GAUNT)    ! CHECK THE DIMENSION AND HOW IT IS USED!!!
    real (kind=dp)       , dimension (irmdnew, nfund)   , intent (in)           :: thetasnew    ! shapefun on the Cheby mesh
    real(kind=dp),dimension(1:irmdnew,1:lmpotd,1:3)        , intent (in) :: mag_den
    real(kind=dp),dimension(1:irmdnew,1:(lmax+1)**2 ,1:3)        , intent (out):: mag_den_convol

    real(kind=dp),dimension(1:irmdnew,1:lmpotd)          :: shapefun_mod  
    real(kind=dp),parameter                                     :: rfpi=3.5449077018110318
    integer                                                     :: lmmax     
    integer                                                     :: ifun
    integer                                                     :: i
    integer                                                     :: j
    integer                                                     :: ilm
    integer                                                     :: jlm
    integer                                                     :: lm1
    integer                                                     :: lm2
    integer                                                     :: lm3
    integer                                                     :: ir
    real(kind=dp)                                               :: c0ll
    
    lmmax = (lmax+1)**2
    c0ll                                                    = 1.d0/rfpi

    shapefun_mod(:,:)                                       = 0.d0
    shapefun_mod(1:imt1,1)                                  = rfpi ! is multipled by C_LL^0
    shapefun_mod(imt1+1:irmdnew,1)                          = thetasnew(imt1+1:irmdnew,1)
    do ilm=2,lmpotd
      ifun = ifunm(ilm)
      if(.not. ifun == 0) then !shapefun%lmused(ilm)==1) then
        !write(*,'(" converted ifun= ",i4," to ilm= ",i4)') ifun, ilm
        shapefun_mod(imt1+1:irmdnew,ilm)           = thetasnew(imt1+1:irmdnew,ifun)
      end if
    end do

    mag_den_convol(:,:,:)=0.d0

    !write(*,'("c0ll=",es16.8)') c0ll


    !!diagonal part (not contained in gaunt-coeff)
    do i = 1,3
      do ilm = 1,lmpotd
        mag_den_convol(:,1,i) = mag_den_convol(:,1,i) + mag_den(:,ilm,i)*shapefun_mod(:,ilm)*c0ll
      end do
    end do
    do i = 1,3
      do j = 1,iend !gauntcoeff%iend
        lm1 = icleb(j, 1)! gauntcoeff%icleb(j,1) ! lmax
        lm2 = icleb(j, 2)! gauntcoeff%icleb(j,2) ! lmax
        lm3 = icleb(j, 3)! gauntcoeff%icleb(j,3) ! 2*lmax
        !write(*,'("lm1,lm2,lm3,gaunt=",3i4,2es16.8)') lm1,lm2,lm3,cleb(j)
        if(lm1<= lmmax  .and. lm2 <= lmmax  .and. lm3<= lmmax) then
        ! since lm1 and lm2 are only defined up to lmax the convoluted
        ! magnetization density can also be defined only up to there
          do ir = 1,irmdnew!cellnew%nrmaxnew
            mag_den_convol(ir,lm3,i) = mag_den_convol(ir,lm3,i) + cleb(j)*mag_den(ir,lm1,i)*shapefun_mod(ir,lm2)
            mag_den_convol(ir,lm3,i) = mag_den_convol(ir,lm3,i) + cleb(j)*mag_den(ir,lm2,i)*shapefun_mod(ir,lm1)
          end do
        end if
      end do
    end do


  end subroutine calc_magmom_newmesh

end module mod_torque