Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

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

V=VoVcVs\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 V\mathcal{V} can be expressed in terms of

ψLα(r,t)(10)(10);ψLβ(r,t)(10)(01)\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}
ψSα(r,t)(01)(10);ψSβ(r,t)(01)(01)\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}

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

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

In this general case, the particle density becomes

n(r,t)=ψψ=cL,Sσα,βψcσ(r,t)2n(\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 ψSα\psi^{\mathrm{S}\alpha} and ψSβ\psi^{\mathrm{S}\beta} are small and sometimes ignored, reducing the electronic wave function to its two-component form

ψ(r,t)=(ψLαψLβ)\psi(\mathbf{r},t) = \begin{pmatrix} \psi^{\mathrm{L}\alpha} \\ \psi^{\mathrm{L}\beta} \end{pmatrix}

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

ψ(r)=ϕ(r)σ;σ=cα(10)+cβ(01)\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}

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

ψp(r)=ϕp(r)(10);ψpˉ(r)=ϕp(r)(01)\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}

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)

ϕp(r)=αcαpχα(rRα)\phi_p(\mathbf{r}) = \sum_\alpha c_{\alpha p} \chi_\alpha(\mathbf{r} - \mathbf{R}_\alpha)

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

ϕp=αχαcαp| \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

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

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

ϕ=χC| \overline{\phi} \rangle = | \overline{\chi} \rangle \mathbf{C}

where C\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, ll

  2. Angular momentum quantum number, mlm_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
"""
molecule = vlx.Molecule.read_xyz_string(mol_str)
basis = vlx.MolecularBasis.read(molecule, "sto-3g", ostream=None)

scf_drv = vlx.ScfRestrictedDriver()
scf_drv.ostream.mute()
scf_results = scf_drv.compute(molecule, basis)
molecule.show()
Loading...

The order of basis functions become

χ1sC\chi_{1s}^{C}, χ2sC\chi_{2s}^{C}, χ1sO\chi_{1s}^{O}, χ2sO\chi_{2s}^{O}, χ2pyC\chi_{2py}^{C}, χ2pyO\chi_{2py}^{O}, χ2pzC\chi_{2pz}^{C}, χ2pzO\chi_{2pz}^{O}, χ2pxC\chi_{2px}^{C}, χ2pxO\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.431  0.004  0.891 -0.197 -0.   ]
 [-0.    -0.     0.    -0.     0.     0.847  0.008 -0.535  0.118 -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.004  0.431 -0.197 -0.891  0.   ]
 [ 0.    -0.     0.    -0.    -0.    -0.008  0.847  0.118  0.535  0.   ]]

Overlap matrix

The overlap between two basis functions is

Sαβ=χαχβS_{\alpha\beta} = \langle \chi_\alpha | \chi_\beta \rangle

and the overlap matrix can be written as

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

where

χ=(,χα,)T\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", ostream=None)

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-RCC-MB', 'ANO-S-MB', 'ANO-S-VDZP', 'AO-START-GUESS', 'AO-START-GUESS-FOR-ECP', '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-PV6Z-NO-OPT-GC', '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', 'DEF2-UNIVERSAL-JFIT', 'DEF2-UNIVERSAL-JKFIT', '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.

CategoryCharacterExample
MinimalSingle basis function per occupied atomic orbital, size for second-row elements is [2s1p][2s1p]STO-3G
Double-ζ\zetaTwo basis functions per occupied valence atomic orbital, size for second-row elements is [3s2p][3s2p]6-31G
Triple-ζ\zetaThree basis functions per occupied valence atomic orbital, for second-row elements [4s3p][4s3p]6-311G
PolarizationBasis functions with higher angular momenta; important for chemical bonding; size for second-row elements is [3s2p1d][3s2p1d]cc-pVDZ
DiffuseBasis functions with small exponents; important for excited states; sizes for second-row elements are [4s3p][4s3p] for 6-31+G and [4s3p2d][4s3p2d] for aug-cc-pVDZ6-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()
nprim = basis.get_dimensions_of_primitive_basis()

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

Additional information

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:

print(basis.get_string('Atomic Basis'))
               Molecular Basis (Atomic Basis)               
              ================================              

Basis: CC-PVDZ                                              

  Atom Contracted GTOs           Primitive GTOs                

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

Contracted Basis Functions : 28                             
Primitive Basis Functions  : 68