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

          Line data    Source code
       1             : MODULE m_dfpt_gradient
       2             :    USE m_juDFT
       3             :    USE m_constants
       4             :    USE m_types
       5             : 
       6             :    IMPLICIT NONE
       7             : CONTAINS
       8           0 :     subroutine mt_gradient_new(atoms, sphhar, sym, r2FlhMt, GrFshMt)
       9             : 
      10             :       use m_gaunt, only : gaunt1
      11             : 
      12             :       type(t_atoms),               intent(in)  :: atoms
      13             :       type(t_sphhar),              intent(in)  :: sphhar
      14             :       type(t_sym),                 intent(in)  :: sym
      15             : 
      16             :       real,                        intent(in)  :: r2FlhMt(:, 0:, :)
      17             :       complex,                     intent(out) :: GrFshMt(:, :, :, :)
      18             : 
      19             :       real                                     :: pfac
      20             :       real                                     :: tGaunt
      21             :       integer                                  :: itype
      22             :       integer                                  :: imesh
      23             :       integer                                  :: mqn_m
      24             :       integer                                  :: oqn_l
      25             :       integer                                  :: mqn_mpp
      26             :       integer                                  :: lm
      27             :       integer                                  :: symType
      28             :       integer                                  :: ilh
      29             :       integer                                  :: imem
      30             : 
      31           0 :       real,           allocatable              :: rDerFlhMt(:)
      32           0 :       complex,        allocatable              :: r2GrFshMtNat(:, :, :, :)
      33             : 
      34           0 :       allocate( r2GrFshMtNat(atoms%jmtd, ( atoms%lmaxd + 1)**2, atoms%nat, 3) )
      35           0 :       allocate( rDerFlhMt(atoms%jmtd) )
      36           0 :       GrFshMt = cmplx(0., 0.)
      37           0 :       r2GrFshMtNat = cmplx(0., 0.)
      38           0 :       rDerFlhMt = 0.
      39             : 
      40             :       pfac = sqrt( fpi_const / 3. )
      41           0 :       do mqn_mpp = -1, 1
      42           0 :         do itype = 1, atoms%ntype
      43           0 :             symType = sym%ntypsy(itype)
      44           0 :             do ilh = 0, sphhar%nlh(symType)
      45           0 :               oqn_l = sphhar%llh(ilh, symType)
      46           0 :               do imem = 1, sphhar%nmem(ilh,symType)
      47           0 :                 mqn_m = sphhar%mlh(imem,ilh,symType)
      48             : 
      49             :                 ! l + 1 block
      50             :                 ! oqn_l - 1 to l, so oqn_l should be < lmax not <= lmax
      51           0 :                 if ( ( abs(mqn_m - mqn_mpp) <= oqn_l + 1 ) .and. ( abs(mqn_m) <= oqn_l ) .and. (oqn_l < atoms%lmax(itype)) ) then
      52           0 :                   lm = ( oqn_l + 1 ) * ( oqn_l + 2 ) + 1 + mqn_m - mqn_mpp
      53           0 :                   call derivative_loc( r2FlhMt(:, ilh, itype), itype, atoms, rDerFlhMt )
      54           0 :                   tGaunt = Gaunt1( oqn_l + 1, oqn_l, 1, mqn_m - mqn_mpp, mqn_m, -mqn_mpp, atoms%lmaxd )
      55           0 :                   do imesh = 1, atoms%jri(itype)
      56             :                     r2GrFshMtNat(imesh, lm, itype, mqn_mpp + 2) = r2GrFshMtNat(imesh, lm, itype, mqn_mpp + 2) + pfac * (-1)**mqn_mpp &
      57             :                       &* tGaunt * (rDerFlhMt(imesh) * sphhar%clnu(imem,ilh,symType) &
      58           0 :                       &- ((oqn_l + 2) * r2FlhMt(imesh, ilh, itype) * sphhar%clnu(imem,ilh,symType) / atoms%rmsh(imesh, itype)))
      59             :                   end do ! imesh
      60             :                 end if ! ( abs(mqn_m - mqn_mpp) <= oqn_l + 1 ) .and. ( abs(mqn_m) <= oqn_l )
      61             : 
      62             :                 ! l - 1 block
      63           0 :                 if ( ( abs(mqn_m - mqn_mpp) <= oqn_l - 1 ) .and. ( abs(mqn_m) <= oqn_l ) ) then
      64             :                   if ( oqn_l - 1 == -1 ) then
      65             :                     write (*, *) 'oqn_l too low'
      66             :                   end if
      67           0 :                   lm = (oqn_l - 1) * oqn_l + 1 + mqn_m - mqn_mpp
      68             :                   ! This is also a trade of between storage and performance, because derivative is called redundantly, maybe store it?
      69           0 :                   call derivative_loc( r2FlhMt(:, ilh, itype), itype, atoms, rDerFlhMt )
      70           0 :                   tGaunt = Gaunt1( oqn_l - 1, oqn_l, 1, mqn_m - mqn_mpp, mqn_m, -mqn_mpp, atoms%lmaxd )
      71           0 :                   do imesh = 1, atoms%jri(itype)
      72             :                     r2GrFshMtNat(imesh, lm, itype, mqn_mpp + 2) = r2GrFshMtNat(imesh, lm, itype, mqn_mpp + 2) + pfac * (-1)**mqn_mpp &
      73             :                       & * tGaunt * (rDerFlhMt(imesh)  * sphhar%clnu(imem,ilh,symType) &
      74           0 :                       & + ((oqn_l - 1) * r2FlhMt(imesh, ilh, itype) * sphhar%clnu(imem,ilh,symType) / atoms%rmsh(imesh, itype)))
      75             :                   end do ! imesh
      76             :                 end if ! ( abs(mqn_m - mqn_mpp) <= oqn_l - 1 ) .and. ( abs(mqn_m) <= oqn_l )
      77             :               end do ! imem
      78             :             end do ! ilh
      79             :         end do ! itype
      80             :       end do ! mqn_mpp
      81             : 
      82             :       ! Conversion from natural to cartesian coordinates
      83           0 :       do itype = 1, atoms%ntype
      84           0 :           do oqn_l = 0, atoms%lmax(itype)
      85           0 :             do mqn_m = -oqn_l, oqn_l
      86           0 :               lm = oqn_l * (oqn_l + 1) + 1 + mqn_m
      87           0 :               do imesh = 1, atoms%jri(itype)
      88           0 :                 grFshMt(imesh, lm, itype, 1:3) = matmul( Tmatrix0(1:3, 1:3), r2GrFshMtNat(imesh, lm, itype, 1:3) ) / atoms%rmsh(imesh, itype)**2
      89             :               end do
      90             :             end do ! mqn_m
      91             :           end do ! oqn_l
      92             :       end do ! itype
      93             : 
      94           0 :    end subroutine mt_gradient_new
      95             : 
      96           0 :    subroutine derivative_loc(f, itype, atoms, df)
      97             : 
      98             :       integer,       intent(in)  :: itype
      99             :       type(t_atoms), intent(in)  :: atoms
     100             :       real,          intent(in)  :: f(atoms%jri(itype))
     101             :       real,          intent(out) :: df(atoms%jri(itype))
     102             :       real                       :: h, r, d21, d32, d43, d31, d42, d41, df1, df2, s
     103             :       real                       :: y0, y1, y2
     104             :       integer                    :: i, n
     105             : 
     106           0 :       n = atoms%jri(itype)
     107           0 :       h = atoms%dx(itype)
     108           0 :       r = atoms%rmsh(1, itype)
     109             : 
     110             :       ! use Lagrange interpolation of 3rd order (and averaging) for points 3 to n
     111           0 :       d21 = r * (exp(h)-1) ; d32 = d21 * exp(h) ; d43 = d32 * exp(h)
     112           0 :       d31 = d21 + d32      ; d42 = d32 + d43
     113           0 :       d41 = d31 + d43
     114             :       df(1) =   d31*d41 / (d21*d32*d42) * f(2) + ( -1d0/d21 - 1d0/d31 - 1d0/d41) * f(1)&
     115           0 :      &        - d21*d41 / (d31*d32*d43) * f(3) + d21*d31 / (d41*d42*d43) * f(4)
     116             :       df(2) = - d32*d42 / (d21*d31*d41) * f(1) + (  1d0/d21 - 1d0/d32 - 1d0/d42) * f(2)&
     117           0 :      &        + d21*d42 / (d31*d32*d43) * f(3) - d21*d32 / (d41*d42*d43) * f(4)
     118             :       df1   =   d32*d43 / (d21*d31*d41) * f(1) - d31*d43 / (d21*d32*d42) * f(2) +&
     119           0 :      &  ( 1d0/d31 + 1d0/d32 - 1d0/d43 ) * f(3) + d31*d32 / (d41*d42*d43) * f(4)
     120           0 :       do i = 3, n - 2
     121           0 :          d21 = d32 ; d32 = d43 ; d43 = d43 * exp(h)
     122           0 :          d31 = d42 ; d42 = d42 * exp(h)
     123           0 :          d41 = d41 * exp(h)
     124             :          df2   = - d32*d42 / (d21*d31*d41) * f(i-1) + ( 1d0/d21 - 1d0/d32 - 1d0/d42) * f(i) + &
     125           0 :      &             d21*d42 / (d31*d32*d43) * f(i+1) - d21*d32 / (d41*d42*d43) * f(i+2)
     126           0 :          df(i) = ( df1 + df2 ) / 2
     127             :          df1   = d32*d43 / (d21*d31*d41) * f(i-1) - d31*d43 / (d21*d32*d42) * f(i) +&
     128           0 :      &    ( 1d0/d31 + 1d0/d32 - 1d0/d43 ) * f(i+1) + d31*d32 / (d41*d42*d43) * f(i+2)
     129             :       enddo
     130           0 :       df(n-1) = df1
     131             :       df(n)   = - d42*d43 / (d21*d31*d41) * f(n-3) + d41*d43 / (d21*d32*d42) * f(n-2) -&
     132           0 :      &            d41*d42 / (d31*d32*d43) * f(n-1) + ( 1d0/d41 + 1d0/d42 + 1d0/d43 ) * f(n)
     133             :       ! for first two points use Lagrange interpolation of second order for log(f(i))
     134             :       ! or, as a fall-back, Lagrange interpolation with the conditions f(1), f(2), f(3), f'(3).
     135           0 :       s = sign(1d0,f(1))
     136           0 :       if(sign(1d0,f(2)) /= s .or. sign(1d0,f(3))  /= s .or. any(abs(f(:3)) < 1e0)) then
     137           0 :          d21   = r * (exp(h)-1)
     138           0 :          d32   = d21 * exp(h)
     139           0 :          d31   = d21 + d32
     140           0 :          s     = df(3) / (d31*d32) - f(1) / (d21*d31**2) + f(2) / (d21*d32**2) - f(3) / (d31**2*d32) - f(3) / (d31*d32**2)
     141           0 :          df(1) = - (d21+d31) / (d21*d31) * f(1) + d31 / (d21*d32) * f(2) - d21 / (d31*d32) * f(3) + d21*d31 * s
     142             : 
     143           0 :          df(2) = - (d21-d32) / (d21*d32) * f(2) - d32 / (d21*d31) * f(1) + d21 / (d31*d32) * f(3) - d21*d32 * s
     144             :       else
     145           0 :          y0    = log(abs(f(1)))
     146           0 :          y1    = log(abs(f(2)))
     147           0 :          y2    = log(abs(f(3)))
     148           0 :          df(1) = ( - 3*y0/2 + 2*y1 - y2/2 ) * f(1) / (h*r)
     149           0 :          df(2) = (y2-y0)/2                  * f(2) / (h*r*exp(h))
     150             :       endif
     151           0 :    end subroutine derivative_loc
     152             : 
     153           0 :     SUBROUTINE sh_to_lh(sym, atoms, sphhar, jspins, radfact, rhosh, rholhreal, rholhimag)
     154             : 
     155             :         ! WARNING: This routine will not fold back correctly for activated sym-
     156             :         !          metry and gradients (rho in l=0 and lattice harmonics do not
     157             :         !          allow l=1 --> gradient in l=1 is lost)
     158             : 
     159             :         TYPE(t_sym),    INTENT(IN)  :: sym
     160             :         TYPE(t_atoms),  INTENT(IN)  :: atoms
     161             :         TYPE(t_sphhar), INTENT(IN)  :: sphhar
     162             :         INTEGER,        INTENT(IN)  :: jspins, radfact
     163             :         COMPLEX,        INTENT(IN)  :: rhosh(:, :, :, :)
     164             :         REAL,           INTENT(OUT) :: rholhreal(:, 0:, :, :), rholhimag(:, 0:, :, :)
     165             : 
     166             :         INTEGER :: iSpin, iType, iAtom, ilh, iMem, ilm, iR
     167             :         INTEGER :: ptsym, l, m
     168             :         REAL    :: factor
     169             : 
     170           0 :         rholhreal = 0.0
     171           0 :         rholhimag = 0.0
     172             : 
     173           0 :         DO iSpin = 1, jspins
     174           0 :             DO iType = 1, atoms%ntype
     175           0 :                 iAtom = atoms%firstAtom(iType)
     176           0 :                 ptsym = sym%ntypsy(iAtom)
     177           0 :                 DO ilh = 0, sphhar%nlh(ptsym)
     178           0 :                     l = sphhar%llh(iLH, ptsym)
     179           0 :                     DO iMem = 1, sphhar%nmem(ilh, ptsym)
     180           0 :                         m = sphhar%mlh(iMem, ilh, ptsym)
     181           0 :                         ilm = l * (l+1) + m + 1
     182           0 :                         DO iR = 1, atoms%jri(iType)
     183           0 :                            IF ((radfact.EQ.0).AND.(l.EQ.0)) THEN
     184           0 :                                factor = atoms%rmsh(iR, iType) / sfp_const
     185           0 :                            ELSE IF (radfact.EQ.2) THEN
     186           0 :                                factor = atoms%rmsh(iR, iType)**2
     187             :                            ELSE
     188             :                                factor = 1.0
     189             :                            END IF
     190             :                             rholhreal(iR, ilh, iType, iSpin) = &
     191             :                           & rholhreal(iR, ilh, iType, iSpin) + &
     192           0 :                           &  real(rhosh(iR, ilm, iatom, iSpin) * conjg(sphhar%clnu(iMem, ilh, ptsym))) * factor
     193             :                             rholhimag(iR, ilh, iType, iSpin) = &
     194             :                           & rholhimag(iR, ilh, iType, iSpin) + &
     195           0 :                           & aimag(rhosh(iR, ilm, iatom, iSpin) * conjg(sphhar%clnu(iMem, ilh, ptsym))) * factor
     196             :                         END DO
     197             :                     END DO
     198             :                 END DO
     199             :             END DO
     200             :         END DO
     201             : 
     202           0 :     END SUBROUTINE sh_to_lh
     203             : END MODULE m_dfpt_gradient

Generated by: LCOV version 1.14