1"""BSSE: Basis Set Superposition Error module.
2
3Defines a Setup-like class which has no properties that change anything,
4except for an atomic basis set."""
5
6import numpy as np
7from ase.data import atomic_numbers
8
9from gpaw.setup import BaseSetup, LocalCorrectionVar
10from gpaw.spline import Spline
11from gpaw.utilities import min_locfun_radius
12
13
14# Some splines are mandatory,
15# but should then be zero to avoid affecting things
16zero_function = Spline(0, min_locfun_radius, [0.0, 0.0, 0.0])
17
18# Some operations fail horribly if the splines are zero, due to weird
19# divisions and assumptions that various quantities are nonzero
20#
21# We'll use a function which is almost zero for these things
22nonzero_function = Spline(0, min_locfun_radius, [0.0, 1.0e-12, 0.0])  # XXX
23
24
25class GhostSetup(BaseSetup):
26    def __init__(self, basis, data):
27        self.symbol = data.symbol
28        self.data = data
29        self.phit_j = basis.tosplines()
30        self.basis = basis
31        self.nao = sum([2 * phit.get_angular_momentum_number() + 1
32                        for phit in self.phit_j])
33        self.HubU = None
34        self.filename = None
35        self.fingerprint = None
36        self.type = 'ghost'
37
38        self.Z = 0
39        self.Nv = 0
40        self.Nc = 0
41
42        self.ni = 1
43        self.pt_j = [zero_function]
44        self.wg_lg = None
45        self.g_lg = None
46
47        self.Nct = 1e-12  # XXX XXX XXX XXX
48        self.nct = nonzero_function  # XXXXXX
49        self.lmax = 0
50        self.xc_correction = None
51        self.ghat_l = [nonzero_function] * (self.lmax + 1)  # XXXXXX
52        self.rcgauss = 1e12  # XXX XXX XXX XXX
53        self.vbar = zero_function
54
55        self.Delta0 = 0.0
56        self.Delta_pL = np.zeros((1, self.lmax + 1))
57
58        self.E = 0.0
59        self.Kc = 0.0
60        self.M = 0.0
61        self.M_p = np.zeros(1)
62        self.M_pp = np.zeros((1, 1))
63        self.K_p = np.zeros(1)
64        self.MB = 0.0
65        self.MB_p = np.zeros(1)
66        self.dO_ii = np.zeros((1, 1))
67        self.f_j = [0.0]
68        self.n_j = [0]
69        self.l_j = [0]
70        self.l_orb_j = [0]
71        self.nj = 1
72        self.lq = None  # XXXX
73
74        self.rcutfilter = None
75        self.rcore = None
76        self.N0_p = np.zeros(1)
77        self.nabla_iiv = np.zeros((self.ni, self.ni, 3))
78        self.rxnabla_iiv = np.zeros((self.ni, self.ni, 3))
79        self.phicorehole_g = None
80        self.rgd = None
81        self.rcut_j = [0.5]
82        self.tauct = None
83        self.Delta_iiL = None
84        self.B_ii = None
85        self.dC_ii = None
86        self.X_p = None
87        self.X_pg = None
88        self.ExxC = None
89        self.X_gamma = None
90        self.dEH0 = 0.0
91        self.dEH_p = np.zeros(1)
92        self.extra_xc_data = {}
93        self.local_corr = LocalCorrectionVar(None)
94        self._Mg_pp = None
95        self._gamma = None
96
97
98class GhostSetupData:
99    def __init__(self, symbol):
100        self.chemsymbol = symbol
101        self.symbol = symbol + '.ghost'
102        self.Z = atomic_numbers[symbol]
103
104    def build(self, xcfunc, lmax, basis, filter=None):
105        if basis is None:
106            raise ValueError('Loading partial waves not supported right now')
107        setup = GhostSetup(basis, self)
108        return setup
109
110    def print_info(self, text, _setup):
111        text('Ghost setup for %s' % self.chemsymbol)
112