nanover.openmm.imd module

Link NanoVer’s user forces to an OpenMM simulation.

The iMD is hooked to the OpenMM simulation in two places. A CustomExternalForce needs to be added in the system; it has the components of the iMD force for each atom as a per-atom parameter. A reporter periodically updates these parameters based on the imd service, and updates the simulation context.

The custom force can be setup using create_imd_force() and populate_imd_force(), or using add_imd_force_to_system() that combines the two previous functions. When a simulation is created using nanover.openmm.serializer.deserialize_simulation(), the imd force must be already present, or must be added by passing it with the imd_force parameter.

The reporter is NanoverImdReporter and both sends the frames and receives the interactions. It can be use instead of nanover.openmm.NanoverReporter that only sends the frames.

from nanover.app import NanoverImdApplication
from nanover.openmm.serializer import deserialize_simulation
from nanover.openmm.imd import NanoverImdReporter, create_imd_force

# Setup the NanoVer application server
# The server is accessible using autoconnect.
with NanoverImdApplication.basic_server() as app:

    # Create the imd force and a simulation that includes it.
    imd_force = create_imd_force()
    with open('simulation.xml') as infile:
        simulation = deserialize_simulation(infile.read(), imd_force=imd_force)

    # Setup the reporter that does the translation between NanoVer and OpenMM
    reporter = NanoverImdReporter(
        frame_interval=5,
        force_interval=10,
        imd_force=imd_force,
        imd_service=app.imd,
        frame_publisher=app.frame_publisher,
    )
    simulation.reporters.append(reporter)

    # Run the simulation
    while True:
        simulation.run(10)
class nanover.openmm.imd.ImdForceManager(imd_state: ImdStateWrapper, imd_force: CustomExternalForce)

Bases: object

add_to_frame_data(frame_data: FrameData)
update_interactions(simulation: Simulation, positions: ndarray)
class nanover.openmm.imd.NanoverImdReporter(frame_interval: int, force_interval: int, include_velocities: bool, include_forces: bool, imd_force: CustomExternalForce, imd_state: ImdStateWrapper, frame_publisher: FramePublisher)

Bases: object

describeNextReport(simulation: Simulation) NextReport

Called by OpenMM. Indicates when the next report is due and what type of data it requires.

force_interval: int
frame_interval: int
frame_publisher: FramePublisher
imd_force: CustomExternalForce
include_forces: bool
include_velocities: bool
make_regular_frame(simulation: Simulation, state: State, positions: List[List[float]] | ndarray[Any, dtype[float32 | float64]] | None = None)
make_topology_frame(simulation: Simulation)
report(simulation: Simulation, state: State) None

Called by OpenMM.

class nanover.openmm.imd.NextReport(steps, include_positions, include_velocities, include_forces, include_energies, wrap_positions)

Bases: NamedTuple

include_energies: bool

Alias for field number 4

include_forces: bool

Alias for field number 3

include_positions: bool

Alias for field number 1

include_velocities: bool

Alias for field number 2

steps: int

Alias for field number 0

wrap_positions: bool

Alias for field number 5

nanover.openmm.imd.add_imd_force_to_system(system: System) CustomExternalForce

Generate an OpenMM force that accepts arbitrary forces per particle.

The force is created, populated, added to the system and returned.

This is the force that is used to communicate the particle interactions from NanoVer by NanoverImdReporter.

nanover.openmm.imd.create_imd_force() CustomExternalForce

Returns an empty OpenMM force to communicate imd forces.

Each particle in the system has a fx, fy, and fz parameter to provide the arbitrary force components.

The force needs to be populated to include all the particle in the simulation mm.System.

nanover.openmm.imd.get_imd_forces_from_system(system: Simulation) List[CustomExternalForce]

Find the forces that are compatible with an imd force in a given system.

A compatible force has the expected energy expression, and contains as many particles as the system.

All the compatible force objects are returned.

nanover.openmm.imd.get_sparse_forces(user_forces: ndarray[Any, dtype[_ScalarType_co]]) Tuple[ndarray[Any, dtype[_ScalarType_co]], ndarray[Any, dtype[_ScalarType_co]]]

Takes in an array of user forces acting on the system containing N particles and outputs two arrays that describe these user forces in a sparse form:

  • The first contains the indices of the particles for which the user forces are non-zero

  • The second contains the non-zero user forces associated with each index

Parameters:

user_forces – Array of user forces with dimensions (N, 3)

Returns:

Array of particle indices, Array of corresponding user forces

nanover.openmm.imd.populate_imd_force(force: CustomExternalForce, system: System) None

Add all the particles to the iMD force.

The iMD force must be one generated by create_imd_force().