Coverage for gpaw/test/response/test_diamond_absorption.py: 100%
95 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
1import pytest
2import numpy as np
3from ase.units import Bohr
4from ase.build import bulk
5from gpaw import GPAW, FermiDirac
6from gpaw.response.df import DielectricFunction, read_response_function
7from gpaw.test import findpeak
10@pytest.mark.dielectricfunction
11@pytest.mark.response
12@pytest.mark.parametrize('eshift', [None, 4])
13@pytest.mark.libxc
14def test_response_diamond_absorption(in_tmp_dir, eshift):
15 a = 6.75 * Bohr
16 atoms = bulk('C', 'diamond', a=a)
18 calc = GPAW(mode='pw',
19 kpts=(3, 3, 3),
20 eigensolver='rmm-diis',
21 occupations=FermiDirac(0.001))
23 atoms.calc = calc
24 atoms.get_potential_energy()
25 calc.write('C.gpw', 'all')
27 if eshift is None:
28 eM1_ = 9.727
29 eM2_ = 9.548
30 w0_ = 10.7782
31 I0_ = 5.47
32 w_ = 10.7532
33 I_ = 5.98
34 else:
35 eM1_ = 6.993
36 eM2_ = 6.904
37 w0_ = 14.784
38 I0_ = 5.47
39 w_ = 14.757
40 I_ = 5.998
42 # Test the old interface to the dielectric constant
43 df = DielectricFunction('C.gpw', frequencies=(0.,), eta=0.001, ecut=50,
44 hilbert=False, eshift=eshift)
45 eM1, eM2 = df.get_macroscopic_dielectric_constant()
46 assert eM1 == pytest.approx(eM1_, abs=0.01)
47 assert eM2 == pytest.approx(eM2_, abs=0.01)
49 # ----- RPA dielectric function ----- #
50 dfcalc = DielectricFunction(
51 'C.gpw', eta=0.25, ecut=50,
52 frequencies=np.linspace(0, 24., 241), hilbert=False, eshift=eshift)
53 eps = dfcalc.get_literal_dielectric_function()
55 # Test the new interface to the dielectric constant
56 eM1, eM2 = eps.dielectric_constant()
57 assert eM1 == pytest.approx(eM1_, abs=0.01)
58 assert eM2 == pytest.approx(eM2_, abs=0.01)
60 # Test the macroscopic dielectric function
61 omega_w, eps0M_w, epsM_w = eps.macroscopic_dielectric_function().arrays
62 w0, I0 = findpeak(omega_w, eps0M_w.imag)
63 assert w0 == pytest.approx(w0_, abs=0.01)
64 assert I0 / (4 * np.pi) == pytest.approx(I0_, abs=0.1)
65 w, I = findpeak(omega_w, epsM_w.imag)
66 assert w == pytest.approx(w_, abs=0.01)
67 assert I / (4 * np.pi) == pytest.approx(I_, abs=0.1)
69 # Test polarizability
70 omega_w, a0rpa_w, arpa_w = eps.polarizability().arrays
71 w0, I0 = findpeak(omega_w, a0rpa_w.imag)
72 assert w0 == pytest.approx(w0_, abs=0.01)
73 assert I0 == pytest.approx(I0_, abs=0.01)
74 w, I = findpeak(omega_w, arpa_w.imag)
75 assert w == pytest.approx(w_, abs=0.01)
76 assert I == pytest.approx(I_, abs=0.01)
78 # Test that the macroscopic dielectric function can be calculated also from
79 # the inverse dielectric function and the bare dielectric function
80 epsinv = dfcalc.get_inverse_dielectric_function()
81 _, _, epsM_frominv_w = epsinv.macroscopic_dielectric_function().arrays
82 assert epsM_frominv_w == pytest.approx(epsM_w, rel=1e-6)
83 epsbare = dfcalc.get_bare_dielectric_function()
84 _, _, epsM_frombare_w = epsbare.macroscopic_dielectric_function().arrays
85 assert epsM_frombare_w == pytest.approx(epsM_w, rel=1e-6)
87 # ----- TDDFT absorption spectra ----- #
89 # Absorption spectrum calculation ALDA
90 if eshift is None:
91 w_ = 10.7562
92 I_ = 5.8803
93 else:
94 w_ = 14.7615
95 I_ = 5.7946
97 epsinv = dfcalc.get_inverse_dielectric_function(xc='ALDA', rshelmax=0)
98 # Here we base the check on a written results file
99 epsinv.polarizability().write(filename='ALDA_pol.csv')
100 dfcalc.context.comm.barrier()
101 omega_w, a0alda_w, aalda_w = read_response_function('ALDA_pol.csv')
103 assert a0alda_w == pytest.approx(a0rpa_w, rel=1e-4)
104 w, I = findpeak(omega_w, aalda_w.imag)
105 assert w == pytest.approx(w_, abs=0.01)
106 assert I == pytest.approx(I_, abs=0.1)
108 # Absorption spectrum calculation long-range kernel
109 if eshift is None:
110 w_ = 10.2906
111 I_ = 5.6955
112 else:
113 w_ = 14.2901
114 I_ = 5.5508
116 epsinv = dfcalc.get_inverse_dielectric_function(xc='LR0.25')
117 omega_w, a0lr_w, alr_w = epsinv.polarizability().arrays
119 assert a0lr_w == pytest.approx(a0rpa_w, rel=1e-4)
120 w, I = findpeak(omega_w, alr_w.imag)
121 assert w == pytest.approx(w_, abs=0.01)
122 assert I == pytest.approx(I_, abs=0.1)
124 # Absorption spectrum calculation Bootstrap
125 if eshift is None:
126 w_ = 10.4600
127 I_ = 6.0263
128 else:
129 w_ = 14.2626
130 I_ = 5.3896
132 epsinv = dfcalc.get_inverse_dielectric_function(xc='Bootstrap')
133 omega_w, a0btsr_w, abtsr_w = epsinv.polarizability().arrays
135 assert a0btsr_w == pytest.approx(a0rpa_w, rel=1e-4)
136 w, I = findpeak(omega_w, abtsr_w.imag)
137 assert w == pytest.approx(w_, abs=0.02)
138 assert I == pytest.approx(I_, abs=0.2)
140 # import matplotlib.pyplot as plt
141 # plt.plot(omega_w, a0rpa_w.imag, label='IP')
142 # plt.plot(omega_w, arpa_w.imag, label='RPA')
143 # plt.plot(omega_w, aalda_w.imag, label='ALDA')
144 # plt.plot(omega_w, alr_w.imag, label='LR0.25')
145 # plt.plot(omega_w, abtsr_w.imag, label='Bootstrap')
146 # plt.legend()
147 # plt.show()