Coverage for gpaw/test/directopt/test_grad_numerically_pw.py: 100%

33 statements  

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

1import pytest 

2import numpy as np 

3 

4from gpaw import GPAW 

5from gpaw.directmin.etdm_fdpw import FDPWETDM 

6from gpaw.directmin.derivatives import Derivatives 

7from gpaw.mom import prepare_mom_calculation 

8 

9 

10@pytest.mark.do 

11def test_gradient_numerically_pw(in_tmp_dir, gpw_files): 

12 """ 

13 Test analytical vs. numerical gradients exponential 

14 transformation in pw 

15 :param in_tmp_dir: 

16 :return: 

17 """ 

18 

19 tol_between_methods = dict(abs=1.0e-4) 

20 tol_between_rngs = dict(abs=1.0e-4) 

21 

22 for calc in [ 

23 GPAW(gpw_files["h3_do_num_pw_complex"]), 

24 GPAW(gpw_files["h3_do_num_pw"]), 

25 ]: 

26 atoms = calc.atoms 

27 atoms.calc = calc 

28 # Repeated for False 

29 atoms.get_potential_energy() 

30 

31 calc.set(eigensolver=FDPWETDM(excited_state=True)) 

32 f_sn = [calc.get_occupation_numbers(spin=s).copy() / 2 

33 for s in range(calc.wfs.nspins)] 

34 prepare_mom_calculation(calc, atoms, f_sn, use_fixed_occupations=True) 

35 atoms.get_potential_energy() 

36 

37 ham = calc.hamiltonian 

38 wfs = calc.wfs 

39 dens = calc.density 

40 

41 rngs = [np.random.default_rng(8), 

42 np.random.default_rng(123456)] 

43 ders = [Derivatives(wfs.eigensolver.outer_iloop, 

44 wfs, 

45 random_amat=rng, 

46 update_c_ref=True) 

47 for rng in rngs] 

48 

49 iut = np.triu_indices(ders[0].a[0].shape[0], 1) 

50 analytical_results = [ 

51 der.get_analytical_derivatives( 

52 wfs.eigensolver.outer_iloop, ham, wfs, dens)[0][iut] 

53 for der in ders] 

54 numerical_results = [ 

55 der.get_numerical_derivatives( 

56 wfs.eigensolver.outer_iloop, ham, wfs, dens)[0] 

57 for der in ders] 

58 

59 # Test 1: consistency between methods (numerical v. analytic) 

60 for an, num in zip(analytical_results, numerical_results): 

61 assert num.real == pytest.approx(an.real, **tol_between_methods) 

62 assert num.imag == pytest.approx(an.imag, **tol_between_methods) 

63 

64 # Test 2: consistency between results obtained from different random 

65 # RNGs 

66 x, *ys = analytical_results 

67 for y in ys: 

68 assert y.real == pytest.approx(x.real, **tol_between_rngs) 

69 assert y.imag == pytest.approx(x.imag, **tol_between_rngs)