Coverage for gpaw/test/vdw/test_libvdwxc_spin.py: 100%

42 statements  

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

1import pytest 

2from gpaw.utilities import compiled_with_libvdwxc 

3import itertools 

4import numpy as np 

5from gpaw.grid_descriptor import GridDescriptor 

6from gpaw.xc import XC 

7from gpaw.xc.libvdwxc import vdw_df_cx 

8from gpaw.mpi import world 

9 

10pytestmark = pytest.mark.skipif(not compiled_with_libvdwxc(), 

11 reason='not compiled_with_libvdwxc()') 

12 

13 

14@pytest.mark.flaky 

15def test_vdw_libvdwxc_spin(): 

16 def test(xc, tol=5e-10): 

17 N_c = np.array([10, 6, 4]) 

18 # This test is totally serial. 

19 gd = GridDescriptor(N_c, N_c * 0.2, pbc_c=(1, 0, 1), 

20 comm=world.new_communicator([world.rank])) 

21 actual_n = N_c - (1 - gd.pbc_c) 

22 

23 gen = np.random.RandomState(17) 

24 n_sg = gd.zeros(2) 

25 n_sg[:] = gen.rand(*n_sg.shape) 

26 # sigma_xg = gd.zeros(3) 

27 # sigma_xg[:] = gen.random.rand(*sigma_xg.shape) 

28 

29 if hasattr(xc, 'libvdwxc'): 

30 xc._nspins = 2 

31 xc.initialize_backend(gd) 

32 

33 v_sg = gd.zeros(2) 

34 E = xc.calculate(gd, n_sg, v_sg) 

35 print('E', E) 

36 

37 dn = 1e-6 

38 

39 all_indices = itertools.product(range(2), 

40 range(1, actual_n[0], 2), 

41 range(0, actual_n[1], 2), 

42 range(0, actual_n[2], 2)) 

43 

44 for testindex in all_indices: 

45 n1_sg = n_sg.copy() 

46 n2_sg = n_sg.copy() 

47 v = v_sg[testindex] * gd.dv 

48 n1_sg[testindex] -= dn 

49 n2_sg[testindex] += dn 

50 

51 E1 = xc.calculate(gd, n1_sg, v_sg.copy()) 

52 E2 = xc.calculate(gd, n2_sg, v_sg.copy()) 

53 

54 dedn = 0.5 * (E2 - E1) / dn 

55 err = abs(dedn - v) 

56 print('{}{} v={} fd={} err={}'.format(xc.name, list(testindex), 

57 v, dedn, err)) 

58 assert err < tol, err 

59 

60 test(XC('PBE')) 

61 test(vdw_df_cx()) 

62 test(vdw_df_cx(vdwcoef=0.0)) 

63 test(vdw_df_cx(vdwcoef=1e5), tol=2e-6)