Coverage for gpaw/test/noncollinear/test_soc.py: 98%

58 statements  

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

1"""Test HOMO and LUMO band-splitting for MoS2. 

2 

3See: 

4 

5 https://journals.aps.org/prb/abstract/10.1103/PhysRevB.98.155433 

6""" 

7 

8import numpy as np 

9import pytest 

10from ase.build import mx2 

11from gpaw import GPAW 

12import gpaw.mpi as mpi 

13from gpaw.spinorbit import soc_eigenstates 

14from gpaw.berryphase import polarization_phase 

15from pathlib import Path 

16 

17 

18def check(E, hsplit, lsplit): 

19 print(E) 

20 h1, h2, l1, l2 = E[24:28] # HOMO-1, HOMO, LUMO, LUMO+1 

21 print(h2 - h1) 

22 print(l2 - l1) 

23 assert abs(h2 - h1 - hsplit) < 0.01 

24 assert abs(l2 - l1 - lsplit) < 0.002 

25 

26 

27def check_pol(phi_c): 

28 pol_c = (phi_c / (2 * np.pi)) % 1 

29 assert abs(pol_c[0] - 2 / 3) < 0.01 

30 assert abs(pol_c[1] - 1 / 3) < 0.01 

31 

32 

33params = dict(mode={'name': 'pw', 'ecut': 350}, 

34 kpts={'size': (3, 3, 1), 'gamma': True}) 

35 

36 

37@pytest.mark.soc 

38@pytest.mark.skipif(mpi.size > 2, reason='May not work in parallel') 

39def test_soc_self_consistent(gpaw_new, in_tmp_dir): 

40 """Self-consistent SOC.""" 

41 gpw_wfs = Path('mos2.gpw') 

42 a = mx2('MoS2') 

43 a.center(vacuum=3, axis=2) 

44 

45 if gpaw_new: 

46 kwargs = {**params, 'symmetry': 'off', 

47 'magmoms': np.zeros((3, 3)), 'soc': True} 

48 else: 

49 kwargs = {**params, 'symmetry': 'off', 

50 'experimental': {'magmoms': np.zeros((3, 3)), 'soc': True}} 

51 

52 a.calc = GPAW(convergence={'bands': 28}, **kwargs) 

53 a.get_potential_energy() 

54 eigs = a.calc.get_eigenvalues(kpt=0) 

55 check(eigs, 0.15, 0.002) 

56 

57 a.calc.write(gpw_wfs, 'all') 

58 GPAW(gpw_wfs) 

59 

60 if mpi.size == 1: 

61 phases_c = polarization_phase(gpw_wfs, comm=mpi.world) 

62 phi_c = phases_c['electronic_phase_c'] 

63 check_pol(phi_c) 

64 

65 

66@pytest.mark.soc 

67@pytest.mark.skipif(mpi.size > 2, 

68 reason='Does not work with more than 2 cores') 

69def test_non_collinear_plus_soc(): 

70 a = mx2('MoS2') 

71 a.center(vacuum=3, axis=2) 

72 

73 a.calc = GPAW(experimental={'magmoms': np.zeros((3, 3)), 'soc': False}, 

74 convergence={'bands': 28}, symmetry='off', 

75 parallel={'domain': 1}, **params) 

76 a.get_potential_energy() 

77 

78 bzwfs = soc_eigenstates(a.calc, n2=28) 

79 eigs = bzwfs.eigenvalues()[8] 

80 check(eigs, 0.15, 0.007) 

81 

82 

83@pytest.mark.soc 

84def test_soc_non_self_consistent(): 

85 """Non self-consistent SOC.""" 

86 a = mx2('MoS2') 

87 a.center(vacuum=3, axis=2) 

88 

89 a.calc = GPAW(convergence={'bands': 14}, **params) 

90 a.get_potential_energy() 

91 

92 bzwfs = soc_eigenstates(a.calc, n2=14) 

93 eigs = bzwfs.eigenvalues()[8] 

94 check(eigs, 0.15, 0.007)