Coverage for gpaw/test/gpu/test_pw.py: 87%

79 statements  

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

1import pytest 

2from ase import Atoms 

3from ase.units import Ha 

4 

5from gpaw.dft import DFT 

6from gpaw.mpi import size 

7from gpaw.poisson import FDPoissonSolver 

8from gpaw.new.c import GPU_AWARE_MPI 

9 

10 

11@pytest.mark.gpu 

12@pytest.mark.serial 

13@pytest.mark.parametrize('dtype', [float, complex]) 

14@pytest.mark.parametrize('gpu', [False, True]) 

15@pytest.mark.parametrize('mode', ['pw', 'fd']) 

16@pytest.mark.parametrize('random', [False, True]) 

17def test_gpu(dtype, gpu, mode, random): 

18 atoms = Atoms('H2') 

19 atoms.positions[1, 0] = 0.75 

20 atoms.center(vacuum=1.0) 

21 if mode == 'fd': 

22 kwargs = {'poissonsolver': FDPoissonSolver(), 

23 'h': 0.17} 

24 else: 

25 kwargs = {} 

26 dft = DFT( 

27 atoms, 

28 mode={'name': mode, 

29 'force_complex_dtype': dtype == complex}, 

30 random=random, 

31 convergence={'density': 1e-8}, 

32 parallel={'gpu': gpu}, 

33 setups='paw', 

34 **kwargs) 

35 dft.converge() 

36 dft.energy() 

37 energy = dft.results['energy'] * Ha 

38 if mode == 'pw': 

39 assert energy == pytest.approx(-16.032945, abs=1e-6) 

40 else: 

41 assert energy == pytest.approx(5.07197289, abs=1e-6) 

42 

43 

44@pytest.mark.gpu 

45@pytest.mark.skipif(size > 2, reason='Not implemented') 

46@pytest.mark.parametrize('gpu', [False, True]) 

47@pytest.mark.parametrize('par', ['domain', 'kpt', 'band']) 

48@pytest.mark.parametrize('mode', ['pw', 'fd']) 

49@pytest.mark.parametrize('xc', ['LDA', 'PBE']) 

50def test_gpu_k(gpu, par, mode, xc): 

51 if gpu and size > 1 and not GPU_AWARE_MPI: 

52 if mode == 'fd' and par == 'domain': 

53 pytest.skip('Domain decomposition needs GPU-aware MPI') 

54 if mode == 'pw' and par == 'domain' and xc == 'PBE': 

55 pytest.skip('Domain decomposition needs GPU-aware MPI') 

56 if mode == 'fd': 

57 pytest.skip('???') 

58 if mode == 'pw' and par in ['kpt', 'band'] and xc == 'PBE': 

59 pytest.skip('???') 

60 

61 if gpu and size > 1: 

62 if mode == 'fd' and par == 'band': 

63 pytest.skip('FAILING') 

64 

65 if size == 1 and par in ['kpt', 'band']: 

66 pytest.skip('Not testing parallelization on single core') 

67 

68 atoms = Atoms('H', pbc=True, cell=[1, 1.1, 1.1]) 

69 if mode == 'fd': 

70 poisson = FDPoissonSolver() 

71 h = 0.09 

72 else: 

73 poisson = None 

74 h = None 

75 

76 dft = DFT( 

77 atoms, 

78 mode={'name': mode}, 

79 spinpol=True, 

80 xc=xc, 

81 h=h, 

82 convergence={'density': 1e-8}, 

83 kpts=(4, 1, 1), 

84 poissonsolver=poisson, 

85 parallel={'gpu': gpu, 

86 par: size}, 

87 setups='paw') 

88 dft.converge() 

89 dft.energy() 

90 if mode == 'pw': 

91 dft.forces() 

92 dft.stress() 

93 energy = dft.results['energy'] * Ha 

94 ref = {'LDAfd': -17.685022604078714, 

95 'PBEfd': -17.336991943070384, 

96 'PBEpw': -17.304186, 

97 'LDApw': -17.653433}[xc + mode] 

98 assert energy == pytest.approx(ref, abs=1e-6) 

99 

100 

101@pytest.mark.gpu 

102def test_2d(): 

103 atoms = Atoms('H', pbc=[True, True, False], cell=[1, 1, 5]) 

104 atoms.center(axis=2) 

105 

106 dft = DFT( 

107 atoms, 

108 mode={'name': 'pw'}, 

109 spinpol=True, 

110 xc='LDA', 

111 convergence={'density': 1e-8}, 

112 kpts=(2, 2, 1), 

113 parallel={'gpu': True}) 

114 dft.converge() 

115 assert dft.potential.get_vacuum_level() == pytest.approx(2.9436, 1e-2) 

116 dft.energy() 

117 dft.forces() 

118 dft.stress() 

119 E = dft.results['energy'] 

120 F = dft.results['forces'] 

121 S = dft.results['stress'] 

122 assert E == pytest.approx(0.1769, 1e-2) 

123 assert F[0] == pytest.approx([0, 0, 0], 1e-6) 

124 assert S == pytest.approx([-0.0110, -0.0110, 0.0002, 

125 0.0, 0.0, 0.0], abs=0.001)