# Orbitals and basis sets#

## Electronic wave functions and molecular orbitals#

State vectors representing single-electron systems reside in a Hilbert space formed as a direct product

$\mathcal{V} = \mathcal{V}^\mathrm{o} \otimes \mathcal{V}^\mathrm{c} \otimes \mathcal{V}^\mathrm{s}$

The underlying vector spaces are associated with orbital, charge, and spin degrees of freedom. The elements of $$\mathcal{V}$$ can be expressed in terms of

$\begin{split} \psi^{\mathrm{L}\alpha}(\mathbf{r},t) \otimes \begin{pmatrix} 1\\0 \end{pmatrix} \otimes \begin{pmatrix} 1\\0 \end{pmatrix}; \quad \psi^{\mathrm{L}\beta}(\mathbf{r},t) \otimes \begin{pmatrix} 1\\0 \end{pmatrix} \otimes \begin{pmatrix} 0\\1 \end{pmatrix} \end{split}$
$\begin{split} \psi^{\mathrm{S}\alpha}(\mathbf{r},t) \otimes \begin{pmatrix} 0\\1 \end{pmatrix} \otimes \begin{pmatrix} 1\\0 \end{pmatrix} ; \quad \psi^{\mathrm{S}\beta}(\mathbf{r},t) \otimes \begin{pmatrix} 0\\1 \end{pmatrix} \otimes \begin{pmatrix} 0\\1 \end{pmatrix} \end{split}$

with a sum that equals a general wave function for a single-electron system, also known as a spinor

$\begin{split} \psi(\mathbf{r},t) = \begin{pmatrix} \psi^{\mathrm{L}\alpha} \\ \psi^{\mathrm{L}\beta} \\ \psi^{\mathrm{S}\alpha} \\ \psi^{\mathrm{S}\beta} \end{pmatrix} \end{split}$

In this general case, the particle density becomes

$n(\mathbf{r},t) = \psi^\dagger \psi = \sum_\mathrm{c}^{\mathrm{L,S}} \sum_\sigma^{\alpha,\beta} \left| \psi^{\mathrm{c}\sigma}(\mathbf{r},t) \right|^2$

Spinor components $$\psi^{\mathrm{S}\alpha}$$ and $$\psi^{\mathrm{S}\beta}$$ are small and sometimes ignored, reducing the electronic wave function to its two-component form

$\begin{split} \psi(\mathbf{r},t) = \begin{pmatrix} \psi^{\mathrm{L}\alpha} \\ \psi^{\mathrm{L}\beta} \end{pmatrix} \end{split}$

For a system described by a spin-independent Hamiltonian, the spatial and spin degrees of freedom are separable and we arrive at (suppressing the time variable) single-electron wave functions, or spin orbitals, of the form

$\begin{split} \psi(\mathbf{r}) = \phi(\mathbf{r}) \sigma ; \quad \sigma = c_\alpha \begin{pmatrix} 1 \\ 0 \end{pmatrix} + c_\beta \begin{pmatrix} 0 \\ 1 \end{pmatrix} \end{split}$

In the collinear approximation, all spin orbitals are eigenfunctions of the spin operator $$\hat{s}_z$$ such that every spatial function (or molecular orbital), $$\phi(\mathbf{r})$$, gives rise to two spin orbitals

$\begin{split} \psi_{p}(\mathbf{r}) = \phi_p(\mathbf{r}) \begin{pmatrix} 1 \\ 0 \end{pmatrix} ; \quad \psi_{\bar{p}}(\mathbf{r}) = \phi_p(\mathbf{r}) \begin{pmatrix} 0 \\ 1 \end{pmatrix} \end{split}$

referred to as $$\alpha$$- and $$\beta$$-spin orbitals, respectively.

### Linear combination of atomic orbitals#

In quantum chemistry, molecular orbitals (MOs) are normally expanded in a set of atom-centered basis functions, or localized atomic orbitals (AOs)

$\phi_p(\mathbf{r}) = \sum_\alpha c_{\alpha p} \chi_\alpha(\mathbf{r} - \mathbf{R}_\alpha)$

where $$\mathbf{R}_\alpha$$ denotes the atomic position center of basis function $$\chi_\alpha$$, and the expansion coefficients $$c_{\alpha p}$$ are known as molecular orbital (MO) coefficients. Using the Dirac notation, this linear combination of atomic orbitals (LCAO) expansion takes the form

$| \phi_p \rangle = \sum_\alpha | \chi_\alpha \rangle c_{\alpha p}$

It can be convenient to collect the set of MOs (and AOs) as a row vector and introduce a notation

$| \overline{\phi} \rangle = (\ldots, | \phi_p \rangle, \ldots)$

The LCAO expansion for the entire set of MOs can then be compactly written as

$| \overline{\phi} \rangle = | \overline{\chi} \rangle \mathbf{C}$

where $$\mathbf{C}$$ is the MO coefficient matrix.

### Ordering of atomic orbitals#

The VeloxChem program orders AO basis functions based on

1. Angular momentum quantum number, $$l$$

2. Angular momentum quantum number, $$m_l$$

3. User-defined order of atoms

Considering carbon monoxide using a minimal basis set

import veloxchem as vlx

mol_str = """2

C        0.00000000    0.00000000   -0.71500000
O        0.00000000    0.00000000    0.71500000
"""

scf_drv = vlx.ScfRestrictedDriver()
scf_results = scf_drv.compute(molecule, basis)


You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
jupyter labextension install jupyterlab_3dmol

The order of basis functions become

$$\chi_{1s}^{C}$$, $$\chi_{2s}^{C}$$, $$\chi_{1s}^{O}$$, $$\chi_{2s}^{O}$$ $$\chi_{2py}^{C}$$, $$\chi_{2py}^{O}$$, $$\chi_{2pz}^{C}$$, $$\chi_{2pz}^{O}$$, $$\chi_{2px}^{C}$$, $$\chi_{2px}^{O}$$

And the resulting MO coefficients are available as

import numpy as np

np.set_printoptions(precision=3, suppress=True, linewidth=170)

C = scf_results["C_alpha"]
print("MO coefficient matrix:\n", C)

MO coefficient matrix:
[[ 0.001  0.994  0.091 -0.228  0.109 -0.    -0.     0.    -0.     0.105]
[-0.004  0.024 -0.26   0.836 -0.47   0.     0.    -0.     0.    -0.536]
[ 0.995  0.     0.231  0.114  0.036 -0.    -0.    -0.     0.    -0.089]
[ 0.023 -0.005 -0.856 -0.526 -0.196  0.     0.     0.    -0.     0.547]
[-0.    -0.    -0.     0.    -0.    -0.299 -0.311  0.912  0.014 -0.   ]
[-0.     0.    -0.     0.    -0.    -0.587 -0.61  -0.548 -0.008  0.   ]
[-0.004  0.004 -0.141 -0.003  0.621 -0.    -0.    -0.     0.    -0.942]
[-0.003  0.002  0.112 -0.38  -0.578  0.     0.    -0.     0.    -0.852]
[ 0.     0.     0.     0.     0.    -0.311  0.299  0.014 -0.912 -0.   ]
[ 0.    -0.    -0.    -0.    -0.    -0.61   0.587 -0.008  0.548  0.   ]]


### Overlap matrix#

The overlap between two basis functions is

$S_{\alpha\beta} = \langle \chi_\alpha | \chi_\beta \rangle$

and the overlap matrix can be written as

$\mathbf{S} = \langle \overline{\chi} | \overline{\chi} \rangle$

where

$\langle \overline{\chi} | = (\ldots, \langle \chi_\alpha |, \ldots)^T$
S = scf_results["S"]
print("Overlap matrix:\n", S)

Overlap matrix:
[[ 1.     0.248  0.     0.017  0.     0.     0.    -0.031  0.     0.   ]
[ 0.248  1.     0.022  0.255  0.     0.     0.    -0.251  0.     0.   ]
[ 0.     0.022  1.     0.237  0.     0.     0.036  0.     0.     0.   ]
[ 0.017  0.255  0.237  1.     0.     0.     0.337  0.     0.     0.   ]
[ 0.     0.     0.     0.     1.     0.132  0.     0.     0.     0.   ]
[ 0.     0.     0.     0.     0.132  1.     0.     0.     0.     0.   ]
[ 0.     0.     0.036  0.337  0.     0.     1.    -0.285  0.     0.   ]
[-0.031 -0.251  0.     0.     0.     0.    -0.285  1.     0.     0.   ]
[ 0.     0.     0.     0.     0.     0.     0.     0.     1.     0.132]
[ 0.     0.     0.     0.     0.     0.     0.     0.     0.132  1.   ]]


## Basis sets of atomic orbitals#

### Assign to molecule#

A basis set object associated with a molecule can be created with the read method.

basis = vlx.MolecularBasis.read(molecule, "cc-pVDZ")


### Basis set library#

Our software comes distributed with several of the standard basis sets and families of basis sets. For a given element, the available basis sets in the VeloxChem library can be provided with the get_avail_basis. Should a basis set not be included in the software distribution, it can be readily supplied by the user in a separate file in the working directory, with basis set parameters available from, e.g., Basis Set Exchange.

print("Available basis sets for carbon:\n", basis.get_avail_basis("C"))

Available basis sets for carbon:
['6-31++G', '6-31++G*', '6-31++G**', '6-31+G', '6-31+G*', '6-31+G**', '6-311++G', '6-311++G(2D,2P)', '6-311++G(3DF,3PD)', '6-311++G*', '6-311++G**', '6-311+G', '6-311+G(2D,P)', '6-311+G*', '6-311+G**', '6-311G', '6-311G(2DF,2PD)', '6-311G*', '6-311G**', '6-31G', '6-31G(2DF,P)', '6-31G(3DF,3PD)', '6-31G*', '6-31G**', 'ANO-L-MB', 'ANO-L-VDZP', 'ANO-L-VQZP', 'ANO-L-VTZP', 'ANO-S-MB', 'ANO-S-VDZP', 'AO-START-GUESS', 'AUG-CC-PCV5Z', 'AUG-CC-PCVDZ', 'AUG-CC-PCVQZ', 'AUG-CC-PCVTZ', 'AUG-CC-PV5Z', 'AUG-CC-PV6Z', 'AUG-CC-PVDZ', 'AUG-CC-PVQZ', 'AUG-CC-PVTZ', 'AUG-PCSEG-0', 'AUG-PCSEG-1', 'AUG-PCSEG-2', 'AUG-PCSEG-3', 'AUG-PCSEG-4', 'AUG-PCX-1', 'AUG-PCX-2', 'AUG-PCX-3', 'AUG-PCX-4', 'CC-PCV5Z', 'CC-PCVDZ', 'CC-PCVQZ', 'CC-PCVTZ', 'CC-PV5Z', 'CC-PV6Z', 'CC-PVDZ', 'CC-PVQZ', 'CC-PVTZ', 'DAUG-CC-PCV5Z', 'DAUG-CC-PCVDZ', 'DAUG-CC-PCVQZ', 'DAUG-CC-PCVTZ', 'DAUG-CC-PV5Z', 'DAUG-CC-PV6Z', 'DAUG-CC-PVDZ', 'DAUG-CC-PVQZ', 'DAUG-CC-PVTZ', 'DEF2-QZVP', 'DEF2-QZVPD', 'DEF2-QZVPP', 'DEF2-QZVPPD', 'DEF2-SV(P)', 'DEF2-SVP', 'DEF2-SVPD', 'DEF2-TZVP', 'DEF2-TZVPD', 'DEF2-TZVPP', 'DEF2-TZVPPD', 'PCSEG-0', 'PCSEG-1', 'PCSEG-2', 'PCSEG-3', 'PCSEG-4', 'PCX-1', 'PCX-2', 'PCX-3', 'PCX-4', 'SADLEJ-PVTZ', 'STO-3G', 'STO-3G-OLD', 'STO-6G', 'TAUG-CC-PCV5Z', 'TAUG-CC-PCVDZ', 'TAUG-CC-PCVQZ', 'TAUG-CC-PCVTZ', 'TAUG-CC-PV5Z', 'TAUG-CC-PV6Z', 'TAUG-CC-PVDZ', 'TAUG-CC-PVQZ', 'TAUG-CC-PVTZ']


Table: Categories of basis set.

Category

Character

Example

Minimal

Single basis function per occupied atomic orbital, size for second-row elements is $$[2s1p]$$

STO-3G

Double-$$\zeta$$

Two basis functions per occupied valence atomic orbital, size for second-row elements is $$[3s2p]$$

6-31G

Triple-$$\zeta$$

Three basis functions per occupied valence atomic orbital, for second-row elements $$[4s3p]$$

6-311G

Polarization

Basis functions with higher angular momenta; important for chemical bonding; size for second-row elements is $$[3s2p1d]$$

cc-pVDZ

Diffuse

Basis functions with small exponents; important for excited states; sizes for second-row elements are $$[4s3p]$$ for 6-31+G and $$[4s3p2d]$$ for aug-cc-pVDZ

6-31+G, aug-cc-pVDZ

### Number of basis functions#

The number of contracted and primitive basis functions are available from the get_dimensions_of_basis and get_dimensions_of_primitive_basis methods, respectively.

nbas = basis.get_dimensions_of_basis(molecule)
nprim = basis.get_dimensions_of_primitive_basis(molecule)

print("Number of contracted basis functions:", nbas)
print("Number of primitive basis functions:", nprim)

Number of contracted basis functions: 28
Number of primitive basis functions: 68


The molecular basis set label is retrieved with the get_label method:

label = basis.get_label()
print("Basis set label:", label)

Basis set label: CC-PVDZ


and additional basis set information is available:

info = basis.get_string(label, molecule)
print(info)

Molecular Basis (CC-PVDZ)
===========================

Basis: CC-PVDZ

Atom Contracted GTOs           Primitive GTOs

O   (3S,2P,1D)                (17S,4P,1D)
C   (3S,2P,1D)                (17S,4P,1D)

Contracted Basis Functions : 28
Primitive Basis Functions  : 68