Coverage for gpaw/test/lrtddft/test_3.py: 100%
77 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-14 00:18 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-14 00:18 +0000
1import re
3import pytest
4import numpy as np
5from ase.build import molecule
6from ase.units import Hartree
8from gpaw import GPAW
9from gpaw.mpi import world
10from gpaw.gauss import Gauss
11from gpaw.lrtddft import LrTDDFT, photoabsorption_spectrum
12from gpaw.lrtddft.kssingle import KSSingles
15@pytest.mark.lrtddft
16@pytest.mark.slow
17@pytest.mark.skipif(world.size > 1, reason='test is serial')
18def test_lrtddft_3(in_tmp_dir):
19 from io import StringIO
21 txt = None
22 N2 = molecule('N2', vacuum=2.0)
24 calc = GPAW(mode='fd',
25 h=0.25,
26 nbands=-2,
27 spinpol=True,
28 xc='LDA',
29 txt=txt)
31 N2.calc = calc
32 _ = N2.get_potential_energy()
33 calc.write('N2_wfs.gpw', 'all')
35 # selections
36 for obj in [KSSingles, LrTDDFT]:
37 # selection using state numbers
38 el = obj(restrict={'istart': 3, 'jend': 6}, txt=txt)
39 el.calculate(N2)
40 if hasattr(obj, 'diagonalize'):
41 el.diagonalize()
43 assert len(el) == 8
44 # selection using an energy range
45 el = obj(restrict={'energy_range': 8}, txt=txt)
46 el.calculate(N2)
47 if hasattr(obj, 'diagonalize'):
48 el.diagonalize()
50 assert len(el) == 4
51 el = obj(restrict={'energy_range': 11.5}, txt=txt)
52 el.calculate(N2)
54 if hasattr(obj, 'diagonalize'):
55 el.diagonalize()
57 # Used to be == 18, but we lowered vacuum so test runs fast
58 # and now it's:
59 assert len(el) == 16
61 if hasattr(obj, 'diagonalize'):
62 el.diagonalize(restrict={'energy_range': 8})
63 assert len(el) == 4
65 lr = LrTDDFT(calc, nspins=2)
66 lr.write('lrtddft3.dat.gz')
67 lr.diagonalize()
69 # This is done to test if writing and reading again yields the same result
70 lr2 = LrTDDFT.read('lrtddft3.dat.gz')
71 lr2.diagonalize()
73 # Post processing
75 Epeak = 19.5 # The peak we want to investigate (this is alone)
76 Elist = np.asarray([lrsingle.get_energy() * Hartree
77 for lrsingle in lr])
78 n = np.argmin(np.abs(Elist - Epeak)) # index of the peak
80 E = lr[n].get_energy() * Hartree
81 osz = lr[n].get_oscillator_strength()
82 print('Original object :', E, osz[0])
84 # Test the output of analyse
85 sio = StringIO()
86 lr.analyse(n, out=sio)
87 s = sio.getvalue()
89 match = re.findall(
90 r'%i: E=([0-9]*\.[0-9]*) eV, f=([0-9]*\.[0-9]*)*' % n, s)
91 Eanalyse = float(match[0][0])
92 oszanalyse = float(match[0][1])
93 print('From analyse :', Eanalyse, oszanalyse)
94 assert E == pytest.approx(Eanalyse,
95 abs=1e-3) # Written precision in analyse
96 assert osz[0] == pytest.approx(oszanalyse, abs=1e-3)
98 E2 = lr2[n].get_energy() * Hartree
99 osz2 = lr2[n].get_oscillator_strength()
100 print('Written and read object:', E2, osz2[0])
102 # Compare values of original and written/read objects
103 assert E == pytest.approx(E2, abs=1e-4)
104 for i in range(len(osz)):
105 assert osz[i] == pytest.approx(osz2[i], abs=1.7e-4)
107 width = 0.05
108 photoabsorption_spectrum(lr,
109 spectrum_file='lrtddft3-spectrum.dat',
110 width=width)
111 # We need to be able to check the heights in the spectrum
112 weight = Gauss(width).get(0)
114 spectrum = np.loadtxt('lrtddft3-spectrum.dat', usecols=(0, 1))
115 idx = (spectrum[:, 0] >= E - 0.1) & (spectrum[:, 0] <= E + 0.1)
116 peak = np.argmax(spectrum[idx, 1]) + np.nonzero(idx)[0][0]
117 Espec = spectrum[peak, 0]
118 oszspec = spectrum[peak, 1] / weight
120 print('Values from spectrum :', Espec, oszspec)
121 # Compare calculated values with values written to file
122 assert E == pytest.approx(Espec,
123 abs=1e-2) # The spectrum has a low sampling
124 assert osz[0] == pytest.approx(oszspec, abs=1e-2)