| name | pyscf |
| description | Comprehensive guide for PySCF - Python-based Simulations of Chemistry Framework. Use for ab initio quantum chemistry calculations including Hartree-Fock, DFT, MP2, CCSD, geometry optimization, excited states, and molecular properties. Industry-standard library for electronic structure calculations. |
| version | 2.5.0 |
| license | Apache-2.0 |
PySCF - Quantum Chemistry Framework
Python library for ab initio electronic structure calculations and quantum chemistry.
When to Use
- Running Hartree-Fock (HF) and Density Functional Theory (DFT) calculations
- Calculating molecular energies and gradients
- Optimizing molecular geometries
- Computing post-HF methods (MP2, CCSD, CI, coupled-cluster)
- Analyzing molecular orbitals and electron density
- Calculating excited states (TD-DFT, CI, EOM-CCSD)
- Computing molecular properties (dipole, charges, NMR, IR)
- Performing periodic calculations (solids, surfaces)
- Benchmarking quantum chemistry methods
- Integrating quantum calculations with ML/AI workflows
Reference Documentation
Official docs: https://pyscf.org/
Search patterns: gto.M, scf.RHF, dft.RKS, mp.MP2, optimize, tddft.TDDFT
Core Principles
Use PySCF For
| Task | Module | Example |
|---|
| Build molecule | gto | gto.M(atom='H 0 0 0; H 0 0 1') |
| Hartree-Fock | scf | scf.RHF(mol).run() |
| DFT calculation | dft | dft.RKS(mol, xc='B3LYP') |
| MP2 correlation | mp | mp.MP2(mf).run() |
| Coupled-cluster | cc | cc.CCSD(mf).run() |
| Geometry optimization | geomopt | optimize(mf) |
| Excited states | tddft | tddft.TDDFT(mf).run() |
| Periodic systems | pbc | pbc.gto.Cell() |
Do NOT Use For
- Molecular dynamics simulations (use GROMACS, OpenMM, ASE)
- Very large systems (>1000 atoms) - use semi-empirical or force fields
- Interactive visualization (use PyMOL, VMD)
- High-throughput virtual screening (too slow)
- Real-time quantum simulations
Quick Reference
Installation
pip install pyscf
pip install pyscf[geomopt,dftd3,dmrgscf]
conda install -c pyscf pyscf
pip install git+https://github.com/pyscf/pyscf
Standard Imports
from pyscf import gto, scf, dft
from pyscf import mp, cc, ci
from pyscf import grad, geomopt
from pyscf import tddft, tdscf
from pyscf import lo, ao2mo
from pyscf.tools import molden, cubegen
import numpy as np
Basic Pattern - Single Point Energy
from pyscf import gto, scf
mol = gto.M(
atom='O 0 0 0; H 0 1 0; H 0 0 1',
basis='6-31g',
charge=0,
spin=0
)
mf = scf.RHF(mol)
energy = mf.kernel()
if not mf.converged:
raise RuntimeError("SCF did not converge")
print(f"E(HF) = {energy:.8f} Hartree")
Basic Pattern - DFT Calculation
from pyscf import gto, dft
mol = gto.M(atom='C 0 0 0; O 0 0 1.2', basis='def2-tzvp')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
energy = mf.kernel()
print(f"E(B3LYP) = {energy:.8f} Hartree")
Basic Pattern - Geometry Optimization
from pyscf import gto, scf
from pyscf.geomopt.geometric_solver import optimize
mol = gto.M(atom='H 0 0 0; H 0 0 1.5', basis='6-31g')
mf = scf.RHF(mol)
mol_eq = optimize(mf)
print(f"Optimized geometry:\n{mol_eq.atom}")
Critical Rules
✅ DO
- Check convergence - Always verify
mf.converged == True
- Start with small basis - Test with STO-3G or 3-21G first
- Specify charge and spin - Be explicit about electronic state
- Save results - Use
chkfile for restart capability
- Use symmetry - Enable when applicable for speed
- Provide good initial guess - Use
init_guess='minao' or previous results
- Monitor memory - Set
max_memory appropriately
- Verify units - PySCF uses Bohr and Hartree internally
- Use density fitting - Enable for large systems
- Check multiplicity - Ensure spin matches expected state
❌ DON'T
- Skip convergence check - Never use results from unconverged calculation
- Use huge basis sets initially - Start small, expand gradually
- Ignore charge/spin - Defaults may not match your system
- Run without
chkfile - You'll lose data if crash occurs
- Disable symmetry unnecessarily - It speeds up calculations
- Mix coordinate systems - Be consistent with Angstrom vs Bohr
- Use wrong multiplicity - 2S+1, not 2S
- Forget about memory - Large calculations can OOM
- Trust unconverged results - They're meaningless
- Compare methods without same basis - Use consistent basis sets
Anti-Patterns (NEVER)
mf = scf.RHF(mol)
energy = mf.kernel()
mf = scf.RHF(mol)
energy = mf.kernel()
if not mf.converged:
raise RuntimeError("SCF not converged, results unreliable")
mol = gto.M(atom='protein.xyz', basis='def2-qzvppd')
mol = gto.M(atom='protein.xyz', basis='sto-3g')
mol = gto.M(atom='O 0 0 0; O 0 0 1.2')
mf = scf.RHF(mol)
mol = gto.M(
atom='O 0 0 0; O 0 0 1.2',
charge=0,
spin=2
)
mf = scf.ROHF(mol)
mf = scf.RHF(mol)
mf.kernel()
mf = scf.RHF(mol)
mf.chkfile = 'calculation.chk'
mf.kernel()
mol = gto.M(atom='O 0 0 0; O 0 0 1.2', spin=2)
mol = gto.M(
atom='O 0 0 0; O 0 0 1.2',
spin=2
)
Molecule Building
Basic Molecule Definition
from pyscf import gto
mol = gto.M(
atom='''
O 0.0 0.0 0.0
H 0.0 1.0 0.0
H 0.0 0.0 1.0
''',
basis='6-31g',
charge=0,
spin=0
)
mol = gto.M(
atom='O 0 0 0; H 0 1 0; H 0 0 1',
basis='6-31g'
)
mol = gto.M(
atom=[
('O', (0.0, 0.0, 0.0)),
('H', (0.0, 1.0, 0.0)),
('H', (0.0, 0.0, 1.0))
],
basis='6-31g'
)
Loading from Files
from pyscf import gto
mol = gto.M(atom='molecule.xyz', basis='6-31g')
mol = gto.M(atom='protein.pdb', basis='sto-3g')
mol = gto.M(
atom='''
H
H 1 0.74
''',
basis='6-31g'
)
Molecular Properties and Info
from pyscf import gto
mol = gto.M(atom='H2O', basis='6-31g')
print(f"Number of atoms: {mol.natm}")
print(f"Number of electrons: {mol.nelectron}")
print(f"Number of basis functions: {mol.nao_nr()}")
print(f"Charge: {mol.charge}")
print(f"Spin (2S): {mol.spin}")
print(f"Nuclear repulsion: {mol.energy_nuc():.8f}")
for i in range(mol.natm):
atom_symbol = mol.atom_symbol(i)
atom_charge = mol.atom_charge(i)
coord = mol.atom_coord(i)
print(f"Atom {i}: {atom_symbol} (Z={atom_charge}) at {coord}")
Basis Set Specification
from pyscf import gto
mol = gto.M(atom='H2O', basis='6-31g')
mol = gto.M(
atom='H2O',
basis={
'O': '6-311g**',
'H': '6-31g'
}
)
mol = gto.M(
atom='H 0 0 0; H 0 0 1',
basis={
'H': gto.basis.parse('''
H S
13.0107010 0.19682158E-01
1.9622572 0.13796524
0.44453796 0.47831935
H S
0.12194962 1.0000000
''')
}
)
Molecular Symmetry
from pyscf import gto
mol = gto.M(atom='H2O', basis='6-31g', symmetry=True)
print(f"Point group: {mol.groupname}")
print(f"Irreps: {mol.irrep_name}")
mol = gto.M(atom='H2O', basis='6-31g', symmetry='C2v')
mol = gto.M(atom='H2O', basis='6-31g', symmetry=False)
Hartree-Fock Methods
Restricted Hartree-Fock (RHF)
from pyscf import gto, scf
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
energy = mf.kernel()
if mf.converged:
print(f"E(RHF) = {energy:.8f} Hartree")
print(f"Orbital energies: {mf.mo_energy}")
else:
print("SCF not converged")
Unrestricted Hartree-Fock (UHF)
from pyscf import gto, scf
mol = gto.M(
atom='O 0 0 0; O 0 0 1.2',
basis='6-31g',
spin=2
)
mf = scf.UHF(mol)
energy = mf.kernel()
print(f"<S^2> = {mf.spin_square()[0]:.4f}")
Restricted Open-Shell HF (ROHF)
from pyscf import gto, scf
mol = gto.M(
atom='O 0 0 0; O 0 0 1.2',
basis='6-31g',
spin=2
)
mf = scf.ROHF(mol)
energy = mf.kernel()
print(f"E(ROHF) = {energy:.8f} Hartree")
SCF Convergence Control
from pyscf import gto, scf
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.conv_tol = 1e-8
mf.conv_tol_grad = 1e-5
mf.max_cycle = 100
mf.diis_space = 12
mf.init_guess = 'minao'
mf.level_shift = 0.5
energy = mf.kernel()
Convergence Strategies for Difficult Cases
from pyscf import gto, scf
mol = gto.M(atom='difficult_molecule.xyz', basis='6-31g')
mol_small = gto.M(atom='difficult_molecule.xyz', basis='sto-3g')
mf_small = scf.RHF(mol_small)
mf_small.kernel()
mol_large = gto.M(atom='difficult_molecule.xyz', basis='6-31g')
mf = scf.RHF(mol_large)
mf.init_guess = mf_small.make_rdm1()
mf.level_shift = 0.3
mf.kernel()
if not mf.converged:
mf.init_guess = 'atom'
mf.kernel()
Density Functional Theory
Basic DFT Calculation
from pyscf import gto, dft
mol = gto.M(atom='H2O', basis='def2-tzvp')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
energy = mf.kernel()
print(f"E(B3LYP) = {energy:.8f} Hartree")
Common Functionals
from pyscf import gto, dft
mol = gto.M(atom='CH4', basis='6-31g')
mf = dft.RKS(mol)
mf.xc = 'LDA,VWN'
e_lda = mf.kernel()
mf.xc = 'PBE'
e_pbe = mf.kernel()
mf.xc = 'B3LYP'
e_b3lyp = mf.kernel()
mf.xc = 'M06'
e_m06 = mf.kernel()
mf.xc = 'wB97X-D'
e_wb97xd = mf.kernel()
print(f"LDA: {e_lda:.6f}")
print(f"PBE: {e_pbe:.6f}")
print(f"B3LYP: {e_b3lyp:.6f}")
print(f"M06: {e_m06:.6f}")
print(f"wB97X-D: {e_wb97xd:.6f}")
Unrestricted DFT
from pyscf import gto, dft
mol = gto.M(
atom='C 0 0 0; H 0 0 1; H 0 1 0; H 1 0 0',
basis='6-31g*',
spin=1
)
mf = dft.UKS(mol)
mf.xc = 'B3LYP'
energy = mf.kernel()
print(f"<S^2> = {mf.spin_square()[0]:.4f}")
Grid and Integration
from pyscf import gto, dft
mol = gto.M(atom='H2O', basis='6-31g')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
mf.grids.level = 3
mf.grids.prune = True
from pyscf.dft import gen_grid
mf.grids = gen_grid.Grids(mol)
mf.grids.atom_grid = {"H": (50, 194), "O": (75, 302)}
mf.grids.build()
energy = mf.kernel()
Dispersion Corrections
from pyscf import gto, dft
mol = gto.M(atom='benzene.xyz', basis='def2-tzvp')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
mf._numint.libxc = dft.xcfun
from pyscf import dftd3
mf = dftd3.dftd3(mf)
energy = mf.kernel()
Post-Hartree-Fock Methods
MP2 - Second-Order Møller-Plesset
from pyscf import gto, scf, mp
mol = gto.M(atom='H2O', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.kernel()
mp2 = mp.MP2(mf)
e_corr, t2 = mp2.kernel()
print(f"E(HF) = {mf.e_tot:.8f}")
print(f"E(MP2) = {mp2.e_tot:.8f}")
print(f"E_corr = {e_corr:.8f}")
CCSD - Coupled Cluster Singles and Doubles
from pyscf import gto, scf, cc
mol = gto.M(atom='H2O', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.kernel()
ccsd = cc.CCSD(mf)
e_corr, t1, t2 = ccsd.kernel()
print(f"E(HF) = {mf.e_tot:.8f}")
print(f"E(CCSD) = {ccsd.e_tot:.8f}")
print(f"E_corr = {e_corr:.8f}")
CCSD(T) - with Perturbative Triples
from pyscf import gto, scf, cc
mol = gto.M(atom='N2', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.kernel()
ccsd = cc.CCSD(mf)
ccsd.kernel()
et = ccsd.ccsd_t()
print(f"E(HF) = {mf.e_tot:.8f}")
print(f"E(CCSD) = {ccsd.e_tot:.8f}")
print(f"E(T) = {et:.8f}")
print(f"E(CCSD(T))= {ccsd.e_tot + et:.8f}")
Configuration Interaction (CI)
from pyscf import gto, scf, ci
mol = gto.M(atom='LiH', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
cisd = ci.CISD(mf)
e_cisd = cisd.kernel()[0]
fci = ci.FCI(mf)
e_fci = fci.kernel()[0]
print(f"E(HF) = {mf.e_tot:.8f}")
print(f"E(CISD) = {e_cisd:.8f}")
print(f"E(FCI) = {e_fci:.8f}")
CASSCF - Complete Active Space
from pyscf import gto, scf, mcscf
mol = gto.M(atom='O 0 0 0; O 0 0 1.2', basis='6-31g', spin=2)
mf = scf.ROHF(mol)
mf.kernel()
mc = mcscf.CASSCF(mf, 6, 6)
mc.kernel()
print(f"E(CASSCF) = {mc.e_tot:.8f}")
from pyscf import tools
tools.molden.from_mo(mol, 'cas_orbitals.molden', mc.mo_coeff)
Geometry Optimization
Basic Optimization
from pyscf import gto, scf
from pyscf.geomopt.geometric_solver import optimize
mol = gto.M(
atom='H 0 0 0; H 0 0 1.5',
basis='6-31g'
)
mf = scf.RHF(mol)
mol_eq = optimize(mf)
print("Optimized geometry:")
print(mol_eq.atom)
print(f"Final energy: {mf.e_tot:.8f}")
Optimization with Constraints
from pyscf import gto, scf
from pyscf.geomopt.geometric_solver import optimize
mol = gto.M(atom='H2O2', basis='6-31g')
mf = scf.RHF(mol)
def callback(mol):
"""Keep O-O distance fixed."""
coords = mol.atom_coords()
distance = np.linalg.norm(coords[0] - coords[1])
return distance - 1.5
mol_eq = optimize(mf, constraints=callback)
Transition State Optimization
from pyscf import gto, scf
from pyscf.geomopt.berny_solver import optimize
mol = gto.M(atom='transition_state_guess.xyz', basis='6-31g')
mf = scf.RHF(mol)
mol_ts = optimize(mf, transition_state=True)
print(f"TS energy: {mf.e_tot:.8f}")
Reaction Path Following
from pyscf import gto, scf
from pyscf.geomopt.geometric_solver import optimize
mol_reactant = gto.M(atom='reactant.xyz', basis='6-31g')
mf_reactant = scf.RHF(mol_reactant)
mol_reactant_opt = optimize(mf_reactant)
mol_product = gto.M(atom='product.xyz', basis='6-31g')
mf_product = scf.RHF(mol_product)
mol_product_opt = optimize(mf_product)
Molecular Properties
Dipole Moment
from pyscf import gto, scf
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
dip = mf.dip_moment(unit='Debye')
print(f"Dipole: {dip} Debye")
print(f"|μ| = {np.linalg.norm(dip):.4f} Debye")
Mulliken Population Analysis
from pyscf import gto, scf
from pyscf.tools import dump_mat
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
mulliken = mf.mulliken_pop()
print("\nMulliken charges:")
for i, charge in enumerate(mulliken[1]):
print(f"Atom {mol.atom_symbol(i)}: {charge:.4f}")
Löwdin Population Analysis
from pyscf import gto, scf
from pyscf import lo
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
lowdin_charges = lo.orth.lowdin(mol, mf.make_rdm1())
print("Löwdin charges:", lowdin_charges)
Natural Bond Orbitals (NBO)
from pyscf import gto, scf
from pyscf import nao
mol = gto.M(atom='CH3OH', basis='6-31g*')
mf = scf.RHF(mol)
mf.kernel()
Molecular Orbitals Analysis
from pyscf import gto, scf
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
print("Orbital energies (eV):")
for i, e in enumerate(mf.mo_energy * 27.2114):
occ = "occ" if i < mol.nelectron//2 else "vir"
print(f" MO {i}: {e:8.4f} eV ({occ})")
homo_idx = mol.nelectron // 2 - 1
lumo_idx = homo_idx + 1
gap = (mf.mo_energy[lumo_idx] - mf.mo_energy[homo_idx]) * 27.2114
print(f"\nHOMO-LUMO gap: {gap:.4f} eV")
Electron Density Analysis
from pyscf import gto, scf
from pyscf.tools import cubegen
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
cubegen.density(mol, 'h2o_density.cube', mf.make_rdm1())
cubegen.orbital(mol, 'h2o_homo.cube', mf.mo_coeff[:, homo_idx])
Excited States
TD-DFT for Excited States
from pyscf import gto, dft, tddft
mol = gto.M(atom='H2O', basis='6-31g')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
mf.kernel()
td = tddft.TDDFT(mf)
td.nroots = 5
excitations = td.kernel()[0]
print("Excitation energies:")
for i, e in enumerate(excitations):
print(f"State {i+1}: {e * 27.2114:.4f} eV")
TD-DFT with Oscillator Strengths
from pyscf import gto, dft, tddft
mol = gto.M(atom='formaldehyde', basis='6-31g')
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
mf.kernel()
td = tddft.TDDFT(mf)
td.nroots = 10
energies, xy = td.kernel()
f = td.oscillator_strength()
print("\nExcitation Energy (eV) f")
print("-" * 40)
for i in range(len(energies)):
print(f" {i+1:2d} {energies[i]*27.2114:8.4f} {f[i]:.6f}")
EOM-CCSD for Excited States
from pyscf import gto, scf, cc
mol = gto.M(atom='H2O', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.kernel()
eom = cc.eom_rccsd.EOMIP(cc.CCSD(mf))
e_ip, v_ip = eom.kernel(nroots=3)
print("Ionization potentials:")
for i, e in enumerate(e_ip):
print(f"IP {i+1}: {e * 27.2114:.4f} eV")
CASSCF/CASPT2 for Multi-Reference States
from pyscf import gto, scf, mcscf
mol = gto.M(atom='ethylene', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
mc = mcscf.CASSCF(mf, 2, 2)
mc = mc.state_average_([0.5, 0.5])
mc.kernel()
print("State-averaged energies:")
for i, e in enumerate(mc.e_states):
print(f"State {i}: {e:.8f}")
Advanced Workflows
Potential Energy Surface Scan
from pyscf import gto, scf
import numpy as np
def calculate_pes_scan(atom_template, distances, basis='6-31g'):
"""Scan potential energy surface along distance."""
energies = []
for d in distances:
atom = atom_template.format(d=d)
mol = gto.M(atom=atom, basis=basis)
mf = scf.RHF(mol)
energy = mf.kernel()
if mf.converged:
energies.append(energy)
else:
energies.append(np.nan)
return np.array(energies)
distances = np.linspace(0.5, 3.0, 20)
atom_template = 'H 0 0 0; H 0 0 {d}'
energies = calculate_pes_scan(atom_template, distances)
min_idx = np.nanargmin(energies)
print(f"Equilibrium distance: {distances[min_idx]:.3f} Angstrom")
print(f"Energy at minimum: {energies[min_idx]:.8f} Hartree")
Thermochemistry
from pyscf import gto, scf, hessian
import numpy as np
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
h = hessian.RHF(mf)
hess = h.kernel()
from pyscf.hessian import thermo
freq_info = thermo.harmonic_analysis(mol, hess)
print("Vibrational frequencies (cm^-1):")
print(freq_info['freq_wavenumber'])
results = thermo.thermo(mf, freq_info['freq_wavenumber'], 298.15)
print(f"\nZero-point energy: {results['ZPE']:.6f} Hartree")
print(f"Enthalpy: {results['H']:.6f} Hartree")
print(f"Entropy: {results['S']:.6f} Hartree/K")
print(f"Gibbs free energy: {results['G']:.6f} Hartree")
NMR Chemical Shifts
from pyscf import gto, scf
from pyscf.prop import nmr
mol = gto.M(atom='CH4', basis='6-31g*')
mf = scf.RHF(mol)
mf.kernel()
nmr_calc = nmr.RHF(mf)
shielding = nmr_calc.kernel()
print("NMR shielding tensors:")
for i in range(mol.natm):
print(f"{mol.atom_symbol(i)}: {shielding[i]} ppm")
IR Spectra Calculation
from pyscf import gto, scf, hessian
from pyscf.hessian import thermo
mol = gto.M(atom='CO2', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
h = hessian.RHF(mf)
hess = h.kernel()
freq_info = thermo.harmonic_analysis(mol, hess)
print("IR Frequencies and Intensities:")
print("Freq (cm^-1) Intensity")
for freq, intensity in zip(freq_info['freq_wavenumber'],
freq_info['IR_intensity']):
if freq > 0:
print(f"{freq:8.2f} {intensity:.4f}")
QMMM Calculations
from pyscf import gto, scf, qmmm
mol = gto.M(
atom='C 0 0 0; H 0 1 0; H 1 0 0; H 0 0 1; H -1 0 0',
basis='6-31g'
)
mm_coords = np.array([
[3.0, 0.0, 0.0],
[0.0, 3.0, 0.0],
[0.0, 0.0, 3.0]
])
mm_charges = np.array([-0.5, -0.5, 1.0])
mf = scf.RHF(mol)
mf = qmmm.mm_charge(mf, mm_coords, mm_charges)
energy = mf.kernel()
print(f"QM/MM energy: {energy:.8f}")
Solvation Models (PCM)
from pyscf import gto, scf, solvent
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf = solvent.ddCOSMO(mf)
mf.with_solvent.eps = 78.3553
energy = mf.kernel()
print(f"Energy in solution: {energy:.8f}")
Periodic Systems
Basic Periodic Calculation
from pyscf.pbc import gto, scf
cell = gto.Cell()
cell.atom = '''
C 0 0 0
C 1.68 1.68 1.68
'''
cell.basis = 'gth-dzvp'
cell.pseudo = 'gth-pade'
cell.a = '''
0.0 3.37 3.37
3.37 0.0 3.37
3.37 3.37 0.0
'''
cell.unit = 'angstrom'
cell.build()
kpts = cell.make_kpts([2, 2, 2])
kmf = scf.KRHF(cell, kpts)
energy = kmf.kernel()
print(f"Energy per unit cell: {energy:.8f}")
Band Structure Calculation
from pyscf.pbc import gto, scf, tools
import numpy as np
cell = gto.Cell()
kmf = scf.KRHF(cell)
kmf.kernel()
kpath = tools.pbc.get_kpath(cell, [10, 10, 10])
bands = []
for k in kpath:
kmf_k = scf.KRHF(cell, k)
kmf_k.kernel(dm0=kmf.make_rdm1())
bands.append(kmf_k.mo_energy)
Performance Optimization
Density Fitting
from pyscf import gto, scf
mol = gto.M(atom='protein_fragment.xyz', basis='def2-svp')
mf = scf.RHF(mol).density_fit()
mf.kernel()
mf = scf.RHF(mol).density_fit(auxbasis='def2-svp-jkfit')
mf.kernel()
Parallel Computation
from pyscf import gto, scf, lib
lib.num_threads(8)
mol = gto.M(atom='large_molecule.xyz', basis='6-31g')
mf = scf.RHF(mol)
mf.max_memory = 4000
energy = mf.kernel()
Memory Management
from pyscf import gto, scf
mol = gto.M(atom='large_system.xyz', basis='6-31g')
mf = scf.RHF(mol)
mf.max_memory = 8000
mf.direct_scf = True
energy = mf.kernel()
Checkpointing and Restart
from pyscf import gto, scf, lib
mol = gto.M(atom='molecule.xyz', basis='6-31g')
mf = scf.RHF(mol)
mf.chkfile = 'calculation.chk'
energy = mf.kernel()
mf2 = scf.RHF(mol)
mf2.chkfile = 'calculation.chk'
mf2.init_guess = 'chkfile'
energy2 = mf2.kernel()
Integration with Other Tools
Export to Molden Format
from pyscf import gto, scf
from pyscf.tools import molden
mol = gto.M(atom='H2O', basis='6-31g')
mf = scf.RHF(mol)
mf.kernel()
with open('molecule.molden', 'w') as f:
molden.header(mol, f)
molden.orbital_coeff(mol, f, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)
Interface with ASE
from pyscf import gto, scf
from ase import Atoms
from ase.optimize import BFGS
class PySCFCalculator:
def __init__(self, basis='6-31g', method='RHF'):
self.basis = basis
self.method = method
def get_potential_energy(self, atoms):
mol = gto.M(
atom=[(atoms.get_chemical_symbols()[i], atoms.positions[i])
for i in range(len(atoms))],
basis=self.basis,
unit='angstrom'
)
if self.method == 'RHF':
mf = scf.RHF(mol)
elif self.method == 'B3LYP':
mf = dft.RKS(mol)
mf.xc = 'B3LYP'
return mf.kernel()
atoms = Atoms('H2O', positions=[[0,0,0], [0,1,0], [0,0,1]])
atoms.calc = PySCFCalculator()
opt = BFGS(atoms)
opt.run(fmax=0.01)
Common Pitfalls and Solutions
SCF Convergence Failures
from pyscf import gto, scf
mol = gto.M(atom='difficult.xyz', basis='6-31g')
mf = scf.RHF(mol)
energy = mf.kernel()
if not mf.converged:
mf.level_shift = 0.5
mf.kernel()
if not mf.converged:
mf.diis_space = 15
mf.kernel()
if not mf.converged:
mf.init_guess = 'atom'
mf.kernel()
if not mf.converged:
mol_small = gto.M(atom='difficult.xyz', basis='sto-3g')
mf_small = scf.RHF(mol_small).run()
mf.init_guess = mf_small.make_rdm1()
mf.kernel()
Memory Issues
from pyscf import gto, scf
mol = gto.M(atom='huge.xyz', basis='def2-tzvp')
mf = scf.RHF(mol)
mf = mf.density_fit()
mf.max_memory = 4000
mf.direct_scf = True
energy = mf.kernel()
Spin Contamination
from pyscf import gto, scf
mol = gto.M(atom='radical.xyz', basis='6-31g', spin=1)
mf = scf.UHF(mol)
mf.kernel()
s2 = mf.spin_square()[0]
print(f"<S^2> = {s2:.4f} (expected 0.75)")
if abs(s2 - 0.75) > 0.1:
mf = scf.ROHF(mol)
mf.kernel()
print(f"Using ROHF instead")
Basis Set Linear Dependency
from pyscf import gto, scf
mol = gto.M(atom='molecule.xyz', basis='aug-cc-pvqz')
mf = scf.RHF(mol)
from pyscf import lo
mf.kernel()
if not mf.converged:
s = mf.get_ovlp()
cond = np.linalg.cond(s)
if cond > 1e10:
print("Linear dependency detected")
mf = scf.addons.remove_linear_dep_(mf)
mf.kernel()
This comprehensive PySCF guide covers 50+ examples across all major quantum chemistry workflows!