| name | python-ase |
| description | Expert assistance with the Atomic Simulation Environment (ASE) Python library for atomistic simulations, including structure building, calculator setup, optimization, dynamics, and analysis |
| allowed-tools | ["*"] |
Python ASE (Atomic Simulation Environment) Skill
This skill provides expert guidance for working with the Atomic Simulation Environment (ASE), a Python library for setting up, manipulating, running, visualizing, and analyzing atomistic simulations.
When to Use This Skill
Use this skill when:
- Building atomic structures (molecules, surfaces, bulk crystals, nanoparticles)
- Setting up and running DFT calculations (VASP, GPAW, Quantum ESPRESSO, etc.)
- Performing geometry optimizations or molecular dynamics
- Analyzing trajectories and simulation results
- Working with ASE Atoms objects and calculators
- Converting between different structure formats
- Calculating properties (energies, forces, stress, bands, DOS)
- Writing automation scripts for materials simulations
Core ASE Concepts
1. Atoms Objects
The fundamental ASE object representing atomic structures:
- Contains atomic positions, cell parameters, periodic boundary conditions
- Can be modified, visualized, and used with calculators
- Supports constraints for selective dynamics
2. Calculators
Interface to quantum chemistry and materials science codes:
- EMT (Effective Medium Theory) - fast, for testing
- VASP - plane-wave DFT
- GPAW - real-space/plane-wave DFT
- Quantum ESPRESSO, CASTEP, NWChem, etc.
- Must be attached to Atoms objects:
atoms.calc = calculator
3. Optimizers
Geometry optimization algorithms:
- BFGS, LBFGS - quasi-Newton methods
- FIRE - fast inertial relaxation
- MDMin - molecular dynamics minimization
4. Dynamics
Molecular dynamics simulations:
- VelocityVerlet - NVE ensemble
- Langevin - NVT with friction
- NPT - constant pressure and temperature
Common Patterns and Workflows
Building Structures
from ase import Atoms
from ase.build import bulk, molecule, surface, add_adsorbate
atoms = bulk('Cu', 'fcc', a=3.6)
atoms = bulk('Si', 'diamond', a=5.43)
atoms = molecule('H2O')
atoms = molecule('CH4')
slab = surface('Au', (1, 1, 1), size=(4, 4, 4), vacuum=10.0)
add_adsorbate(slab, 'O', height=1.5, position='fcc')
Setting Up Calculators
from ase.calculators.emt import EMT
atoms.calc = EMT()
from ase.calculators.vasp import Vasp
calc = Vasp(
xc='PBE',
encut=400,
kpts=(4, 4, 4),
ismear=1,
sigma=0.1,
ibrion=2,
nsw=100,
ediff=1e-5,
)
atoms.calc = calc
from gpaw import GPAW, PW
calc = GPAW(
mode=PW(400),
xc='PBE',
kpts=(4, 4, 4),
txt='output.txt'
)
atoms.calc = calc
Geometry Optimization
from ase.optimize import BFGS, LBFGS, FIRE
opt = BFGS(atoms, trajectory='opt.traj')
opt.run(fmax=0.05)
from ase.constraints import FixAtoms
mask = [atom.position[2] < 10.0 for atom in atoms]
atoms.set_constraint(FixAtoms(mask=mask))
opt = BFGS(atoms)
opt.run(fmax=0.05)
opt = BFGS(atoms, logfile='opt.log', trajectory='opt.traj')
opt.run(fmax=0.01, steps=100)
Molecular Dynamics
from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
from ase.md.langevin import Langevin
from ase import units
MaxwellBoltzmannDistribution(atoms, temperature_K=300)
dyn = Langevin(
atoms,
timestep=1.0 * units.fs,
temperature_K=300,
friction=0.002
)
from ase.io.trajectory import Trajectory
traj = Trajectory('md.traj', 'w', atoms)
dyn.attach(traj.write, interval=10)
dyn.run(5000)
Analyzing Results
from ase.io import read, write
traj = read('opt.traj', ':')
final = traj[-1]
energies = [atoms.get_potential_energy() for atoms in traj]
forces = final.get_forces()
max_force = max(np.linalg.norm(forces, axis=1))
from ase.geometry import get_distances
d = atoms.get_distance(0, 1)
write('structure.cif', atoms)
write('structure.xyz', atoms)
write('POSCAR', atoms)
Band Structure Calculations
from ase.dft.kpoints import bandpath
atoms = bulk('Si', 'diamond', a=5.43)
path = atoms.cell.bandpath('GXWLG', npoints=100)
calc = GPAW(
mode=PW(400),
xc='PBE',
kpts={'path': path, 'density': 10}
)
atoms.calc = calc
atoms.get_potential_energy()
bs = calc.band_structure()
bs.plot(filename='bands.png', show=True)
Best Practices
1. Structure Validation
Always check your structure before running expensive calculations:
from ase.visualize import view
view(atoms)
from ase.geometry import get_distances
distances = get_distances(atoms.positions)[1]
min_distance = distances[distances > 0].min()
print(f"Minimum distance: {min_distance:.3f} Å")
print(f"Cell: {atoms.cell}")
print(f"PBC: {atoms.pbc}")
2. Calculator Management
if atoms.calc is None:
raise RuntimeError("No calculator attached")
calc = Vasp(xc='PBE', encut=400)
for structure in structures:
structure.calc = calc
energy = structure.get_potential_energy()
3. Error Handling
from ase.calculators.calculator import CalculationFailed
try:
energy = atoms.get_potential_energy()
except CalculationFailed as e:
print(f"Calculation failed: {e}")
4. Performance Tips
from ase.io import read
last_frame = read('md.traj', -1)
every_10th = read('md.traj', '::10')
from ase.constraints import FixAtoms
Common Workflows
Workflow 1: Surface Adsorption Energy
from ase.build import fcc111, add_adsorbate
from ase.optimize import BFGS
slab = fcc111('Pt', size=(4, 4, 4), vacuum=10.0)
slab.calc = EMT()
opt = BFGS(slab)
opt.run(fmax=0.05)
E_slab = slab.get_potential_energy()
add_adsorbate(slab, 'O', height=2.0, position='fcc')
opt = BFGS(slab)
opt.run(fmax=0.05)
E_slab_ads = slab.get_potential_energy()
from ase import Atoms
adsorbate = Atoms('O', positions=[(0, 0, 0)])
adsorbate.center(vacuum=10.0)
adsorbate.calc = EMT()
E_ads = adsorbate.get_potential_energy()
E_adsorption = E_slab_ads - E_slab - E_ads
print(f"Adsorption energy: {E_adsorption:.3f} eV")
Workflow 2: Lattice Constant Optimization
from ase.build import bulk
from ase.eos import calculate_eos
import numpy as np
atoms = bulk('Cu', 'fcc', a=3.6)
atoms.calc = EMT()
cell_params = np.linspace(3.4, 3.8, 10)
energies = []
for a in cell_params:
atoms = bulk('Cu', 'fcc', a=a)
atoms.calc = EMT()
energies.append(atoms.get_potential_energy())
eos = calculate_eos(atoms, trajectory='eos.traj')
v, e, B = eos.fit()
eos.plot('eos.png')
Workflow 3: Nudged Elastic Band (NEB)
from ase.neb import NEB
from ase.optimize import BFGS
initial = read('initial.traj')
final = read('final.traj')
images = [initial]
images += [initial.copy() for i in range(5)]
images += [final]
neb = NEB(images)
neb.interpolate()
for image in images[1:-1]:
image.calc = EMT()
opt = BFGS(neb, trajectory='neb.traj')
opt.run(fmax=0.05)
energies = [image.get_potential_energy() for image in images]
barrier = max(energies) - energies[0]
print(f"Activation barrier: {barrier:.3f} eV")
Debugging Tips
Check calculation status
print(atoms.calc.get_property('energy', atoms))
print(atoms.get_forces())
print(atoms.calc.parameters)
Visualization debugging
from ase.io import write
write('temp.png', atoms, rotation='10x,10y,10z')
traj = read('opt.traj', ':')
print(f"Number of steps: {len(traj)}")
for i, atoms in enumerate(traj):
print(f"Step {i}: E = {atoms.get_potential_energy():.3f} eV")
Important Notes
- Units: ASE uses eV for energy, Å for length, and eV/Å for forces by default
- PBC: Always set periodic boundary conditions correctly:
atoms.pbc = [True, True, False]
- Vacuum: For surfaces/molecules, add sufficient vacuum (typically 10-15 Å)
- k-points: Increase k-point density for accurate total energies; fewer k-points OK for geometry optimization
- Convergence: Test encut/k-points convergence for production calculations
- Constraints: Remember to fix appropriate atoms (e.g., bottom layers of slabs)
Resources
When suggesting ASE solutions:
- Reference official ASE documentation for specific modules
- Show complete, runnable examples
- Include appropriate error handling
- Mention calculator-specific requirements (VASP POTCAR files, GPAW setups, etc.)
- Suggest convergence testing for critical parameters
- Recommend visualization checks before expensive calculations
Example Response Pattern
When helping with ASE:
- Understand the specific task (structure building, calculation setup, analysis)
- Provide complete code example with imports
- Explain key parameters and their typical values
- Suggest validation/checking steps
- Mention common pitfalls for that task
- Recommend convergence tests if applicable