npx skills add ...
npx skills add nvidia/nvalchemi-toolkit --skill nvalchemi-dynamics-implementation
How to implement a dynamics integrator by subclassing BaseDynamics and overriding pre_update() and post_update() methods. Use when creating a custom integrator, optimizer, or sampler that the built-in stages do not provide; for configuring existing dynamics, see nvalchemi-dynamics-api.
npx skills add nvidia/nvalchemi-toolkit --skill nvalchemi-dynamics-implementation
To implement a dynamics class (integrator) in nvalchemi, subclass BaseDynamics
and override two methods: pre_update() and post_update(). The base class handles
the model forward pass, hook dispatch, convergence checking, and the step/run loop.
The first step(batch) after admission dispatches ON_ADMISSION, while subsequent
steps skip it until admission is explicitly reset. The per-step sequence is:
step() calls pre_update() and post_update() with autograd enabled — it does not wrap them in torch.no_grad(). Your implementation must wrap its own state updates in torch.no_grad() itself (as the example below and DemoDynamics do)compute() calls the model forward pass and writes forces/energy to the batch in-placepre_update() and post_update(); everything else is inheritedSet __needs_keys__ (model outputs your integrator requires) and __provides_keys__
(state your integrator produces).
__init__Store integrator parameters. Always call super().__init__() and forward **kwargs
(needed for cooperative multiple inheritance with the communication mixin).
BaseDynamics constructor parameters:
| Parameter | Type | Description |
|---|---|---|
model | BaseModelMixin | The neural network potential |
hooks | list[Hook] | None | Hooks to register (organized by stage) |
convergence_hook | ConvergenceHook | dict | None | Convergence detection |
n_steps | int | None | Default step count for run() |
exit_status | int | Status value for graduated samples (default: 1) |
**kwargs | Any | Forwarded to communication mixin |
pre_update(batch)Update positions based on current velocities and forces. Modify the batch in-place.
post_update(batch)Update velocities based on new forces (computed between pre_update and post_update
by the inherited compute() method). Modify the batch in-place.
| Method | Description |
|---|---|
compute(batch) | Model forward pass → validates outputs → writes forces/energy to batch |
step(batch) | Full step with hook dispatch (see flow above) |
run(batch, n_steps=None) | Loop calling step() for n_steps iterations |
register_hook(hook) | Register a hook at its declared stage |
_check_convergence(batch) | Check convergence criteria, return converged indices |
_validate_model_outputs(outputs) | Verify __needs_keys__ are present in model output |
| Attribute | Type | Description |
|---|---|---|
model | BaseModelMixin | The wrapped model |
step_count | int | Current step (starts at 0, incremented after each step) |
hooks | dict[DynamicsStage, list[Hook]] | Registered hooks by stage |
convergence_hook | ConvergenceHook | None | Convergence detector |
n_steps | int | None | Default step count |
exit_status | int | Status threshold for graduated samples |
model_is_conservative | bool | Whether forces use autograd |
This mirrors DemoDynamics, the reference implementation.
Use ConvergenceHook to stop early or migrate samples in a pipeline:
Chain multiple dynamics stages that share a single model forward pass:
Chain stages across ranks with the | operator: