LCOV - code coverage report
Current view: top level - vgen - rotate_int_den_tofrom_local.f90 (source / functions) Coverage Total Hit
Test: FLEUR test coverage Lines: 40.0 % 160 64
Test Date: 2025-06-14 04:34:23 Functions: 100.0 % 2 2

            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          192 :       ALLOCATE(den%phi_pw(ifft3),den%theta_pw(ifft3))
      85              :       !ALLOCATE(den%phi_vacz(vacuum%nmzd,2),den%theta_vacz(vacuum%nmzd,2))
      86          384 :       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          192 :       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          192 :       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 2.0-1