Coverage for gpaw/test/response/test_chi0_intraband.py: 100%

57 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2025-07-08 00:17 +0000

1from functools import cached_property 

2import numpy as np 

3import pytest 

4 

5from gpaw.test import findpeak 

6from gpaw.response.df import DielectricFunction 

7from ase.units import Bohr, Hartree 

8 

9 

10class Helper: 

11 def __init__(self, gpw, integrationmode): 

12 self._gpw = gpw 

13 self._integrationmode = integrationmode 

14 

15 @cached_property 

16 def df(self): 

17 return DielectricFunction( 

18 self._gpw, 

19 frequencies={'type': 'nonlinear', 

20 'domega0': 0.03}, 

21 ecut=10, 

22 rate=0.1, 

23 integrationmode=self._integrationmode, 

24 txt=None) 

25 

26 @cached_property 

27 def lfc(self): 

28 # lfc == local field corrections (?) 

29 return {axis: self.df.get_dielectric_function(direction=axis)[1] 

30 for axis in 'xyz'} 

31 

32 @cached_property 

33 def wp(self): 

34 chi0_drude = self.df.chi0calc.chi0_opt_ext_calc.drude_calc.calculate( 

35 self.df.chi0calc.chi0_opt_ext_calc.wd, 0.1) 

36 return chi0_drude.plasmafreq_vv[0, 0]**0.5 

37 

38 @cached_property 

39 def w_w(self): 

40 return self.df.chi0calc.chi0_opt_ext_calc.wd.omega_w 

41 

42 def _compare_peak(self, calc, axis): 

43 df1LFCx = self.lfc[axis] 

44 df2LFCx = calc.lfc[axis] 

45 # w_x equal for paired & polarized tetra 

46 w1, I1 = findpeak(self.w_w, -(1. / df1LFCx).imag) 

47 w2, I2 = findpeak(self.w_w, -(1. / df2LFCx).imag) 

48 assert w1 == pytest.approx(w2, abs=1e-3) 

49 assert I1 == pytest.approx(I2, abs=0.1) 

50 

51 def compare_peaks(self, calc): 

52 for axis in 'xyz': 

53 self._compare_peak(calc, axis) 

54 

55 

56@pytest.mark.dielectricfunction 

57@pytest.mark.tetrahedron 

58@pytest.mark.response 

59def test_chi0_intraband(in_tmp_dir, gpw_files): 

60 """Comparing the plasmon peaks found in bulk sodium for two different 

61 atomic structures. Testing for idential plasmon peaks. Not using 

62 physical sodium cell.""" 

63 intraband_spinpaired = gpw_files['intraband_spinpaired_fulldiag'] 

64 intraband_spinpolarized = gpw_files['intraband_spinpolarized_fulldiag'] 

65 

66 calc1 = Helper(intraband_spinpaired, 'tetrahedron integration') 

67 calc2 = Helper(intraband_spinpaired, 'point integration') 

68 calc3 = Helper(intraband_spinpolarized, 'tetrahedron integration') 

69 calc4 = Helper(intraband_spinpolarized, 'point integration') 

70 

71 # Compare plasmon frequencies and intensities 

72 w_w = calc1.w_w 

73 

74 # frequency grids must be the same 

75 for calc in [calc1, calc2, calc3, calc4]: 

76 assert np.allclose(calc.w_w, w_w, atol=1e-5, rtol=1e-4) 

77 

78 # Analytical Drude result 

79 n = 1 / (calc1.df.gs.volume * Bohr**-3) 

80 drude_wp = np.sqrt(4 * np.pi * n) 

81 

82 # From https://doi.org/10.1021/jp810808h 

83 ref_wp = 5.71 / Hartree 

84 

85 # spin paired matches spin polar - tetra 

86 assert calc1.wp == pytest.approx(calc3.wp, abs=1e-2) 

87 # spin paired matches spin polar - none 

88 assert calc2.wp == pytest.approx(calc4.wp, abs=1e-2) 

89 # Use larger margin when comparing to Drude 

90 assert calc1.wp == pytest.approx(drude_wp, abs=0.5) 

91 # Use larger margin when comparing to Drude 

92 assert calc2.wp == pytest.approx(drude_wp, abs=0.5) 

93 # paired tetra match paper 

94 assert calc1.wp == pytest.approx(ref_wp, abs=0.1) 

95 # paired none match paper 

96 assert calc2.wp == pytest.approx(ref_wp, abs=0.1) 

97 

98 # w_x, w_y and w_z equal for paired & polarized tetra 

99 calc1.compare_peaks(calc3) 

100 

101 # w_x, w_y and w_z equal for paired & polarized none 

102 calc2.compare_peaks(calc4)