Coverage for gpaw/test/directopt/test_mom_directopt_pw.py: 84%
68 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-19 00:19 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-19 00:19 +0000
1import pytest
3from gpaw import GPAW, restart
4from gpaw.mom import prepare_mom_calculation
5from gpaw.directmin.tools import excite
6import numpy as np
9@pytest.mark.do
10def test_mom_directopt_pw(in_tmp_dir, gpaw_new, gpw_files):
11 calc = GPAW(gpw_files['h2o_mom_do_pw'])
12 atoms = calc.atoms
13 atoms.calc = calc
14 calc.write('h2o.gpw', mode='all')
16 for canonical in [True, False]:
17 # Mixed-spin excited state calculation
18 atoms, calc = restart('h2o.gpw', txt='-')
19 mom_after_canonical = False # Test MOM after canonical only
20 if mom_after_canonical:
21 momevery = np.inf
22 else:
23 momevery = 3
24 calc.set(eigensolver=dict(name='etdm-fdpw',
25 excited_state=True,
26 momevery=momevery,
27 restart_canonical=canonical,
28 printinnerloop=True))
29 f_sn = excite(calc, 0, 0, (0, 0))
30 prepare_mom_calculation(calc, atoms, f_sn)
32 def rotate_homo_lumo(ctx=None, calc=calc):
33 a = 70 * np.pi / 180.0
34 if gpaw_new:
35 iters = ctx.niter
36 else:
37 iters = calc.get_number_of_iterations()
38 if iters == 3:
39 psit_nG_old = calc.wfs.kpt_u[0].psit_nG.copy()
40 calc.wfs.kpt_u[0].psit_nG[3] = \
41 np.cos(a) * psit_nG_old[3] + np.sin(a) * psit_nG_old[4]
42 calc.wfs.kpt_u[0].psit_nG[4] = \
43 np.cos(a) * psit_nG_old[4] - np.sin(a) * psit_nG_old[3]
44 for kpt in calc.wfs.kpt_u:
45 calc.wfs.pt.integrate(kpt.psit_nG, kpt.P_ani, kpt.q)
47 if gpaw_new:
48 calc.hooks['scf_step'] = rotate_homo_lumo
49 else:
50 calc.attach(rotate_homo_lumo, 1)
51 e = atoms.get_potential_energy()
52 assert e == pytest.approx(0.027152, abs=1.0e-3)
54 f = atoms.get_forces()
56 # Numeric forces, generated by disabled code below
57 f2 = np.array([[-4.07053122, -5.46395110, -2.54491307e-04],
58 [5.57197214, -1.00373986e-01, 1.87598849e-04],
59 [-1.52873845, 5.38474614, 2.07965790e-04]])
60 assert f2 == pytest.approx(f, abs=0.1)
62 numeric = False
63 if numeric:
64 calc.observers = []
65 from gpaw.test import calculate_numerical_forces
66 f_num = calculate_numerical_forces(atoms, 0.001)
67 print('Numerical forces')
68 print(f_num)
69 print(f - f_num, np.abs(f - f_num).max())
71 calc.write('h2o.gpw', mode='all')
73 # Test restart and fixed occupations
74 atoms, calc = restart('h2o.gpw', txt='-')
75 if gpaw_new:
76 return
77 atoms.calc.results.pop('energy')
78 atoms.calc.scf.converged = False
79 e2 = atoms.get_potential_energy()
80 niter = calc.get_number_of_iterations()
81 assert niter == pytest.approx(4, abs=3)
82 assert e == pytest.approx(e2, abs=1.0e-3)
84 prepare_mom_calculation(calc, atoms, f_sn, use_fixed_occupations='True')
85 e2 = atoms.get_potential_energy()
86 for spin in range(calc.get_number_of_spins()):
87 f_n = calc.get_occupation_numbers(spin=spin)
88 assert (np.allclose(f_sn[spin], f_n))
89 assert (np.allclose(f_sn[spin], calc.wfs.occupations.numbers[spin]))
90 niter = calc.get_number_of_iterations()
91 assert niter == pytest.approx(4, abs=3)
92 assert e == pytest.approx(e2, abs=1.0e-3)
95if __name__ == '__main__':
96 test_mom_directopt_pw(1, 1)