Basis set (qcip_tools.basis_set)

Theory

Definition

Quantum calculations are, most of the time, based on the LCAO (linear combination of atomic orbitals) principle,

\[\Psi_i = \sum_j^N c_{ij} \phi_{j},\]

where \(c_{ij}\) are coefficient of the linear combination and \(\phi_j\) are the atomic orbitals. The atomic orbitals (or basis functions) are solution of the Hartree-Fock equation for the atom. Slater type obritals (STO, \(\propto e^{-r}\)) are sometimes used to describe the atomic orbitals, due to their similarity to hydrogen atom solutions, but Gaussian type orbitals (GTO) are more convenient from a computationnal point of view. The general expression (in carthesian coordinates) of a GTO centered in \(\mathbf{R}\) is

\[G_{lmn}^{\mathbf{R}, \alpha}(\mathbf{r}) = N_{lmn}^\alpha\,(r_x - R_x)^l\,(r_y-R_y)^m\,(r_z - R_z)^n\,e^{-\alpha\,|\mathbf{r}-\mathbf{R}|^2},\]

where \(\alpha\) (the letter \(\zeta\) is also used) is the exponent of the GTO (which controls the width of the orbital, small \(\alpha\) giving large/diffuse functions), and \(N_{lmn}^\alpha\) is a normalization factor.

To mimic STO’s, a linear combination (a contraction) of GTO’s (primitives) is used to form a basis function.

The sum of exponents \(L=l+m+n\) (which are not quantum numbers) is used analogously to the angular quantum number for atom, to mark function as s-type (\(L=0\)), p-type (\(L=1\)), d-type (\(L=2\)), etc. Primitives (and basis functions) are regrouped in shells (S, P, D, F …), forming a collection of GTO’s with the same \(L\): in each shell \(\mu\), the primitives are contracted in \(n_\mu\) basis functions \(\mu\gamma\) (for example, with s-type basis function, the usual atomic orbitals 1s, 2s, 3s …).

The general expression for an atomic basis set centered in \(\mathbf{R}\) is therefore:

(1)\[\begin{split}\phi^{\mathbf{R}}(\mathbf{r}) = \sum_\mu^{\text{S, P, D, }\ldots}\sum_{(l,m,n)\in \mu} \sum_{\gamma}^{n_\mu} \underbrace{N_{\mu\gamma}\,\sum_k^{n_{\mu\gamma}} c_{\mu\gamma k}\,G_{lmn}^{\mathbf{R}, \alpha_{\mu\gamma k}}(\mathbf{r})}_{\begin{array}{c}\text{basis function}\,\mu\gamma\,\equiv\\\text{contraction of }n_{\mu\gamma}\text{ primitives}\end{array}},\end{split}\]

where \(c_{\mu\gamma k}\) is the contraction coefficient of the primitive \(k\) in basis function \(\mu\gamma\) in shell \(\mu\), to which correspond a exponent \(\alpha_{\mu\gamma k}\). \(N_{\mu\gamma}\) is a normalization constant for the whole basis function \(\gamma\) in \(\mu\).

In the calculation, a LCAO coefficient is associated to each \(\mu\gamma\) basis function.

Construction

Some basis sets are constucted using the same number of basis function in each shell. This number of contractions helps to label the basis set as n-uple \(\zeta\): simple \(\zeta\) (for example the infamous STO-3G), double \(\zeta\) (DZ), triple \(\zeta\) (TZ), quadruple \(\zeta\) (QZ) and so all (5Z, 6Z, …).

On the other hand, since valence orbitals are affected than the core (inner) orbitals by chemical processes, more basis functions (contractions) are sometimes used to describe these (which does not mean more primitives). The corresponding basis sets (for example the Pople basis sets) are sometimes called split-valence. These basis sets are usually structured in such a way that most diffuse primitives (small \(\alpha\)) are left uncontracted. For example, in the 6-31G basis set of Pople, a contraction of 6 primitives is used for core orbitals while 2 contractions (of 3 and 1 primitives, respectively) is used for valence orbitals. It is therefore referred as double \(\zeta\).

Basis sets are frequently augmented with others functions:

  • Polarization functions: functions with higher values of \(L\) than those present in occupied atomic orbitals of the ground state of the corresponding atom (or, strictly speaking, of the noble gas belonging to the same row in the periodic table). They are important for correlated calculations as well as description of bonding. In Pople’s notation, they are indicated in parentheses, for example 6-31G(d) include a d-type basis function.

  • Diffuse functions: primitives with very small (< 0.01 ?) exponent, contained in uncontracted basis functions, that therefore decay slowly with \(|\mathbf{r}-\mathbf{R}|^2\). They are important for the computation of properties, weak bonds (i.e. hydrogen bonds) and long distance interactions. In Pople’s notation, they are indicated by +, for example 6+31G include a p-type diffuse basis function on heavy atoms. Note that “polarization-diffuse” functions are possible (in Dunning “aug” basis sets, for example), although not in Pople’s basis sets.

Note

Shells. Even thought it does not make sense strictly speaking (because of the orthogonality of primitives of different shells), the “SP” shell exists (in Pople basis sets), and define a shell when GTO share the same exponent but different contraction coefficients for the s and p orbitals.

Naming of basis sets. Basis set are named based on arbitrary criterions (with the author name, generally) or more systematically (Pople or Dunning). One notation, used by Dalton and some authors in the literature is [uncontracted set|contracted set]. For example [10s4p1d|3s2p1d] for second row atoms (6-31G* in the notation of Pople), which is constituted of 10 s-type primitives (contracted in 3 s-type basis functions), 4 p-type primitives (contracted in 2 p-type basis functions) and 1 d-type primitive (in one d-type polarization basis function). The representation of a atomic basis function in the code follows this notation.

Basis functions. Therefore, when using a basis set defined by [10s4p1d|3s2p1d] for second row atoms, in means that there is, on an atomic point of view the [1s, 2s, 2p, 3s’, 3p’, 3d’] orbitals (where ‘ represents the added polarization orbitals).

Number of basis basis functions and primitives. Don’t forget that for each p-type “basis function”, there is actually 3 basis function (\(p_x\), \(p_y\) and \(p_z\)) defined, as emphasized by the sum of over \((l,m,n)\in\mu\) in Eq. (1), 5 for each d-type orbitals (or six if one consider the carthesian counterparts), and so all. The same goes for the number of primitives. For example, water with a 6-31+G(d) basis set ([11s5p1d|4s3p1d] for oxygen, [4s|2s] for hydrogen) contains actually 18 basis functions for the oxygen (= \(4\times 1+3\times 3+1\times 5\)) and 31 primitives (= \(11\times 1+5\times 3 + 1\times 5\)), so in total there is 22 basis functions and 39 GTO’s for the water molecule.

Output. By convention, the primitives of a basis set are listed shell by shell, in decrasing order of number of primitive per basis function and starting from the highest coefficient. The code handle that order by sorting internal lists.

Sources

(last consultation on the 18th of August, 2017)

Implementation

A primitive is defined with the Primitive object, and represent basically a contraction coefficient and and exponent. Basis functions are defined with the Function object, which contains the different primitives. For a given atom, one defines a basis set with AtomicBasisSet, in which you define the different basis functions for a given shell (S, P or SP, D, F …). Finally, a basis set is defined by the BasisSet object, which contains the different basis sets for each atoms.

from qcip_tools import basis_set

# STO-3G for hydrogen or oxygen (with SP):
# From ESML basis set exchange
sto3g = basis_set.BasisSet('STO-3G')

bf_H_S = basis_set.Function()
bf_H_S.add_primitive(basis_set.Primitive(3.42525091, 0.15432897))  # exponent, then coefficient
bf_H_S.add_primitive(basis_set.Primitive(0.62391373, 0.53532814))
bf_H_S.add_primitive(basis_set.Primitive(0.16885540, 0.44463454))

b_H = basis_set.AtomicBasisSet('H')  # you can use symbol or atomic number
b_H.add_basis_function('s', bf_H_S)  # you can use upper or lowercase

bf_O_S = basis_set.Function()
bf_O_S.add_primitive(basis_set.Primitive(130.7093200, 0.15432897))
bf_O_S.add_primitive(basis_set.Primitive(23.8088610, 0.53532814))
bf_O_S.add_primitive(basis_set.Primitive(6.4436083, 0.44463454))

bf_O_SP = basis_set.Function()
bf_O_SP.add_primitive(basis_set.Primitive(5.0331513, -0.09996723, 0.15591627))  # "sp" primitives have two coefficients
bf_O_SP.add_primitive(basis_set.Primitive(1.1695961, 0.39951283, 0.60768372))
bf_O_SP.add_primitive(basis_set.Primitive(0.3803890, 0.70011547, 0.39195739))

b_O = basis_set.AtomicBasisSet('O')
b_O.add_basis_function('s', bf_O_S)
b_O.add_basis_function('sp', bf_O_SP)

sto3g.add_atomic_basis_set(b_O)  # add the atomic basis set for oxygen
sto3g.add_atomic_basis_set(b_H)

API documentation

class qcip_tools.basis_set.AtomicBasisSet(symbol=None, atomic_number=None)

Set of basis functions for a given atom.

Parameters:
  • atomic_number (int) – the atomic number

  • symbol (str) – the atom symbol (starting with an upercase letter)

add_basis_function(shell, basis_function)
Parameters:
  • shell (str) – the shell

  • basis_function (Function) – the basis function

class qcip_tools.basis_set.BasisSet(nickname='')

Basis set

Parameters:

nickname (str) – name of the basis set

add_atomic_basis_set(atomic_basis_set, force_replace=True)
Parameters:
  • atomic_basis_set (AtomicBasisSet) – the atomic basis set

  • force_replace – replace if existing (otherwise, raise an exception if already exists)

class qcip_tools.basis_set.Function(normalization=1.0)

Contracted Gaussian type orbital (basis function)

add_primitive(primitive)

Add a GTO to the contraction

Parameters:

primitive (Primitive) – the GTO

is_diffuse(exponent_threshold=0.1)

Test if the function correspond to a diffuse one, based on the following criterions:

  • There is only one primitive in the basis function ;

  • This primitive have a contraction coefficient of 1.0 ;

  • This primitive have a exponent lower than exponent_threshold.

Parameters:

exponent_threshold (float) – threshold for the exponent of the primitive

Return type:

bool

exception qcip_tools.basis_set.NotAValidAngularMomentum
class qcip_tools.basis_set.Primitive(exponent=1.0, contraction_coefficient=1.0, p_coefficient=0.0)

Gaussian type orbital (primitive gaussian function)

Parameters:
  • contraction_coefficient (float) – contraction coefficient

  • p_coefficient (float) – contraction coefficient for the p function (SP orbital)

  • exponent (float) – exponent of the gaussian (also called “zeta”)

qcip_tools.basis_set.SHELL_TO_TAM = {'D': 2, 'F': 3, 'G': 4, 'H': 5, 'I': 6, 'P': 1, 'S': 0, 'SP': -1}

Shell to total angular momentum

qcip_tools.basis_set.TAM_TO_SHELL = {-1: 'SP', 0: 'S', 1: 'P', 2: 'D', 3: 'F', 4: 'G', 5: 'H', 6: 'I'}

total angular momentum to shell