LCOV - code coverage report
Current view: top level - vgen - rotate_int_den_tofrom_local.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 64 160 40.0 %
Date: 2024-05-02 04:21:52 Functions: 2 2 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_rotate_int_den_tofrom_local
       8             :    USE m_juDFT
       9             :    USE m_fft2d
      10             :    USE m_fft3d
      11             :    USE m_types
      12             :    
      13             :    IMPLICIT NONE
      14             : 
      15             : CONTAINS
      16             :    
      17         192 :    SUBROUTINE rotate_int_den_to_local(sym, stars, atoms, sphhar, vacuum, cell, &
      18             :                                       input, noco,   den)
      19             : 
      20             :       !--------------------------------------------------------------------------
      21             :       ! This subroutine calculates the spin-up and -down density in the intersti-
      22             :       ! tial region i.e. it takes the non-collinear density and rotates it into
      23             :       ! a local spin-frame, making it spin-diagonal.
      24             :       ! 
      25             :       ! The rotated density is needed to calculate the potential-energy integrals
      26             :       ! in vgen_xcpot. For accuracy reasons, the magnetisation for the potential
      27             :       ! itself is regenerated from the unrotated densities.
      28             :       ! 
      29             :       ! In addition this routine stores the angles used in the rotation. These
      30             :       ! angles are later needed to rotate the up- and down-potentials back to the
      31             :       ! global frame. DW 2018
      32             :       ! 
      33             :       ! Based on rhodirgen by
      34             :       ! Philipp Kurz 99/11/01
      35             :       !--------------------------------------------------------------------------
      36             : 
      37             :       !-------Important variables:----------------------------------------------- 
      38             :       ! ifft3: size of the 3d real space mesh
      39             :       ! ifft2: size of the 2d real space mesh
      40             :       ! ris:   first components of the density matrix
      41             :       !        later interstitial spin-up and -down density and direction of mag-
      42             :       !        netic field (theta and phi) all stored on real space mesh
      43             :       !--------------------------------------------------------------------------
      44             : 
      45             :       USE m_constants
      46             :       USE m_polangle
      47             :     
      48             :       TYPE(t_noco),   INTENT(IN)    :: noco
      49             :        
      50             :       TYPE(t_input),  INTENT(IN)    :: input
      51             :       TYPE(t_vacuum), INTENT(IN)    :: vacuum
      52             :       TYPE(t_sym),    INTENT(IN)    :: sym
      53             :       TYPE(t_stars),  INTENT(IN)    :: stars
      54             :       TYPE(t_cell),   INTENT(IN)    :: cell
      55             :       TYPE(t_sphhar), INTENT(IN)    :: sphhar
      56             :       TYPE(t_atoms),  INTENT(IN)    :: atoms
      57             :       TYPE(t_potden), INTENT(INOUT) :: den
      58             : 
      59             :       INTEGER                       :: iden, jspin, ivac, ifft2, ifft3
      60             :       INTEGER                       :: imz, ityp, iri, ilh, imesh, iq2, iq3
      61             :       REAL                          :: rho_11, rho_22, rho_21r, rho_21i
      62             :       REAL                          :: mx, my, mz, magmom, vz_r, vz_i, rziw
      63             :       REAL                          :: rhotot, rho_up, rho_down, theta, phi
      64             :       REAL                          :: eps=1E-20
      65             : 
      66         192 :       REAL, ALLOCATABLE             :: rz(:,:,:), rvacxy(:,:,:,:), ris(:,:)
      67         192 :       REAL, ALLOCATABLE             :: fftwork(:)
      68             : 
      69             :       ! Initialize arrays for the density matrix:
      70             : 
      71         192 :       ifft3 = 27*stars%mx1*stars%mx2*stars%mx3
      72         192 :       IF (input%film) THEN
      73           0 :          ifft2 = 9*stars%mx1*stars%mx2
      74             :       ELSE
      75             :          ifft2=0
      76             :       END IF
      77             : 
      78         192 :       IF (ALLOCATED(den%phi_pw)) THEN
      79           0 :          DEALLOCATE(den%phi_pw)!,den%phi_vacz,den%phi_vacxy)
      80           0 :          DEALLOCATE(den%theta_pw)!,den%theta_vacz,den%theta_vacxy)
      81           0 :          DEALLOCATE(den%theta_vac,den%phi_vac)
      82             :       END IF
      83             : 
      84         768 :       ALLOCATE(den%phi_pw(ifft3),den%theta_pw(ifft3))
      85             :       !ALLOCATE(den%phi_vacz(vacuum%nmzd,2),den%theta_vacz(vacuum%nmzd,2))
      86        1344 :       ALLOCATE(den%phi_vac(ifft2,vacuum%nmzd,2),den%theta_vac(ifft2,vacuum%nmzd,2))
      87             :       !ALLOCATE(den%phi_vacxy(ifft2,vacuum%nmzxyd,2),den%theta_vacxy(ifft2,vacuum%nmzxyd,2))
      88             : 
      89         768 :       ALLOCATE (ris(ifft3,4),fftwork(ifft3))
      90             :  
      91             :       ! Interstitial part:
      92             : 
      93             :       ! Fourier transform the diagonal part of the density matrix (den%pw)
      94             :       ! to real space (ris):
      95         576 :       DO iden = 1,2
      96         576 :          CALL fft3d(ris(:,iden),fftwork,den%pw(:,iden),stars,+1)
      97             :       END DO
      98             : 
      99             :       ! Fourier transform the off-diagonal part of the density matrix:
     100         192 :       CALL fft3d(ris(:,3),ris(:,4),den%pw(:,3),stars,+1)
     101             : 
     102             :       ! Calculate the charge and magnetization densities on the real space mesh:
     103     7185054 :       DO imesh = 1,ifft3
     104     7184862 :          rho_11   = ris(imesh,1)
     105     7184862 :          rho_22   = ris(imesh,2)
     106     7184862 :          rho_21r  = ris(imesh,3)
     107     7184862 :          rho_21i  = ris(imesh,4)
     108     7184862 :          mx       =  2*rho_21r
     109     7184862 :          my       = -2*rho_21i ! TODO: This is a magic minus.
     110     7184862 :          mz       = rho_11 - rho_22
     111     7184862 :          magmom   = SQRT(mx**2 + my**2 + mz**2)
     112     7184862 :          rhotot   = rho_11 + rho_22
     113     7184862 :          rho_up   = (rhotot + magmom)/2
     114     7184862 :          rho_down = (rhotot - magmom)/2
     115             : 
     116     7184862 :          CALL pol_angle(mx,my,mz,theta,phi)
     117             : 
     118     7184862 :          ris(imesh,1) = rho_up
     119     7184862 :          ris(imesh,2) = rho_down
     120     7184862 :          den%theta_pw(imesh) = theta
     121     7185054 :          den%phi_pw(imesh) = phi
     122             :       END DO
     123             : 
     124             :       ! Fourier transform the matrix potential back to reciprocal space:
     125         576 :       DO jspin = 1, input%jspins
     126    14370108 :          fftwork=0.0
     127         576 :          CALL fft3d(ris(:,jspin),fftwork,den%pw(:,jspin),stars,-1)
     128             :       END DO
     129             : 
     130         192 :       IF (.NOT.input%film) RETURN
     131             : 
     132             :       ! Now the vacuum part starts:
     133             :    
     134           0 :       ALLOCATE(rvacxy(ifft2,vacuum%nmzxyd,2,4))
     135           0 :       ALLOCATE (rz(vacuum%nmzd,2,2))
     136             : 
     137             :       ! Fourier transform the diagonal part of the density matrix (den%vacz and
     138             :       ! den%vacxy) to real space (rvacxy):
     139           0 :       DO iden = 1,2
     140           0 :          DO ivac = 1,vacuum%nvac
     141           0 :             DO imz = 1,vacuum%nmzxyd
     142           0 :                rziw = 0.0
     143             :                   CALL fft2d(stars,rvacxy(:,imz,ivac,iden),fftwork,&
     144             :                        den%vac(imz,:,ivac,iden),&
     145           0 :                        1)
     146             :             END DO
     147             :          END DO
     148             :       END DO
     149             : 
     150             :       ! Fourier transform the off-diagonal part of the density matrix:
     151           0 :       DO ivac = 1,vacuum%nvac
     152           0 :          DO imz = 1,vacuum%nmzxyd
     153           0 :             rziw = 0.0
     154           0 :             vz_r = REAL(den%vac(imz,1,ivac,3))
     155           0 :             vz_i = AIMAG(den%vac(imz,1,ivac,3))
     156             :                CALL fft2d(stars,rvacxy(:,imz,ivac,3),rvacxy(:,imz,ivac,4),&
     157           0 :                     den%vac(imz,:,ivac,3),1)
     158             :             
     159             :          END DO
     160             :       END DO
     161             : 
     162             :       ! Calculate the charge and magnetization densities on the real space mesh:
     163           0 :       DO ivac = 1,vacuum%nvac
     164           0 :          DO imz = 1,vacuum%nmzxyd
     165           0 :             DO imesh = 1,ifft2
     166           0 :                rho_11   = rvacxy(imesh,imz,ivac,1)
     167           0 :                rho_22   = rvacxy(imesh,imz,ivac,2)
     168           0 :                rho_21r  = rvacxy(imesh,imz,ivac,3)
     169           0 :                rho_21i  = rvacxy(imesh,imz,ivac,4)
     170           0 :                mx       =  2*rho_21r
     171           0 :                my       = -2*rho_21i
     172           0 :                mz       = rho_11 - rho_22
     173           0 :                magmom   = SQRT(mx**2 + my**2 + mz**2)
     174           0 :                rhotot   = rho_11 + rho_22
     175           0 :                rho_up   = (rhotot + magmom)/2
     176           0 :                rho_down = (rhotot - magmom)/2
     177             : 
     178           0 :                CALL pol_angle(mx,my,mz,theta,phi)
     179             : 
     180           0 :                rvacxy(imesh,imz,ivac,1) = rho_up
     181           0 :                rvacxy(imesh,imz,ivac,2) = rho_down
     182           0 :                den%theta_vac(imesh,imz,ivac) = theta
     183           0 :                den%phi_vac(imesh,imz,ivac) = phi
     184             :             END DO
     185             :          END DO
     186             :        
     187           0 :          DO imz = vacuum%nmzxyd+1,vacuum%nmzd
     188           0 :             rho_11   = REAL(den%vac(imz,1,ivac,1))
     189           0 :             rho_22   = REAL(den%vac(imz,1,ivac,2))
     190           0 :             rho_21r  = REAL(den%vac(imz,1,ivac,3))
     191           0 :             rho_21i  = AIMAG(den%vac(imz,1,ivac,3))
     192           0 :             mx       =  2*rho_21r
     193           0 :             my       = -2*rho_21i
     194           0 :             mz       = rho_11 - rho_22
     195           0 :             magmom   = SQRT(mx**2 + my**2 + mz**2)
     196           0 :             rhotot   = rho_11 + rho_22
     197           0 :             rho_up   = (rhotot + magmom)/2
     198           0 :             rho_down = (rhotot - magmom)/2
     199             : 
     200           0 :             CALL pol_angle(mx,my,mz,theta,phi)
     201             : 
     202           0 :             den%vac(imz,1,ivac,1) = rho_up
     203           0 :             den%vac(imz,1,ivac,2) = rho_down
     204           0 :             den%theta_vac(1,imz,ivac) = theta
     205           0 :             den%phi_vac(1,imz,ivac) = phi
     206             :          END DO
     207             :       END DO
     208             :     
     209             :       ! Fourier transform the matrix potential back to reciprocal space:
     210           0 :       DO jspin = 1,input%jspins
     211           0 :          DO ivac = 1,vacuum%nvac
     212           0 :             DO imz = 1,vacuum%nmzxyd
     213           0 :                fftwork=0.0
     214             :                   CALL fft2d(stars,rvacxy(:,imz,ivac,jspin),fftwork,&
     215             :                        den%vac(imz,:,ivac,jspin),&
     216           0 :                        -1)
     217             :                
     218             :             END DO
     219             :          END DO
     220             :       END DO
     221             :     
     222             :       RETURN
     223             : 
     224         192 :    END SUBROUTINE rotate_int_den_to_local
     225             : 
     226         192 :    SUBROUTINE rotate_int_den_from_local(stars,atoms,vacuum,sym,input,den,vTot)
     227             : 
     228             :       !--------------------------------------------------------------------------
     229             :       ! This subroutine prepares the spin dependent 2x2 matrix potential for the 
     230             :       ! Hamiltonian setup. This is done in 4 steps.
     231             :       ! 
     232             :       ! i)   The spin up and down potential and the angles of the magentic field, 
     233             :       !      theta and phi, are reloaded from den.
     234             :       ! ii)  The spin up and down potential is Fourier transformed to real space 
     235             :       !      (theta and phi are also stored on the real space grid).
     236             :       ! iii) The four components of the matrix potential are calculated on the
     237             :       !      real space mesh.
     238             :       ! iv)  The matrix potential is Fourier transformed, stored in terms of
     239             :       !      stars and written to vTot%pw(_w).
     240             :       ! 
     241             :       ! Philipp Kurz 99/11/01
     242             :       !--------------------------------------------------------------------------
     243             : 
     244             :       !-------Important variables:----------------------------------------------- 
     245             :       ! ifft3: size of the 3d real space mesh
     246             :       ! ifft2: size of the 2d real space mesh
     247             :       ! vis: first interstitial spin up and down potential and angles of magnetic
     248             :       !      field (theta and phi)
     249             :       !      later four components of matrix potential all stored in real space
     250             :       !--------------------------------------------------------------------------
     251             : 
     252             :       ! 
     253             :       TYPE(t_input), INTENT(IN)     :: input
     254             :       TYPE(t_vacuum), INTENT(IN)    :: vacuum
     255             :       TYPE(t_sym),    INTENT(IN)    :: sym
     256             :       TYPE(t_stars),  INTENT(IN)    :: stars
     257             :       TYPE(t_atoms),  INTENT(IN)    :: atoms
     258             :       TYPE(t_potden), INTENT(IN)    :: den
     259             :       TYPE(t_potden), INTENT(INOUT) :: vTot
     260             :  
     261             :       INTEGER                       :: imeshpt, ipot, jspin, ig2, ig3, ivac
     262             :       INTEGER                       :: ifft2, ifft3, imz, iter, i
     263             :       REAL                          :: vup, vdown, veff, beff, vziw, theta, phi
     264             : 
     265         192 :       REAL, ALLOCATABLE             :: vvacxy(:,:,:,:), vis(:,:), vis2(:,:)
     266             :       REAL, ALLOCATABLE             :: fftwork(:)
     267             : 
     268             :       ! Initialize arrays for the potential matrix:
     269             : 
     270         192 :       ifft3 = 27*stars%mx1*stars%mx2*stars%mx3
     271         192 :       IF (ifft3.NE.SIZE(den%theta_pw)) CALL judft_error("Wrong size of angles")
     272         192 :       ifft2 = SIZE(den%phi_vac,1) 
     273             :     
     274        1152 :       ALLOCATE ( vis(ifft3,4),fftwork(ifft3),vis2(ifft3,4))
     275             :     
     276             :       ! Interstitial part:
     277             : 
     278             :       ! Fourier transform the diagonal part of the potential matrix (vTot%pw)
     279             :       ! to real space (vis):
     280         576 :       DO jspin = 1,input%jspins
     281         576 :          CALL fft3d(vis(:,jspin),fftwork, vTot%pw(:,jspin), stars,+1)
     282             :       END DO
     283             : 
     284             :       ! Calculate the four components of the matrix potential on the real space
     285             :       ! mesh:
     286     7185054 :       DO imeshpt = 1, ifft3
     287     7184862 :          vup   = vis(imeshpt,1)
     288     7184862 :          vdown = vis(imeshpt,2)
     289     7184862 :          theta = den%theta_pw(imeshpt)
     290     7184862 :          phi   = den%phi_pw(imeshpt)
     291             : 
     292     7184862 :          veff  = (vup + vdown)/2.0
     293     7184862 :          beff  = (vup - vdown)/2.0
     294             : 
     295     7184862 :          vis(imeshpt,1) = veff + beff*COS(theta) ! V_(1,1) [V+B_z]
     296     7184862 :          vis(imeshpt,2) = veff - beff*COS(theta) ! V_(2,2) [V-B_z]
     297     7184862 :          vis(imeshpt,3) = beff*SIN(theta)*COS(phi) ! Re(V_(2,1)) [B_x]
     298     7184862 :          vis(imeshpt,4) = beff*SIN(theta)*SIN(phi) ! Im(V_(2,1)) [B_y]
     299             : 
     300    35924502 :          DO ipot = 1,4
     301    35924310 :             vis2(imeshpt,ipot) =  vis(imeshpt,ipot) * stars%ufft(imeshpt-1)
     302             :          END DO
     303             :       END DO
     304             : 
     305             :       ! Fourier transform the matrix potential back to reciprocal space:
     306         576 :       DO ipot = 1,2
     307    14370108 :          fftwork=0.0
     308         384 :          CALL fft3d(vis(:,ipot),fftwork, vTot%pw(1,ipot), stars,-1)
     309    14370108 :          fftwork=0.0
     310         576 :          CALL fft3d(vis2(:,ipot),fftwork, vTot%pw_w(1,ipot), stars,-1)
     311             :       END DO
     312             :     
     313         192 :       CALL fft3d(vis(:,3),vis(:,4), vTot%pw(1,3), stars,-1)
     314         192 :       CALL fft3d(vis2(:,3),vis2(:,4), vTot%pw_w(1,3), stars,-1)
     315             : 
     316         192 :       IF (.NOT. input%film) RETURN
     317             : 
     318             :       ! Now the vacuum part starts:
     319             : 
     320           0 :       ALLOCATE(vvacxy(ifft2,vacuum%nmzxyd,2,4))
     321             :     
     322             :       ! Fourier transform the up and down potentials (vTot%vacz and vTot%vacxy)
     323             :       ! to real space (vvacxy):
     324           0 :       DO jspin = 1,input%jspins
     325           0 :          DO ivac = 1,vacuum%nvac
     326           0 :             DO imz = 1,vacuum%nmzxyd
     327           0 :                vziw = 0.0
     328             :                ! 
     329             :                   CALL fft2d(stars, vvacxy(:,imz,ivac,jspin),fftwork,&
     330           0 :                        vTot%vac(imz,:,ivac,jspin), 1)
     331             :                
     332             :             END DO
     333             :          END DO
     334             :       END DO
     335             : 
     336             :       ! Calculate the four components of the matrix potential in real space:
     337           0 :       DO ivac = 1,vacuum%nvac
     338           0 :          DO imz = 1,vacuum%nmzxyd
     339           0 :             DO imeshpt = 1,ifft2
     340           0 :                vup   = vvacxy(imeshpt,imz,ivac,1)
     341           0 :                vdown = vvacxy(imeshpt,imz,ivac,2)
     342           0 :                theta = den%theta_vac(imeshpt,imz,ivac)
     343           0 :                phi   = den%phi_vac(imeshpt,imz,ivac)
     344             : 
     345           0 :                veff  = (vup + vdown)/2.0
     346           0 :                beff  = (vup - vdown)/2.0
     347           0 :                vvacxy(imeshpt,imz,ivac,1) = veff + beff*COS(theta)
     348           0 :                vvacxy(imeshpt,imz,ivac,2) = veff - beff*COS(theta)
     349           0 :                vvacxy(imeshpt,imz,ivac,3) = beff*SIN(theta)*COS(phi)
     350           0 :                vvacxy(imeshpt,imz,ivac,4) = beff*SIN(theta)*SIN(phi)
     351             :             END DO
     352             :          END DO
     353             :           
     354           0 :          DO imz = vacuum%nmzxyd+1,vacuum%nmzd
     355           0 :             vup   = REAL(vTot%vac(imz,1,ivac,1))
     356           0 :             vdown = REAL(vTot%vac(imz,1,ivac,2))
     357           0 :             theta = den%theta_vac(1,imz,ivac)
     358           0 :             phi   = den%phi_vac(1,imz,ivac)
     359           0 :             veff  = (vup + vdown)/2.0
     360           0 :             beff  = (vup - vdown)/2.0
     361           0 :             vTot%vac(imz,1,ivac,1) = veff + beff*COS(theta)
     362           0 :             vTot%vac(imz,1,ivac,2) = veff - beff*COS(theta)
     363           0 :             vTot%vac(imz,1,ivac,3) = beff*SIN(theta)*COS(phi)+ImagUnit*beff*SIN(theta)*SIN(phi)
     364             :          END DO
     365             :       END DO
     366             : 
     367             :       ! Fourier transform the matrix potential back to reciprocal space:
     368           0 :       DO ipot = 1,2
     369           0 :          DO ivac = 1,vacuum%nvac
     370           0 :             DO imz = 1,vacuum%nmzxyd
     371           0 :                fftwork=0.0
     372             :                ! 
     373             :                   CALL fft2d(stars, vvacxy(:,imz,ivac,ipot),fftwork,&
     374           0 :                        vTot%vac(imz,:,ivac,ipot),-1)
     375             :                
     376             :             END DO
     377             :          END DO
     378             :       END DO
     379             : 
     380           0 :       DO ivac = 1,vacuum%nvac
     381           0 :          DO imz = 1,vacuum%nmzxyd
     382           0 :             fftwork=0.0
     383             :             ! 
     384             :                CALL fft2d(stars, vvacxy(:,imz,ivac,3),vvacxy(:,imz,ivac,4),&
     385           0 :                     vTot%vac(imz,:,ivac,3),-1)
     386             :             
     387             :          END DO
     388             :       END DO
     389             : 
     390             :       RETURN
     391             : 
     392         192 :    END SUBROUTINE rotate_int_den_from_local
     393             : 
     394             : END MODULE m_rotate_int_den_tofrom_local

Generated by: LCOV version 1.14