ExpandedEnsembleSampler¶
- class openmm.app.expandedensemblesampler.ExpandedEnsembleSampler(states: list[dict], simulation: Simulation, stepsPerIteration: int, reinitializeVelocities: bool = False, weights: list[float] | None = None, reportInterval: int = 1000, logFile: str | object | None = None, energyFile: str | object | None = None, checkpointFile: str | None = None, resume: bool = False)¶
ExpandedEnsembleSampler uses the expanded ensemble method to simulate a system in a collection of thermodynamic states. It supports both the temperature version, in which the states correspond to different temperatures, and the Hamiltonian version, in which they correspond to different potential functions. It also can combine them to vary temperature and potential function at the same time.
You provide a Simulation describing the system to simulate and a list of states. It simulates the system while periodically moving between states in a way that ensures correct sampling. The method is based on Gibbs sampling, which alternates sampling of conformations x and thermodynamic states s. It first performs molecular dynamics to sample P(x|s), the distribution of conformations for a fixed state. It then chooses a new state from the distribution P(s|x) for the current conformation. For more information on this method, see https://doi.org/10.33011/livecoms.4.1.1583.
Expanded ensemble sampling is used for a variety of purposes. Here are some of the more common ones.
The temperature version is most often used to accelerate sampling of rare events. A particular transition might only happen rarely at physiological temperature. You therefore simulate both the temperature you care about and also higher temperatures at which the transition happens more easily. Allowing it to move between temperatures produces accurate sampling at low temperature of the entire phase space.
The Hamiltonian version may be used to sample an alchemical transition between two endpoints. It produces efficient sampling at every point along the transition pathway from which a free energy difference can be computed.
Each thermodynamic state (not to be confused with a State object) is represented by a dict containing property values. All states must specify values for the same properties. They describe the ways in which the states differ from each other. The following properties are supported.
‘temperature’: the simulation temperature
‘groups’: a set containing the force groups to include when computing the energy, for example {0, 2}. It also may be a weighted sum specified as a dict. For example, {0:1.0, 2:0.5} means to compute the energy of group 0 plus half the energy of group 2.
Context parameters, specified by the parameter name
Global variables defined by a CustomIntegrator, specified by the variable name
For example, a typical use of temperature sampling might define the states as
>>> states = [{'temperature':t*kelvin} for t in np.geomspace(300.0, 500.0, 10)]
A typical use of Hamiltonian sampling might include forces that depend on a parameter lambda. The states could be defined as
>>> states = [{'lambda':x} for x in np.linspace(0.0, 1.0, 11)]
States may also specify multiple properties. This example includes all combinations of two different parameters.
>>> states = [{'lambda1':x, 'lambda2':y} for x in np.linspace(0.0, 1.0, 6) for y in np.linspace(0.0, 1.0, 6)]
To run an expanded ensemble simulation, first create a Simulation object in the normal way. Then create a ExpandedEnsembleSampler:
>>> sampler = ExpandedEnsembleSampler(states, simulation, stepsPerIteration)
The third argument is the number of time steps to integrate between attempted state changes. Then perform a simulation by calling simulation.step() in the usual way. The ExpandedEnsembleSampler adds a reporter to the Simulation that manages state changes as it runs.
The probability distribution P(s|x) is often very nonuniform, which can lead to the simulation spending much more time in some states than others. This is addressed by including a weight factor for each state when computing the probability. Ideally the weights should be chosen so it spends equal time in every state. You can specify the weights yourself with a constructor argument, but usually it is easier to let the ExpandedEnsembleSampler choose them automatically. This is done with a combination of the Wang-Landau (https://doi.org/10.1103/PhysRevLett.86.2050) and Self-Adjusted Mixture Sampling (http://dx.doi.org/10.1080/10618600.2015.1113975) algorithms. You should monitor the weights and discard the initial part of the simulation where they are changing rapidly. Until the weights have converged, the simulation will not sample the correct distribution.
An ExpandedEnsembleSampler can act as a reporter, generating output to files at regular intervals. The reporting interval should generally be the same as the one used for writing a trajectory so they will be synchronized with each other. The following files can optionally be written.
A log file that records the current thermodynamic state and weights. To analyze the results of a simulation, it
is essential to know what state it was in at every point in time. - A file recording the current reduced energy (potential energy divided by kT) of every thermodynamic state. This information is useful for calculating free energies. - A checkpoint file containing all information necessary to resume the simulation. This includes internal fields of the ExpandedEnsembleSampler itself, as well as a State object recording the current positions, velocities, parameters, etc.
To resume a simulation from the saved checkpoint, pass resume=True to the constructor. It will load all necessary information and configure the ExpandedEnsembleSampler correctly.
- states¶
The states to sample
- Type:
list[dict]
- simulation¶
The Simulation defining the System, Context, and Integrator to use
- Type:
openmm.app.Simulation
- stepsPerIteration¶
The number of time steps to integrate between attempted state changes
- Type:
int
- reinitializeVelocities¶
If true, the simulation’s velocities are reinitialized from a Boltzmann distribution every time its state changes. This may sometimes improve stability, but also decreases efficiency.
- Type:
bool
- currentIteration¶
The number of iterations that have been completed, each consisting of stepsPerIteration time steps followed by an attempted state change
- Type:
int
- currentStateIndex¶
The current state of the simulation, specified as an index into states.
- Type:
int
- __init__(states: list[dict], simulation: Simulation, stepsPerIteration: int, reinitializeVelocities: bool = False, weights: list[float] | None = None, reportInterval: int = 1000, logFile: str | object | None = None, energyFile: str | object | None = None, checkpointFile: str | None = None, resume: bool = False)¶
Create a new ExpandedEnsembleSampler.
- Parameters:
states (list[dict]) – The states to sample
simulation (openmm.app.Simulation) – The Simulation defining the System, Context, and Integrator to use
stepsPerIteration (int) – The number of time steps to integrate between attempted state changes
reinitializeVelocities (bool) – If true, the simulation’s velocities are reinitialized from a Boltzmann distribution every time its state changes. This may sometimes improve stability, but also decreases efficiency.
weights (list[float] | None) – The weights to use for each state. If None, weights are chosen automatically as the simulation runs.
reportInterval (int) – The frequency at which to write output, measured in time steps. This must be a multiple of stepsPerIteration.
logFile (str | object | None) – An optional file to write a log to. This may be either a file-like object or a string containing the path to the file.
energyFile (str | object | None) – An optional file to write reduced energies to. This may be either a file-like object or a string containing the path to the file.
checkpointFile (str | None) – The path to an optional file for saving checkpointing information
resume (bool) – Specifies whether to resume an earlier simulation. If True, the checkpoint will be loaded and future output will be appended to the existing files.
Methods
__init__(states, simulation, stepsPerIteration)Create a new ExpandedEnsembleSampler.
attemptStateChange(state)Attempt to move to a different state.
step(steps)Advance the simulation by integrating a specified number of time steps.
Attributes
weights- step(steps: int)¶
Advance the simulation by integrating a specified number of time steps.