LCOV - code coverage report
Current view: top level - vgen - vmts.F90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 62 88 70.5 %
Date: 2024-04-26 04:44:34 Functions: 1 1 100.0 %

          Line data    Source code
       1             : module m_vmts
       2             : #ifdef CPP_MPI
       3             :   use mpi
       4             : #endif
       5             : contains
       6             : 
       7         696 :   subroutine vmts( input, fmpi, stars, sphhar, atoms, sym, cell,   dosf, vpw, rho, potdenType, vr, rhoIm, vrIm, iDtype, iDir, iDir2, mat2ord )
       8             : 
       9             :   !-------------------------------------------------------------------------
      10             :   ! This subroutine calculates the lattice harmonics expansion coefficients
      11             :   ! of the Coulomb / Yukawa potential for all atom types.
      12             :   !
      13             :   ! In more detail:
      14             :   ! the radius-dependent coefficient of the potential is
      15             :   ! V_{lm}(r) = \int_0^R G_l(r,r') \rho_{lm}(r') r'^2 dr' + V_{lm}(R) P_l(r)
      16             :   ! where
      17             :   ! [sphere boundary contribution - first part of code:]
      18             :   ! V_{lm}(R) is the spherical harmonics expansion of the interstitial
      19             :   ! potential,
      20             :   ! P_l(r) is the derivative of the spherical Green's function on the sphere
      21             :   ! boundary (times a constant),
      22             :   ! [sphere interior contribution - second part of code:]
      23             :   ! G_l(r,r') ) = green_factor u_1(r_<) u_2(r_>) is the spherical Green's
      24             :   ! function with homogeneous solutions u_1 and u_2 and
      25             :   ! r_< = min(r,r') and r_> = max(r,r')
      26             :   ! The integral is split in a part where r'=r_< and a part where r'=r_> and
      27             :   ! the integral from r to R is split in \int_0^R - \int_0^r. Resulting
      28             :   ! terms depending solely on R (not on r) are summarised in the variable
      29             :   ! termsR.
      30             :   !
      31             :   ! More information and equations can be found in
      32             :   ! F. Tran, P. Blaha: Phys. Rev. B 83, 235118(2011)
      33             :   !-------------------------------------------------------------------------
      34             : 
      35             :     use m_constants
      36             :     use m_types
      37             :     use m_mpi_reduce_tool
      38             :     use m_intgr, only : intgr2, sfint
      39             :     use m_phasy1
      40             :     use m_sphbes
      41             :      
      42             :     use m_SphBessel
      43             :     !$ use omp_lib
      44             :     implicit none
      45             : 
      46             :     type(t_input),  intent(in)        :: input
      47             :     type(t_mpi),    intent(in)        :: fmpi
      48             :     type(t_stars),  intent(in)        :: stars
      49             :     type(t_sphhar), intent(in)        :: sphhar
      50             :     type(t_atoms),  intent(in)        :: atoms
      51             :     type(t_sym),    intent(in)        :: sym
      52             :     type(t_cell),   intent(in)        :: cell
      53             :      
      54             :     LOGICAL,        INTENT(IN)        :: dosf
      55             :     complex,        intent(in)        :: vpw(:)!(stars%ng3,input%jspins)
      56             :     real,           intent(in)        :: rho(:,0:,:)!(atoms%jmtd,0:sphhar%nlhd,atoms%ntype)
      57             :     integer,        intent(in)        :: potdenType
      58             :     real,           intent(out)       :: vr(:,0:,:)!(atoms%jmtd,0:sphhar%nlhd,atoms%ntype)
      59             :     REAL,    OPTIONAL, INTENT(IN)     :: rhoIm(:,0:,:)
      60             :     REAL,    OPTIONAL, INTENT(OUT)    :: vrIm(:,0:,:)
      61             :     INTEGER, OPTIONAL, INTENT(IN)     :: iDtype, iDir
      62             :     INTEGER, OPTIONAL, INTENT(IN)     :: iDir2
      63             :     COMPLEX, OPTIONAL, INTENT(IN)     :: mat2ord(5,3,3)
      64             : 
      65             :     complex                           :: cp, sm
      66             :     integer                           :: i, jm, k, l, lh, n, nd, lm, m, imax, lmax, iMem, ptsym
      67             :     integer                           :: maxBunchSize, numBunches, iBunch, firstStar, iTempArray
      68             :     complex                           :: temp
      69         696 :     complex                           :: vtl(0:sphhar%nlhd, atoms%ntype)
      70         696 :     complex                           :: pylm(( atoms%lmaxd + 1 ) ** 2, atoms%ntype)
      71             :     real                              :: green_factor, termsR, pref
      72         696 :     real                              :: green_1    (1:atoms%jmtd), green_2    (1:atoms%jmtd)
      73         696 :     real                              :: integrand_1(1:atoms%jmtd), integrand_2(1:atoms%jmtd)
      74         696 :     real                              :: integral_1 (1:atoms%jmtd), integral_2 (1:atoms%jmtd)!, integral_3 (1:atoms%jmtd)
      75         696 :     real                              :: sbf(0:atoms%lmaxd)
      76         696 :     real, allocatable, dimension(:,:) :: il, kl
      77             :     LOGICAL                           :: l_dfptvgen
      78         696 :     COMPLEX, ALLOCATABLE              :: vtlStars(:,:,:), vtlLocal(:,:)
      79             :     TYPE(t_parallelLoop)              :: mpiLoop, ompLoop
      80             : 
      81         696 :     l_dfptvgen = PRESENT(rhoIm)
      82             : 
      83             :     ! SPHERE BOUNDARY CONTRIBUTION to the coefficients calculated from the values
      84             :     ! of the interstitial Coulomb / Yukawa potential on the sphere boundary
      85             : 
      86        2784 :     ALLOCATE (vtlLocal(0:sphhar%nlhd,atoms%ntype))
      87       35144 :     vtlLocal(:,:) = cmplx(0.0,0.0)
      88             : 
      89        2784 :     firstStar = MERGE(2,1,norm2(stars%center)<=1e-8)
      90         696 :     maxBunchSize = 2*getNumberOfThreads() ! This bunch size is kind of a magic number determined from some
      91             :                                           ! naive performance tests for a 64 atom unit cell
      92         696 :     CALL calcNumberComputationBunches(firstStar, stars%ng3, maxBunchSize, numBunches)
      93             : 
      94         696 :     CALL mpiLoop%init(fmpi%irank,fmpi%isize,0,numBunches-1)
      95             : 
      96        3480 :     ALLOCATE(vtlStars(0:sphhar%nlhd,atoms%ntype,maxBunchSize))
      97      141272 :     vtlStars = CMPLX(0.0,0.0)
      98             : 
      99             :     ! q/=0 components
     100      195887 :     DO iBunch = mpiLoop%bunchMinIndex, mpiLoop%bunchMaxIndex
     101      195191 :        CALL ompLoop%init(iBunch,numBunches,firstStar,stars%ng3)
     102             :        !$OMP parallel do default( NONE ) &
     103             :        !$OMP SHARED(ompLoop,atoms,stars,sym,cell,sphhar,vpw,vtlStars,potdenType) &
     104      195887 :        !$OMP private(iTempArray,cp,pylm,n,sbf,nd,lh,l,sm,jm,m,lm)
     105             :        do k = ompLoop%bunchMinIndex, ompLoop%bunchMaxIndex
     106             :           iTempArray = k - ompLoop%bunchMinIndex + 1
     107             :           cp = vpw(k) * stars%nstr(k)
     108             :           call phasy1( atoms, stars, sym, cell, k, pylm )
     109             :           do n = 1, atoms%ntype
     110             :              call sphbes( atoms%lmax(n), stars%sk3(k) * atoms%rmt(n), sbf )
     111             :              nd = sym%ntypsy(atoms%firstAtom(n))
     112             :              do lh = 0, sphhar%nlh(nd)
     113             :                 l = sphhar%llh(lh,nd)
     114             :                 sm = (0.0,0.0)
     115             :                 do jm = 1, sphhar%nmem(lh,nd)
     116             :                    m = sphhar%mlh(jm,lh,nd)
     117             :                    lm = l * ( l + 1 ) + m + 1
     118             :                    sm = sm + conjg( sphhar%clnu(jm,lh,nd) ) * pylm(lm,n)
     119             :                 end do
     120             :                 vtlStars(lh,n,iTempArray) = vtlStars(lh,n,iTempArray) + cp * sbf(l) * sm
     121             :              end do
     122             :           end do
     123             :        end do
     124             :        !$OMP END PARALLEL DO
     125             :     END DO
     126             :     
     127             :     !$OMP parallel do default( NONE ) &
     128             :     !$OMP SHARED(atoms,sym,sphhar,maxBunchSize,vtlStars,vtlLocal) &
     129         696 :     !$OMP private(nd,lh,temp,iTempArray)
     130             :     DO n = 1, atoms%ntype
     131             :        nd = sym%ntypsy(atoms%firstAtom(n))
     132             :        do lh = 0, sphhar%nlh(nd)
     133             :           temp = CMPLX(0.0,0.0)
     134             :           DO iTempArray = 1, maxBunchSize
     135             :              temp = temp + vtlStars(lh,n,iTempArray)
     136             :           END DO
     137             :           vtlLocal(lh,n) = temp
     138             :        END DO
     139             :     END DO
     140             :     !$OMP END PARALLEL DO
     141             :     
     142             :     ! q=0 component
     143        2784 :     if ( fmpi%irank == 0 .AND. norm2(stars%center)<=1e-8 ) then
     144         975 :        DO n = 1, atoms%ntype
     145         975 :           vtlLocal(0,n) = vtlLocal(0,n) + sfp_const * vpw(1)
     146             :        END DO
     147             :     end if
     148             : 
     149         696 :     CALL mpi_sum_reduce(vtlLocal, vtl,fmpi%mpi_comm)
     150             : 
     151             :     ! SPHERE INTERIOR CONTRIBUTION to the coefficients calculated from the
     152             :     ! values of the sphere Coulomb/Yukawa potential on the sphere boundary
     153             : 
     154         696 :     if( fmpi%irank == 0 ) then
     155         348 :     if ( potdenType == POTDEN_TYPE_POTYUK ) then
     156          18 :       allocate( il(0:atoms%lmaxd, 1:atoms%jmtd), kl(0:atoms%lmaxd, 1:atoms%jmtd) )
     157             :     end if
     158             : 
     159         975 :     do n = 1, atoms%ntype
     160         627 :       nd = sym%ntypsy(atoms%firstAtom(n))
     161         627 :       imax = atoms%jri(n)
     162         627 :       lmax = sphhar%llh(sphhar%nlh(nd), nd)
     163         627 :       if ( potdenType == POTDEN_TYPE_POTYUK ) then
     164             :         !do concurrent (i = 1:imax)
     165       11370 :         do i = 1,imax
     166       11370 :           call ModSphBessel( il(0:,i), kl(0:,i), input%preconditioning_param * atoms%rmsh(i,n), lmax )
     167             :         end do
     168             :       end if
     169       16806 :       do lh = 0, sphhar%nlh(nd)
     170       15831 :         l = sphhar%llh(lh,nd)
     171       15831 :         if ( potdenType == POTDEN_TYPE_POTYUK ) then
     172      156906 :           green_1(1:imax) = il(l,1:imax)
     173      156906 :           green_2(1:imax) = kl(l,1:imax)
     174         207 :           green_factor    = fpi_const * input%preconditioning_param
     175             :         else
     176    11166770 :           green_1(1:imax) = atoms%rmsh(1:imax,n) ** l
     177    11166770 :           green_2(1:imax) = 1.0 / ( green_1(1:imax) * atoms%rmsh(1:imax,n) )
     178       15624 :           green_factor    = fpi_const / ( 2 * l + 1 )
     179             :         end if
     180             : 
     181    11323676 :         integrand_1(1:imax) = green_1(1:imax) * rho(1:imax,lh,n)
     182    11323676 :         integrand_2(1:imax) = green_2(1:imax) * rho(1:imax,lh,n)
     183       15831 :         if (.not.dosf) THEN
     184       15669 :          call intgr2( integrand_1(1:imax), atoms%rmsh(1,n), atoms%dx(n), imax, integral_1(1:imax) )
     185       15669 :          call intgr2( integrand_2(1:imax), atoms%rmsh(1,n), atoms%dx(n), imax, integral_2(1:imax) )
     186             :         else
     187         162 :            call sfint(integrand_1(1:imax),atoms%rmsh(:,n),atoms%dx(n),imax,integral_1(1:imax))
     188         162 :            call sfint(integrand_2(1:imax),atoms%rmsh(:,n),atoms%dx(n),imax,integral_2(1:imax))
     189             :         end if
     190       15831 :         termsR = integral_2(imax) + ( vtl(lh,n) / green_factor - integral_1(imax) * green_2(imax) ) / green_1(imax)
     191             :         vr(1:imax,lh,n) = green_factor * (   green_1(1:imax) * ( termsR - integral_2(1:imax) ) &
     192    11323676 :                                            + green_2(1:imax) *            integral_1(1:imax)   )
     193       16458 :         IF (l_dfptvgen) THEN
     194             :            ! Integrate the imaginary part of the density perturbation as well.
     195           0 :            integrand_1(1:imax) = green_1(1:imax) * rhoIm(1:imax,lh,n)
     196           0 :            integrand_2(1:imax) = green_2(1:imax) * rhoIm(1:imax,lh,n)
     197           0 :            call intgr2( integrand_1(1:imax), atoms%rmsh(1,n), atoms%dx(n), imax, integral_1(1:imax) )
     198           0 :            call intgr2( integrand_2(1:imax), atoms%rmsh(1,n), atoms%dx(n), imax, integral_2(1:imax) )
     199           0 :            termsR = integral_2(imax) + ( AIMAG(vtl(lh,n)) / green_factor - integral_1(imax) * green_2(imax) ) / green_1(imax)
     200             :            vrIm(1:imax,lh,n) = green_factor * (   green_1(1:imax) * ( termsR - integral_2(1:imax) ) &
     201           0 :                                                 + green_2(1:imax) *            integral_1(1:imax)   )
     202             :         END IF
     203             :       end do
     204             :     end do
     205         348 :     if ( potdenType == POTDEN_TYPE_POTYUK ) then
     206           3 :       deallocate( il, kl )
     207             :     end if
     208             : 
     209         348 :     if ( potdenType /= POTDEN_TYPE_POTYUK .AND. potdenType /= POTDEN_TYPE_CRYSTALFIELD) then
     210         344 :       IF (.NOT.l_dfptvgen) THEN
     211         951 :          do n = 1, atoms%ntype
     212      417810 :          vr(1:atoms%jri(n),0,n) = vr(1:atoms%jri(n),0,n) - sfp_const * ( 1.0 / atoms%rmsh(1:atoms%jri(n),n) - 1.0 / atoms%rmt(n) ) * atoms%zatom(n)
     213             :          end do
     214           0 :       ELSE IF (.NOT.PRESENT(iDir2)) THEN
     215             :          ! DFPT case:
     216             :          ! l=1 contributions from the Coulomb singularity instead of l=0 (1/r -> 1/r^2)
     217           0 :          DO n = MERGE(1,iDtype,iDtype==0), MERGE(atoms%ntype,iDtype,iDtype==0)
     218           0 :             ptsym = sym%ntypsy(atoms%firstAtom(n))
     219           0 :             pref = MERGE(atoms%zatom(n),-atoms%zatom(n),iDtype==0)
     220           0 :             DO lh = 1, 3
     221           0 :                l = sphhar%llh(lh, ptsym)
     222           0 :                DO iMem = 1, sphhar%nmem(lh, ptsym)
     223           0 :                   m = sphhar%mlh(iMem, lh, ptsym)
     224           0 :                   lm = l*(l+1) + m + 1
     225             :                   vr(1:atoms%jri(n),lh,n) = vr(1:atoms%jri(n),lh,n) + &
     226             :                                              conjg(sphhar%clnu(iMem, lh, ptsym)) * c_im(iDir, lm - 1) * pref * &
     227           0 :                                              ( 1 - (atoms%rmsh(1:atoms%jri(n), n) / atoms%rmt(n))**3) / atoms%rmsh(1:atoms%jri(n),n)**2
     228             :                END DO
     229             :             END DO
     230             :          END DO
     231             :       ELSE
     232             :          ! DFPT 2nd order case:
     233             :          ! l=2 contributions from the Coulomb singularity instead of l=0 (1/r -> 1/r^3)
     234           0 :          DO n = 1, atoms%ntype!MERGE(1,iDtype,iDtype==0), MERGE(atoms%ntype,iDtype,iDtype==0)
     235           0 :             ptsym = sym%ntypsy(atoms%firstAtom(n))
     236           0 :             pref = -atoms%zatom(n)!MERGE(atoms%zatom(n),-atoms%zatom(n),iDtype==0)
     237           0 :             DO lh = 4, 8
     238           0 :                l = sphhar%llh(lh, ptsym)
     239           0 :                DO iMem = 1, sphhar%nmem(lh, ptsym)
     240           0 :                   m = sphhar%mlh(iMem, lh, ptsym)
     241           0 :                   lm = l*(l+1) + m + 1
     242           0 :                   IF ((n.EQ.iDtype).OR.(0.EQ.iDtype)) vr(1:atoms%jri(n),lh,n) = vr(1:atoms%jri(n),lh,n) + &
     243             :                                                       conjg(sphhar%clnu(iMem, lh, ptsym)) * mat2ord(lm-4,iDir2,iDir) * pref * &
     244           0 :                                                       ( 1 - (atoms%rmsh(1:atoms%jri(n), n) / atoms%rmt(n))**5) / atoms%rmsh(1:atoms%jri(n),n)**3
     245             :                END DO
     246             :             END DO
     247             :          END DO
     248             :       END IF
     249             :     end if
     250             :     end if
     251             : 
     252        1392 :   end subroutine vmts
     253             : 
     254             : end module m_vmts

Generated by: LCOV version 1.14