LCOV - code coverage report
Current view: top level - startden - flipcdn.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 48 110 43.6 %
Date: 2024-05-15 04:28:08 Functions: 1 1 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------
       2             : ! Copyright (c) 2016 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
       3             : ! This file is part of FLEUR and available as free software under the conditions
       4             : ! of the MIT license as expressed in the LICENSE file in more detail.
       5             : !--------------------------------------------------------------------------------
       6             : 
       7             : MODULE m_flipcdn
       8             : !     *******************************************************
       9             : !     this subroutine reads the charge density and flips the
      10             : !     magnetic moment within the m.t.sphere for each atom
      11             : !     according to the variable nflip. This variable is read in
      12             : !     the main program
      13             : !  TODO; (Test)           nflip = -1 : flip spin in sphere
      14             : !  TODO:           nflip = -2 : scale spin by bmu(n)
      15             : !             nflip = any: no spin flip
      16             : !                            r.pentcheva,kfa,Feb'96
      17             : !
      18             : !     Extension to multiple U per atom type by G.M. 2017
      19             : !
      20             : !     Removed integer nflip switch and added angles phi/theta
      21             : !     (and an additional spin scale switch)
      22             : !     which defines spin flip for each atom individually.
      23             : !     => Magnetisation axis can now be chosen independet
      24             : !     of spin quantization axis.
      25             : !     R. Hilgers, Okt. 2019
      26             : !     *******************************************************
      27             :    CONTAINS
      28             : 
      29          14 :    SUBROUTINE flipcdn(atoms,input,vacuum,sphhar,stars,sym,noco ,cell,phi,theta,optDen,toGlobal)
      30             :       !USE m_rotdenmat
      31             :       USE m_rotMMPmat
      32             :       USE m_constants
      33             :       USE m_cdn_io
      34             :       USE m_types
      35             : 
      36             :       IMPLICIT NONE
      37             : 
      38             :       TYPE(t_stars),INTENT(IN)    :: stars
      39             :       TYPE(t_vacuum),INTENT(IN)   :: vacuum
      40             :       TYPE(t_atoms),INTENT(IN)    :: atoms
      41             :       TYPE(t_sphhar),INTENT(IN)   :: sphhar
      42             :       TYPE(t_input),INTENT(IN)    :: input
      43             :       TYPE(t_sym),INTENT(IN)      :: sym
      44             :       TYPE(t_noco),INTENT(IN)     :: noco
      45             :        
      46             :       TYPE(t_cell),INTENT(IN)     :: cell
      47             :       REAL, OPTIONAL, INTENT(IN)  :: phi(atoms%ntype)
      48             :       REAL, OPTIONAL, INTENT(IN)  :: theta(atoms%ntype)
      49             :       TYPE(t_potden), OPTIONAL,INTENT(INOUT) :: optDen
      50             :       LOGICAL,OPTIONAL,INTENT(IN)            :: toGlobal
      51             : 
      52             :       ! Local type instance
      53          14 :       TYPE(t_potden)            :: den
      54          56 :       TYPE(t_nococonv)          :: nococonv
      55             : 
      56             :       ! Local Scalars
      57             :       COMPLEX                   :: rhodummy, imPart12, realPart12
      58          14 :       REAL                      :: rhodumms,fermiEnergyTemp, realPart1, realPart2, imPart1,imPart2, rhodummyR, rotAnglePhi(atoms%ntype),rotAngleTheta(atoms%ntype),zeros(atoms%ntype)
      59             :       REAL                      :: tempDistance
      60             :       INTEGER                   :: i,nt,j,lh,na,mp,ispin,urec,itype,m,i_u,k,l
      61             :       INTEGER                   :: archiveType
      62          14 :       LOGICAL                   :: n_exist,l_qfix,l_error, l_flip(atoms%ntype), scaleSpin(atoms%ntype),opt
      63             :       ! Local Arrays
      64          14 :       CHARACTER(len=80), ALLOCATABLE :: clines(:)
      65          14 :       REAL,ALLOCATABLE          :: mt_tmp(:,:,:,:)
      66          14 :       COMPLEX,ALLOCATABLE       :: mmpMat_tmp(:,:,:,:)
      67          40 :       zeros=0.0
      68             : 
      69             :       !Flipcdn by optional given angle if lflip is false but routine is called.
      70          40 :       DO k=1, atoms%ntype
      71          40 :          IF(.NOT.input%lflip.AND.PRESENT(phi).AND.present(theta)) THEN
      72          24 :             rotAnglePhi(k)=phi(k)
      73          24 :             rotAngleTheta(k)=theta(k)
      74          24 :             scaleSpin(k)=.FALSE.
      75           2 :          ELSE IF (input%lflip) THEN
      76             :             !Rotation triggerd by lflip.
      77           2 :             rotAnglePhi(k)=atoms%flipSpinPhi(k)
      78           2 :             rotAngleTheta(k)=atoms%flipSpinTheta(k)
      79           2 :             scaleSpin(k)=atoms%flipSpinScale(k)
      80             :          ELSE
      81           0 :             CALL judft_error("You shouldn't be here. There went something wrong.",calledby="flipcdn")
      82             :          END IF
      83             :       END DO
      84             : 
      85             : 
      86          40 :       DO itype=1, atoms%ntype
      87          61 :          l_flip(itype)=MERGE(.TRUE.,.FALSE.,(rotAnglePhi(itype).NE.0.0) .OR.(rotAngleTheta(itype).NE.0.0))
      88             :       END DO
      89             : 
      90             :       !rot_den_mat(alph,beta,rho11,rho22,rho21)
      91          14 :       IF (any(noco%l_unrestrictMT)) THEN
      92          14 :          archiveType=CDN_ARCHIVE_TYPE_FFN_const
      93           0 :       ELSE IF (noco%l_noco) THEN
      94           0 :          archiveType=CDN_ARCHIVE_TYPE_NOCO_const
      95             :       ELSE
      96           0 :          archiveType=CDN_ARCHIVE_TYPE_CDN1_const
      97             :       END IF
      98             : 
      99             : 
     100          14 :       IF(.NOT.PRESENT(optDen)) THEN
     101           2 :          opt=.FALSE.
     102           2 :          CALL den%init(stars,atoms,sphhar,vacuum,noco,input%jspins,POTDEN_TYPE_DEN)
     103             :          ! read the charge density
     104             :          CALL readDensity(stars,noco,vacuum,atoms,cell,sphhar,input,sym ,archiveType,&
     105           2 :                           CDN_INPUT_DEN_const,0,fermiEnergyTemp,tempDistance,l_qfix,den)
     106             :       ELSE
     107          12 :          den=optDen
     108          12 :          opt=.TRUE.
     109             :       END IF
     110             : 
     111             :       ! flip cdn for each atom with rotation angles given
     112          14 :       if (any(noco%l_unrestrictMT).and.size(den%mt,4)<4) then
     113             :         !So far the density was collinear in spheres, now we make it FFN ready
     114           2 :         CALL move_alloc(den%mt,mt_tmp)
     115          12 :         allocate(den%mt(size(mt_tmp,1),0:size(mt_tmp,2)-1,size(mt_tmp,3),4))
     116      491198 :         den%mt(:,:,:,1:2)=mt_tmp
     117      491198 :         den%mt(:,:,:,3:)=0.0
     118             : 
     119           2 :         if (allocated(den%mmpMat)) then
     120           2 :            CALL move_alloc(den%mmpMat,mmpMat_tmp)
     121           8 :            allocate(den%mmpMat(-lmaxU_const:lmaxU_const,-lmaxU_const:lmaxU_const,SIZE(mmpMat_tmp,3),3))
     122         234 :            den%mmpMat(:,:,:,1:2)=mmpMat_tmp
     123         116 :            den%mmpMat(:,:,:,3)=0.0
     124             :         endif
     125             :       endif
     126             : 
     127             :       !$OMP parallel PRIVATE(rhodummy,rhodumms,j,rhodummyR,lh,itype,na) DEFAULT(none) &
     128             :       !$OMP SHARED(noco,den,zeros,atoms,sphhar,input,sym,l_flip,scalespin,toGlobal,nococonv) &
     129          14 :       !$OMP FIRSTPRIVATE(rotAngleTheta,rotAnglePhi)
     130             :       !$OMP do
     131             :       DO itype = 1, atoms%ntype
     132             :          na = atoms%firstAtom(itype)
     133             :          IF (l_flip(itype).AND.(.NOT.scaleSpin(itype))) THEN
     134             :             ! spherical and non-spherical m.t. charge density
     135             :             DO lh = 0,sphhar%nlh(sym%ntypsy(na))
     136             :                DO j = 1,atoms%jri(itype)
     137             :                   IF (any(noco%l_unrestrictMT)) THEN
     138             :                      rhodummy=CMPLX(den%mt(j,lh,itype,3),den%mt(j,lh,itype,4))
     139             :                      !CALL rot_den_mat(zeros(itype),rotAngleTheta(itype),den%mt(j,lh,itype,1),den%mt(j,lh,itype,2),rhodummy)
     140             :                      !CALL rot_den_mat(rotAnglePhi(itype),zeros(itype),den%mt(j,lh,itype,1),den%mt(j,lh,itype,2),rhodummy)
     141             :                      call nococonv%rotdenmat(rotAnglePhi(itype),rotAngleTheta(itype),den%mt(j,lh,itype,1),den%mt(j,lh,itype,2),rhodummy, toGlobal)
     142             :                      den%mt(j,lh,itype,3)=REAL(rhodummy)
     143             :                      den%mt(j,lh,itype,4)=AIMAG(rhodummy)
     144             :                   ELSE
     145             :                      IF (rotAngleTheta(itype).EQ.(pimach()).AND.rotAnglePhi(itype).EQ.0) THEN
     146             :                         rhodummyR = den%mt(j,lh,itype,1)
     147             :                         den%mt(j,lh,itype,1) = den%mt(j,lh,itype,input%jspins)
     148             :                         den%mt(j,lh,itype,input%jspins) = rhodummyR
     149             :                      ELSE
     150             :                         !Since in non-noco case the den-matrices are only initialized with two diagonal components we cannot perform flips where off-diagonal elements arise in non-noco case => Only rotations by theta=Pi/2 are allowed.
     151             :                         CALL judft_error("l_mtNocoPot=F in combination with spin flips different from flipSpinTheta=Pi and flipSpinPhi=0 is currently not supported.",&
     152             :                                          calledby="flipcdn")
     153             :                      END IF
     154             :                   END IF
     155             :                END DO
     156             :             END DO
     157             :          ELSE IF (l_flip(itype).AND.scaleSpin(itype)) THEN
     158             :             IF((rotAngleTheta(itype).NE.(pimach()) .OR.rotAnglePhi(itype).NE.0.0)) CALL judft_error("Spinscaling in combination with flipSpin is currently only implemented using flipSpinTheta=Pi and flipSpinPhi=0.0.",calledby="flipcdn")
     159             :             DO lh = 0,sphhar%nlh(sym%ntypsy(na))
     160             :                DO j = 1,atoms%jri(itype)
     161             :                   rhodummy = den%mt(j,lh,itype,1) + den%mt(j,lh,itype,input%jspins)
     162             :                   rhodumms = den%mt(j,lh,itype,1) - den%mt(j,lh,itype,input%jspins)
     163             :                   den%mt(j,lh,itype,1) = 0.5 * (rhodummy + atoms%bmu(itype)*rhodumms)
     164             :                   den%mt(j,lh,itype,input%jspins) = 0.5 * (rhodummy - atoms%bmu(itype)*rhodumms )
     165             :                END DO
     166             :             END DO
     167             :          END IF
     168             :       END DO
     169             :       !$OMP end do
     170             :       !$OMP end parallel
     171             : 
     172          14 :       IF (input%l_onlyMtStDen) THEN
     173             :       !!This Segment takes care that no interstitial magnetization is written in the the density. Meaning: Off diagonal elements of density matrix set to 0 and diagonal elements of density matrix are equal to their mean value.
     174           0 :          den%pw(:,2)=(den%pw(:,1)+den%pw(:,2))*0.5 !mean value
     175           0 :          den%pw(:,1)=den%pw(:,2)
     176           0 :          IF (noco%l_noco) THEN
     177           0 :             den%pw(:,3)=CMPLX(0.0,0.0)
     178             :          END IF
     179             :       END IF
     180             : 
     181             : 
     182             :       ! for LDA+U: flip density matrix
     183        2450 :       IF (input%lflip.AND.ANY(ABS(den%mmpMat) > 1e-12).AND.atoms%n_u+atoms%n_hia+atoms%n_opc>0) THEN
     184           0 :          DO i_u = 1, atoms%n_u+atoms%n_hia+atoms%n_opc
     185           0 :             if(i_u> atoms%n_u+atoms%n_hia) then
     186           0 :                itype = atoms%lda_u(i_u)%atomType
     187           0 :                l = atoms%lda_u(i_u)%l
     188             :             else
     189           0 :                itype = atoms%lda_opc(i_u-atoms%n_u-atoms%n_hia)%atomType
     190           0 :                l = atoms%lda_opc(i_u-atoms%n_u-atoms%n_hia)%l
     191             :             endif
     192           0 :             IF (l_flip(itype).AND.(.NOT.scaleSpin(itype))) THEN
     193           0 :                IF (any(noco%l_unrestrictMT)) THEN
     194             :                   den%mmpMat(:,:,i_u,:) = rotMMPmat(den%mmpMat(:,:,i_u,:),rotAnglePhi(itype),rotAngleTheta(itype),0.0,&
     195           0 :                                                     l,inverse=toGlobal,real_space_rotation=.FALSE., spin_rotation=.TRUE.)
     196             :                ELSE
     197           0 :                   IF (rotAngleTheta(itype).EQ.(pimach()).AND.rotAnglePhi(itype).EQ.0) THEN
     198           0 :                      DO m = -lmaxU_const,lmaxU_const
     199           0 :                         DO mp = -lmaxU_const,lmaxU_const
     200           0 :                            rhodummyR = den%mmpMat(m,mp,i_u,1)
     201           0 :                            den%mmpMat(m,mp,i_u,1) = den%mmpMat(m,mp,i_u,input%jspins)
     202           0 :                            den%mmpMat(m,mp,i_u,input%jspins) = rhodummyR
     203             :                         ENDDO
     204             :                      ENDDO
     205             :                   ELSE
     206             :                         !Since in non-noco case the den-matrices are only initialized with two diagonal components we cannot perform flips where off-diagonal elements arise in non-noco case => Only rotations by Pi degrees are allowed.
     207             :                         CALL judft_error("l_mtNocoPot=F in combination with spin flips different from flipSpinTheta=Pi, flipSpinPhi=0 is currently not supported.",&
     208           0 :                                          calledby="flipcdn")
     209             :                   END IF
     210             :                END IF
     211           0 :             ELSE IF (l_flip(itype).AND.(scaleSpin(itype))) THEN
     212           0 :                DO m = -lmaxU_const,lmaxU_const
     213           0 :                   DO mp = -lmaxU_const,lmaxU_const
     214           0 :                      IF((rotAngleTheta(itype).NE.pimach() .OR.rotAnglePhi(itype).NE.0.0)) CALL judft_error("Spinscaling in combination with flipSpin is currently only implemented using flipSpinTheta=Pi and flipSpinPhi=0.0",calledby="flipcdn")
     215           0 :                      rhodummy = den%mmpMat(m,mp,i_u,1) + den%mmpMat(m,mp,i_u,input%jspins)
     216           0 :                      rhodumms = den%mmpMat(m,mp,i_u,1) - den%mmpMat(m,mp,i_u,input%jspins)
     217           0 :                      den%mmpMat(m,mp,i_u,1) = 0.5 * (rhodummy + atoms%bmu(itype) * rhodumms)
     218           0 :                      den%mmpMat(m,mp,i_u,input%jspins) = 0.5 * (rhodummy - atoms%bmu(itype) * rhodumms)
     219             :                   END DO
     220             :                END DO
     221             :             END IF
     222             :          END DO
     223             :       END IF
     224             : 
     225             :       ! write the spin-polarized density
     226          14 :        IF(input%lflip) CALL writeDensity(stars,noco,vacuum,atoms,cell,sphhar,input,sym ,archiveType,CDN_INPUT_DEN_const,&
     227           2 :                                          1,-1.0,0.0,-1.0,-1.0,.FALSE.,den)
     228     5894386 :        IF(opt) optDen%mt=den%mt
     229             : 
     230             :       ! read enpara and  flip lines
     231          14 :       INQUIRE(file='enpara',exist=n_exist)
     232          14 :       IF (n_exist) THEN
     233           0 :          OPEN(40,file ='enpara',status='old',form='formatted')
     234             : 
     235           0 :          j = 2
     236           0 :          DO itype = 1, atoms%ntype
     237           0 :             j = j + 1
     238           0 :             IF (atoms%nlo(itype)>0) j = j + 2
     239             :          END DO
     240           0 :          IF (input%film) j = j + 1
     241           0 :          ALLOCATE (clines(2*j))
     242           0 :          DO i = 1, 2*j
     243           0 :             READ (40,'(a)') clines(i)
     244             :          END DO
     245             : 
     246           0 :          REWIND 40
     247           0 :          i = 0
     248           0 :          DO ispin = 1,input%jspins
     249           0 :             i = i + 2
     250           0 :             WRITE (40,'(a)') TRIM(clines(i-1))
     251           0 :             WRITE (40,'(a)') TRIM(clines(i))
     252           0 :             DO itype = 1, atoms%ntype
     253           0 :                i = i + 1
     254           0 :                m = i
     255           0 :                IF (l_flip(itype)) m = MOD(i+j,2*j)
     256           0 :                IF (m==0) m = 2*j
     257           0 :                WRITE (40,'(a)') TRIM(clines(m))
     258           0 :                IF (atoms%nlo(itype)>0) THEN
     259           0 :                   WRITE (40,'(a)') TRIM(clines(m+1))
     260           0 :                   WRITE (40,'(a)') TRIM(clines(m+2))
     261           0 :                   i = i + 2
     262             :                END IF
     263             :             END DO
     264           0 :             IF (input%film) THEN
     265           0 :                i = i + 1
     266           0 :                WRITE (40,'(a)') TRIM(clines(i))
     267             :             END IF
     268             :          END DO
     269           0 :          DEALLOCATE (clines)
     270           0 :          CLOSE(40)
     271             :       END IF
     272             : 
     273             : 
     274          14 :       IF(PRESENT(optDen)) optDen=den
     275             : 
     276          14 :    END SUBROUTINE flipcdn
     277             : 
     278             : END MODULE m_flipcdn

Generated by: LCOV version 1.14