TABLE OF CONTENTS
- ABINIT/m_exc_spectra
- m_exc_spectra/build_spectra
- m_exc_spectra/check_fsumrule
- m_exc_spectra/check_kramerskronig
- m_exc_spectra/exc_eps_coupling
- m_exc_spectra/exc_eps_resonant
- m_exc_spectra/exc_eps_rpa
- m_exc_spectra/exc_write_data
- m_exc_spectra/exc_write_tensor
- m_exc_spectra/mdfs_ncwrite
ABINIT/m_exc_spectra [ Modules ]
NAME
m_exc_spectra
FUNCTION
Routines to compute the macroscopic dielectric function in the Bethe-Salpeter code.
COPYRIGHT
Copyright (C) 2009-2024 ABINIT and EXC groups (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi, Y. Gillet) 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
16 #if defined HAVE_CONFIG_H 17 #include "config.h" 18 #endif 19 20 #include "abi_common.h" 21 22 MODULE m_exc_spectra 23 24 use defs_basis 25 use m_bs_defs 26 use m_abicore 27 use, intrinsic :: iso_c_binding 28 use m_xmpi 29 use m_errors 30 use m_nctk 31 use netcdf 32 use m_ebands 33 use m_hdr 34 35 use defs_datatypes, only : pseudopotential_type, ebands_t 36 use m_io_tools, only : open_file 37 use m_fstrings, only : toupper, strcat, sjoin, int2char4 38 use m_numeric_tools, only : simpson_int, simpson_cplx 39 use m_hide_blas, only : xdotu,xdotc 40 use m_special_funcs, only : gaussian 41 use m_crystal, only : crystal_t 42 use m_bz_mesh, only : kmesh_t 43 use m_eprenorms, only : eprenorms_t, renorm_bst 44 use m_pawtab, only : pawtab_type 45 use m_paw_hr, only : pawhur_t 46 use m_wfd, only : wfdgw_t 47 !use m_bse_io, only : exc_amplitude 48 use m_wfd_optic, only : calc_optical_mels 49 50 implicit none 51 52 private 53 54 public :: build_spectra ! Driver routine for the computation of optical spectra. 55 public :: exc_write_data ! This routine drives the writing of the files produced by the Bethe-Salpeter code. 56 public :: exc_eps_rpa ! Build epsilon within RPA and GW. 57 public :: mdfs_ncwrite ! Writes the MDF.nc file with the final results. 58 public :: exc_write_tensor ! Write of complex dielectric tensor 59 !public :: exc_eps_resonant ! Build the macroscopic dielectric function with excitonic effects.
m_exc_spectra/build_spectra [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
build_spectra
FUNCTION
Driver routine for the computation of optical spectra.
INPUTS
usepaw=1 for PAW calculations, 0 otherwise. drude_plsmf=Drude plasma frequency. Bsp<excparam>=Data type gathering the paramenters used for the Bethe-Salpeter calculation. inclvkb=If different from 0, [Vnl,r] is included in the calculation of the matrix elements of the velocity operator. BS_files<excfiles>=filenames used in the Bethe-Salpeter part. Kmesh<kmesh_t>=the k-point sampling for the wave functions. Cryst<crystal_t>=Structure defining the crystalline structure. KS_BSt=The KS energies. QP_BSt=The QP energies. Psps <pseudopotential_type>=variables related to pseudopotentials. Pawtab(Cryst%ntypat*usepaw)<pawtab_type>=PAW tabulated starting data Hur(Cryst%natom*usepaw)<pawhur_t>=Only for PAW and DFT+U, quantities used to evaluate the commutator [H_u,r]. Wfd<wfdgw_t>=Handler for the wavefunctions. nsppol=Number of independent spin polarizations. nspinor=Number of spinorial components. comm=MPI communicator.
OUTPUT
No output. The routine calls specialized routines where the computation and the output of the spectra is done.
SOURCE
94 subroutine build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm,Epren) 95 96 !Arguments ------------------------------------ 97 !scalars 98 integer,intent(in) :: comm 99 real(dp),intent(in) :: drude_plsmf 100 type(excparam),intent(in) :: BSp 101 type(excfiles),intent(in) :: BS_files 102 type(pseudopotential_type),intent(in) :: Psps 103 type(kmesh_t),intent(in) :: Kmesh 104 type(crystal_t),intent(in) :: Cryst 105 type(ebands_t),intent(in) :: KS_BSt,QP_BSt 106 type(wfdgw_t),intent(inout) :: Wfd 107 type(eprenorms_t),optional,intent(in) :: Epren 108 !arrays 109 type(pawtab_type),intent(in) :: Pawtab(Cryst%ntypat*Wfd%usepaw) 110 type(pawhur_t),intent(in) :: Hur(Cryst%natom*Wfd%usepaw) 111 112 !Local variables ------------------------------ 113 !scalars 114 integer :: my_rank,master,iq,io,nsppol,lomo_min,max_band,ncid 115 integer :: itemp,ntemp 116 logical :: do_ep_renorm 117 real(dp) :: omegaev 118 complex(dpc) :: ks_avg,gw_avg,exc_avg 119 character(len=4) :: ts 120 character(len=fnlen) :: path,prefix 121 character(len=fnlen) :: filbseig, ost_fname 122 !character(len=500) :: msg 123 type(ebands_t) :: EPBSt, EP_QPBSt 124 !arrays 125 real(dp),allocatable :: dos_exc(:),dos_gw(:),dos_ks(:) 126 complex(dpc),allocatable :: eps_rpanlf(:,:),eps_gwnlf(:,:) 127 complex(dpc),allocatable :: eps_exc(:,:),opt_cvk(:,:,:,:,:) 128 129 !************************************************************************ 130 131 my_rank = Wfd%my_rank 132 master = Wfd%master 133 nsppol = Wfd%nsppol 134 135 do_ep_renorm = .False. 136 ntemp = 1 137 if (BSp%do_ep_renorm .and. PRESENT(Epren)) then 138 do_ep_renorm = .True. 139 ntemp = Epren%ntemp 140 end if 141 142 ! 143 ! ===================================================== 144 ! === Calculate fcv(k)=<c k s|e^{-iqr}|v k s> in BZ === 145 ! ===================================================== 146 lomo_min=Bsp%lomo_min; max_band=Bsp%nbnds 147 ABI_MALLOC(opt_cvk,(lomo_min:max_band,lomo_min:max_band,BSp%nkbz,nsppol,BSp%nq)) 148 149 do iq=1,BSp%nq 150 call calc_optical_mels(Wfd,Kmesh,KS_BSt,Cryst,Psps,Pawtab,Hur,BSp%inclvkb,Bsp%lomo_spin,lomo_min,max_band,& 151 & BSp%nkbz,BSp%q(:,iq),opt_cvk(:,:,:,:,iq)) 152 end do 153 ! 154 ! ============================ 155 ! ==== Make EPS EXCITONIC ==== 156 ! ============================ 157 if (my_rank==master) then ! Only master works. 158 159 ABI_MALLOC(eps_exc,(BSp%nomega,BSp%nq)) 160 ABI_MALLOC(dos_exc,(BSp%nomega)) 161 162 ABI_MALLOC(eps_rpanlf,(BSp%nomega,BSp%nq)) 163 ABI_MALLOC(dos_ks,(BSp%nomega)) 164 165 ABI_MALLOC(eps_gwnlf ,(BSp%nomega,BSp%nq)) 166 ABI_MALLOC(dos_gw,(BSp%nomega)) 167 168 do itemp = 1, ntemp 169 170 call int2char4(itemp,ts) 171 172 if(do_ep_renorm) then 173 prefix = TRIM("_T") // ts 174 else 175 prefix = "" 176 end if 177 178 ost_fname = strcat(BS_files%out_basename,prefix,"_EXC_OST") 179 180 !TODO for RPA 181 call ebands_copy(KS_BST, EPBSt) 182 call ebands_copy(QP_BST, EP_QPBSt) 183 184 if (BS_files%in_eig /= BSE_NOFILE) then 185 filbseig = strcat(BS_files%in_eig,prefix) 186 else 187 filbseig = strcat(BS_files%out_eig,prefix) 188 end if 189 190 if(do_ep_renorm) then 191 ! No scissor with KSBST 192 call renorm_bst(Epren, EPBSt, Cryst, itemp, do_lifetime=.TRUE.,do_check=.TRUE.) 193 194 call renorm_bst(Epren, EP_QPBSt, Cryst, itemp, do_lifetime=.TRUE.,do_check=.FALSE.) 195 end if 196 197 198 if (BSp%use_coupling==0) then 199 call exc_eps_resonant(BSp,filbseig,ost_fname,lomo_min,max_band,BSp%nkbz,nsppol,opt_cvk,& 200 & Cryst%ucvol,BSp%nomega,BSp%omega,eps_exc,dos_exc,elph_lifetime=do_ep_renorm) 201 else 202 call exc_eps_coupling(Bsp,BS_files,lomo_min,max_band,BSp%nkbz,nsppol,opt_cvk,& 203 & Cryst%ucvol,BSp%nomega,BSp%omega,eps_exc,dos_exc) 204 end if 205 ! 206 ! ======================================================= 207 ! === Make EPS RPA and GW without local-field effects === 208 ! ======================================================= 209 call wrtout(std_out," Calculating RPA NLF and QP NLF epsilon","COLL") 210 211 call exc_eps_rpa(BSp%nbnds,BSp%lomo_spin,Bsp%lomo_min,BSp%homo_spin,Kmesh,EPBSt,BSp%nq,nsppol,opt_cvk,& 212 & Cryst%ucvol,BSp%broad,BSp%nomega,BSp%omega,eps_rpanlf,dos_ks) 213 214 call exc_eps_rpa(BSp%nbnds,BSp%lomo_spin,Bsp%lomo_min,BSp%homo_spin,Kmesh,EP_QPBSt,BSp%nq,nsppol,opt_cvk,& 215 & Cryst%ucvol,Bsp%broad,BSp%nomega,BSp%omega,eps_gwnlf,dos_gw) 216 ! 217 ! ========================= 218 ! === Write out Epsilon === 219 ! ========================= 220 !this is just for the automatic tests, It will be removed when fldiff 221 !will be able to compare two optical spectral 222 write(ab_out,*)" " 223 write(ab_out,*)"Macroscopic dielectric function:" 224 write(ab_out,*)"omega [eV] <KS_RPA_nlf> <GW_RPA_nlf> <BSE> " 225 do io=1,MIN(10,BSp%nomega) 226 omegaev = REAL(BSp%omega(io))*Ha_eV 227 ks_avg = SUM( eps_rpanlf(io,:)) / Bsp%nq 228 gw_avg = SUM( eps_gwnlf (io,:)) / Bsp%nq 229 exc_avg = SUM( eps_exc (io,:)) / Bsp%nq 230 write(ab_out,'(7f9.4)')omegaev,ks_avg,gw_avg,exc_avg 231 end do 232 write(ab_out,*)" " 233 234 ! 235 ! Master node writes final results on file. 236 call exc_write_data(BSp,BS_files,"RPA_NLF_MDF",eps_rpanlf,prefix=prefix,dos=dos_ks) 237 238 call exc_write_data(BSp,BS_files,"GW_NLF_MDF",eps_gwnlf,prefix=prefix,dos=dos_gw) 239 240 call exc_write_data(BSp,BS_files,"EXC_MDF",eps_exc,prefix=prefix,dos=dos_exc) 241 242 call wrtout(std_out," Checking Kramers Kronig on Excitonic Macroscopic Epsilon","COLL") 243 call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_exc(:,1)) 244 245 call wrtout(std_out," Checking Kramers Kronig on RPA NLF Macroscopic Epsilon","COLL") 246 call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_rpanlf(:,1)) 247 248 call wrtout(std_out," Checking Kramers Kronig on GW NLF Macroscopic Epsilon","COLL") 249 call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_gwnlf(:,1)) 250 251 call wrtout(std_out," Checking f-sum rule on Excitonic Macroscopic Epsilon","COLL") 252 253 if (BSp%exchange_term>0) then 254 ABI_COMMENT(' f-sum rule should be checked without LF') 255 end if 256 call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_exc(:,1)),drude_plsmf) 257 258 call wrtout(std_out," Checking f-sum rule on RPA NLF Macroscopic Epsilon","COLL") 259 call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_rpanlf(:,1)),drude_plsmf) 260 261 call wrtout(std_out," Checking f-sum rule on GW NLF Macroscopic Epsilon","COLL") 262 call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_gwnlf(:,1)),drude_plsmf) 263 264 path = strcat(BS_files%out_basename, strcat(prefix,"_MDF.nc")) 265 NCF_CHECK_MSG(nctk_open_create(ncid, path, xmpi_comm_self), sjoin("Creating MDF file:", path)) 266 NCF_CHECK(cryst%ncwrite(ncid)) 267 NCF_CHECK(ebands_ncwrite(QP_BSt, ncid)) 268 ! Write dielectric functions. 269 call mdfs_ncwrite(ncid, Bsp, eps_exc,eps_rpanlf,eps_gwnlf) 270 NCF_CHECK(nf90_close(ncid)) 271 272 !TODO 273 call ebands_free(EPBSt) 274 call ebands_free(EP_QPBSt) 275 276 end do 277 278 ABI_FREE(eps_rpanlf) 279 ABI_FREE(eps_gwnlf) 280 ABI_FREE(eps_exc) 281 ABI_FREE(dos_exc) 282 ABI_FREE(dos_ks) 283 ABI_FREE(dos_gw) 284 end if ! my_rank==master 285 286 ABI_FREE(opt_cvk) 287 288 call xmpi_barrier(comm) 289 290 end subroutine build_spectra
m_exc_spectra/check_fsumrule [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
check_fsumrule
FUNCTION
check f-sum rule \int_0^\infty d\omega \omega Im \epsilon_GG'(q,\omega) = = \frac{1}{2} \pi \omega_p^2 \frac{\rho(G-G')}{\rho(0)} versor(q+G) \dot versor(q+G') for q = G = G' = 0, it reads: \int_0^\infty d\omega \omega Im \epsilon_00(q=0,\omega) = = \pi \omega_p^2 / 2 calculate only the second one calculate the integral to evaluate an omega_plasma^eff to compare with omega_plasma
INPUTS
n=Number of frequencies. o(n)=Frequency mesh. e2(n)=imaginary part of epsilon_00 omegaplasma=Drude plasma frequency.
OUTPUT
Only checking.
SOURCE
1396 subroutine check_fsumrule(n,o,e2,omegaplasma) 1397 1398 !Arguments ------------------------------------ 1399 !scalars 1400 integer,intent(in) :: n 1401 real(dp),intent(in) :: omegaplasma 1402 !arrays 1403 real(dp),intent(in) :: o(n),e2(n) 1404 1405 !Local variables ------------------------------ 1406 !scalars 1407 integer :: ii,ip 1408 real(dp) :: omegap,domega,integral,omegaplasmaeff,fsumrule 1409 character(len=500) :: msg 1410 !arrays 1411 complex(dpc) :: intg(n) 1412 1413 !************************************************************************ 1414 1415 ! calculate domega step and verify 1416 domega = (o(n) - o(1)) / (n-1) 1417 1418 do ii=2,n 1419 if (domega-(o(ii)-o(ii-1)) > tol3) then 1420 ABI_WARNING("Frequency mesh not linear. Returning") 1421 return 1422 end if 1423 end do 1424 1425 if (o(1) > 0.1/Ha_eV) then 1426 ABI_WARNING("First frequency is not zero. Returning") 1427 return 1428 end if 1429 1430 if (e2(n) > 0.1) then 1431 write(msg,'(a,f12.6,3a,f12.6,2a)')& 1432 & ' Im epsilon for omega= ',o(n)*Ha_eV,' eV ',ch10,& 1433 & ' is not yet zero, epsilon_2= ',e2(n),ch10,& 1434 & ' f-sum rule test could give wrong results.' 1435 ABI_WARNING(msg) 1436 end if 1437 1438 ! integrate to obtain f-sum rule 1439 integral=zero 1440 do ip=1,n 1441 omegap=o(ip) 1442 integral = integral + omegap * e2(ip) 1443 end do 1444 integral = domega * integral 1445 1446 !integrate with simpson to obtain f-sum rule 1447 do ip = 1, n 1448 omegap = o(ip) 1449 intg(ip) = omegap * e2(ip) 1450 end do 1451 1452 integral = real(simpson_cplx(n,domega,intg)) 1453 if(integral < 0) then 1454 ABI_ERROR("The integral of the imaginary of dielectric function is negative !!!") 1455 else 1456 omegaplasmaeff = sqrt(integral*two/pi) 1457 end if 1458 1459 fsumrule = abs((omegaplasmaeff - omegaplasma)) / omegaplasma 1460 1461 ! write data 1462 write(msg,'(3(a,f6.2,2a))')& 1463 & " omega_plasma = ",omegaplasma*Ha_eV, " [eV]",ch10,& 1464 & " omega_plasma^eff = ",omegaplasmaeff*Ha_eV," [eV]",ch10,& 1465 & " the f-sum rule is verified within ",fsumrule*100,"%",ch10 1466 call wrtout(std_out,msg,"COLL") 1467 1468 end subroutine check_fsumrule
m_exc_spectra/check_kramerskronig [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
check_kramerskronig
FUNCTION
check Kramers Kronig \int_0^\infty d\omega' frac{\omega'}{\omega'^2 - \omega^2} Im \epsilon(\omega') = Re \epsilon(\omega)
INPUTS
n=Number of frequency points. eps(n)=Dielectric function. o(n)=Frequency mesh.
OUTPUT
Only checking.
SOURCE
1270 subroutine check_kramerskronig(n,o,eps) 1271 1272 !Arguments ------------------------------------ 1273 !scalars 1274 integer,intent(in) :: n 1275 !arrays 1276 complex(dpc),intent(in) :: eps(n) 1277 real(dp),intent(in) :: o(n) 1278 1279 !Local variables ------------------------------ 1280 !scalars 1281 integer :: ii,ip 1282 real(dp) :: omega,omegap,domega,kk,kkrms,eav 1283 complex(dpc) c 1284 character(len=500) :: msg 1285 !arrays 1286 real(dp) :: e1kk(n) 1287 complex(dpc) :: intg(n) 1288 1289 !************************************************************************ 1290 ! init jmb 1291 e1kk=zero 1292 intg=(zero,zero) 1293 1294 ! calculate domega step and verify all 1295 domega = (o(n) - o(1)) / (n-1) 1296 1297 do ii=2,n 1298 if (domega-(o(ii)-o(ii-1)) > tol3) then 1299 ABI_WARNING("Frequency mesh not linear. Returning") 1300 return 1301 end if 1302 end do 1303 1304 if(o(1) > 0.1/Ha_eV) then 1305 ABI_WARNING("First frequency is not zero. Returning") 1306 return 1307 end if 1308 1309 if (aimag(eps(n)) > 0.1) then 1310 write(msg,'(a,f12.6,3a,f12.6,2a)')& 1311 & ' Im epsilon for omega= ',o(n)*Ha_eV,'eV',ch10,& 1312 & ' is not yet zero, epsilon_2= ',aimag(eps(n)),ch10,& 1313 & ' Kramers Kronig test could give wrong results. ' 1314 ABI_WARNING(msg) 1315 end if 1316 1317 ! Fill array for kramers kronig. 1318 do ii=1,n 1319 omega=o(ii) 1320 c = (0.0,0.0) 1321 do ip=1,n 1322 if(ip == ii) cycle 1323 omegap = o(ip) 1324 c = c + omegap / (omegap**2-omega**2) * aimag(eps(ip)) 1325 end do 1326 e1kk(ii) = one + two/pi * domega*real(c) 1327 end do 1328 1329 !perform kramers kronig with simpson integration 1330 do ii=1,n 1331 omega=o(ii) 1332 do ip=1,n 1333 if (ip==ii) cycle 1334 omegap = o(ip) 1335 intg(ip) = omegap / (omegap**2 - omega**2) * aimag(eps(ip)) 1336 end do 1337 c = simpson_cplx(n,domega,intg) 1338 e1kk(ii) = one + two/pi * real(c) 1339 end do 1340 1341 !verify kramers kronig 1342 eav=zero; kk=zero; kkrms=zero 1343 do ii=1,n 1344 kk = kk + abs(real(eps(ii)) - e1kk(ii)) 1345 kkrms = kkrms +(real(eps(ii)) - e1kk(ii))*(real(eps(ii)) - e1kk(ii)) 1346 eav = eav + abs(real(eps(ii))) 1347 end do 1348 1349 eav = eav/n 1350 kk = (kk/n)/eav 1351 kkrms = (kkrms/n) / (eav*eav) 1352 1353 kk = abs(real(eps(1)) - e1kk(1)) / real(eps(1)) 1354 1355 ! write data 1356 write(msg,'(a,f7.2,a)')" The Kramers-Kronig is verified within ",100*kk,"%" 1357 call wrtout(std_out,msg,"COLL") 1358 1359 ! write(std_out,'("# Kramers Kronig calculation of epsilon1")') 1360 ! write(std_out,'("# omega epsilon1 epsilon1kk")') 1361 ! do ii=1,n 1362 ! write(std_out,'(f7.3,2e15.7)') o(ii)*Ha_eV, real(eps(ii)), e1kk(ii) 1363 ! end do 1364 1365 end subroutine check_kramerskronig
m_exc_spectra/exc_eps_coupling [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
exc_eps_coupling
FUNCTION
Make epsilon EXCITONIC with full COUPLING.
INPUTS
Bsp nkbz=Number of points in the BZ lomo_min,max_band nomega=Number of frequencies omega(nomega)=frequency mesh. nsppol=Number of independent spin polarizations. ucvol=Unit cell volume. BS_files<excfiles>File names used in the Bethe-Salpeter code. opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
OUTPUT
eps_exc(nomega)=Macroscopic dielectric function with excitonic effects calculated including the COUPLING. dos_exc(nomega)=The DOS of the excitonic Hamiltonian
SOURCE
850 subroutine exc_eps_coupling(Bsp,BS_files,lomo_min,max_band,nkbz,nsppol,opt_cvk,ucvol,nomega,omega,eps_exc,dos_exc) 851 852 !Arguments ------------------------------------ 853 !scalars 854 integer,intent(in) :: lomo_min,max_band,nkbz,nomega,nsppol 855 real(dp),intent(in) :: ucvol 856 type(excfiles),intent(in) :: BS_files 857 type(excparam),intent(in) :: BSp 858 !arrays 859 real(dp),intent(out) :: dos_exc(nomega) 860 complex(dpc),intent(in) :: opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol,BSp%nq),omega(nomega) 861 complex(dpc),intent(out) :: eps_exc(nomega,BSp%nq) 862 863 !Local variables ------------------------------ 864 !scalars 865 integer :: mi,it,ii,ib_v,ib_c,ik_bz,exc_size_read,nstates_read,eig_unt !,fform 866 integer :: exc_size,iq,spin,tr_idx,tar_idx,nstates,iw,ll,ierr 867 real(dp) :: fact,arg 868 complex(dpc) :: eps,fam,famp 869 character(len=500) :: msg,errmsg 870 character(len=fnlen) :: filbseig 871 logical :: do_lifetime 872 !type(Hdr_type) :: tmp_Hdr 873 !arrays 874 complex(dpc),allocatable :: Ami(:),exc_ene(:),Sm1mi(:) 875 complex(dpc),allocatable :: msfap(:,:),fa(:,:),fap(:,:) 876 877 !************************************************************************ 878 879 call wrtout(std_out," Calculating absorption strength with full coupling","COLL") 880 881 if (nsppol==2) then 882 ABI_WARNING("nsppol==2 is still under development") 883 end if 884 885 ! Rank of the entire excitonic Hamiltonian including the coupling block. 886 exc_size = 2*SUM(BSp%nreh); if (nsppol==2) exc_size = 2*(SUM(BSp%nreh) + BSp%nreh(2)) 887 nstates = BSp%nstates 888 889 ! TODO: four_pi comes from the bare Coulomb term hence the 890 ! present implementation is not compatible with the cutoff technique. 891 ! factor two is due to the occupation factors. 892 fact=four_pi/(ucvol*nkbz); if (nsppol==1) fact=two*fact 893 894 if (BS_files%in_eig /= BSE_NOFILE) then 895 filbseig = BS_files%in_eig 896 else 897 filbseig = BS_files%out_eig 898 end if 899 900 call wrtout(std_out," Reading excitonic eigenstates from file: "//trim(filbseig),"COLL") 901 if (open_file(filbseig,msg,newunit=eig_unt,form="unformatted", status="old", action="read") /= 0) then 902 ABI_ERROR(msg) 903 end if 904 905 read(eig_unt, err=10, iomsg=errmsg) do_lifetime 906 907 if (do_lifetime) then 908 ABI_CHECK(.not. do_lifetime, "Finite lifetime with coupling is not supported yet !") 909 end if 910 911 read(eig_unt, err=10, iomsg=errmsg) exc_size_read, nstates_read 912 ABI_CHECK(exc_size_read==exc_size,"wrong file") 913 ABI_CHECK(nstates_read==nstates,"Partial diago not supported yet") 914 ! 915 ! Read eigenvalues 916 ABI_MALLOC(exc_ene,(nstates)) 917 read(eig_unt, err=10, iomsg=errmsg) exc_ene(:) 918 919 ABI_MALLOC(fa,(nstates,BSp%nq)) 920 ABI_MALLOC(fap,(nstates,BSp%nq)) 921 ABI_MALLOC_OR_DIE(Ami,(exc_size), ierr) 922 923 do mi=1,nstates ! Loop on excitonic eigenvalues mi 924 read(eig_unt, err=10, iomsg=errmsg) Ami(:) 925 926 do iq=1,BSp%nq 927 fam = czero 928 famp = czero 929 do spin=1,nsppol 930 do it=1,BSp%nreh(spin) ! Loop over transition t = (k,v,c) 931 ik_bz = Bsp%Trans(it,spin)%k 932 ib_v = Bsp%Trans(it,spin)%v 933 ib_c = Bsp%Trans(it,spin)%c 934 tr_idx = it + (spin-1)*Bsp%nreh(1) 935 if (nsppol==1) then 936 tar_idx = it + Bsp%nreh(1) 937 else 938 if (spin==1) tar_idx = it + SUM(Bsp%nreh) 939 if (spin==2) tar_idx = it + 2*Bsp%nreh(1)+Bsp%nreh(2) 940 end if 941 942 fam = fam + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * Ami(tr_idx) & 943 & + CONJG(opt_cvk(ib_v,ib_c,ik_bz,spin,iq)) * Ami(tar_idx) 944 945 famp = famp - opt_cvk(ib_c,ib_v,ik_bz,spin,iq) * CONJG(Ami(tr_idx)) & 946 & + opt_cvk(ib_v,ib_c,ik_bz,spin,iq) * CONJG(Ami(tar_idx)) 947 end do 948 end do 949 ! Save results. 950 fa (mi,iq) = fam 951 fap(mi,iq) = famp 952 end do 953 end do ! mi 954 955 ABI_FREE(Ami) 956 957 ! Read O{-1} and sum over the eigenstates. 958 ABI_MALLOC(msfap,(nstates,BSp%nq)) 959 ABI_MALLOC(Sm1mi,(nstates)) 960 961 do mi=1,nstates 962 read(eig_unt, err=10, iomsg=errmsg) Sm1mi 963 Sm1mi = DCONJG(Sm1mi) ! This gives the row since O^{-1} is Hermitian. 964 do iq=1,BSp%nq 965 msfap(mi,iq) = xdotu(exc_size,Sm1mi,1,fap(:,iq),1) 966 end do 967 end do 968 969 ABI_FREE(Sm1mi) 970 971 close(eig_unt, err=10, iomsg=errmsg) 972 ! 973 ! === Calculate excitonic epsilon with coupling === 974 do iq=1,BSp%nq 975 ! 976 do ii=1,nomega 977 eps = czero 978 do mi=1,nstates ! sum over all exciton eigenstates 979 eps = eps - fa(mi,iq) * msfap(mi,iq) / (exc_ene(mi) - omega(ii)) 980 end do 981 eps_exc(ii,iq) = one + fact * eps 982 end do 983 ! 984 end do 985 986 ABI_FREE(fa) 987 ABI_FREE(msfap) 988 ABI_FREE(fap) 989 ! 990 ! The excitonic DOS. 991 dos_exc=zero 992 do ll=1,nstates ! Sum over the calculate excitonic eigenstates. 993 do iw=1,nomega 994 arg = DBLE(omega(iw) - exc_ene(ll)) 995 dos_exc(iw) = dos_exc(iw) + gaussian(arg, Bsp%broad) 996 end do 997 end do 998 999 ABI_FREE(exc_ene) 1000 1001 return 1002 1003 10 continue 1004 ABI_ERROR(errmsg) 1005 1006 end subroutine exc_eps_coupling
m_exc_spectra/exc_eps_resonant [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
exc_eps_resonant
FUNCTION
This routine builds the macroscopic dielectric function with excitonic effects.
INPUTS
Bsp lomo_min,max_band nkbz=Number of points in the BZ nsppol=Number of independent polarizations. nomega=Number of frequencies omega(nomega)=frequency mesh (complex shift is already included) ucvol=Volume of the unit cell. opt_cvk(lomo_min:max_band,mib:max_band,nkbz,nsppol,Bsp%nq)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
OUTPUT
eps_exc(nomega,Bsp%nq)=Macroscopic dielectric function with excitonic effects. dos_exc(nomega)=The DOS of the excitonic Hamiltonian
SOURCE
606 subroutine exc_eps_resonant(Bsp,filbseig,ost_fname,lomo_min,max_band,nkbz,nsppol,opt_cvk,& 607 & ucvol,nomega,omega,eps_exc,dos_exc,elph_lifetime) 608 609 !Arguments ------------------------------------ 610 !scalars 611 integer,intent(in) :: lomo_min,max_band,nkbz,nomega,nsppol 612 real(dp),intent(in) :: ucvol 613 type(excparam),intent(in) :: BSp 614 character(len=fnlen),intent(in) :: filbseig,ost_fname 615 logical,optional,intent(in) :: elph_lifetime 616 !arrays 617 real(dp),intent(out) :: dos_exc(nomega) 618 complex(dpc),intent(in) :: opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol,BSp%nq),omega(nomega) 619 complex(dpc),intent(out) :: eps_exc(nomega,BSp%nq) 620 621 !Local variables ------------------------------ 622 !scalars 623 integer :: ll,it,iw,ib_v,ib_c,ik_bz,neig_read,eig_unt,exc_size,iq !fform, 624 integer :: spin,spad,hsize_read,nstates,ost_unt 625 logical :: do_ep_lifetime, file_do_lifetime 626 real(dp) :: fact,arg 627 complex(dpc) :: dotprod 628 character(len=500) :: msg,frm,errmsg 629 !type(Hdr_type) :: tmp_Hdr 630 !arrays 631 real(dp),allocatable :: exc_ene(:) 632 complex(dpc) :: ctemp(BSp%nq),dtemp(BSp%nq) 633 complex(dpc),allocatable :: ostrength(:,:),exc_ene_cplx(:),exc_state(:),exc_state2(:) 634 635 !************************************************************************ 636 637 call wrtout(std_out," Calculating excitonic epsilon with antiresonant","COLL") 638 639 if (nsppol==2) then 640 ABI_WARNING("nsppol==2 still under development") 641 end if 642 643 exc_size = SUM(BSp%nreh) 644 nstates = BSp%nstates 645 646 do_ep_lifetime = .FALSE. 647 if(PRESENT(elph_lifetime)) then 648 do_ep_lifetime = elph_lifetime 649 end if 650 651 if (ANY(Bsp%nreh/=Bsp%nreh(1))) then 652 write(msg,'(a,2(i0,1x))')"BSE does not support different number of transitions for the two spin channels. nreh: ",Bsp%nreh 653 ABI_WARNING(msg) 654 end if 655 ! 656 ! TODO: 657 ! four_pi comes from the bare Coulomb term hence the 658 ! present implementation is not compatible with the cutoff technique. 659 fact=four_pi/(ucvol*nkbz); if (nsppol==1) fact=two*fact ! two to account for the occupation numbers. 660 661 call wrtout(std_out," Reading excitonic eigenstates from file: "//TRIM(filbseig),"COLL") 662 if (open_file(filbseig,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then 663 ABI_ERROR(msg) 664 end if 665 666 read(eig_unt, err=10, iomsg=errmsg) file_do_lifetime 667 668 if(do_ep_lifetime .and. .not. file_do_lifetime) then 669 ABI_ERROR("Cannot do lifetime as the data is not present in the file !") 670 end if 671 672 read(eig_unt, err=10, iomsg=errmsg) hsize_read,neig_read 673 674 if (hsize_read /= exc_size) then 675 write(msg,'(2(a,i0))')" Wrong size of the Hamiltonian: read: ",hsize_read," expected= ",exc_size 676 ABI_ERROR(msg) 677 end if 678 679 if (neig_read /= nstates) then 680 write(msg,'(2(a,i0))')" Wrong number of eigenstates: read: ",neig_read," expected= ",nstates 681 ABI_ERROR(msg) 682 end if 683 ! 684 ! Read eigenvalues, ignore possibly small imaginary part. 685 ABI_MALLOC(exc_ene_cplx,(neig_read)) 686 read(eig_unt, err=10, iomsg=errmsg) exc_ene_cplx 687 688 ABI_MALLOC(exc_ene,(neig_read)) 689 exc_ene = DBLE(exc_ene_cplx) 690 !ABI_FREE(exc_ene_cplx) 691 ! 692 ! Calculate oscillator strength. 693 ABI_MALLOC(exc_state,(exc_size)) 694 ABI_MALLOC(ostrength,(neig_read,BSp%nq)) 695 696 if (do_ep_lifetime) then 697 ABI_MALLOC(exc_state2,(exc_size)) 698 do ll=1,neig_read ! Loop over excitonic eigenstates reported on file. 699 read(eig_unt, err=10, iomsg=errmsg) exc_state(:) ! Righteigenvector 700 read(eig_unt, err=10, iomsg=errmsg) exc_state2(:) ! Lefteigenvector 701 702 ! Here assuming that eigenvectors are such as Xl_i' Xr_j = delta_ij 703 ! Otherwise, I need to invert the overlap matrix ! 704 705 ! Rescale the vectors so that they are "normalized" with respect to the other one ! 706 dotprod = xdotc(exc_size,exc_state2(:),1,exc_state(:),1) 707 exc_state2(:) = exc_state2(:)/CONJG(dotprod) 708 709 ctemp(:) = czero 710 dtemp(:) = czero 711 do spin=1,nsppol 712 spad=(spin-1)*BSp%nreh(1) ! Loop over spin channels. 713 do it=1,BSp%nreh(spin) ! Loop over resonant transition t = (k,v,c,s) 714 ik_bz = Bsp%Trans(it,spin)%k 715 ib_v = Bsp%Trans(it,spin)%v 716 ib_c = Bsp%Trans(it,spin)%c 717 do iq=1,BSp%nq 718 ctemp(iq) = ctemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state(it+spad) 719 dtemp(iq) = dtemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state2(it+spad) 720 end do 721 end do ! it 722 end do 723 ostrength(ll,:) = ctemp(:)*CONJG(dtemp(:)) 724 end do ! ll 725 ABI_FREE(exc_state2) 726 else 727 do ll=1,neig_read ! Loop over excitonic eigenstates reported on file. 728 read(eig_unt, err=10, iomsg=errmsg) exc_state(:) 729 if(file_do_lifetime) read(eig_unt, err=10, iomsg=errmsg) 730 731 ctemp(:) = czero 732 do spin=1,nsppol 733 spad=(spin-1)*BSp%nreh(1) ! Loop over spin channels. 734 do it=1,BSp%nreh(spin) ! Loop over resonant transition t = (k,v,c,s) 735 ik_bz = Bsp%Trans(it,spin)%k 736 ib_v = Bsp%Trans(it,spin)%v 737 ib_c = Bsp%Trans(it,spin)%c 738 do iq=1,BSp%nq 739 ctemp(iq) = ctemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state(it+spad) 740 end do 741 end do ! it 742 end do 743 ostrength(ll,:) = ctemp(:)*CONJG(ctemp(:)) 744 end do ! ll 745 end if 746 747 748 close(eig_unt, err=10, iomsg=errmsg) 749 ABI_FREE(exc_state) 750 751 if(do_ep_lifetime) then 752 eps_exc = one 753 do ll=1,neig_read ! Sum over all excitonic eigenstates read from file. 754 do iq=1,BSp%nq 755 do iw=1,nomega 756 eps_exc(iw,iq) = eps_exc(iw,iq) + & 757 & fact * ostrength(ll,iq) * (one/(exc_ene_cplx(ll) - omega(iw)) - one/(-DCONJG(exc_ene_cplx(ll)) - omega(iw))) 758 end do 759 end do !ll 760 end do !iw 761 else 762 eps_exc = one 763 do ll=1,neig_read ! Sum over all excitonic eigenstates read from file. 764 do iq=1,BSp%nq 765 do iw=1,nomega 766 eps_exc(iw,iq) = eps_exc(iw,iq) + & 767 & fact * ostrength(ll,iq) * (one/(exc_ene(ll) - omega(iw)) - one/(-exc_ene(ll) - omega(iw))) 768 end do 769 end do !ll 770 end do !iw 771 end if 772 773 ! 774 ! The excitonic DOS. 775 dos_exc=zero 776 do ll=1,neig_read ! Sum over the calculate excitonic eigenstates. 777 do iw=1,nomega 778 arg = ( DBLE(omega(iw)) - exc_ene(ll)) 779 if(do_ep_lifetime) then 780 dos_exc(iw) = dos_exc(iw) + gaussian(arg, AIMAG(exc_ene_cplx(ll))) 781 else 782 dos_exc(iw) = dos_exc(iw) + gaussian(arg, Bsp%broad) 783 end if 784 end do 785 end do 786 ! 787 ! Write the oscillator strengths to file. 788 if (open_file(ost_fname,msg,newunit=ost_unt,form="formatted",action="write") /= 0) then 789 ABI_ERROR(msg) 790 end if 791 792 write(ost_unt,'("# Oscillator strengths of the excitonic states for the different q-polarizations.")') 793 ! 794 ! Write the list of q-points. 795 write(ost_unt,*)"# List of q-points for the optical limit" 796 do iq=1,BSp%nq 797 write(ost_unt,'(a,3(f9.6,","),a)')'# q = ',BSp%q(:,iq),' [Reduced coords] ' 798 end do 799 800 write(ost_unt,*)"# E_lambda [eV] ostrength(q=1) ostrength(q=2) .... " 801 write(frm,*)'(f8.4,',BSp%nq,'es12.4)' 802 do ll=1,neig_read 803 write(ost_unt,frm)exc_ene(ll)*Ha_eV,(ostrength(ll,iq), iq=1,BSp%nq) 804 end do 805 806 close(ost_unt) 807 808 ABI_FREE(ostrength) 809 ABI_FREE(exc_ene) 810 ABI_FREE(exc_ene_cplx) 811 812 !call exc_amplitude(Bsp,filbseig,1,(/(ll,ll=1,10)/),"TEST_AMPLITUDE") 813 !call exc_amplitude(Bsp,filbseig,1,(/30/),"TEST_AMPLITUDE") 814 815 return 816 817 ! Handler IO-error 818 10 continue 819 ABI_ERROR(errmsg) 820 821 end subroutine exc_eps_resonant
m_exc_spectra/exc_eps_rpa [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
exc_eps_rpa
FUNCTION
Build epsilon within RPA and GW.
INPUTS
nkbz=Number of points in the BZ nbnds=Number of bands lomo_spin(nsppol) lomo_min=Lowest occupied state homo=Number of occupied states. homo_spin(nsppol) nsppol=Number of independent spin polarizations. nomega=Number of frequencies omega(nomega)=Frequency mesh. ucvol=Unit cell volume. broad=Broadening used for the DOS. opt_cvk(nbnds,nbnds,nkbz)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
OUTPUT
eps_rpa(nomega)=RPA spectrum without local-field effects. dos(nomega)=The DOS.
SOURCE
483 subroutine exc_eps_rpa(nbnds,lomo_spin,lomo_min,homo_spin,Kmesh,Bst,nq,nsppol,opt_cvk,ucvol,broad,nomega,omega,eps_rpa,dos) 484 485 !Arguments ------------------------------------ 486 !scalars 487 integer,intent(in) :: nbnds,lomo_min,nsppol,nomega,nq 488 real(dp),intent(in) :: ucvol,broad 489 type(kmesh_t),intent(in) :: Kmesh 490 type(ebands_t),intent(in) :: BSt 491 !arrays 492 integer,intent(in) :: lomo_spin(nsppol),homo_spin(nsppol) 493 real(dp),intent(out) :: dos(nomega) 494 complex(dpc),intent(in) :: omega(nomega) 495 complex(dpc),intent(in) :: opt_cvk(lomo_min:nbnds,lomo_min:nbnds,Kmesh%nbz,nsppol,nq) 496 complex(dpc),intent(out) :: eps_rpa(nomega,nq) 497 498 !Local variables ------------------------------ 499 !scalars 500 integer :: iw,ib_v,ib_c,ik_bz,ik_ibz,spin,iq 501 real(dp) :: fact,arg,ediff 502 real(dp) :: linewidth 503 complex(dpc) :: ctemp 504 logical :: do_linewidth 505 506 !************************************************************************ 507 508 ! TODO: four_pi comes from the bare Coulomb term hence the 509 ! present implementation is not compatible with the cutoff technique. 510 fact=four_pi/(ucvol*Kmesh%nbz) 511 if (nsppol==1) fact=two*fact ! two accounts for the occupation factors. 512 513 eps_rpa=czero; dos=zero 514 515 do_linewidth = .FALSE. 516 do_linewidth = allocated(BSt%linewidth) 517 518 !write(std_out,*)nsppol,Kmesh%nbz,lomo_min,homo,nbnds 519 ! 520 ! Sum over all QP transitions. 521 do spin=1,nsppol 522 do ik_bz=1,Kmesh%nbz 523 ik_ibz = Kmesh%tab(ik_bz) 524 do ib_v=lomo_spin(spin),homo_spin(spin) 525 do ib_c=homo_spin(spin)+1,nbnds 526 ! 527 ! TODO here energies are always assumed to be real. 528 ediff = BSt%eig(ib_c,ik_ibz,spin) - BSt%eig(ib_v,ik_ibz,spin) 529 530 ! 531 if(do_linewidth) then 532 linewidth = BSt%linewidth(1,ib_c,ik_ibz,spin) + BSt%linewidth(1,ib_v,ik_ibz,spin) 533 do iq=1,nq 534 ctemp = opt_cvk(ib_c,ib_v,ik_bz,spin,iq) 535 do iw=1,nomega 536 eps_rpa(iw,iq) = eps_rpa(iw,iq) + ctemp * CONJG(ctemp) *& 537 & (one/(ediff-j_dpc*linewidth-omega(iw)) + one/(ediff+j_dpc*linewidth+omega(iw))) 538 end do 539 end do 540 ! 541 ! The JDOS at q=0 542 !if (ediff*Ha_eV < 0.3) then 543 ! write(std_out,*)"Small transition ",ik_ibz,ib_v,ib_c 544 !end if 545 546 do iw=1,nomega 547 arg = DBLE(omega(iw)) - ediff 548 dos(iw) = dos(iw) + gaussian(arg, linewidth) 549 end do 550 else 551 do iq=1,nq 552 ctemp = opt_cvk(ib_c,ib_v,ik_bz,spin,iq) 553 do iw=1,nomega 554 eps_rpa(iw,iq) = eps_rpa(iw,iq) + ctemp * CONJG(ctemp) *& 555 (one/(ediff-omega(iw)) + one/(ediff+omega(iw))) 556 end do 557 end do 558 ! 559 ! The JDOS at q=0 560 !if (ediff*Ha_eV < 0.3) then 561 ! write(std_out,*)"Small transition ",ik_ibz,ib_v,ib_c 562 !end if 563 564 do iw=1,nomega 565 arg = DBLE(omega(iw)) - ediff 566 dos(iw) = dos(iw) + gaussian(arg, broad) 567 end do 568 end if 569 ! 570 end do !ib_c 571 end do !ib_v 572 end do !ik_bz 573 end do !spin 574 575 dos = dos/Kmesh%nbz 576 eps_rpa = cone + fact*eps_rpa 577 578 end subroutine exc_eps_rpa
m_exc_spectra/exc_write_data [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
exc_write_data
FUNCTION
This routine drives the writing of the files produced by the Bethe-Salpeter code.
INPUTS
BSp<excparam>=Bethe-Salpeter Parameters. what= "EXC_MDF" "RPA_NLF_MDF" "GW_NLF_MDF" [dos(nomega)]
OUTPUT
Only writing.
SIDE EFFECTS
eps(BSp%nomega,BSp%nq) = Macroscopic dielectric function to be written.
SOURCE
317 subroutine exc_write_data(BSp,BS_files,what,eps,prefix,dos) 318 319 !Arguments ------------------------------------ 320 !scalars 321 character(len=*),intent(in) :: what 322 type(excparam),intent(in) :: BSp 323 type(excfiles),intent(in) :: BS_files 324 character(len=*),optional,intent(in) :: prefix 325 !arrays 326 real(dp),optional,intent(in) :: dos(BSp%nomega) 327 complex(dpc),intent(in) :: eps(BSp%nomega,BSp%nq) 328 329 !Local variables ------------------------------ 330 !scalars 331 integer :: io,iq,funt 332 real(dp) :: omegaev,step 333 !real(dp),parameter :: SMALL=5.0d-99 334 !arrays 335 real(dp) :: int_dos(BSp%nomega) 336 real(dp) :: tmp_eps(2,BSp%nq) 337 character(len=500) :: lf_type,block_type,wgg_type,frm,str_type,msg 338 character(len=fnlen) :: fname 339 340 !************************************************************************ 341 342 if (PRESENT(prefix)) then 343 fname = strcat(BS_files%out_basename,prefix,'_',toupper(what)) 344 else 345 fname = strcat(BS_files%out_basename,'_',toupper(what)) 346 end if 347 348 if (open_file(fname,msg,newunit=funt,form="formatted", action="write") /= 0) then 349 ABI_ERROR(msg) 350 end if 351 352 select case (toupper(what)) 353 case ("EXC_MDF") 354 call wrtout(ab_out," Writing EXC Macroscopic dielectric function to file: "//trim(fname),"COLL") 355 356 write(funt,'("# Macroscopic dielectric function obtained with the BS equation.")') 357 358 lf_type = 'WITHOUT LOCAL FIELD EFFECTS' 359 if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED' 360 call bsp_calctype2str(Bsp,str_type) 361 write(funt,'("# ",a," " ,a)') TRIM(str_type), TRIM(lf_type) 362 363 block_type = 'RESONANT-ONLY calculation' 364 if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation' 365 write(funt,'("# ",a)') TRIM(block_type) 366 367 if (BSp%use_coulomb_term) then 368 wgg_type = "Coulomb term constructed with full W(G1,G2)" 369 if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)" 370 write(funt,'("# ",a)') TRIM(wgg_type) 371 end if 372 373 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 374 375 case ("RPA_NLF_MDF") 376 call wrtout(ab_out," Writing KS-RPA macroscopic dielectric function without local fields to file: "//trim(fname),"COLL") 377 write(funt,'("# RPA macroscopic dielectric function without local fields")') 378 379 case ("GW_NLF_MDF") 380 call wrtout(ab_out," Writing GW-RPA macroscopic dielectric function without local fields to file: "//trim(fname),"COLL") 381 382 write(funt,'("# GW Macroscopic dielectric function without local field effects ")') 383 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 384 385 case default 386 ABI_ERROR("Unknown value for what: "//trim(what)) 387 end select 388 ! 389 ! Paramaters common to the different calculations. 390 if (BSp%algorithm /= BSE_ALGO_HAYDOCK) then 391 write(funt,'(a,i0)')"# nstates included in the diagonalization = ",BSp%nstates 392 end if 393 394 if (BSp%algorithm == BSE_ALGO_HAYDOCK) then 395 write(funt,'(a,2f7.4)')'# Tolerance = ',BSp%haydock_tol 396 end if 397 398 write(funt,'(a,i0)')"# npweps = ",BSp%npweps 399 write(funt,'(a,i0)')"# npwwfn = ",BSp%npwwfn 400 write(funt,'(a,i0)')"# nbands = ",BSp%nbnds 401 write(funt,'(a,i0)')"# loband = ",BSp%lomo_spin(1) 402 if (Bsp%nsppol==2) write(funt,'(a,i0)')"# loband(spin=2) = ",BSp%lomo_spin(2) 403 write(funt,'(a,i0)')"# nkibz = ",BSp%nkibz 404 write(funt,'(a,i0)')"# nkbz = ",BSp%nkbz 405 write(funt,'(a,f7.4,a)')'# Lorentzian broadening = ',BSp%broad*Ha_eV,' [eV]' 406 ! 407 ! Write the list of q-points. 408 write(funt,'(a)')"# List of q-points for the optical limit:" 409 do iq=1,BSp%nq 410 write(funt,'(a,3(f9.6,","),a)')'# q = ',BSp%q(:,iq),' [Reduced coords] ' 411 end do 412 ! 413 ! Write spectra. 414 if (.not.PRESENT(dos)) then 415 write(funt,'(a)')"# omega [eV] RE(eps(q=1)) IM(eps(q=1) RE(eps(q=2) ) ... " 416 !write(frm,*)'(f7.3,',2*BSp%nq,'es12.4)' 417 write(frm,*)'(f7.3,',2*BSp%nq,'(1x,f9.4))' 418 do io=1,BSp%nomega 419 omegaev = DBLE(BSp%omega(io))*Ha_eV 420 tmp_eps(1,:) = REAL (eps(io,:)) 421 tmp_eps(2,:) = AIMAG(eps(io,:)) 422 !where (ABS(tmp_eps) < SMALL) ! this to improve the portability of the automatic tests. 423 ! tmp_eps = zero 424 !end where 425 write(funt,frm) omegaev,(tmp_eps(:,iq), iq=1,BSp%nq) 426 end do 427 428 else 429 write(funt,'(a)')"# omega [eV] RE(eps(q=1)) IM(eps(q=1) RE(eps(q=2) ) ... DOS IDOS" 430 step = DBLE(BSp%omega(2) - BSp%omega(1)) 431 if ( ABS( step - DBLE((BSp%omega(BSp%nomega) - BSp%omega(BSp%nomega-1)))) > tol6 ) then 432 ABI_WARNING("Frequency mesh must be linear for using simpson_int") 433 end if 434 call simpson_int(Bsp%nomega,step,dos,int_dos) 435 !write(frm,*)'(f7.3,',2*BSp%nq,'es12.4,2es12.4)' 436 write(frm,*)'(f7.3,',2*BSp%nq,'(1x,f9.4,1x,f9.4,1x,f9.4))' 437 do io=1,BSp%nomega 438 omegaev = DBLE(BSp%omega(io))*Ha_eV 439 tmp_eps(1,:) = REAL (eps(io,:)) 440 tmp_eps(2,:) = AIMAG(eps(io,:)) 441 !where (ABS(tmp_eps) < SMALL) ! this to improve the portability of the automatic tests. 442 ! tmp_eps = zero 443 !end where 444 !write(funt,frm) omegaev,(eps(io,iq), iq=1,BSp%nq), dos(io), int_dos(io) 445 write(funt,frm) omegaev,(tmp_eps(:,iq), iq=1,BSp%nq), dos(io), int_dos(io) 446 end do 447 end if 448 449 close(funt) 450 451 end subroutine exc_write_data
m_exc_spectra/exc_write_tensor [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
exc_write_tensor
FUNCTION
This routine drives the writing of complex dielectric tensor
INPUTS
BSp<excparam>=Bethe-Salpeter Parameters. what= "EXC_TSR_CART" or "EXC_TSR_RED" "RPA_NLF_TSR_CART" or "RPA_NLF_TSR_RED" "GW_NLF_TSR_CART" or "GW_NLF_TSR_RED"
OUTPUT
Only writing.
SIDE EFFECTS
tensor(BSp%nomega,6) = Complex dielectric tensor to be written
SOURCE
1032 subroutine exc_write_tensor(BSp,BS_files,what,tensor) 1033 1034 !Arguments ------------------------------------ 1035 !scalars 1036 character(len=*),intent(in) :: what 1037 type(excparam),intent(in) :: BSp 1038 type(excfiles),intent(in) :: BS_files 1039 !arrays 1040 complex(dpc),intent(in) :: tensor(BSp%nomega,6) 1041 1042 !Local variables ------------------------------ 1043 !scalars 1044 integer :: io,iq,funt 1045 real(dp) :: omegaev 1046 !arrays 1047 character(len=500) :: lf_type,block_type,wgg_type,frm,str_type, msg 1048 character(len=fnlen) :: fname 1049 1050 !************************************************************************ 1051 1052 fname = strcat(BS_files%out_basename,'_',toupper(what)) 1053 if (open_file(fname,msg,newunit=funt,form="formatted", action="write") /= 0) then 1054 ABI_ERROR(msg) 1055 end if 1056 1057 select case (toupper(what)) 1058 1059 case ("EXC_TSR_CART") 1060 write(funt,'("# Complex dielectric tensor (cart. coord.) obtained with the BS equation.")') 1061 1062 lf_type = 'WITHOUT LOCAL FIELD EFFECTS' 1063 if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED' 1064 call bsp_calctype2str(Bsp,str_type) 1065 write(funt,'("# ",a," " ,a)') TRIM(str_type), TRIM(lf_type) 1066 1067 block_type = 'RESONANT-ONLY calculation' 1068 if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation' 1069 write(funt,'("# ",a)') TRIM(block_type) 1070 1071 if (BSp%use_coulomb_term) then 1072 wgg_type = "Coulomb term constructed with full W(G1,G2)" 1073 if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)" 1074 write(funt,'("# ",a)') TRIM(wgg_type) 1075 end if 1076 1077 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 1078 1079 case ("EXC_TSR_RED") 1080 write(funt,'("# Complex dielectric tensor (red. coord.) obtained with the BS equation.")') 1081 1082 lf_type = 'WITHOUT LOCAL FIELD EFFECTS' 1083 if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED' 1084 call bsp_calctype2str(Bsp,str_type) 1085 write(funt,'("# ",a," " ,a)') TRIM(str_type), TRIM(lf_type) 1086 1087 block_type = 'RESONANT-ONLY calculation' 1088 if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation' 1089 write(funt,'("# ",a)') TRIM(block_type) 1090 1091 if (BSp%use_coulomb_term) then 1092 wgg_type = "Coulomb term constructed with full W(G1,G2)" 1093 if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)" 1094 write(funt,'("# ",a)') TRIM(wgg_type) 1095 end if 1096 1097 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 1098 1099 case ("RPA_NLF_TSR_CART") 1100 write(funt,'("# RPA complex dielectric tensor (cart. coord.) without local fields")') 1101 1102 case ("RPA_NLF_TSR_RED") 1103 write(funt,'("# RPA complex dielectric tensor (red. coord.) without local fields")') 1104 1105 case ("GW_NLF_TSR_CART") 1106 write(funt,'("# GW complex dielectric tensor (cart. coord.) without local field effects ")') 1107 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 1108 1109 case ("GW_NLF_TSR_RED") 1110 write(funt,'("# GW complex dielectric tensor (red. coord.) without local field effects ")') 1111 write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]' 1112 1113 case default 1114 ABI_ERROR("Unknown value for what: "//TRIM(what)) 1115 end select 1116 ! 1117 ! Paramaters common to the different calculations. 1118 if (BSp%algorithm /= BSE_ALGO_HAYDOCK) then 1119 write(funt,'(a,i0)')"# nstates included in the diagonalization = ",BSp%nstates 1120 end if 1121 1122 if (BSp%algorithm == BSE_ALGO_HAYDOCK) then 1123 write(funt,'(a,2f7.4)')'# Tolerance = ',BSp%haydock_tol 1124 end if 1125 1126 write(funt,'(a,i0)')"# npweps = ",BSp%npweps 1127 write(funt,'(a,i0)')"# npwwfn = ",BSp%npwwfn 1128 write(funt,'(a,i0)')"# nbands = ",BSp%nbnds 1129 write(funt,'(a,i0)')"# loband = ",BSp%lomo_spin(1) 1130 if (Bsp%nsppol==2) write(funt,'(a,i0)')"# loband(spin=2) = ",BSp%lomo_spin(2) 1131 write(funt,'(a,i0)')"# nkibz = ",BSp%nkibz 1132 write(funt,'(a,i0)')"# nkbz = ",BSp%nkbz 1133 write(funt,'(a,f7.4,a)')'# Lorentzian broadening = ',BSp%broad*Ha_eV,' [eV]' 1134 1135 ! 1136 ! Write tensor. 1137 write(funt,'(3a)') "# omega [eV] RE(eps_11) IM(eps_11) RE(eps_22)", & 1138 & "IM(eps_22) RE(eps_33) IM(eps_33) RE(eps_12) IM(eps_12)", & 1139 & "RE(eps_13) IM(eps_13) RE(eps_23) IM(eps_23))" 1140 write(frm,*) '(f7.3,12es14.6)' 1141 do io=1,BSp%nomega 1142 omegaev = DBLE(BSp%omega(io))*Ha_eV 1143 write(funt,frm) omegaev,(tensor(io,iq), iq=1,6) 1144 end do 1145 1146 close(funt) 1147 1148 end subroutine exc_write_tensor
m_exc_spectra/mdfs_ncwrite [ Functions ]
[ Top ] [ m_exc_spectra ] [ Functions ]
NAME
mdfs_ncwrite
FUNCTION
Writes the MDF.nc file with the final results.
INPUTS
ncid =NC file handle Bsp<excparam>=Data type gathering the paramenters used for the Bethe-Salpeter calculation. eps_exc = Excitonic MDF eps_rpanlf = KS-RPA MDF without local-field effects. eps_gwnlf = GW-RPA MDF without local-field effects.
OUTPUT
Only writing.
SOURCE
1172 subroutine mdfs_ncwrite(ncid,Bsp,eps_exc,eps_rpanlf,eps_gwnlf) 1173 1174 !Arguments ------------------------------------ 1175 !scalars 1176 integer,intent(in) :: ncid 1177 type(excparam),intent(in) :: BSp 1178 !arrays 1179 complex(dpc),target,intent(in) :: eps_exc(BSp%nomega,BSp%nq) 1180 complex(dpc),target,intent(in) :: eps_rpanlf(BSp%nomega,BSp%nq) 1181 complex(dpc),target,intent(in) :: eps_gwnlf(BSp%nomega,BSp%nq) 1182 1183 !Local variables------------------------------- 1184 !scalars 1185 integer :: ncerr 1186 real(dp), ABI_CONTIGUOUS pointer :: rvals(:,:,:) 1187 1188 ! ************************************************************************* 1189 ! ========================= 1190 ! === Write the dimensions 1191 ! ========================= 1192 1193 ncerr = nctk_defnwrite_ivars(ncid, [character(len=nctk_slen) :: & 1194 & "mdf_version", "nsppol", "npwwfn", "npweps", "nkibz", "nkbz",& 1195 & "nkibz_iterp", "nkbz_interp", "wtype", "interp_mode"],& 1196 & [1, Bsp%nsppol, Bsp%npwwfn, Bsp%npweps, Bsp%nkibz, Bsp%nkbz, & 1197 & Bsp%nkibz_interp, Bsp%nkbz_interp,Bsp%wtype, Bsp%interp_mode]) 1198 NCF_CHECK(ncerr) 1199 1200 ncerr = nctk_defnwrite_dpvars(ncid, [character(len=nctk_slen) :: & 1201 & "ecutwfn", "ecuteps", "mbpt_sciss", "broad", "eps_inf"],& 1202 & [Bsp%ecutwfn, Bsp%ecuteps, Bsp%mbpt_sciss, Bsp%broad, Bsp%eps_inf]) 1203 NCF_CHECK(ncerr) 1204 1205 ncerr = nctk_def_dims(ncid, [nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("number_of_qpoints", Bsp%nq),& 1206 nctkdim_t("number_of_frequencies", Bsp%nomega), nctkdim_t("number_of_spins", bsp%nsppol)], defmode=.True.) 1207 NCF_CHECK(ncerr) 1208 1209 ! Define variables. 1210 1211 !arrays 1212 ncerr = nctk_def_arrays(ncid, [& 1213 nctkarr_t('qpoints', "dp", 'three, number_of_qpoints'),& 1214 nctkarr_t('wmesh', "dp", 'number_of_frequencies'),& 1215 nctkarr_t('nreh', "i", "number_of_spins"),& 1216 nctkarr_t('lomo_spin', "i", "number_of_spins"),& 1217 nctkarr_t('humo_spin', "i", "number_of_spins"),& 1218 nctkarr_t('exc_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints'),& 1219 nctkarr_t('rpanlf_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints'),& 1220 nctkarr_t('gwnlf_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints')]) 1221 NCF_CHECK(ncerr) 1222 1223 ! Write data. 1224 NCF_CHECK(nctk_set_datamode(ncid)) 1225 NCF_CHECK(nf90_put_var(ncid, vid('qpoints'), Bsp%q)) 1226 NCF_CHECK(nf90_put_var(ncid, vid('nreh'), bsp%nreh)) 1227 NCF_CHECK(nf90_put_var(ncid, vid('lomo_spin'), bsp%lomo_spin)) 1228 NCF_CHECK(nf90_put_var(ncid, vid('humo_spin'), bsp%humo_spin)) 1229 1230 ! Write frequency in mesh in eV. 1231 NCF_CHECK(nf90_put_var(ncid, vid('wmesh'), REAL(Bsp%omega)*Ha_eV)) 1232 1233 call c_f_pointer(c_loc(eps_exc(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq]) 1234 NCF_CHECK(nf90_put_var(ncid, vid('exc_mdf'), rvals)) 1235 1236 call c_f_pointer(c_loc(eps_rpanlf(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq]) 1237 NCF_CHECK(nf90_put_var(ncid, vid('rpanlf_mdf'), rvals)) 1238 1239 call c_f_pointer(c_loc(eps_gwnlf(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq]) 1240 NCF_CHECK(nf90_put_var(ncid, vid("gwnlf_mdf"), rvals)) 1241 1242 contains 1243 integer function vid(vname) 1244 character(len=*),intent(in) :: vname 1245 vid = nctk_idname(ncid, vname) 1246 end function vid 1247 1248 end subroutine mdfs_ncwrite