nvalchemi.dynamics.hooks.MaxForceClampHook#

class nvalchemi.dynamics.hooks.MaxForceClampHook(max_force, frequency=1)[source]#

Clamp per-atom force vectors to a maximum magnitude.

After the model forward pass, this hook checks whether any atom has a force vector whose L2 norm exceeds max_force. If so, the offending force vectors are rescaled in-place to have norm exactly equal to max_force, preserving their direction.

This is a lightweight safety mechanism that prevents numerical explosions caused by:

  • ML potential extrapolation on out-of-distribution geometries.

  • Bad initial configurations with overlapping atoms.

  • Sudden large gradients from discontinuities in the potential energy surface.

The clamping is applied before the velocity update (post_update), so the integrator sees bounded accelerations. This can prevent irreversible simulation blowups while allowing the system to recover.

Parameters:
  • max_force (float) – Maximum allowed force magnitude (L2 norm) per atom, in the same units as the model’s force output (typically eV/A).

  • frequency (int, optional) – Apply clamping every frequency steps. Default 1 (every step).

max_force#

Maximum allowed force norm.

Type:

float

frequency#

Clamping frequency in steps.

Type:

int

stage#

Fixed to AFTER_COMPUTE.

Type:

HookStageEnum

Examples

>>> from nvalchemi.dynamics.hooks import MaxForceClampHook
>>> hook = MaxForceClampHook(max_force=50.0)
>>> dynamics = DemoDynamics(model=model, n_steps=1000, dt=0.5, hooks=[hook])
>>> dynamics.run(batch)

Notes

  • Clamping is a band-aid, not a fix. Frequent clamping indicates that the model is being evaluated outside its domain of applicability or that the timestep is too large.

  • The implementation uses torch.linalg.vector_norm and torch.where for efficient, in-place operation on the full (V, 3) force tensor.

  • When used with NaNDetectorHook, register MaxForceClampHook first so that forces are clamped before the NaN check (both fire at AFTER_COMPUTE in registration order).

__init__(max_force, frequency=1)[source]#
Parameters:
  • max_force (float)

  • frequency (int)

Return type:

None

Methods

__init__(max_force[, frequency])

Attributes

stage