Coverage for gpaw/test/test_reuse_wfs_celldisp.py: 97%
35 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 numpy as np
2from ase.build import molecule
4from gpaw import GPAW, Mixer
5from gpaw.mpi import world
7# Place one atom next to cell boundary, then check that reuse_wfs
8# works correctly when atom is subsequently displaced across the
9# boundary, i.e., that the kpoint phases of the PAW correction
10# are handled correctly when unprojecting/reprojecting the wavefunctions.
13def test_reuse_wfs_celldisp(in_tmp_dir):
14 def check(reuse):
15 atoms = molecule('H2')
16 atoms.pbc = 1
17 atoms.center(vacuum=1.5)
18 atoms.positions -= atoms.positions[1]
19 dz = 1e-2
20 atoms.positions[:, 2] += dz
22 calc = GPAW(mode='pw',
23 txt=f'gpaw-{reuse}.txt',
24 nbands=1,
25 eigensolver='davidson',
26 experimental=dict(
27 reuse_wfs_method='paw' if reuse else None),
28 kpts=[[-0.3, 0.4, 0.2]],
29 symmetry='off',
30 mixer=Mixer(0.7, 5, 50.0))
31 atoms.calc = calc
33 for ctx in calc.icalculate(atoms):
34 if ctx.niter == 2:
35 # logerr1 = np.log10(calc.wfs.eigensolver.error)
36 logerr1 = np.log10(ctx.wfs.eigensolver.error)
38 atoms.positions[:, 2] -= 2 * dz
40 if not reuse and not calc.old:
41 calc.dft.ibzwfs.move_wave_functions = lambda *args: None
43 for ctx in calc.icalculate(atoms, system_changes=['positions']):
44 if ctx.niter == 2:
45 logerr2 = np.log10(ctx.wfs.eigensolver.error)
46 break
48 if world.rank == 0:
49 print(f'reuse={bool(reuse)}')
50 print('logerr1', logerr1)
51 print('logerr2', logerr2)
52 gain = logerr2 - logerr1
53 print('gain', gain)
54 return logerr2
56 noreuse_logerr = check(0)
57 reuse_logerr = check(1)
58 # Ref values: logerr=-4.8 without reuse_wfs and -6.1 with reuse_wfs
59 assert reuse_logerr < -6.0, reuse_logerr
60 assert reuse_logerr < noreuse_logerr - 1.2, (reuse_logerr, noreuse_logerr)