Coverage for gpaw/xc/ri/__init__.py: 94%

52 statements  

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

1from gpaw.xc import XC 

2from gpaw.utilities import pack_hermitian, unpack_density 

3from gpaw.hybrids.paw import pawexxvv 

4import numpy as np 

5 

6 

7def RI(name, **args): 

8 if name == 'HSE06WIP': 

9 return RIXC(name, exx_fraction=0.25, 

10 omega=0.11, localxc='HYB_GGA_XC_HSE06') 

11 raise NotImplementedError(f'RI backend does not support ' 

12 f'functional called: {name}.') 

13 

14 

15EXXCW_NONE_ERROR = 'The setup does not contain erfc-screened exchange '\ 

16 'core-core energy for given omega.' 

17 

18 

19class RIXC: 

20 orbital_dependent = False # SIC! 

21 type = 'ri' 

22 # orbital_dependent_lcao = True 

23 # type = 'auxhybrid' 

24 

25 def __init__(self, name, *, exx_fraction=None, omega=None, localxc=None): 

26 self.name = name 

27 self.exx_fraction = exx_fraction 

28 self.omega = omega 

29 self.localxc = XC(localxc) 

30 

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

32 self.density = density 

33 self.ecc = 0 

34 for setup in wfs.setups: 

35 if self.omega is not None: 

36 if setup.ExxC_w is None: 

37 raise RuntimeError(EXXCW_NONE_ERROR) 

38 self.ecc += setup.ExxC_w[self.omega] * self.exx_fraction 

39 else: 

40 self.ecc += setup.ExxC * self.exx_fraction 

41 # self.ri_algorithm.initialize(density, hamiltonian, wfs) 

42 

43 def get_setup_name(self): 

44 return 'PBE' 

45 

46 def set_grid_descriptor(self, gd): 

47 pass 

48 

49 def set_positions(self, spos_ac): 

50 pass 

51 

52 def get_description(self): 

53 return f'Resolution of identity (RI) for {self.name} functional.\n'\ 

54 f' EXX fraction: {self.exx_fraction}\n'\ 

55 f' Kernel : erfc(wr)/r\n'\ 

56 f' omega (w) : {self.omega}\n' 

57 

58 def calculate(self, gd, nt_sr, vt_sr): 

59 """ 

60 Calculate the semi-local potential of the hybrid. 

61 """ 

62 # if self.use_lda: 

63 # return self.ldaxc.calculate(gd, nt_sr, vt_sr) 

64 energy = self.ecc # + self.evv + self.evc 

65 energy += self.localxc.calculate(gd, nt_sr, vt_sr) 

66 return energy 

67 

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

69 E = self.localxc.calculate_paw_correction(setup, D_sp, dH_sp, a=a) 

70 

71 for s, (dH_p, D_p) in enumerate(zip(dH_sp, D_sp)): 

72 D_ii = unpack_density(D_p) 

73 V_ii = pawexxvv(setup.M_wpp[self.omega], D_ii) # *(dens.nspins/2) 

74 dH_p += pack_hermitian(V_ii) 

75 

76 E += np.sum(V_ii.ravel() * D_ii.ravel()) # * prefactor 

77 

78 dH_p -= self.density.setups[a].X_p * self.exx_fraction 

79 E -= self.exx_fraction * np.dot(D_p, self.density.setups[a].X_p) 

80 

81 return E 

82 

83 def get_kinetic_energy_correction(self): 

84 return 0 # self.ekin 

85 

86 def summary(self, log): 

87 # Take no changes 

88 # if self.use_lda: 

89 # raise ValueError('Error: Due to an 

90 # internal error, LDA was used thorough the calculation.') 

91 

92 log(self.get_description())