Molecular Dynamics¶
Molecular dynamics (MD) simulates atomic motion over time, sampling configurations at finite temperature.
Basic Usage¶
from mace_inference import MACEInference
from ase.io import read
calc = MACEInference(model="medium", device="auto")
atoms = read("structure.cif")
# NVT simulation at 300 K
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=300,
timestep=1.0,
steps=1000
)
Ensembles¶
MACE Inference supports two common ensembles:
NVT (Canonical)¶
Constant number of particles, volume, and temperature.
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=300, # Kelvin
timestep=1.0, # fs
steps=5000,
taut=100 # Temperature coupling time (fs)
)
Uses Langevin thermostat for temperature control.
NPT (Isothermal-Isobaric)¶
Constant number of particles, pressure, and temperature.
final = calc.run_md(
atoms,
ensemble="npt",
temperature_K=300, # Kelvin
pressure_GPa=0.0001, # GPa (0.1 MPa ≈ 1 atm)
timestep=1.0, # fs
steps=5000
)
Uses Berendsen barostat for pressure control.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
atoms |
Atoms |
required | Initial structure |
ensemble |
str |
"nvt" |
"nvt" or "npt" |
temperature_K |
float |
300 |
Temperature in Kelvin |
pressure_GPa |
float |
None |
Pressure in GPa (NPT only) |
timestep |
float |
1.0 |
Time step in fs |
steps |
int |
1000 |
Number of MD steps |
taut |
float |
None |
Temperature coupling time (fs) |
taup |
float |
None |
Pressure coupling time (fs) |
trajectory |
str |
None |
Save trajectory to file |
log_interval |
int |
100 |
Print every N steps |
progress_callback |
Callable |
None |
Callback function |
Return Values¶
The run_md method returns the final Atoms object after the simulation.
Examples¶
Basic NVT Simulation¶
# Run MD and get final structure
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=300,
timestep=1.0,
steps=5000,
trajectory="md.traj", # Save trajectory to file
log_interval=100
)
# Final structure is an Atoms object
print(f"Final energy: {final.get_potential_energy():.4f} eV")
Using Trajectory File¶
from ase.io import read, Trajectory
# Run MD with trajectory saved
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=300,
steps=5000,
trajectory="md.traj"
)
# Read trajectory for analysis
traj = Trajectory("md.traj")
print(f"Trajectory frames: {len(traj)}")
# Analyze energies
energies = [frame.get_potential_energy() for frame in traj]
NPT for Volume Equilibration¶
# Equilibrate at 1 atm
final = calc.run_md(
atoms,
ensemble="npt",
temperature_K=300,
pressure_GPa=0.0001, # ~1 atm
timestep=1.0,
steps=10000,
trajectory="npt.traj"
)
# Check volume change
print(f"Initial volume: {atoms.get_volume():.2f} ų")
print(f"Final volume: {final.get_volume():.2f} ų")
High-Temperature Dynamics¶
# Simulate at 1000 K
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=1000,
timestep=0.5, # Smaller timestep for stability
steps=10000,
taut=50 # Tighter coupling at high T
)
With Progress Callback¶
def progress(current, total):
if current % 100 == 0:
print(f"MD: {current}/{total} steps ({100*current/total:.1f}%)")
final = calc.run_md(
atoms,
ensemble="nvt",
temperature_K=300,
steps=5000,
progress_callback=progress
)
Workflow Tips¶
Always Optimize First¶
# Step 1: Optimize (returns Atoms object)
optimized = calc.optimize(atoms, fmax=0.01)
# Step 2: Run MD on relaxed structure
final = calc.run_md(optimized, ensemble="nvt", temperature_K=300, steps=5000)
Equilibration + Production¶
# Equilibration run
equil = calc.run_md(atoms, ensemble="nvt", temperature_K=300, steps=2000)
# Production run from equilibrated structure
final = calc.run_md(equil, ensemble="nvt", temperature_K=300, steps=10000, trajectory="prod.traj")
# Analyze production trajectory from file
Temperature Ramp¶
temps = [100, 200, 300, 400, 500]
current_atoms = atoms.copy()
for T in temps:
current_atoms = calc.run_md(
current_atoms,
ensemble="nvt",
temperature_K=T,
steps=1000
)
print(f"T={T} K: E={current_atoms.get_potential_energy():.4f} eV")
Common Issues¶
Temperature Instability¶
If temperature fluctuates wildly:
- Reduce timestep
- Increase friction
- Check initial structure (optimize first)
Atoms "Explode"¶
If atoms fly apart:
- Structure may not be relaxed - optimize first
- Timestep too large
- Check for atoms too close together
Slow Simulation¶
For faster simulations:
- Use GPU:
device="cuda" - Increase
save_interval - Use float32:
default_dtype="float32"