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
« 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
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}.')
15EXXCW_NONE_ERROR = 'The setup does not contain erfc-screened exchange '\
16 'core-core energy for given omega.'
19class RIXC:
20 orbital_dependent = False # SIC!
21 type = 'ri'
22 # orbital_dependent_lcao = True
23 # type = 'auxhybrid'
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)
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)
43 def get_setup_name(self):
44 return 'PBE'
46 def set_grid_descriptor(self, gd):
47 pass
49 def set_positions(self, spos_ac):
50 pass
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'
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
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)
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)
76 E += np.sum(V_ii.ravel() * D_ii.ravel()) # * prefactor
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)
81 return E
83 def get_kinetic_energy_correction(self):
84 return 0 # self.ekin
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.')
92 log(self.get_description())