Coverage for gpaw/xc/functional.py: 94%

62 statements  

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

1import numpy as np 

2from gpaw.xc.kernel import XCKernel 

3 

4 

5class XCFunctional: 

6 orbital_dependent = False 

7 xp = np 

8 

9 def __init__(self, name: str, type: str): 

10 self.name = name 

11 self.gd = None 

12 self.ekin = 0.0 

13 self.type = type 

14 self.kernel: XCKernel 

15 

16 def todict(self): 

17 """Get dictionary representation of XC functional. 

18 

19 This representation works for libxc kernels; other classes should 

20 likely override this function and should probably not rely on 

21 this implementation.""" 

22 return {'type': self.kernel.type, 

23 'kernel': self.kernel.name} 

24 

25 def tostring(self): 

26 """Get string representation of XC functional. 

27 

28 This will give the name for libxc functionals but other data for 

29 hybrids.""" 

30 return self.name 

31 

32 def get_setup_name(self): 

33 return self.name 

34 

35 def initialize(self, density, hamiltonian, wfs): 

36 pass 

37 

38 def set_grid_descriptor(self, gd): 

39 self.gd = gd 

40 

41 def calculate(self, gd, n_sg, v_sg=None, e_g=None): 

42 """Calculate energy and potential. 

43 

44 gd: GridDescriptor 

45 Descriptor for 3-d grid. 

46 n_sg: rank-4 ndarray 

47 Spin densities. 

48 v_sg: rank-4 ndarray 

49 Array for potential. The XC potential is added to the values 

50 already there. 

51 e_g: rank-3 ndarray 

52 Energy density. Values must be written directly, not added. 

53 

54 The total XC energy is returned.""" 

55 

56 if gd is not self.gd: 

57 self.set_grid_descriptor(gd) 

58 if e_g is None: 

59 e_g = gd.empty() 

60 if v_sg is None: 

61 v_sg = np.zeros_like(n_sg) 

62 self.calculate_impl(gd, n_sg, v_sg, e_g) 

63 return gd.integrate(e_g) 

64 

65 def calculate_impl(self, gd, n_sg, v_sg, e_g): 

66 raise NotImplementedError 

67 

68 def calculate_paw_correction(self, setup, D_sp, dEdD_sp=None, a=None): 

69 raise NotImplementedError 

70 

71 def set_positions(self, spos_ac, atom_partition=None): 

72 pass 

73 

74 def get_description(self): 

75 """Get long description of functional as a string, or None.""" 

76 return None 

77 

78 def summary(self, fd): 

79 """Write summary of last calculation to file.""" 

80 pass 

81 

82 def write(self, writer, natoms=None): 

83 pass 

84 

85 def read(self, reader): 

86 pass 

87 

88 def estimate_memory(self, mem): 

89 pass 

90 

91 # Orbital dependent stuff: 

92 def apply_orbital_dependent_hamiltonian(self, kpt, psit_nG, 

93 Htpsit_nG, dH_asp=None): 

94 pass 

95 

96 def correct_hamiltonian_matrix(self, kpt, H_nn): 

97 # In what sense? Some documentation here maybe? 

98 pass 

99 

100 def add_correction(self, kpt, psit_xG, R_xG, P_axi, c_axi, n_x=None, 

101 calculate_change=False): 

102 # Which kind of correction is this? Maybe some kind of documentation 

103 # could be written? What is required of an implementation? 

104 pass 

105 

106 def rotate(self, kpt, U_nn): 

107 pass 

108 

109 def get_kinetic_energy_correction(self): 

110 return self.ekin 

111 

112 def add_forces(self, F_av): 

113 pass 

114 

115 def stress_tensor_contribution(self, n_sg, skip_sum=False): 

116 raise NotImplementedError('Calculation of stress tensor is not ' + 

117 f'implemented for {self.name}') 

118 

119 def calculate_spherical(self, rgd, n_sg, v_sg, e_g=None): 

120 raise NotImplementedError