Simulations with TorchSim#
TorchSim is a GPU-accelerated
molecular simulation engine built on PyTorch. MatterSim provides a
TorchSimWrapper that adapts MatterSim potentials as a TorchSim
ModelInterface, so you can use TorchSim’s optimizers and integrators
directly with MatterSim models.
Creating a TorchSim wrapper#
The easiest way to create a wrapper is via the get_torchsim_wrapper
helper, which accepts a model identifier, a checkpoint path, or an
already-loaded Potential object.
1import torch
2from mattersim.torchsim import get_torchsim_wrapper
3
4device = "cuda" if torch.cuda.is_available() else "cpu"
5
6# From a model identifier (downloads the checkpoint automatically)
7wrapper = get_torchsim_wrapper(potential="mattersim-v1.0.0-1M", device=device)
8
9# Or from an already-loaded Potential
10from mattersim.forcefield import Potential
11
12potential = Potential.from_checkpoint(device=device)
13wrapper = get_torchsim_wrapper(potential=potential, device=device)
You can also construct the wrapper directly if you need full control:
1from mattersim.torchsim import TorchSimWrapper
2from mattersim.forcefield import Potential
3
4potential = Potential.from_checkpoint(device=device)
5wrapper = TorchSimWrapper(model=potential, device=device)
Structure relaxation#
TorchSim provides several optimizers for structure relaxation, including
fire, lbfgs, bfgs, and gradient_descent.
1import numpy as np
2import torch
3import torch_sim as ts
4from ase.build import bulk
5from mattersim.torchsim import get_torchsim_wrapper
6
7device = "cuda" if torch.cuda.is_available() else "cpu"
8
9# Create the wrapper
10wrapper = get_torchsim_wrapper(potential="mattersim-v1.0.0-1M", device=device)
11
12# Set up the structure
13si = bulk("Si", "diamond", a=5.43)
14si.positions += 0.1 * np.random.randn(len(si), 3)
15
16# Initialize a TorchSim state from the ASE Atoms object
17state = ts.initialize_state([si], device=device)
18
19# Run relaxation with the FIRE optimizer
20relaxed_state = ts.optimize(
21 system=state,
22 model=wrapper,
23 optimizer=ts.Optimizer.fire,
24 max_steps=500,
25 pbar=True,
26)
27
28# Convert back to ASE Atoms
29relaxed_atoms = relaxed_state.to_atoms()[0]
30print(f"Relaxed energy: {relaxed_state.energy[0].item():.4f} eV")
You can also customize convergence criteria using
ts.generate_force_convergence_fn:
1convergence_fn = ts.generate_force_convergence_fn(force_tol=0.01)
2
3relaxed_state = ts.optimize(
4 system=state,
5 model=wrapper,
6 optimizer=ts.Optimizer.fire,
7 max_steps=500,
8 convergence_fn=convergence_fn,
9 pbar=True,
10)
Molecular dynamics#
TorchSim supports various integrators for molecular dynamics simulations. Below we demonstrate NVT dynamics using a Langevin thermostat.
1import torch
2import torch_sim as ts
3from ase.build import bulk
4from mattersim.torchsim import get_torchsim_wrapper
5
6device = "cuda" if torch.cuda.is_available() else "cpu"
7
8# Create the wrapper
9wrapper = get_torchsim_wrapper(potential="mattersim-v1.0.0-1M", device=device)
10
11# Set up the structure
12si = bulk("Si", "diamond", a=5.43)
13state = ts.initialize_state([si], device=device)
14
15# Run NVT MD at 300 K for 1000 steps
16final_state = ts.integrate(
17 system=state,
18 model=wrapper,
19 integrator=ts.Integrator.nvt_langevin,
20 n_steps=1000,
21 temperature=300.0,
22 timestep=1e-3,
23 pbar=True,
24)
25
26# Convert back to ASE Atoms
27final_atoms = final_state.to_atoms()[0]
Available integrators include:
NVE:
ts.Integrator.nve— microcanonical ensembleNVT Langevin:
ts.Integrator.nvt_langevin— Langevin thermostatNVT Nosé–Hoover:
ts.Integrator.nvt_nose_hoover— Nosé–Hoover thermostatNPT Langevin:
ts.Integrator.npt_langevin_isotropic— Langevin barostat (isotropic)NPT Nosé–Hoover:
ts.Integrator.npt_nose_hoover_isotropic— Nosé–Hoover barostat (isotropic)
Saving trajectories#
TorchSim can save trajectory frames to HDF5 files during the simulation
using a TrajectoryReporter.
1import torch
2import torch_sim as ts
3from ase.build import bulk
4from mattersim.torchsim import get_torchsim_wrapper
5
6device = "cuda" if torch.cuda.is_available() else "cpu"
7wrapper = get_torchsim_wrapper(potential="mattersim-v1.0.0-1M", device=device)
8
9si = bulk("Si", "diamond", a=5.43)
10state = ts.initialize_state([si], device=device)
11
12# Configure a trajectory reporter to save every 100 steps
13reporter = ts.TrajectoryReporter(
14 filenames=["md_trajectory.h5md"],
15 state_frequency=100,
16 state_kwargs=dict(save_velocities=True, save_forces=True),
17)
18
19final_state = ts.integrate(
20 system=state,
21 model=wrapper,
22 integrator=ts.Integrator.nvt_langevin,
23 n_steps=1000,
24 temperature=300.0,
25 timestep=1e-3,
26 trajectory_reporter=reporter,
27 pbar=True,
28)
Note
For more details on TorchSim’s API, including autobatching, advanced trajectory handling, and custom integrators, please refer to the TorchSim documentation.