This notebook runs an actual Hartree-Fock (self-consistent field) calculation on atoms using the PySCF quantum chemistry package, and visualizes the resulting orbitals. It complements the Hartree-Fock lecture page, where the theory (Slater determinant, Fock operator, SCF cycle) is developed.
This demo uses the following libraries (already installed for the site build; on your own machine, pip install pyscf py3Dmol plotly):
Hartree-Fock energies and orbitals of alkali-metal atoms¶
The function below builds an atom in a minimal STO-3G basis, runs a restricted open-shell Hartree-Fock calculation, extracts the molecular-orbital energies, and writes a cube file for the highest occupied molecular orbital (HOMO) so it can be visualized with py3Dmol.
import py3Dmol
from pyscf import gto, scf
from pyscf.tools import cubegen
# Function to calculate orbitals and energies for a given atom
def calculate_orbitals_energies(atom_symbol):
"""
Calculate the orbitals and energies for a given atom using PySCF.
Parameters:
atom_symbol (str): Symbol of the atom (e.g., 'He', 'Li').
Returns:
dict: A dictionary containing the total energy, MO coefficients, and MO energies.
"""
# Define the atom and basis set
mol = gto.Mole()
mol.atom = [(atom_symbol, (0, 0, 0))] # Specify the atom and its position
mol.basis = 'sto-3g' # Basis set
mol.spin = 1 # 2S = 1, since Li, Na, K has 1 unpaired electron
mol.build()
# Perform Hartree-Fock calculation
mf = scf.RHF(mol) # Restricted Hartree-Fock
total_energy = mf.kernel() # Calculate the total electronic energy
# Extract molecular orbital coefficients and energies
mo_coefficients = mf.mo_coeff # MO coefficients
mo_energies = mf.mo_energy # MO energies
# Determine the HOMO (highest occupied molecular orbital) energy
num_electrons = mol.nelectron # Total number of electrons in the system
homo_index = num_electrons // 2 - 1 # HOMO index for closed-shell systems (0-indexed)
homo_energy = mo_energies[homo_index] if homo_index >= 0 else None
# Generate the cube file for the HOMO
if homo_index >= 0:
cube_filename = f"{atom_symbol}_HOMO.cube"
cubegen.orbital(mol, cube_filename, mf.mo_coeff[:, homo_index])
print(f"HOMO cube file saved as: {cube_filename}")
# Visualize the cube file using py3Dmol
cube_view = py3Dmol.view(width=400, height=400)
with open(cube_filename, 'r') as file:
cube_data = file.read()
cube_view.addVolumetricData(cube_data, "cube", {'isoval': -0.03, 'color': "red", 'opacity': 0.85})
cube_view.addVolumetricData(cube_data, "cube", {'isoval': 0.03, 'color': "blue", 'opacity': 0.85})
cube_view.addModel(mol.tostring(format="xyz"), 'xyz')
cube_view.setStyle({'stick': {}, "sphere": {"radius": 0.4}})
cube_view.setBackgroundColor('0xeeeeee')
cube_view.show()
results = {
'atom': atom_symbol,
'total_energy': total_energy,
'mo_coefficients': mo_coefficients,
'mo_energies': mo_energies,
'homo_energy': homo_energy
}
return resultsNow loop over a couple of alkali-metal atoms, run the calculation, and print the total Hartree-Fock energy, the orbital energies, and the HOMO energy for each.
# List of atoms to calculate
atoms = ['Li', 'Na']
# Store the results for each atom
results_dict = {}
# Loop over each atom and calculate orbitals and energies
for atom in atoms:
results = calculate_orbitals_energies(atom)
results_dict[atom] = results
print(f"Results for {atom} atom:")
print("Total Energy (Hartree):", results['total_energy'])
print("Molecular Orbital Energies (Hartree):", results['mo_energies'])
print("HOMO energy (Hartree):", results['homo_energy'])
print("\n")converged SCF energy = -7.31552598128109
HOMO cube file saved as: Li_HOMO.cube
Results for Li atom:
Total Energy (Hartree): -7.315525981281089
Molecular Orbital Energies (Hartree): [-2.35349063 -0.03895976 0.16052129 0.16052129 0.16052129]
HOMO energy (Hartree): -2.3534906342705435
converged SCF energy = -159.668211391144
HOMO cube file saved as: Na_HOMO.cube
Results for Na atom:
Total Energy (Hartree): -159.66821139114353
Molecular Orbital Energies (Hartree): [-40.04250273 -2.62740763 -1.26706067 -1.26706067 -1.26706067
0.32267877 0.80168088 0.80168088 0.80168088]
HOMO energy (Hartree): -1.267060673295641