TABLE OF CONTENTS


ABINIT/m_ppmodel [ Modules ]

[ Top ] [ Modules ]

NAME

 m_ppmodel

FUNCTION

  Module containing the definition of the ppmodel_t used to deal with
  the plasmonpole technique. Methods to operate on the object are also provided.

COPYRIGHT

  Copyright (C) 2008-2024 ABINIT group (MG, GMR, VO, LR, RWG, RS)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

17 #if defined HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "abi_common.h"
22 
23 MODULE m_ppmodel
24 
25  use defs_basis
26  use m_errors
27  use m_abicore
28  use m_array
29  use m_linalg_interfaces
30  use m_distribfft
31 
32  use defs_abitypes,    only : MPI_type
33  use m_fstrings,       only : sjoin, itoa
34  use m_hide_lapack,    only : xhegv
35  use m_gwdefs,         only : GW_Q0_DEFAULT, czero_gw
36  use m_crystal,        only : crystal_t
37  use m_bz_mesh,        only : kmesh_t
38  use m_gsphere,        only : gsphere_t
39  use m_vcoul,          only : vcoul_t
40  use m_qplusg,         only : cmod_qpg
41  use m_fft_mesh,       only : g2ifft
42  use m_fft,            only : fourdp
43  use m_mpinfo,         only : destroy_mpi_enreg, initmpi_seq
44 
45  implicit none
46 
47  private

m_ppmodel/calc_sig_ppm [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 calc_sig_ppm

FUNCTION

  Calculate the contribution to self-energy operator using a plasmon-pole model.

INPUTS

  nomega=Number of frequencies.
  nspinor=Number of spinorial components.
  npwc=Number of G vectors in the plasmon pole.
  npwx=number of G vectors in rhotwgp, i.e. no. of G-vectors for the exchange part.
  theta_mu_minus_e0i= $\theta(\mu-\epsilon_{k-q,b1,s}), defines if the state is occupied or not
  zcut=Small imaginary part to avoid the divergence. (see related input variable)
  omegame0i(nomega)=Frequencies used to evaluate \Sigma_c ($\omega$ - $\epsilon_i)$
  otq(npwc,dm2_otq)=Plasmon pole parameters for this q-point.
  PPm<ppmodel_t>=structure gathering info on the Plasmon-pole technique.
     %model=type plasmon pole model
     %dm2_botsq= 1 if model==3, =npwc if model== 4, 1 for all the other cases
     %dm2_otq= 1 if model==3, =1    if model== 4, 1 for all the other cases
     %dm_eig=npwc if model=3, 0 otherwise
  botsq(npwc,dm2_botsq)=Plasmon pole parameters for this q-point.
  eig(dm_eig,dm_eig)=The eigvectors of the symmetrized inverse dielectric matrix for this q point
   (first index for G, second index for bands)
  rhotwgp(npwx)=oscillator matrix elements divided by |q+G| i.e.
    $\frac{\langle b1 k-q s | e^{-i(q+G)r | b2 k s \rangle}{|q+G|}$

OUTPUT

  sigcme(nomega) (to be described), only relevant if ppm3 or ppm4
  ket(npwc,nomega):
  === model==1,2 ====
    ket(G,omega) = Sum_G2       conjg(rhotw(G)) * Omega(G,G2) * rhotw(G2)
                            ---------------------------------------------------
                             2 omegatw(G,G2) (omega-E_i + omegatw(G,G2)(2f-1))

SOURCE

2106 subroutine calc_sig_ppm(PPm,nspinor,npwc,nomega,rhotwgp,botsq,otq,&
2107 & omegame0i,zcut,theta_mu_minus_e0i,eig,npwx,ket,sigcme)
2108 
2109 !Arguments ------------------------------------
2110 !scalars
2111  integer,intent(in) :: nomega,npwc,npwx,nspinor
2112  real(dp),intent(in) :: theta_mu_minus_e0i,zcut
2113  type(ppmodel_t),intent(in) :: PPm
2114 !arrays
2115  real(dp),intent(in) :: omegame0i(nomega)
2116  complex(gwpc),intent(in) :: botsq(npwc,PPm%dm2_botsq),eig(PPm%dm_eig,PPm%dm_eig),otq(npwc,PPm%dm2_otq)
2117  complex(gwpc),intent(in) :: rhotwgp(npwx*nspinor)
2118  complex(gwpc),intent(inout) :: ket(npwc*nspinor,nomega)
2119  complex(gwpc),intent(out) :: sigcme(nomega)
2120 
2121 !Local variables-------------------------------
2122 !scalars
2123  integer :: ig,igp,ii,ios,ispinor,spadc,spadx
2124  real(dp) :: den,ff,inv_den,omegame0i_io,otw,twofm1,twofm1_zcut
2125  complex(gwpc) :: ct,num,numf,rhotwgdp_igp
2126  logical :: fully_occupied,totally_empty
2127  !character(len=500) :: msg
2128 !arrays
2129  complex(gwpc),allocatable :: rhotwgdpcc(:)
2130 
2131 !*************************************************************************
2132 
2133  SELECT CASE (PPm%model)
2134  CASE (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
2135    fully_occupied =(ABS(theta_mu_minus_e0i-one)<0.001)
2136    totally_empty  =(ABS(theta_mu_minus_e0i    )<0.001)
2137 
2138    do ispinor=1,nspinor
2139      spadx=(ispinor-1)*npwx; spadc=(ispinor-1)*npwc
2140 
2141      if (.not.totally_empty) then
2142        ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(\mu-e_s) / (\omega+\omegat_{G1G2}-e_s-i\delta)
2143        twofm1_zcut=zcut
2144 !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den)
2145        do ios=1,nomega
2146          omegame0i_io=omegame0i(ios)
2147          do igp=1,npwc
2148            rhotwgdp_igp=rhotwgp(spadx+igp)
2149            do ig=1,npwc
2150              otw=DBLE(otq(ig,igp)) !in principle otw -> otw - ieta
2151              num = botsq(ig,igp)*rhotwgdp_igp
2152              den = omegame0i_io+otw
2153              if (den**2>zcut**2) then
2154                ket(spadc+ig,ios)=ket(spadc+ig,ios) + num/(den*otw)*theta_mu_minus_e0i
2155              else
2156                ket(spadc+ig,ios)=ket(spadc+ig,ios) + &
2157 &                num*CMPLX(den,twofm1_zcut)/((den**2+twofm1_zcut**2)*otw)*theta_mu_minus_e0i
2158              end if
2159            end do !ig
2160          end do !igp
2161        end do !ios
2162      end if !not totally empty
2163 
2164      if (.not.(fully_occupied)) then
2165        ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(e_s-\mu) / (\omega-\omegat_{G1G2}-e_s+i\delta)
2166        twofm1_zcut=-zcut
2167 !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den)
2168        do ios=1,nomega
2169          omegame0i_io=omegame0i(ios)
2170          do igp=1,npwc
2171            rhotwgdp_igp=rhotwgp(spadx+igp)
2172            do ig=1,npwc
2173              otw=DBLE(otq(ig,igp)) !in principle otw -> otw - ieta
2174              num = botsq(ig,igp)*rhotwgdp_igp
2175              den=omegame0i_io-otw
2176              if (den**2>zcut**2) then
2177                ket(spadc+ig,ios)=ket(spadc+ig,ios) + num/(den*otw)*(one-theta_mu_minus_e0i)
2178              else
2179                ket(spadc+ig,ios)=ket(spadc+ig,ios) + &
2180 &                num*CMPLX(den,twofm1_zcut)/((den**2+twofm1_zcut**2)*otw)*(one-theta_mu_minus_e0i)
2181              end if
2182            end do !ig
2183          end do !igp
2184          !
2185        end do !ios
2186      end if !not fully occupied
2187 
2188    end do !ispinor
2189 
2190    ket=ket*half
2191 
2192  CASE (PPM_LINDEN_HORSH,PPM_ENGEL_FARID)
2193    ABI_CHECK(nspinor == 1, "nspinor/=1 not allowed")
2194 
2195    ! rho-twiddle(G) is formed, introduce rhotwgdpcc, for speed reason
2196    ABI_MALLOC(rhotwgdpcc,(npwx))
2197 
2198    ff=theta_mu_minus_e0i      ! occupation number f (include poles if ...)
2199    twofm1=two*ff-one          ! 2f-1
2200    twofm1_zcut=twofm1*zcut
2201    rhotwgdpcc(:)=CONJG(rhotwgp(:))
2202 
2203    do ios=1,nomega
2204      omegame0i_io=omegame0i(ios)
2205      ct=czero_gw
2206      do ii=1,npwc ! Loop over the DM bands
2207        num=czero_gw
2208 
2209        SELECT CASE (PPm%model)
2210        CASE (PPM_LINDEN_HORSH)
2211          ! Calculate \beta (eq. 106 pag 47)
2212          do ig=1,npwc
2213            num=num+rhotwgdpcc(ig)*eig(ig,ii)
2214          end do
2215          numf=num*CONJG(num) !MG this means that we cannot do SCGW
2216          numf=numf*botsq(ii,1)
2217 
2218        CASE (PPM_ENGEL_FARID)
2219          do ig=1,npwc
2220            num=num+rhotwgdpcc(ig)*botsq(ig,ii)
2221          end do
2222          numf=num*CONJG(num) !MG this means that we cannot do SCGW
2223 
2224        CASE DEFAULT
2225          ABI_ERROR("Wrong PPm%model")
2226        END SELECT
2227 
2228        !numf=num*CONJG(num) !MG this means that we cannot do SCGW
2229        !if (PPm%model==3) numf=numf*botsq(ii,1)
2230 
2231        otw=DBLE(otq(ii,1)) ! in principle otw -> otw - ieta
2232        den=omegame0i_io+otw*twofm1
2233 
2234        if (den**2>zcut**2) then
2235          inv_den=one/den
2236          ct=ct+numf*inv_den
2237        else
2238          inv_den=one/((den**2+twofm1_zcut**2))
2239          ct=ct+numf*CMPLX(den,twofm1_zcut)*inv_den
2240        end if
2241 
2242      end do !ii DM bands
2243      sigcme(ios)=ct*half
2244    end do !ios
2245    ABI_FREE(rhotwgdpcc)
2246 
2247  CASE DEFAULT
2248    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
2249  END SELECT
2250 
2251 end subroutine calc_sig_ppm

m_ppmodel/cppm1par [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 cppm1par

FUNCTION

 Calculate the plasmon-pole parameters big-omega-twiddle-squared and omega-twiddle from
 epsilon-twiddle^-1 calculated for nomega (usually 2) frequencies omega=0 and omega=iE0.

INPUTS

  epsm1(npwc,npwc,nomega)=dielectric matrix at nomega frequencies.
  npwc=number of plane waves
  nomega=number of frequencies (usually 2)
  omega(nomega)=frequencies
  omegaplasma=input variable or Drude plasma frequency

OUTPUT

  bigomegatwsq(npwc,npwc)=parameter of the plasmon-pole model (see gwa.pdf file)
  omegatw(npwc,npwc)=parameter of the plasmon-pole model (see gwa.pdf file)

TODO

  Calculation can be done in place.

SOURCE

1171 subroutine cppm1par(npwc,nomega,omega,omegaplasma,epsm1,omegatw,bigomegatwsq)
1172 
1173 !Arguments ------------------------------------
1174 !scalars
1175  integer,intent(in) :: nomega,npwc
1176  real(dp),intent(in) :: omegaplasma
1177 !arrays
1178  complex(gwpc),intent(in) :: epsm1(npwc,npwc,nomega)
1179  complex(dpc),intent(in) :: omega(nomega)
1180  complex(gwpc),intent(out) :: bigomegatwsq(npwc,npwc)
1181  complex(gwpc),intent(out) :: omegatw(npwc,npwc)
1182 
1183 !Local variables-------------------------------
1184 !scalars
1185  integer :: ig,igp,io,io0,ioe0
1186  real(dp) :: e0,minomega
1187  character(len=500) :: msg
1188  complex(gwpc) :: AA,omegatwsq,diff,ratio
1189  complex(gwpc) :: epsm1_io0,epsm1_ioe0
1190 
1191 ! *************************************************************************
1192 
1193  DBG_ENTER("COLL")
1194  !
1195  ! === Find omega=0 and omega=imag (closest to omegaplasma) to fit the ppm parameters ===
1196  minomega=1.0d-3; io0=0
1197  do io=1,nomega
1198    if (ABS(omega(io))<minomega) then
1199      io0=io; minomega=ABS(omega(io))
1200    end if
1201  end do
1202  ABI_CHECK(io0/=0,"omega=0 not found")
1203 
1204  minomega=1.0d-3; e0=200.0; ioe0=0
1205  do io=1,nomega
1206    if (REAL(omega(io))<minomega.and.AIMAG(omega(io))>minomega) then
1207      if (ABS(AIMAG(omega(io))-omegaplasma)<ABS(e0-omegaplasma)) then
1208        ioe0=io; e0=AIMAG(omega(io))
1209      end if
1210    end if
1211  end do
1212 
1213  write(msg,'(a,f9.4,a)')' Imaginary frequency for fit located at: ',e0*Ha_eV,' [eV] '
1214  call wrtout(std_out,msg,'COLL')
1215  ABI_CHECK(ioe0/=0,"Imaginary omega not found")
1216  !
1217  ! ================================================================
1218  ! === Calculate plasmon-pole A parameter A=epsilon^-1(0)-delta ===
1219  ! ================================================================
1220  do ig=1,npwc
1221    do igp=1,npwc
1222      epsm1_io0  = epsm1(ig,igp,io0)
1223      epsm1_ioe0 = epsm1(ig,igp,ioe0)
1224 
1225      AA=epsm1_io0
1226      if (ig==igp) AA=AA-one
1227 
1228      ! === Calculate plasmon-pole omega-twiddle-square parameter ===
1229      ! XG201009 Strangely, the next formula does not work with gcc43-debug
1230      ! omegatwsq=(AA/(epsm1_io0-epsm1_ioe0)-one)*e0**2
1231      ! This seems to be due to precision issue at the level of division by a complex whose norm squared
1232      ! is below the smallest representable number.
1233      ! After many trials, I have decided to shift the difference by a small number ... well, not so small ...
1234      ! for numerical issues
1235      diff=epsm1_io0-epsm1_ioe0
1236      diff=diff+cmplx(tol10,tol10)
1237      ratio=AA/diff
1238      omegatwsq=(ratio-cone)*e0**2
1239      !
1240      ! If omega-twiddle-squared is negative,set omega-twiddle-squared to 1.0 (a reasonable way of treating
1241      ! such terms, in which epsilon**-1 was originally increasing along this part of the imaginary axis)
1242      ! (note: originally these terms were ignored in Sigma; this was changed on 6 March 1990.)
1243 
1244      if (REAL(omegatwsq)<=zero) omegatwsq=one
1245      !
1246      ! Get omega-twiddle
1247      ! * Neglect the imag part (if any) in omega-twiddle-squared
1248      omegatw(ig,igp)=SQRT(REAL(omegatwsq))
1249      !
1250      ! Get big-omega-twiddle-squared=-omega-twiddle-squared AA
1251      bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1252 
1253    end do !igp
1254  end do !ig
1255 
1256  write(msg,'(2a,f15.12,2a,2i5,a)')ch10,&
1257 &  ' cppm1par : omega twiddle minval [eV]  = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1258 &  '            omega twiddle min location = ',MINLOC(ABS(omegatw)),ch10
1259  call wrtout(std_out,msg,'COLL')
1260 
1261  DBG_EXIT("COLL")
1262 
1263 end subroutine cppm1par

m_ppmodel/cppm2par [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 cppm2par

FUNCTION

  Calculate plasmon-pole parameters of the Hybertsen and Louie model (PRB 34, 5390 (1986) [[cite:Hybertsen1986]])

INPUTS

  qpt(3)=The coordinates of the q-point in the IBZ.
  epsm1(npwc,npwc)=symmetrized inverse dielectric (static limit is used)
  gmet(3,3)=metric in reciprocal space
  ngfftf(18)=contain all needed information about the 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
  npwc=number of plane waves in epsm1
  rhor(nfftf)=charge density on the real space FFT grid
  nfftf= total number of points in the fine FFT mesh  (for this processor)
  invalid_freq: what to do when PPM omega is found negative or imaginary
     0) drop it (default as specified in Hybersen-Louie original GW paper)
     1) set to 1 hartree
     2) set to infinity

OUTPUT

  bigomegatwsq(npwc,npwc)= squared bare plasma frequencies
   \Omega^2_{G1 G2}(q) = 4\pi \frac {(q+G1).(q+G2)}/{|q+G1|^2} n(G1-G2)
  omegatw(npwc,npwc)= plasmon frequencies \tilde\omega_{G1 G2}(q) where:
  \tilde\omega^2_{G1 G2}(q) =
    \frac {\Omega^2_{G1 G2}(q)} {\delta_{G1 G2}-\tilde\epsilon^{-1}_{G1 G2} (q, \omega=0)}

SOURCE

1297 subroutine cppm2par(qpt,npwc,epsm1,ngfftf,gvec,gprimd,rhor,nfftf,gmet,bigomegatwsq,omegatw,invalid_freq)
1298 
1299 !Arguments ------------------------------------
1300 !scalars
1301  integer,intent(in) :: npwc,nfftf,invalid_freq
1302 !arrays
1303  integer,intent(in) :: gvec(3,npwc)
1304  integer,intent(in) :: ngfftf(18)
1305  real(dp),intent(in) :: qpt(3),gmet(3,3),gprimd(3,3)
1306  real(dp),intent(in) :: rhor(nfftf)
1307  complex(gwpc),intent(in) :: epsm1(npwc,npwc)
1308  complex(gwpc),intent(out) :: bigomegatwsq(npwc,npwc)
1309  complex(gwpc),intent(out) :: omegatw(npwc,npwc)
1310 
1311 !Local variables-------------------------------
1312 !scalars
1313  integer,parameter :: paral_kgb0=0
1314  integer :: ig,igp,nimwp,ngfft1,ngfft2,ngfft3,gmgp_idx,ierr
1315  real(dp) :: lambda,phi,AA
1316  logical,parameter :: use_symmetrized=.TRUE.,check_imppf=.FALSE.
1317  character(len=500) :: msg
1318  type(MPI_type) :: MPI_enreg_seq
1319 !arrays
1320  real(dp) :: qlist(3,1)
1321  real(dp),allocatable :: tmp_rhor(:),qratio(:,:),qplusg(:),rhog_dp(:,:)
1322  complex(gwpc),allocatable :: omegatwsq(:,:)
1323  complex(gwpc),allocatable :: rhog(:),rhogg(:,:),temp(:,:)  !MG these should be double precision TODO
1324 !*************************************************************************
1325 
1326  call initmpi_seq(MPI_enreg_seq)
1327  call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfftf(2),ngfftf(3),'all')
1328  !
1329  ! === Calculate qratio(npwec,npvec) = (q+G).(q+Gp)/|q+G|^2 ===
1330  ABI_MALLOC_OR_DIE(qratio,(npwc,npwc), ierr)
1331 
1332  call cqratio(npwc,gvec,qpt,gmet,gprimd,qratio)
1333  !
1334  ! === Compute the density in G space rhor(R)--> rhog(G) ===
1335  ABI_MALLOC(rhog_dp,(2,nfftf))
1336  ABI_MALLOC(rhog,(nfftf))
1337  ngfft1=ngfftf(1)
1338  ngfft2=ngfftf(2)
1339  ngfft3=ngfftf(3)
1340 
1341  ABI_MALLOC(tmp_rhor,(nfftf))
1342  tmp_rhor=rhor ! To avoid having to use intent(inout).
1343  call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1344  ABI_FREE(tmp_rhor)
1345 
1346  rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1347  !
1348  ! Calculate the FFT index of each (G-Gp) vector and assign
1349  ! the value of the correspondent density simultaneously
1350  ABI_MALLOC_OR_DIE(rhogg,(npwc,npwc), ierr)
1351 
1352  ierr=0
1353  do ig=1,npwc
1354    do igp=1,npwc
1355      gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1356      if (gmgp_idx/=0) then
1357        rhogg(ig,igp)=rhog(gmgp_idx)
1358      else
1359        ierr=ierr+1
1360        rhogg(ig,igp)=czero
1361      end if
1362    end do
1363  end do
1364 
1365  if (ierr/=0) then
1366    write(msg,'(a,i4,3a)')&
1367 &   'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1368 &   'Enlarge the FFT mesh to get rid of this problem. '
1369    ABI_WARNING(msg)
1370  end if
1371 
1372  rhogg=four_pi*rhogg
1373  ABI_FREE(rhog_dp)
1374  ABI_FREE(rhog)
1375  !
1376  ! Calculate GPP parameters
1377  ! unsymmetrized epsm1 -> epsm1=|q+Gp|/|q+G|*epsm1
1378  ABI_MALLOC(qplusg,(npwc))
1379  ABI_MALLOC(temp,(npwc,npwc))
1380  ABI_MALLOC_OR_DIE(omegatwsq,(npwc,npwc), ierr)
1381 
1382  temp = -epsm1(:,:)
1383  !
1384  ! RS still not obvious for me whether one shall use the symmetrized inverse DM or the unsymmetrized one
1385  ! the default here is to use the symmetrized one, I must discuss this with XG
1386  !
1387  ! MG it turns out that using the symmetrized inverse DM in the plasmon-pole
1388  ! equations give the same results for the squared plasmon frequencies omegatwsq while the
1389  ! squared bare plasma frequencies bigomegatwsq related to the symmetrized dielectric matrix
1390  ! are obtained multipling by |q+G1|/|q+G2|
1391  !
1392  if (.not.use_symmetrized) then
1393    qlist(:,1) = qpt
1394    call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1395    do ig=1,npwc
1396      do igp=1,npwc
1397        temp(ig,igp)=qplusg(igp)/qplusg(ig)*temp(ig,igp)
1398      end do
1399    end do
1400  end if
1401 
1402  nimwp=0
1403  do ig=1,npwc
1404    temp(ig,ig)=temp(ig,ig)+one
1405    do igp=1,npwc
1406      bigomegatwsq(ig,igp) = rhogg(ig,igp)*qratio(ig,igp)
1407      omegatwsq(ig,igp)=bigomegatwsq(ig,igp)/temp(ig,igp)
1408      !
1409      ! Set to an arbitrary value the omegawsq which become negative or imaginary
1410      ! in principle these correspond to cases where the imaginary part of epsm1 does not have
1411      ! a well defined peak. The imaginary part of epsm1 in these cases oscillates  with a small amplitude
1412      ! since the amplitude A_GGpr=-pi/2*bigomegatwsq/omegatw,
1413      ! it follows that bigomegatwsq shall be set to zero for these cases
1414      if ( REAL(omegatwsq(ig,igp))<= tol12 .or. AIMAG(omegatwsq(ig,igp))**2*tol12> REAL(omegatwsq(ig,igp))**2) then
1415        nimwp=nimwp+1
1416 
1417        if ( invalid_freq == 1 ) then
1418         ! set omegatwsq to 1 hartree
1419          omegatwsq(ig,igp)=cone
1420          AA = epsm1(ig,igp)
1421          if ( ig == igp ) AA = AA - one
1422          omegatw(ig,igp)=SQRT(REAL(omegatwsq(ig,igp)))
1423          bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1424        elseif ( invalid_freq == 2 ) then
1425          ! set omegatwsq to infinity
1426          omegatwsq(ig,igp)=cone/tol6
1427          AA = epsm1(ig,igp)
1428          if ( ig == igp ) AA = AA - one
1429          omegatw(ig,igp)=SQRT(REAL(omegatwsq(ig,igp)))
1430          bigomegatwsq(ig,igp)=-AA*omegatw(ig,igp)**2
1431        else
1432          ! simply ignore all cases of omegatw with imaginary values
1433          bigomegatwsq(ig,igp)=(0.,0.)
1434          omegatw(ig,igp)=(ten,0.)
1435        end if
1436        if (check_imppf) then
1437          write(msg,'(a,2i8)')' Imaginary plasmon frequency at : ',ig,igp
1438          call wrtout(std_out,msg,'COLL')
1439        end if
1440      else
1441        ! this part has been added to deal with systems without inversion symmetry
1442        ! this new implementation gives the same results as the previous one if
1443        ! omegatwsq is a pure real number and has the advantage of being an improved
1444        ! approach for systems without an inversion center.
1445        lambda=ABS(omegatwsq(ig,igp))
1446        phi=ATAN(AIMAG(omegatwsq(ig,igp))/REAL(omegatwsq(ig,igp)))
1447        omegatw(ig,igp)=SQRT(lambda/COS(phi))
1448        bigomegatwsq(ig,igp)=bigomegatwsq(ig,igp)*(1.-(0.,1.)*TAN(phi))
1449        ! Uncomment the following line and comment the previous to restore the old version.
1450        !omegatw(ig,igp)=sqrt(real(omegatwsq(ig,igp)))
1451      end if
1452    end do
1453  end do
1454 
1455  write(msg,'(a,3f12.6,a,i8,a,i8)')&
1456 &  ' at q-point : ',qpt,&
1457 &  ' number of imaginary plasmonpole frequencies = ',nimwp,' / ',npwc**2
1458  call wrtout(std_out,msg,'COLL')
1459 
1460  write(msg,'(2a,f12.8,2a,3i5)')ch10,&
1461 &  ' cppm2par : omega twiddle minval [eV]  = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1462 &  '            omega twiddle min location = ',MINLOC(ABS(omegatw))
1463  call wrtout(std_out,msg,'COLL')
1464 
1465  call destroy_mpi_enreg(MPI_enreg_seq)
1466 
1467  ABI_FREE(omegatwsq)
1468  ABI_FREE(rhogg)
1469  ABI_FREE(temp)
1470  ABI_FREE(qplusg)
1471  ABI_FREE(qratio)
1472 
1473 end subroutine cppm2par

m_ppmodel/cppm3par [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 cppm3par

FUNCTION

 Calculate the plasmon-pole parameters using the von Linden-Horsh model (PRB 37, 8351, 1988) [[cite:vonderLinden1988]]
 (see also Pag 22 of Quasiparticle Calculations in Solids [[cite:Aulbur2001]].

INPUTS

 epsm1(npwc,npwc))= symmetrized inverse dielectric
 ngfftf(18)=contain all needed information about 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
 npwc=number of plane waves in epsm1
 qratio=(q+G1).(q+G2)/(|q+G1|.|q+G2|)
 rhor(nfftf)=charge density on the real space FFT grid
 nfftf=number of points in the FFT grid (for this processor)
 gvec(3,npwc)= G vectors in reduced coordinates

OUTPUT

  omegatw(npwc,npwc)= plasmon pole positions
  bigomegatwsq(npwc,npwc)=(E_{q,ii}^{-1}-1)*omegatw
   where E^{-1} is the eigenvalue of the inverse dielectric matrix
  eigtot(npwc,npwc)=the eigvectors of the symmetrized inverse dielectric matrix
   (first index for G, second index for bands)

SOURCE

1504 subroutine cppm3par(qpt,npwc,epsm1,ngfftf,gvec,gprimd,rhor,nfftf,bigomegatwsq,omegatw,eigtot)
1505 
1506 !Arguments ------------------------------------
1507 !scalars
1508  integer,intent(in) :: nfftf,npwc
1509 !arrays
1510  integer,intent(in) :: gvec(3,npwc),ngfftf(18)
1511  real(dp),intent(in) :: qpt(3),gprimd(3,3),rhor(nfftf)
1512  complex(gwpc),intent(in) :: epsm1(npwc,npwc)
1513  complex(gwpc),intent(out) :: bigomegatwsq(npwc,1),eigtot(npwc,npwc)
1514  complex(gwpc),intent(out) :: omegatw(npwc)
1515 
1516 !Local variables-------------------------------
1517 !TODO these should be dp
1518 !scalars
1519  integer,parameter :: paral_kgb0=0
1520  integer :: idx,ierr,ig,igp,ii,jj,ngfft1,ngfft2,ngfft3,gmgp_idx
1521  real(dp) :: num,qpg_dot_qpgp
1522  complex(dpc) :: conjg_eig
1523  logical :: qiszero
1524  character(len=500) :: msg
1525  type(MPI_type) :: MPI_enreg_seq
1526 !arrays
1527  real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),qlist(3,1)
1528  real(dp),allocatable :: eigval(:),qplusg(:),rhog_dp(:,:),zhpev2(:),tmp_rhor(:)
1529  complex(dpc),allocatable :: eigvec(:,:),matr(:),mm(:,:),rhog(:),rhogg(:,:)
1530  complex(dpc),allocatable :: zhpev1(:),zz(:)
1531 
1532 !*************************************************************************
1533 
1534  ! Fake MPI_type for the sequential part.
1535  call initmpi_seq(MPI_enreg_seq)
1536  call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfftf(2),ngfftf(3),'all')
1537 
1538  qiszero = (ALL(ABS(qpt)<1.0e-3))
1539 
1540  b1=two_pi*gprimd(:,1)
1541  b2=two_pi*gprimd(:,2)
1542  b3=two_pi*gprimd(:,3)
1543 
1544  ngfft1=ngfftf(1)
1545  ngfft2=ngfftf(2)
1546  ngfft3=ngfftf(3)
1547 
1548  ABI_MALLOC(rhog_dp,(2,nfftf))
1549  ABI_MALLOC(rhog,(nfftf))
1550 
1551  ABI_MALLOC_OR_DIE(rhogg,(npwc,npwc), ierr)
1552  !
1553  ! === Compute the density in G space rhog(r)--> rho(G) ===
1554  ! FIXME this has to be fixed, rho(G) should be passed instead of doing FFT for each q
1555 
1556  ABI_MALLOC(tmp_rhor,(nfftf))
1557  tmp_rhor=rhor ! To avoid having to use intent(inout).
1558  call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1559  ABI_FREE(tmp_rhor)
1560 
1561  rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1562  !
1563  ! Calculate the FFT index of each (G-Gp) vector and assign the value
1564  ! of the correspondent density simultaneously
1565  ierr=0
1566  do ig=1,npwc
1567    do igp=1,npwc
1568      gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1569      if (gmgp_idx/=0) then
1570        rhogg(ig,igp)=rhog(gmgp_idx)
1571      else
1572        ierr=ierr+1
1573        rhogg(ig,igp)=czero
1574      end if
1575    end do
1576  end do
1577 
1578  if (ierr/=0) then
1579    write(msg,'(a,i4,3a)')&
1580 &   'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1581 &   'Enlarge the FFT mesh to get rid of this problem. '
1582    ABI_WARNING(msg)
1583  end if
1584  !
1585  ! mm(G,Gp) = (q+G) \cdot (q+Gp) n(G-Gp)
1586  ABI_MALLOC_OR_DIE(mm,(npwc,npwc), ierr)
1587 
1588  do ig=1,npwc
1589    if (qiszero) then
1590      ! To be discussed with Riad, here we should use the small q
1591      ! to be consistent and consider the limit q-->0
1592      gpq(:)=gvec(:,ig)
1593    else
1594      gpq(:)=gvec(:,ig)+qpt
1595    end if
1596    do igp=1,npwc
1597      if (qiszero) then
1598        gppq(:)=gvec(:,igp)
1599      else
1600        gppq(:)=gvec(:,igp)+qpt
1601      end if
1602      qpg_dot_qpgp=zero
1603      do ii=1,3
1604        qpg_dot_qpgp=qpg_dot_qpgp+&
1605 &        ( gpq(1)*b1(ii) +gpq(2)*b2(ii) +gpq(3)*b3(ii))*&
1606 &        (gppq(1)*b1(ii)+gppq(2)*b2(ii)+gppq(3)*b3(ii))
1607      end do
1608      mm(ig,igp)=rhogg(ig,igp)*qpg_dot_qpgp
1609    end do !igp
1610  end do !ig
1611 
1612  ABI_FREE(rhog_dp)
1613  ABI_FREE(rhog)
1614  ! === Now we have rhogg,rho0 ===
1615  !
1616  ! Calculate the dielectric matrix eigenvalues and vectors
1617  ! Use only the static epsm1 i.e., only the w=0 part (eps(:,:,1,:))
1618  ABI_MALLOC(eigval,(npwc))
1619 
1620  ABI_MALLOC_OR_DIE(eigvec,(npwc,npwc), ierr)
1621 
1622  ABI_MALLOC(zz,(npwc))
1623  zz=czero
1624 
1625  ABI_MALLOC(qplusg,(npwc))
1626 
1627  ! Store the susceptibility matrix in upper mode before calling zhpev.
1628  ABI_MALLOC_OR_DIE(matr,(npwc*(npwc+1)/2), ierr)
1629 
1630  idx=1
1631  do ii=1,npwc
1632    do jj=1,ii
1633      matr(idx)=epsm1(jj,ii); idx=idx+1
1634    end do
1635  end do
1636 
1637  ABI_MALLOC(zhpev2,(3*npwc-2))
1638  ABI_MALLOC(zhpev1,(2*npwc-1))
1639 
1640  call ZHPEV('V','U',npwc,matr,eigval,eigvec,npwc,zhpev1,zhpev2,ierr)
1641  ABI_FREE(matr)
1642  ABI_FREE(zhpev2)
1643  ABI_FREE(zhpev1)
1644 
1645  if (ierr<0) then
1646    write (msg,'(2a,i4,a)')&
1647 &    ' Failed to calculate the eigenvalues and eigenvectors of the dielectric matrix ',ch10,&
1648 &    ierr*(-1),'-th argument in the matrix has an illegal value. '
1649    ABI_ERROR(msg)
1650  end if
1651 
1652  if (ierr>0) then
1653    write(msg,'(3a,i4,2a)')&
1654 &    ' Failed to calculate the eigenvalues and eigenvectors of the dielectric matrix ',ch10,&
1655 &    ' the algorithm failed to converge; ierr = ', ierr,ch10,&
1656 &    ' off-diagonal elements of an intermediate tridiagonal form did not converge to zero. '
1657    ABI_ERROR(msg)
1658  end if
1659  !
1660  ! Calculate the PPM parameters and the eigenpotentials needed for
1661  ! the calculation of the generalized overlap matrix
1662  ! Note: the eigenpotentials has to be calculated on the FFT (G-Gp) index
1663  !
1664  ! Save eigenvectors of \tilde\epsilon^{-1}
1665  ! MG well it is better to save \Theta otherwise
1666  ! we have to calculare \Theta for each band, spin, k-point but oh well
1667  eigtot=eigvec
1668 
1669  qlist(:,1) = qpt
1670  call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1671  !
1672  ! Basic Equation:
1673  !
1674  ! \Theta_{q,ii}(G)=\Psi_{q,ii}(G)/|q+G|
1675  ! where \Psi_{q,ii}(G) is the eigenvector of \tilde\epsilon^{-1}
1676 
1677  ! \tilde\omega_{ii,q}^2= 4\pi (1-eigenval(ii,q)))
1678  ! \sum_{G,Gp} \Theta^*_{q,ii}(G) (q+G)\cdot(q+Gp) n(G-Gp) \Theta_{q,ii}(Gp)
1679 
1680  do ii=1,npwc !DM band
1681    ! Calculate \Theta_{q,ii}(G)
1682    ! why the first element is not modified? if the problem is the small value of qplusg(1)
1683    ! we could multiply by sqrt(mod((q+G)(q+G'))) and then add the sing at the end
1684    if (qiszero)then
1685      eigvec(2:,ii)=eigvec(2:,ii)/qplusg(2:)
1686    else
1687      eigvec(:,ii)=eigvec(:,ii)/qplusg(:)
1688    end if
1689    do ig=1,npwc
1690      conjg_eig=CONJG(eigvec(ig,ii))
1691      do igp=1,npwc
1692        if(qiszero .and. ig==1 .and. igp==1)then
1693          zz(ii)=zz(ii)+conjg_eig*rhogg(ig,igp)*eigvec(igp,ii)
1694        else
1695          zz(ii)=zz(ii)+conjg_eig*mm(ig,igp)*eigvec(igp,ii)
1696        end if
1697      end do
1698    end do
1699 
1700    num=one-eigval(ii)
1701    if (num<=zero) then
1702 !    here I think we should set bigomegatwsq=0 and omegatw to an arbitrary value
1703 !    maybe we can output a warning TO BE discussed with Riad
1704      if (ABS(num)<1.0d-4) then
1705        num=1.0d-5
1706      else
1707        ABI_ERROR("One or more imaginary plasmon pole energies")
1708      end if
1709    end if
1710 
1711    omegatw(ii)=SQRT(4*pi*REAL(zz(ii))/num)
1712    ! this should be \alpha = 2\pi omegatw * (1-eigenval)
1713    ! MG check this, in the review I found a factor 2\pi, maybe it is reintroduced later
1714    bigomegatwsq(ii,1)=num*omegatw(ii)
1715  end do
1716 
1717  ABI_FREE(rhogg)
1718  ABI_FREE(mm)
1719  ABI_FREE(eigval)
1720  ABI_FREE(zz)
1721  ABI_FREE(eigvec)
1722  ABI_FREE(qplusg)
1723 
1724  call destroy_mpi_enreg(MPI_enreg_seq)
1725 
1726  write(msg,'(2a,f12.8,2a,3i5)')ch10,&
1727 &  ' cppm3par : omega twiddle minval [eV]  = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1728 &  '            omega twiddle min location = ',MINLOC(ABS(omegatw))
1729  call wrtout(std_out,msg,'COLL')
1730 
1731 end subroutine cppm3par

m_ppmodel/cppm4par [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 cppm4par

FUNCTION

 Calculate the plasmon-pole parameters using Engel and Farid model (PRB47,15931,1993) [[cite:Engel1993]].
 See also Quasiparticle Calculations in Solids [[cite:Aulbur2001]] p. 23

INPUTS

  qpt(3)=Reduced coordinates of the q-point.
  epsm1(npwc,npwc)=symmetrized inverse dielectric matrix.
  gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
  ngfftf(18)=contain all needed information about 3D fine FFT, see ~abinit/doc/variables/vargs.htm#ngfft
  npwc=number of plane waves in epsm1
  rhor(nfftf)=charge density on the real space FFT grid
  gvec(3,npwc)=G vectors in reduced coordinated

OUTPUT

  bigomegatwsq(npwc,npwc)=plasmon-pole strength
  omegatw(npwc)=plasmon-pole frequencies

SOURCE

1759 subroutine cppm4par(qpt,npwc,epsm1,ngfftf,gvec,gprimd,rhor,nfftf,bigomegatwsq,omegatw)
1760 
1761 !Arguments ------------------------------------
1762 !scalars
1763  integer,intent(in) :: nfftf,npwc
1764 !arrays
1765  integer,intent(in) :: gvec(3,npwc),ngfftf(18)
1766  real(dp),intent(in) :: gprimd(3,3),qpt(3)
1767  real(dp),intent(in) :: rhor(nfftf)
1768  complex(gwpc),intent(in) :: epsm1(npwc,npwc)
1769  complex(gwpc),intent(out) :: bigomegatwsq(npwc,npwc),omegatw(npwc)
1770 
1771 !Local variables-------------------------------
1772 !scalars
1773  integer,parameter :: paral_kgb0=0
1774  integer :: ierr,ig,igp,ii,ngfft1,ngfft2,ngfft3,gmgp_idx
1775  real(dp) :: qpg_dot_qpgp
1776  character(len=500) :: msg
1777  character(len=80) :: bar
1778  type(MPI_type) :: MPI_enreg_seq
1779 !arrays
1780  real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),qlist(3,1)
1781  real(dp),allocatable :: eigval(:),qplusg(:),rhog_dp(:,:)
1782  real(dp),allocatable :: tmp_rhor(:)
1783  complex(dpc),allocatable :: chi(:,:),chitmp(:,:),chitmps(:,:),eigvec(:,:)
1784  complex(dpc),allocatable :: mm(:,:),mtemp(:,:),rhog(:)
1785  complex(dpc),allocatable :: rhogg(:,:),tmp1(:),zz2(:,:)
1786 
1787 !*************************************************************************
1788 
1789  DBG_ENTER("COLL")
1790 
1791  call initmpi_seq(MPI_enreg_seq)
1792  call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfftf(2),ngfftf(3),'all')
1793 
1794  b1=two_pi*gprimd(:,1)
1795  b2=two_pi*gprimd(:,2)
1796  b3=two_pi*gprimd(:,3)
1797  !
1798  ! === Calculate density in G space rhog(G) ===
1799  ABI_MALLOC(rhog_dp,(2,nfftf))
1800  ABI_MALLOC(rhog,(nfftf))
1801 
1802  ABI_MALLOC_OR_DIE(rhogg,(npwc,npwc), ierr)
1803  !
1804  ! Conduct FFT tho(r)-->rhog(G)
1805  ! FIXME this has to be fixed, rho(G) should be passed instead of doing FFT for each q
1806  ABI_MALLOC(tmp_rhor,(nfftf))
1807  tmp_rhor=rhor ! To avoid having to use intent(inout).
1808  call fourdp(1,rhog_dp,tmp_rhor,-1,MPI_enreg_seq,nfftf,1,ngfftf,0)
1809  ABI_FREE(tmp_rhor)
1810 
1811  rhog(1:nfftf)=CMPLX(rhog_dp(1,1:nfftf),rhog_dp(2,1:nfftf))
1812  ABI_FREE(rhog_dp)
1813  !
1814  ! Calculate the FFT index of each (G-Gp) vector and assign the value
1815  ! of the correspondent density simultaneously
1816  ngfft1=ngfftf(1)
1817  ngfft2=ngfftf(2)
1818  ngfft3=ngfftf(3)
1819 
1820  ierr=0
1821  do ig=1,npwc
1822    do igp=1,npwc
1823      gmgp_idx = g2ifft(gvec(:,ig)-gvec(:,igp),ngfftf)
1824      if (gmgp_idx/=0) then
1825        rhogg(ig,igp)=rhog(gmgp_idx)
1826      else
1827        ierr=ierr+1
1828        rhogg(ig,igp)=czero
1829      end if
1830    end do
1831  end do
1832 
1833  if (ierr/=0) then
1834    write(msg,'(a,i0,3a)')&
1835 &   'Found ',ierr,' G1-G2 vectors falling outside the FFT box. ',ch10,&
1836 &   'Enlarge the FFT mesh to get rid of this problem. '
1837    ABI_WARNING(msg)
1838  end if
1839 
1840  ABI_FREE(rhog)
1841  !
1842  ! Now we have rhogg, calculate the M matrix (q+G1).(q+G2) n(G1-G2)
1843  ABI_MALLOC_OR_DIE(mm,(npwc,npwc), ierr)
1844 
1845  do ig=1,npwc
1846    gpq(:)=gvec(:,ig)+qpt
1847    do igp=1,npwc
1848      gppq(:)=gvec(:,igp)+qpt
1849      qpg_dot_qpgp=zero
1850      do ii=1,3
1851        qpg_dot_qpgp=qpg_dot_qpgp+&
1852 &        ( gpq(1)*b1(ii) +gpq(2)*b2(ii) +gpq(3)*b3(ii))*&
1853 &        (gppq(1)*b1(ii)+gppq(2)*b2(ii)+gppq(3)*b3(ii))
1854      end do
1855      mm(ig,igp)=rhogg(ig,igp)*qpg_dot_qpgp
1856    end do !igp
1857  end do !ig
1858 
1859  !MG TODO too much memory in chi, we can do all this stuff inside a loop
1860  ABI_MALLOC_OR_DIE(chitmp,(npwc,npwc), ierr)
1861 
1862  ABI_MALLOC_OR_DIE(chi,(npwc,npwc), ierr)
1863 
1864  ABI_MALLOC(qplusg,(npwc))
1865  !
1866  ! Extract the full polarizability from \tilde \epsilon^{-1}
1867  ! \tilde\epsilon^{-1}_{G1 G2} = \delta_{G1 G2} + 4\pi \frac{\chi_{G1 G2}}{|q+G1| |q+G2|}
1868  chitmp(:,:)=epsm1(:,:)
1869 
1870  qlist(:,1) = qpt
1871  call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1872 
1873  do ig=1,npwc
1874    chitmp(ig,ig)=chitmp(ig,ig)-one
1875  end do
1876  do ig=1,npwc
1877    do igp=1,npwc
1878      chi(ig,igp)=chitmp(ig,igp)*qplusg(ig)*qplusg(igp)/four_pi
1879    end do
1880  end do
1881  ABI_FREE(chitmp)
1882  !
1883  ! === Solve chi*X = Lambda M*X where Lambda=-1/em(q)**2 ===
1884  ABI_MALLOC(eigval,(npwc))
1885 
1886  ABI_MALLOC_OR_DIE(eigvec,(npwc,npwc), ierr)
1887  ABI_MALLOC_OR_DIE(mtemp,(npwc,npwc), ierr)
1888  ABI_MALLOC_OR_DIE(chitmps,(npwc,npwc), ierr)
1889  !
1890  ! Copy chi and mm into working arrays
1891  chitmps(:,:)=chi(:,:)
1892  mtemp(:,:)=mm(:,:)
1893 
1894  call xhegv(1,"Vectors","Upper",npwc,chitmps,mtemp,eigval)
1895  !
1896  ! Eigenvectors are normalized as : X_i^* M X_j = \delta_{ij}
1897  eigvec(:,:)=chitmps(:,:)
1898  ABI_FREE(mtemp)
1899  ABI_FREE(chitmps)
1900  !
1901  ! === Calculate the plasmon pole parameters ===
1902  ABI_MALLOC(tmp1,(npwc))
1903 
1904  ABI_MALLOC_OR_DIE(zz2,(npwc,npwc), ierr)
1905  !
1906  ! good check:
1907  ! the lowest plasmon energy on gamma should be
1908  ! close to experimental plasma energy within an error of 10 %
1909  ! this error can be reduced further if one includes the non local
1910  ! commutators in the calculation of the polarizability at q==0
1911  zz2(:,:)=(0.0,0.0)
1912 
1913  qlist(:,1) = qpt
1914  call cmod_qpg(1,1,qlist,npwc,gvec,gprimd,qplusg) !MG TODO here take care of small q
1915 
1916  do ii=1,npwc
1917    !
1918    ! keeping in mind that the above matrix is negative definite
1919    ! we might have a small problem with the eigval that correspond to large G vectors
1920    ! i.e. DM band index, where the eigevalues become very small with
1921    ! possibility of being small positive numbers (due to numerical problems)
1922    ! thus as a caution one can use the following condition
1923    ! this will not affect the result since such a huge plasmon energy give almost zero
1924    ! contribution to the self correlation energy
1925 
1926    if (eigval(ii)>=zero) then
1927      eigval(ii) = -1.0d-4
1928      if (eigval(ii)>1.0d-3) then
1929        eigval(ii) = -1.0d-22
1930        write(msg,'(a,i6,a,es16.6)')&
1931 &        ' Imaginary plasmon pole eigenenergy, eigenvector number ',ii,' with eigval',eigval(ii),ch10
1932        ABI_ERROR(msg)
1933      end if
1934    end if
1935    !
1936    ! === Save plasmon energies ===
1937    omegatw(ii)=SQRT(-1/eigval(ii))
1938    !
1939    ! Calculate and save scaled plasmon-pole eigenvectors
1940    ! defined as \sqrt{4\pi} \frac{Mx}{\sqrt{\tilde\omega} |q+G|}
1941    tmp1(:)=eigvec(:,ii)
1942 
1943    do ig=1,npwc
1944      do igp=1,npwc
1945        zz2(ig,ii)=zz2(ig,ii)+mm(ig,igp)*tmp1(igp) ! z--->y
1946      end do
1947      bigomegatwsq(ig,ii)=SQRT(four_pi)*zz2(ig,ii)/SQRT(omegatw(ii))
1948      bigomegatwsq(ig,ii)=bigomegatwsq(ig,ii)/qplusg(ig)
1949    end do
1950 
1951  end do
1952 
1953  ABI_FREE(tmp1)
1954  ABI_FREE(eigvec)
1955  ABI_FREE(eigval)
1956  ABI_FREE(zz2)
1957 
1958  call destroy_mpi_enreg(MPI_enreg_seq)
1959 
1960  ABI_FREE(qplusg)
1961  ABI_FREE(chi)
1962  ABI_FREE(rhogg)
1963  ABI_FREE(mm)
1964 
1965  bar=REPEAT('-',80)
1966  write(msg,'(3a)')bar,ch10,' plasmon energies vs q vector shown for lowest 10 bands                 '
1967  call wrtout(std_out,msg,'COLL')
1968  write(msg,'(2x,5x,10f7.3)')(REAL(omegatw(ig))*Ha_eV, ig=1,10)
1969  call wrtout(std_out,msg,'COLL')
1970  write(msg,'(a)')bar
1971  call wrtout(std_out,msg,'COLL')
1972 
1973  write(msg,'(2a,f12.8,2a,3i5)')ch10,&
1974 &  ' cppm4par : omega twiddle minval [eV]  = ',MINVAL(ABS(omegatw))*Ha_eV,ch10,&
1975 &  '            omega twiddle min location = ',MINLOC(ABS(omegatw))
1976  call wrtout(std_out,msg,'COLL')
1977 
1978  DBG_EXIT("COLL")
1979 
1980 end subroutine cppm4par

m_ppmodel/cqratio [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 cqratio

FUNCTION

  Calculate qratio(G,Gp,q)= (q+G)\cdot(q+Gp) / |q+G|^2 needed for Hybertsen-Louie and Plasmonpole model

INPUTS

  npwc=number of planewaves considered (used for the correlation part)
  gvec(3,npwc)=reduced coordinates of the plane waves
  q(3)=coordinates of q points
  gmet(3,3)=metric in reciprocal space
  gprimd(3,3)=reciprocal lattice vectors

OUTPUT

  qratio(npwc,npwc)=(q+G).(q+Gp)

SOURCE

2004 subroutine cqratio(npwc,gvec,q,gmet,gprimd,qratio)
2005 
2006 !Arguments ------------------------------------
2007 !scalars
2008  integer,intent(in) :: npwc
2009 !arrays
2010  integer,intent(in) :: gvec(3,npwc)
2011  real(dp),intent(in) :: gmet(3,3),gprimd(3,3),q(3)
2012  real(dp),intent(out) :: qratio(npwc,npwc)
2013 
2014 !Local variables ------------------------------
2015 !scalars
2016  integer :: ig,igp,ii
2017  real(dp) :: qpg_dot_qpgp
2018 !arrays
2019  real(dp) :: b1(3),b2(3),b3(3),gppq(3),gpq(3),norm(npwc)
2020 
2021 !************************************************************************
2022 
2023  b1=two_pi*gprimd(:,1); b2=two_pi*gprimd(:,2); b3=two_pi*gprimd(:,3)
2024 
2025  norm(:)=zero; qratio=zero
2026 
2027  !FIXME this loops have to be rewritten!!!!
2028  do ig=1,npwc
2029    gpq(:)=gvec(:,ig)+q
2030    norm(ig)=two_pi*SQRT(DOT_PRODUCT(gpq,MATMUL(gmet,gpq)))
2031 !  norm(ig)=normv(gpq,gmet,'g')
2032  end do
2033  do ig=1,npwc
2034    gpq(:)=gvec(:,ig)+q
2035    do igp=1,npwc
2036      gppq(:)=gvec(:,igp)+q
2037      qpg_dot_qpgp=zero
2038 !    qpg_dot_qpgp=vdotw(gpq,gppq,gmet,'g')
2039      do ii=1,3
2040        qpg_dot_qpgp=qpg_dot_qpgp+&
2041 &        ( gpq(1)*b1(ii) +  gpq(2)*b2(ii) + gpq(3)*b3(ii))*&
2042 &        (gppq(1)*b1(ii) + gppq(2)*b2(ii) +gppq(3)*b3(ii))
2043      end do
2044 
2045 !    Now calculate qratio = (q+G).(q+Gp)/|q+G|^2
2046 !    when |q+G|^2 and (q+G).(q+Gp) are both zero set (q+G).(q+Gp)/|q+G|^2 = 1
2047 !    when |q+G|^2 is zero and |q+Gp| is not zero set (q+G).(q+Gp)/|q+G|^2 = 0
2048      if (norm(ig)<0.001) then
2049        if (norm(igp)<0.001) then     ! Case q=0 and G=Gp=0
2050          qratio(ig,igp)=one
2051        else                          ! Case q=0 and G=0 and Gp !=0
2052          qratio(ig,igp)=zero
2053        end if
2054      else if (norm(igp)<0.001) then  ! Case q=0 and G= !0 and Gp=0
2055        qratio(ig,igp)=zero
2056      else
2057        qratio(ig,igp)=qpg_dot_qpgp/norm(ig)**2
2058      end if
2059 
2060    end do
2061  end do
2062 
2063 end subroutine cqratio

m_ppmodel/get_ppm_eigenvalues [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  get_ppm_eigenvalues

FUNCTION

  Constructs the inverse dielectri matrix starting from the plasmon-pole
  parameters and calculates the frequency-dependent eigenvalues for each
  of the nomega frequencies specifies in the array omega.

INPUTS

OUTPUT

SIDE EFFECTS

SOURCE

1034 subroutine get_ppm_eigenvalues(PPm,iqibz,zcut,nomega,omega,Vcp,eigenvalues)
1035 
1036 !Arguments ------------------------------------
1037 !scalars
1038  integer,intent(in) :: iqibz,nomega
1039  type(ppmodel_t),intent(in) :: PPm
1040  type(vcoul_t),intent(in) :: Vcp
1041  real(dp),intent(in) :: zcut
1042 !arrays
1043  complex(dpc),intent(in) :: omega(nomega)
1044  complex(dpc),intent(out) :: eigenvalues(PPm%npwc,nomega)
1045 
1046 !Local variables-------------------------------
1047 !scalars
1048  integer :: info,lwork,negw,ig1,ig2,idx,sdim,iomega,ierr
1049  character(len=500) :: msg
1050 !arrays
1051  real(dp),allocatable :: ww(:),rwork(:)
1052  complex(dpc),allocatable :: work(:),Adpp(:),eigvec(:,:),wwc(:),vs(:,:),Afull(:,:)
1053  complex(dpc),allocatable :: em1q(:,:,:)
1054  logical,allocatable :: bwork(:)
1055  logical :: sortcplx !BUG in abilint
1056 
1057 ! *************************************************************************
1058 
1059  ABI_CHECK(PPm%mqmem/=0,'mqmem==0 not implemented')
1060 
1061  ABI_MALLOC(em1q,(PPm%npwc,PPm%npwc,nomega))
1062 
1063  call getem1_from_PPm(PPm,PPm%npwc,iqibz,zcut,nomega,omega,Vcp,em1q)
1064 
1065  do iomega=1,nomega
1066    !
1067    if (ABS(REAL(omega(iomega)))>0.00001) then
1068      !if (.TRUE.) then
1069      ! === Eigenvalues for a generic complex matrix ===
1070 
1071      lwork=4*2*PPm%npwc
1072      ABI_MALLOC(wwc,(PPm%npwc))
1073      ABI_MALLOC(work,(lwork))
1074      ABI_MALLOC(rwork,(PPm%npwc))
1075      ABI_MALLOC(bwork,(PPm%npwc))
1076      ABI_MALLOC(vs,(PPm%npwc,PPm%npwc))
1077      ABI_MALLOC(Afull,(PPm%npwc,PPm%npwc))
1078      Afull=em1q(:,:,iomega)
1079 
1080      !for the moment no sort, maybe here I should sort using the real part?
1081      call ZGEES('V','N',sortcplx,PPm%npwc,Afull,PPm%npwc,sdim,wwc,vs,PPm%npwc,work,lwork,rwork,bwork,info)
1082      if (info/=0) then
1083       write(msg,'(2a,i10)')' get_ppm_eigenvalues : Error in ZGEES, diagonalizing complex matrix, info = ',info
1084       call wrtout(std_out,msg,'COLL')
1085      end if
1086 
1087      eigenvalues(:,iomega)=wwc(:)
1088 
1089      ABI_FREE(wwc)
1090      ABI_FREE(work)
1091      ABI_FREE(rwork)
1092      ABI_FREE(bwork)
1093      ABI_FREE(vs)
1094      ABI_FREE(Afull)
1095 
1096    else
1097      ! === Hermitian Case ===
1098      lwork=2*PPm%npwc-1
1099      ABI_MALLOC(ww,(PPm%npwc))
1100      ABI_MALLOC(work,(lwork))
1101      ABI_MALLOC(rwork,(3*PPm%npwc-2))
1102      ABI_MALLOC(eigvec,(PPm%npwc,PPm%npwc))
1103 
1104      ABI_MALLOC_OR_DIE(Adpp,(PPm%npwc*(PPm%npwc+1)/2), ierr)
1105      write(std_out,*) 'in hermitian'
1106 
1107      idx=0
1108      do ig2=1,PPm%npwc
1109        do ig1=1,ig2
1110          idx=idx+1
1111          Adpp(idx)=em1q(ig1,ig2,iomega)
1112        end do
1113      end do
1114 
1115      ! For the moment we require also the eigenvectors.
1116      call ZHPEV('V','U',PPm%npwc,Adpp,ww,eigvec,PPm%npwc,work,rwork,info)
1117 
1118      if (info/=0) then
1119        write(msg,'(2a,i10)')' get_ppm_eigenvalues : Error diagonalizing matrix, info = ',info
1120        call wrtout(std_out,msg,'COLL')
1121      end if
1122      negw = (COUNT((REAL(ww)<tol6)))
1123      if (negw/=0) then
1124        write(msg,'(a,i0,a,i0,a,f8.4)')&
1125 &       'Found negative eigenvalues. No. ',negw,' at iqibz= ',iqibz,' minval= ',MINVAL(REAL(ww))
1126         ABI_WARNING(msg)
1127      end if
1128 
1129      eigenvalues(:,iomega)=ww(:)
1130 
1131      ABI_FREE(ww)
1132      ABI_FREE(work)
1133      ABI_FREE(rwork)
1134      ABI_FREE(eigvec)
1135      ABI_FREE(Adpp)
1136    end if
1137    !
1138  end do !iomega
1139 
1140  ABI_FREE(em1q)
1141 
1142 end subroutine get_ppm_eigenvalues

m_ppmodel/getem1_from_ppm [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  getem1_from_ppm

FUNCTION

  Calculate the symmetrized inverse dielectric matrix from the parameters of the plasmon-pole model.

INPUTS

OUTPUT

SIDE EFFECTS

SOURCE

786 subroutine getem1_from_ppm(PPm,mpwc,iqibz,zcut,nomega,omega,Vcp,em1q,only_ig1,only_ig2)
787 
788 !Arguments ------------------------------------
789 !scalars
790  integer,intent(in) :: mpwc,iqibz,nomega
791  type(ppmodel_t),intent(in) :: PPm
792  type(vcoul_t),intent(in) :: Vcp
793  real(dp),intent(in) :: zcut
794  integer,optional,intent(in) :: only_ig1,only_ig2
795 !arrays
796  complex(dpc),intent(in) :: omega(nomega)
797  complex(dpc),intent(out) :: em1q(mpwc,mpwc,nomega)
798 
799 !Local variables-------------------------------
800 !scalars
801  integer :: ig1,ig2,io,idm,ig1_min,ig2_min,ig1_max,ig2_max
802  real(dp) :: den
803  complex(dpc) :: qpg1,qpg2,ug1,ug2
804  complex(dpc) :: delta,em1ggp,otw,zzpq,yg1,yg2,bot1,bot2,chig1g2
805  !character(len=500) :: msg
806 
807 ! *************************************************************************
808 
809  ABI_CHECK(PPm%mqmem/=0,'mqmem==0 not implemented')
810 
811  !TODO zcut should be an entry in PPm
812  delta=CMPLX(zero,zcut)
813 
814  ! To save memory, a particular combination of
815  ! ig1 and ig2 can be selected
816  ig1_min = 1
817  ig2_min = 1
818  ig1_max = PPm%npwc
819  ig2_max = PPm%npwc
820  if (present(only_ig1)) then
821    ig1_min = only_ig1
822    ig1_max = only_ig1
823  end if
824  if (present(only_ig2)) then
825    ig2_min = only_ig2
826    ig2_max = only_ig2
827  end if
828 
829  select case (PPm%model)
830  case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
831    do io=1,nomega
832      !
833      do ig2=ig2_min,ig2_max
834        do ig1=ig1_min,ig1_max
835         !den = omega(io)**2-REAL(PPm%omegatw(iqibz)%vals(ig1,ig2)**2)
836         !if (den**2<zcut**2) den = omega(io)**2-REAL( (PPm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
837         den = omega(io)**2 - REAL( (PPm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
838         em1ggp = PPm%bigomegatwsq(iqibz)%vals(ig1,ig2)/den
839         if (ig1==ig2) em1ggp=em1ggp+one
840         em1q(ig1,ig2,io)=em1ggp
841         !em1q(ig1,ig2,io)=em1ggp*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
842        end do
843      end do
844      !
845    end do !io
846 
847  case (PPM_LINDEN_HORSH)
848    !TODO Check coefficients
849    do io=1,nomega
850      !
851      do ig2=ig2_min,ig2_max
852        do ig1=ig1_min,ig1_max
853          !
854          em1ggp=czero
855          do idm=1,PPm%npwc
856            !den=omega(io)**2-(PPm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2
857            !em1w(io)=em1w(io)+eigvec(ig1,idm,iqibz)*conjg(eigvec(ig2,idm,iqibz))*bigomegatwsq(ig1,ig2,iqibz)/den
858            ug1 = PPm%eigpot(iqibz)%vals(ig1,idm)
859            ug2 = PPm%eigpot(iqibz)%vals(ig2,idm)
860            otw = PPm%bigomegatwsq(iqibz)%vals(idm,1)*PPm%omegatw(iqibz)%vals(idm,1)
861            zzpq=PPm%bigomegatwsq(iqibz)%vals(idm,1)
862            den=half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
863            em1ggp=em1ggp+ug1*CONJG(ug2)*den
864            !eigenvalues(idm,io)=one + half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
865          end do
866          if (ig2==ig1) em1ggp=em1ggp+one
867          em1q(ig1,ig2,io)=em1ggp
868        end do !ig1
869      end do !ig2
870      !
871    end do !iomega
872 
873  case (PPM_ENGEL_FARID)
874    ! Make e^-1
875    do io=1,nomega
876      !
877      do ig2=ig2_min,ig2_max
878        qpg2=one/Vcp%vc_sqrt(ig2,iqibz)
879        do ig1=ig1_min,ig1_max
880          qpg1=one/Vcp%vc_sqrt(ig1,iqibz)
881 
882          chig1g2=czero
883          do idm=1,PPm%npwc
884            otw =PPm%omegatw(iqibz)%vals(idm,1)
885            bot1=PPm%bigomegatwsq(iqibz)%vals(ig1,idm)
886            bot2=PPm%bigomegatwsq(iqibz)%vals(ig2,idm)
887            yg1=SQRT(otw/four_pi)*qpg1*bot1
888            yg2=SQRT(otw/four_pi)*qpg2*bot2
889            chig1g2=chig1g2 + yg1*CONJG(yg2)/(omega(io)**2-(otw-delta)**2)
890          end do
891 
892          em1ggp=four_pi*chig1g2/(qpg1*qpg2)
893          if (ig1==ig2) em1ggp=em1ggp+one
894          em1q(ig1,ig2,io)=em1ggp !*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
895        end do !ig1
896      end do !ig2
897      !
898    end do !iomega
899 
900  case default
901    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
902  end select
903 
904 end subroutine getem1_from_ppm

m_ppmodel/getem1_from_ppm_one_ggp [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  getem1_from_ppm

FUNCTION

  Same as getem1_from_ppm, but does it for a single set of G,G' vectors

INPUTS

OUTPUT

SIDE EFFECTS

SOURCE

 924 subroutine getem1_from_ppm_one_ggp(PPm,iqibz,zcut,nomega,omega,Vcp,em1q,ig1,ig2)
 925 
 926 !Arguments ------------------------------------
 927 !scalars
 928  integer,intent(in) :: iqibz,nomega
 929  type(ppmodel_t),intent(in) :: PPm
 930  type(vcoul_t),intent(in) :: Vcp
 931  real(dp),intent(in) :: zcut
 932  integer, intent(in) :: ig1,ig2
 933 !arrays
 934  complex(dpc),intent(in) :: omega(nomega)
 935  complex(dpc),intent(out) :: em1q(nomega)
 936 
 937 !Local variables-------------------------------
 938 !scalars
 939  integer :: io,idm !,ig1_min,ig2_min,ig2_max
 940  real(dp) :: den
 941  complex(dpc) :: qpg1,qpg2,ug1,ug2
 942  complex(dpc) :: delta,em1ggp,otw,zzpq,yg1,yg2,bot1,bot2,chig1g2
 943  !character(len=500) :: msg
 944 
 945 ! *************************************************************************
 946 
 947  ABI_CHECK(PPm%mqmem/=0,'mqmem==0 not implemented')
 948 
 949  !TODO zcut should be an entry in PPm
 950  delta=CMPLX(zero,zcut)
 951 
 952  select case (PPm%model)
 953 
 954  case (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
 955    do io=1,nomega
 956      !den = omega(io)**2-REAL(PPm%omegatw(iqibz)%vals(ig1,ig2)**2)
 957      !if (den**2<zcut**2) den = omega(io)**2-REAL( (PPm%omegatw(iqibz)%value(ig1,ig2)-delta)**2 )
 958      den = omega(io)**2-REAL( (PPm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2 )
 959      em1ggp = PPm%bigomegatwsq(iqibz)%vals(ig1,ig2)/den
 960      if (ig1==ig2) em1ggp=em1ggp+one
 961      em1q(io)=em1ggp
 962      !em1q(io)=em1ggp*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
 963    end do !io
 964 
 965  case (PPM_LINDEN_HORSH)
 966    !TODO Check coefficients
 967    do io=1,nomega
 968      em1ggp=czero
 969      do idm=1,PPm%npwc
 970        !den=omega(io)**2-(PPm%omegatw(iqibz)%vals(ig1,ig2)-delta)**2
 971        !em1w(io)=em1w(io)+eigvec(ig1,idm,iqibz)*conjg(eigvec(ig2,idm,iqibz))*bigomegatwsq(ig1,ig2,iqibz)/den
 972        ug1 =PPm%eigpot(iqibz)%vals(ig1,idm)
 973        ug2 =PPm%eigpot(iqibz)%vals(ig2,idm)
 974        otw =PPm%bigomegatwsq(iqibz)%vals(idm,1)*PPm%omegatw(iqibz)%vals(idm,1)
 975        zzpq=PPm%bigomegatwsq(iqibz)%vals(idm,1)
 976        den=half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
 977        em1ggp=em1ggp+ug1*CONJG(ug2)*den
 978        !eigenvalues(idm,io)=one + half*REAL(zzpq*otw*( one/(omega(io)-otw+delta) - one/(omega(io)+otw-delta) ))
 979      end do
 980 
 981      if (ig2==ig1) em1ggp=em1ggp+one
 982      em1q(io)=em1ggp
 983    end do !iomega
 984 
 985  case (PPM_ENGEL_FARID)
 986    ! Make e^-1
 987    do io=1,nomega
 988      !
 989      qpg2=one/Vcp%vc_sqrt(ig2,iqibz)
 990      qpg1=one/Vcp%vc_sqrt(ig1,iqibz)
 991 
 992      chig1g2=czero
 993      do idm=1,PPm%npwc
 994        otw =PPm%omegatw(iqibz)%vals(idm,1)
 995        bot1=PPm%bigomegatwsq(iqibz)%vals(ig1,idm)
 996        bot2=PPm%bigomegatwsq(iqibz)%vals(ig2,idm)
 997        yg1=SQRT(otw/four_pi)*qpg1*bot1
 998        yg2=SQRT(otw/four_pi)*qpg2*bot2
 999        chig1g2=chig1g2 + yg1*CONJG(yg2)/(omega(io)**2-(otw-delta)**2)
1000      end do
1001 
1002      em1ggp=four_pi*chig1g2/(qpg1*qpg2)
1003      if (ig1==ig2) em1ggp=em1ggp+one
1004      em1q(io)=em1ggp !*Vcp%vc_sqrt(ig1,iqibz)*Vcp%vc_sqrt(ig2,iqibz)
1005 
1006    end do !iomega
1007 
1008  case default
1009    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
1010  end select
1011 
1012 end subroutine getem1_from_ppm_one_ggp

m_ppmodel/new_setup_ppmodel [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 new_setup_ppmodel

FUNCTION

  Initialize some values of several arrays of the PPm datastructure
  that are used in case of plasmonpole calculations
  Just a wrapper around different plasmonpole routines.

INPUTS

  Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
  Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
  iq_ibz=Index of the q-point in the BZ.
  npwe=number of G vectors for the correlation part
  nomega=number of frequencies in $\epsilon^{-1}$
  omega=frequencies in epsm1_ggw
  epsm1_ggw(npwe,npwe,nomega)=the inverse dielctric matrix
  ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
  gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
  nfftf=the number of points in the FFT mesh (for this processor)
  rhor_tot(nfftf)=the total charge in real space
  PPm<ppmodel_t>:

SIDE EFFECTS

  PPm<ppmodel_t>:
  == if ppmodel 1 or 2 ==
   %omegatw and %bigomegatwsq
  == if ppmodel 3 ==
   %omegatw, %bigomegatwsq and %eigpot
  == if ppmodel 4 ==
   %omegatw and %bigomegatwsq

NOTES

 * FFT parallelism not implemented.
 * TODO: rhor_tot should be replaced by rhog_tot

SOURCE

2433 subroutine new_setup_ppmodel(PPm,iq_ibz,Cryst,Qmesh,npwe,nomega,omega,epsm1_ggw,nfftf,gvec,ngfftf,rhor_tot)
2434 
2435 !Arguments ------------------------------------
2436 !scalars
2437  integer,intent(in) :: nfftf,npwe,nomega,iq_ibz
2438  type(kmesh_t),intent(in) :: Qmesh
2439  type(crystal_t),intent(in) :: Cryst
2440  type(ppmodel_t),intent(inout) :: PPm
2441 !arrays
2442  integer,intent(in) :: gvec(3,npwe),ngfftf(18)
2443  real(dp),intent(in) :: rhor_tot(nfftf)
2444  complex(dpc),intent(in) :: omega(nomega)
2445  complex(gwpc),intent(in) :: epsm1_ggw(npwe,npwe,nomega)
2446 
2447 !Local variables-------------------------------
2448 !scalars
2449  real(dp) :: n_at_G_zero
2450  character(len=500) :: msg
2451 !scalars
2452  real(dp) :: qpt(3)
2453 ! *************************************************************************
2454 
2455  DBG_ENTER("COLL")
2456 
2457  !@ppmodel_t
2458  !
2459  if (PPm%has_q(iq_ibz) /= PPM_TAB_ALLOCATED) then
2460    ABI_ERROR("ppmodel tables are not allocated")
2461  end if
2462 
2463  qpt = Qmesh%ibz(:,iq_ibz)
2464  PPm%has_q(iq_ibz) = PPM_TAB_STORED
2465  !
2466  ! Calculate plasmonpole parameters
2467  ! TODO ppmodel==1 by default, should be set to 0 if AC and CD
2468  SELECT CASE (PPm%model)
2469 
2470  CASE (PPM_NONE)
2471    ABI_COMMENT('Skipping Plasmonpole model calculation')
2472 
2473  CASE (PPM_GODBY_NEEDS)
2474    ! Note: the q-dependency enters only through epsilon^-1.
2475    call cppm1par(npwe,nomega,omega,PPm%drude_plsmf,epsm1_ggw,&
2476 &     PPm%omegatw(iq_ibz)%vals,PPm%bigomegatwsq(iq_ibz)%vals)
2477 
2478  CASE (PPM_HYBERTSEN_LOUIE)
2479    call cppm2par(qpt,npwe,epsm1_ggw(:,:,1),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,Cryst%gmet,&
2480 &    PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals,PPm%invalid_freq)
2481    !
2482    ! Quick-and-dirty change of the plasma frequency. Never executed in standard runs.
2483    if (PPm%force_plsmf>tol6) then ! Integrate the real-space density
2484       n_at_G_zero = SUM(rhor_tot(:))/nfftf
2485       ! Change the prefactor
2486       write(msg,'(2(a,es16.8))') 'Forced ppmfreq:',PPm%force_plsmf*Ha_eV,' nelec/ucvol:',n_at_G_zero
2487       ABI_WARNING(msg)
2488       PPm%force_plsmf = (PPm%force_plsmf**2)/(four_pi*n_at_G_zero)
2489       PPm%bigomegatwsq(iq_ibz)%vals = PPm%force_plsmf * PPm%bigomegatwsq(iq_ibz)%vals
2490       PPm%omegatw(iq_ibz)%vals      = PPm%force_plsmf * PPm%omegatw(iq_ibz)%vals
2491       write(msg,'(a,es16.8)') 'Plasma frequency forced in HL ppmodel, new prefactor is:',PPm%force_plsmf
2492       ABI_WARNING(msg)
2493    end if
2494 
2495  CASE (PPM_LINDEN_HORSH)
2496    ! TODO Check better double precision, this routine is in a messy state
2497    call cppm3par(qpt,npwe,epsm1_ggw(:,:,1),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
2498 &                PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals(:,1),PPm%eigpot(iq_ibz)%vals)
2499 
2500  CASE (PPM_ENGEL_FARID)  ! TODO Check better double precision, this routine is in a messy state
2501    if ((ALL(ABS(qpt)<1.0e-3))) qpt = GW_Q0_DEFAULT ! FIXME
2502 
2503    call cppm4par(qpt,npwe,epsm1_ggw(:,:,1),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
2504 &    PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals(:,1))
2505 
2506  CASE DEFAULT
2507    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
2508  END SELECT
2509 
2510  DBG_EXIT("COLL")
2511 
2512 end subroutine new_setup_ppmodel

m_ppmodel/ppm_free [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_free

FUNCTION

  Deallocate all associated pointers defined in a variable of type ppmodel_t.

SIDE EFFECTS

  PPm<ppmodel_t>=All dynamic memory is released.

SOURCE

360 subroutine ppm_free(PPm)
361 
362 !Arguments ------------------------------------
363  type(ppmodel_t),intent(inout) :: PPm
364 
365 !Local variables-------------------------------
366 !scalars
367  integer :: dim_q,iq_ibz
368 
369 ! *********************************************************************
370 
371  !@ppmodel_t
372 
373  ! Be careful here to avoid dangling pointers.
374  if (associated(PPm%bigomegatwsq_qbz)) then
375    select case (PPm%bigomegatwsq_qbz_stat)
376    case (PPM_ISALLOCATED)
377      call array_free(PPm%bigomegatwsq_qbz)
378    case (PPM_ISPOINTER)
379      nullify(PPm%bigomegatwsq_qbz)
380    end select
381  end if
382 
383  if (associated(PPm%omegatw_qbz)) then
384    select case (PPm%omegatw_qbz_stat)
385    case (PPM_ISALLOCATED)
386      call array_free(PPm%omegatw_qbz)
387    case (PPM_ISPOINTER)
388      nullify(PPm%omegatw_qbz)
389    end select
390  end if
391 
392  if (associated(PPm%eigpot_qbz)) then
393    select case (PPm%eigpot_qbz_stat)
394    case (PPM_ISALLOCATED)
395      call array_free(PPm%eigpot_qbz)
396    case (PPM_ISPOINTER)
397      nullify(PPm%eigpot_qbz)
398    end select
399  end if
400 
401  dim_q=PPm%nqibz; if (PPm%mqmem==0) dim_q=1
402 
403 #if 0
404  do iq_ibz=1,dim_q
405    call ppm_table_free(PPm,iq_ibz)
406  end do
407  ABI_FREE(PPm%bigomegatwsq)
408  ABI_FREE(PPm%omegatw)
409  ABI_FREE(PPm%eigpot)
410 
411 #else
412  if (allocated(PPm%bigomegatwsq)) then
413    do iq_ibz=1,dim_q
414      call array_free(PPm%bigomegatwsq(iq_ibz))
415    end do
416    ABI_FREE(PPm%bigomegatwsq)
417  end if
418  !
419  if (allocated(PPm%omegatw)) then
420    do iq_ibz=1,dim_q
421      call array_free(PPm%omegatw(iq_ibz))
422    end do
423    ABI_FREE(PPm%omegatw)
424  end if
425  !
426  if (allocated(PPm%eigpot)) then
427    do iq_ibz=1,dim_q
428      call array_free(PPm%eigpot(iq_ibz))
429    end do
430    ABI_FREE(PPm%eigpot)
431  end if
432 #endif
433 
434  ! logical flags must be deallocated here.
435  ABI_SFREE(PPm%keep_q)
436  ABI_SFREE(PPm%has_q)
437 
438 end subroutine ppm_free

m_ppmodel/ppm_get_qbz [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_get_qbz

FUNCTION

  Calculates the plasmonpole matrix elements in the full BZ zone.

INPUTS

  PPm<ppmodel_t>=data type containing information on the plasmonpole technique
  Gsph<gsphere_t>=data related to the G-sphere
    %grottb
    %phmSGt
  Qmesh<kmesh_t>=Info on the q-mesh
    %nbz=number if q-points in the BZ
    %tab(nbz)=index of the symmeric q-point in the IBZ, for each point in the BZ
    %tabo(nbz)=the operation that rotates q_ibz onto \pm q_bz (depending on tabi)
    %tabi(nbz)=-1 if time-reversal has to be considered, 1 otherwise
  iq_bz=Index of the q-point in the BZ where PPmodel parameters have to be symmetrized

OUTPUT

  botsq
  otq
  eig (only if PPm%ppmodel==3)

NOTES

  In the present implementation we are not considering a possible umklapp vector G0.
  In this case,indeed, the equation is different since we have to consider G-G0.
  There is however a check in sigma

  * Remember the symmetry properties of \tilde\espilon^{-1}
    If q_bz=Sq_ibz+G0:

    $\epsilon^{-1}_{SG1-G0,SG2-G0}(q_bz) = e^{+iS(G2-G1).\tau}\epsilon^{-1}_{G1,G2)}(q)

    If time-reversal symmetry can be used then :
    $\epsilon^{-1}_{G1,G2}(-q_bz) = e^{+i(G1-G2).\tau}\epsilon^{-1}_{-S^{-1}(G1+Go),-S^{-1}(G2+G0)}^*(q)

 * Notice that eig is used only if PPm%model==3

SOURCE

219 subroutine ppm_get_qbz(PPm,Gsph,Qmesh,iq_bz,botsq,otq,eig)
220 
221 !Arguments ------------------------------------
222 !scalars
223  integer,intent(in) :: iq_bz
224  type(ppmodel_t),target,intent(inout) :: PPm
225  type(gsphere_t),target,intent(in) :: Gsph
226  type(kmesh_t),intent(in) :: Qmesh
227  complex(gwpc),intent(out) :: botsq(:,:),otq(:,:),eig(:,:)
228 
229 !Local variables-------------------------------
230 !scalars
231  integer :: ii,jj,iq_ibz,itim_q,isym_q,iq_curr,isg1,isg2
232  !character(len=500) :: msg
233 !arrays
234  integer, ABI_CONTIGUOUS pointer :: grottb(:)
235  complex(gwpc),ABI_CONTIGUOUS pointer :: phsgt(:),bigomegatwsq(:,:),omegatw(:,:)
236 ! *********************************************************************
237 
238  !@ppmodel_t
239  ! Save the index of the q-point for checking purpose.
240  PPm%iq_bz = iq_bz
241 
242  ! Here there is a problem with the small q, still cannot use BZ methods
243  iq_ibz=Qmesh%tab(iq_bz)
244  isym_q=Qmesh%tabo(iq_bz)
245  itim_q=(3-Qmesh%tabi(iq_bz))/2
246 
247  !call Qmesh%get_bz_item(iq_bz,qbz,iq_ibz,isym_q,itim_q,isirred=q_isirred)
248 
249  iq_curr=iq_ibz; if (PPm%mqmem==0) iq_curr=1
250 
251  grottb => Gsph%rottb (1:PPm%npwc,itim_q,isym_q)
252  phsgt  => Gsph%phmSGt(1:PPm%npwc,isym_q)
253 
254  bigomegatwsq => PPm%bigomegatwsq(iq_curr)%vals
255  omegatw      => PPm%omegatw(iq_curr)%vals
256 
257  ! Symmetrize the PPM parameters
258  SELECT CASE (PPm%model)
259  CASE (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
260    ! Plasmon pole frequencies otq are invariant under symmetry
261 !$omp parallel do private(isg1, isg2)
262    do jj=1,PPm%npwc
263      isg2 = grottb(jj)
264      do ii=1,PPm%npwc
265        isg1 = grottb(ii)
266        botsq(isg1,isg2) = bigomegatwsq(ii,jj)*phsgt(ii)*CONJG(phsgt(jj))
267        otq  (isg1,isg2) = omegatw(ii,jj)
268      end do
269    end do
270 
271  CASE (PPM_LINDEN_HORSH)
272    ! * For notations see pag 22 of Quasiparticle Calculations in solid (Aulbur et al)
273    !  If q_bz=Sq_ibz+G0 then:
274    !
275    ! $\omega^2_{ii}(q_bz) = \omega^2_{ii}(q)$        (otq array)
276    ! $\alpha_{ii}(q_bz)   = \alpha_{ii}(q)$          (botq array
277    ! $\Phi_{SG-G0}(q_bz)  = \Phi_{G}(q) e^{-iSG.t}$  (eigenvectors of e^{-1}, eig array)
278    !
279    do ii=1,PPm%npwc ! DM bands index
280      botsq(ii,1) = bigomegatwsq(ii,1)
281      otq  (ii,1) = omegatw     (ii,1)
282      do jj=1,PPm%npwc
283        eig(grottb(jj),ii) = PPm%eigpot(iq_curr)%vals(jj,ii) * phsgt(jj)
284      end do
285    end do
286    if (itim_q==2) eig=CONJG(eig) ! Time-reversal
287 
288  CASE (PPM_ENGEL_FARID)
289    ! * For notations see pag 23 of Quasiparticle Calculations in solid (Aulbur et al)
290    ! If q_bz=Sq_ibz+G0 then:
291    !
292    ! $\omega^2_{ii}(q_bz) = \omega^2_{ii}(q)$        (otq array)
293    ! $y_{SG-G0}(q_bz)     = y_{G}(q) e^{-iSG.t}$     (y=Lx)
294    !
295    do ii=1,PPm%npwc ! DM bands index
296      otq(ii,1) = omegatw(ii,1)
297      do jj=1,PPm%npwc
298        botsq(grottb(jj),ii) = bigomegatwsq(jj,ii)*phsgt(jj)
299      end do
300    end do
301 
302  CASE DEFAULT
303    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
304  END SELECT
305  !
306  ! * Take into account time-reversal symmetry.
307  if (itim_q==2) then
308 !$omp parallel workshare
309    botsq=CONJG(botsq)
310 !$omp end parallel workshare
311  end if
312 
313 end subroutine ppm_get_qbz

m_ppmodel/ppm_init [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_init

FUNCTION

  Initialize dimensions and other useful variables related to the PPmodel

INPUTS

 ppmodel=
 drude_plsmf=

SIDE EFFECTS

  PPm<ppmodel_t>=Arrays needed to store the ppmodel parameters are allocated with
   proper dimensions according to the plasmon-pole model.

SOURCE

532 subroutine ppm_init(PPm,mqmem,nqibz,npwe,ppmodel,drude_plsmf,invalid_freq)
533 
534 !Arguments ------------------------------------
535  integer,intent(in) :: mqmem,nqibz,npwe,ppmodel,invalid_freq
536  real(dp),intent(in) :: drude_plsmf
537  type(ppmodel_t),intent(out) :: PPm
538 
539 !Local variables-------------------------------
540 !scalars
541  integer :: dim_q,iq_ibz,ierr
542  logical :: ltest
543  !character(len=500) :: msg
544 ! *********************************************************************
545 
546  DBG_ENTER("COLL")
547 
548  !@ppmodel_t
549  call ppm_nullify(PPm)
550 
551  PPm%invalid_freq=invalid_freq
552  PPm%nqibz = nqibz
553  PPm%mqmem = mqmem
554  ltest = (PPm%mqmem==0.or.PPm%mqmem==PPm%nqibz)
555 ! write(std_out,'(a,I0)') ' PPm%mqmem = ',PPm%mqmem
556 ! write(std_out,'(a,I0)') ' PPm%nqibz = ',PPm%nqibz
557 ! ABI_CHECK(ltest,'Wrong value for mqmem')
558 
559  PPm%npwc        = npwe
560  PPm%model       = ppmodel
561  PPm%drude_plsmf = drude_plsmf
562  PPm%userho      = 0
563  if (ANY(ppmodel==(/PPM_HYBERTSEN_LOUIE, PPM_LINDEN_HORSH, PPM_ENGEL_FARID/))) PPm%userho=1
564 
565  ABI_MALLOC(PPm%keep_q,(nqibz))
566  PPm%keep_q=.FALSE.; if (PPm%mqmem>0) PPm%keep_q=.TRUE.
567 
568  ABI_MALLOC(PPm%has_q,(nqibz))
569  PPm%has_q=PPM_NOTAB
570  !
571  ! Full q-mesh is stored or out-of-memory solution.
572  dim_q=PPm%nqibz; if (PPm%mqmem==0) dim_q=1
573 
574  ABI_MALLOC(PPm%bigomegatwsq, (dim_q))
575  ABI_MALLOC(PPm%omegatw,(dim_q))
576  ABI_MALLOC(PPm%eigpot,(dim_q))
577 
578  SELECT CASE (PPm%model)
579 
580  CASE (PPM_NONE)
581    ABI_WARNING("Called with ppmodel==0")
582    PPm%dm2_botsq = 0
583    PPm%dm2_otq   = 0
584    PPm%dm_eig    = 0
585    RETURN
586 
587  CASE (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
588    PPm%dm2_botsq = PPm%npwc
589    PPm%dm2_otq   = PPm%npwc
590    PPm%dm_eig    = 1 ! Should be set to 0, but g95 doesnt like zero-sized arrays
591 
592  CASE (PPM_LINDEN_HORSH)
593    PPm%dm2_botsq = 1
594    PPm%dm2_otq   = 1
595    PPm%dm_eig    = PPm%npwc
596 
597  CASE (PPM_ENGEL_FARID)
598    PPm%dm2_botsq = PPm%npwc
599    PPm%dm2_otq   = 1
600    PPm%dm_eig    = 1 ! Should be set to 0, but g95 doesnt like zero-sized arrays
601 
602  CASE DEFAULT
603    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
604  END SELECT
605  !
606  ! Allocate tables depending on the value of keep_q.
607  do iq_ibz=1,dim_q
608    !%if (keep_q(iq_ibz)) then
609 #if 1
610    ABI_MALLOC_OR_DIE(PPm%bigomegatwsq(iq_ibz)%vals, (PPm%npwc,PPm%dm2_botsq), ierr)
611    ABI_MALLOC_OR_DIE(PPm%omegatw(iq_ibz)%vals, (PPm%npwc,PPm%dm2_otq), ierr)
612    ABI_MALLOC_OR_DIE(PPm%eigpot(iq_ibz)%vals, (PPm%dm_eig,PPm%dm_eig), ierr)
613    !%endif
614 #else
615    call ppm_mallocq(PPm,iq_ibz)
616 #endif
617    !%end if
618  end do
619 
620  DBG_EXIT("COLL")
621 
622 end subroutine ppm_init

m_ppmodel/ppm_mallocq [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_mallocq

FUNCTION

  Allocate the ppmodel tables for the selected q-point in the IBZ.

 INPUT
  iq_ibz=Index of the q-point in the IBZ.

SIDE EFFECTS

  PPm<ppmodel_t>=PPm tables are allocated.

SOURCE

458 subroutine ppm_mallocq(PPm,iq_ibz)
459 
460 !Arguments ------------------------------------
461  integer,intent(in) :: iq_ibz
462  type(ppmodel_t),intent(inout) :: PPm
463 
464 ! *********************************************************************
465 
466  !@ppmodel_t
467  ABI_MALLOC(PPm%bigomegatwsq(iq_ibz)%vals, (PPm%npwc,PPm%dm2_botsq))
468 
469  ABI_MALLOC(PPm%omegatw(iq_ibz)%vals, (PPm%npwc,PPm%dm2_otq))
470 
471  ABI_MALLOC(PPm%eigpot(iq_ibz)%vals, (PPm%dm_eig,PPm%dm_eig))
472 
473  PPm%has_q(iq_ibz) = PPM_TAB_ALLOCATED
474 
475 end subroutine ppm_mallocq

m_ppmodel/ppm_nullify [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_nullify

FUNCTION

  Nullify dynamic entities in a ppmodel_t object.

INPUTS

OUTPUT

SOURCE

331 subroutine ppm_nullify(PPm)
332 
333 !Arguments ------------------------------------
334  type(ppmodel_t),intent(inout) :: PPm
335 ! *********************************************************************
336 
337  !@ppmodel_t
338  ! types
339  nullify(Ppm%bigomegatwsq_qbz)
340  nullify(Ppm%omegatw_qbz)
341  nullify(Ppm%eigpot_qbz)
342 
343 end subroutine ppm_nullify

m_ppmodel/ppm_symmetrizer [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_symmetrizer

FUNCTION

  Symmetrize the plasmonpole matrix elements in the full BZ zone.

INPUTS

  iq_bz=Index of the q-point in the BZ where the PPmodel parameters are wanted.
  Gsph<gsphere_t>=data related to the G-sphere.
  Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
  Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
  iq_ibz=Index of the q-point in the BZ.
  npwe=number of G vectors for the correlation part
  nomega=number of frequencies in $\epsilon^{-1}$
  omega=frequencies in epsm1_ggw
  epsm1_ggw(npwe,npwe,nomega)=the inverse dielctric matrix
  ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
  gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
  nfftf=the number of points in the FFT mesh (for this processor)
  rhor_tot(nfftf)=the total charge in real space

SIDE EFFECTS

  PPm<ppmodel_t>=data type containing information on the plasmonpole technique.
  Internal tables are modified so that they (point|store) the plasmon-pole parameters
  for the specified q-point in the BZ.

SOURCE

2285 subroutine ppm_symmetrizer(PPm,iq_bz,Cryst,Qmesh,Gsph,npwe,nomega,omega,epsm1_ggw,nfftf,ngfftf,rhor_tot)
2286 
2287 !Arguments ------------------------------------
2288 !scalars
2289  integer,intent(in) :: nfftf,npwe,nomega,iq_bz
2290  type(crystal_t),intent(in) :: Cryst
2291  type(gsphere_t),intent(in) :: Gsph
2292  type(kmesh_t),intent(in) :: Qmesh
2293  type(ppmodel_t),target,intent(inout) :: PPm
2294 !arrays
2295  integer,intent(in) :: ngfftf(18)
2296  real(dp),intent(in) :: rhor_tot(nfftf)
2297  complex(dpc),intent(in) :: omega(nomega)
2298  complex(gwpc),intent(in) :: epsm1_ggw(npwe,npwe,nomega)
2299 
2300 !Local variables-------------------------------
2301 !scalars
2302  integer :: iq_ibz,itim_q,isym_q,iq_curr,ierr
2303  logical :: q_isirred
2304  !character(len=500) :: msg
2305 !arrays
2306  real(dp) :: qbz(3)
2307 ! *********************************************************************
2308 
2309  !@ppmodel_t
2310  !
2311  ! Save the index of the q-point in the BZ for checking purpose.
2312  PPm%iq_bz = iq_bz
2313  !
2314  ! Here there is a problem with the small q, still cannot use BZ methods
2315  !iq_ibz=Qmesh%tab(iq_bz)
2316  !isym_q=Qmesh%tabo(iq_bz)
2317  !itim_q=(3-Qmesh%tabi(iq_bz))/2
2318 
2319  call qmesh%get_bz_item(iq_bz,qbz,iq_ibz,isym_q,itim_q,isirred=q_isirred)
2320  iq_curr=iq_ibz; if (PPm%mqmem==0) iq_curr=1
2321  !
2322  ! =======================================================
2323  ! ==== Branching for in-core or out-of-core solution ====
2324  ! =======================================================
2325  !
2326  if (PPm%has_q(iq_ibz)==PPM_NOTAB) then
2327    ! Allocate the tables for this q_ibz
2328    call ppm_mallocq(PPm,iq_ibz)
2329  end if
2330 
2331  if (PPm%has_q(iq_ibz)==PPM_TAB_ALLOCATED) then
2332    ! Calculate the ppmodel tables for this q_ibz
2333    call new_setup_ppmodel(PPm,iq_ibz,Cryst,Qmesh,npwe,nomega,omega,epsm1_ggw,nfftf,Gsph%gvec,ngfftf,rhor_tot) !Optional
2334  end if
2335 
2336  if (q_isirred) then
2337    ! Symmetrization is not needed.
2338    if (PPm%bigomegatwsq_qbz_stat==PPM_ISALLOCATED)  then
2339      ABI_FREE(PPm%bigomegatwsq_qbz%vals)
2340    end if
2341    if (PPm%omegatw_qbz_stat==PPM_ISALLOCATED)  then
2342      ABI_FREE(PPm%omegatw_qbz%vals)
2343    end if
2344    if (PPm%eigpot_qbz_stat==PPM_ISALLOCATED)  then
2345      ABI_FREE(PPm%eigpot_qbz%vals)
2346    end if
2347 
2348    ! Point the data in memory and change the status.
2349    PPm%bigomegatwsq_qbz => PPm%bigomegatwsq(iq_ibz)
2350    PPm%bigomegatwsq_qbz_stat = PPM_ISPOINTER
2351 
2352    PPm%omegatw_qbz => PPm%omegatw(iq_ibz)
2353    PPm%omegatw_qbz_stat = PPM_ISPOINTER
2354 
2355    PPm%eigpot_qbz => PPm%eigpot(iq_ibz)
2356    PPm%eigpot_qbz_stat = PPM_ISPOINTER
2357  else
2358    ! Allocate memory if not done yet.
2359    if (PPm%bigomegatwsq_qbz_stat==PPM_ISPOINTER) then
2360       nullify(PPm%bigomegatwsq_qbz)
2361       ABI_MALLOC_OR_DIE(PPm%bigomegatwsq_qbz%vals, (PPm%npwc,PPm%dm2_botsq), ierr)
2362       PPm%bigomegatwsq_qbz_stat=PPM_ISALLOCATED
2363    end if
2364 
2365    if (PPm%omegatw_qbz_stat==PPM_ISPOINTER) then
2366       nullify(PPm%omegatw_qbz)
2367       ABI_MALLOC_OR_DIE(PPm%omegatw_qbz%vals,(PPm%npwc,PPm%dm2_otq), ierr)
2368       PPm%omegatw_qbz_stat=PPM_ISALLOCATED
2369    end if
2370 
2371    if (PPm%eigpot_qbz_stat==PPM_ISPOINTER) then
2372      nullify(PPm%eigpot_qbz)
2373      ABI_MALLOC_OR_DIE(PPm%eigpot_qbz%vals,(PPm%dm_eig,PPm%dm_eig), ierr)
2374      PPm%eigpot_qbz_stat=PPM_ISALLOCATED
2375    end if
2376    !
2377    ! Calculate new table for this q-point in the BZ.
2378    ! Beware: Dimensions should not change.
2379    !botsq => PPm%bigomegatwsq_qbz%vals
2380    !otq   => PPm%omegatw_qbz%vals
2381    !eig   => PPm%eigpot_qbz%vals
2382 
2383    call ppm_get_qbz(PPm,Gsph,Qmesh,iq_bz,PPm%bigomegatwsq_qbz%vals,&
2384 &    PPm%omegatw_qbz%vals,PPm%eigpot_qbz%vals)
2385 
2386    ! Release the table in the IBZ if required.
2387    if (.not.PPm%keep_q(iq_ibz)) call ppm_table_free(PPm,iq_ibz)
2388  end if
2389 
2390 end subroutine ppm_symmetrizer

m_ppmodel/ppm_table_free [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

  ppm_table_free

FUNCTION

  Free the ppmodel tables for the selected q-point in the IBZ.

 INPUT
  iq_ibz=Index of the q-point in the IBZ.

SIDE EFFECTS

  PPm<ppmodel_t>=PPm tables are deallocated.

SOURCE

495 subroutine ppm_table_free(PPm,iq_ibz)
496 
497 !Arguments ------------------------------------
498  integer,intent(in) :: iq_ibz
499  type(ppmodel_t),intent(inout) :: PPm
500 
501 ! *********************************************************************
502 
503  !@ppmodel_t
504  if (allocated(PPm%bigomegatwsq)) call array_free(PPm%bigomegatwsq(iq_ibz))
505  if (allocated(PPm%omegatw)) call array_free(PPm%omegatw(iq_ibz))
506  if (allocated(PPm%eigpot)) call array_free(PPm%eigpot(iq_ibz))
507 
508  PPm%has_q(iq_ibz) = PPM_NOTAB
509 
510 end subroutine ppm_table_free

m_ppmodel/ppm_times_ket [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 ppm_times_ket

FUNCTION

  Calculate the contribution to self-energy operator using a plasmon-pole model.

INPUTS

  nomega=Number of frequencies.
  nspinor=Number of spinorial components.
  npwc=Number of G vectors in the plasmon pole.
  npwx=number of G vectors in rhotwgp, i.e. no. of G-vectors for the exchange part.
  theta_mu_minus_e0i= $\theta(\mu-\epsilon_{k-q,b1,s}), defines if the state is occupied or not
  zcut=Small imaginary part to avoid the divergence. (see related input variable)
  omegame0i(nomega)=Frequencies used to evaluate \Sigma_c ($\omega$ - $\epsilon_i)$
  PPm<ppmodel_t>=structure gathering info on the Plasmon-pole technique.
     %model=type plasmon pole model
     %dm2_botsq= 1 if model==3, =npwc if model== 4, 1 for all the other cases
     %dm2_otq= 1 if model==3, =1    if model== 4, 1 for all the other cases
     %dm_eig=npwc if model=3, 0 otherwise
     %botsq(npwc,dm2_botsq)=Plasmon pole parameters for this q-point.
     %eig(dm_eig,dm_eig)=The eigvectors of the symmetrized inverse dielectric matrix for this q point
       (first index for G, second index for bands)
     %otq(npwc,dm2_otq)=Plasmon pole parameters for this q-point.
  rhotwgp(npwx)=oscillator matrix elements divided by |q+G| i.e.
    $\frac{\langle b1 k-q s | e^{-i(q+G)r | b2 k s \rangle}{|q+G|}$

OUTPUT

  sigcme(nomega) (to be described), only relevant if ppm3 or ppm4
  ket(npwc,nomega):
   === model==1,2 ====

   ket(G,omega) = Sum_G2       conjg(rhotw(G)) * Omega(G,G2) * rhotw(G2)
                          ---------------------------------------------------
                            2 omegatw(G,G2) (omega-E_i + omegatw(G,G2)(2f-1))

SOURCE

2556 subroutine ppm_times_ket(PPm,nspinor,npwc,nomega,rhotwgp,omegame0i,zcut,theta_mu_minus_e0i,npwx,ket,sigcme)
2557 
2558 !Arguments ------------------------------------
2559 !scalars
2560  integer,intent(in) :: nomega,npwc,npwx,nspinor
2561  real(dp),intent(in) :: theta_mu_minus_e0i,zcut
2562  type(ppmodel_t),intent(in) :: PPm
2563 !arrays
2564  real(dp),intent(in) :: omegame0i(nomega)
2565  complex(gwpc),intent(in) :: rhotwgp(npwx*nspinor)
2566  complex(gwpc),intent(inout) :: ket(npwc*nspinor,nomega)
2567  complex(gwpc),intent(out) :: sigcme(nomega)
2568 
2569 !Local variables-------------------------------
2570 !scalars
2571  integer :: ig,igp,ii,ios,ispinor,spadc,spadx
2572  real(dp) :: den,ff,inv_den,omegame0i_io,otw,twofm1,twofm1_zcut
2573  complex(gwpc) :: ct,num,numf,rhotwgdp_igp
2574  logical :: fully_occupied,totally_empty
2575 !arrays
2576  complex(gwpc),allocatable :: rhotwgdpcc(:)
2577  complex(gwpc), ABI_CONTIGUOUS pointer :: botsq(:,:),eig(:,:),otq(:,:)
2578 
2579 !*************************************************************************
2580 
2581  SELECT CASE (PPm%model)
2582  CASE (PPM_GODBY_NEEDS, PPM_HYBERTSEN_LOUIE)
2583    botsq  => PPm%bigomegatwsq_qbz%vals !(1:npwc,1:PPm%dm2_botsq)
2584    otq    => PPm%omegatw_qbz%vals      !(1:npwc,1:PPm%dm2_otq)
2585    fully_occupied =(ABS(theta_mu_minus_e0i-one)<0.001)
2586    totally_empty  =(ABS(theta_mu_minus_e0i    )<0.001)
2587 
2588    do ispinor=1,nspinor
2589      spadx=(ispinor-1)*npwx; spadc=(ispinor-1)*npwc
2590 
2591      if (.not.totally_empty) then
2592        ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(\mu-e_s) / (\omega+\omegat_{G1G2}-e_s-i\delta)
2593        twofm1_zcut=zcut
2594 !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den)
2595        do ios=1,nomega
2596          omegame0i_io=omegame0i(ios)
2597          do igp=1,npwc
2598            rhotwgdp_igp=rhotwgp(spadx+igp)
2599            do ig=1,npwc
2600              otw=DBLE(otq(ig,igp)) !in principle otw -> otw - ieta
2601              num = botsq(ig,igp)*rhotwgdp_igp
2602              den = omegame0i_io+otw
2603              if (den**2>zcut**2) then
2604                ket(spadc+ig,ios)=ket(spadc+ig,ios) + num/(den*otw)*theta_mu_minus_e0i
2605              else
2606                ket(spadc+ig,ios)=ket(spadc+ig,ios) + &
2607 &                num*CMPLX(den,twofm1_zcut)/((den**2+twofm1_zcut**2)*otw)*theta_mu_minus_e0i
2608              end if
2609            end do !ig
2610          end do !igp
2611        end do !ios
2612      end if !not totally empty
2613 
2614      if (.not.(fully_occupied)) then
2615        ! \Bomega^2_{G1G2}/\omegat_{G1G2} M_{G1,G2}. \theta(e_s-\mu) / (\omega-\omegat_{G1G2}-e_s+i\delta)
2616        twofm1_zcut=-zcut
2617 !$omp parallel do private(omegame0i_io, rhotwgdp_igp, otw, num, den)
2618        do ios=1,nomega
2619          omegame0i_io=omegame0i(ios)
2620          do igp=1,npwc
2621            rhotwgdp_igp=rhotwgp(spadx+igp)
2622            do ig=1,npwc
2623              otw=DBLE(otq(ig,igp)) !in principle otw -> otw - ieta
2624              num = botsq(ig,igp)*rhotwgdp_igp
2625              den=omegame0i_io-otw
2626              if (den**2>zcut**2) then
2627                ket(spadc+ig,ios)=ket(spadc+ig,ios) + num/(den*otw)*(one-theta_mu_minus_e0i)
2628              else
2629                ket(spadc+ig,ios)=ket(spadc+ig,ios) + &
2630 &               num*CMPLX(den,twofm1_zcut)/((den**2+twofm1_zcut**2)*otw)*(one-theta_mu_minus_e0i)
2631              end if
2632            end do !ig
2633          end do !igp
2634        end do !ios
2635      end if !not fully occupied
2636 
2637    end do !ispinor
2638 
2639 !$omp parallel workshare
2640    ket=ket*half
2641 !$omp end parallel workshare
2642 
2643  CASE (PPM_LINDEN_HORSH,PPM_ENGEL_FARID)
2644    ABI_CHECK(nspinor == 1, "nspinor/=1 not allowed")
2645 
2646    botsq => PPm%bigomegatwsq_qbz%vals !(1:npwc,1:PPm%dm2_botsq)
2647    otq   => PPm%omegatw_qbz%vals      !(1:npwc,1:PPm%dm2_otq)
2648    eig   => PPm%eigpot_qbz%vals       !(1:PPm%dm_eig,1:PPm%dm_eig)
2649 
2650    ! rho-twiddle(G) is formed, introduce rhotwgdpcc, for speed reason
2651    ABI_MALLOC(rhotwgdpcc,(npwx))
2652 
2653    ff=theta_mu_minus_e0i      ! occupation number f (include poles if ...)
2654    twofm1=two*ff-one          ! 2f-1
2655    twofm1_zcut=twofm1*zcut
2656    rhotwgdpcc(:)=CONJG(rhotwgp(:))
2657 
2658    do ios=1,nomega
2659      omegame0i_io=omegame0i(ios)
2660      ct=czero_gw
2661      do ii=1,npwc ! Loop over the DM bands
2662        num=czero_gw
2663 
2664        SELECT CASE (PPm%model)
2665        CASE (PPM_LINDEN_HORSH)
2666          ! Calculate \beta (eq. 106 pag 47)
2667          do ig=1,npwc
2668            num=num+rhotwgdpcc(ig)*eig(ig,ii)
2669          end do
2670          numf=num*CONJG(num) !MG this means that we cannot do SCGW
2671          numf=numf*botsq(ii,1)
2672 
2673        CASE (PPM_ENGEL_FARID)
2674          do ig=1,npwc
2675            num=num+rhotwgdpcc(ig)*botsq(ig,ii)
2676          end do
2677          numf=num*CONJG(num) !MG this means that we cannot do SCGW
2678 
2679        CASE DEFAULT
2680          ABI_ERROR("Wrong PPm%model")
2681        END SELECT
2682 
2683        !numf=num*CONJG(num) !MG this means that we cannot do SCGW
2684        !if (PPm%model==3) numf=numf*botsq(ii,1)
2685 
2686        otw=DBLE(otq(ii,1)) ! in principle otw -> otw - ieta
2687        den=omegame0i_io+otw*twofm1
2688 
2689        if (den**2>zcut**2) then
2690          inv_den=one/den
2691          ct=ct+numf*inv_den
2692        else
2693          inv_den=one/((den**2+twofm1_zcut**2))
2694          ct=ct+numf*CMPLX(den,twofm1_zcut)*inv_den
2695        end if
2696 
2697      end do !ii DM bands
2698      sigcme(ios)=ct*half
2699    end do !ios
2700    ABI_FREE(rhotwgdpcc)
2701 
2702  CASE DEFAULT
2703    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
2704  END SELECT
2705 
2706 end subroutine ppm_times_ket

m_ppmodel/ppmodel_t [ Types ]

[ Top ] [ m_ppmodel ] [ Types ]

NAME

 ppmodel_t

FUNCTION

  For the GW part of ABINIT, this structure datatype gathers all
  the information on the Plasmonpole technique used in the calculations

NOTES

  If you modify this datatype, please check there there is no creation/destruction/copy routine,
  declared in another part of ABINIT, that might need to take into account your modification.
  Procedures that should be modified to reflect the changes done in the datatype have the tag @ppmodel_t.

SOURCE

 82  type,public :: ppmodel_t
 83 
 84    !integers
 85    integer :: dm2_botsq
 86    ! =npwc if ppmodel=1,2; =1 if ppmodel=3,4
 87 
 88    integer :: dm_eig
 89    ! =npwc if ppmodel=3;   =0 if ppmodel=1,2,4
 90 
 91    integer :: dm2_otq
 92    ! =npwc if ppmodel=1,2; =1 if ppmodel=3,4
 93 
 94    integer :: invalid_freq
 95    ! what to do when PPM frequencies are invalid
 96 
 97    integer :: model
 98    ! The type of Plasmonpole model
 99 
100    integer :: mqmem
101    ! =nqibz if in-core solutions, =0 for out-of-core for which the last dimension in the PPm arrays has size 1.
102 
103    integer :: nqibz
104    ! Number of q-points in the IBZ
105 
106    integer :: npwc
107    ! Number of G vectors in $\tilde \epsilon $
108 
109    integer :: userho
110    ! 1 if the ppmodel requires rho(G).
111 
112    integer :: iq_bz=0
113    ! The index of the q-point in the BZ that is referenced by the internal pointer.
114 
115    integer :: bigomegatwsq_qbz_stat = PPM_ISPOINTER
116    ! Status of bigomegatwsq.
117 
118    integer :: omegatw_qbz_stat = PPM_ISPOINTER
119    ! Status of omegatw_qbz.
120 
121    integer :: eigpot_qbz_stat = PPM_ISPOINTER
122    ! Status of new_eigpot_qbz_stat.
123 
124    real(dp) :: drude_plsmf
125    ! Drude plasma frequency
126 
127    real(dp) :: force_plsmf=zero
128    ! Force plasma frequency to that set by ppmfreq (not used if set zero).
129 
130    ! arrays
131    logical,allocatable :: keep_q(:)
132    ! .TRUE. if the ppmodel tables for this q in the IBZ are kept in memory.
133 
134    integer,allocatable :: has_q(:)
135    ! Flag defining the status of the tables for the different q. See the PPM_TAB flags.
136 
137    type(array2_gwpc_t),pointer :: bigomegatwsq_qbz   => null()
138    ! (Points|Stores) the symmetrized plasmon pole parameters $\tilde\Omega^2_{G Gp}(q_bz)$.
139 
140    type(array2_gwpc_t),pointer :: omegatw_qbz  => null()
141    ! (Points|Stores) the symmetrized plasmon pole parameters $\tilde\omega_{G Gp}(q_bz)$.
142 
143    type(array2_gwpc_t),pointer :: eigpot_qbz   => null()
144    ! (Points|Stores) the eigvectors of the symmetrized inverse dielectric matrix
145 
146    type(array2_gwpc_t),allocatable :: bigomegatwsq(:)
147    ! bigomegatwsq(nqibz)%value(npwc,dm2_botsq)
148    ! Plasmon pole parameters $\tilde\Omega^2_{G Gp}(q)$.
149 
150    type(array2_gwpc_t),allocatable :: omegatw(:)
151    ! omegatw(nqibz)%value(npwc,dm2_otq)
152    ! Plasmon pole parameters $\tilde\omega_{G Gp}(q)$.
153 
154    type(array2_gwpc_t),allocatable :: eigpot(:)
155    ! eigpot(nqibz)%value(dm_eig,dm_eig)
156    ! Eigvectors of the symmetrized inverse dielectric matrix
157 
158  end type ppmodel_t
159 
160  public :: ppm_get_qbz              ! Symmetrize the PPm parameters in the BZ.
161  public :: ppm_nullify              ! Nullify all pointers
162  public :: ppm_init                 ! Initialize dimensions and pointers
163  public :: ppm_free                 ! Destruction method.
164  public :: setup_ppmodel            ! Main Driver
165  public :: new_setup_ppmodel        ! Main Driver
166  public :: getem1_from_PPm          ! Reconstruct e^{-1}(w) from PPm.
167  public :: getem1_from_PPm_one_ggp  ! Reconstruct e^{-1}(w) from PPm for one G,G' pair
168  public :: get_ppm_eigenvalues
169  public :: calc_sig_ppm             ! Matrix elements of the self-energy with ppmodel.
170  public :: ppm_times_ket            ! Matrix elements of the self-energy with ppmodel.
171  public :: ppm_symmetrizer
172  public :: cqratio

m_ppmodel/setup_ppmodel [ Functions ]

[ Top ] [ m_ppmodel ] [ Functions ]

NAME

 setup_ppmodel

FUNCTION

  Initialize some values of several arrays of the PPm datastructure
  that are used in case of plasmonpole calculations
  This is a wrapper around different plasmonpole routines.

INPUTS

  Cryst<crystal_t>=Info on the unit cell and crystal symmetries.
  Qmesh<kmesh_t>=the q-mesh used for the inverse dielectric matrix
    %nibz=number of irreducible q-points
    %ibz(3,%nibz)=the irred q-point
  npwe=number of G vectors for the correlation part
  nomega=number of frequencies in $\epsilon^{-1}$
  omega=frequencies in epsm1
  epsm1=the inverse dielctric matrix
  ngfftf(18)=contain all needed information about the 3D fine FFT mesh, see ~abinit/doc/variables/vargs.htm#ngfft
  gprimd(3,3)=dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
  nfftf=the number of points in the FFT mesh (for this processor)
  rhor_tot(nfftf)=the total charge in real space
  PPm<ppmodel_t>:
    %ppmodel=the type of  plasmonpole model

OUTPUT

SIDE EFFECTS

  PPm<ppmodel_t>:
  == if ppmodel 1 or 2 ==
   %omegatw and %bigomegatwsq
  == if ppmodel 3 ==
   %omegatw, %bigomegatwsq and %eigpot
  == if ppmodel 4 ==
   %omegatw and %bigomegatwsq

NOTES

 * FFT parallelism not implemented.
 * TODO: rhor_tot should be replaced by rhog_tot

SOURCE

669 subroutine setup_ppmodel(PPm,Cryst,Qmesh,npwe,nomega,omega,epsm1,nfftf,gvec,ngfftf,rhor_tot,&
670 & iqiA) !Optional
671 
672 !Arguments ------------------------------------
673 !scalars
674  integer,intent(in) :: nfftf,npwe,nomega
675  integer,intent(in),optional :: iqiA
676  type(kmesh_t),intent(in) :: Qmesh
677  type(crystal_t),intent(in) :: Cryst
678  type(ppmodel_t),intent(inout) :: PPm
679 !arrays
680  integer,intent(in) :: gvec(3,npwe),ngfftf(18)
681  real(dp),intent(in) :: rhor_tot(nfftf)
682  complex(dpc),intent(in) :: omega(nomega)
683  complex(gwpc),intent(in) :: epsm1(:,:,:,:)
684 
685 !Local variables-------------------------------
686 !scalars
687  integer :: nqiA,iq_ibz
688  real(dp) :: n_at_G_zero
689  logical :: single_q
690  character(len=500) :: msg
691 !scalars
692  real(dp) :: qpt(3)
693 ! *************************************************************************
694 
695  DBG_ENTER("COLL")
696 
697  !@ppmodel_t
698  !
699  ! === if iqiA is present, then consider only one qpoint to save memory ===
700  ! * This means the object has been already initialized
701  nqiA=Qmesh%nibz; single_q=.FALSE.
702  if (PRESENT(iqiA)) then
703    nqiA=1; single_q=.TRUE.
704  end if
705  !
706  ! Allocate plasmonpole parameters
707  ! TODO ppmodel==1 by default, should be set to 0 if AC and CD
708  SELECT CASE (PPm%model)
709 
710  CASE (PPM_NONE)
711    ABI_COMMENT(' Skipping Plasmompole model calculation')
712 
713  CASE (PPM_GODBY_NEEDS)
714    ! * Note: the q-dependency enters only through epsilon^-1.
715    do iq_ibz=1,nqiA
716      call cppm1par(npwe,nomega,omega,PPm%drude_plsmf,&
717 &       epsm1(:,:,:,iq_ibz),PPm%omegatw(iq_ibz)%vals,PPm%bigomegatwsq(iq_ibz)%vals)
718    end do
719 
720  CASE (PPM_HYBERTSEN_LOUIE)
721    do iq_ibz=1,nqiA
722      qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
723 
724      call cppm2par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,Cryst%gmet,&
725 &      PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals,PPm%invalid_freq)
726    end do
727    !
728    ! Quick-and-dirty change of the plasma frequency. Never executed in standard runs.
729    if (PPm%force_plsmf>tol6) then ! Integrate the real-space density
730       n_at_G_zero = SUM(rhor_tot(:))/nfftf
731       ! Change the prefactor
732       write(msg,'(2(a,es16.8))') 'Forced ppmfreq:',PPm%force_plsmf*Ha_eV,' nelec/ucvol:',n_at_G_zero
733       ABI_WARNING(msg)
734       PPm%force_plsmf = (PPm%force_plsmf**2)/(four_pi*n_at_G_zero)
735       do iq_ibz=1,PPm%nqibz
736         PPm%bigomegatwsq(iq_ibz)%vals = PPm%force_plsmf * PPm%bigomegatwsq(iq_ibz)%vals
737         PPm%omegatw(iq_ibz)%vals      = PPm%force_plsmf * PPm%omegatw(iq_ibz)%vals
738       end do
739       write(msg,'(a,es16.8)') 'Plasma frequency forced in HL ppmodel, new prefactor is:',PPm%force_plsmf
740       ABI_WARNING(msg)
741    end if
742 
743  CASE (PPM_LINDEN_HORSH) ! TODO Check better double precision, this routine is in a messy state
744    do iq_ibz=1,nqiA
745      qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
746 
747      call cppm3par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
748 &      PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals(:,1),PPm%eigpot(iq_ibz)%vals)
749    end do
750 
751  CASE (PPM_ENGEL_FARID)  ! TODO Check better double precision, this routine is in a messy state
752    do iq_ibz=1,nqiA
753      qpt = Qmesh%ibz(:,iq_ibz); if (single_q) qpt=Qmesh%ibz(:,iqiA)
754      if ((ALL(ABS(qpt)<1.0e-3))) qpt = GW_Q0_DEFAULT ! FIXME
755 
756      call cppm4par(qpt,npwe,epsm1(:,:,1,iq_ibz),ngfftf,gvec,Cryst%gprimd,rhor_tot,nfftf,&
757 &      PPm%bigomegatwsq(iq_ibz)%vals,PPm%omegatw(iq_ibz)%vals(:,1))
758    end do
759 
760  CASE DEFAULT
761    ABI_BUG(sjoin('Wrong PPm%model:',itoa(PPm%model)))
762  END SELECT
763 
764  DBG_EXIT("COLL")
765 
766 end subroutine setup_ppmodel