Expert guidance for Meta's FAIRChem library - machine learning methods for materials science and quantum chemistry using pretrained UMA models with ASE integration for fast, accurate predictions
This skill provides expert guidance for using FAIRChem (formerly OCP - Open Catalyst Project), Meta's FAIR Chemistry library of machine learning methods for materials science and quantum chemistry.
Use this skill when:
FAIRChem is Meta's machine learning framework for chemistry that provides:
uma-s-1p1, uma-m-1p1) for universal predictionsFAIRChemCalculatorFAIRChem allows you to use the same model across different chemistry domains by simply changing the task_name parameter.
Universal Materials Algebra models trained on diverse datasets:
uma-s-1p1: Small model (~50M parameters) - faster inferenceuma-m-1p1: Medium model (~300M parameters) - higher accuracySpecify the chemistry domain for domain-specific predictions:
oc20: Catalysis (surfaces with adsorbates)omat: Inorganic materials (crystals, bulk)omol: Molecules (organic chemistry)odac: Metal-organic frameworks (MOFs)omc: Molecular crystalsASE calculator interface that wraps UMA models:
Performance optimization modes:
turbo: Maximum speed, slightly reduced accuracyworkers=N# Install fairchem
pip install fairchem-core
# For GPU support
pip install fairchem-core[gpu]
# Hugging Face login (required for UMA models)
pip install huggingface-hub
huggingface-cli login
Note: You must have a Hugging Face account and request access to the UMA model repository.
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.build import bulk
from ase.optimize import LBFGS
# 1. Load pretrained model
predict_unit = load_predict_unit("uma-m-1p1")
# 2. Create calculator for specific domain
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omat" # Choose domain
)
# 3. Use with ASE
atoms = bulk("Cu", "fcc", a=3.6)
atoms.calc = calc
# 4. Calculate properties
energy = atoms.get_potential_energy()
forces = atoms.get_forces()
# 5. Optimize structure
opt = LBFGS(atoms)
opt.run(fmax=0.05)
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.build import fcc111, add_adsorbate
from ase.optimize import LBFGS
from ase.constraints import FixAtoms
# Load model
predict_unit = load_predict_unit("uma-m-1p1")
# Create calculator for catalysis
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="oc20" # Catalysis domain
)
# Build slab with adsorbate
slab = fcc111("Cu", size=(4, 4, 4), vacuum=10.0)
add_adsorbate(slab, "CO", height=2.0, position="fcc")
# Fix bottom layers
n_atoms_per_layer = 16
constraint = FixAtoms(indices=range(n_atoms_per_layer * 2))
slab.set_constraint(constraint)
# Attach calculator and optimize
slab.calc = calc
opt = LBFGS(slab, trajectory="slab_opt.traj")
opt.run(fmax=0.05)
# Get results
E = slab.get_potential_energy()
forces = slab.get_forces()
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.build import bulk
from ase.optimize import FIRE
from ase.filters import FrechetCellFilter
# Load model
predict_unit = load_predict_unit("uma-m-1p1")
# Calculator for materials
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omat" # Materials domain
)
# Create bulk structure
atoms = bulk("Fe", "bcc", a=2.87)
atoms.calc = calc
# Optimize both positions and cell
# FrechetCellFilter allows cell parameters to change
ucf = FrechetCellFilter(atoms)
opt = FIRE(ucf)
opt.run(fmax=0.05)
# Results
optimized_lattice = atoms.cell.cellpar()[0]
print(f"Optimized lattice constant: {optimized_lattice:.3f} Å")
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.build import bulk
from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
from ase.md.langevin import Langevin
from ase import units
# Load with turbo settings for speed
predict_unit = load_predict_unit(
"uma-s-1p1", # Use small model for MD
inference_settings="turbo"
)
# Calculator for MD
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omat",
workers=4 # Multi-GPU for large systems
)
# Large system
atoms = bulk("C", "diamond", a=3.57) * (10, 10, 10) # Large system
atoms.calc = calc
# Initialize velocities
MaxwellBoltzmannDistribution(atoms, temperature_K=300)
# Run NVT dynamics
dyn = Langevin(
atoms,
timestep=1.0 * units.fs,
temperature_K=300,
friction=0.002
)
# Run
from ase.io.trajectory import Trajectory
traj = Trajectory("md.traj", "w", atoms)
dyn.attach(traj.write, interval=10)
dyn.run(5000)
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.build import molecule
from ase.optimize import LBFGS
# Load model
predict_unit = load_predict_unit("uma-m-1p1")
# Calculator for molecules
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omol" # Molecular domain
)
# Build molecule
mol = molecule("H2O")
mol.center(vacuum=10.0)
mol.calc = calc
# Optimize
opt = LBFGS(mol, trajectory="mol_opt.traj")
opt.run(fmax=0.05)
# Get properties
E = mol.get_potential_energy()
forces = mol.get_forces()
from fairchem.data.ase import FAIRChemCalculator
from fairchem.predict import load_predict_unit
from ase.neb import NEB
from ase.optimize import BFGS
from ase.io import read
# Load model
predict_unit = load_predict_unit("uma-m-1p1")
# Calculator
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="oc20"
)
# Load initial and final states
initial = read("initial.traj")
final = read("final.traj")
# Create NEB
images = [initial]
images += [initial.copy() for i in range(5)]
images += [final]
neb = NEB(images)
neb.interpolate()
# Attach calculator to intermediate images
for image in images[1:-1]:
image.calc = calc
# Optimize
opt = BFGS(neb, trajectory="neb.traj")
opt.run(fmax=0.05)
# Analyze
energies = [img.get_potential_energy() for img in images]
barrier = max(energies) - energies[0]
print(f"Barrier: {barrier:.3f} eV")
from fairchem.predict import load_predict_unit
# Standard loading
predict_unit = load_predict_unit("uma-m-1p1")
# With turbo mode (faster, slight accuracy trade-off)
predict_unit = load_predict_unit(
"uma-m-1p1",
inference_settings="turbo"
)
# Specify device
predict_unit = load_predict_unit(
"uma-m-1p1",
device="cuda:0"
)
# Load local checkpoint
predict_unit = load_predict_unit(
"/path/to/checkpoint.pt",
device="cuda"
)
uma-s-1p1: Small, fast (~50M params)uma-m-1p1: Medium, accurate (~300M params)| Domain | Task Name | Use For | Examples |
|---|---|---|---|
| Catalysis | oc20 | Surfaces + adsorbates | CO on Cu(111), O on Pt |
| Materials | omat | Bulk crystals, defects | Fe lattice, Si bulk |
| Molecules | omol | Organic molecules | H2O, CH4, proteins |
| MOFs | odac | Metal-organic frameworks | ZIF-8, MOF-5 |
| Crystals | omc | Molecular crystals | Ice, organic crystals |
# Use multiple GPUs automatically
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omat",
workers=8 # Use 8 GPUs
)
# Achieves ~10× speedup on 8× H100 GPUs
# Trade slight accuracy for speed
predict_unit = load_predict_unit(
"uma-s-1p1", # Small model
inference_settings="turbo"
)
# Good for:
# - MD simulations
# - Large systems
# - Initial screening
# For multiple similar calculations, iterate over structures
results = []
for atoms in [atoms1, atoms2, atoms3]:
atoms.calc = calc
results.append({
'energy': atoms.get_potential_energy(),
'forces': atoms.get_forces()
})
Always choose the appropriate task for your system:
oc20omatomolodacomcuma-s-1p1 + turbouma-m-1p1uma-s-1p1 + workersML models have different error characteristics than DFT:
# Always validate critical results
# Compare ML prediction with DFT for representative cases
ml_energy = atoms.get_potential_energy() # FAIRChem
atoms.calc = Vasp(...) # Switch to DFT
dft_energy = atoms.get_potential_energy()
error = abs(ml_energy - dft_energy)
FAIRChem models provide predictions but not uncertainty:
For large systems:
# Use turbo mode
predict_unit = load_predict_unit(
"uma-s-1p1",
inference_settings="turbo"
)
# Distribute across GPUs
calc = FAIRChemCalculator(
predict_unit=predict_unit,
task_name="omat",
workers=4
)
atoms.calc = calc
energy = atoms.get_potential_energy() # eV
forces = atoms.get_forces() # eV/Å
stress = atoms.get_stress() # eV/ų
from ase.optimize import LBFGS, FIRE, BFGS
# Fast convergence
opt = LBFGS(atoms, trajectory="opt.traj")
opt.run(fmax=0.05)
# For difficult systems
opt = FIRE(atoms)
opt.run(fmax=0.05)
from ase.filters import FrechetCellFilter
# Optimize both atoms and cell
ucf = FrechetCellFilter(atoms)
opt = FIRE(ucf)
opt.run(fmax=0.05)
FAIRChemCalculator is a full ASE calculator:
# All ASE functionality works
from ase.vibrations import Vibrations
from ase.thermochemistry import IdealGasThermo
from ase.eos import calculate_eos
# Vibrational analysis
vib = Vibrations(atoms)
vib.run()
# Thermochemistry
thermo = IdealGasThermo(...)
# Equation of state
eos = calculate_eos(atoms)
# Login to Hugging Face
huggingface-cli login
# Request access to UMA models at:
# https://huggingface.co/fairchem-team/uma-m-1p1
# Use smaller model
predict_unit = load_predict_unit("uma-s-1p1")
# Use turbo mode
predict_unit = load_predict_unit(
"uma-s-1p1",
inference_settings="turbo"
)
# Reduce batch size (if using batch predictions)
# Enable turbo mode
inference_settings="turbo"
# Use multiple GPUs
workers=N
# Use smaller model
"uma-s-1p1"
# Symptoms: Poor predictions, unphysical results
# Solution: Verify task matches your system
# For surfaces + adsorbates:
task_name="oc20" # NOT "omat" or "omol"
# For bulk materials:
task_name="omat" # NOT "oc20"
Important: FAIRChem v2 is a breaking change from v1
# Check version
import fairchem
print(fairchem.__version__) # Should be >= 2.0 for UMA
| Aspect | FAIRChem | DFT |
|---|---|---|
| Speed | 100-1000× faster | Slower |
| Accuracy | ~0.1 eV | Reference |
| Scaling | Linear, multi-GPU | Cubic |
| System size | 1000s of atoms | 10-100s atoms |
| Use case | Screening, MD | High accuracy |
Use FAIRChem for:
Use DFT for:
When suggesting FAIRChem solutions:
When helping with FAIRChem: