LCOV - code coverage report
Current view: top level - juphon - dfpt_eii2.F90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 0 323 0.0 %
Date: 2024-05-15 04:28:08 Functions: 0 11 0.0 %

          Line data    Source code
       1             : module m_dfpt_eii2
       2             : 
       3             :   use m_types
       4             : 
       5             :   implicit none
       6             : 
       7             :   contains
       8             : 
       9             : 
      10             :   ! should be correct, has been reviewed
      11           0 :   subroutine GenPsDens2ndOrd(atoms, cell, ngpqdp, G0index, gpqdp, qpt, psDens2ndOrd, testMode)
      12             : 
      13             :     use m_sphbes
      14             : 
      15             :     implicit none
      16             : 
      17             :     ! Type parameter
      18             :     type(t_atoms),                  intent(in) :: atoms
      19             :     type(t_cell),                   intent(in) :: cell
      20             : 
      21             :     ! Scalar parameter
      22             :     integer,                        intent(in) :: ngpqdp
      23             :     logical,                        intent(in) :: testMode
      24             :     integer,                        intent(out):: G0index
      25             : 
      26             :     ! Array parameter
      27             :     integer,                        intent(in) :: gpqdp(:, :)
      28             :     real,                           intent(in) :: qpt(:)
      29             :     complex,           allocatable, intent(out):: psDens2ndOrd(:, :, :, :)
      30             : 
      31             :     ! Scalar variable
      32             :     integer                                    :: itype
      33             :     integer                                    :: ii
      34             :     integer                                    :: jj
      35             :     integer                                    :: iG
      36             :     integer                                    :: iatom
      37             :     integer                                    :: iatomTemp
      38             :     integer                                    :: ieqat
      39             : 
      40             :     ! Array variable
      41           0 :     real,              allocatable             :: sbes(:, :, :)
      42           0 :     real,              allocatable             :: psDensMat(:, :, :) ! Matrix part of pseudo density
      43           0 :     real,              allocatable             :: Gpqext(:, :)
      44           0 :     real,              allocatable             :: Gpq(:, :)
      45           0 :     complex,           allocatable             :: phaseFactor(:, :)
      46           0 :     real,              allocatable             :: GpqextRmt(:, :)
      47           0 :     real,              allocatable             :: prefactor(:)
      48             : 
      49             :     ! Initializiation of local arrays
      50           0 :     allocate(psDensMat(ngpqdp, 3, 3))
      51           0 :     allocate(psDens2ndOrd(ngpqdp, 3, atoms%nat, 3))
      52           0 :     allocate(Gpqext(3, ngpqdp))
      53           0 :     allocate(Gpq(3, ngpqdp))
      54           0 :     allocate( sbes( 0 : MAXVAL(atoms%ncv) + 1, ngpqdp, atoms%ntype) )
      55           0 :     allocate( phaseFactor(ngpqdp, atoms%nat) )
      56           0 :     allocate( GpqextRmt(ngpqdp, atoms%ntype) )
      57           0 :     allocate( prefactor(atoms%ntype) )
      58             : 
      59           0 :     sbes(:, :, :) = 0.
      60           0 :     GpqextRmt(:, :) = 0.
      61           0 :     psDensMat(:, :, :) = 0.
      62           0 :     psDens2ndOrd(:, :, :, :) = cmplx(0.0, 0.0)
      63           0 :     Gpqext(:, :) = 0.
      64           0 :     Gpq(:, :) = 0.
      65           0 :     G0index = -1
      66           0 :     prefactor(:) = 1.
      67           0 :     phaseFactor(:, :) = cmplx(0., 0.)
      68             : 
      69             :     ! Precalculate the matrix-like part of the pseudodensity
      70             :     ! todo If we optimize for the dynamical matrix in the end, we need one non-linear run through memory. As we have to evaluate every matrix
      71             :     !      element of the dynamical matrix seperately, it makes sense to shift the indices of the 3x3 matrix after iG to avoid redundant
      72             :     !      operations later.
      73           0 :     do iG = 1, ngpqdp
      74             :       ! If denominator gets zero skip G-vector, that happens only for q = 0, basically.
      75           0 :       if ( norm2( gpqdp(1:3, iG) + qpt(1:3) ) <= 1e-9 )  then
      76           0 :         G0index = iG
      77           0 :         cycle
      78             :       end if
      79             : 
      80             :       ! (G+q)(G+q)^T and ((G+q)(G+q)^T - (G+q)^2/3)
      81           0 :       Gpq(1:3, iG) = real(gpqdp(1:3, iG) + qpt(1:3))
      82           0 :       Gpqext(1:3, iG) = matmul(Gpq(1:3, iG), cell%bmat(1:3, 1:3))
      83           0 :       if ( testMode ) then
      84           0 :         psDensMat(iG, 1:3, 1:3) = outerProduct(Gpqext(1:3, iG), Gpqext(1:3, iG))
      85             :       else
      86           0 :         psDensMat(iG, 1:3, 1:3) = outerProduct(Gpqext(1:3, iG), Gpqext(1:3, iG)) - (norm2(Gpqext(1:3, iG))**2 * id3x3(1:3, 1:3) / 3.)
      87             :       end if
      88             :     end do ! iG
      89             : 
      90             :     iatom = 0
      91           0 :     do itype = 1, atoms%ntype
      92             : 
      93             :       ! Calculate double factorial (2 N + 7)!! in 7.78 (PhD thesis Klüppelberg). Note, atoms%ncv(itype) is already the value taken from
      94             :       ! Table 1 in the Weinert paper. For the orbital quantum number l = 2, this leads to
      95             :       ! (2 * atoms%ncv(itype) + 3)!! = (2 * N + 2 * l + 3)!! = (2 * N + 7)!!.
      96             :       ! The right hand side of the recent equation is consistent with 7.78 (PhD thesis Klüppelberg), where N is the Weinert parameter.
      97           0 :       do ii = 1, 2 * atoms%ncv(itype) + 3, 2
      98           0 :         prefactor(itype) = prefactor(itype) * ii
      99             :       end do ! ii
     100             : 
     101             :       ! Complete prefactor.
     102           0 :       prefactor(itype) = prefactor(itype) * atoms%zatom(itype) / cell%omtil
     103             : 
     104           0 :       iatomTemp = iatom
     105           0 :       do iG = 1, ngpqdp
     106             : 
     107             :         ! No pseudo density contribution for G + q = 0
     108           0 :         if (iG == G0index) cycle
     109             : 
     110           0 :         GpqextRmt(iG, itype) = norm2(Gpqext(1:3, iG)) * atoms%rmt(itype)
     111             :         ! sbes is initialized within sphbes with first parameter of sphbes
     112           0 :         call sphbes(atoms%ncv(itype) + 1, GpqextRmt(iG, itype), sbes(0:atoms%ncv(itype) + 1, iG, itype))
     113           0 :         iatom = iatomTemp
     114           0 :         do ieqat = 1, atoms%neq(itype)
     115           0 :           iatom = iatom + 1
     116           0 :           phaseFactor(iG, iatom) = exp(-tpi_const * ImagUnit * dot_product(Gpq(1:3, iG), atoms%taual(1:3, iatom)))
     117             :         end do ! ieqat
     118             :       end do ! iG
     119             :     end do ! itype
     120             : 
     121           0 :     do jj = 1, 3
     122             :       iatom = 0
     123           0 :       do itype = 1, atoms%ntype
     124           0 :         do ieqat = 1, atoms%neq(itype)
     125           0 :           iatom = iatom + 1
     126           0 :           do ii = 1, 3
     127           0 :             do iG = 1, ngpqdp
     128           0 :               if (iG == G0index) cycle
     129             :               ! Note that atoms%ncv = N + l, so for l = 2, we need only an exponent or the spherical Bessel function, respectively,
     130             :               ! of ncv + 1.
     131             :               psDens2ndOrd(iG, ii, iatom, jj) = prefactor(itype) / GpqextRmt(iG, itype)**(atoms%ncv(itype) + 1) &
     132           0 :                 &                           * sbes(atoms%ncv(itype) + 1, iG, itype) * psDensMat(iG, ii, jj) * phaseFactor(iG, iatom)
     133             :             end do ! iG
     134             :           end do ! jj
     135             :         end do ! ieqat
     136             :       end do ! itype
     137             :     end do ! jj
     138             : 
     139           0 :   end subroutine GenPsDens2ndOrd
     140             : 
     141           0 :   subroutine CalcIIEnerg2MatElem( atoms, cell, qpt, ngpqdp, gpqdp, E2ndOrdII )
     142             : 
     143             :     use m_sphbes
     144             : 
     145             :     implicit none
     146             : 
     147             :     ! Type parameter
     148             :     type(t_atoms),                  intent(in) :: atoms
     149             :     type(t_cell),                   intent(in) :: cell
     150             : 
     151             :     ! Scalar parameter
     152             :     integer,                        intent(in) :: ngpqdp
     153             : 
     154             :     ! Array parameter
     155             :     integer,                        intent(in) :: gpqdp(:, :)
     156             :     real,                           intent(in) :: qpt(:)
     157             :     complex,                        intent(out):: E2ndOrdII(:, :)
     158             : 
     159             :     ! Scalar variable
     160             :     integer                                    :: G0index
     161             :     integer                                    :: iG
     162             :     integer                                    :: iAdir
     163             :     integer                                    :: iBdir
     164             :     integer                                    :: oqn_l
     165             :     integer                                    :: mqn_m
     166             :     integer                                    :: lm
     167             :     integer                                    :: t
     168             :     logical                                    :: testMode
     169             :     integer                                    :: iAtype
     170             :     integer                                    :: iBtype
     171             :     integer                                    :: iAatom
     172             :     integer                                    :: iBatom
     173             :     integer                                    :: iAeqat
     174             :     integer                                    :: iBeqat
     175             : 
     176             : 
     177             :     ! Array variables
     178           0 :     complex,           allocatable             :: psDens2ndOrd(:, :, :, :)
     179           0 :     complex,           allocatable             :: expAlpha(:)
     180           0 :     real,              allocatable             :: Gpqext(:, :)
     181           0 :     real,              allocatable             :: sbes(:, :)
     182             : 
     183           0 :     allocate( expAlpha(ngpqdp) )
     184           0 :     allocate( Gpqext(3, ngpqdp))
     185           0 :     allocate( sbes(0:atoms%lmaxd, ngpqdp) )
     186             : 
     187           0 :     E2ndOrdII(:, :) = cmplx(0.0, 0.0)
     188           0 :     expAlpha(:) = cmplx(0.0, 0.0)
     189           0 :     Gpqext(:, :) = 0.0
     190           0 :     sbes(:, :) = 0.0
     191             : 
     192             :     ! Generates pseudodensity as it is given in 7.95 Aaron Phd thesis, or for q = 0 in 7.78 Aaron Phd thesis
     193             :     ! We leave the test mode on, leading to the fact that the trace is not subtracted. Therefore, we have a non-vanishing diagonal.
     194           0 :     testMode = .true.
     195           0 :     call GenPsDens2ndOrd(atoms, cell, ngpqdp, G0index, gpqdp, qpt, psDens2ndOrd, testMode)
     196             : 
     197             :     ! Leave it here so it needs not be calculated 3N x 3N times.
     198           0 :     do iG = 1, ngpqdp
     199           0 :       Gpqext(1:3, iG) = matmul(real(gpqdp(1:3, iG) + qpt(1:3)), cell%bmat(1:3, 1:3))
     200             :     end do ! iG
     201             : 
     202           0 :     iAatom = 0
     203           0 :     do iAtype = 1, atoms%ntype
     204           0 :       sbes(:, :) = 0.0
     205           0 :       do iG = 1, ngpqdp
     206             :         ! If we precalcalculate the scalar factor we have 7 multiplications less
     207             :         !todo we can also only calculate it to 0 not to lmaxd for performance reasons
     208           0 :         call Sphbes( atoms%lmaxd, norm2(Gpqext(1:3, iG)) * atoms%rmt(iAtype), sbes(0:atoms%lmaxd, iG) )
     209             :       end do
     210           0 :       do iAeqat = 1, atoms%neq(iAtype)
     211           0 :         iAatom = iAatom + 1
     212           0 :         expAlpha(:) = cmplx(0.0, 0.0)
     213           0 :         do iG = 1, ngpqdp
     214           0 :           expAlpha(iG) = exp(tpi_const * ImagUnit * dot_product(gpqdp(1:3, iG) + qpt(1:3), atoms%taual(1:3, iAatom)))
     215             :         end do
     216           0 :         do iAdir = 1, 3
     217             :           iBatom = 0
     218           0 :           do iBtype = 1, atoms%ntype
     219           0 :             do iBeqat = 1, atoms%neq(iBtype)
     220           0 :               iBatom = iBatom + 1
     221           0 :               if (iBatom /= iAatom) then
     222           0 :                 do iBdir = 1, 3
     223             :                   ! Add contribution 7.99
     224           0 :                   do iG = 1, ngpqdp
     225           0 :                     if (iG == G0index) cycle
     226             :                     E2ndOrdII( iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1) ) = &
     227             :                       & E2ndOrdII( iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1) ) &
     228             :                       + atoms%zatom(iAtype) * fpi_const / &
     229           0 :                                                 & norm2(Gpqext(1:3, iG))**2 * psDens2ndOrd(iG, iBdir, iBatom, iAdir) * expAlpha(iG)
     230             :                   end do ! iG
     231             :                 end do ! iBdir
     232             :               else ! iBatom = iAatom
     233             :                 oqn_l = 0
     234             :                 mqn_m = 0
     235             :                 lm = oqn_l * (oqn_l + 1) + 1 + mqn_m
     236           0 :                 do iBdir = 1, 3
     237           0 :                   do iG = 1, ngpqdp
     238           0 :                     if (iG == G0index) cycle
     239             :                     E2ndOrdII( iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1) ) = &
     240             :                       E2ndOrdII( iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1) ) + atoms%zatom(iAtype) * fpi_const *               &
     241           0 :                       & psDens2ndOrd(iG, iBdir, iBatom, iAdir) * sbes(0, iG) / norm2(Gpqext(:, iG))**2 * expAlpha(iG)
     242             :                   end do
     243             :                   ! Constant term is switched off because it is subtracted away anyway in Equation 7.89, as q-independent
     244           0 :                   if (.false.) then
     245             :                     do t = -1, 1
     246             :                       E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1)) = &
     247             :                         & E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom -1)) &
     248             :                                  - atoms%zatom(iAtype) * atoms%zatom(iBtype) / atoms%rmt(iBtype)**3 * &
     249             :                                             & ( 3 / fpi_const * c_im(iBdir, t + 2) * c_im(iAdir, 2 - t) * (-1)**t  )
     250             :                     end do ! t
     251             :                   end if ! Constant term switched off
     252             :                 end do ! iBdir
     253             :               end if ! iBatom = iAatom ?
     254             :             end do ! iBeqat
     255             :           end do ! iBtype
     256             : 
     257             :           ! Constant term is switched off because it is subtracted away anyway in Equation 7.89 because it is not dependent on q
     258           0 :           if (.false.) then
     259             :             ! Factor 3 because it is within the t-sum
     260             :             E2ndOrdII(iAdir + 3 * (iAatom - 1), iAdir + 3 * (iAatom -1)) = E2ndOrdII(iAdir, iAdir) + 3 * atoms%zatom(iAtype) * atoms%zatom(iAtype) / atoms%rmt(iAtype)**3
     261             :           end if ! Constant term switched off
     262             : 
     263             :         end do ! iAdir
     264             :       end do ! iAeqat
     265             :     end do ! iAtype
     266             : 
     267           0 :   end subroutine CalcIIEnerg2MatElem
     268             : 
     269           0 :   SUBROUTINE getConstTerm(atoms, cell, constTerm)
     270             :      TYPE(t_atoms), INTENT(IN) :: atoms
     271             :      TYPE(t_cell),  INTENT(IN) :: cell
     272             : 
     273             :      REAL, INTENT(OUT) :: constTerm(:, :)
     274             : 
     275             :      INTEGER :: iAlpha, iBeta
     276             : 
     277             :      REAL :: tauExtAlpha(3), tauExtBeta(3), vecR(3)
     278             : 
     279           0 :      constTerm = 0.0
     280             : 
     281           0 :      DO iBeta = 1, atoms%nat
     282           0 :         tauExtBeta = MATMUL(cell%amat, atoms%taual(:, iBeta))
     283           0 :         DO iAlpha = 1, atoms%nat
     284           0 :            IF (iBeta==iAlpha) CYCLE
     285           0 :            tauExtAlpha = MATMUL(cell%amat, atoms%taual(:, iAlpha))
     286           0 :            vecR = tauExtAlpha - tauExtBeta
     287             :            constTerm(3*(iBeta-1) + 1:3*(iBeta-1) + 3, 3*(iAlpha-1) + 1:3*(iAlpha-1) + 3) &
     288           0 :            & = atoms%zatom(iBeta) * atoms%zatom(iBeta) * (3*outerProduct(vecR,vecR)-id3x3*norm2(vecR)**2) / norm2(vecR)**5
     289             :        END DO
     290             :      END DO
     291           0 :   END SUBROUTINE
     292             : 
     293           0 :   subroutine CalcIIEnerg2(atoms, cell, qpts, stars, input, iqpt, ngdp, gdp, E2ndOrdII)
     294             : 
     295             :     use m_sphbes
     296             : 
     297             :     implicit none
     298             : 
     299             : 
     300             :     ! Type parameter
     301             :     type(t_atoms),                  intent(in) :: atoms
     302             :     type(t_cell),                   intent(in) :: cell
     303             :     type(t_kpts),                   intent(in) :: qpts
     304             :     type(t_stars),                  intent(in) :: stars
     305             :     type(t_input),                  intent(in) :: input
     306             : 
     307             :     ! Scalar parameter
     308             :     integer,                        intent(in) :: iqpt
     309             :     integer,                        intent(in) :: ngdp
     310             : 
     311             :     ! Array parameter
     312             :     integer,                        intent(in) :: gdp(:, :)
     313             :     complex,           allocatable, intent(out):: E2ndOrdII(:, :)
     314             : 
     315             :     ! Scalar variables
     316             :     integer                                    :: iAtype
     317             :     integer                                    :: iBtype, iCtype
     318             :     integer                                    :: iAeqat
     319             :     integer                                    :: iBeqat
     320             :     integer                                    :: iAatom
     321             :     integer                                    :: iBatom
     322             :     integer                                    :: iAdir
     323             :     integer                                    :: iBdir, iCdir
     324             :     integer                                    :: ngpqdp2km
     325             :     integer                                    :: ngpqdp
     326             : 
     327             :     LOGICAL :: oldStuff
     328             : 
     329             :     ! Array variables
     330             :     complex,           allocatable             :: E2ndOrdIIatFinQ(:, :)
     331             :     complex,           allocatable             :: E2ndOrdIIatQ0(:, :)
     332             :     real,              allocatable             :: constTerm(:, :)
     333           0 :     integer,           allocatable             :: gpqdp(:, :)
     334             : 
     335           0 :     oldStuff = .FALSE.
     336             : 
     337             :     ! We get the same results for -q and q, probably because Eii2 is a real quantity
     338             :     ! todo only generate G-vectors once in the beginning #56, leave the -q version here so that we can test it to be the same
     339           0 :     call genPertPotDensGvecs( stars, cell, input, ngpqdp, ngpqdp2km, -qpts%bk(1:3, iqpt), gpqdp )
     340             : 
     341             : #ifdef DEBUG_MODE
     342             :     if (.false.) then
     343             :       call genPertPotDensGvecs( stars, cell, input, ngpqdp, ngpqdp2km, qpts%bk(1:3, iqpt), gpqdp )
     344             :     end if
     345             : #endif
     346             : 
     347             :     ! Create final Eii2 matrix and temporary array for passing to the subroutine
     348           0 :     allocate( E2ndOrdII(3 * atoms%nat, 3 * atoms%nat) )
     349           0 :     allocate( E2ndOrdIIatFinQ(3 * atoms%nat, 3 * atoms%nat) )
     350           0 :     allocate( E2ndOrdIIatQ0(3 * atoms%nat, 3 * atoms%nat) )
     351           0 :     allocate( constTerm(3 * atoms%nat, 3 * atoms%nat) )
     352             : 
     353           0 :     E2ndOrdII = cmplx(0.0, 0.0)
     354           0 :     E2ndOrdIIatFinQ = cmplx(0.0, 0.0)
     355           0 :     E2ndOrdIIatQ0 = cmplx(0.0, 0.0)
     356             : 
     357             :     ! Call the routine for q = 0
     358           0 :     call CalcIIEnerg2MatElem(atoms, cell, [0.0,0.0,0.0], ngdp, gdp, E2ndOrdIIatQ0)
     359             : 
     360             :     ! Call the routine for finite q
     361           0 :     call CalcIIEnerg2MatElem(atoms, cell, -qpts%bk(1:3, iqpt), ngpqdp, gpqdp, E2ndOrdIIatFinQ)
     362             : 
     363           0 :     CALL getConstTerm(atoms, cell, constTerm)
     364             : 
     365             :     !write(4543,*) E2ndOrdIIatQ0
     366             :     !write(4544,*) E2ndOrdIIatFinQ
     367             : 
     368             : #ifdef DEBUG_MODE
     369             :     if (.false.) then
     370             :       ! We get the same results for -q and q, probably because Eii2 is a real quantity
     371             :       call CalcIIEnerg2MatElem(atoms, cell, qpts%bk(1:3, iqpt), ngpqdp, gpqdp, E2ndOrdIIatFinQ)
     372             :     end if
     373             : #endif
     374           0 :     iAatom = 0
     375           0 :     do iAtype = 1, atoms%ntype
     376           0 :       do iAeqat = 1, atoms%neq(iAtype)
     377           0 :         iAatom = iAatom + 1
     378           0 :         do iAdir = 1, 3
     379             :           iBatom = 0
     380           0 :           do iBtype = 1, atoms%ntype
     381           0 :             do iBeqat = 1, atoms%neq(iBtype)
     382           0 :               iBatom = iBatom + 1
     383           0 :               do iBdir = 1, 3
     384           0 :                 IF (oldStuff) THEN
     385             :                 E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) =          &
     386             :                    & E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1))      &
     387             :                    & - E2ndOrdIIatQ0(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) &
     388             :                    & + E2ndOrdIIatFinQ(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1))
     389             :                 ELSE
     390             :                    E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) = &
     391             :                  & E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) + &
     392           0 :                  & E2ndOrdIIatFinQ(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1))
     393           0 :                    IF (iBatom/=iAatom) THEN
     394             :                   !    E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) = &
     395             :                   !  & E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) - &
     396             :                   !  & constTerm(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1))
     397             :                    ELSE
     398           0 :                       DO iCtype = 1, atoms%ntype
     399             :                         !DO iCdir = 1, 3
     400             :                            E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) = &
     401             :                          & E2ndOrdII(iBdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) - &
     402           0 :                          & E2ndOrdIIatQ0(iBdir + 3 * (iCtype - 1), iAdir + 3 * (iAatom - 1))
     403             :                         !END DO
     404             :                         IF (iCtype==iBtype) CYCLE
     405           0 :                         DO iCdir = 1, 3
     406             :                         !   E2ndOrdII(iCdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) = &
     407             :                         ! & E2ndOrdII(iCdir + 3 * (iBatom - 1), iAdir + 3 * (iAatom - 1)) + &
     408             :                         ! & constTerm(iCdir + 3 * (iCtype - 1), iAdir + 3 * (iAatom - 1))
     409             :                         END DO
     410             :                       END DO
     411             :                    END IF
     412             :                 END IF
     413             :               end do ! iBdir
     414             :             end do ! iBeqat
     415             :           end do ! iBtype
     416             :         end do ! iAdir
     417             :       end do ! iAeqat
     418             :     end do ! iAtype
     419             : 
     420           0 :   end subroutine CalcIIEnerg2
     421             : 
     422             :   ! Creates interstitial and muffin-tin coefficients of the second-variation external potential required for the Dynamical Matrix using
     423             :   ! the Weinert method.
     424             :   ! Main subroutine for creating the second-order V_ext interstitial coefficients and muffin-tin coefficients using the Weinert method.
     425             :   ! Here the output is a matrix!!! So the factor of 2 is multiplied in the dynamical matrix not before multipliying the Qs.
     426           0 :   subroutine GenVext2(atoms, cell, ngdp, gdp, vExt2IR, vExt2MT, testMode)
     427             : 
     428             :     implicit none
     429             : 
     430             :     ! Type parameter
     431             :     type(t_atoms),                  intent(in) :: atoms
     432             :     type(t_cell),                   intent(in) :: cell
     433             : 
     434             :     ! Scalar parameter
     435             :     integer,                        intent(in) :: ngdp
     436             :     logical,                        intent(in) :: testMode
     437             : 
     438             :     ! Array parameter
     439             :     integer,                        intent(in) :: gdp(:, :)
     440             :     complex,           allocatable, intent(out):: vExt2IR(:, :, :, :)
     441             :     complex,           allocatable, intent(out):: vExt2MT(:, :, :, :)
     442             : 
     443             :     ! Scalar variables
     444             :     integer                                    :: G0index
     445             :     integer                                    :: iatom
     446             :     integer                                    :: itype
     447             :     integer                                    :: ieqat
     448             :     integer                                    :: ii
     449             :     integer                                    :: jj
     450             :     integer                                    :: iG
     451             : 
     452             :     ! Array variables
     453           0 :     real,              allocatable             :: Gext(:, :)
     454           0 :     complex,           allocatable             :: psDens2ndOrd(:, :, :, :)
     455             : 
     456           0 :     allocate(vExt2IR(ngdp, 3, 3, atoms%nat))
     457           0 :     allocate(Gext(3, ngdp))
     458           0 :     vExt2IR = cmplx(0.0, 0.0)
     459             : 
     460           0 :     call GenPsDens2ndOrd(atoms, cell, ngdp, G0index, gdp, [0., 0., 0.], psDens2ndOrd, testMode)
     461             : 
     462           0 :     do iG = 1, ngdp
     463           0 :       Gext(:, iG) = matmul(gdp(:, iG), cell%bmat)
     464             :     end do
     465             : 
     466           0 :     iatom = 0
     467           0 :     do itype = 1, atoms%ntype
     468           0 :       do ieqat = 1, atoms%neq(itype)
     469           0 :         iatom = iatom + 1
     470           0 :           do jj = 1, 3
     471           0 :             do ii = 1, 3
     472           0 :               do iG = 1, ngdp
     473           0 :                 if ( iG /= G0index ) then
     474           0 :                   vExt2IR(iG, ii, jj, iatom) = fpi_const * psDens2ndOrd(iG, ii, iatom, jj ) / norm2(Gext(:, iG))**2
     475             :                 end if
     476             :               end do
     477             :             end do
     478             :           end do
     479             :         end do
     480             :     end do ! iG
     481             : 
     482           0 :     call GenVext2MT(atoms, cell, ngdp, gdp, testMode, vExt2IR, vExt2MT)
     483             : 
     484           0 :   end subroutine GenVext2
     485             : 
     486             :   ! Generates second-order V_ext coefficients for the muffin-tin region.
     487           0 :   subroutine GenVext2MT(atoms, cell, ngdp, gdp, testMode, vExt2IR, vExt2MT)
     488             : 
     489             :     use m_gaunt, only : gaunt1
     490             :     use m_sphbes
     491             :     use m_jpGrVeff0, only : Phasy1nSym
     492             : 
     493             :     implicit none
     494             : 
     495             :     ! Type parameters
     496             :     type(t_atoms),              intent(in)  :: atoms
     497             :     type(t_cell),               intent(in)  :: cell
     498             : 
     499             :     ! Scalar parameters
     500             :     integer,                    intent(in)  :: ngdp
     501             : 
     502             :     ! Array parameters
     503             :     integer,                    intent(in)  :: gdp(:, :)
     504             :     logical,                    intent(in)  :: testMode
     505             :     complex,                    intent(in)  :: vExt2IR(:, :, :, :)
     506             :     complex,       allocatable, intent(out) :: vExt2MT(:, :, :, :)
     507             :     ! Scalar variables
     508             :     integer                                 :: itype
     509             :     integer                                 :: ii
     510             :     integer                                 :: jj
     511             :     integer                                 :: oqn_l
     512             :     integer                                 :: mqn_m
     513             :     integer                                 :: t
     514             :     integer                                 :: tPrime
     515             :     integer                                 :: lm
     516             :     integer                                 :: imesh
     517             :     integer                                 :: iatom
     518             :     integer                                 :: ieqat
     519             :     integer                                 :: iG
     520             :     integer                                 :: iDtype
     521             :     integer                                 :: iDeqat
     522             :     integer                                 :: iDatom
     523             : 
     524             :     !complex(kind=16) :: kindTest ?? This is not portable 
     525             : 
     526             :     ! Array variables
     527             :     ! lmax is 2, so the upper limit of lm is (2 + 1)**3 = 9
     528             :     real                                    :: Gext(3)
     529           0 :     real                                    :: sbes(0:atoms%lmaxd)
     530           0 :     real,          allocatable              :: prfMesh(:, :)
     531           0 :     complex,       allocatable              :: pylm(:, :)
     532           0 :     complex,       allocatable              :: surfIntMat(:, :, :, :, :)
     533           0 :     complex,       allocatable              :: scalFac(:)
     534           0 :     real,          allocatable              :: recMesh(:, :)
     535             :     complex                                 :: volIntMat(9, 3, 3)
     536             :     complex                                 :: volIntMatTest(9, 3, 3)
     537             : 
     538             :     complex :: testMat(3, 3)
     539             : 
     540           0 :     allocate( recMesh(atoms%jmtd, atoms%ntype) )
     541           0 :     recMesh(:, :) = 0.
     542             : 
     543             :     ! Calculate the lm dependent matrix part of the 2nd order external potential
     544           0 :     volIntMat = cmplx(0.0, 0.0)
     545             :     volIntMatTest = cmplx(0.0, 0.0)
     546             : 
     547             :     ! l = 0, m = 0
     548             :     !if (testMode) then
     549             :     if (.false.) then
     550             :       volIntMat(1, 1, 1) = cmplx(sqrt(fpi_const), 0.)
     551             :       volIntMat(1, 2, 2) = cmplx(sqrt(fpi_const), 0.)
     552             :       volIntMat(1, 3, 3) = cmplx(sqrt(fpi_const), 0.)
     553             :     end if
     554             : 
     555             :     ! l = 1 has vanishing Gaunt coefficients.
     556             : 
     557             :     ! l = 2,  m = -2
     558           0 :     volIntMat(5, 1, 1) = cmplx(sqrt(3 * tpi_const / 5), 0.)
     559           0 :     volIntMat(5, 2, 2) = cmplx(-sqrt(3 * tpi_const / 5), 0.)
     560           0 :     volIntMat(5, 1, 2) = cmplx(0., sqrt(3 * tpi_const / 5))
     561           0 :     volIntMat(5, 2, 1) = cmplx(0., sqrt(3 * tpi_const / 5))
     562             : 
     563             :     ! l = 2, m = -1
     564           0 :     volIntMat(6, 1, 3) = cmplx(sqrt(3 * tpi_const / 5), 0.)
     565           0 :     volIntMat(6, 3, 1) = cmplx(sqrt(3 * tpi_const / 5), 0.)
     566           0 :     volIntMat(6, 2, 3) = cmplx(0., sqrt(3 * tpi_const / 5))
     567           0 :     volIntMat(6, 3, 2) = cmplx(0., sqrt(3 * tpi_const / 5))
     568             : 
     569             :     ! l = 2, m = 0
     570           0 :     volIntMat(7, 1, 1) = cmplx(-sqrt(fpi_const / 5), 0.)
     571           0 :     volIntMat(7, 2, 2) = cmplx(-sqrt(fpi_const / 5), 0.)
     572           0 :     volIntMat(7, 3, 3) = cmplx(4 * sqrt(pi_const / 5), 0.)
     573             : 
     574             :     ! l = 2,  m = 1
     575           0 :     volIntMat(8, 1, 3) = cmplx(-sqrt(3 * tpi_const / 5), 0.)
     576           0 :     volIntMat(8, 3, 1) = cmplx(-sqrt(3 * tpi_const / 5), 0.)
     577           0 :     volIntMat(8, 3, 2) = cmplx(0., sqrt(3 * tpi_const / 5))
     578           0 :     volIntMat(8, 2, 3) = cmplx(0., sqrt(3 * tpi_const / 5))
     579             : 
     580             :     ! l = 2, m = 2
     581           0 :     volIntMat(9, 1, 1) = cmplx(sqrt(3 * tpi_const / 5), 0.)
     582           0 :     volIntMat(9, 2, 2) = cmplx(-sqrt(3 * tpi_const / 5), 0.)
     583           0 :     volIntMat(9, 1, 2) = cmplx(0., -sqrt(3 * tpi_const / 5))
     584           0 :     volIntMat(9, 2, 1) = cmplx(0., -sqrt(3 * tpi_const / 5))
     585             : 
     586             :     if (.false.) then
     587             :     do jj = 1, 3
     588             :       do ii = 1, 3
     589             :         do oqn_l = 0, 2, 2
     590             :           do t = -1, 1
     591             :             do tPrime = -1, 1
     592             :               ! For l = 0, we only have m = 0
     593             :               if (abs(t + tPrime) > oqn_l) cycle
     594             :               lm = oqn_l * (oqn_l + 1) + 1 + t + tPrime
     595             :               ! + 2 because c_im array starts at 1 and not at - 1
     596             :               volIntMatTest(lm, ii, jj) = volIntMatTest(lm, ii, jj) + 3 * c_im(ii, t + 2) * c_im(jj, tPrime + 2)                   &
     597             :               &  * gaunt1(oqn_l, 1, 1, t + tPrime, t, tPrime, 2)
     598             :             end do
     599             :           end do
     600             :         end do ! oqn_l
     601             :       end do ! ii
     602             :     end do ! jj
     603             :    ! if (.not.testMode) then
     604             :    !   volIntMat(1, :, :) = cmplx(0.0, 0.0)
     605             :    ! end if
     606             : 
     607             :     do lm = 1, 9
     608             :       do jj = 1, 3
     609             :         do ii = 1, 3
     610             :           write(1104, '(3(i8),2(f15.8))') jj, ii, lm, volIntMatTest(lm, ii, jj)
     611             :           write(1105, '(3(i8),2(es15.8))') jj, ii, lm, volIntMatTest(lm, ii, jj) - volIntMat(lm, ii, jj)
     612             :         end do ! lm
     613             :       end do ! ii
     614             :       write(1104, *)
     615             :       write(1105, *)
     616             :     end do ! jj
     617             : 
     618             :     do jj = 1, 3
     619             :       write(*, '(i8,1x,2(es15.8))') jj, volIntMat(1, jj, jj)
     620             :     end do ! lm
     621             :     write(*, *) 'shack'
     622             : 
     623             :   end if
     624             : 
     625             : 
     626             : !    testMat = 0
     627             : !    do lm = 1, 10
     628             : !      testMat(:, :) = testMat(:, :) + volIntMat(lm, :, :)
     629             : !    end do
     630             : !    do ii = 1, 3
     631             : !      do jj = 1, 3
     632             : !        write(*, *) testMat(jj, ii)
     633             : !      end do
     634             : !    end do
     635             : !
     636             : !    NOstopNO
     637             : !    do jj = 1, 9
     638             : !      write(*, *) jj
     639             : !      do ii = 1, 3
     640             : !        write(*, '(3(2(f15.8),2x))') volIntMat(jj, ii, 1), volIntMat(jj, ii, 2), volIntMat(jj, ii, 3)
     641             : !      end do
     642             : !      write(*, *)
     643             : !    end do
     644             : !   ! do ii = 1, 3
     645             : !   !   do jj = 1, 3
     646             : !   !     write(*, *) jj, ii, c_im(jj, ii)
     647             : !   !   end do
     648             : !   ! end do
     649             : !   ! NOstopNO
     650             : !!    write(*, *) 'gaunt'
     651             : !    write(*, *) gaunt1(0, 1, 1, 0, 0, 0, 2)
     652             : !    write(*, *) gaunt1(0, 1, 1, 0, -1, 1, 2)
     653             : !    write(*, *) gaunt1(0, 1, 1, 0, 1, -1, 2)
     654             : !    NOstopNO
     655             :    ! NOstopNO
     656             : !    write(*, *) gaunt1(0, 1, 1, 0, -1, 1, 2)
     657             : !    NOstopNO
     658             : !    write(*, *) 1. / 4. / 3.14 !    NOstopNO
     659             : !    do t = 1, 3
     660             : !      do tPrime = 1, 3
     661             : !        write(*, *) tPrime, t, c_im(tPrime, t)
     662             : !      end do
     663             : !    end do
     664             : !    NOstopNO
     665             : 
     666             : 
     667             :     ! Calculate the mesh dependent prefactor
     668           0 :     allocate( prfMesh(atoms%jmtd, atoms%ntype) )
     669           0 :     prfMesh = cmplx(0.0, 0.0)
     670           0 :     do itype = 1, atoms%ntype
     671             :       ! Numerical optimization. At the MT boundary, we set the factor zero because it is analytically zero to prevent error propagation.
     672           0 :       do imesh = 1, atoms%jri(itype) - 1
     673           0 :         prfMesh(imesh, itype) = atoms%zatom(itype) * (1 - (atoms%rmsh(imesh, itype) / atoms%rmt(itype))**5)
     674           0 :         recMesh(imesh, itype) = atoms%rmsh(imesh, itype)**(-3)
     675             :       end do
     676             :     end do
     677             : 
     678             :     ! Calculate the surface integral part of the Dirichelet boundary problem
     679           0 :     allocate( surfIntMat((atoms%lmaxd + 1)**2, 3, 3, atoms%nat, atoms%nat) )
     680           0 :     allocate( pylm(( atoms%lmaxd + 1 )**2, atoms%nat) )
     681           0 :     allocate( scalFac(( atoms%lmaxd + 1 )**2) )
     682           0 :     surfIntMat(:, :, :, :, :) = cmplx(0.0, 0.0)
     683           0 :     pylm = cmplx(0.0, 0.0)
     684           0 :     scalFac = cmplx(0.0, 0.0)
     685             :     iatom = 0
     686           0 :     do itype = 1, atoms%ntype
     687           0 :       do ieqat = 1, atoms%neq(itype)
     688           0 :         iatom = iatom + 1
     689           0 :         do iG = 1, ngdp
     690           0 :           if ( all( gdp(:, iG)  == 0 ) ) then
     691             :             !todo we should determine the G=0 vector once or put it to the beginning at all
     692             :             cycle
     693             :           end if
     694           0 :           Gext(1:3) = matmul( gdp(1:3, iG), cell%bmat(1:3, 1:3) )
     695           0 :           pylm(:, :) = cmplx(0.0, 0.0)
     696           0 :           scalFac(:) = cmplx(0.0, 0.0)
     697           0 :           sbes(:) = cmplx(0., 0.)
     698           0 :           call phasy1nSym( atoms, cell, gdp(:, iG), [0., 0., 0.], pylm )
     699           0 :           call Sphbes( atoms%lmax(itype), norm2( Gext ) * atoms%rmt(itype), sbes )
     700             :           ! If we precalcalculate the scalar factor we have 7 multiplications less
     701           0 :           do oqn_l = 0, atoms%lmax(itype)
     702           0 :             do mqn_m = -oqn_l, oqn_l
     703           0 :               lm = oqn_l * (oqn_l + 1) + mqn_m + 1
     704           0 :               scalFac(lm) = sbes(oqn_l) * pylm(lm, iatom)
     705             :             end do
     706             :           end do
     707             :           iDatom = 0
     708           0 :           do iDtype = 1, atoms%ntype
     709           0 :             do iDeqat = 1, atoms%neq(iDtype)
     710           0 :               iDatom = iDatom + 1
     711           0 :               do jj = 1, 3
     712           0 :                 do ii = 1, 3
     713           0 :                   do oqn_l = 0, atoms%lmax(itype)
     714           0 :                     do mqn_m = -oqn_l, oqn_l
     715           0 :                       lm = oqn_l * (oqn_l + 1) + mqn_m + 1
     716             :                       surfIntMat(lm, ii, jj, iDatom, iatom) = surfIntMat(lm, ii, jj, iDatom, iatom) + vExt2IR(iG, ii, jj, iDatom)  &
     717           0 :                                                                                                                      & * scalFac(lm)
     718             :                     end do
     719             :                   end do
     720             :                 end do
     721             :               end do
     722             :             end do
     723             :           end do
     724             :         end do
     725             :       end do
     726             :     end do
     727           0 :     deallocate(pylm, scalFac)
     728             : 
     729             :     ! Add the volume and surface integral contribution of the Dirichelet boundary problem for determing the MT coefficients of the 2nd
     730             :     ! order external potential
     731             :     ! We have chosen this loop structure sothat the if-statement is as outermost as possible
     732           0 :     allocate(vExt2MT(atoms%jmtd, (atoms%lmaxd + 1)**2, 3 * atoms%nat, 3 * atoms%nat ))
     733           0 :     vExt2MT = cmplx(0.0, 0.0)
     734             :     iDatom = 0
     735           0 :     do iDtype = 1, atoms%ntype
     736           0 :       do iDeqat = 1, atoms%neq(iDtype)
     737           0 :         iDatom = iDatom + 1
     738           0 :         do jj = 1, 3
     739             :           iatom = 0
     740           0 :           do itype = 1, atoms%ntype
     741           0 :             do ieqat = 1, atoms%neq(itype)
     742           0 :               iatom = iatom + 1
     743           0 :               if ( iatom == iDatom ) then
     744           0 :                 do ii = 1, 3
     745             :                 ! if trace is subtracted there is no l = 0 component
     746             :                   !do oqn_l = 0, 2, 2
     747           0 :                   do oqn_l = 2, 2
     748             :                   !do oqn_l = 0, 2
     749           0 :                     do mqn_m = -oqn_l, oqn_l
     750           0 :                       lm = oqn_l * (oqn_l + 1) + 1 + mqn_m
     751           0 :                       do imesh = 1, atoms%jri(itype)
     752             :                         vExt2MT(imesh, lm, ii + (iatom - 1) * 3, jj + (iDatom - 1) * 3) =                                          &
     753             :                                                                 & vExt2MT(imesh, lm, ii + (iatom - 1) * 3,  jj + (iDatom - 1) * 3) &
     754             :                                                               ! We calculate prfMesh * volIntMat first due to numerical stability
     755           0 :                                                          & - (prfMesh(imesh, itype) * volIntMat(lm, ii, jj)) * recMesh(imesh, itype)
     756             :                       end do ! imesh
     757             :                     end do ! mqn_m
     758             :                   end do ! oqn_l
     759             :                 end do ! ii
     760             :               end if ! within displaced muffin-tin
     761             : 
     762             :               ! Add surface integral contribution.
     763           0 :               do ii = 1, 3
     764           0 :                 do oqn_l = 0, atoms%lmax(itype)
     765           0 :                   do mqn_m = -oqn_l, oqn_l
     766           0 :                     lm = oqn_l * (oqn_l + 1) + 1 + mqn_m
     767           0 :                     do imesh = 1, atoms%jri(itype)
     768             :                       vExt2MT(imesh, lm, ii + (iatom - 1) * 3, jj + (iDatom - 1) * 3) =                                            &
     769             :                                                                  & vExt2MT(imesh, lm, ii + (iatom - 1) * 3, jj + (iDatom - 1) * 3) &
     770           0 :                                     & + (atoms%rmsh(imesh, itype) / atoms%rmt(itype))**oqn_l * surfIntMat(lm, ii, jj, iDatom, iatom)
     771             :                     end do ! imesh
     772             :                   end do ! mqn_m
     773             :                 end do ! oqn_l
     774             :               end do ! ii
     775             : 
     776             :             end do ! ieqat
     777             :           end do ! itype
     778             :         end do ! ii
     779             :       end do ! iDeqat
     780             :     end do ! iDtype
     781             : 
     782           0 :   end subroutine GenVext2MT
     783             : 
     784             :   !--------------------------------------------------------------------------------------------------------------------------------------
     785             :   !> @author
     786             :   !> Christian-Roman Gerhorst, Forschungszentrum Jülich: IAS1 / PGI1
     787             :   !>
     788             :   !> @brief
     789             :   !> Auxiliary method which is similiar to FLEUR's phasy routine but does not implement symmetry.
     790             :   !>
     791             :   !>
     792             :   !> @details
     793             :   !> This method calculates for a given G-vector and q-vector: 4 π i^l exp((Gvec + qpoint) * taual) Y*_lm(Gvec + qpoint)
     794             :   !> Opposite to the original phasy1 routine, here, stars and any type of symmetry is not considered here.
     795             :   !>
     796             :   !> @param[in]  atomsT     : Contains atoms-related quantities; definition of its members in types.F90 file.
     797             :   !> @param[in]  cellT      : Contains unit-cell related quantities; definition of its members in types.F90 file.
     798             :   !> @param[in]  Gvec       : Current G-vector
     799             :   !> @param[in]  qpoint     : Current q-point
     800             :   !> @param[out] pylm       : Result of the routine, is atom resolved due to lack of symmetry in first variation of the potentials.
     801             :   !--------------------------------------------------------------------------------------------------------------------------------------
     802             :   ! Deprecated
     803           0 :   subroutine phasy1lp2nSym(atomsT, cellT, Gvec, qptn, pylm)
     804             : 
     805             :     use m_ylm
     806             :     use m_types
     807             : 
     808             :     implicit none
     809             : 
     810             :     ! Scalar Type Arguments
     811             :     type(t_atoms),  intent(in)  ::  atomsT
     812             :     type(t_cell),   intent(in)  ::  cellT
     813             : 
     814             :     ! Array Arguments
     815             :     integer,        intent(in)  ::  Gvec(:)
     816             :     real,           intent(in)  ::  qptn(:)
     817             :     complex,        intent(out) ::  pylm((atomsT%lmaxd + 3)**2, atomsT%nat)
     818             : 
     819             :     !---------------------------------------------------------------------------------------------------------------------------------
     820             :     ! Local Scalar Variables
     821             :     ! iatom : runs over all atoms
     822             :     ! itype : runs over all types
     823             :     ! ineq  : runs over all equivalent atoms of one atom type
     824             :     ! lm    : encodes oqn_l and mqn_m
     825             :     ! sf    : stores exponential function
     826             :     ! csf   : stores exponential function times 4 π i^l
     827             :     ! x     : stores argument of exponential function
     828             :     ! mqn_m : magnetic quantum number m
     829             :     ! oqn_l : orbital quantum number l
     830             :     ! ll1   : auxiliary variable to calculate lm
     831             :     !---------------------------------------------------------------------------------------------------------------------------------
     832             :     integer                     ::  iatom
     833             :     integer                     ::  itype
     834             :     integer                     ::  ineq
     835             :     integer                     ::  lm
     836             :     complex                     ::  sf
     837             :     complex                     ::  csf
     838             :     real                        ::  x
     839             :     integer                     ::  mqn_m
     840             :     integer                     ::  oqn_l
     841             :     integer                     ::  ll1
     842             : 
     843             :     !---------------------------------------------------------------------------------------------------------------------------------
     844             :     ! Local Array Variables
     845             :     ! fpiul: stores 4 π i^l
     846             :     ! Gqext: stores G + q in external coordinates
     847             :     ! ylm  : stores Y_lm
     848             :     !---------------------------------------------------------------------------------------------------------------------------------
     849           0 :     complex                     ::  fpiul(0:atomsT%lmaxd + 2)
     850             :     real                        ::  Gqext(3)
     851           0 :     complex                     ::  ylm((atomsT%lmaxd + 3)**2)
     852             : 
     853             :     ! calculates 4 π i^l resolved for every l, not divided by nop because no loop over symmetry operations
     854           0 :     do oqn_l = 0, atomsT%lmaxd + 2
     855           0 :        fpiul(oqn_l) = fpi_const * ImagUnit**oqn_l
     856             :     enddo
     857             : 
     858             : 
     859             :     ! calculates Y*_lm(\vec{G} + \vec{q}) for every l and m. The argument Gqext must be in external coordinates.
     860           0 :     Gqext = matmul(Gvec + qptn, cellT%bmat)
     861             :     !call Ylmnorm_init( atomsT%lmaxd + 2 )
     862           0 :     call ylm4(atomsT%lmaxd + 2, Gqext, ylm)
     863             :     !call Ylmnorm_init( atomsT%lmaxd)
     864           0 :     ylm = conjg(ylm)
     865             : 
     866             : 
     867             :     ! calculates first exp(i (G + q) tau)  and multiplies recent factors before storing the final result to pylm
     868           0 :     iatom = 1
     869           0 :     pylm = cmplx(0.,0.)
     870           0 :     do itype = 1, atomsT%ntype
     871           0 :        do ineq = 1, atomsT%neq(itype)
     872           0 :           x = tpi_const * dot_product(Gvec + qptn, atomsT%taual(:, iatom))
     873           0 :           sf = exp(ImagUnit *  x)
     874           0 :           do oqn_l = 0, atomsT%lmax(itype) + 2
     875           0 :              ll1 = oqn_l * (oqn_l + 1) + 1
     876           0 :              csf = fpiul(oqn_l) * sf
     877           0 :              do mqn_m = -oqn_l, oqn_l
     878           0 :                 lm = ll1 + mqn_m
     879           0 :                 pylm(lm, iatom) = csf * ylm(lm)
     880             :              enddo ! mqn_m
     881             :           enddo ! oqn_l
     882           0 :           iatom = iatom + 1
     883             :        enddo ! ineq
     884             :     enddo ! itype
     885             : 
     886           0 :   end subroutine phasy1lp2nSym
     887             : 
     888           0 :   function outerProduct(a, b)
     889             : 
     890             :     implicit none
     891             : 
     892             :     real, intent(in) :: a(:)
     893             :     real, intent(in) :: b(:)
     894             : 
     895             :     real             :: outerProduct(size(a), size(b))
     896             : 
     897           0 :     outerProduct(:, :) = spread(a, dim=2, ncopies=size(b)) * spread(b, dim=1, ncopies=size(a))
     898             : 
     899             :   end function outerProduct
     900             : 
     901           0 :   function outerProductME(a, b, i, j)
     902             : 
     903             :     use m_juDFT_stop, only : juDFT_error
     904             : 
     905             :     implicit none
     906             : 
     907             :     complex,    intent(in)  :: a(:)
     908             :     complex,    intent(in)  :: b(:)
     909             :     integer,    intent(in)  :: i
     910             :     integer,    intent(in)  :: j
     911             : 
     912             :     complex                 :: outerProductME
     913             : 
     914           0 :     if (i > size(a) .or. j > size(b)) then
     915             :       call juDFT_error( 'Wished matrix element is out of scope of outer product matrix.', calledby='outerProductME', &
     916           0 :         & hint='Choose smaller indices.')
     917             :     end if
     918             : 
     919           0 :     outerProductME = a(i) * b(j)
     920             : 
     921           0 :   end function outerProductME
     922             : 
     923           0 :   subroutine genPertPotDensGvecs( stars, cell, input, ngpqdp, ngpqdp2km, qpoint, gpqdp )
     924             : 
     925             :     use m_types
     926             : 
     927             :     implicit none
     928             : 
     929             :     ! Type parameters
     930             :     type(t_stars),          intent(in)   :: stars
     931             :     type(t_cell),           intent(in)   :: cell
     932             :     type(t_input),          intent(in)   :: input
     933             : 
     934             :     ! Scalar parameters
     935             :     integer,                intent(out)  :: ngpqdp
     936             :     integer,                intent(out)  :: ngpqdp2km
     937             : 
     938             :     ! Array parameters
     939             :     real,                   intent(in)   :: qpoint(:)
     940             :     integer,  allocatable,  intent(out)  :: gpqdp(:, :)
     941             : 
     942             :     ! Scalar variables
     943             :     integer                              :: ngrest
     944             :     integer                              :: iGx
     945             :     integer                              :: iGy
     946             :     integer                              :: iGz
     947             :     integer                              :: iG
     948             : 
     949             :     ! Array variables
     950           0 :     integer,  allocatable                :: gpqdptemp2kmax(:, :)
     951           0 :     integer,  allocatable                :: gpqdptemprest(:, :)
     952             :     integer                              :: Gint(3)
     953             :     real                                 :: Gpqext(3)
     954             : 
     955             :     allocate( gpqdptemp2kmax(3, (2 * stars%mx1 + 1) * (2 * stars%mx2 + 1) * (2 * stars%mx3 +  1)), &
     956           0 :             & gpqdptemprest(3, (2 * stars%mx1 + 1) * (2 * stars%mx2 + 1) * (2 * stars%mx3 +  1)) )
     957             : 
     958           0 :     ngpqdp = 0
     959           0 :     ngpqdp2km = 0
     960           0 :     ngrest = 0
     961           0 :     gpqdptemp2kmax(:, :) = 0
     962           0 :     gpqdptemprest(:, :) = 0
     963             :     ! From all possible G-vectors in a box, only these are accepted which are element of a sphere with radius gmax which is shifted.
     964             :     ! We need a little bit more than k*d because they are thought for a Gmax ball that is not shifted by a q, i.e. |G+q|<Gmax
     965           0 :     do iGx = -(stars%mx1 + 3), (stars%mx1 + 3)
     966           0 :       do iGy = -(stars%mx2 + 3), (stars%mx2 + 3)
     967           0 :         do iGz = -(stars%mx3 + 3), (stars%mx3 + 3)
     968           0 :           Gint = [iGx, iGy, iGz]
     969           0 :           Gpqext =  matmul(real(Gint(1:3) + qpoint(1:3)),cell%bmat) !transform from internal to external coordinates
     970           0 :           if (norm2(Gpqext) <= input%gmax) then
     971           0 :             ngpqdp = ngpqdp + 1
     972             :             ! Sort G-vectors
     973           0 :             if ( norm2(Gpqext) <= 2 * input%rkmax ) then
     974           0 :               ngpqdp2km = ngpqdp2km + 1
     975           0 :               gpqdptemp2kmax(1:3, ngpqdp2km) = Gint(1:3)
     976             :             else
     977           0 :               ngrest = ngrest + 1
     978           0 :               gpqdptemprest(1:3, ngrest) = Gint(1:3)
     979             :             end if
     980             :           end if
     981             :         end do !iGz
     982             :       end do !iGy
     983             :     end do !iGx
     984           0 :     allocate(gpqdp(3, ngpqdp))
     985             :     ! Mapping array from G-vector to G-vector index
     986           0 :     gpqdp(:, :) = 0
     987           0 :     gpqdp(1:3, 1:ngpqdp2km) = gpqdptemp2kmax(1:3, 1:ngpqdp2km)
     988           0 :     gpqdp(1:3, ngpqdp2km + 1 : ngpqdp) = gpqdptemprest(1:3, 1:ngrest)
     989             : 
     990           0 :   end subroutine genPertPotDensGvecs
     991             : 
     992           0 :   SUBROUTINE dfpt_e2_madelung(atoms,jspins,grgrRho,grgrVC,e2_vm)
     993             :       USE m_intgr
     994             :       TYPE(t_atoms), INTENT(IN)     :: atoms
     995             :       INTEGER,       INTENT(IN)     :: jspins
     996             :       REAL,          INTENT(IN)     :: grgrRho(:,:,:), grgrVC(:,:)
     997             :       REAL,          INTENT(OUT)    :: e2_vm(:)
     998             : 
     999           0 :       REAL    :: mt(atoms%jmtd,atoms%nat), dpj(atoms%jmtd), rhs_arr(atoms%jmtd), totz_arr(atoms%jmtd)
    1000           0 :       REAL    :: vmd(atoms%nat), zintn_r(atoms%nat)
    1001             :       INTEGER :: n, j
    1002             : 
    1003           0 :       e2_vm = 0.0
    1004           0 :       mt=0.0
    1005           0 :       DO n = 1,atoms%nat
    1006           0 :          DO j = 1,atoms%jri(n)
    1007           0 :             mt(j,n) = grgrRho(j,n,1) + grgrRho(j,n,jspins)
    1008             :          ENDDO
    1009             :       ENDDO
    1010           0 :       IF (jspins.EQ.1) mt=mt/2
    1011             : 
    1012           0 :       rhs_arr = 0.0
    1013           0 :       DO n = 1,atoms%nat
    1014           0 :          DO j = 1,atoms%jri(n)
    1015           0 :             dpj(j) = mt(j,n)/atoms%rmsh(j,n)
    1016             :          END DO
    1017             :          !CALL intgr3(dpj,atoms%rmsh(1,n),atoms%dx(n),atoms%jri(n),rhs)
    1018           0 :          CALL sfint(dpj,atoms%rmsh(1,n),atoms%dx(n),atoms%jri(n),rhs_arr)
    1019             : 
    1020           0 :          zintn_r(n) = atoms%zatom(n)*sfp_const*rhs_arr(atoms%jri(n))
    1021           0 :          e2_vm(n) = e2_vm(n) - zintn_r(n)
    1022             : 
    1023             :          !CALL intgr3(mt(1,n),atoms%rmsh(1,n),atoms%dx(n),atoms%jri(n),totz)
    1024           0 :          CALL sfint(mt(:,n),atoms%rmsh(1,n),atoms%dx(n),atoms%jri(n),totz_arr)
    1025           0 :          vmd(n) = atoms%rmt(n)*grgrVC(atoms%jri(n),n)/sfp_const - totz_arr(atoms%jri(n))*sfp_const
    1026           0 :          vmd(n) = -atoms%zatom(n)*vmd(n)/ atoms%rmt(n)
    1027           0 :          e2_vm(n) = e2_vm(n) + vmd(n)
    1028             :       END DO
    1029             : 
    1030           0 :   END SUBROUTINE dfpt_e2_madelung
    1031             : 
    1032             : end module m_dfpt_eii2

Generated by: LCOV version 1.14