PairForcesModel

class torch_sim.models.pair_potential.PairForcesModel(force_fn, *, cutoff, device=None, dtype=torch.float64, compute_stress=False, per_atom_stresses=False, neighbor_list_fn=torchsim_nl, reduce_to_half_list=False)[source]

Bases: ModelInterface

Batched pair model for potentials defined directly as forces.

Use this when the interaction is specified as a scalar force magnitude force_fn(distances, zi, zj) -> force_magnitudes rather than as an energy. This covers asymmetric or non-conservative interactions such as the particle-life potential where no scalar energy exists.

Forces are accumulated as:

F_i += -f_ij * r̂_ij, F_j += +f_ij * r̂_ij

Note

Unlike PairPotentialModel, this class does not compute energies (returns zeros) since there is no underlying energy function. Use PairPotentialModel when your interaction can be expressed as an energy function, as it provides automatic force computation via autograd and is generally more efficient.

Example:

from torch_sim.models.particle_life import particle_life_pair_force
from torch_sim.models.pair_potential import PairForcesModel
import functools

fn = functools.partial(particle_life_pair_force, A=1.0, beta=0.3, sigma=1.0)
model = PairForcesModel(force_fn=fn, cutoff=1.0)
results = model(sim_state)
Parameters:
  • force_fn (Callable)

  • cutoff (float)

  • device (device | None)

  • dtype (dtype)

  • compute_stress (bool)

  • per_atom_stresses (bool)

  • neighbor_list_fn (Callable)

  • reduce_to_half_list (bool)

forward(state, **_kwargs)[source]

Compute forces from a direct pair force function.

Parameters:
  • state (SimState) – Simulation state.

  • **_kwargs (object) – Unused; accepted for interface compatibility.

Returns:

dict with keys "energy" (zeros, shape [n_systems]), "forces" (shape [n_atoms, 3]), and optionally "stress" (shape [n_systems, 3, 3]) and "stresses" (shape [n_atoms, 3, 3]).

Raises:

TypeError – If the SimState’s dtype does not match the model’s dtype.

Return type:

dict[str, Tensor]