Basic usage
===========
This section provides a brief overview of how to use the `adaptive_sampling` package. For more detailed information, please refer to the tutorials and code documentation.
Molecular dynamics (MD) interfaces
----------------------------------
The `adaptive_sampling` package provides interfaces to run molecular dynamics simulation on various levels of theory.
These interfaces allow you to run simulations using the sampling and exploration tools provided by the package.
* **AseMD**: For running *ab initio* molecular dynamics simulations using the calculators from the atomic simulation environment (ASE), which provides interfaces to various quantum chemistry packages.
* **AshMD**: For running *ab initio* molecular dynamics simulations using the ASH package, which provides additional support for QM/MM simulations.
* **AdaptiveSamplingOpenMM**: Allows performing molecular dynamics simulations using the OpenMM engine.
* **InterfaceMD_2D**: Provides 2D potentials for testing of sampling methods.
The ASE interface
^^^^^^^^^^^^^^^^^
The `AseMD` class allows for running adaptive sampling algorithms using any ASE calculator.
Refer to the ASE `documentation `_ for more information on available calculators and molecular modeling workflows in ASE.
In the below example we will use the `tblite` package and the GFN2-xTB tight-binding method.
.. code-block:: python
:linenos:
# create an ASE fragment from an XYZ files
from ase.io import read
frag = read("structure.xyz")
# Attach the tblite calculator to the fragment
from tblite.ase import TBLite
frag.calc = TBLite(method="GFN2-xTB")
# Initialize the AseMD object
from adaptive_sampling.interface import AseMD
the_md = AseMD(
atoms=frag, # ASE fragment
dt=1.0, # Timestep in fs
thermostat=True, # Apply an langevin thermostat
target_temp=300.0, # The thermostat temperature
scratch_dir="./scratch/", # Location where scratch files of the calculator should be written
)
# Initialize one or multiple sampling methods from `sampling_tools`
from adaptive_sampling.sampling_tools import *
the_bias = ...
# Initialize the MD
the_md.calc_init(
init_momenta="random", # Method for momenta initialization
biaspots=[the_bias, ], # Set the sampling algorithms
init_temp=300.0, # The initial temperature, if `init_momenta="random"`
restart_file=None, # Filename of restart file, if `init_momenta="read"`
)
# Ready for running the MD
the_md.run(nsteps=10000)
The ASH interface
^^^^^^^^^^^^^^^^^
The `AshMD` class allows for running adaptive sampling algorithms using any ASH theory object.
Refer to the ASH `documentation `_ for more information on available theory objects and molecular modeling workflows in ASH.
In the below example we will perform a QM/MM MD simulation using the xTB method and an AMBER force field.
.. code-block:: python
:linenos:
# Create the ASH fragment from a PDB
import ash
frag = ash.Fragment(
pdbfile="structure.pdb",
charge=0, # charge of the QM subsystem
mult=1 # multiplicity of the QM subsystem
)
# Create the MM Theory
mm_theory = ash.OpenMMTheory(
cluster_fragment=frag, # ASH Fragment
Amberfiles=True, # Use Amber parameter file
amberprmtopfile=f"structure.parm7", # The Amber parameter file
hydrogenmass=1.0, # default: 1.5 (hydrogen mass repartitioning)
rigidwater=False, # constraints not compatible with QM/MM!
autoconstraints=None, # constraints not compatible with QM/MM!
periodic=True, # Periodic boundary conditions or not.
)
# Create the QM Theory
qm_theory = ash.xTBTheory(
xtbmethod="GFN2", # The xTB method
runmode="inputfile", # Only "inputfile" supports QM/MM
)
# Create the QM/MM System
qm_atoms = [i for i in range(0, 23)] # Indices of QM atoms
qmmm_theory = ash.QMMMTheory(
qm_theory=qm_theory, # ASH QM Theory object
mm_theory=mm_theory, # ASH MM Theory object (should be OpenMMTheory)
fragment=frag, # ASH Fragment
embedding="Elstat", # QM/MM embedding type
qmatoms=qm_atoms, # The QM atoms (list of atom indices)
)
# Initialize the AseMD interface
from adaptive_sampling.interface.interfaceASH import AshMD
the_md = AshMD(
fragment=frag, # ASH fragment
calculator=qmmm_theory, # ASH calculator
dt=1.0, # Time step in fs
thermostat=True, # Apply Langevin thermostat
target_temp=300.0, # The target temperature in Kelvin
barostat=True, # Apply Monte-Carlo barostat
target_pressure=1.0, # The target pressure in Bar
barostat_freq=25, # Frequency of updating the barostat
)
# Initialize one or multiple sampling methods from `sampling_tools`
from adaptive_sampling.sampling_tools import *
the_bias = ...
# Initialize the MD
the_md.calc_init(
init_momenta="random", # Method for momenta initialization
biaspots=[the_bias, ], # Set the sampling algorithms
init_temp=300.0, # The initial temperature, if `init_momenta="random"`
restart_file=None, # Filename of restart file, if `init_momenta="read"`
)
# Ready to run the MD
the_md.run(nsteps=2)
The OpenMM interface
^^^^^^^^^^^^^^^^^^^^
This section provides a minimal example for using the OpenMM interface together with AMBER style `prmtop` and `crd` files.
Note that also other file formats are supported by OpenMM.
You can initialize the `AdaptiveSamplingOpenMM` class as follows:
.. code-block:: python
:linenos:
from sys import stdout
from openmm import *
from openmm.app import *
from openmm.unit import *
from adaptive_sampling.interface import AdaptiveSamplingOpenMM
# Setup OpenMM
prmtop = AmberPrmtopFile(f"structure.prmtop")
crd = AmberInpcrdFile(f"structure.crd")
system = prmtop.createSystem(
nonbondedMethod=NoCutoff,
constraints=HBonds,
)
# Initialize the `AdaptiveSamplingOpenMM` interface to couple the OpenMM simulation to a bias potential
the_md = AdaptiveSamplingOpenMM(
crd.positions,
prmtop.topology,
system,
dt=2.0, # timestep in fs
equil_temp=300.0, # temperature of simulation in Kelvin
langevin_damping=1.0, # langevin damping in 1/ps
)
# The OpenMM `simulation` and `integrator` objects are set up internally, but can still be modified by calling `the_md.simulation` or `the_md.integrator`
the_md.integrator.setConstraintTolerance(0.00001)
the_md.simulation.reporters.append(DCDReporter('trajectory.dcd', 100))
Before running the MD any importance sampling algorithm from `sampling_tools` has to be attached to the OpenMM interface:
.. code-block:: python
:linenos:
from adaptive_sampling.sampling_tools import *
the_bias = ... # init sampling algorithm
the_md.set_sampling_algorithm(the_bias)
If you want to apply multiple sampling algorithms, you can specify those as a list:
.. code-block:: python
:linenos:
from adaptive_sampling.sampling_tools import *
the_bias1 = ... # init first sampling algorithm
the_bias2 = ... # init second sampling algorithm, e.g. additional harmonic constraint
the_md.set_sampling_algorithm([the_bias1, the_bias2])
Now, the MD is ready to run:
.. code-block:: python
:linenos:
the_md.run(nsteps=500000) # 500000 * 2 fs = 1 ns
Sampling tools
--------------
Importance sampling algorithms facilitate the calculation of reaction and activation free energies by sampling molecular transitions.
In the `adaptive sampling` package these are located in the `sampling_tools` subpackage.
.. code-block:: python
:linenos:
from adaptive_sampling.sampling_tools import *
Implemented are a wide range of sampling algorithms, including well-tempered metadynamics (WTM) and its successor on-the-fly probability enhanced sampling (OPES), the adaptive biasing force (ABF) method or extended-system based hybrid methods (WTM-eABF, OPES-eABF).
To apply simple harmonic constraints, like for example often used in Umbrella Sampling (US), you can use the `Harmonic_Constraint` class.
.. code-block:: python
:linenos:
from adaptive_sampling.sampling_tools import Harmonic_Constraint
the_bias = Harmonic_Constraint(
the_md,
force_constants=100.0, # In kJ/mol/(CV unit)^2, can also be a list for multiple harmonic constraints
equil_positions=1.0, # In the unit of the CV, can also be a list for multiple harmonic constraints
colvars=[
['distance', [0,1]], # Definition of the Collective Variable
# Additional CVs can be added to the list
],
outputfile='constraints_traj.dat', # The output file
output_stride=1, # The output stride
)
The OPES-eABF hybrid sampling method can be applied as follows:
.. code-block:: python
:linenos:
from adaptive_sampling.sampling_tools import OPESeABF
the_cv = [
# TYPE IDX MIN MAX BIN WIDTH
['distance', [0,1], 1.0, 5.0, 0.1]
]
the_bias = OPESeABF(
the_md,
the_cv,
)
Here, default parameters of OPES-eABF are applied, estimating parameters like the coupling width to the extended system and the kernel standard deviation from the first 1000 MD steps, before applying any bias.
For more information on OPES-eABF parameters and other sampling methods visit the corresponding section of the documentation, as well as the Code Documentation.
Exploration tools
-----------------