LCOV - code coverage report
Current view: top level - cdn_mt - magDiMom.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 0 117 0.0 %
Date: 2024-04-28 04:28:00 Functions: 0 1 0.0 %

          Line data    Source code
       1             : ! Copyright (c) 2018 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
       2             : ! This file is part of FLEUR and available as free software under the conditions
       3             : ! of the MIT license as expressed in the LICENSE file in more detail.
       4             : !--------------------------------------------------------------------------------
       5             : 
       6             : MODULE m_magDiMom
       7             : 
       8             : CONTAINS
       9             : 
      10             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      11             : !
      12             : ! This subroutine calculates intraatomic magnetic dipole moments.
      13             : !
      14             : !                                           GM'2018
      15             : !
      16             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      17             : 
      18           0 : SUBROUTINE magDiMom(sym,input,atoms,sphhar,noco,nococonv,l_fmpl2,rho,magDipoles,elecDipoles)
      19             : 
      20             :    USE m_constants
      21             :    USE m_types
      22             :    USE m_juDFT
      23             :    USE m_rotdenmat
      24             :    USE m_lattHarmsSphHarmsConv
      25             :    USE m_gaunt
      26             :    USE m_intgr
      27             : 
      28             :    IMPLICIT NONE
      29             :    TYPE(t_sym),           INTENT(IN)    :: sym
      30             :    TYPE(t_input),         INTENT(IN)    :: input
      31             :    TYPE(t_atoms),         INTENT(IN)    :: atoms
      32             :    TYPE(t_sphhar),        INTENT(IN)    :: sphhar
      33             :    TYPE(t_noco),          INTENT(IN)    :: noco
      34             :    TYPE(t_nococonv),      INTENT(IN)    :: nococonv
      35             :    REAL,                  INTENT(IN)    :: rho(:,0:,:,:) ! if l_fmpl last dimension is 4, otherwise 2.
      36             : 
      37             :    LOGICAL,               INTENT(IN)    :: l_fmpl2
      38             :    REAL,                  INTENT(INOUT) :: magDipoles(:,:)
      39             :    REAL,                  INTENT(INOUT) :: elecDipoles(:,:)
      40             : 
      41             : 
      42           0 :    REAL,    ALLOCATABLE :: inRho(:,:,:,:)
      43           0 :    COMPLEX, ALLOCATABLE :: rhoSphHarms(:,:,:,:), rhoTempSphHarms(:,:,:,:)
      44           0 :    COMPLEX, ALLOCATABLE :: rhoSphHarmsR(:,:,:)
      45             : 
      46             :    INTEGER :: iType, ilh, l, m, lm, lp, mp, lmp, i
      47             :    REAL    :: theta, phi, cdn11, cdn22
      48             :    REAL    :: magDipole(3), myCharge, elecDipole(3)
      49             :    REAL    :: constA
      50             :    COMPLEX :: gauntA, gauntB, gauntC
      51             :    COMPLEX :: cdn21
      52             : 
      53           0 :    IF(input%jspins.EQ.1) RETURN
      54           0 :    IF(.NOT.noco%l_noco) RETURN
      55             : 
      56             :    !---> calculate the charge and magnetization density in the muffin tins
      57           0 :    ALLOCATE(inRho(atoms%jmtd,0:sphhar%nlhd,atoms%ntype,4))
      58           0 :    DO iType = 1,atoms%ntype
      59           0 :       IF (.NOT.l_fmpl2) THEN
      60           0 :          theta = nococonv%beta(iType)
      61           0 :          phi   = nococonv%alph(iType)
      62           0 :          inRho(:,:,iType,1) = rho(:,:,iType,1) + rho(:,:,iType,2)
      63           0 :          inRho(:,:,iType,2) = rho(:,:,iType,1) - rho(:,:,iType,2)
      64           0 :          inRho(:,:,iType,3) = inRho(:,:,iType,2) * SIN(phi)*SIN(theta)
      65           0 :          inRho(:,:,iType,4) = inRho(:,:,iType,2) * COS(theta)
      66           0 :          inRho(:,:,iType,2) = inRho(:,:,iType,2) * COS(phi)*SIN(theta)
      67             :       ELSE
      68           0 :          DO ilh = 0,sphhar%nlh(sym%ntypsy(atoms%firstAtom(iType)))
      69           0 :             DO i = 1,atoms%jri(iType)
      70             : 
      71           0 :                cdn11 = rho(i,ilh,iType,1)
      72           0 :                cdn22 = rho(i,ilh,iType,2)
      73           0 :                cdn21 = CMPLX(rho(i,ilh,iType,3),rho(i,ilh,iType,4))
      74           0 :                CALL rot_den_mat(nococonv%alph(iType),nococonv%beta(iType),cdn11,cdn22,cdn21)
      75           0 :                inRho(i,ilh,iType,1) = cdn11 + cdn22
      76           0 :                inRho(i,ilh,iType,2) = 2.0 * REAL(cdn21)
      77             :                ! Note: The minus sign in the following line is temporary to adjust for differences in the offdiagonal
      78             :                !       part of the density between this fleur version and ancient (v0.26) fleur.
      79           0 :                inRho(i,ilh,iType,3) = -2.0 * AIMAG(cdn21)
      80           0 :                inRho(i,ilh,iType,4) = cdn11 - cdn22
      81             :             END DO
      82             :          END DO
      83             :       END IF
      84             :    END DO
      85             : 
      86           0 :    ALLOCATE (rhoSphHarms(atoms%jmtd,(atoms%lmaxd+1)**2,atoms%ntype,4))
      87           0 :    ALLOCATE (rhoTempSphHarms(atoms%jmtd,(atoms%lmaxd+1)**2,atoms%ntype,4))
      88           0 :    ALLOCATE (rhoSphHarmsR(atoms%jmtd,(atoms%lmaxd+1)**2,atoms%ntype))
      89             : 
      90           0 :    rhoSphHarms = CMPLX(0.0,0.0)
      91           0 :    DO i = 1, 4
      92           0 :       DO iType = 1, atoms%ntype
      93           0 :          CALL lattHarmsRepToSphHarms(sym,atoms,sphhar,iType,inRho(:,0:,iType,i),rhoSphHarms(:,:,iType,i))
      94             :       END DO
      95             :    END DO
      96             : 
      97             :    ! electric dipole moment (start)
      98           0 :    DO iType = 1, atoms%ntype
      99           0 :       DO i = 1, atoms%jri(iType)
     100           0 :          rhoSphHarmsR(i,:,iType) = rhoSphHarms(i,:,iType,1) * atoms%rmsh(i,iType)
     101             :       END DO
     102             :    END DO
     103             : 
     104           0 :    constA = SQRT(2.0*pi_const/3.0)
     105           0 :    rhoTempSphHarms = CMPLX(0.0,0.0)
     106           0 :    DO iType = 1, atoms%ntype
     107           0 :       DO lp = 0, MIN(2,atoms%lmax(iType))
     108           0 :          DO mp = -lp, lp
     109           0 :             DO l = 0, MIN(2,atoms%lmax(iType))
     110           0 :                DO m = -l, l
     111             :                   !note 1: For refinement maybe I could make use of selection rules.
     112             :                   !note 2: ls for r^\hat is 1, ms is -1..1.
     113           0 :                   gauntA = gaunt1(lp,1,l,mp,-1,m,atoms%lmaxd)
     114           0 :                   gauntB = gaunt1(lp,1,l,mp,0,m,atoms%lmaxd)
     115           0 :                   gauntC = gaunt1(lp,1,l,mp,1,m,atoms%lmaxd)
     116           0 :                   lmp = lp*(lp+1) + mp + 1
     117           0 :                   lm = l*(l+1) + m + 1
     118           0 :                   DO i = 1, atoms%jri(iType)
     119             :                      rhoTempSphHarms(i,lmp,iType,2) = rhoTempSphHarms(i,lmp,iType,2) +&
     120           0 :                         constA*(gauntA-gauntC)*rhoSphHarmsR(i,lm,iType)
     121             :                      rhoTempSphHarms(i,lmp,iType,3) = rhoTempSphHarms(i,lmp,iType,3) +&
     122           0 :                         constA*CMPLX(0.0,1.0)*(gauntA+gauntC)*rhoSphHarmsR(i,lm,iType)
     123             :                      rhoTempSphHarms(i,lmp,iType,4) = rhoTempSphHarms(i,lmp,iType,4) +&
     124           0 :                         constA*SQRT(2.0)*gauntB*rhoSphHarmsR(i,lm,iType)
     125             :                   END DO
     126             :                END DO
     127             :             END DO
     128             :          END DO
     129             :       END DO
     130             :    END DO
     131             : 
     132           0 :    elecDipole = 0.0
     133           0 :    DO iType = 1, atoms%ntype
     134           0 :       CALL intgr3(REAL(rhoTempSphHarms(:,1,iType,2)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),elecDipole(1))
     135           0 :       CALL intgr3(REAL(rhoTempSphHarms(:,1,iType,3)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),elecDipole(2))
     136           0 :       CALL intgr3(REAL(rhoTempSphHarms(:,1,iType,4)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),elecDipole(3))
     137           0 :       elecDipoles(:,iType) = elecDipole(:) * sfp_const
     138             :    END DO
     139             : 
     140             :    ! electric dipole moment (end)
     141             : 
     142             : !   WRITE(7534,*) '===================================================='
     143           0 :    DO iType = 1, atoms%ntype
     144           0 :       DO l = 0, 2
     145           0 :          DO m = -l, l
     146           0 :          magDipole(:) = 0.0
     147             :          myCharge = 0.0
     148           0 :          lm = l*(l+1) + m + 1
     149           0 :          CALL intgr3(REAL(rhoSphHarms(:,lm,iType,1)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),myCharge)
     150           0 :          CALL intgr3(REAL(rhoSphHarms(:,lm,iType,2)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(1))
     151           0 :          CALL intgr3(REAL(rhoSphHarms(:,lm,iType,3)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(2))
     152           0 :          CALL intgr3(REAL(rhoSphHarms(:,lm,iType,4)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(3))
     153             : !         WRITE(7534,'(3i7,4e24.8)') iType, l, m, myCharge, magDipole(:)
     154             :          END DO
     155             :       END DO
     156           0 :       rhoSphHarms(:,:,iType,1) = CMPLX(0.0,0.0)
     157             :    END DO
     158             : 
     159           0 :    constA = SQRT(2.0*pi_const/3.0)
     160           0 :    DO iType = 1, atoms%ntype
     161           0 :       DO lp = 0, MIN(2,atoms%lmax(iType))
     162           0 :          DO mp = -lp, lp
     163           0 :             DO l = 0, MIN(2,atoms%lmax(iType))
     164           0 :                DO m = -l, l
     165             :                   !note 1: For refinement maybe I could make use of selection rules.
     166             :                   !note 2: ls for r^\hat is 1, ms is -1..1.
     167           0 :                   gauntA = gaunt1(lp,1,l,mp,-1,m,atoms%lmaxd)
     168           0 :                   gauntB = gaunt1(lp,1,l,mp,0,m,atoms%lmaxd)
     169           0 :                   gauntC = gaunt1(lp,1,l,mp,1,m,atoms%lmaxd)
     170           0 :                   lmp = lp*(lp+1) + mp + 1
     171           0 :                   lm = l*(l+1) + m + 1
     172           0 :                   DO i = 1, atoms%jri(iType)
     173             :                      rhoSphHarms(i,lmp,iType,1) = rhoSphHarms(i,lmp,iType,1) +&
     174           0 :                         constA*(gauntA-gauntC)*rhoSphHarms(i,lm,iType,2)
     175             :                      rhoSphHarms(i,lmp,iType,1) = rhoSphHarms(i,lmp,iType,1) +&
     176           0 :                         constA*CMPLX(0.0,1.0)*(gauntA+gauntC)*rhoSphHarms(i,lm,iType,3)
     177             :                      rhoSphHarms(i,lmp,iType,1) = rhoSphHarms(i,lmp,iType,1) +&
     178           0 :                         constA*SQRT(2.0)*gauntB*rhoSphHarms(i,lm,iType,4)
     179             :                   END DO
     180             :                END DO
     181             :             END DO
     182             :          END DO
     183             :       END DO
     184             :    END DO
     185             : 
     186           0 :    rhoTempSphHarms = CMPLX(0.0,0.0)
     187           0 :    DO iType = 1, atoms%ntype
     188           0 :       DO lp = 0, MIN(2,atoms%lmax(iType))
     189           0 :          DO mp = -lp, lp
     190           0 :             DO l = 0, MIN(2,atoms%lmax(iType))
     191           0 :                DO m = -l, l
     192             :                   !note 1: For refinement maybe I could make use of selection rules.
     193             :                   !note 2: ls for r^\hat is 1, ms is -1..1.
     194           0 :                   gauntA = gaunt1(lp,1,l,mp,-1,m,atoms%lmaxd)
     195           0 :                   gauntB = gaunt1(lp,1,l,mp,0,m,atoms%lmaxd)
     196           0 :                   gauntC = gaunt1(lp,1,l,mp,1,m,atoms%lmaxd)
     197           0 :                   lmp = lp*(lp+1) + mp + 1
     198           0 :                   lm = l*(l+1) + m + 1
     199           0 :                   DO i = 1, atoms%jri(iType)
     200             :                      rhoTempSphHarms(i,lmp,iType,2) = rhoTempSphHarms(i,lmp,iType,2) +&
     201           0 :                         constA*(gauntA-gauntC)*rhoSphHarms(i,lm,iType,1)
     202             :                      rhoTempSphHarms(i,lmp,iType,3) = rhoTempSphHarms(i,lmp,iType,3) +&
     203           0 :                         constA*CMPLX(0.0,1.0)*(gauntA+gauntC)*rhoSphHarms(i,lm,iType,1)
     204             :                      rhoTempSphHarms(i,lmp,iType,4) = rhoTempSphHarms(i,lmp,iType,4) +&
     205           0 :                         constA*SQRT(2.0)*gauntB*rhoSphHarms(i,lm,iType,1)
     206             :                   END DO
     207             :                END DO
     208             :             END DO
     209             :          END DO
     210             :       END DO
     211             :    END DO
     212             : 
     213           0 :    DO iType = 1, atoms%ntype
     214           0 :       DO l = 0, atoms%lmax(iType)
     215           0 :          DO m = -l, l
     216           0 :             lm = l*(l+1) + m + 1
     217           0 :             DO i = 1, atoms%jri(iType)
     218           0 :                rhoSphHarms(i,lm,iType,2) = rhoSphHarms(i,lm,iType,2) - 3.0 * rhoTempSphHarms(i,lm,iType,2)
     219           0 :                rhoSphHarms(i,lm,iType,3) = rhoSphHarms(i,lm,iType,3) - 3.0 * rhoTempSphHarms(i,lm,iType,3)
     220           0 :                rhoSphHarms(i,lm,iType,4) = rhoSphHarms(i,lm,iType,4) - 3.0 * rhoTempSphHarms(i,lm,iType,4)
     221             :             END DO
     222             :          END DO
     223             :       END DO
     224             :    END DO
     225             : 
     226           0 :    DO iType = 1, atoms%ntype
     227           0 :       DO i = 1, atoms%jri(iType)
     228           0 :          IF (ANY(AIMAG(rhoSphHarms(i,1,iType,:)).GT.1.0e-11)) THEN
     229           0 :             WRITE(oUnit,*) 'imaginary part too large!'
     230             :          END IF
     231             :       END DO
     232             :    END DO
     233             : 
     234           0 :    magDipole = 0.0
     235           0 :    DO iType = 1, atoms%ntype
     236           0 :       CALL intgr3(REAL(rhoSphHarms(:,1,iType,2)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(1))
     237           0 :       CALL intgr3(REAL(rhoSphHarms(:,1,iType,3)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(2))
     238           0 :       CALL intgr3(REAL(rhoSphHarms(:,1,iType,4)),atoms%rmsh(:,iType),atoms%dx(iType),atoms%jri(iType),magDipole(3))
     239           0 :       magDipoles(:,iType) = magDipole(:) * sfp_const
     240             :    END DO
     241             : 
     242           0 : END SUBROUTINE magDiMom
     243             : 
     244             : END MODULE m_magDiMom

Generated by: LCOV version 1.14