HOOMD-blue
HOOMD-blue is a Python package that runs simulations of particle systems on CPUs and GPUs. It performs hard particle Monte Carlo simulations of a variety of shape classes and molecular dynamics simulations of particles with a range of pair, bond, angle, and other potentials. Many features are targeted at the soft matter research community, though the code is general and capable of many types of particle simulations.
Resources
GitHub Repository: Source code and issue tracker.
Citing HOOMD-blue: How to cite the code.
Installation guide: Instructions for installing HOOMD-blue binaries.
Compilation guide: Instructions for compiling HOOMD-blue.
hoomd-users mailing list: Send messages to the HOOMD-blue user community.
HOOMD-blue website: Additional information and publications.
HOOMD-blue benchmark scripts: Scripts to evaluate the performance of HOOMD-blue simulations.
HOOMD-blue validation tests: Scripts to validate that HOOMD-blue performs accurate simulations.
Example scripts
These examples demonstrate some of the Python API.
Hard particle Monte Carlo:
import hoomd
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=20)
sim.operations.integrator = mc
# The tutorial describes how to construct an initial configuration 'init.gsd'.
sim.create_state_from_gsd(filename='init.gsd')
sim.run(1e5)
Molecular dynamics:
import hoomd
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator = hoomd.md.Integrator(dt=0.005)
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
gpu = hoomd.device.GPU()
sim = hoomd.Simulation(device=gpu)
sim.operations.integrator = integrator
# The tutorial describes how to construct an initial configuration 'init.gsd'.
sim.create_state_from_gsd(filename='init.gsd')
sim.state.thermalize_particle_momenta(filter=hoomd.filter.All(), kT=1.5)
sim.run(1e5)
Features
Hard particle Monte Carlo
HOOMD-blue can perform simulations of hard particles using the Monte Carlo method (hpmc
). Hard
particles are defined by their shape, and the HPMC integrator
supports
polygons, spheropolygons, polyhedra, spheropolyhedra, ellipsoids, faceted ellipsoids, spheres,
indented spheres, and unions of shapes. HPMC can make both constant volume and constant pressure
box moves (hpmc.update.BoxMC
), perform cluster moves (hpmc.update.Clusters
)
and can compute the pressure during constant volume simulations (hpmc.compute.SDF
).
HPMC can also apply external and pair potentials to the particles. Use
hpmc.external.field.Harmonic
to restrain particles to a lattice (e.g. for Frenkel-Ladd
calculations) or hpmc.external.user.CPPExternalPotential
to implement arbitrary external fields
(e.g. gravity). Use hpmc.pair.user
to define arbitrary pairwise interactions between particles.
At runtime, hoomd.version.hpmc_built
indicates whether the build supports HPMC simulations.
See also
Tutorial: Introducing HOOMD-blue
Molecular dynamics
HOOMD-blue can perform molecular dynamics simulations (md
) with NVE, NVT, NPT, NPH, Langevin,
Brownian, overdamped viscous integration methods (md.methods
), and energy minimization
(md.minimize
). Unless otherwise stated in the documentation, all integration methods integrate
both translational and rotational degrees of freedom. Some integration methods support manifold
constraints (md.methods.rattle
). HOOMD-blue provides a number of pair potentials (md.pair
)
including pair potentials that depend on particle orientation (md.pair.aniso
) and many body
potentials (md.many_body
). HOOMD-blue also provides bond potentials and distance constraints
commonly used in atomistic and coarse-grained force fields (md.angle
, md.bond
,
md.constrain.Distance
, md.dihedral
, md.improper
, md.special_pair
) and can model rigid bodies
(md.constrain.Rigid
). External fields md.external.field
apply potentials based only on the
particle’s position and orientation, including walls (md.external.wall
) to confine particles in a
specific region of space. md.long_range
provides long ranged interactions, including the PPPM
method for electrostatics. HOOMD-blue enables active matter simulations with md.force.Active
and
md.update.ActiveRotationalDiffusion
. At runtime, hoomd.version.md_built
indicates whether the
build supports MD simulations.
See also
Tutorial: Introducing Molecular Dynamics
Python package
HOOMD-blue is a Python package and is designed to interoperate with other packages in the scientific
Python ecosystem and to be extendable in user scripts. To enable interoperability, all operations
provide access to useful computed quantities as properties in native Python types or numpy arrays
where appropriate. Additionally, State
and md.force.Force
provide direct access to
particle properties and forces using Python array protocols. Users can customize their simulation or
extend HOOMD-blue with functionality implemented in Python code by subclassing trigger.Trigger
,
variant.Variant
, hoomd.update.CustomUpdater
, hoomd.write.CustomWriter
,
hoomd.tune.CustomTuner
, or by using the HOOMD-blue API in combination with other Python packages
to implement methods that couple simulation, analysis, and multiple simulations (such as umbrella
sampling).
See also
Tutorial: Custom Actions in Python
CPU and GPU devices
HOOMD-blue can execute simulations on CPUs or GPUs. Typical simulations run more efficiently on
GPUs for system sizes larger than a few thousand particles, although this strongly depends on the
details of the simulation. The provided binaries support NVIDIA GPUs. Build from source to enable
preliminary support for AMD GPUs. CPU support is always enabled. GPU support must be enabled at
compile time with the ENABLE_GPU
CMake option (see Building from source). Select the device to use at
run time with the device
module. Unless otherwise stated in the documentation,
all operations and methods support GPU execution. At runtime, hoomd.version.gpu_enabled
indicates
whether the build supports GPU devices.
Autotuned kernel parameters
HOOMD-blue automatically tunes kernel parameters to improve performance when executing on a GPU device. During the first 1,000 - 20,000 timesteps of the simulation run, HOOMD-blue will change kernel parameters each time it calls a kernel. Kernels compute the same output regardless of the parameter (within floating point precision), but the parameters have a large impact on performance.
Check to see whether tuning is complete with the is_tuning_complete
attribute of your simulation’s Operations
. For example, use this to run timed benchmarks after the performance stabilizes.
The optimal parameters can depend on the number of particles in the simulation and the density, and
may vary weakly with other system properties. To maintain peak performance, call
tune_kernel_parmeters
to tune the parameters again after
making a change to your system.
AutotunedObject
provides a settable dictionary parameter with the current kernel parameters in
kernel_parameters
. Use this to inspect the
autotuner’s behavior or override with specific values (e.g. values saved from a previous execution).
MPI
HOOMD-blue can use the message passing interface (MPI) to execute simulations in less time using
more than one CPU core or GPU. Unless otherwise stated in the documentation, all operations and
methods support MPI parallel execution. MPI support is optional, requires a compatible MPI library,
and must be enabled at compile time with the ENABLE_MPI
CMake option (see Building from source).
At runtime, hoomd.version.mpi_enabled
indicates whether the build supports MPI.
See also
Tutorial: Parallel Simulation With MPI
Threading
Some operations in HOOMD-blue can use multiple CPU threads in a single process. Control this with
the device.Device.num_cpu_threads
property. In this release, threading support in HOOMD-blue is
very limited and only applies to implicit depletants in hpmc.integrate.HPMCIntegrator
, and
hpmc.pair.user.CPPPotentialUnion
. Threading must must be enabled at compile time with the
ENABLE_TBB
CMake option (see Building from source). At runtime, hoomd.version.tbb_enabled
indicates
whether the build supports threaded execution.
Run time compilation
Some operations allow the user to provide arbitrary C++ code that HOOMD-blue compiles at run time
and executes during the simulation. hpmc.pair.user
and hpmc.external.user
enable users to apply
arbitrary pair and external potentials to particles in HPMC simulations. hpmc.pair.user
supports both CPUs and NVIDIA GPUs while hpmc.external.user
only supports CPUs. Run time
compilation must be enabled at compile time with the ENABLE_LLVM
CMake option (see
Building from source). At runtime, hoomd.version.llvm_enabled
indicates whether the build supports run
time compilation.
Mixed precision
HOOMD-blue performs computations with mixed floating point precision. There is a high precision
type and a reduced precision type. All particle properties are stored in the high precision
type, and most operations also perform all computations with high precision. Operations that do not
mention “Mixed precision” in their documentation perform all calculations in high percision. Some
operations use reduced precision when possible to improve performance, as detailed in the
documentation for each operation. In this release, only hpmc
implements mixed precision.
The precision is set at compile time with the SINGLE_PRECISION
and
ENABLE_HPMC_MIXED_PRECISION
CMake options (see Building from source). By default, the high precision
width is 64 bits and the reduced precision width is 32 bits. At runtime,
hoomd.version.floating_point_precision
indicates the width of the floating point types.
Plugins
Plugin code that provides additional functionality to HOOMD-blue may be implemented in pure Python or as a package with C++ compiled libraries.
See also
Installing binaries
HOOMD-blue binaries are available in the glotzerlab-software Docker/Singularity images and in packages on conda-forge
Singularity / Docker images
See the glotzerlab-software documentation for instructions to install and use the containers on supported HPC clusters.
Conda package
HOOMD-blue is available on conda-forge on the linux-64, osx-64, and osx-arm64 platforms.
Install the hoomd
package from the conda-forge channel into a conda environment:
$ conda install -c conda-forge hoomd
Recent versions of conda
auto-detect whether your system has a GPU and installs the appropriate
package. Override this and force GPU package installation with:
$ conda install -c conda-forge "hoomd=*=*gpu*"
Note
To use Run time compilation on macOS, install the compilers
package:
$ conda install -c conda-forge compilers
Without this package you will get file not found errors when HOOMD-blue performs the run time compilation.
Tip
Use mambaforge, miniforge or miniconda instead of the full Anaconda distribution to avoid package conflicts with conda-forge packages.
Building from source
To build the HOOMD-blue Python package from source:
-
$ <package-manager> install cmake eigen git python numpy pybind11
-
$ git clone --recursive https://github.com/glotzerlab/hoomd-blue
-
$ cmake -B build/hoomd -S hoomd-blue
-
$ cmake --build build/hoomd
Install the package (optional):
$ cmake --install build/hoomd
To build the documentation from source (optional):
-
$ <package-manager> install sphinx sphinx_rtd_theme nbsphinx ipython
Note
nbsphinx
requires pandoc>=1.12.1
, which you may need to install separately.
-
$ sphinx-build -b html hoomd-blue/sphinx-doc build/hoomd-documentation
The sections below provide details on each of these steps.
Install prerequisites
HOOMD-blue requires a number of tools and libraries to build. The options ENABLE_MPI
,
ENABLE_GPU
, ENABLE_TBB
, and ENABLE_LLVM
each require additional libraries when enabled.
Note
This documentation is generic. Replace <package-manager>
with your package or module
manager. You may need to adjust package names and/or install additional packages, such as
-dev
packages that provide headers needed to build hoomd.
Tip
Create a virtual environment, one place where you can install dependencies and HOOMD-blue:
$ python3 -m venv hoomd-venv
You will need to activate your environment before configuring HOOMD-blue:
$ source hoomd-venv/bin/activate
Note
Some package managers (such as pip) and many clusters are missing some or all of pybind11,
eigen, and cereal. install-prereq-headers.py
will install these packages into your
virtual environment:
$ python3 hoomd-blue/install-prereq-headers.py
General requirements:
C++17 capable compiler (tested with
gcc
7 - 12 andclang
6 - 14)Python >= 3.6
NumPy >= 1.7
pybind11 >= 2.2
Eigen >= 3.2
CMake >= 3.9
For MPI parallel execution (required when ENABLE_MPI=on
):
MPI (tested with OpenMPI, MVAPICH)
cereal >= 1.1
For GPU execution (required when ENABLE_GPU=on
):
NVIDIA CUDA Toolkit >= 9.0
OR
AMD ROCm >= 3.5.0 with additional dependencies:
HIP [with
hipcc
andhcc
as backend]rocFFT
rocPRIM
rocThrust
hipCUB, included for NVIDIA GPU targets, but required as an external dependency when building for AMD GPUs
roctracer-dev
Linux kernel >= 3.5.0
CMake >= 3.21
For HOOMD-blue on AMD GPUs, the following limitations currently apply.
Certain kernels trigger an unknown HSA error.
The
mpcd
component is disabled on AMD GPUs.Multi-GPU execution via unified memory is not available.
Note
When ENABLE_GPU=on
, HOOMD-blue will default to CUDA. Set HHOOMD_GPU_PLATFORM=HIP
to
choose HIP.
For threaded parallelism on the CPU (required when ENABLE_TBB=on
):
Intel Threading Building Blocks >= 4.3
For runtime code generation (required when ENABLE_LLVM=on
):
LLVM >= 10.0
libclang-cpp >= 10.0
To build the documentation:
sphinx
sphinx_rtd_theme
nbsphinx
ipython
Obtain the source
Clone using Git:
$ git clone --recursive https://github.com/glotzerlab/hoomd-blue
Release tarballs are also available as GitHub release assets: Download hoomd-v3.7.0.tar.gz.
See also
See the git book to learn how to work with Git repositories.
Warning
HOOMD-blue uses Git submodules. Clone with the --recursive
to clone the submodules.
Execute git submodule update --init
to fetch the submodules each time you switch branches
and the submodules show as modified.
Configure
Use CMake to configure a HOOMD-blue build in the given directory. Pass
-D<option-name>=<value>
to cmake
to set options on the command line. When modifying code,
you only need to repeat the build step to update your build - it will automatically reconfigure
as needed.
Tip
Use Ninja to perform incremental builds in less time:
$ cmake -B build/hoomd -S hoomd-blue -GNinja
Tip
Place your build directory in /tmp
or /scratch
for faster builds. CMake performs
out-of-source builds, so the build directory can be anywhere on the filesystem.
Tip
Pass the following options to cmake
to optimize the build for your processor:
-DCMAKE_CXX_FLAGS=-march=native -DCMAKE_C_FLAGS=-march=native
.
Important
When using a virtual environment, activate the environment and set the cmake prefix path
before running CMake: $ export CMAKE_PREFIX_PATH=<path-to-environment>
.
HOOMD-blue’s cmake configuration accepts a number of options.
Options that find libraries and executables only take effect on a clean invocation of CMake. To set
these options, first remove CMakeCache.txt
from the build directory and then run cmake
with
these options on the command line.
PYTHON_EXECUTABLE
- Specify whichpython
to build against. Example:/usr/bin/python3
.Default:
python3.X
detected on$PATH
.
CMAKE_CUDA_COMPILER
- Specify whichnvcc
orhipcc
to build with.Default: location of
nvcc
detected on$PATH
.
MPI_HOME
(env var) - Specify the location where MPI is installed.Default: location of
mpicc
detected on the$PATH
.
<package-name>_ROOT
- Specify the location of a package.Default: Found on the CMake search path.
Other option changes take effect at any time:
BUILD_HPMC
- When enabled, build thehoomd.hpmc
module (default:on
).BUILD_MD
- When enabled, build thehoomd.md
module (default:on
).BUILD_METAL
- When enabled, build thehoomd.metal
module (default:on
).BUILD_TESTING
- When enabled, build unit tests (default:on
).CMAKE_BUILD_TYPE
- Sets the build type (case sensitive) Options:Debug
- Compiles debug information into the library and executables. Enables asserts to check for programming mistakes. HOOMD-blue will run slow when compiled inDebug
mode, but problems are easier to identify.RelWithDebInfo
- Compiles with optimizations and debug symbols.Release
- (default) All compiler optimizations are enabled and asserts are removed. Recommended for production builds.
CMAKE_INSTALL_PREFIX
- Directory to install HOOMD-blue. Defaults to the root path of the found Python executable.ENABLE_LLVM
- Enable run time code generation with LLVM.ENABLE_GPU
- When enabled, compiled GPU accelerated computations (default:off
).HOOMD_GPU_PLATFORM
- Choose eitherCUDA
orHIP
as a GPU backend (default:CUDA
).SINGLE_PRECISION
- Controls precision (default:off
).When set to
on
, all calculations are performed in single precision.When set to
off
, all calculations are performed in double precision.
ENABLE_HPMC_MIXED_PRECISION
- Controls mixed precision in thehpmc
component. When on, single precision is forced in expensive shape overlap checks.ENABLE_MPI
- Enable multi-processor/GPU simulations using MPI.When set to
on
, multi-processor/multi-GPU simulations are supported.When set to
off
(the default), always run in single-processor/single-GPU mode.
ENABLE_MPI_CUDA
- Enable CUDA-aware MPI library support.Requires a MPI library with CUDA support to be installed.
When set to
on
, HOOMD-blue will make use of the capability of the MPI library to accelerate CUDA-buffer transfers.When set to
off
, standard MPI calls will be used.
ENABLE_TBB
- Enable support for Intel’s Threading Building Blocks (TBB).When set to
on
, HOOMD-blue will use TBB to speed up calculations in some classes on multiple CPU cores.
PYTHON_SITE_INSTALL_DIR
- Directory to installhoomd
to relative toCMAKE_INSTALL_PREFIX
. Defaults to thesite-packages
directory used by the found Python executable.
These options control CUDA compilation via nvcc
:
CUDA_ARCH_LIST
- A semicolon-separated list of GPU architectures to compile.
Build the package
The command cmake --build build/hoomd
will build the HOOMD-blue Python package in the given
build directory. After the build completes, the build directory will contain a functioning Python
package.
Install the package
The command cmake --install build/hoomd
installs the given HOOMD-blue build to
${CMAKE_INSTALL_PREFIX}/${PYTHON_SITE_INSTALL_DIR}
. CMake autodetects these paths, but you can
set them manually in CMake.
Build the documentation
Run Sphinx to build the documentation with the command
sphinx-build -b html hoomd-blue/sphinx-doc build/hoomd-documentation
. Open the file
build/hoomd-documentation/index.html
in your web browser to view the documentation.
Tip
When iteratively modifying the documentation, the sphinx options -a -n -W -T --keep-going
are helpful to produce docs with consistent links in the side panel and to see more useful error
messages:
$ sphinx-build -a -n -W -T --keep-going -b html \
hoomd-blue/sphinx-doc build/hoomd-documentation
Migrating to HOOMD v3
HOOMD v3 introduces many breaking changes for both users and developers in order to provide a cleaner Python interface, enable new functionalities, and move away from unsupported tools. This guide highlights those changes.
Overview of API changes
HOOMD v3 introduces a completely new API. All classes have been renamed to match PEP8 naming guidelines and have new or renamed parameters, methods, and properties. See the tutorials and the Python module documentation for full class-level details.
Here is a module level overview of features that have been moved or removed:
v2 module, class, or method |
Replaced with |
---|---|
|
|
|
Removed. Use Python standard libraries for timing. |
|
Removed. See Citing HOOMD-blue. |
|
|
|
|
|
|
|
|
|
|
|
|
|
Removed. Use an external tool. |
|
|
|
Removed. Use Python standard libraries for option parsing. |
|
Some classes have been moved to |
|
Enable GPU profiling with |
|
|
|
|
|
|
|
|
|
|
|
Removed. This is not needed. |
|
|
|
Removed. |
|
|
|
|
|
Removed functionality
HOOMD v3 removes old APIs, unused functionality, and features better served by other codes:
Feature |
Replace with |
---|---|
Python 2.7 |
Python >= 3.6 |
Compute < 6.0 GPUs |
Compute >= 6.0 GPUs |
|
|
|
Parameters and type parameters accessed by properties. |
|
|
|
No longer needed. |
hoomd.deprecated
:
Feature |
Replace with |
---|---|
|
Offline analysis: e.g. Freud’s msd module. |
|
|
|
|
|
|
|
|
|
Feature |
Replace with |
---|---|
|
no longer needed |
|
|
|
n/a |
|
no longer needed |
|
no longer needed |
|
no longer needed |
|
no longer needed |
|
set |
Feature |
Replace with |
---|---|
|
Pass group to integration method. |
|
n/a |
|
Per-type |
|
hoomd.cgcmm
:
Feature |
Replace with |
---|---|
|
no longer needed |
|
no longer needed |
hoomd.dem
:
Feature |
Replace with |
---|---|
DEM pair potentials |
ALJ pair potential in |
Not yet ported
The following v2 functionalities have not yet been ported to the v3 API. They may be added in a future 3.x release:
HPMC box volume move size tuner.
These contributed functionalities rely on the community for support. Please contact the developers if you have an interest in porting these in a future release:
hoomd.hdf5
hoomd.metal
hoomd.mpcd
Compiling
CMake 3.8 or newer is required to build HOOMD v3.0.
To compile with GPU support, use the option
ENABLE_GPU=ON
.UPDATE_SUBMODULES
no longer exists. Users and developers should usegit clone --recursive
,git submodule update
andgit submodule sync
as appropriate.COPY_HEADERS
no longer exists. HOOMD will pull headers from the source directory when needed.CMAKE_INSTALL_PREFIX
is set to the Pythonsite-packages
directory (if not explicitly set by the user).cereal, eigen, and pybind11 headers must be provided to build HOOMD. See Installing binaries for details.
BUILD_JIT
is replaced withENABLE_LLVM
.
Components
HOOMD now uses native CUDA support in CMake. Use
CMAKE_CUDA_COMPILER
to specify a specificnvcc
orhipcc
. Plugins will require updates toCMakeLists.txt
to compile.cu
files.Remove
CUDA_COMPILE
.Pass
.cu
sources directly topybind11_add_module
.Add
NVCC
as a compile definition to.cu
sources.
External components require additional updates to work with v3. See
example_plugin
for details:Remove
FindHOOMD.cmake
.Replace
include(FindHOOMD.cmake)
withfind_package(HOOMD 3.Y REQUIRED)
(where 3.Y is the minor version this plugin is compatible with).Always force set
CMAKE_INSTALL_PREFIX
to${HOOMD_INSTALL_PREFIX}
.Replace
PYTHON_MODULE_BASE_DIR
withPYTHON_SITE_INSTALL_DIR
.Replace all
target_link_libraries
andset_target_properties
withtarget_link_libraries(_${COMPONENT_NAME} PUBLIC HOOMD::_hoomd)
(can linkHOOMD::_md
,HOOMD::_hpmc
, etc. if necessary).
Numerous C++ class APIs have changed, been removed, or renamed. Review the header files to see new class signatures. These changes may require you to update your component accordingly. Some of the more notable changes include:
Variant
has been completely rewritten.Trigger
replaces periodic and variable period scheduling.NeighborList
has aaddRCutMatrix
method clients must use to specify the maximum cutoff radii per type pair.timestep
is now of typeuint64_t
.Saru
has been removed. UseRandomGenerator
.RandomGenerator
is now constructed with aSeed
andCounter
object that support 64-bit timesteps.m_seed
is no longer present in individual operation objects. Use the global seed provided bySystemDefinition
.The HPMC integrators have been heavily refactored.
HPMC GPU kernels are now instantiated by template .cu files that are generated by CMake at configure time.
ParticleGroup
instances are now constructed from immutable, reusable, and user-customizableParticleFilter
instances.All GPU code is now written with HIP to support NVIDIA and AMD GPUs.
ActiveForceCompute
always uses particle orientation in combination with per-type active forces and torques.getProvidedLogQuantities
andgetLogQuantities
have been removed. Provide loggable properties instead.Removed the Sphere, Ellipsoid, and oneD constraints. Replaced with the more general RATTLE integration methods and Manifold classes.
Removed the Enforce2D and TempRescale Updaters. Enforce2D is not needed for 2D simulations, and TempRescale has been replaced by
thermalize_
methods.Removed Doxygen configuration scripts. View the document for classes in the source files.
Particle types may no longer be added after a Simulation is initialized. Classes no longer need to subscribe to the types added signal and reallocate data structures when the number of types changes.
Change Log
v3.x
v3.7.0 (2022-11-29)
Added
Neighborlist.r_cut
sets the base cutoff radius for neighbor search - for use when the neighbor list is used for analysis or custom Python code.Neighborlist.cpu_local_nlist_arrays
provides zero-copy access to the computed neighbor list.Neighborlist.gpu_local_nlist_arrays
provides zero-copy access to the computed neighbor list.Neighborlist.local_pair_list
provides the rank local pair list by index.Neighborlist.pair_list
provides the global pair list by tag on rank 0.hoomd.md.dihedral.Periodic
- a new name for the previousHarmonic
potential.default_gamma
anddefault_gamma_r
arguments to thehoomd.md.methods
:Brownian
,Langevin
, andOverdampedViscous
.reservoir_energy
loggable inhoomd.md.methods.Langevin
.hoomd.md.force.Constant
applies constant forces and torques to particles.
Changed
[plugin developers] Refactored the
LocalDataAccess
C++ classes to add flexibility.
Fixed
hoomd.hpmc.nec
integrators compute non-infinite virial pressures for 2D simulations.Raise an exception when attempting to get the shape specification of shapes with 0 elements.
Box conversion error message now names
hoomd.Box
.
Deprecated
hoomd.md.dihedral.Harmonic
- use the functionally equivalenthoomd.md.dihedral.Periodic
.charges
key inhoomd.md.constrain.Rigid.body
.diameters
key inhoomd.md.constrain.Rigid.body
.
v3.6.0 (2022-10-25)
Changed
In
hoomd.md.pair.aniso.ALJ
,shape.rounding_radii
now defaults to (0.0, 0.0, 0.0).Revise
hoomd.md.pair.aniso.ALJ
documentation.hoomd.md.force.Force
instances can now be added to theOperations
list allowing users to compute force, torque, energy, and virials of forces that are not included in the dynamics of the system.[developers]: Removed internal methods
_remove
and_add
from the data model.
Fixed
Increase the performance of
md.pair.Table
on the CPU.Improve accuracy of
hoomd.hpmc.update.BoxMC
when used with patch potentials.Provide an accurate warning message when creating the state with many bond/angle/… types.
Add missing documentation for
hoomd.md.methods.Berendsen
.CVE-2007-4559
v3.5.0 (2022-09-14)
Added
Example plugin that demonstrates how to add a MD pair potential.
Support a large number of particle and bond types (subject to available GPU memory and user patience) for the
Cell
neighbor list, MD pair potentials, MD bond potentials, Brownian, and Langevin integration methods.
Changed
Raise an error when initializing with duplicate types.
hpmc.compute.SDF
now computes pressures of systems with patch interactions.Raise descriptive error messages when the shared memory request exceeds that available on the GPU.
Fixed
Include all
Neighborlist
attributes in the documentation.Memory allocation errors in C++ now result in
MemoryError
exceptions in Python.Add missing
Autotuned.h
header file.External components build correctly when
ENABLE_MPI=on
orENABLE_GPU=on
.Type parameter validation when items contain
numpy.ndarray
elements.Compile with CUDA 12.0.
Deprecated
Device.memory_traceback
attribute. This attribute has no effect.
v3.4.0 (2022-08-15)
Added
The new HOOMD-blue logo is now available in the documentation.
hoomd.md.methods.DisplacementCapped
class for relaxing configurations with overlaps.hoomd.md.methods.rattle.DisplacementCapped
class for relaxing configurations with overlaps.hoomd.device.Device.notice
- print user-defined messages to the configured message output stream.Tutorial: Modelling Rigid Bodies.
AutotunedObject
class that provides an interface to read and write tuned kernel parameters, query whether tuning is complete, and start tuning again at the object level.is_tuning_complete
method toOperations
. Check whether kernel parameter tuning is complete for all operations.tune_kernel_parameters
methods toOperations
and many other classes. Start tuning kernel parameters in all operations.hoomd.md.HalfStepHook
- extensible hook class called between step 1 and 2 of MD integration.hoomd.md.Integrator.half_step_hook
- property to get/set the half step hook.
Fixed
Active forces on manifolds now attach to the
Simulation
correctly.hoomd.update.FilterUpdater
now acceptshoomd.filter.CustomFilter
subclasses.Correct error message is given when a sequence like parameter is not given to a type parameter.
Fix non-axis-aligned Cylinder walls in MD.
hoomd.md.constrain.Constraint
now hashoomd.md.force.Force
as a base class.Provide a warning instead of an error when passing an out of range seed to the
Simulation
constructor.Compile with current versions of HIP and ROCm.
Compilation errors with CUDA >=11.8.
v3.3.0 (2022-07-08)
Added
A decorator that modifies the namespace of operation and custom action classes
hoomd.logging.modify_namespace
.Tuner for the neighbor list buffer size
hoomd.md.tune.NeighborListBuffer
.Solver infrastructure for optimization problems.
Simulation.initial_timestep
: the timestep on which the last call torun
started.variant_like
,trigger_like
, andfilter_like
typing objects for documentation.
Changed
Removed
"__main__"
from some user custom action logging namespaces.
Fixed
Improve documentation.
Non-default loggables can now be explicitly specified with
Logger.add
.Iteration of
Logger
instances.The logging category of
hoomd.md.Integrate.linear_momentum
v3.2.0 (2022-05-18)
Added
hoomd.md.nlist.Neighborlist.num_builds
property - The number of neighbor list builds since the last call toSimulation.run
.hoomd.md.nlist.Cell.dimensions
property - The dimensions of the cell list.hoomd.md.nlist.Cell.allocated_particles_per_cell
property - The number of particle slots allocated per cell.hoomd.mesh.Mesh
- Triangular mesh data structure.hoomd.md.mesh.bond
- Bond potentials on mesh edges.Support gcc 12.
Support clang 14.
Set
ENABLE_LLVM=on
in conda binary builds.
Fixed
Clarify documentation.
Box.dimension
reports the correct value when reading in 2D boxes from GSD files generated in HOOMD v2.Improve performance of run time compiled HPMC potentials on the CPU.
Pressing Ctrl-C or interrupting the kernel in Jupyter stops the run at the end of the current timestep.
v3.1.0 (2022-04-27)
Added
Support LLVM 13 when
ENABLE_LLVM=on
.hoomd.md.pair.LJGauss
- Lennard-Jones-Gaussian pair potential.hoomd.md.alchemy.methods.NVT
- Alchemical molecular dynamics integration method.hoomd.md.alchemy.pair.LJGauss
- Lennard-Jones-Gaussian pair potential with alchemical degrees of freedom.hoomd.hpmc.update.Shape
- Alchemical hard particle Monte Carlo through shape change moves.hoomd.hpmc.shape_move.Elastic
- Shape move with elastic potential energy penalty.hoomd.hpmc.shape_move.ShapeSpace
- Moves in a user defined shape space.hoomd.hpmc.shape_move.Vertex
- Translate shape vertices.
Changed
HPMC fugacity is now a per-type quantity.
Improved documentation.
[developers] Reduced the time needed for incremental builds.
[developers] Reduced memory needed to compile HOOMD.
Fixed
ALJ unit test passes in Debug builds.
Add quotes to conda-forge gpu package installation example.
hoomd.md.force.Custom
zeroes forces, torques, energies, and virials before callingset_forces
.Point tarball download link to https://github.com/glotzerlab/hoomd-blue/releases.
Deprecated
hoomd.md.pair.aniso.ALJ.mode
- parameter has no effect.hoomd.md.pair.aniso.Dipole.mode
- parameter has no effect.
v3.0.1 (2022-04-08)
Fixed
Display status of
trunk-patch
branch in the GitHub actions badge.Add
EvaluatorPairTable.h
to installation directory.Add
hoomd.filter.Rigid
to the documentation.Prevent
TypeError: 'bool' object is not iterable
errors when comparingTag
filters with different lengths arrays.Simulation.tps
andSimulation.walltime
update every step of the run.
v3.0.0 (2022-03-22)
Overview
HOOMD-blue v3.0.0 is the first production release with the new API that has been developed and implemented over more than 2 years. Those still using v2.x will need to make changes to their scripts to use v3. See the Migrating to HOOMD v3 page for an overview and individual class and method documentation for more information. To summarize, the new API is object oriented, allows HOOMD-blue to work effectively as a Python package, and provides more hooks for Python code to directly interface with the simulation.
New features in v3 since v2.9.7:
Zero-copy data access through numpy and cupy.
Triggers determine what timesteps operations execute on.
User-defined operations, triggers, particle filters, variants, and forces.
Logging subsystem supports array quantities.
Implicit depletants for 2D shapes in HPMC.
Harmonically mapped averaging for MD thermodynamic quantities of crystals.
TWF and OPP pair potentials.
Tether bond potential.
Manifold constraints for MD integration methods (using RATTLE) and active forces.
Document code architecture in
ARCHITECTURE.md
.Overdamped viscous MD integration method.
User-defined pair potentials work with HPMC on the GPU.
Long range tail correction for Lennard-Jones potential.
Anisotropic Lennard-Jones-like pair potential for polyhedra and ellipsoids.
Newtownian event chain Monte Carlo for spheres and convex polyhedra.
See the full change log below for all v3 beta releases.
Changes from v3.0.0-beta.14:
Added
hoomd.hpmc.tune.BoxMCMoveSize
- TuneBoxMC
move sizes to meet target acceptance ratios.hoomd.hpmc.nec.integrate.Sphere
- Newtonian event chain Monte Carlo for hard spheres.hoomd.hpmc.nec.integrate.ConvexPolyhedron
- Newtonian event chain Monte Carlo for hard convex polyhedra.hoomd.hpmc.nec.tune.ChainTime
- Tune chain times in newtonian event chain Monte Carlo method.
Changed
Improve documentation.
[breaking] Renamed the
hoomd.md.bond.Table
energy parameter fromV
toU
.[breaking] Renamed the
hoomd.md.pair.Table
energy parameter fromV
toU
.[breaking] Renamed the
hoomd.md.angle.Table
energy parameter fromV
toU
.[breaking] Renamed the
hoomd.md.dihedral.Table
energy parameter fromV
toU
.[breaking] Renamed
hoomd.md.nlist.Nlist
tohoomd.md.nlist.NeighborList
.[developer]
Updater
andAnalyzer
in C++ have am_trigger
member now.[developer]
_TriggeredOperation
has been moved toTriggeredOperation
and custom trigger setting and getting logic removed.
Fixed
FIRE.converged
may be queried before callingSimulation.run
.Bug where using
__iadd__
to certain attributes would fail with an exception.Bug where
hoomd.md.pair.LJ.additional_energy
isNaN
whentail_correction
is enabled and some pairs haver_cut=0
.Compile error with CUDA 11.7.
Compile errors on native ubuntu 20.04 systems.
Compile errors with
ENABLE_GPU=on
andclang
as a host compiler.
Removed
[developers] Removed
IntegratorData
class. It is replaced by structs that are defined in the integrator classes.get_ordered_vertices
fromhoomd.md.pair.aniso.ALJ
.Removed optional coxeter dependency.
The
limit
parameter fromhoomd.md.methods.NVE
.The
limit
parameter fromhoomd.md.methods.rattle.NVE
.The
diameter_shift
parameter fromhoomd.md.nlist.NeighborList
.The
max_diameter
parameter fromhoomd.md.nlist.NeighborList
.
v3.0.0-beta.14 (2022-02-18)
Added
hoomd.hpmc.external.field.Harmonic
- harmonic potential of particles to specific sites in the simulation box and orientations.Support
cereal
1.3.1Guide on how to model molecular systems.
version.floating_point_precision
- Floating point width in bits for the particle properties and local calculations.hoomd.md.pair.LJ.tail_correction
- Option to enable the isotropic integrated long range tail correction.hoomd.md.Integrator.linear_momentum
- Compute the total system linear momentum. Loggable.hoomd.md.bond.Table
- Tabulated bond potential.hoomd.md.angle.Table
- Tabulated angle potential.hoomd.md.dihedral.Table
- Tabulated dihedral potential.hoomd.md.improper.Harmonic
- Compute the harmonic improper potential and forces.Tutorial on Organizing and executing simulations.
C++ and build system overview in
ARCHITECTURE.md
.hoomd.hpmc.external.wall
- Overlap checks between particles and wall surfaces.hoomd.md.pair.ansio.ALJ
- an anisotropic Lennard-Jones-like pair potential for polyhedra and ellipsoids.New optional dependency:
coxeter
, needed for someALJ
methods.
Changed
Support variant translational and rotational spring constants in
hoomd.hpmc.external.field.Harmonic
.[breaking] Renamed
hoomd.md.angle.Cosinesq
tohoomd.md.angle.CosineSquared
.[breaking]
hoomd.Box
no longer has amatrix
property useto_matrix
andfrom_matrix
.
Fixed
Compilation errors on FreeBSD.
TypeError
when instantiating special pair forces.Inconsistent state when using the
walls
setter of ahoomd.md.external.wall.WallPotential
.
Removed
[breaking] Removed
hoomd.md.pair.SLJ
potential and wall. Usehoomd.md.pair.ExpandedLJ
.[breaking]
hoomd.Box.lattice_vectors
property no longer exists.
v3.0.0-beta.13 (2022-01-18)
Added
md.pair.ExpandedLJ
- A Lennard-Jones potential wherer
is replaced withr-delta
.Support nested modification of operation parameters.
wall
- Define wall surfaces in the simulation box.md.external.wall
- Pair interactions between particles and wall surfaces.Communicator.walltime
- the wall clock time since creating theCommunicator
.md.force.Custom
- user defined forces in Python.
Changed
Call
update_group_dof
implicitly inset_snapshot
, when changing integrators or integration methods, and on steps whereFilterUpdater
acts on the system.[breaking]
update_group_dof
defers counting the degrees of freedom until the next timestep or the next call toSimulation.run
.[breaking] Renamed
md.bond.FENE
tomd.bond.FENEWCA
.md.bond.FENEWCA
takes a user provideddelta
parameter and ignores the particle diameters.[breaking]
md.pair.DLVO
takes user provideda1
anda2
parameters and ignores the particle diameters.Removed invalid linker options when using gcc on Apple systems.
Removed the
r_on
attribute anddefault_r_on
constructor argument from pair potentials that do not use it.Building from source requires a C++17 compatible compiler.
Fixed
Compile error with
Apple clang clang-1300.0.29.30
.Incorrect OPLS dihedral forces when compiled with
Apple clang clang-1300.0.29.30
.
Deprecated
md.pair.SLJ
- Replaced withmd.pair.ExpandedLJ
.
Removed
Leftover
state
logging category.
v3.0.0-beta.12 (2021-12-14)
Added
Support simulations with arbitrarily large or small scales (within the limits of the floating point representation).
Changed
Report full error details in the exception message.
Improved documentation.
[breaking]:
buffer
is now a required argument when constructing a neighbor list.[breaking]:
force_tol
,angmom_tol
, andenergy_tol
are now required arguments tomd.minimize.FIRE
Fixed
Allow neighbor lists to store more than
2**32-1
total neighbors.Return expected parameter values instead of
NaN
when potential parameters are set to 0.
v3.0.0-beta.11 (2021-11-18)
Added
Support Python 3.10.
Support clang 13.
Changed
[developers] Place all all HOOMD C++ classes in the
hoomd
and nested namespaces.[developers] Use official pre-commit clang-format repository.
v3.0.0-beta.10 (2021-10-25)
Added
md.minimize.FIRE
- MD integrator that minimizes the system’s potential energy.Include example AKMA and MD unit conversion factors in the documentation.
BUILD_LLVM
CMake option (defaults off) to enable features that require LLVM.hpmc.pair.user.CPPPotential
- user-defined pair potentials between particles in HPMC.hpmc.pair.user.CPPPotentialUnion
- user-defined site-site pair potentials between shapes in HPMC.hpmc.external.user.CPPExternalPotential
- user-defined external potentials in HPMC.Support user-defined pair potentials in HPMC on the GPU.
Changed
Improved documentation.
Improved error messages when setting operation parameters.
Noted some dependencies of dependencies for building documentation.
[developers] Removed
m_comm
from most classes. Usem_sysdef->isDomainDecomposed()
instead.Add support for LLVM 12
ENABLE_LLVM=on
requires the clang development libraries.[breaking] Renamed the Integrator attribute
aniso
tointegrate_rotational_dof
and removed the'auto'
option. Users must now explicitly chooseintegrate_rotational_dof=True
to integrate the rotational degrees of freedom in the system.
Fixed
Calling
Operations.__len__
no longer raises aRecursionError
.RATTLE integration methods execute on the GPU.
Include
EvaluatorPairDLVO.h
in the installation for plugins.Bug in setting zero sized
ManagedArrays
.Kernel launch errors when one process uses different GPU devices.
Race condition that lead to incorrect simulations with
md.pair.Table
.Bug where some particle filers would have 0 rotational degrees of freedom.
Removed
The
BUILD_JIT
CMake option.Support for LLVM <= 9.
v3.0.0-beta.9 (2021-09-08)
Added
Communicator.num_partitions
- the number of partitions in the communicator.domain_decomposition
argument toState
factory methods - set the parameters of the MPI domain decompositionState.domain_decomposition
- number of domains in the x, y, and z directions in the domain decomposition.State.domain_decomposition_split_fractions
- the fractional positions of the split planes in the domain decomposition.hoomd.update.FilterUpdater
- an updater that evaluates the particles associated with ahoomd.filter.ParticleFilter
instance.hoomd.update.RemoveDrift
- Remove the average drift from a system restrained on a lattice.Developer documentation for HOOMD-blue’s Python object data model in
ARCHITECTURE.md
.Autocomplete support for interactive notebooks.
hoomd.md.methods.OverdampedViscous
- Overdamped integrator with a drag force but no random force .MutabilityError
exception when setting read-only operation parameters.
Changed
Improved documentation.
[breaking] Moved
manifold_constrant
to separate integration method classes inhoomd.md.methods.rattle
.[breaking] Moved
trigger
to first argument position inhoomd.update.BoxResize
,hoomd.write.DCD
, andhoomd.write.GSD
.[breaking]
hoomd.data.LocalSnapshot
particle data API now matchesSnapshot
. Changes to angular momentum, moment of intertia, and rigid body id attributes.hoomd.write.CustomWriter
now exposes action through thewriter
attribute.[breaking] Active force rotational diffusion is managed by
hoomd.md.update.ActiveRotationalDiffusion
.
Fixed
TypeParameter
can set multiple parameters after callinghoomd.Simulation.run
.tune.LoadBalancer
can be used in a simulation.hoomd.md.pair.Pair
r_cut
type parameter can be set to 0.MD integration methods can be removed from the integrator’s method list.
Neighborlist exclusions update when the number of bonds change.
Errors related to equality checks between HOOMD operations.
The integrator can be removed from a simulation after running.
hoomd.md.constrain.Rigid.create_bodies
method correctly assigns the body attribute.Setting rigid attribute of a MD integrator to
None
is allowed.
Deprecated
Removed
Snapshot.exists
- usesnapshot.communicator.rank == 0
State.snapshot
- useget_snapshot
andset_snapshot
The
State.box
property setter - useState.set_box
v3.0.0-beta.8 (2021-08-03)
Added
Consistent documentation of parameter dimensions and units reference documentation.
md.update.ReversePerturbationFlow
- implementation ofmueller_plathe_flow
from v2.md.pair.ExpandedMie
- Mie potential wherer
is replaced withr - delta
.md.pair.Table
- Pair potential evaluated using the given tabulated values.md.constrain.Distance
- fix distances between pairs of particles.hpmc.compute.SDF
- compute the pressure of convex hard particle systems.Snapshot.wrap()
- wrap snapshot particles back into the box.Support gcc11.
md.bond.Tether
- A bond with minimum and maximum lengths.State.get_snapshot
andState.set_snapshot
- methods to access the global snapshot.State.set_box
set a new simulation box without modifying particle properties.md.long_range.pppm.make_pppm_coulomb_forces
- Long range electrostatics evaluated by PPPM.md.long_range.pppm.Coulomb
- The reciprocal part of PPPM electrostatics.md.force.ActiveOnManifold
- Active forces constrained to manifolds.
Changed
Improved documentation.
[breaking] Constructor arguments that set a default value per type or pair of types now have default in their name (e.g.
r_cut
todefault_r_cut
for pair potentials anda
todefault_a
for HPMC integrators).[developer] Support git worktree checkouts.
[breaking] Rename
nrank
toranks_per_partition
inCommunicator
.rowan is now an optional dependency when running unit tests.
Snapshot
andBox
methods that make in-place modifications return the object.
Fixed
Bug where
ThermdynamicQuantities.volume
returned 0 in 2D simulations.Update neighbor list exclusions after the number of particles changes.
Test failures with the CMake option
BUILD_MD=off
.write.Table
can now display MD pressures.
Deprecated
State.snapshot
- useget_snapshot
andset_snapshot
.The ability to set boxes with the property
State.box
- useset_box
.
Removed
[breaking]
Simulation.write_debug_data
.[breaking]
shared_msg_file
option toDevice
.msg_file
now has the same behavior asshared_msg_file
.[developers] C++ and Python implementations of
constraint_ellipsoid
, fromhoomd.md.update
andsphere
andoneD
fromhoomd.md.constrain
.[developers] Doxygen configuration files.
v3.0.0-beta.7 (2021-06-16)
Added
md.constrain.Rigid
- Rigid body constraints.dem_built
,hpmc_built
,md_built
, andmpcd_built
tohoomd.version
- flags that indicate when optional submodules have been built.GPU.compute_capability
property.[developers] pre-commit enforced style guidelines for the codebase.
[developers] Validation tests for MD Lennard-Jones simulations.
[developers] Unit tests for bond, angle, and dihedral potentials.
Changed
Improved documentation on compiling HOOMD.
Operations raise a
DataAccessError
when accessing properties that are not available becauseSimulation.run
has not been called.TypeConversionError
is now in thehoomd.error
package.from_gsd_snapshot
only accesses the GSD snapshot on MPI rank 0.
Fixed
Some broken references in the documentation.
Missing documentation for
md.pair.TWF
.Inconsistent documentation in
md.pair
.Correctly identify GPUs by ID in
GPU.devices
.Don’t initialize contexts on extra GPUs on MPI ranks.
Support 2D inputs in
from_gsd_snapshot
.
Deprecated
Snapshot.exists
- useSnapshot.communicator.rank == 0
instead.
Removed
[developers] C++ implementations of
rescale_temp
andenforce2d
.[developers] Unused methods of
Integrator
.
v3.0.0-beta.6 (2021-05-17)
Added
md.pair.LJ0804
- 8,4 Lennard-Jones pair potential.md.nlist.Stencil
- Stencil algorithm to generate neighbor lists.md.nlist.Tree
- BVH algorithm to generate neighbor lists.hoomd.md.Force
,hoomd.md.Operation
, andhoomd.md.Operations
objects are now picklable.Manifold constraints using RATTLE with
md.methods.NVE
,md.methods.Langevin
andmd.methods.Brownian
- Supporting sphere, ellipsoid, plane, cylinder, gyroid, diamond, and primitive manifolds.md.compute.HarmonicAveragedThermodynamicQuantities
- More accurate thermodynamic quantities for crystals
Changed
Raise an exception when initializing systems with invalid particle type ids.
Fixed
Setting the operations attribute in
Simulation
objects in specific circumstances.Misc documentation updates.
'sim' is not defined
error when usingmd.dihedral
potentials.
Removed
C++ implemtation of v2 logging infrastructure.
v3.0.0-beta.5 (2021-03-23)
Added
filter
parameter toupdate.BoxResize
- AParticleFilter
that identifies the particles to scale with the box.Simulation.seed
- one place to set random number seeds for all operations.net_force
,net_torque
, andnet_energy
per-particle arrays in local snapshots.Support
hpmc.update.Clusters
on the GPU.hpmc.update.MuVT
- Gibbs ensemble simulations with HPMC.md.update.ZeroMomentum
- Remove linear momentum from the system.hpmc.compute.FreeVolume
- Compute free volume available to test particles.Custom action tutorials.
Changed
[breaking] Removed the parameter
scale_particles
inupdate.BoxResize
[internal] Modified signature of
data.typeconverter.OnlyTypes
Remove use of deprecated numpy APIs.
Added more details to the migration guide.
Support timestep values in the range [0,2**64-1].
[breaking] Removed seed argument from
State.thermalize_particle_momenta
[breaking] Removed seed argument from
md.methods.NVT.thermalize_thermostat_dof
[breaking] Removed seed argument from
md.methods.NPT.thermalize_thermostat_and_barostat_dof
[breaking] Removed seed argument from
md.methods.NPH.thermalize_barostat_dof
[breaking] Removed seed argument from
md.methods.Langevin
[breaking] Removed seed argument from
md.methods.Brownian
[breaking] Removed seed argument from
md.force.Active
[breaking] Removed seed argument from
md.pair.DPD
[breaking] Removed seed argument from
md.pair.DPDLJ
[breaking] Removed seed argument from all HPMC integrators.
[breaking] Removed seed argument from
hpmc.update.Clusters
[breaking] Removed seed argument from
hpmc.update.BoxMC
[breaking] Removed seed argument from
hpmc.update.QuickCompress
Use latest version of getar library.
Improve documentation.
Improve performance of
md.pair.Mie
.[breaking]
hpmc.update.Clusters
re-implemented with a rejection free, but not ergodic, algorithm for anisotropic particles. The new algorithm does not run in parallel over MPI ranks.[breaking] HPMC depletion algorithm rewritten.
[breaking, temporary] HPMC depletant fugacity is now set for type pairs. This change will be reverted in a future release.
Tutorials require fresnel 0.13.
Support TBB 2021.
Fixed
Install
ParticleFilter
header files for external plugins.md.force.Active
keeps floating point values set foractive_force
andactive_torque
.create_state_from_snapshot
acceptsgsd.hoomd.Snapshot
objects without error.HOOMD compiles on Apple silicon macOS systems.
Memory leak in PPPM force compute.
Segmentation fault that occurred when dumping GSD shapes for spheropolygons and spheropolyhedra with 0 vertices.
Incorrect MD neighbor lists in MPI simulations with more than 1 rank.
md.bond.FENE
accepts parameters.
Removed
Testing with CUDA 9, GCC 4.8, GCC 5.x, GCC 6.x, clang 5
v3.0.0-beta.4 (2021-02-16)
Added
hoomd.write.DCD
- DCD trajectory writer.hoomd.md.many_body
- RevCross, SquareDensity, and Tersoff triplet potentials.hoomd.md.methods.Berendsen
- Berendsen integration method.hoomd.md.methods.NPH
- Constant pressure constant enthalpy integration method.hoomd.md.pair.TWF
- Potential for modeling globular proteins by Pieter Rein ten Wolde and Daan Frenkel.Custom particle filters in Python via
hoomd.filter.CustomFilter
.
Changed
Documentation improvements.
Fixed
Correctly determine the maximum
r_cut
in simulations with more than one pair potential and more than one type.
v3.0.0-beta.3 (2021-01-11)
Added
hoomd.variant.Variant
objects are picklable.hoomd.filter.ParticleFilter
objects are picklable.hoomd.trigger.Trigger
objects are picklable.hoomd.Snapshot.from_gsd_snapshot
- Convert GSD snapshots to HOOMD.hoomd.md.pair.aniso.GayBerne
- Uniaxial ellipsoid pair potential.hoomd.md.pair.aniso.Dipole
- Dipole pair potential.hoomd.md.pair.OPP
- Oscillating pair potential.
Changed
Improved compilation docs.
Box equality checking now returns
NotImplemented
for non-hoomd.Box
objects.Simulation.create_state_from_snapshot
now acceptsgsd.hoomd.Snapshot
objects.Attempting to run in a local snapshot context manager will now raise a
RuntimeError
.Attempting to set the state to a new snapshot in a local snapshot context manager will now raise a
RuntimeError
.
Fixed
hoomd.variant.Power
objects now have at_ramp
attribute as documented.Enable memory buffers larger than 2-4 GiB.
Correctly write large image flags to GSD files.
Support more than 26 default type names.
Correctly represent fractional degrees of freedom.
Compute the minimum image in double precision.
v3.0.0-beta.2 (2020-12-15)
Added
Support pybind11 2.6.0
Exclusive creation file mode for
write.GSD
.hpmc.update.BoxMC
.walltime
andfinal_timestep
loggable properties inSimulation
.Null
particle filter.Logging tutorial.
Changed
[breaking] Replace
write.GSD
argumentoverwrite
withmode
.[breaking] Rename
flags
tocategories
inLogger
hoomd.snapshot.ConfigurationData.dimensions
is not settable and is determined by the snapshot box. Ifbox.Lz == 0
, the dimensions are 2 otherwise 3.Building from source requires a C++14 compatible compiler.
Improved documentation.
hpmc.integrate.FacetedEllipsoid
’s shape specification now has a default origin of (0, 0, 0).Document loggable quantities in property docstrings.
Skip GPU tests when no GPU is present.
write.Table
writes integers with integer formatting.
Fixed
Simulation.run
now ends with aKeyboardInterrupt
exception when Jupyter interrupts the kernel.Logging the state of specific objects with nested attributes.
Broken relative RPATHs.
Add missing documentation for
version.version
Error when removing specific operations from a simulation’s operations attribute.
Find CUDA libraries on additional Linux distributions.
hpmc.update.Clusters
now works with all HPMC integrators.Simulation.timestep
reports the correct value when analyzers are called.Logger
names quantities with the documented namespace name.
v3.0.0-beta.1 (2020-10-15)
Overview
v3 has a completely new Python API. See the tutorials, migration guide and new API documentation learn about it. The API documentation serves as the complete list of all features currently implemented in v3.0.0-beta.1. Not all features in v2 have been ported in v3.0.0-beta.1. Future beta releases will add additional functionality.
Added
Zero-copy data access through numpy (CPU) and cupy (GPU).
User-defined operations in Python.
User-defined triggers determine what time steps operations execute on.
New logging subsystem supports array quantities and binary log files.
Implicit depletants are now supported by any hpmc integrator through
mc.set_fugacity('type', fugacity)
.Enable implicit depletants for two-dimensional shapes in hpmc.
jit.patch.user()
andjit.patch.user_union()
now support GPUs via NVRTC.Add harmonically mapped averaging.
Add Visual Studio Code workspace
Changed
The
run
method has minimal overheadAll loggable quantities are directly accessible as object properties.
Operation parameters are always synchronized.
Operations can be instantiated without a device or MPI communicator.
Writers write output for
step+1
at the bottom of therun
loop.HOOMD writes minimal output to stdout/stderr by default.
CMake >=3.9, cereal, eigen, and pybind11 are required to compile HOOMD.
Plugins must be updated to build against v3.
By default, HOOMD installs to the
site-packages
directory associated with thepython
executable given, which may be inside a virtual environment.Refactored CMake code.
git submodule update
no longer runs when during CMake configuration.Use
random123
library for implicit depletants in hpmc.HOOMD requires a GPU that supports concurrent managed memory access (Pascal or newer).
Bug fixes
Improved accuracy of DLVO potential on the GPU.
Improved performance of HPMC simulations on the CPU in non-cubic boxes.
Removed
HOOMD-blue no longer parses command line options.
Type swap moves in
hpmc.update.muvt()
are no longer supported (transfer_ratio
option tomuvt.set_params()
)The option
implicit=True
tohpmc.integrate.*
is no longer available (useset_fugacity
).static
parameter indump.gsd
util.quiet_status
andutil.unquiet_status
.deprecated.analyze.msd
.deprecated.dump.xml
.deprecated.dump.pos
.deprecated.init.read_xml
.deprecated.init.create_random
.deprecated.init.create_random_polymers
.hpmc
ignore_overlaps
parameter.hpmc
sphere_union::max_members
parameter.hpmc
convex_polyhedron_union
.hpmc
setup_pos_writer
method.hpmc
depletant_mode='circumsphere'
.hpmc
max_verts
parameter.hpmc
depletant_mode
parameter.hpmc
ntrial
parameter.hpmc
implicit
boolean parameter.group
parameter tomd.integrate.mode_minimize_fire
cgcmm.angle.cgcmm
cgcmm.pair.cgcmm
COPY_HEADERS
CMake option.Many other python modules have been removed or re-implemented with new names. See the migration guide and new API documentation for a complete list.
Support for NVIDIA GPUS with compute capability < 6.0.
v2.x
v2.9.7 (2021-08-03)
Bug fixes
Support CUDA 11.5. A bug in CUDA 11.4 may result in the error
__global__ function call is not configured
when running HOOMD.
v2.9.6 (2021-03-16)
Bug fixes
Support TBB 2021.
v2.9.5 (2021-03-15)
Bug fixes
Support macos-arm64.
Support TBB 2021.
Fix memory leak in PPPM.
v2.9.4 (2021-02-05)
Bug fixes
Support thrust 1.10
Support LLVM11
Fix Python syntax warnings
Fix compile errors with gcc 10
v2.9.3 (2020-08-05)
Bug fixes
Fix a compile error with CUDA 11
v2.9.2 (2020-06-26)
Bug fixes
Fix a bug where repeatedly using objects with
period=None
would use significant amounts of memory.Support CUDA 11.
Reccomend citing the 2020 Computational Materials Science paper 10.1016/j.commatsci.2019.109363.
v2.9.1 (2020-05-28)
Bug fixes
Fixed a minor bug where the variable period timestep would be off by one when the timestep got sufficiently large.
Updated collections API to hide
DeprecationWarning
.Fix scaling of cutoff in Gay-Berne potential to scale the current maximum distance based on the orientations of the particles, ensuring ellipsoidal energy isocontours.
Misc documentation fixes.
v2.9.0 (2020-02-03)
New features
General
Read and write GSD 2.0 files.
HOOMD >=2.9 can read and write GSD files created by HOOMD <= 2.8 or GSD 1.x. HOOMD <= 2.8 cannot read GSD files created by HOOMD >=2.9 or GSD >= 2.0.
OVITO >=3.0.0-dev652 reads GSD 2.0 files.
A future release of the
gsd-vmd
plugin will read GSD 2.0 files.
HPMC
User-settable parameters in
jit.patch
.2D system support in muVT updater.
Fix bug in HPMC where overlaps were not checked after adding new particle types.
MD
The performance of
nlist.tree
has been drastically improved for a variety of systems.
v2.8.2 (2019-12-20)
Bug fixes
Fix randomization of barostat and thermostat velocities with
randomize_velocities()
for non-unit temperatures.Improve MPCD documentation.
Fix uninitialized memory in some locations which could have led to unreproducible results with HPMC in MPI, in particular with
ALWAYS_USE_MANAGED_MEMORY=ON
.Fix calculation of cell widths in HPMC (GPU) and
nlist.cell()
with MPI.Fix potential memory-management issue in MPI for migrating MPCD particles and cell energy.
Fix bug where exclusions were sometimes ignored when
charge.pppm()
is the only potential using the neighbor list.Fix bug where exclusions were not accounted for properly in the
pppm_energy
log quantity.Fix a bug where MD simulations with MPI start off without a ghost layer, leading to crashes or dangerous builds shortly after
run()
.hpmc.update.remove_drift
now communicates particle positions after updating them.
v2.8.1 (2019-11-26)
Bug fixes
Fix a rare divide-by-zero in the
collide.srd
thermostat.Improve performance of first frame written by
dump.gsd
.Support Python 3.8.
Fix an error triggering migration of embedded particles for MPCD with MPI + GPU configurations.
v2.8.0 (2019-10-30)
New Features
MD:
hoomd.md.dihedral.harmonic
now accepts phase offsets,phi_0
, for CHARMM-style periodic dihedrals.Enable per-type shape information for anisotropic pair potentials that complements the existing pair parameters struct.
HPMC:
Enable the use of an array with adjustable parameters within the user defined pair potential.
Add muVT updater for 2D systems.
Bug fixes
Fix missing header in external plugin builds.
Enable
couple='none'
option tomd.integrate.npt()
when randomly initializing velocities.Documentation improvements.
Skip gsd shape unit test when required modules are not compiled.
Fix default particle properties when new particles are added to the system (e.g., via the muVT updater).
Fix
charge.pppm()
execution on multiple GPUs.Enable
with SimulationContext() as c
.Fix a bug for
mpcd.collide.at
with embedded particles, which may have given incorrect results or simulation crashes.
v2.7.0 (2019-10-01)
New features
General:
Allow components to use
Logger
at the C++ level.Drop support for python 2.7.
User-defined log quantities in
dump.gsd
.Add
hoomd.dump.gsd.dump_shape
to save particle shape information in GSD files.
HPMC:
Add
get_type_shapes
toellipsoid
.
MPCD:
mpcd.stream.slit_pore
allows for simulations through parallel-plate (lamellar) pores.mpcd.integrate
supports integration of MD (solute) particles with bounce-back rules in MPCD streaming geometries.
Bug fixes
hoomd.hdf5.log.query
works with matrix quantities.test_group_rigid.py
is run out of themd
module.Fix a bug in
md.integrate.langevin()
andmd.integrate.bd()
where on the GPU the value ofgamma
would be ignored.Fix documentation about interoperability between
md.mode_minimize_fire()
and MPI.Clarify
dump.gsd
documentation.Improve documentation of
lattice_field
andfrenkel_ladd_energy
classes.Clarify singularity image download documentation.
Correctly document the functional form of the Buckingham pair potential.
Correct typos in HPMC example snippets.
Support compilation in WSL.
v2.6.0 (2019-05-28)
New features
General:
Enable
HPMC
plugins.Fix plug-in builds when
ENABLE_TBB
orALWAYS_USE_MANAGED_MEMORY
CMake parameters are set.Remove support for compute 3.0 GPUs.
Report detailed CUDA errors on initialization.
Document upcoming feature removals and API changes.
MD:
Exclude neighbors that belong to the same floppy molecule.
Add fourier potential.
HPMC:
New shape class:
hpmc.integrate.faceted_ellipsoid_union()
.Store the orientable shape state.
MPCD:
mpcd.stream.slit
allows for simulations in parallel-plate channels. Users can implement other geometries as a plugin.MPCD supports virtual particle filling in bounded geometries through the
set_filler
method ofmpcd.stream
classes.mpcd.stream
includes an externalmpcd.force
acting on the MPCD particles. A block force, a constant force, and a sine force are implemented.
Bug fixes
Fix compile errors with LLVM 8 and
-DBUILD_JIT=on
.Allow simulations with 0 bonds to specify bond potentials.
Fix a problem where HOOMD could not be imported in
mpi4py
jobs.Validate snapshot input in
restore_snapshot
.Fix a bug where rigid body energy and pressure deviated on the first time step after
run()
.Fix a bug which could lead to invalid MPI simulations with
nlist.cell()
andnlist.stencil()
.
C++ API changes
Refactor handling of
MPI_Comm
inside libraryUse
random123
for random number generationCMake version 2.8.10.1 is now a minimum requirement for compiling from source
v2.5.2 (2019-04-30)
Bug fixes
Support LLVM 9 in
jit
Fix error when importing
jit
beforehpmc
HPMC integrators raise errors when
restore_state=True
and state information is missingSend messages to replaced
sys.stdout
andsys.stderr
streamsAdd
hpmc.update.clusters
to documentation indexFix a bug in the MPCD Gaussian random number generator that could lead to NaN values
Fix issue where an initially cubic box can become non-cubic with
integrate.npt()
andrandomize_velocities()
Fix illegal memory access in NeighborListGPU with
-DALWAYS_USE_MANAGED_MEMORY=ON
on single GPUsImprove
pair.table
performance with multi-GPU executionImprove
charge.pppm
performance with multi-GPU executionImprove rigid body performance with multi-GPU execution
Display correct cell list statistics with the
-DALWAYS_USE_MANAGED_MEMORY=ON
compile optionFix a sporadic data corruption / bus error issue when data structures are dynamically resized in simulations that use unified memory (multi-GPU, or with -DALWAYS_USE_MANAGED_MEMORY=ON compile time option)
Improve
integrate.nve
andintegrate.npt
performance with multi-GPU executionImprove some angular degrees of freedom integrators with multi-GPU execution
Improve rigid body pressure calculation performance with multi-GPU execution
v2.5.1 (2019-03-14)
Bug fixes
fix out-of-range memory access in
hpmc.integrate.convex_polyheron
Remove support for clang3.8 and 4.0
Documentation improvements
Fix a segfault when using
SLURM_LOCALID
v2.5.0 (2019-02-05)
New features
General:
Fix BondedGroupData and CommunicatorGPU compile errors in certain build configurations
MD:
Generalize
md.integrate.brownian
andmd.integrate.langevin
to support anisotropic friction coefficients for rotational Brownian motion.Improve NVLINK performance with rigid bodies
randomize_velocities
now chooses random values for the internal integrator thermostat and barostat variables.get_net_force
returns the net force on a group of particles due to a specific force compute
HPMC:
Fix a bug where external fields were ignored with the HPMC implicit integrator unless a patch potential was also in use.
JIT:
Add
jit.external.user
to specify user-defined external fields in HPMC.Use
-DHOOMD_LLVMJIT_BUILD
now instead of-DHOOMD_NOPYTHON
v2.4.2 (2018-12-20)
Bug fixes
Miscellaneous documentation updates
Fix compile error with
with -DALWAYS_USE_MANAGED_MEMORY=ON
Fix MuellerPlatheFlow, cast input parameter to int to avoid C++ constructor type mismatch
Improve startup time with multi-GPU simulations
Correctly assign GPUs to MPI processes on Summit when launching with more than one GPU per resource set
Optimize multi-GPU performance with NVLINK
Do not use mapped memory with MPI/GPU anymore
Fix some cases where a multi-GPU simulation fails with an alignment error
Eliminate remaining instance of unsafe
__shfl
Hide CMake warnings regarding missing CPU math libraries
Hide CMake warning regarding missing MPI<->CUDA interoperability
Refactor memory management to fix linker errors with some compilers
C++ API Changes
May break some plug-ins which rely on
GPUArray
data type being returned fromParticleData
and other classes (replace byGlobalArray
)
v2.4.1 (2018-11-27)
Bug fixes
Install
WarpTools.cuh
for use by pluginsFix potential violation of detailed balance with anisotropic particles with
hpmc.update.clusters
in periodic boundary conditionsSupport llvm 7.0
v2.4.0 (2018-11-07)
New features
General:
Misc documentation updates
Accept
mpi4py
communicators incontext.initialize
.CUDA 10 support and testing
Sphinx 1.8 support
Flush message output so that
python -u
is no longer required to obtain output on some batch job systemsSupport multi-GPU execution on dense nodes using CUDA managed memory. Execute with
--gpu=0,1,..,n-1
command line option to run on the first n GPUs (Pascal and above).Node-local acceleration is implemented for a subset of kernels. Performance improvements may vary.
Improvements are only expected with NVLINK hardware. Use MPI when NVLINK is not available.
Combine the
--gpu=..
command line option with mpirun to execute on many dense nodes
Bundle
libgetar
v0.7.0 and removesqlite3
dependencyWhen building with ENABLE_CUDA=on, CUDA 8.0 is now a minimum requirement
MD:
no changes.
HPMC:
Add
convex_spheropolyhedron_union
shape class.Correctly count acceptance rate when maximum particle move is is zero in
hpmc.integrate.*
.Correctly count acceptance rate when maximum box move size is zero in
hpmc.update.boxmc
.Fix a bug that may have led to overlaps between polygon soups with
hpmc.integrate.polyhedron
.Improve performance in sphere trees used in
hpmc.integrate.sphere_union
.Add
test_overlap
method to python API
API:
Allow external callers of HOOMD to set the MPI communicator
Removed all custom warp reduction and scan operations. These are now performed by CUB.
Separate compilation of pair potentials into multiple files.
Removed compute 2.0 workaround implementations. Compute 3.0 is now a hard minimum requirement to run HOOMD.
Support and enable compilation for sm70 with CUDA 9 and newer.
Deprecated:
HPMC: The implicit depletant mode
circumsphere
withntrial > 0
does not support compute 7.0 (Volta) and newer GPUs and is now disabled by default. To enable this functionality, configure HOOMD with option the-DENABLE_HPMC_REINSERT=ON
, which will not function properly on compute 7.0 (Volta) and newer GPUs.HPMC:
convex_polyhedron_union
is replaced byconvex_spheropolyhedron_union
(when sweep_radii are 0 for all particles)
v2.3.5 (2018-10-07)
Bug fixes
Document
--single-mpi
command line option.HPMC: Fix a bug where
hpmc.field.lattice_field
did not resize 2D systems properly in combination withupdate.box_resize
.
v2.3.4 (2018-07-30)
Bug fixes
init.read_gsd
no longer applies the time_step override when reading the restart fileHPMC: Add
hpmc_patch_energy
andhpmc_patch_rcut
loggable quantities to the documentation
v2.3.3 (2018-07-03)
Bug fixes
Fix
libquickhull.so
not found regression on Mac OS X
v2.3.2 (2018-06-29)
Bug fixes
Fix a bug where gsd_snapshot would segfault when called without an execution context.
Compile warning free with gcc8.
Fix compile error when TBB include files are in non-system directory.
Fix
libquickhull.so
not found error on additional platforms.HOOMD-blue is now available on conda-forge and the docker hub.
MPCD: Default value for
kT
parameter is removed formpcd.collide.at
. Scripts that are correctly running are not affected by this change.MPCD:
mpcd
notifies the user of the appropriate citation.MD: Correct force calculation between dipoles and point charge in
pair.dipole
Deprecated
The anaconda channel glotzer will no longer be updated. Use conda-forge to upgrade to v2.3.2 and newer versions.
v2.3.1 (2018-05-25)
Bug fixes
Fix doxygen documentation syntax errors
Fix libquickhull.so not found error on some platforms
HPMC: Fix bug that allowed particles to pas through walls
HPMC: Check spheropolyhedra with 0 vertices against walls correctly
HPMC: Fix plane wall/spheropolyhedra overlap test
HPMC: Restore detailed balance in implicit depletant integrator
HPMC: Correctly choose between volume and lnV moves in
hpmc.update.boxmc
HPMC: Fix name of log quantity
hpmc_clusters_pivot_acceptance
MD: Fix image list for tree neighbor lists in 2d
v2.3.0 (2018-04-25)
New features
General:
Store
BUILD_*
CMake variables in the hoomd cmake cache for use in external plugins.init.read_gsd
anddata.gsd_snapshot
now accept negative frame indices to index from the end of the trajectory.Faster reinitialization from snapshots when done frequently.
New command line option
--single-mpi
allows non-mpi builds of hoomd to launch within mpirun (i.e. for use with mpi4py managed pools of jobs)For users of the University of Michigan Flux system: A
--mode
option is no longer required to run hoomd.
MD:
Improve performance with
md.constrain.rigid
in multi-GPU simulations.New command
integrator.randomize_velocities()
sets a particle group’s linear and angular velocities to random values consistent with a given kinetic temperature.md.force.constant()
now supports setting the force per particle and inside a callback
HPMC:
Enabled simulations involving spherical walls and convex spheropolyhedral particle shapes.
Support patchy energetic interactions between particles (CPU only)
New command
hpmc.update.clusters()
supports geometric cluster moves with anisotropic particles and/or depletants and/or patch potentials. Supported move types: pivot and line reflection (geometric), and AB type swap.
JIT:
Add new experimental
jit
module that uses LLVM to compile and execute user provided C++ code at runtime. (CPU only)Add
jit.patch.user
: Compute arbitrary patch energy between particles in HPMC (CPU only)Add
jit.patch.user_union
: Compute arbitrary patch energy between rigid unions of points in HPMC (CPU only)Patch energies operate with implicit depletant and normal HPMC integration modes.
jit.patch.user_union
operates efficiently with additive contributions to the cutoff.
MPCD:
The
mpcd
component adds support for simulating hydrodynamics using the multiparticle collision dynamics method.
Beta feature
Node local parallelism (optional, build with
ENABLE_TBB=on
):The Intel TBB library is required to enable this feature.
The command line option
--nthreads
limits the number of threads HOOMD will use. The default is all CPU cores in the system.Only the following methods in HOOMD will take advantage of multiple threads:
hpmc.update.clusters()
HPMC integrators with implicit depletants enabled
jit.patch.user_union
Node local parallelism is still under development. It is not enabled in builds by default and only a few methods utilize multiple threads. In future versions, additional methods in HOOMD may support multiple threads.
To ensure future workflow compatibility as future versions enable threading in more components, explicitly set –nthreads=1.
Bug fixes
Fixed a problem with periodic boundary conditions and implicit depletants when
depletant_mode=circumsphere
Fixed a rare segmentation fault with
hpmc.integrate.*_union()
andhpmc.integrate.polyhedron
md.force.active
andmd.force.dipole
now record metadata properly.Fixed a bug where HPMC restore state did not set ignore flags properly.
hpmc_boxmc_ln_volume_acceptance
is now available for logging.
Other changes
Eigen is now provided as a submodule. Plugins that use Eigen headers need to update include paths.
HOOMD now builds with pybind 2.2. Minor changes to source and cmake scripts in plugins may be necessary. See the updated example plugin.
HOOMD now builds without compiler warnings on modern compilers (gcc6, gcc7, clang5, clang6).
HOOMD now uses pybind11 for numpy arrays instead of
num_util
.HOOMD versions v2.3.x will be the last available on the anaconda channel
glotzer
.
v2.2.5 (2018-04-20)
Bug fixes
Pin cuda compatible version in conda package to resolve
libcu*.so
not found errors in conda installations.
v2.2.4 (2018-03-05)
Bug fixes
Fix a rare error in
md.nlist.tree
when particles are very close to each other.Fix deadlock when
`init.read_getar`
is given different file names on different ranks.Sample from the correct uniform distribution of depletants in a sphere cap with
depletant_mode='overlap_regions'
on the CPUFix a bug where ternary (or higher order) mixtures of small and large particles were not correctly handled with
depletant_mode='overlap_regions'
on the CPUImprove acceptance rate in depletant simulations with
depletant_mode='overlap_regions'
v2.2.3 (2018-01-25)
Bug fixes
Write default values to gsd frames when non-default values are present in frame 0.
md.wall.force_shifted_lj
now works.Fix a bug in HPMC where
run()
would not start afterrestore_state
unless shape parameters were also set from python.Fix a bug in HPMC Box MC updater where moves were attempted with zero weight.
dump.gsd()
now writeshpmc
shape state correctly when there are multiple particle types.hpmc.integrate.polyhedron()
now produces correct results on the GPU.Fix binary compatibility across python minor versions.
v2.2.2 (2017-12-04)
Bug fixes
md.dihedral.table.set_from_file
now works.Fix a critical bug where forces in MPI simulations with rigid bodies or anisotropic particles were incorrectly calculated
Ensure that ghost particles are updated after load balancing.
meta.dump_metadata
no longer reports an error when used withmd.constrain.rigid
Miscellaneous documentation fixes
dump.gsd
can now write GSD files with 0 particles in a frameExplicitly report MPI synchronization delays due to load imbalance with
profile=True
Correctly compute net torque of rigid bodies with anisotropic constituent particles in MPI execution on multiple ranks
Fix
PotentialPairDPDThermoGPU.h
for use in external pluginsUse correct ghost region with
constrain.rigid
in MPI execution on multiple rankshpmc.update.muvt()
now works withdepletant_mode='overlap_regions'
Fix the sampling of configurations with in
hpmc.update.muvt
with depletantsFix simulation crash after modifying a snapshot and re-initializing from it
The pressure in simulations with rigid bodies (
md.constrain.rigid()
) and MPI on multiple ranks is now computed correctly
v2.2.1 (2017-10-04)
Bug fixes
Add special pair headers to install target
Fix a bug where
hpmc.integrate.convex_polyhedron
,hpmc.integrate.convex_spheropolyhedron
,hpmc.integrate.polyedron
,hpmc.integrate.faceted_sphere
,hpmc.integrate.sphere_union
andhpmc.integrate.convex_polyhedron_union
produced spurious overlaps on the GPU
v2.2.0 (2017-09-08)
New features
General:
Add
hoomd.hdf5.log
to log quantities in hdf5 format. Matrix quantities can be logged.dump.gsd
can now save internal state to gsd files. Calldump_state(object)
to save the state for a particular object. The following objects are supported:HPMC integrators save shape and trial move size state.
Add dynamic argument to
hoomd.dump.gsd
to specify which quantity categories should be written every frame.HOOMD now inter-operates with other python libraries that set the active CUDA device.
Add generic capability for bidirectional ghost communication, enabling multi body potentials in MPI simulation.
MD:
Added support for a 3 body potential that is harmonic in the local density.
force.constant
andforce.active
can now apply torques.quiet
option tonlist.tune
to quiet the output of the embeddedrun()
commands.Add special pairs as exclusions from neighbor lists.
Add cosine squared angle potential
md.angle.cosinesq
.Add
md.pair.DLVO()
for evaluation of colloidal dispersion and electrostatic forces.Add Lennard-Jones 12-8 pair potential.
Add Buckingham (exp-6) pair potential.
Add Coulomb 1-4 special_pair potential.
Check that composite body dimensions are consistent with minimum image convention and generate an error if they are not.
md.integrate.mode.minimize_fire()
now supports anisotropic particles (i.e. composite bodies)md.integrate.mode.minimize_fire()
now supports flexible specification of integration methodsmd.integrate.npt()/md.integrate.nph()
now accept a friction parameter (gamma) for damping out box fluctuations during minimization runsAdd new command
integrate.mode_standard.reset_methods()
to clear NVT and NPT integrator variables
HPMC:
hpmc.integrate.sphere_union()
takes new capacity parameter to optimize performance for different shape sizeshpmc.integrate.polyhedron()
takes new capacity parameter to optimize performance for different shape sizeshpmc.integrate.convex_polyhedron
andconvex_spheropolyhedron
now support arbitrary numbers of vertices, subject only to memory limitations (max_verts
is now ignored).HPMC integrators restore state from a gsd file read by
init.read_gsd
when the optionrestore_state
isTrue
.Deterministic HPMC integration on the GPU (optional):
mc.set_params(deterministic=True)
.New
hpmc.update.boxmc.ln_volume()
move allows logarithmic volume moves for fast equilibration.New shape:
hpmc.integrate.convex_polyhedron_union
performs simulations of unions of convex polyhedra.hpmc.field.callback()
now enables MC energy evaluation in a python functionThe option
depletant_mode='overlap_regions'
forhpmc.integrate.*
allows the selection of a new depletion algorithm that restores the diffusivity of dilute colloids in dense depletant baths
Deprecated
HPMC:
hpmc.integrate.sphere_union()
no longer needs themax_members
parameter.HPMC:
hpmc.integrate.convex_polyhedron
andconvex_spheropolyhedron
no longer needs themax_verts
parameter.The static argument to
hoomd.dump.gsd
should no longer be used. Use dynamic instead.
Bug fixes
HPMC:
hpmc.integrate.sphere_union()
andhpmc.integrate.polyhedron()
missed overlaps.Fix alignment error when running implicit depletants on GPU with ntrial > 0.
HPMC integrators now behave correctly when the user provides different RNG seeds on different ranks.
Fix a bug where overlapping configurations were produced with
hpmc.integrate.faceted_sphere()
MD:
charge.pppm()
withorder=7
now gives correct resultsThe PPPM energy for particles excluded as part of rigid bodies now correctly takes into account the periodic boundary conditions
EAM:
metal.pair.eam
now produces correct results.
Other changes
Optimized performance of HPMC sphere union overlap check and polyhedron shape
Improved performance of rigid bodies in MPI simulations
Support triclinic boxes with rigid bodies
Raise an error when an updater is given a period of 0
Revised compilation instructions
Misc documentation improvements
Fully document
constrain.rigid
-march=native
is no longer set by default (this is now a suggestion in the documentation)Compiler flags now default to CMake defaults
ENABLE_CUDA
andENABLE_MPI
CMake options default OFF. User must explicitly choose to enable optional dependencies.HOOMD now builds on powerpc+CUDA platforms (tested on summitdev)
Improve performance of GPU PPPM force calculation
Use sphere tree to further improve performance of
hpmc.integrate.sphere_union()
v2.1.9 (2017-08-22)
Bug fixes
Fix a bug where the log quantity
momentum
was incorrectly reported in MPI simulations.Raise an error when the user provides inconsistent
charge
ordiameter
lists tomd.constrain.rigid
.Fix a bug where
pair.compute_energy()
did not report correct results in MPI parallel simulations.Fix a bug where make rigid bodies with anisotropic constituent particles did not work on the GPU.
Fix hoomd compilation after the rebase in the cub repository.
deprecated.dump.xml()
now writes correct results when particles have been added or deleted from the simulation.Fix a critical bug where
charge.pppm()
calculated invalid forces on the GPU
v2.1.8 (2017-07-19)
Bug fixes
`init.read_getar`
now correctly restores static quantities when given a particular frame.Fix bug where many short calls to
run()
caused incorrect results when usingmd.integrate.langevin
.Fix a bug in the Saru pseudo-random number generator that caused some double-precision values to be drawn outside the valid range [0,1) by a small amount. Both floats and doubles are now drawn on [0,1).
Fix a bug where coefficients for multi-character unicode type names failed to process in Python 2.
Other changes
The Saru generator has been moved into
hoomd/Saru.h
, and plugins depending on Saru or SaruGPU will need to update their includes. TheSaruGPU
class has been removed. Usehoomd::detail::Saru
instead for both CPU and GPU plugins.
v2.1.7 (2017-05-11)
Bug fixes
Fix PPM exclusion handling on the CPU
Handle
r_cut
for special pairs correctlyFix tauP reference in NPH documentation
Fixed
constrain.rigid
on compute 5.x.Fixed random seg faults when using sqlite getar archives with LZ4 compression
Fixed XZ coupling with
hoomd.md.integrate.npt
integrationFixed aspect ratio with non-cubic boxes in
hoomd.hpmc.update.boxmc
v2.1.6 (2017-04-12)
Bug fixes
Document
hpmc.util.tune_npt
Fix dump.getar.writeJSON usage with MPI execution
Fix a bug where integrate.langevin and integrate.brownian correlated RNGs between ranks in multiple CPU execution
Bump CUB to version 1.6.4 for improved performance on Pascal architectures. CUB is now embedded using a git submodule. Users upgrading existing git repositories should reinitialize their git submodules with
git submodule update --init
CMake no longer complains when it finds a partial MKL installation.
v2.1.5 (2017-03-09)
Bug fixes
Fixed a compile error on Mac
v2.1.4 (2017-03-09)
Bug fixes
Fixed a bug re-enabling disabled integration methods
Fixed a bug where adding particle types to the system failed for anisotropic pair potentials
scipy is no longer required to execute DEM component unit tests
Issue a warning when a subsequent call to context.initialize is given different arguments
DPD now uses the seed from rank 0 to avoid incorrect simulations when users provide different seeds on different ranks
Miscellaneous documentation updates
Defer initialization message until context.initialize
Fixed a problem where a momentary dip in TPS would cause walltime limited jobs to exit prematurely
HPMC and DEM components now correctly print citation notices
v2.1.3 (2017-02-07)
Bug fixes
Fixed a bug where the WalltimeLimitReached was ignored
v2.1.2 (2017-01-11)
Bug fixes
(HPMC) Implicit depletants with spheres and faceted spheres now produces correct ensembles
(HPMC) Implicit depletants with ntrial > 0 now produces correct ensembles
(HPMC) NPT ensemble in HPMC (
hpmc.update.boxmc
) now produces correct ensemblesFix a bug where multiple nvt/npt integrators caused warnings from analyze.log.
update.balance() is properly ignored when only one rank is available
Add missing headers to plugin install build
Fix a bug where charge.pppm calculated an incorrect pressure
Other changes *
Drop support for compute 2.0 GPU devices
Support cusolver with CUDA 8.0
v2.1.1 (2016-10-23)
Bug fixes
Fix
force.active
memory allocation bugQuiet Python.h warnigns when building (python 2.7)
Allow multi-character particle types in HPMC (python 2.7)
Enable
dump.getar.writeJSON
in MPIAllow the flow to change directions in
md.update.mueller_plathe_flow
Fix critical bug in MPI communication when using HPMC integrators
v2.1.0 (2016-10-04)
New features
enable/disable overlap checks between pairs of constituent particles for
hpmc.integrate.sphere_union()
Support for non-additive mixtures in HPMC, overlap checks can now be enabled/disabled per type-pair
Add
md.constrain.oned
to constrain particles to move in one dimensionhpmc.integrate.sphere_union()
now takes max_members as an optional argument, allowing to use GPU memory more efficientlyAdd
md.special_pair.lj()
to support scaled 1-4 (or other) exclusions in all-atom force fieldsmd.update.mueller_plathe_flow()
: Method to create shear flows in MD simulationsuse_charge
option formd.pair.reaction_field
md.charge.pppm()
takes a Debye screening length as an optional parametermd.charge.pppm()
now computes the rigid body correction to the PPPM energy
Deprecated
HPMC: the
ignore_overlaps
flag is replaced byhpmc.integrate.interaction_matrix
Other changes
Optimized MPI simulations of mixed systems with rigid and non-rigid bodies
Removed dependency on all boost libraries. Boost is no longer needed to build hoomd
Intel compiler builds are no longer supported due to c++11 bugs
Shorter compile time for HPMC GPU kernels
Include symlinked external components in the build process
Add template for external components
Optimized dense depletant simulations with HPMC on CPU
Bug fixes
fix invalid mesh energy in non-neutral systems with
md.charge.pppm()
Fix invalid forces in simulations with many bond types (on GPU)
fix rare cases where analyze.log() would report a wrong pressure
fix possible illegal memory access when using
md.constrain.rigid()
in GPU MPI simulationsfix a bug where the potential energy is misreported on the first step with
md.constrain.rigid()
Fix a bug where the potential energy is misreported in MPI simulations with
md.constrain.rigid()
Fix a bug where the potential energy is misreported on the first step with
md.constrain.rigid()
md.charge.pppm()
computed invalid forcesFix a bug where PPPM interactions on CPU where not computed correctly
Match logged quantitites between MPI and non-MPI runs on first time step
Fix
md.pair.dpd
andmd.pair.dpdlj
set_params
Fix diameter handling in DEM shifted WCA potential
Correctly handle particle type names in lattice.unitcell
Validate
md.group.tag_list
is consistent across MPI ranks
v2.0.3 (2016-08-30)
hpmc.util.tune now works with particle types as documented
Fix pressure computation with pair.dpd() on the GPU
Fix a bug where dump.dcd corrupted files on job restart
Fix a bug where HPMC walls did not work correctly with MPI
Fix a bug where stdout/stderr did not appear in MPI execution
HOOMD will now report an human readable error when users forget context.initialize()
Fix syntax errors in frenkel ladd field
v2.0.2 (2016-08-09)
Support CUDA Toolkit 8.0
group.rigid()/nonrigid() did not work in MPI simulations
Fix builds with ENABLE_DOXYGEN=on
Always add -std=c++11 to the compiler command line arguments
Fix rare infinite loops when using hpmc.integrate.faceted_sphere
Fix hpmc.util.tune to work with more than one tunable
Fix a bug where dump.gsd() would write invalid data in simulations with changing number of particles
replicate() sometimes did not work when restarting a simulation
v2.0.1 (2016-07-15)
Bug fixes
Fix acceptance criterion in mu-V-T simulations with implicit depletants (HPMC).
References to disabled analyzers, computes, updaters, etc. are properly freed from the simulation context.
Fix a bug where
init.read_gsd
ignored therestart
argument.Report an error when HPMC kernels run out of memory.
Fix ghost layer when using rigid constraints in MPI runs.
Clarify definition of the dihedral angle.
v2.0.0 (2016-06-22)
HOOMD-blue v2.0 is released under a clean BSD 3-clause license.
New packages
dem
- simulate faceted shapes with dynamicshpmc
- hard particle Monte Carlo of a variety of shape classes.
Bug fixes
Angles, dihedrals, and impropers no longer initialize with one default type.
Fixed a bug where integrate.brownian gave the same x,y, and z velocity components.
Data proxies verify input types and vector lengths.
dump.dcd no longer generates excessive metadata traffic on lustre file systems
New features
Distance constraints
constrain.distance
- constrain pairs of particles to a fixed separation distanceRigid body constraints
constrain.rigid
- rigid bodies now have central particles, and support MPI and replicationMulti-GPU electrostatics
charge.pppm
- the long range electrostatic forces are now supported in MPI runscontext.initialize()
can now be called multiple times - useful in jupyter notebooksManage multiple simulations in a single job script with
SimulationContext
as a python context manager.util.quiet_status() / util.unquiet_status()
allow users to control if line status messages are output.Support executing hoomd in Jupyter (ipython) notebooks. Notice, warning, and error messages now show up in the notebook output blocks.
analyze.log
can now register python callback functions as sources for logged quantities.The GSD file format (http://gsd.readthedocs.io) is fully implemented in hoomd
dump.gsd
writes GSD trajectories and restart files (usetruncate=true
for restarts).init.read_gsd
reads GSD file and initializes the system, and can start the simulation from any frame in the GSD file.data.gsd_snapshot
reads a GSD file into a snapshot which can be modified before system initialization withinit.read_snapshot
.The GSD file format is capable of storing all particle and topology data fields in hoomd, either static at frame 0, or varying over the course of the trajectory. The number of particles, types, bonds, etc. can also vary over the trajectory.
force.active
applies an active force (optionally with rotational diffusion) to a group of particlesupdate.constrain_ellipsoid
constrains particles to an ellipsoidintegrate.langevin
andintegrate.brownian
now apply rotational noise and damping to anisotropic particlesSupport dynamically updating groups.
group.force_update()
forces the group to rebuild according to the original selection criteria. For example, this can be used to periodically update a cuboid group to include particles only in the specified region.pair.reaction_field
implements a pair force for a screened electrostatic interaction of a charge pair in a dielectric medium.force.get_energy
allows querying the potential energy of a particle group for a specific forceinit.create_lattice
initializes particles on a lattice.lattice.unitcell
provides a generic unit cell definition forcreate_lattice
Convenience functions for common lattices: sq, hex, sc, bcc, fcc.
Dump and initialize commands for the GTAR file format (http://libgetar.readthedocs.io).
GTAR can store trajectory data in zip, tar, sqlite, or bare directories
The current version stores system properties, later versions will be able to capture log, metadata, and other output to reduce the number of files that a job script produces.
integrate.npt
can now apply a constant stress tensor to the simulation box.Faceted shapes can now be simulated through the
dem
component.
Changes that require job script modifications
context.initialize()
is now required before any other hoomd script command.init.reset()
no longer exists. Usecontext.initialize()
or activate aSimulationContext
.Any scripts that relied on undocumented members of the
globals
module will fail. These variables have been moved to thecontext
module and members of the currently activeSimulationContext
.bonds, angles, dihedrals, and impropers no longer use the
set_coeff
syntax. Usebond_coeff.set
,angle_coeff.set
,dihedral_coeff.set
, andimproper_coeff.set
instead.hoomd_script
no longer exists, python commands are now spread acrosshoomd
,hoomd.md
, and other sub packages.integrate.\*_rigid()
no longer exists. Use a standard integrator ongroup.rigid_center()
, and define rigid bodies usingconstrain.rigid()
All neighbor lists must be explicitly created using
nlist.\*
, and each pair potential must be attached explicitly to a neighbor list. A default global neighbor list is no longer created.Moved cgcmm into its own package.
Moved eam into the metal package.
Integrators now take
kT
arguments for temperature instead ofT
to avoid confusion on the units of temperature.phase defaults to 0 for updaters and analyzers so that restartable jobs are more easily enabled by default.
dump.xml
(deprecated) requires a particle group, and can dump subsets of particles.
Other changes
CMake minimum version is now 2.8
Convert particle type names to
str
to allow unicode type name input__version__
is now available in the top level packageboost::iostreams
is no longer a build dependencyboost::filesystem
is no longer a build dependencyNew concepts page explaining the different styles of neighbor lists
Default neighbor list buffer radius is more clearly shown to be r_buff = 0.4
Memory usage of
nlist.stencil
is significantly reducedA C++11 compliant compiler is now required to build HOOMD-blue
Removed
Removed
integrate.bdnvt
: useintegrate.langevin
Removed
mtk=False
option fromintegrate.nvt
- The MTK NVT integrator is now the only implementation.Removed
integrate.\*_rigid()
: rigid body functionality is now contained in the standard integration methodsRemoved the global neighbor list, and thin wrappers to the neighbor list in
nlist
.Removed PDB and MOL2 dump writers.
Removed init.create_empty
Deprecated
Deprecated analyze.msd.
Deprecated dump.xml.
Deprecated dump.pos.
Deprecated init.read_xml.
Deprecated init.create_random.
Deprecated init.create_random_polymers.
v1.x
v1.3.3 (2016-03-06)
Bug fixes
Fix problem incluing
hoomd.h
in pluginsFix random memory errors when using walls
v1.3.2 (2016-02-08)
Bug fixes
Fix wrong access to system.box
Fix kinetic energy logging in MPI
Fix particle out of box error if particles are initialized on the boundary in MPI
Add integrate.brownian to the documentation index
Fix misc doc typos
Fix runtime errors with boost 1.60.0
Fix corrupt metadata dumps in MPI runs
v1.3.1 (2016-1-14)
Bug fixes
Fix invalid MPI communicator error with Intel MPI
Fix python 3.5.1 seg fault
v1.3.0 (2015-12-8)
New features
Automatically load balanced domain decomposition simulations.
Anisotropic particle integrators.
Gay-Berne pair potential.
Dipole pair potential.
Brownian dynamics
integrate.brownian
Langevin dynamics
integrate.langevin
(formerlybdnvt
)nlist.stencil
to compute neighbor lists using stencilled cell lists.Add single value scale,
min_image
, andmake_fraction
todata.boxdim
analyze.log
can optionally not write a file and now supports querying current quantity values.Rewritten wall potentials.
Walls are now sums of planar, cylindrical, and spherical half-spaces.
Walls are defined and can be modified in job scripts.
Walls execute on the GPU.
Walls support per type interaction parameters.
Implemented for: lj, gauss, slj, yukawa, morse, force_shifted_lj, and mie potentials.
External electric field potential:
external.e_field
Bug fixes
Fixed a bug where NVT integration hung when there were 0 particles in some domains.
Check SLURM environment variables for local MPI rank identification
Fixed a typo in the box math documentation
Fixed a bug where exceptions weren’t properly passed up to the user script
Fixed a bug in the velocity initialization example
Fixed an openmpi fork() warning on some systems
Fixed segfaults in PPPM
Fixed a bug where compute.thermo failed after reinitializing a system
Support list and dict-like objects in init.create_random_polymers.
Fall back to global rank to assign GPUs if local rank is not available
Deprecated commands
integrate.bdnvt
is deprecated. Useintegrate.langevin
instead.dump.bin
andinit.bin
are now removed. Use XML files for restartable jobs.
Changes that may break existing scripts
boxdim.wrap
now returns the position and image in a tuple, where it used to return just the position.wall.lj
has a new APIdump.bin
andinit.bin
have been removed.
v1.2.1 (2015-10-22)
Bug fixes
Fix a crash when adding or removing particles and reinitializing
Fix a bug where simulations hung on sm 5.x GPUs with CUDA 7.5
Fix compile error with long tests enabled
Issue a warning instead of an error for memory allocations greater than 4 GiB.
Fix invalid RPATH when building inside
zsh
.Fix incorrect simulations with
integrate.npt_rigid
Label mie potential correctly in user documentation
v1.2.0 (2015-09-30)
New features
Performance improvements for systems with large particle size disparity
Bounding volume hierarchy (tree) neighbor list computation
Neighbor lists have separate
r_cut
values for each pair of typesaddInfo callback for dump.pos allows user specified information in pos files
Bug fixes
Fix
test_pair_set_energy
unit test, which failed on numpy < 1.9.0Analyze.log now accepts unicode strings.
Fixed a bug where calling
restore_snapshot()
during a run zeroed potential parameters.Fix segfault on exit with python 3.4
Add
cite.save()
to documentationFix a problem were bond forces are computed incorrectly in some MPI configurations
Fix bug in pair.zbl
Add pair.zbl to the documentation
Use
HOOMD_PYTHON_LIBRARY
to avoid problems with modified CMake builds that presetPYTHON_LIBRARY
v1.1.1 (2015-07-21)
Bug fixes
dump.xml(restart=True)
now works with MPI executionAdded missing documentation for
meta.dump_metadata
Build all unit tests by default
Run all script unit tests through
mpirun -n 1
v1.1.0 (2015-07-14)
New features
Allow builds with ninja.
Allow K=0 FENE bonds.
Allow number of particles types to change after initialization.
system.particles.types.add('newtype')
Allow number of particles to change after initialization.
system.particles.add(‘A’) del system.particles[0]
OPLS dihedral
Add
phase
keyword to analyzers and dumps to make restartable jobs easier.HOOMD_WALLTIME_STOP
environment variable to stop simulation runs before they hit a wall clock limit.init.read_xml()
Now accepts an initialization and restart file.dump.xml()
can now write restart files.Added documentation concepts page on writing restartable jobs.
New citation management infrastructure.
cite.save()
writes.bib
files with a list of references to features actively used in the current job script.Snapshots expose data as numpy arrays for high performance access to particle properties.
data.make_snapshot()
makes a new empty snapshot.analyze.callback()
allows multiple python callbacks to operate at different periods.comm.barrier()``and
comm.barrier_all()``allow users to insert barriers into their scripts.Mie pair potential.
meta.dump_metadata()
writes job metadata information out to a json file.context.initialize()
initializes the execution context.Restart option for
dump.xml()
Bug fixes
Fix slow performance when initializing
pair.slj()
in MPI runs.Properly update particle image when setting position from python.
PYTHON_SITEDIR hoomd shell launcher now calls the python interpreter used at build time.
Fix compile error on older gcc versions.
Fix a bug where rigid bodies had 0 velocity when restarting jobs.
Enable
-march=native
builds in OS X clang builds.Fix
group.rigid()
andgroup.nonrigid()
.Fix image access from the python data access proxies.
Gracefully exit when launching MPI jobs with mixed execution configurations.
Changes that may require updated job scripts
context.initialize()
must be called before anycomm
method that queries the MPI rank. Call it as early as possible in your job script (right after importinghoomd_script
) to avoid problems.
Deprecated
init.create_empty()
is deprecated and will be removed in a future version. Usedata.make_snapshot()
andinit.read_snapshot()
instead.Job scripts that do not call
context.initialize()
will result in a warning message. A future version of HOOMD will require that you callcontext.initialize()
.
Removed
Several
option
commands for controlling the execution configuration. Replaced withcontext.initialize
.
v1.0.5 (2015-05-19)
Bug fixes
Fix segfault when changing integrators
Fix system.box to indicate the correct number of dimensions
Fix syntax error in comm.get_rank with –nrank
Enable CUDA enabled builds with the intel compiler
Use CMake builtin FindCUDA on recent versions of CMake
GCC_ARCH env var sets the -march command line option to gcc at configure time
Auto-assign GPU-ids on non-compute exclusive systems even with –mode=gpu
Support python 3.5 alpha
Fix a bug where particle types were doubled with boost 1.58.0
Fix a bug where angle_z=true dcd output was inaccurate near 0 angles
Properly handle lj.wall potentials with epsilon=0.0 and particles on top of the walls
v1.0.4 (2015-04-07)
Bug fixes
Fix invalid virials computed in rigid body simulations when multi-particle bodies crossed box boundaries
Fix invalid forces/torques for rigid body simulations caused by race conditions
Fix compile errors on Mac OS X 10.10
Fix invalid pair force computations caused by race conditions
Fix invalid neighbour list computations caused by race conditions on Fermi generation GPUs
Other
Extremely long running unit tests are now off by default. Enable with -DHOOMD_SKIP_LONG_TESTS=OFF
Add additional tests to detect race conditions and memory errors in kernels
v1.0.3 (2015-03-18)
Bug fixes
Enable builds with intel MPI
Silence warnings coming from boost and python headers
v1.0.2 (2015-01-21)
Bug fixes
Fixed a bug where
linear_interp
would not take a floating point value for zeroProvide more useful error messages when cuda drivers are not present
Assume device count is 0 when
cudaGetDeviceCount()
returns an errorLink to python statically when
ENABLE_STATIC=on
Misc documentation updates
v1.0.1 (2014-09-09)
Bug fixes
Fixed bug where error messages were truncated and HOOMD exited with a segmentation fault instead (e.g. on Blue Waters)
Fixed bug where plug-ins did not load on Blue Waters
Fixed compile error with gcc4.4 and cuda5.0
Fixed syntax error in
read_snapshot()
Fixed a bug where
init.read_xml throwing
an error (or any other command outside ofrun()
) would hang in MPI runsSearch the install path for hoomd_script - enable the hoomd executable to be outside of the install tree (useful with cray aprun)
Fixed CMake 3.0 warnings
Removed dependancy on tr1/random
Fixed a bug where
analyze.msd
ignored images in the r0_fileFixed typos in
pair.gauss
documentationFixed compile errors on Ubuntu 12.10
Fix failure of
integrate.nvt
to reach target temperature in analyze.log. The fix is a new symplectic MTK integrate.nvt integrator. Simulation results in hoomd v1.0.0 are correct, just the temperature and velocity outputs are off slightly.Remove MPI from Mac OS X dmg build.
Enable
import hoomd_script as ...
Other changes
Added default compile flag -march=native
Support CUDA 6.5
Binary builds for CentOS/RHEL 6, Fedora 20, Ubuntu 14.04 LTS, and Ubuntu 12.04 LTS.
Version 1.0.0 (2014-05-25)
New features
Support for python 3
New NPT integrator capable of flexible coupling schemes
Triclinic unit cell support
MPI domain decomposition
Snapshot save/restore
Autotune block sizes at run time
Improve performance in small simulation boxes
Improve performance with smaller numbers of particles per GPU
Full double precision computations on the GPU (compile time option must be enabled, binary builds provided on the download page are single precision)
Tabulated bond potential
bond.table
Tabulated angle potential
angle.table
Tabulated dihedral potental
dihedral.table
update.box_resize
now acceptsperiod=None
to trigger an immediate update of the box without creating a periodic updaterupdate.box_resize
now replaces None arguments with the current box parametersinit.create_random
andinit.create_random_polymers
can now create random configurations in triclinc and 2D boxesinit.create_empty
can now create triclinic boxesparticle, bond, angle, dihedral, and impropers types can now be named in
init.create_empty
system.replicate
command replicates the simulation box
Bug fixes
Fixed a bug where init.create_random_polymers failed when lx,ly,lz were not equal.
Fixed a bug in init.create_random_polymers and init.create_random where the separation radius was not accounted for correctly
Fixed a bug in bond.* where random crashes would occur when more than one bond type was defined
Fixed a bug where dump.dcd did not write the period to the file
Changes that may require updated job scripts
integrate.nph
: A time scaletau_p
for the relaxation of the barostat is now required instead of the barostat mass W of the previous release. The time scale is the relaxation time the barostat would have at an average temperatureT_0 = 1
, and it is related to the internally used (Andersen) Barostat mass W viaW = d N T_0 tau_p^2
, where d is the dimensionsality and N the number of particles.sorter
andnlist
are now modules, not variables in the__main__
namespace.Data proxies function correctly in MPI simulations, but are extremely slow. If you use
init.create_empty
, consider separating the generation step out to a single rank short execution that writes an XML file for the main run.update.box_resize(Lx=...)
no longer makes cubic box updates, instead it will keep the current Ly and Lz. Use theL=...
shorthand for cubic box updates.All
init.*
commands now takedata.boxdim
objects, instead ofhoomd.boxdim
(or 3-tuples). We strongly encourage the use of explicit argument names fordata.boxdim()
. In particular, ifhoomd.boxdim(123)
was previously used to create a cubic box, it is now required to usedata.boxdim(L=123)
(CORRECT) instead ofdata.boxdim(123)
(INCORRECT), otherwise a box with unit dimensions along the y and z axes will be created.system.dimensions
can no longer be set after initialization. System dimensions are now set during initialization via thedata.boxdim
interface. The dimensionality of the system can now be queried throughsystem.box
.system.box
no longer accepts 3-tuples. It takesdata.boxdim
objects.system.dimensions
no longer exists. Query the dimensionality of the system fromsystem.box
. Set the dimensionality of the system by passing an appropriatedata.boxdim
to aninit
method.init.create_empty
no longer acceptsn_*_types
. Instead, it now takes a list of strings to name the types.
Deprecated
Support for G80, G200 GPUs.
dump.bin
andread.bin
. These will be removed in v1.1 and replaced with a new binary format.
Removed
OpenMP mult-core execution (replaced with MPI domain decomposition)
tune.find_optimal_block_size
(replaced by Autotuner)
v0.x
Version 0.11.3 (2013-05-10)
Bug fixes
Fixed a bug where charge.pppm could not be used after init.reset()
Data proxies can now set body angular momentum before the first run()
Fixed a bug where PPPM forces were incorrect on the GPU
Version 0.11.2 (2012-12-19)
New features
Block sizes tuned for K20
Bug fixes
Warn user that PPPM ignores rigid body exclusions
Document that proxy iterators need to be deleted before init.reset()
Fixed a bug where body angular momentum could not be set
Fixed a bug where analyze.log would report nan for the pressure tensor in nve and nvt simulations
Version 0.11.1 (2012-11-2)
New features
Support for CUDA 5.0
Binary builds for Fedora 16 and OpenSUSE 12.1
Automatically specify /usr/bin/gcc to nvcc when the configured gcc is not supported
Bug fixes
Fixed a compile error with gcc 4.7
Fixed a bug where PPPM forces were incorrect with neighborlist exclusions
Fixed an issue where boost 1.50 and newer were not detected properly when BOOST_ROOT is set
Fixed a bug where accessing force data in python prevented init.reset() from working
Fixed a bug that prevented pair.external from logging energy
Fixed a unit test that failed randomly
Version 0.11.0 (2012-07-27)
New features
Support for Kepler GPUs (GTX 680)
NPH integration (integrate.nph)
Compute full pressure tensor
Example plugin for new bond potentials
New syntax for bond coefficients: bond.bond_coeff.set(‘type’, params)
New external potential: external.periodic applies a periodic potential along one direction (uses include inducing lamellar phases in copolymer systems)
Significant performance increases when running analyze.log, analyze.msd, update.box_resize, update.rescale_temp, or update.zero_momentum with a small period
Command line options may now be overwritten by scripts, ex: options.set_gpu(2)
Added –user command line option to allow user defined options to be passed into job scripts, ex: –user=“-N=5 -phi=0.56”
Added table.set_from_file method to enable reading table based pair potentials from a file
Added –notice-level command line option to control how much extra information is printed during a run. Set to 0 to disable, or any value up to 10. At 10, verbose debugging information is printed.
Added –msg-file command line option which redirects the message output to a file
New pair potential pair.force_shifted_lj : Implements http://dx.doi.org/10.1063/1.3558787
Bug fixes
Fixed a bug where FENE bonds were sometimes computed incorrectly
Fixed a bug where pressure was computed incorrectly when using pair.dpd or pair.dpdlj
Fixed a bug where using OpenMP and CUDA at the same time caused invalid memory accesses
Fixed a bug where RPM packages did not work on systems where the CUDA toolkit was not installed
Fixed a bug where rigid body velocities were not set from python
Disabled OpenMP builds on Mac OS X. HOOMD-blue w/ openmp enabled crashes due to bugs in Apple’s OpenMP implementation.
Fixed a bug that allowed users to provide invalid rigid body data and cause a seg fault.
Fixed a bug where using PPPM resulted in error messages on program exit.
API changes
Bond potentials rewritten with template evaluators
External potentials use template evaluators
Complete rewrite of ParticleData - may break existing plugins
Bond/Angle/Dihedral data structures rewritten
The GPU specific data structures are now generated on the GPU
DPDThermo and DPDLJThermo are now processed by the same template class
Headers that cannot be included by nvcc now throw an error when they are
CUDA 4.0 is the new minimum requirement
Rewrote BoxDim to internally handle minimum image conventions
HOOMD now only compiles ptx code for the newest architecture, this halves the executable file size
New Messenger class for global control of messages printed to the screen / directed to a file.
Testing changes
Automated test suite now performs tests on OpenMPI + CUDA builds
Valgrind tests added back into automated test suite
Added CPU test in bd_ridid_updater_tests
ctest -S scripts can now set parallel makes (with cmake > 2.8.2)
Version 0.10.1 (2012-02-10)
Add missing entries to credits page
Add
dist_check
option to neighbor list. Can be used to force neighbor list builds at a specified frequency (useful in profiling runs with nvvp).Fix typos in ubuntu compile documentation
Add missing header files to hoomd.h
Add torque to the python particle data access API
Support boost::filesystem API v3
Expose name of executing gpu, n_cpu, hoomd version, git sha1, cuda version, and compiler version to python
Fix a bug where multiple
nvt_rigid
ornpt_rigid
integrators didn’t work correctlyFix missing pages in developer documentation
Version 0.10.0 (2011-12-14)
New features
Added pair.dpdlj which uses the DPD thermostat and the Lennard-Jones potential. In previous versions, this could be accomplished by using two pair commands but at the cost of reduced performance.
Additional example scripts are now present in the documentation. The example scripts are cross-linked to the commands that are used in them.
Most dump commands now accept the form: dump.ext(filename=“filename.ext”) which immediately writes out filename.ext.
Added vis parameter to dump.xml which enables output options commonly used in files written for the purposes of visulization. dump.xml also now accepts parameters on the instantiation line. Combined with the previous feature, dump.xml(filename=“file.xml”, vis=True) is now a convenient short hand for what was previously
xml = dump.xml() xml.set_params(position = True, mass = True, diameter = True, type = True, bond = True, angle = True, dihedral = True, improper = True, charge = True) xml.write(filename="file.xml")
Specify rigid bodies in XML input files
Simulations that contain rigid body constraints applied to groups of particles in BDNVT, NVE, NVT, and NPT ensembles.
integrate.bdnvt_rigid
integrate.nve_rigid
integrate.nvt_rigid
integrate.npt_rigid
Energy minimization of rigid bodies (integrate.mode_minimize_rigid_fire)
Existing commands are now rigid-body aware
update.rescale_temp
update.box_resize
update.enforce2d
update.zero_momentum
NVT integration using the Berendsen thermostat (integrate.berendsen)
Bonds, angles, dihedrals, and impropers can now be created and deleted with the python data access API.
Attribution clauses added to the HOOMD-blue license.
Changes that may break existing job scripts
The wrap option to dump.dcd has been changed to unwrap_full and its meaning inverted. dump.dcd now offers two options for unwrapping particles, unwrap_full fully unwraps particles into their box image and unwrap_rigid unwraps particles in rigid bodies so that bodies are not broken up across a box boundary.
Bug/fixes small enhancements
Fixed a bug where launching hoomd on mac os X 10.5 always resulted in a bus error.
Fixed a bug where DCD output restricted to a group saved incorrect data.
force.constant may now be applied to a group of particles, not just all particles
Added C++ plugin example that demonstrates how to add a pair potential in a plugin
Fixed a bug where box.resize would always transfer particle data even in a flat portion of the variant
OpenMP builds re-enabled on Mac OS X
Initial state of integrate.nvt and integrate.npt changed to decrease oscillations at startup.
Fixed a bug where the polymer generator would fail to initialize very long polymers
Fixed a bug where images were passed to python as unsigned ints.
Fixed a bug where dump.pdb wrote coordinates in the wrong order.
Fixed a rare problem where a file written by dump.xml would not be read by init.read_xml due to round-off errors.
Increased the number of significant digits written out to dump.xml to make them more useful for ad-hoc restart files.
Potential energy and pressure computations that slow performance are now only performed on those steps where the values are actually needed.
Fixed a typo in the example C++ plugin
Mac build instructions updated to work with the latest version of macports
Fixed a bug where set_period on any dump was ineffective.
print_status_line now handles multiple lines
Fixed a bug where using bdnvt tally with per type gammas resulted in a race condition.
Fix an issue where ENABLE_CUDA=off builds gave nonsense errors when –mode=gpu was requested.
Fixed a bug where dumpl.xml could produce files that init.xml would not read
Fixed a typo in the example plugin
Fix example that uses hoomd as a library so that it compiles.
Update maintainer lines
Added message to nlist exclusions that notifies if diameter or body exclusions are set.
HOOMD-blue is now hosted in a git repository
Added bibtex bibliography to the user documentation
Converted user documentation examples to use doxygen auto cross-referencing
\example
commandsFix a bug where particle data is not released in dump.binary
ENABLE_OPENMP can now be set in the ctest builds
Tuned block sizes for CUDA 4.0
Removed unsupported GPUS from CUDA_ARCH_LIST
Version 0.9.2 (2011-04-04)
Note: only major changes are listed here.
New features
New exclusion option: Particles can now be excluded from the neighbor list based on diameter consistent with pair.slj.
New pair coeff syntax: Coefficients for multiple type pairs can be specified conveniently on a single line.
coeff.set(['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], epsilon=1.0)
New documentation: HOOMD-blue’s system of units is now fully documented, and every coefficient in the documentation is labeled with the appropriate unit.
Performance improvements: Performance has been significantly boosted for simulations of medium sized systems (5,000-20,000 particles). Smaller performance boosts were made to larger runs.
CUDA 3.2 support: HOOMD-blue is now fully tested and performance tuned for use with CUDA 3.2.
CUDA 4.0 support: HOOMD-blue compiles with CUDA 4.0 and passes initial tests.
New command: tune.r_buff performs detailed auto-tuning of the r_buff neighborlist parameter.
New installation method: RPM, DEB, and app bundle packages are now built for easier installation
New command: charge.pppm computes the full long range electrostatic interaction using the PPPM method
Bug/fixes small enhancements
Fixed a bug where the python library was linked statically.
Added the PYTHON_SITEDIR setting to allow hoomd builds to install into the native python site directory.
FIRE energy minimization convergence criteria changed to require both energy and force to converge
Clarified that groups are static in the documentation
Updated doc comments for compatibility with Doxygen#7.3
system.particles.types now lists the particle types in the simulation
Creating a group of a non-existant type is no longer an error
Mention XML file format for walls in wall.lj documentation
Analyzers now profile themselves
Use
\n
for newlines in dump.xml - improves performance when writing many XML files on a NFS file systemFixed a bug where the neighbor list build could take an exceptionally long time (several seconds) to complete the first build.
Fixed a bug where certain logged quantities always reported as 0 on the first step of the simulation.
system.box can now be used to read and set the simulation box size from python
Numerous internal API updates
Fixed a bug the resulted in incorrect behavior when using integrate.npt on the GPU.
Removed hoomd launcher shell script. In non-sitedir installs, ${HOOMD_ROOT}/bin/hoomd is now the executable itself
Creating unions of groups of non-existent types no longer produces a seg fault
hoomd now builds on all cuda architectures. Modify CUDA_ARCH_LIST in cmake to add or remove architectures from the build
hoomd now builds with boost#46.0
Updated hoomd icons to maize/blue color scheme
hoomd xml file format bumped to#3, adds support for charge.
FENE and harmonic bonds now handle 0 interaction parameters and 0 length bonds more gracefully
The packaged plugin template now actually builds and installs into a recent build of hoomd
Version 0.9.1 (2010-10-08)
Note: only major changes are listed here.
New features
New constraint: constrain.sphere constrains a group of particles to the surface of a sphere
New pair potential/thermostat: pair.dpd implements the standard DPD conservative, random, and dissipative forces
New pair potential: pair.dpd_conservative applies just the conservative DPD potential
New pair potential: pair.eam implements the Embedded Atom Method (EAM) and supports both alloy and FS type computations.
Faster performance: Cell list and neighbor list code has been rewritten for performance.
In our benchmarks, performance increases ranged from 10-50% over HOOMD-blue 0.9.0. Simulations with shorter cutoffs tend to attain a higher performance boost than those with longer cutoffs.
We recommended that you re-tune r_buff values for optimal performance with 0.9.1.
Due to the nature of the changes, identical runs may produce different trajectories.
Removed limitation: The limit on the number of neighbor list exclusions per particle has been removed. Any number of exclusions can now be added per particle. Expect reduced performance when adding excessive numbers of exclusions.
Bug/fixes small enhancements
Pressure computation is now correct when constraints are applied.
Removed missing files from hoomd.h
pair.yukawa is no longer referred to by “gaussian” in the documentation
Fermi GPUs are now prioritized over per-Fermi GPUs in systems where both are present
HOOMD now compiles against CUDA 3.1
Momentum conservation significantly improved on compute#x hardware
hoomd plugins can now be installed into user specified directories
Setting r_buff=0 no longer triggers exclusion list updates on every step
CUDA 2.2 and older are no longer supported
Workaround for compiler bug in 3.1 that produces extremely high register usage
Disabled OpenMP compile checks on Mac OS X
Support for compute 2.1 devices (such as the GTX 460)
Version 0.9.0 (2010-05-18)
Note: only major changes are listed here.
New features
New pair potential: Shifted LJ potential for particles of varying diameters (pair.slj)
New pair potential: Tabulated pair potential (pair.table)
New pair potential: Yukawa potential (pair.yukawa)
Update to pair potentials: Most pair potentials can now accept different values of r_cut for different type pairs. The r_cut specified in the initial pair.*** command is now treated as the default r_cut, so no changes to scripts are necessary.
Update to pair potentials: Default pair coeff values are now supported. The parameter alpha for lj now defaults to#0, so there is no longer a need to specify it for a majority of simulations.
Update to pair potentials: The maximum r_cut needed for the neighbor list is now determined at the start of each run(). In simulations where r_cut may decrease over time, increased performance will result.
Update to pair potentials: Pair potentials are now specified via template evaluator classes. Adding a new pair potential to hoomd now only requires a small amount of additional code.
Plugin API : Advanced users/developers can now write, install, and use plugins for hoomd without needing to modify core hoomd source code
Particle data access: User-level hoomd scripts can now directly access the particle data. For example, one can change all particles in the top half of the box to be type B:
top = group.cuboid(name="top", zmin=0) for p in top: p.type = 'B'
. All particle data including position, velocity, type, ‘’et cetera’’, can be read and written in this manner. Computed forces and energies can also be accessed in a similar way.
New script command: init.create_empty() can be used in conjunction with the particle data access above to completely initialize a system within the hoomd script.
New script command: dump.bin() writes full binary restart files with the entire system state, including the internal state of integrators.
File output can be gzip compressed (if zlib is available) to save space
Output can alternate between two different output files for safe crash recovery
New script command: init.read_bin() reads restart files written by dump.bin()
New option: run() now accepts a quiet option. When True, it eliminates the status information printouts that go to stdout.
New example script: Example 6 demonstrates the use of the particle data access routines to initialize a system. It also demonstrates how to initialize velocities from a gaussian distribution
New example script: Example 7 plots the pair.lj potential energy and force as evaluated by hoomd. It can trivially be modified to plot any potential in hoomd.
New feature: Two dimensional simulations can now be run in hoomd: #259
New pair potential: Morse potential for particles of varying diameters (pair.morse)
New command: run_upto will run a simulation up to a given time step number (handy for breaking long simulations up into many independent jobs)
New feature: HOOMD on the CPU is now accelerated with OpenMP.
New feature: integrate.mode_minimize_fire performs energy minimization using the FIRE algorithm
New feature: analyze.msd can now accept an xml file specifying the initial particle positions (for restarting jobs)
Improved feature: analyze.imd now supports all IMD commands that VMD sends (pause, kill, change trate, etc.)
New feature: Pair potentials can now be given names, allowing multiple potentials of the same type to be logged separately. Additionally, potentials that are disabled and not applied to the system dynamics can be optionally logged.
Performance improvements: Simulation performance has been increased across the board, but especially when running systems with very low particle number densities.
New hardware support: 0.9.0 and newer support Fermi GPUs
Deprecated hardware support: 0.9.x might continue run on compute#1 GPUs but that hardware is no longer officially supported
New script command: group.tag_list() takes a python list of particle tags and creates a group
New script command: compute.thermo() computes thermodynamic properties of a group of particles for logging
New feature: dump.dcd can now optionally write out only those particles that belong to a specified group
Changes that will break jobs scripts written for 0.8.x
Integration routines have changed significantly to enable new use cases. Where scripts previously had commands like:
integrate.nve(dt=0.005)
they now need
all = group.all() integrate.mode_standard(dt=0.005) integrate.nve(group=all)
. Integrating only specific groups of particles enables simulations to fix certain particles in place or integrate different parts of the system at different temperatures, among many other possibilities.
sorter.set_params no longer takes the ‘’bin_width’’ argument. It is replaced by a new ‘’grid’’ argument, see the documentation for details.
conserved_quantity is no longer a quantity available for logging. Instead log the nvt reservoir energy and compute the total conserved quantity in post processing.
Bug/fixes small enhancements
Fixed a bug where boost#38 is not found on some machines
dump.xml now has an option to write particle accelerations
Fixed a bug where periods like 1e6 were not accepted by updaters
Fixed a bug where bond.fene forces were calculated incorrectly between particles of differing diameters
Fixed a bug where bond.fene energies were computed incorrectly when running on the GPU
Fixed a bug where comments in hoomd xml files were not ignored as they aught to be: #331
It is now possible to prevent bond exclusions from ever being added to the neighbor list: #338
init.create_random_polymers can now generate extremely dense systems and will warn the user about large memory usage
variant.linear_interp now accepts a user-defined zero (handy for breaking long simulations up into many independent jobs)
Improved installation and compilation documentation
Integration methods now silently ignore when they are given an empty group
Fixed a bug where disabling all forces resulted in some forces still being applied
Integrators now behave in a reasonable way when given empty groups
Analyzers now accept a floating point period
run() now aborts immediately if limit_hours=0 is specified.
Pair potentials that diverge at r=0 will no longer result in invalid simulations when the leading coefficients are set to zero.
integrate.bdnvt can now tally the energy transferred into/out of the “reservoir”, allowing energy conservation to be monitored during bd simulation runs.
Most potentials now prevent NaN results when computed for overlapping particles
Stopping a simulation from a callback or time limit no longer produces invalid simulations when continued
run() commands limited with limit_hours can now be set to only stop on given timestep multiples
Worked around a compiler bug where pair.morse would crash on Fermi GPUs
ULF stability improvements for G200 GPUs.
Version 0.8.2 (2009-09-10)
Note: only major changes are listed here.
New features
Quantities that vary over time can now be specified easily in scripts with the variant.linear_interp command.
Box resizing updater (update.box_resize) command that uses the time varying quantity command to grow or shrink the simulation box.
Individual run() commands can be limited by wall-clock time
Angle forces can now be specified
Dihedral forces can now be specified
Improper forces can now be specified
1-3 and 1-4 exclusions from the cutoff pair force can now be chosen
New command line option: –minimize-cpu-usage cuts the CPU usage of HOOMD down to 10% of one CPU core while only decreasing overall performance by 10%
Major changes have been made in the way HOOMD chooses the device on which to run (all require CUDA 2.2 or newer)
there are now checks that an appropriate NVIDIA drivers is installed
running without any command line options will now correctly revert to running on the CPU if no capable GPUs are installed
when no gpu is explicitly specified, the default choice is now prioritized to choose the fastest GPU and one that is not attached to a display first
new command line option: –ignore-display-gpu will prevent HOOMD from executing on any GPU attached to a display
HOOMD now prints out a short description of the GPU(s) it is running on
on linux, devices can be set to compute-exclusive mode and HOOMD will then automatically choose the first free GPU (see the documentation for details)
nlist.reset_exclusions command to control the particles that are excluded from the neighbor list
Bug/fixes small enhancements
Default block size change to improve stability on compute#3 devices
ULF workaround on GTX 280 now works with CUDA 2.2
Standalone benchmark executables have been removed and replaced by in script benchmarking commands
Block size tuning runs can now be performed automatically using the python API and results can be saved on the local machine
Fixed a bug where GTX 280 bug workarounds were not properly applied in CUDA 2.2
The time step read in from the XML file can now be optionally overwritten with a user-chosen one
Added support for CUDA 2.2
Fixed a bug where the WCA forces included in bond.fene had an improper cutoff
Added support for a python callback to be executed periodically during a run()
Removed demos from the hoomd downloads. These will be offered separately on the webpage now to keep the required download size small.
documentation improvements
Significantly increased performance of dual-GPU runs when build with CUDA 2.2 or newer
Numerous stability and performance improvements
Temperatures are now calculated based on 3N-3 degrees of freedom. See #283 for a more flexible system that is coming in the future.
Emulation mode builds now work on systems without an NVIDIA card (CUDA 2.2 or newer)
HOOMD now compiles with CUDA 2.3
Fixed a bug where uninitialized memory was written to dcd files
Fixed a bug that prevented the neighbor list on the CPU from working properly with non-cubic boxes
There is now a compile time hack to allow for more than 4 exclusions per particle
Documentation added to aid users in migrating from LAMMPS
hoomd_script now has an internal version number useful for third party scripts interfacing with it
VMD#8.7 is now found by the live demo scripts
live demos now run in vista 64-bit
init.create_random_polymers can now create polymers with more than one type of bond
Version 0.8.1 (2009-03-24)
Note: only major changes are listed here.
New features
Significant performance enhancements
New build option for compiling on UMich CAC clusters: ENABLE_CAC_GPU_ID compiles HOOMD to read in the $CAC_GPU_ID environment variable and use it to determine which GPUs to execute on. No –gpu command line required in job scripts any more.
Particles can now be assigned a non-unit mass
init.reset() command added to allow for the creation of a looped series of simulations all in python
dump.pdb() command for writing PDB files
pair.lj now comes with an option to shift the potential energy to 0 at the cutoff
pair.lj now comes with an opiton to smoothly switch both the potential and force to 0 at the cutoff with the XPLOR smoothing function
Gaussian pair potential computation added (pair.gauss)
update and analyze commands can now be given a function to determine a non-linear rate to run at
analyze.log, and dump.dcd can now append to existing files
Changes that will break scripts from 0.8.0
dump.mol2() has been changed to be more consistent with other dump commands. In order to get the same result as the previous behavior, replace
dump.mol2(filename="file.mol2")
with
mol2 = dump.mol2() mol2.write(filename="file.mol2")
Grouping commands have been moved to their own package for organizational purposes. group_all() must now be called as group.all() and similarly for tags and type.
Bug/fixes small enhancements
Documentation updates
DCD file writing no longer crashes HOOMD in windows
!FindBoost.cmake is patched upstream. Use CMake 2.6.3 if you need BOOST_ROOT to work correctly
Validation tests now run with –gpu_error_checking
ULF bug workarounds are now enabled only on hardware where they are needed. This boosts performance on C1060 and newer GPUs.
!FindPythonLibs now always finds the shared python libraries, if they exist
“make package” now works fine on mac os x
Fixed erroneously reported dangerous neighbor list builds when using –mode=cpu
Small tweaks to the XML file format.
Numerous performance enhancements
Workaround for ULF on compute#1 devices in place
dump.xml can now be given the option “all=true” to write all fields
total momentum can now be logged by analyze.log
HOOMD now compiles with boost#38 (and hopefully future versions)
Updaters can now be given floating point periods such as 1e5
Additional warnings are now printed when HOOMD is about to allocate a large amount of memory due to the specification of an extremely large box size
run() now shows up in the documentation index
Default sorter period is now 100 on CPUs to improve performance on chips with small caches
Version 0.8.0 (2008-12-22)
Note: only major changes are listed here.
New features
Addition of FENE bond potential
Addition of update.zero_momentum command to zero a system’s linear momentum
Brownian dynamics integration implemented
Multi-GPU simulations
Particle image flags are now tracked. analyze.msd command added to calculate the mean squared displacement.
Changes that will break scripts from 0.7.x
analyze.log quantity names have changed
Bug/fixes small enhancements
Performance of the neighbor list has been increased significantly on the GPU (overall performance improvements are approximately 10%)
Profile option added to the run() command
Warnings are now correctly printed when negative coefficients are given to bond forces
Simulations no longer fail on G200 cards
Mac OS X binaries will be provided for download: new documentation for installing on Mac OS x has been written
Two new demos showcasing large systems
Particles leaving the simulation box due to bad initial conditions now generate an error
win64 installers will no longer attempt to install on win32 and vice-versa
neighborlist check_period now defaults to 1
The elapsed time counter in run() now continues counting time over multiple runs.
init.create_random_polymers now throws an error if the bond length is too small given the specified separation radii
Fixed a bug where a floating point value for the count field in init.create_random_polymers produced an error
Additional error checking to test if particles go NaN
Much improved status line printing for identifying hoomd_script commands
Numerous documentation updates
The VS redistributable package no longer needs to be installed to run HOOMD on windows (these files are distributed with HOOMD)
Now using new features in doxygen#5.7 to build pdf user documentation for download.
Performance enhancements of the Lennard-Jones pair force computation, thanks to David Tarjan
A header prefix can be added to log files to make them more gnuplot friendly
Log quantities completely revamped. Common quantities (i.e. kinetic energy, potential energy can now be logged in any simulation)
Particle groups can now be created. Currently only analyze.msd makes use of them.
The CUDA toolkit no longer needs to be installed to run a packaged HOOMD binary in windows.
User documentation can now be downloaded as a pdf.
Analyzers and updaters now count time 0 as being the time they were created, instead of time step 0.
Added job test scripts to aid in validating HOOMD
HOOMD will now build with default settings on a linux/unix-like OS where the boost static libraries are not installed, but the dynamic ones are.
Version 0.7.1 (2008-09-12)
Fixed bug where extremely large box dimensions resulted in an argument error - ticket:118
Fixed bug where simulations ran incorrectly with extremely small box dimensions - ticket:138
Version 0.7.0 (2008-08-12)
Note: only major changes are listed here.
Stability and performance improvements.
Cleaned up the hoomd_xml file format.
Improved detection of errors in hoomd_xml files significantly.
Users no longer need to manually specify HOOMD_ROOT, unless their installation is non-standard
Particle charge can now be read in from a hoomd_xml file
Consistency changes in the hoomd_xml file format: HOOMD 0.6.0 XML files are not compatible. No more compatibility breaking changes are planned after 0.7.0
Enabled parallel builds in MSVC for faster compilation times on multicore systems
Numerous small bug fixes
New force compute for implementing walls
Documentation updates
Support for CUDA 2.0
Bug fixed allowing simulations with no integrator
Support for boost#35.0
Cleaned up GPU code interface
NVT integrator now uses tau (period) instead of Q (the mass of the extra degree of freedom).
Added option to NVE integration to limit the distance a particle moves in a single time step
Added code to dump system snapshots in the DCD file format
Particle types can be named by strings
A snapshot of the initial configuration can now be written in the .mol2 file format
The default build settings now enable most of the optional features
Separated the user and developer documentation
Mixed polymer systems can now be generated inside HOOMD
Support for CMake 2.6.0
Wrote the user documentation
GPU selection from the command line
Implementation of the job scripting system
GPU can now handle neighbor lists that overflow
Energies are now calculated
Added a logger for logging energies during a simulation run
Code now actually compiles on Mac OS X
Benchmark and demo scripts now use the new scripting system
Consistent error message format that is more visible.
Multiple types of bonds each with the own coefficients are now supported
Added python scripts to convert from HOOMD’s XML file format to LAMMPS input and dump files
Fixed a bug where empty xml nodes in input files resulted in an error message
Fixed a bug where HOOMD seg faulted when a particle left the simulation , vis=True)* is now a convenient short hand for what was previously box now works fine on mac os x
Fixed erroneously reported dangerous neighbor list builds when using –mode=cpu
Small tweaks to the XML file format.
Numerous performance enhancements
Workaround for ULF on compute#1 devices in place
dump.xml can now be given the option
Citing HOOMD-blue
- Please cite this publication in any work that uses HOOMD-blue:
J. A. Anderson, J. Glaser, and S. C. Glotzer. HOOMD-blue: A Python package for high-performance molecular dynamics and hard particle Monte Carlo simulations. Computational Materials Science 173: 109363, Feb 2020. 10.1016/j.commatsci.2019.109363
The following publications document significant contributions to features in HOOMD-blue. We encourage you to cite these, if possible, when you make use of these specific functionalities.
- HPMC:
J. A. Anderson, M. E. Irrgang, and S. C. Glotzer. Scalable Metropolis Monte Carlo for simulation of hard shapes. Computer Physics Communications 204: 21-30, July 2016. 10.1016/j.cpc.2016.02.024
- Implicit depletants in HPMC:
J. Glaser, A. S. Karas, and S. C. Glotzer. A parallel algorithm for implicit depletant simulations. The Journal of Chemical Physics 143: 184110, 2015. 10.1063/1.4935175
- MPI scaling:
J. Glaser, T. D. Nguyen, J. A. Anderson, P. Lui, F. Spiga, J. A. Millan, D. C. Morse, S. C. Glotzer. Strong scaling of general-purpose molecular dynamics simulations on GPUs. Computer Physics Communications 192: 97-107, July 2015. 10.1016/j.cpc.2015.02.028
- Intra-node scaling on multiple GPUs:
J. Glaser, P. S. Schwendeman, J. A. Anderson, S. C. Glotzer. Unified memory in HOOMD-blue improves node-level strong scaling. Computational Materials Science 173: 109359, Feb 2020. 10.1016/j.commatsci.2019.109359
- Alchemical MD simulations:
G. van Anders, D. Klotsa, A. S. Karas, P. M. Dodd, S. C. Glotzer. Digital Alchemy for Materials Design: Colloids and Beyond. ACS Nano 2015, 9, 10, 9542-9553 10.1021/acsnano.5b04181
P. Zhou, J. C. Proctor, G. van Anders, S. C. Glotzer. Alchemical molecular dynamics for inverse design. Molecular Physics, 117:23-24, 3968-3980 2019. 10.1080/00268976.2019.1680886
- Alchemical HPMC simulations:
G. van Anders, D. Klotsa, A. S. Karas, P. M. Dodd, S. C. Glotzer. Digital Alchemy for Materials Design: Colloids and Beyond. ACS Nano 2015, 9, 10, 9542-9553 10.1021/acsnano.5b04181
Y. Geng, G. van Anders, P. M. Dodd, J. Dshemuchadse, S. C. Glotzer. Engineering entropy for the inverse design of colloidal crystals from hard shapes. Science Advances 2019, 5, 7, eaaw051 10.1126/sciadv.aaw0514
- When including historical development of HOOMD-blue, or noting that HOOMD-blue was first implemented on GPUs, please also cite:
J. A. Anderson, C. D. Lorenz, and A. Travesset. General purpose molecular dynamics simulations fully implemented on graphics processing units. Journal of Computational Physics 227(10): 5342-5359, May 2008. 10.1016/j.jcp.2008.01.047
- DEM:
M. Spellings, R. L. Marson, J. A. Anderson, and S. C. Glotzer. GPU accelerated Discrete Element Method (DEM) molecular dynamics for conservative, faceted particle simulations. Journal of Computational Physics 334: 460-467, Apr 2017. 10.1016/j.jcp.2017.01.014
- The tree or stencil MD neighbor list:
M. P. Howard, J. A. Anderson, A. Nikoubashman, S. C. Glotzer, and A. Z. Panagiotopoulos. Efficient neighbor list calculation for molecular simulation of colloidal systems using graphics processing units. Computer Physics Communications 203: 45-52, Mar 2016. 10.1016/j.cpc.2016.02.003
M. P. Howard, A. Statt, F. Madutsa, T. M. Truskett, and A. Z. Panagiotopoulos. Quantized bounding volume hierarchies for neighbor search in molecular simulations on graphics processing units. Computational Materials Science 164(15): 139-146, June 2019. 10.1016/j.commatsci.2019.04.004
- MPCD:
M. P. Howard, A. Z. Panagiotopoulos, and A. Nikoubashman. Efficient mesoscale hydrodynamics: Multiparticle collision dynamics with massively parallel GPU acceleration Computer Physics Communications 230: 10-20, Sep. 2018. 10.1016/j.cpc.2018.04.009
- Rigid bodies in MD:
T. D. Nguyen, C. L. Phillips, J. A. Anderson, and S. C. Glotzer. Rigid body constraints realized in massively-parallel molecular dynamics on graphics processing units. Computer Physics Communications 182(11): 2313-2307, June 2011. 10.1016/j.cpc.2011.06.005
J. Glaser, X. Zha, J. A. Anderson, S. C. Glotzer, A. Travesset. Pressure in rigid body molecular dynamics. Computational Materials Science Computational Materials Science 173: 109430, Feb 2020. 10.1016/j.commatsci.2019.109430
- DPD:
C. L. Phillips, J. A. Anderson, and S. C. Glotzer. Pseudo-random number generation for Brownian Dynamics and Dissipative Particle Dynamics simulations on GPU devices Journal of Computational Physics 230(19): 7191-7201, Aug. 2011. 10.1016/j.jcp.2011.05.021
- EAM:
I.V. Morozov, A.M. Kazennova, R.G. Bystryia, G.E. Normana, V.V. Pisareva, and V.V. Stegailova. Molecular dynamics simulations of the relaxation processes in the condensed matter on GPUs. Computer Physics Communications 182(9): 1974-1978, 2011. 10.1016/j.cpc.2010.12.026
L. Yang, F. Zhang, C. Wang, K. Ho, and A. Travesset. Implementation of metal-friendly EAM/FS-type semi-empirical potentials in HOOMD-blue: A GPU-accelerated molecular dynamics software. Journal of Computational Physics 359(15): 352-360, 2018. 10.1016/j.jcp.2018.01.015
- PPPM:
D. N. LeBard, B. G. Levine, P. Mertmann, S. A. Barr, A. Jusufi, S. Sanders, M. L. Klein, and A. Z. Panagiotopoulos. Self-assembly of coarse-grained ionic surfactants accelerated by graphics processing units. Soft Matter 8: 2385-2397, 2012. 10.1039/c1sm06787g
- CGCMM potential:
B. G. Levine, D. N. LeBard, R. DeVane, W. Shinoda, A. Kohlmeyer, and M. L. Klein. Micellization studied by GPU-accelerated coarse-grained molecular dynamics. Journal of Chemical Theory and Computation 7(12): 4135-4145, Oct. 2011. 10.1021/ct2005193
Introducing HOOMD-blue
HOOMD-blue is a Python package that performs Molecular Dynamics and hard particle Monte Carlo simulations. HOOMD-blue is general and can be used to model nanoparticles, bead-spring polymers, active mater, and many other types of systems. This tutorial introduces the core concepts in HOOMD-blue using hard particle self-assembly as an example. Later tutorials will expand on these concepts for other types of simulations.
Prerequisites:
This tutorial assumes you have some familiarity with the Python programming language.
The Simulation Object
Overview
Questions
How can I configure and control a simulation?
How do I choose which processor to use?
Objectives
Explain the parts of the Simulation object and how they relate.
Explain how the device object influences how the simulation executes.
Demonstrate the creation of these objects.
Core objects
HOOMD-blue is an object-oriented Python package. First, import the package:
[1]:
import hoomd
The Simulation object combines all the elements of a simulation together and provides an interface to run the simulation. It consists of the simulation state and operations which act on that state. The simulation state includes the current box, bonds, particle positions, velocities, orientations, and other particle properties. Operations examine or modify the state. A simulation has one state, and any number of operations.
Selecting a device
You must specify a device when constructing a Simulation. The device tells the simulation where to store the state and what processor to use when executing operations. HOOMD-blue can execute on the CPU:
[2]:
cpu = hoomd.device.CPU()
Or the GPU:
[3]:
gpu = hoomd.device.GPU()
GPUs are highly parallel processors best suited for larger workloads. In typical systems with more than 4,000 particles a single GPU performs an order of magnitude faster than an entire CPU (all cores). Try your simulation on both to see what hardware can run the same number of time steps in less time.
Creating a Simulation
Now, you can instantiate a Simulation with the chosen device.
[4]:
sim = hoomd.Simulation(device=cpu)
A newly constructed Simulation has no state:
[5]:
print(sim.state)
None
And no integrator, updaters, or writers, which are types of operations:
[6]:
print(sim.operations.integrator)
None
[7]:
print(sim.operations.updaters[:])
[]
[8]:
print(sim.operations.writers[:])
[]
The remaining sections in this tutorial will show you how to populate a Simulation with operations, initialize the state, and run the simulation.
Performing Hard Particle Monte Carlo Simulations
Overview
Questions
What is hard particle Monte Carlo?
How do I set up a hard particle Monte Carlo simulation?
Objectives
Describe hard particle Monte Carlo simulations, particle shape, and trial moves.
Show how to initialize the ConvexPolyhedron integrator.
Explain the integrator parameters.
Introduce time steps.
Boilerplate code
[1]:
import math
import hoomd
Particle shape
A hard particle Monte Carlo (HPMC) simulation represents particles as extended objects which are not allowed to overlap. There are no attractive or repulsive forces in the system. The shape of the particle alone controls how it interacts with other particles. Formally, the potential energy of the system is zero when there are no overlaps and infinite when there are. Purely hard interactions induce effective attractions between particles which can lead to ordered structures. For example, hard regular octahedra will self-assemble into a bcc structure. In this tutorial, you will learn how to run a simulation of hard octahedra and observe this behavior.

The integrator
The ConvexPolyhedron integrator implements HPMC simulations - Create one:
[2]:
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
Set the shape
property to define the particle shape. A convex polyhedron is defined by the convex hull of a set of vertices:
[3]:
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
Trial moves
During each time step, HPMC attempts nselect
trial moves on each particle in the system. Each trial move is drawn from a pseudorandom number stream and may be either a translation or rotation move. Translation moves displace a particle a random distance (up to d
) in a random direction. Rotation moves rotate the particle by a random angle about a random axis. Larger values of a
lead to larger possible rotation moves.
Any trial move whose shape overlaps with another particle is rejected, leaving the particle’s position and orientation unchanged. Any trial move whose shape does not overlap with any other particle is accepted, setting the particle’s position or orientation to the new value.
nselect
, d
, and a
are properties of the integrator:
[4]:
mc.nselect = 2
mc.d['octahedron'] = 0.15
mc.a['octahedron'] = 0.2
Setting the integrator
[5]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=1)
An integrator is a type of operation. There can only be one integrator in a Simulation and it operates on the system state on every time step. Assign the HPMC integrator to the Simulation to use it:
[6]:
sim.operations.integrator = mc
The seed
value (passed to the simulation constructor above) selects the sequence of values in the pseudorandom number stream. Given the same initial condition and seed
, HPMC simulations will produce exactly the same results.
All operations that generate psuedorandom numbers use the seed set in the simulation. Whenever you add operations that utilize random numbers, you should set the seed to a non-default value.
Now you have a Simulation and a ConvexPolyhedron integrator, but can’t run the simulation yet. You first need to define the system state for the integrator to operate on. The next section in this tutorial will show you how to initialize the state.
Initializing the System State
Overview
Questions
How do I place particles in the initial condition?
What units does HOOMD-blue use?
Objectives
Describe the basic properties of the initial condition, including particle position, orientation, type and the periodic box.
Briefly describe HOOMD-blue’s system of units.
Demonstrate writing a system to a GSD file.
Show how to initialize Simulation state from a GSD file.
Boilerplate code
[1]:
import itertools
import math
import hoomd
import numpy
The render
function in the next (hidden) cell will render the initial condition using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Components of the system state
You need to initialize the system state before you can run a simulation. The initial condition describes the the position and orientation of every particle in the system and the periodic box at the start of the simulation.
The hard regular octahedra system self-assembles the the bcc structure. Self-assembly is a process where particles will organize themselves into an ordered structure at equilibrium. Most self-assembly studies run simulations of many thousands of particles for tens of hours. To keep this tutorial short, it simulations a small number of particles commensurate with the bcc structure (2 * m**3
, where m is an integer).
[4]:
m = 4
N_particles = 2 * m**3
Placing particles
In hard particle Monte Carlo, valid particle configurations have no overlaps. The octahedron particle in this tutorial sits inside a sphere of diameter 1, so place particles a little bit further than that apart on a KxKxK simple cubic lattice of width L. The following sections of this tutorial will demonstrate how to randomize this ordered configuration and compress it to a higher density.
[5]:
spacing = 1.2
K = math.ceil(N_particles**(1 / 3))
L = K * spacing
In HOOMD, particle positions must be placed inside a periodic box. Cubic boxes range from -L/2 to L/2. Use itertools and numpy to place the positions on the lattice in this range.
[6]:
x = numpy.linspace(-L / 2, L / 2, K, endpoint=False)
position = list(itertools.product(x, repeat=3))
print(position[0:4])
[(-3.5999999999999996, -3.5999999999999996, -3.5999999999999996), (-3.5999999999999996, -3.5999999999999996, -2.3999999999999995), (-3.5999999999999996, -3.5999999999999996, -1.1999999999999997), (-3.5999999999999996, -3.5999999999999996, 0.0)]
Filter this list down to N particles because K*K*K >= N_particles
.
[7]:
position = position[0:N_particles]
You also need to set the orientation for each particle. HOOMD represents orientations with quaternions. The quaternion (1, 0, 0, 0) represents no rotation. Set that for all particles:
[8]:
orientation = [(1, 0, 0, 0)] * N_particles
Here is what the system looks like now:
[9]:
render(position, orientation, L)
[9]:

Units
HOOMD-blue does not adopt any particular real system of units. Instead, HOOMD-blue uses an internally self-consistent system of units and is compatible with many systems of units. For example: if you select the units of meter, Joule, and kilogram for length, energy and mass then the units of force will be Newtons and velocity will be meters/second. A popular system of units for nano-scale systems is nanometers, kilojoules/mol, and atomic mass units.
In HPMC, the primary unit is that of length. Mass exists, but is factored out of the partition function and does not enter into the simulation. The scale of energy is irrelevant in athermal HPMC systems where overlapping energies are infinite and valid configurations have zero potential energy. However, energy does appear implicitly in derived units like \([\mathrm{pressure}] = \left(\frac{\mathrm{[energy]}}{\mathrm{[length]}^3}\right)\). In HPMC, \(kT\) is assumed to be 1 energy. You can convert a pressure \(P\) in HPMC’s units to a non-dimensional value with \(P^* = \frac{P\sigma^3}{kT}\) where \(\sigma\) is a representative length in your system, such as the particle’s diameter or edge length.
Writing the configuration to the file system
GSD files store the periodic box, particle positions, orientations, and other properties of the state. Use the GSD Python package to write this file.
[10]:
import gsd.hoomd
The Snapshot object stores the state of the system.
[11]:
snapshot = gsd.hoomd.Snapshot()
snapshot.particles.N = N_particles
snapshot.particles.position = position
snapshot.particles.orientation = orientation
Each particle also has a type. In HPMC, each type has its own shape parameters. There is a single type in this tutorial, so set a type id of 0 for all particles (type ids are 0-indexed):
[12]:
snapshot.particles.typeid = [0] * N_particles
Every particle type needs a name. Names can be any string. HOOMD-blue uses the type names to match the parameters you specify in operations with the type names present in the state. Give the name 'octahedron'
to the type id 0:
[13]:
snapshot.particles.types = ['octahedron']
GSD represents boxes with a 6-element array. Three box lengths L_x, L_y, L_z, and 3 tilt factors. Set equal box lengths 0 tilt factors to define a cubic box.
[14]:
snapshot.configuration.box = [L, L, L, 0, 0, 0]
Write this snapshot to lattice.gsd
:
[15]:
with gsd.hoomd.open(name='lattice.gsd', mode='xb') as f:
f.append(snapshot)
Initializing a Simulation
You can use the file to initialize the Simulation state. First, create a Simulation:
[16]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
Then use the create_state_from_gsd
factory function to read in the GSD file and populate the state with the particles and box from the file:
[17]:
sim.create_state_from_gsd(filename='lattice.gsd')
The next section in this tutorial will show you how to use HPMC to randomize the particle positions and orientations.
Randomizing the System
Overview
Questions
How can I generate a random initial condition?
Objectives
Show how to use HPMC to randomize the initial condition.
Demonstrate how to run a simulation.
Show how to use HPMC integrator properties to examine the acceptance ratio.
Explain that short simulations at low density effectively randomize the system.
Boilerplate code
[1]:
import math
import hoomd
The render
function in the next (hidden) cell will render a snapshot using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Method
The previous section of this tutorial placed all the particles on a simple cubic lattice. This is a convenient way to place non-overlapping particles, but it starts the simulation in a highly ordered state. You should randomize the the system enough so that it forgets this initial state and self-assembly can proceed without influence by the initial condition.
You cannot draw random numbers trivially for the particle positions, as that will result in overlaps between particles. Instead, start from the lattice and use HPMC to move particles randomly while ensuring that they do not overlap. In low density configurations, like the lattice generated in the previous section, a short simulation will quickly randomize the system.
Set up the simulation
The following code block creates the Simulation, configures the HPMC integrator, and initializes the system state from lattice.gsd
as has been discussed in previous sections in this tutorial:
[4]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=20)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
sim.create_state_from_gsd(filename='lattice.gsd')
Run the simulation
Save a snapshot of the current state of the system. This tutorial uses this later to see how far particles have moved.
[5]:
initial_snapshot = sim.state.get_snapshot()
Run the simulation to randomize the particle positions and orientations. The run
method takes the number of steps to run as an argument. 10,000 steps is enough to randomize a low density system:
[6]:
sim.run(10e3)
You can query properties of the HPMC integrator to see what it did. translate_moves
is a tuple with the number of accepted and rejected translation moves. The acceptance ratio, the fraction of attempted moves which are accepted, is very high at this low density.
[7]:
mc.translate_moves
[7]:
(2412359, 147260)
[8]:
mc.translate_moves[0] / sum(mc.translate_moves)
[8]:
0.9424680001203304
rotate_moves
similarly provides the number of accepted and rejected rotation moves.
[9]:
mc.rotate_moves
[9]:
(2489315, 71066)
[10]:
mc.rotate_moves[0] / sum(mc.rotate_moves)
[10]:
0.9722439746272137
overlaps
reports the number of overlapping particle pairs in the state. There are no overlaps in the final configuration:
[11]:
mc.overlaps
[11]:
0
The final configuration
Look at the final particle positions and orientations and see how they have changed:
[12]:
final_snapshot = sim.state.get_snapshot()
render(final_snapshot)
[12]:

[13]:
initial_snapshot.particles.position[0:4]
[13]:
array([[-3.5999999 , -3.5999999 , -3.5999999 ],
[-3.5999999 , -3.5999999 , -2.4000001 ],
[-3.5999999 , -3.5999999 , -1.20000005],
[-3.5999999 , -3.5999999 , 0. ]])
[14]:
final_snapshot.particles.position[0:4]
[14]:
array([[-0.34045062, -3.40372881, 0.97162443],
[ 0.37658316, 2.24546797, -1.57884474],
[ 2.89672535, -0.69444436, -3.18158696],
[-1.60254438, -1.12832378, -0.05738665]])
[15]:
initial_snapshot.particles.orientation[0:4]
[15]:
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
[16]:
final_snapshot.particles.orientation[0:4]
[16]:
array([[-0.1604707 , 0.00679003, 0.56703214, 0.80788464],
[ 0.30537333, 0.06005637, 0.66613445, -0.6777944 ],
[-0.83000904, -0.09179543, 0.40795323, -0.36909723],
[ 0.52359268, -0.49392678, -0.68970674, -0.07868712]])
The particle positions and orientations have indeed changed significantly, telling us that the system is well randomized.
Save the final configuration to a GSD file for use in the next stage of the simulation:
[17]:
hoomd.write.GSD.write(state=sim.state, mode='xb', filename='random.gsd')
The next section of the tutorial takes random.gsd
and compresses it down to a higher density.
Compressing the System
Overview
Questions
How do I compress the system to a target density?
What is a volume fraction?
Objectives
Show how to compute the volume fraction of a system.
Explain how how an Updater is an operation that modifies the system when its Trigger returns
True
.Demonstrate using the QuickCompress updater to achieve a target volume fraction.
Demonstrate using the MoveSize tuner to adjust the trial move size.
Boilerplate code
[1]:
import copy
import math
import hoomd
The render
function in the next (hidden) cell will render a snapshot using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Volume fraction
Self-assembly in hard particle systems typically occurs at a volume fraction above 0.5. The volume fraction is the ratio of the volume occupied by the particles to the volume of the periodic box.
So far, this tutorial as randomized a system of N octahedra in a box with a very low volume fraction and stored that in random.gsd
. Initialize a Simulation with this configuration and see what volume fraction it is at:
[4]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=20)
sim.create_state_from_gsd(filename='random.gsd')
Compute the volume of the octahedron:
[5]:
a = math.sqrt(2) / 2
V_particle = 1 / 3 * math.sqrt(2) * a**3
Compute the volume fraction:
[6]:
initial_volume_fraction = (sim.state.N_particles * V_particle
/ sim.state.box.volume)
print(initial_volume_fraction)
0.05715592589579699
As you can see, this volume fraction is very low and the box volume needs to be significantly reduced to achieve a volume fraction above 0.5.
Use HPMC to move particles into non-overlapping configurations while you compress the system. Set up the HPMC integrator for the octahedron simulations:
[7]:
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
The QuickCompress updater
An Updater is a type of operation in HOOMD-blue that makes changes to the state. To use an Updater, first instantiate the object, assign a Trigger, and add it to the Simulation. Simulation will apply the Updater on time steps where the Trigger returns True
. The Periodic trigger returns True
every period
steps.
QuickCompress is an Updater that works with HPMC to quickly compress the box to a target volume. When triggered, QuickCompress reduces the box volume by a scale factor, while allowing slight overlaps between the particles. It then waits for the translation and rotation trial moves to remove these overlaps before it reduces the volume again. This process temporarily produces invalid system configurations, but is much quicker than a process that does not allow temporary overlaps.
Compute the final box size with a volume fraction above 0.5 and configure a QuickCompress to trigger every 10 time steps.
[8]:
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box)
final_volume_fraction = 0.57
final_box.volume = sim.state.N_particles * V_particle / final_volume_fraction
compress = hoomd.hpmc.update.QuickCompress(trigger=hoomd.trigger.Periodic(10),
target_box=final_box)
Add the Updater to the Simulation:
[9]:
sim.operations.updaters.append(compress)
The MoveSize tuner
A Tuner is another type of operation. Tuners make changes to other operations to improve performance. In HPMC, the translation and rotation trial move sizes have a huge performance impact. When the move size is too small it takes many time steps to make appreciable changes to the system. When the move size is too large very few moves are accepted and it again takes many time steps to make appreciable changes. The system makes the most progress at moderate move sizes and, in
most cases, the optimal acceptance ratio is 20%. The MoveSize tuner monitors the acceptance ratio and adjusts d
and a
to achieve the target.
The optimal move size depends on the density of the system. QuickCompress changes the density rapidly during compression, so use the MoveSize tuner to adjust the move sizes regularly:
[10]:
periodic = hoomd.trigger.Periodic(10)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(moves=['a', 'd'],
target=0.2,
trigger=periodic,
max_translation_move=0.2,
max_rotation_move=0.2)
sim.operations.tuners.append(tune)
Run until complete
When the QuickCompress updater achieves the target box size and there are no overlaps between particles, the compression process is complete. The number of time steps needed to achieve this varies based on parameters. Check the compress.complete
property regularly and stop running the simulation when the compression completes:
[11]:
while not compress.complete and sim.timestep < 1e6:
sim.run(1000)
The sim.timestep < 1e6
check ensures that this while loop will not waste resources in cases where the compression will never complete. The loop should complete before that point:
[12]:
sim.timestep
[12]:
13000
Check to see if the compression completed successfully:
[13]:
if not compress.complete:
raise RuntimeError("Compression failed to complete")
The MoveSize tuner should have adjusted the move sizes to relatively small values at the final density:
[14]:
mc.a['octahedron']
[14]:
0.0573165403351847
[15]:
mc.d['octahedron']
[15]:
0.031253275743820426
Now that the compression is complete, the particles are much closer together and not overlapping, but still arranged randomly.
[16]:
render(sim.state.get_snapshot())
[16]:

Save the final configuration to a GSD file for use in the next stage of the simulation:
[17]:
hoomd.write.GSD.write(state=sim.state, mode='xb', filename='compressed.gsd')
Equilibrating the System
Overview
Questions
What is equilibration?
How do I save simulation results?
Objectives
Explain the process of equilibration.
Demonstrate using GSD to write the simulation trajectory to a file.
Demonstrate best practices for move size tuning using Before and And Triggers.
Boilerplate code
[1]:
import math
import hoomd
The render
function in the next (hidden) cell will render a snapshot using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Equilibration
So far, this tutorial has placed N non-overlapping octahedra randomly in a box and then compressed it to a moderate volume fraction. The resulting configuration of particles is valid, but strongly dependent on the path taken to create it. There are many more equilibrium configurations in the set of possible configurations that do not depend on the path. Equilibrating the system is the process of taking an artificially prepared state and running a simulation. During the simulation run, the system will relax to equilibrium. Initialize the Simulation first:
[4]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=20)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
The previous section of this tutorial wrote the compressed system to compressed.gsd
. Initialize the system state from this file:
[5]:
sim.create_state_from_gsd(filename='compressed.gsd')
Writing simulation trajectories
Save the system state to a file periodically so that you can observe the equilibration process. This tutorial previously used GSD files to store a single frame of the system state using either the GSD Python package or GSD.write
. The GSD Writer (another operation) will create a GSD file with many frames in a trajectory.
We use the 'xb'
mode to open the file to ensure that the file does not exist before opening it. If the file does exist an error will be raised rather than overwriting or appending to the file.
[6]:
gsd_writer = hoomd.write.GSD(filename='trajectory.gsd',
trigger=hoomd.trigger.Periodic(1000),
mode='xb')
sim.operations.writers.append(gsd_writer)
Tuning the trial move size
The previous section used the MoveSize tuner regularly during compression to adjust d
and a
to achieve a target acceptance ratio while the system density changed rapidly. Use it again during the equilibration run to ensure that HPMC is working optimally.
Move sizes should be tuned briefly at the beginning, then left constant for the duration of the run. Changing the move size throughout the simulation run violates detailed balance and can lead to incorrect results. Trigger the tuner every 100 steps but only for the first 5000 steps of the simulation by combining a Periodic and Before trigger with an And operation. Before returns True
for all time steps t < value
and the And trigger returns True
when all
of its child triggers also return True
.
[7]:
tune = hoomd.hpmc.tune.MoveSize.scale_solver(
moves=['a', 'd'],
target=0.2,
trigger=hoomd.trigger.And([
hoomd.trigger.Periodic(100),
hoomd.trigger.Before(sim.timestep + 5000)
]))
sim.operations.tuners.append(tune)
[8]:
sim.run(5000)
Check the acceptance ratios over the next 100 steps to verify that the tuner achieved the target acceptance ratios:
[9]:
sim.run(100)
[10]:
rotate_moves = mc.rotate_moves
mc.rotate_moves[0] / sum(mc.rotate_moves)
[10]:
0.18988232534500957
[11]:
translate_moves = mc.translate_moves
mc.translate_moves[0] / sum(mc.translate_moves)
[11]:
0.1901174817532493
Equilibrating the system
To equilibrate the system, run the simulation. The length of the run needed is strongly dependent on the particular model, the system size, the density, and many other factors. Hard particle Monte Carlo self-assembly often takes tens of millions of time steps for systems with ~10,000 particles. This system is much smaller, so it takes fewer steps.
This cell may require several minutes to complete.
[12]:
sim.run(1e5)
Here is the final state of the system after the run.
[13]:
render(sim.state.get_snapshot())
[13]:

Is the final state an equilibrium state? The next section in this tutorial shows you how to analyze the trajectory and answer this question.
Analyzing Trajectories
Overview
Questions
How can I analyze trajectories?
Objectives
Describe how to access trajectory frames in GSD.
Examine the trajectory with freud and fresnel.
Boilerplate code
[1]:
import math
import fresnel
import freud
import gsd.hoomd
import matplotlib
%matplotlib inline
matplotlib.style.use('ggplot')
The render
function in the next (hidden) cell will render a snapshot using fresnel. render_movie
will render a sequence of frames as an animated GIF. These methods accept a particles argument that filters out which particles to display.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Equilibration challenges
In the previous section, you ran the hard octahedra system for many time steps to equilibrate it and saved the trajectory in trajectory.gsd
. Is the final state you obtained actually an equilibrium state? Statistical mechanics tells us that as long as our system is ergodic it will eventually achieve equilibrium. You need to analyze this trajectory to determine if you have achieved the ordered equilibrium structure.
Tools
There are many tools that can read GSD files and analyze or visualize the simulations, and many more Python packages that can work with the numerical data. This tutorial will show you how to use freud to determine which particles are in a solid-like environment and fresnel to render system configurations. The freud Python package provides a simple, flexible, powerful set of tools for analyzing trajectories obtained from molecular dynamics or Monte Carlo simulations. The fresnel Python package produces publication quality renders with soft lighting, depth of field and other effects.
While outside the scope of this tutorial, you might want to use tools such as OVITO or VMD to visualize the trajectory interactively. OVITO has built-in support for GSD files. The gsd-vmd plugin adds support to VMD.
Read the trajectory
Use GSD to open the trajectory generated by the previous section of this tutorial.
[3]:
traj = gsd.hoomd.open('trajectory.gsd')
You can index into the frames of the trajectory like a list. See how many frames exist in the trajectory:
[4]:
len(traj)
[4]:
105
Ergodicity
A system is ergodic when it can explore all possible states by making small moves from one to another. In HPMC simulations, low volume fraction simulations are ergodic while very high volume fraction ones are not. At high volume fractions, there isn’t enough free space for the particles to rearrange so they get stuck in local configurations.
Visualize the motion of just a few particles to see if they appear stuck or if they are freely moving about the box:
[5]:
render_movie(traj[0:50:5], particles=[12, 18])

Good! Over the first part of the simulation (while the system is still fluid), individual particles are able to move a significant distance and explore many different orientations. This indicates that our system is ergodic.
Simulation length
How can you tell if you have run long enough to equilibrate the system? The hard octahedra system forms the bcc structure by nucleation and growth. Nucleation is a rare event, so you need to keep running the simulation until it occurs. If you ran this simulation many times with different random seeds, each would take a different number of steps to nucleate. You need to examine the simulation trajectory in detail to determine if you have run it long enough.
[6]:
render_movie(traj[0:100:12])

Can you see the system ordering? The orientations of the octahedra appear to quickly snap to face the same direction and the particle positions line up on evenly spaced planes. You can use freud’s SolidLiquid analysis method to quantitatively identify which particles are in the solid structure.
Loop over all of the frames in the file and create a boolean array that indicates which particles are in a solid environment:
[7]:
solid = freud.order.SolidLiquid(l=6, q_threshold=0.7, solid_threshold=6)
is_solid = []
for frame in traj:
solid.compute(system=(frame.configuration.box, frame.particles.position),
neighbors=dict(mode='nearest', num_neighbors=8))
is_solid.append(solid.num_connections > solid.solid_threshold)
Plot the total number of particles in a solid environment over time:
[8]:
fig = matplotlib.figure.Figure(figsize=(10, 6.18))
ax = fig.add_subplot()
num_solid = numpy.array([numpy.sum(a) for a in is_solid])
ax.plot(num_solid)
ax.set_xlabel('frame')
ax.set_ylabel('number of particles in a solid environment')
fig
[8]:

This plot confirms what you saw visually and what you should expect in a system that nucleates and grows a crystal. There is no solid at the beginning of the simulation. Then a solid cluster forms and grows quickly to fill the box.
Visualize just the solid particles to see this more clearly:
[9]:
start_frame = int(numpy.argmax(num_solid > 4))
end_frame = int(numpy.argmax(num_solid == numpy.max(num_solid)))
step = int((end_frame - start_frame) / 6)
render_movie(traj[start_frame:end_frame:step],
is_solid=is_solid[start_frame:end_frame:step])

This is the end of the first tutorial! It covered the core HOOMD-blue objects, described hard particle Monte Carlo simulations, and demonstrated how to initialize, randomize, compress, equilibrate, and analyze a system of self-assembling hard octahedra. See the other HOOMD-blue tutorials to learn about other concepts, or browse the reference documentation for more information.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Introducing Molecular Dynamics
This tutorial introduces the molecular dynamics simulation in HOOMD-blue using the Lennard-Jones system as an example.
Prerequisites:
This tutorial assumes you are familiar with the concepts taught in the tutorial Introducing HOOMD-blue and have some background knowledge on statistical mechanics.
Molecular Dynamics Simulations
Overview
Questions
What is molecular dynamics?
How do I set up a molecular dynamics simulation in HOOMD-blue?
Objectives
Describe the equations of motion of the system and HOOMD-blue solves them with time steps.
Define forces, potential energy and explain how HOOMD-blue evaluates pair potentials within a cutoff.
Explain how the MD Integrator and integration methods solve the equations of motion and allow for different thermodynamic ensembles.
Boilerplate code
[1]:
import hoomd
import matplotlib
import numpy
%matplotlib inline
matplotlib.style.use('ggplot')
Equations of motion
Molecular dynamics simulations model the movement of particles over time by solving the equations of motion numerically, advancing the state of the system forward by time dt
on each time step. You can use molecular dynamics to model dynamic, time dependent processes (like fluid flow) or thermodynamic equilibrium states (like crystals). This tutorial models a system of Lennard-Jones particles crystallizing.
The Integrator class in the md package implements molecular dynamics integration in HOOMD-blue:
[2]:
integrator = hoomd.md.Integrator(dt=0.005)
The dt
property sets the step size \(\Delta t\):
[3]:
integrator.dt
[3]:
0.005
Forces
The force term in the equations of motion determines how particles interact. The forces
Integrator property is the list of forces applied to the system. The default is no forces:
[4]:
integrator.forces[:]
[4]:
[]
You can add any number of Force objects to this list. Each will compute forces on all particles in the system state. Integrator will add all of the forces together into the net force used in the equations of motion.
HOOMD-blue provides a number of forces that are derived from potential energy. Pair potentials define the functional form of the potential energy between a single pair of particles given their separation distance r. The Lennard-Jones potential is:
[5]:
sigma = 1
epsilon = 1
r = numpy.linspace(0.95, 3, 500)
V_lj = 4 * epsilon * ((sigma / r)**12 - (sigma / r)**6)
fig = matplotlib.figure.Figure(figsize=(10, 6.18))
ax = fig.add_subplot()
ax.plot(r, V_lj)
ax.set_xlabel('r')
ax.set_ylabel('V')
fig
[5]:

While pair potentials are nominally defined between all pairs of particles, Molecular dynamics simulations evaluate short ranged pair potentials only for \(r \lt r_{\mathrm{cut}}\) to make the computation fast through the use of a neighbor list. By default, HOOMD-blue introduces a discontinuity in V at \(r=r_{\mathrm{cut}}\), though there are options to shift or smooth the potential at the cutoff.
HOOMD-blue provides several neighbor list options to choose from. Cell performs well in most situations. The buffer
parameter sets an extra distance to include in the neighbor list, so it can be used for multiple timesteps without recomputing neighbors. Choose a value that minimizes the time to execute your simulation.
[6]:
cell = hoomd.md.nlist.Cell(buffer=0.4)
Construct the LJ pair force object to compute the Lennard-Jones interactions:
[7]:
lj = hoomd.md.pair.LJ(nlist=cell)
Pair potentials accept parameters for every pair of particle types in the simulation. Define a single A-A interaction for this tutorial:
[8]:
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
Add the force to the Integrator:
[9]:
integrator.forces.append(lj)
Now, the Integrator will compute the net force term using the Lennard-Jones pair force.
Integration methods
HOOMD-blue provides a number of integration methods, which define the equations of motion that apply to a subset of the particles in the system. These methods are named after the thermodynamic ensemble they implement. For example, NVE implements Newton’s laws while NVT adds a thermostat degree of freedom so the system will sample the canonical ensemble.
Lennard-Jones particles crystallize readily at constant temperature and volume. One of the points in the solid area of the phase diagram is \(kT=1.5\) at a number density \(\rho=1.2\) Apply the NVT method all particles to set the constant temperature (later sections in this tutorial will set the density):
[10]:
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
kT
is the temperature multiplied by Boltzmann’s constant and has units of energy. tau
is a time constant that controls the amount of coupling between the thermostat and particle’s degrees of freedom. filter
is a particle filter object that selects which particles this integration method applies to. You can apply multiple integration methods to different sets of particles or leave some particles fixed.
Add the method to the Integrator:
[11]:
integrator.methods.append(nvt)
Now, you have defined a molecular dynamics integrator with a step size dt
that will use the NVT integration method on all particles interacting via the Lennard-Jones potential.
The remaining sections in this tutorial will show you how to initialize a random low density state, compress the system to a target density, and run the simulation long enough to self-assemble an ordered state.
Initializing a Random System
Overview
Questions
How can I generate a random initial condition?
What units does HOOMD-blue use?
Objectives
Describe the units HOOMD employs in molecular dynamics simulations.
Demonstrate how to place particles on an initial lattice and randomize the configuration with an MD simulation.
Explain why initial random velocities are important when using the NVT integration method.
Show how to use ThermodynamicQuantities to compute properties of the system.
Address the difference between kinetic temperature and temperature.
Boilerplate code
[1]:
import itertools
import math
import gsd.hoomd
import hoomd
import numpy
The render
function in the next (hidden) cell will render the system state using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Procedure
One effective way to initialize a random configuration of particles is to start with a low density non-overlapping configuration and run a simulation that compresses the system to the target density. This section of the tutorial will place particles on a simple cubic lattice and run a short simulation allowing them to relax into the fluid state.
Units
You need to know what system of units HOOMD-blue uses so that you can place particles at appropriate separations in the initial configuration.
HOOMD-blue does not adopt any particular real system of units. Instead, HOOMD-blue uses an internally self-consistent system of units and is compatible with many systems of units. For example: if you select the units of meter, Joule, and kilogram for length, energy and mass then the units of force will be Newtons and velocity will be meters/second. A popular system of units for nano-scale systems is nanometers, kilojoules/mol, and atomic mass units.
In molecular dynamics, the primary units are length, energy, and mass. Other units are derived from these, for example \([\mathrm{pressure}] = \left(\frac{\mathrm{[energy]}}{\mathrm{[length]}^3}\right)\) and \([\mathrm{time}] = \sqrt{\frac{\mathrm{[mass]}\cdot\mathrm{[length]}^2}{\mathrm{[energy]}}}\). Some quantities involve physical constants as well, such as charge which has units of \(\sqrt{4\pi\epsilon_0\cdot\mathrm{[length]}\cdot\mathrm{[energy]}}\) (where \(\epsilon_0\) is the permittivity of free space), and thermal energy \(kT\) (where k is Boltzmann’s constant). HOOMD-blue never uses the temperature T directly. Instead it always appears indirectly in the value \(kT\) which has units of energy.
HOOMD-blue does not perform unit conversions. You provide all parameters in this system of units and all outputs will be given in these units. The documentation for each property and parameter will list the units. For the parameters set in this tutorial so far, the integrator’s dt
is in time units, the pair potentials epsilon
is in energy units while sigma
and r_cut
are in length units.
You can interpret these values in the nano-scale units mentioned previously:
Unit |
Value |
---|---|
[length] |
nanometer |
[energy] |
kilojoules/mol |
[mass] |
atomic mass unit |
[time] |
picoseconds |
[volume] |
cubic nanometers |
[velocity] |
nm/picosecond |
[momentum] |
amu nm/picosecond |
[acceleration] |
nm/picosecond^2 |
[force] |
kilojoules/mol/nm |
[pressure] |
kilojoules/mol/nm^3 |
k |
0.0083144626181532 kJ/mol/Kelvin |
For example, the values used in this tutorial could represent a system with 1 nanometer diameter particles that interact with a well depth of 1 kilojoule/mol at a thermal energy pf 1.5 kilojoules/mol (which implies \(T \approx 180\) Kelvin).
Initial condition
The Lennard-Jones system self-assembles the the fcc structure at moderately high densities. To keep this tutorial’s run time short, it simulates a small number of particles commensurate with the fcc structure (4 * m**3
, where m is an integer).
[4]:
m = 4
N_particles = 4 * m**3
In molecular dynamics, particles can theoretically have any position in the periodic box. However, the steepness of the Lennard-Jones potential near \(r \approx \sigma\) leads to extremely large forces that destabilize the numerical integration method. Practically, you need to choose an initial condition with particles where their hard cores do not overlap. The Lennard-Jones potential used in this tutorial represents a sphere with diameter ~1, so place particles a little bit further than that apart on a KxKxK simple cubic lattice of width L. Later, this section will run an MD simulation allowing the particles to expand and fill the box randomly.
This is the same code you used in Introducing HOOMD-blue tutorial. See that tutorial for a more detailed description.
[5]:
spacing = 1.3
K = math.ceil(N_particles**(1 / 3))
L = K * spacing
x = numpy.linspace(-L / 2, L / 2, K, endpoint=False)
position = list(itertools.product(x, repeat=3))
snapshot = gsd.hoomd.Snapshot()
snapshot.particles.N = N_particles
snapshot.particles.position = position[0:N_particles]
snapshot.particles.typeid = [0] * N_particles
snapshot.configuration.box = [L, L, L, 0, 0, 0]
The single particle type needs a name. Call it A because it is short and the first letter of the alphabet:
[6]:
snapshot.particles.types = ['A']
Here is what the system looks like now:
[7]:
render(snapshot)
[7]:

Write this snapshot to lattice.gsd
:
[8]:
with gsd.hoomd.open(name='lattice.gsd', mode='xb') as f:
f.append(snapshot)
Initialize the simulation
Configure this simulation to run on the CPU:
[9]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=1)
sim.create_state_from_gsd(filename='lattice.gsd')
The simulation seed will be used when randomizing velocities later in the notebook.
Set up the molecular dynamics simulation, as discussed in the previous section of this tutorial:
[10]:
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
Assign the integrator to the simulation:
[11]:
sim.operations.integrator = integrator
Setting random velocities
In HOOMD-blue, velocities default to 0:
[12]:
snapshot = sim.state.get_snapshot()
snapshot.particles.velocity[0:5]
[12]:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
When using the NVT integration method, you must specify non-zero initial velocities. NVT modifies particle velocities by a scale factor so it cannot scale a zero velocity to a non-zero one. The thermalize_particle_momenta
method will assign Gaussian distributed velocities consistent with the the canonical ensemble. It also sets the velocity of the center of mass to 0:
[13]:
sim.state.thermalize_particle_momenta(filter=hoomd.filter.All(), kT=1.5)
You can inspect the snapshot to see the changes that thermalize_particle_momenta
produced. Use the ThermodynamicQuantities class to compute properties of the system:
[14]:
thermodynamic_properties = hoomd.md.compute.ThermodynamicQuantities(
filter=hoomd.filter.All())
ThermodynamicQuantities is a Compute, an Operation that computes properties of the system state. Some computations can only be performed during or after a simulation run has started. Add the compute to the operations list and call run(0)
to make all all properties available without changing the system state:
[15]:
sim.operations.computes.append(thermodynamic_properties)
sim.run(0)
There are \((3 N_{\mathrm{particles}} - 3)\) degrees of freedom in the system. The NVT integration method conserves linear momentum, so the - 3
accounts for the effectively pinned center of mass.
[16]:
thermodynamic_properties.degrees_of_freedom
[16]:
765.0
Following the equipartition theorem, the average kinetic energy of the system should be approximately \(\frac{1}{2}kTN_{\mathrm{dof}}\).
[17]:
1 / 2 * 1.5 * thermodynamic_properties.degrees_of_freedom
[17]:
573.75
[18]:
thermodynamic_properties.kinetic_energy
[18]:
566.7599495184154
Why isn’t this exactly equal? Doesn’t this kinetic energy correspond to a different temperature than was set?
[19]:
thermodynamic_properties.kinetic_temperature
[19]:
1.4817253582180794
No, it doesn’t. The instantaneous kinetic temperature \(T_k\) (\(kT_k\) in energy units here) of a finite number of particles fluctuates! The canonical ensemble holds the number of particles, volume, and the thermodynamic temperature constant. Other thermodynamic quantities like kinetic energy (and thus kinetic temperature) will fluctuate about some average. Both that average and the scale of the fluctuations are well defined by statistical mechanics.
Run the simulation
Run the simulation forward in time to randomize the particle positions. As the simulation progresses, it will move from the initial highly ordered state to a random fluid that fills the box.
[20]:
sim.run(10000)
Here is the final random configuration of particles:
[21]:
render(sim.state.get_snapshot())
[21]:

[22]:
thermodynamic_properties.kinetic_energy
[22]:
565.9683492727562
Here, you can see that the instantaneous kinetic energy of the system has taken on a different value. Depending on the random number seed and other conditions when this notebook runs, this value may be smaller or larger than the expected average value, but it should remain relatively close to the expected average.
Now, you’ve created an initial random configuration of Lennard-Jones particles in a low density fluid. Save the final configuration to a GSD file for use in the next stage of the simulation:
[23]:
hoomd.write.GSD.write(state=sim.state, filename='random.gsd', mode='xb')
The next section of this tutorial will compress this initial condition to a higher density where it will assemble an ordered structure.
Compressing the System
Overview
Questions
How do I compress the system to a target density?
Objectives
Describe how Variants describe values that vary with the timestep.
Show how to use BoxResize with a Ramp variant to slowly compress the system to the target volume.
Demonstrate the crystallization of Lennard-Jones particles
Boilerplate code
[1]:
import math
import fresnel
import hoomd
import matplotlib
%matplotlib inline
matplotlib.style.use('ggplot')
The render
function in the next (hidden) cell will render the system state using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Procedure
random.gsd
, generated by the previous section of this tutorial has particles randomly placed in a low density fluid state. To find the crystalline state, you need to compress the system to a higher density. If you were to immediately scale the system to the target density, the particle’s hard cores would overlap and the integrator would be become unstable. A more effective strategy gradually resizes the simulation box a little at a time over the course of a simulation, allowing any slight
overlaps to relax.
Initialize the simulation
Configure this simulation to run on the CPU.
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
sim.create_state_from_gsd(filename='random.gsd')
Set up the molecular dynamics simulation, as discussed in the previous sections of this tutorial:
[4]:
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
Variants
The BoxResize class performs scales the simulation box. You provide a Variant that tells BoxResize how to interpolate between two boxes, box1
and box2
, over time. A Variant is a scalar-valued function of the simulation timestep. BoxResize sets box1
when the function is at its minimum, box2
when the function is at its maximum, and linearly interpolates between the two boxes for intermediate values.
Use the Ramp variant to define a function that ramps from one value to another over a given number of steps. Note that this simulation does not start at timestep 0, random.gsd
was saved after running a number of steps to randomize the system in the previous section:
[5]:
sim.timestep
[5]:
10000
Create a Ramp that starts at this step and ends 100,000 steps later:
[6]:
ramp = hoomd.variant.Ramp(A=0, B=1, t_start=sim.timestep, t_ramp=20000)
Here is what the ramp looks like as a function of timestep:
[7]:
steps = range(0, 40000, 20)
y = [ramp(step) for step in steps]
fig = matplotlib.figure.Figure(figsize=(10, 6.18))
ax = fig.add_subplot()
ax.plot(steps, y)
ax.set_xlabel('timestep')
ax.set_ylabel('ramp')
fig
[7]:

Gradually resize the simulation box
Now, you need to determine the initial simulation box box1
and final simulation box at the target density box2
. This is the initial number density \(\rho\) of the current simulation box:
[8]:
rho = sim.state.N_particles / sim.state.box.volume
rho
[8]:
0.3397157902913389
Create a new Box at the target number density:
[9]:
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box) # make a copy of initial_box
final_rho = 1.2
final_box.volume = sim.state.N_particles / final_rho
To avoid destabilizing the integrator with large forces due to large box size changes, scale the box with a small period.
[10]:
box_resize_trigger = hoomd.trigger.Periodic(10)
Construct the BoxResize updater and add it to the simulation.
[11]:
box_resize = hoomd.update.BoxResize(box1=initial_box,
box2=final_box,
variant=ramp,
trigger=box_resize_trigger)
sim.operations.updaters.append(box_resize)
Run the simulation to compress the box.
[12]:
sim.run(10001)
At the half way point of the ramp, the variant is 0.5 and the current box lengths are half way between the initial and final ones:
[13]:
ramp(sim.timestep - 1)
[13]:
0.5
[14]:
current_box = sim.state.box
(current_box.Lx - initial_box.Lx) / (final_box.Lx - initial_box.Lx)
[14]:
0.5
Finish the rest of the compression:
[15]:
sim.run(10000)
The current box matches the final box:
[16]:
sim.state.box == final_box
[16]:
True
The system is at a higher density:
[17]:
render(sim.state.get_snapshot())
[17]:

Now that the system has reached the target volume, remove the BoxResize updater from the simulation:
[18]:
sim.operations.updaters.remove(box_resize)
Equilibrating the system
Run the simulation for a longer time and see if it self assembles the ordered fcc structure:
This cell may require several minutes to complete.
[19]:
sim.run(5e5)
Here is what the final state of the system looks like:
[20]:
render(sim.state.get_snapshot())
[20]:

Analyzing the simulation results
Is this the fcc structure? Did the system reach equilibrium? These are topics covered in the Introducing HOOMD-blue tutorial. Consider it an exercise to modify this example and implement that analysis here. You will need to save a GSD file with the simulation trajectory, then use freud’s SolidLiquid order parameter to identify when the ordered structure appears.
This is the end of the introducing molecular dynamics tutorial! It described molecular dynamics simulations, demonstrated how to initialize, randomize, compress, and equilibrate a system of Lennard-Jones particles. See the other HOOMD-blue tutorials to learn about other concepts, or browse the reference documentation for more information.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Logging
This tutorial explains how to log quantities computed during the simulation.
Prerequisites:
While logging is a general topic, this tutorial uses MD and HPMC simulations to demonstrate. The tutorials Introducing HOOMD blue and Introducing Molecular Dynamics teach these concepts.
Logging to a GSD file
Overview
Questions
What is a Logger?
How can I write thermodynamic and other quantities to a file?
How can I access that data?
Objectives
Describe and give examples of loggable quantities.
Show how to add quantities to a Logger.
Demonstrate GSD as a log writer.
Explain how to read logged quantities from GSD files.
Describe how namespaces appear in the names of the logged quantities.
Boilerplate code
[1]:
import gsd.hoomd
import hoomd
import matplotlib
%matplotlib inline
matplotlib.style.use('ggplot')
Introduction
HOOMD separates logging into three parts: Loggable quantities, the Logger class, and Writers.
Loggable quantities are values computed during a simulation.
The Logger class provides a way to collect and name quantities of interest.
Writers write these values out in a format you can use.
In this section, you will use the GSD Writer to capture the values of quantities during a simulation run for later analysis.
Define the Simulation
This tutorial executes the Lennard-Jones particle simulation from a previous tutorial. See Introducing Molecular Dyamics for a complete description of this code.
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
sim.run(0)
Loggable quantities
Many classes in HOOMD-blue provide special properties called loggable quantities. For example, the Simulation class provides timestep
, tps
, and others. The reference documentation labels each of these as Loggable. You can also examine the loggables
property to determine the loggable quantities:
[4]:
sim.loggables
[4]:
{'timestep': 'scalar',
'seed': 'scalar',
'tps': 'scalar',
'walltime': 'scalar',
'final_timestep': 'scalar'}
The ThermodynamicQuantities class computes a variety of thermodynamic properties in MD simulations. These are all loggable.
[5]:
thermodynamic_properties = hoomd.md.compute.ThermodynamicQuantities(
filter=hoomd.filter.All())
sim.operations.computes.append(thermodynamic_properties)
thermodynamic_properties.loggables
[5]:
{'kinetic_temperature': 'scalar',
'pressure': 'scalar',
'pressure_tensor': 'sequence',
'kinetic_energy': 'scalar',
'translational_kinetic_energy': 'scalar',
'rotational_kinetic_energy': 'scalar',
'potential_energy': 'scalar',
'degrees_of_freedom': 'scalar',
'translational_degrees_of_freedom': 'scalar',
'rotational_degrees_of_freedom': 'scalar',
'num_particles': 'scalar',
'volume': 'scalar'}
Loggable quantities are class properties or methods. You can directly access them in your code.
[6]:
sim.timestep
[6]:
10000
[7]:
thermodynamic_properties.kinetic_temperature
[7]:
1.4796558111045974
Each loggable quantity has a category, which is listed both in the reference documentation and in loggables
. The category is a string that identifies the quantity’s type or category. Example categories include: * scalar
- numbers * sequence
- arrays of numbers * string
- strings of characters * particle
- arrays of per-particle values
Add quantities to a Logger
Add each of the quantities you would like to store to a Logger. The Logger will maintain these quantities in a list and provide them to the Writer when needed.
[8]:
logger = hoomd.logging.Logger()
You can add loggable quantities from any number of objects to a Logger. Logger uses the namespace of the class to assign a unique name for each quantity. Call add
to add all quantities provided by thermodynamic_properties
:
[9]:
logger.add(thermodynamic_properties)
You can also select specific quantities to add with the quantities
argument. Add only the timestep
and walltime
quantities from Simulation:
[10]:
logger.add(sim, quantities=['timestep', 'walltime'])
Writing log quantities to a GSD file
GSD files always store trajectories of particle properties. Set the log
attribute and GSD will also store the selected quantities.
You can store only the logged quantities by using the Null filter to select no particles for the trajectory. This way, you can log thermodynamic properties at a high rate and keep the file size small.
[11]:
gsd_writer = hoomd.write.GSD(filename='log.gsd',
trigger=hoomd.trigger.Periodic(1000),
mode='xb',
filter=hoomd.filter.Null())
sim.operations.writers.append(gsd_writer)
Assign the logger to include the logged quanties in the GSD file:
[12]:
gsd_writer.log = logger
The writer triggers and writes to the log file when the simulation runs:
[13]:
sim.run(100000)
Reading logged data from a GSD file
You need to close the GSD file that gsd_writer
has open before you can read it. The following code block deletes the simulation and operations manually so that it is safe to open the file for reading later in this notebook.
In typical workflows, you will run separate simulation and analysis scripts and the GSD file will be closed when your simulation script exits.
[14]:
del sim, gsd_writer, thermodynamic_properties, logger
del integrator, nvt, lj, cell, cpu
Use the gsd
package to open the file:
[15]:
traj = gsd.hoomd.open('log.gsd', 'rb')
Each frame in the trajectory has a log
dictionary that maps quantity names to values. Inspect this dictionary in the first frame:
[16]:
traj[0].log
[16]:
{'md/compute/ThermodynamicQuantities/kinetic_temperature': array([1.48311699]),
'md/compute/ThermodynamicQuantities/pressure': array([0.51801307]),
'md/compute/ThermodynamicQuantities/pressure_tensor': array([ 0.57363457, 0.0193231 , -0.00974054, 0.44857891, 0.14908453,
0.53182573]),
'md/compute/ThermodynamicQuantities/kinetic_energy': array([567.29224759]),
'md/compute/ThermodynamicQuantities/translational_kinetic_energy': array([567.29224759]),
'md/compute/ThermodynamicQuantities/rotational_kinetic_energy': array([0.]),
'md/compute/ThermodynamicQuantities/potential_energy': array([-528.13490623]),
'md/compute/ThermodynamicQuantities/degrees_of_freedom': array([765.]),
'md/compute/ThermodynamicQuantities/translational_degrees_of_freedom': array([765.]),
'md/compute/ThermodynamicQuantities/rotational_degrees_of_freedom': array([0.]),
'md/compute/ThermodynamicQuantities/num_particles': array([256]),
'md/compute/ThermodynamicQuantities/volume': array([753.57109477]),
'Simulation/timestep': array([11000]),
'Simulation/walltime': array([0.227067])}
The dictionary keys are verbose names that include the namespace of the class which computed the quantity, where .
has been replaced with /
. For example, access the potential energy computed by ThermodynamicQuantities with the key md/compute/ThermodynamicQuantities/potential_energy
.
[17]:
traj[0].log['md/compute/ThermodynamicQuantities/potential_energy']
[17]:
array([-528.13490623])
GSD stores all quantities in arrays. It stores scalar quantities such as the system potential energy in length 1 arrays (above) while it stores vector and other array quantities as appropriately sized arrays:
[18]:
traj[0].log['md/compute/ThermodynamicQuantities/pressure_tensor']
[18]:
array([ 0.57363457, 0.0193231 , -0.00974054, 0.44857891, 0.14908453,
0.53182573])
GSD provides logged quantities individually at each frame in the file. You can convert this to time-series data with a loop and then plot or analyze it:
[19]:
timestep = []
walltime = []
potential_energy = []
for frame in traj:
timestep.append(frame.configuration.step)
walltime.append(frame.log['Simulation/walltime'][0])
potential_energy.append(
frame.log['md/compute/ThermodynamicQuantities/potential_energy'][0])
[20]:
fig = matplotlib.figure.Figure(figsize=(10, 6.18))
ax = fig.add_subplot()
ax.plot(timestep, potential_energy)
ax.set_xlabel('timestep')
ax.set_ylabel('potential energy')
fig
[20]:

In this section, you have logged quantities to a GSD file during a simulation run and analyzed that data as a time series. The next section of this tutorial shows you how to save per-particle quantities associated with specific system configurations.
Saving Array Quantities
Overview
Questions
How can I save per-particle quantities for later analysis?
How can I access that data?
Objectives
Show how to log per-particle properties to a GSD file.
Explain how to read logged quantities from a GSD file.
Mention that OVITO reads these quantities.
Boilerplate code
[1]:
import gsd.hoomd
import hoomd
import matplotlib
import numpy
%matplotlib inline
matplotlib.style.use('ggplot')
The render
function in the next (hidden) cell will render the system state using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Array quantities
You logged a 6-element array quantity in the previous section, the pressure tensor. You can also log larger arrays and per-particle quantities (e.g. energy and force) in a GSD file along with the trajectory. Then you can use utilize the data in your analysis and visualization workflow, such as using OVITO to color particles by energy or display force vectors. When using OVITO, open the GSD file and all logged quantities will be available in the inspector and for use in the pipeline.
Define the Simulation
This tutorial executes the Lennard-Jones particle simulation from a previous tutorial. See Introducing Molecular Dyamics for a complete description of this code.
[4]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
sim.run(0)
Logging per-particle quantities
MD forces provide a number of loggable quantities including their contribution to the system energy, but also per-particle energy contributions (in energies
) and per-particle forces, torques, and virials.
[5]:
lj.loggables
[5]:
{'energy': 'scalar',
'energies': 'particle',
'additional_energy': 'scalar',
'forces': 'particle',
'torques': 'particle',
'virials': 'particle',
'additional_virial': 'sequence'}
Add the per-particle LJ energies and forces to a logger:
[6]:
logger = hoomd.logging.Logger()
logger.add(lj, quantities=['energies', 'forces'])
Writing per-particle quantities to a GSD file
In the previous section, you used the Null filter to produce GSD file with only logged data. In this section, include all particles so that you can associate logged per-particle quantities with the particle properties.
[7]:
gsd_writer = hoomd.write.GSD(filename='trajectory.gsd',
trigger=hoomd.trigger.Periodic(10000),
mode='xb',
filter=hoomd.filter.All(),
log=logger)
sim.operations.writers.append(gsd_writer)
Run the simulation:
[8]:
sim.run(100000)
As discussed in the previous section, delete the simulation so it is safe to open the GSD file for reading in the same process.
[9]:
del sim, gsd_writer, logger, integrator, nvt, lj, cell, cpu
Reading logged data from a GSD file
Use the gsd
package to open the file:
[10]:
traj = gsd.hoomd.open('trajectory.gsd', 'rb')
GSD prepends particles/
to the logged name of per-particle quantities:
[11]:
traj[0].log.keys()
[11]:
dict_keys(['particles/md/pair/LJ/energies', 'particles/md/pair/LJ/forces'])
The quantities are numpy arrays with N_particles
elements. Here are a few slices:
[12]:
traj[-1].log['particles/md/pair/LJ/energies'][0:10]
[12]:
array([-3.39840884, -2.03033218, -3.15903353, -2.30211083, -0.97440217,
-2.66465184, -1.63920762, -0.29580836, -1.14112247, -1.36468275])
[13]:
traj[-1].log['particles/md/pair/LJ/forces'][0:10]
[13]:
array([[ 1.44681031, 2.01198357, 1.0663342 ],
[ 0.63208369, 0.6460156 , 2.66476508],
[-6.49972295, 1.1223018 , -2.62407767],
[-9.1854849 , 16.68038846, -2.25596829],
[-0.22897598, -2.50517732, 0.39782844],
[-4.04538785, -5.33049461, -3.18924051],
[ 0.58601689, 1.03414847, -1.51408613],
[ 0.5440693 , 0.40387901, -0.44558506],
[ 4.02543414, -5.13080125, 0.17843608],
[ 0.60842181, 0.4165125 , 0.20256789]])
You can use these arrays as inputs to any computation or plotting tools:
[14]:
numpy.mean(traj[-1].log['particles/md/pair/LJ/forces'], axis=0)
[14]:
array([ 2.22044605e-16, 3.31223764e-16, -4.51028104e-17])
[15]:
fig = matplotlib.figure.Figure(figsize=(10, 6.18))
ax = fig.add_subplot()
ax.hist(traj[-1].log['particles/md/pair/LJ/energies'], 100)
ax.set_xlabel('potential energy')
ax.set_ylabel('count')
fig
[15]:

As with scalar quantities, the array quantities are stored separately in each frame. Use a loop to access a range of frames and compute time-series data or averages.
This is what the system looks like when you color the particles by the values in particles/md/pair/LJ/energies
:
[16]:
render(traj[-1])
[16]:

In this section, you have logged per-particle quantities to a GSD file during a simulation run and accessed that data with a script. The next section of this tutorial demonstrates how to log particle shape information that OVITO can use.
Storing Particle Shape
Overview
Questions
How can I store particle shape for use with visualization tools?
Objectives
Demonstrate logging type_shapes to a GSD file.
Explain that OVITO can read this information.
Boilerplate code
[1]:
import gsd.hoomd
import hoomd
Particle Shape
HPMC integrators and some anisotropic MD pair potentials model particles that have a well defined shape. You can save this shape definition to a GSD file for use in analysis and visualization workflows. In particular, OVITO will read this shape information and render particles appropriately.
Define the Simulation
This section executes the hard particle simulation from a previous tutorial. See Introducing HOOMD-blue for a complete description of this code.
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=2)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
sim.create_state_from_gsd(
filename='../00-Introducing-HOOMD-blue/compressed.gsd')
sim.run(0)
Logging particle shape to a GSD file
The type_shapes loggable quantity is a representation of the particle shape for each type following the type_shapes specification for the GSD file format. In HPMC simulations, the integrator provides type_shapes:
[4]:
mc.loggables
[4]:
{'state': 'state',
'map_overlaps': 'sequence',
'overlaps': 'scalar',
'translate_moves': 'sequence',
'rotate_moves': 'sequence',
'mps': 'scalar',
'type_shapes': 'object'}
[5]:
mc.type_shapes
[5]:
[{'type': 'ConvexPolyhedron',
'rounding_radius': 0,
'vertices': [[-0.5, 0, 0],
[0.5, 0, 0],
[0, -0.5, 0],
[0, 0.5, 0],
[0, 0, -0.5],
[0, 0, 0.5]]}]
Add the type_shapes quantity to a Logger.
[6]:
logger = hoomd.logging.Logger()
logger.add(mc, quantities=['type_shapes'])
Write the simulation trajectory to a GSD file along with the logged quantities:
[7]:
gsd_writer = hoomd.write.GSD(filename='trajectory.gsd',
trigger=hoomd.trigger.Periodic(10000),
mode='xb',
filter=hoomd.filter.All(),
log=logger)
sim.operations.writers.append(gsd_writer)
Run the simulation:
[8]:
sim.run(20000)
As discussed in a previous section, delete the simulation so it is safe to open the GSD file for reading in the same process.
[9]:
del sim, gsd_writer, logger, mc, cpu
Reading logged shapes from a GSD file
You can access the shape from scripts using the gsd
package:
[10]:
traj = gsd.hoomd.open('trajectory.gsd', 'rb')
type_shapes is a special quantity available via particles.type_shapes
rather than the log
dictionary:
[11]:
traj[0].particles.type_shapes
[11]:
[{'type': 'ConvexPolyhedron',
'rounding_radius': 0,
'vertices': [[-0.5, 0, 0],
[0.5, 0, 0],
[0, -0.5, 0],
[0, 0.5, 0],
[0, 0, -0.5],
[0, 0, 0.5]]}]
Open the file in OVITO and it will read the shape definition and render particles appropriately.
In this section, you have logged particle shape to a GSD file during a simulation so that visualization and analysis tools can access it. The next section shows how to write formatted output.
Writing Formatted Output
Overview
Questions
How do I display status information during a simulation?
How can I log user-defined quantities?
How can I write formatted output to a text file?
Objectives
Demonstrate user-defined log quantities.
Explain the use of Table to display status information during a simulation run.
Show that Table can write to a file.
Boilerplate code
[1]:
import datetime
import hoomd
Define the Simulation
This tutorial executes the Lennard-Jones particle simulation from a previous tutorial. See Introducing Molecular Dyamics for a complete description of this code.
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
Formatted output
The Table writer formats log quantities in human-readable text and writes them to stdout
or a file. Table only supports scalar
and string
quantities due to the limitations of this format. This section shows you how to use Table to display status information during a simulation run.
Add quantities to a Logger
The categories
argument to Logger defines the categories that it will accept.
[4]:
logger = hoomd.logging.Logger(categories=['scalar', 'string'])
Log the and simulation timestep
and tps
quantities:
[5]:
logger.add(sim, quantities=['timestep', 'tps'])
You can also log user-defined quantities using functions, callable class instances, or class properties. For example, this class computes the estimated time remaining:
[6]:
class Status():
def __init__(self, sim):
self.sim = sim
@property
def seconds_remaining(self):
try:
return (self.sim.final_timestep - self.sim.timestep) / self.sim.tps
except ZeroDivisionError:
return 0
@property
def etr(self):
return str(datetime.timedelta(seconds=self.seconds_remaining))
Assign the loggable quantity using the tuple (object, property_name, flag)
, where flag
is the string name of the flag for this quantity. (The tuple for callable objects would be (callable, flag)
).
[7]:
status = Status(sim)
logger[('Status', 'etr')] = (status, 'etr', 'string')
Represent the namespace of your user-defined quantity with a tuple of strings - ('Status', 'etr'
) above. You can use any number of arbitrary strings in the tuple to name your quantity.
Display quantities with Table
Table is a Writer that formats the quantities in a Logger into a human readable table. Create one that triggers periodically:
[8]:
table = hoomd.write.Table(trigger=hoomd.trigger.Periodic(period=5000),
logger=logger)
Add it to the simulation:
[9]:
sim.operations.writers.append(table)
Run the simulation and see the output:
[10]:
sim.run(100000)
Simulation.timestep Simulation.tps Status.etr
15000 7079.19236 0:00:13.419610
20000 7711.58264 0:00:11.670756
25000 7873.23870 0:00:10.796065
30000 7998.88650 0:00:10.001392
35000 8067.65223 0:00:09.296385
40000 8130.34130 0:00:08.609725
45000 8161.39123 0:00:07.964328
50000 8198.28541 0:00:07.318603
55000 8220.85883 0:00:06.690299
60000 8243.20310 0:00:06.065603
65000 8260.47214 0:00:05.447631
70000 8281.81727 0:00:04.829858
75000 8297.38171 0:00:04.218198
80000 8302.28728 0:00:03.613462
85000 8311.39834 0:00:03.007917
90000 8320.74372 0:00:02.403631
95000 8318.73378 0:00:01.803159
100000 8328.36479 0:00:01.200716
105000 8335.28337 0:00:00.599860
110000 8341.92073 0:00:00
Later in this notebook, you are going to create another Table Writer. Remove table
now to avoid confusing the two:
[11]:
sim.operations.writers.remove(table)
Save Table output to a file
Table writes to stdout
by default. It can write to a file (or any Python file-like object with write
and flush
methods) instead.
Open the file to write:
[12]:
file = open('log.txt', mode='x', newline='\n')
Create a Table Writer that outputs to this file and add it to the Simulation:
[13]:
table_file = hoomd.write.Table(output=file,
trigger=hoomd.trigger.Periodic(period=5000),
logger=logger)
sim.operations.writers.append(table_file)
Run the simulation:
[14]:
sim.run(100000)
You can read the file with standard tools:
[15]:
!tail log.txt
165000 8394.76121 0:00:05.360486
170000 8398.18003 0:00:04.762937
175000 8395.87278 0:00:04.168715
180000 8406.33943 0:00:03.568735
185000 8416.43930 0:00:02.970377
190000 8415.16128 0:00:02.376663
195000 8412.77978 0:00:01.783002
200000 8404.64913 0:00:01.189818
205000 8407.71957 0:00:00.594692
210000 8413.83845 0:00:00
In this section, you have displayed loggable quantities during a simulation run and saved them to a text file. This is the last section in the logging tutorial.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Parallel Simulation With MPI
This tutorial explains how to run simulations in parallel using MPI.
Prerequisites:
This tutorial assumes you are familiar with terms relating to high performance computing clusters, specifically job and scheduler.
This tutorial uses molecular dynamics simulations to demonstrate parallel jobs. The tutorial Introducing Molecular Dynamics teaches these concepts.
To execute these notebooks locally, you need an MPI enabled version of HOOMD-blue. You can check this by checking that
hoomd.version.mpi_enabled
isTrue
:
[1]:
import hoomd
hoomd.version.mpi_enabled
[1]:
True
The HOOMD-blue binaries on conda-forge do not enable MPI due to technical limitations.
The system used in Introducing Molecular Dynamics is small. Replicate the state of that system, as MPI parallel simulations require a minimum system size (this requirement is explained in more details in the next section).
[2]:
import hoomd
sim = hoomd.Simulation(device=hoomd.device.CPU())
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
sim.state.replicate(3, 3, 3)
hoomd.write.GSD.write(filename="random.gsd", state=sim.state, mode='wb')
Introduction to MPI
Overview
Questions
What is MPI?
Why should I run my simulations in parallel?
How can I execute scripts in parallel?
Objectives
Describe MPI.
Explain how MPI can provide faster performance on HPC systems.
Show how to write a single program that can execute in serial or parallel.
Demonstrate how to execute that program with mpirun.
Explain how strong scaling enables higher performance at the cost of some efficiency.
Introduction
MPI (message passing interface) is a library that enables programs to execute in parallel. MPI is commonly available on HPC (high performance computing) clusters. HOOMD-blue uses MPI to execute on many CPUs and/or GPUs. Using more resources in parallel can provide higher performance than the same simulation run on one CPU core or one GPU.
The Simulation Script
This tutorial executes the Lennard-Jones particle simulation from a previous tutorial. See Introducing Molecular Dyamics for a complete description of this code.
You can also run HPMC and other types of simulations in HOOMD-blue using MPI. All operations in HOOMD-blue support MPI unless otherwise noted in their documentation.
[1]:
%pycat lj_performance.py
import hoomd
# Initialize the simulation.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Set the operations for a Lennard-Jones particle simulation.
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
# Run a short time before measuring performance.
sim.run(100)
# Run the simulation and print the performance.
sim.run(1000)
print(sim.tps)
lj_performance.py
is a file in the same directory as this notebook. Due to the way MPI launches parallel jobs, the code must be in a file instead of a notebook cell. %pycat
is an IPython magic command that displays the contents of a Python file with syntax highlighting.
Compare this script to the one used in Introducing Molecular Dyamics. The only difference is the addition of print(sim.tps)
which prints the performance in time steps per second. The same script can be run in serial or in parallel on different numbers of CPU cores.
Run the simulation with MPI
Use the MPI launcher mpirun
to execute this script in parallel on any number of CPU cores given by the -n
option.
Your HPC cluster may use a different launcher that may take different arguments, such as mpiexec, ibrun, or jsrun. See your cluster’s documentation to find the right launcher to use.
In Jupyter, the “!” magic command is equivalent to typing the given command in a shell.
[2]:
!mpirun -n 1 python3 lj_performance.py
270.2858299680495
[3]:
!mpirun -n 2 python3 lj_performance.py
notice(2): Using domain decomposition: n_x = 1 n_y = 1 n_z = 2.
445.91139383875304
445.91139383875304
[4]:
!mpirun -n 4 python3 lj_performance.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
761.6418866478846
761.6418866478846
761.6418866478846
761.6418866478846
The simulation runs faster on more CPU cores. This sequence of simulations demonstrates strong scaling where a simulation of a fixed number of particles executes in less time on more parallel resources. You can compute the efficiency of the scaling by taking the performance on n cores divided by the performance on one core divided by n. Strong scaling rarely nears 100% efficiency, so it will use more total resources than executing with -n 1
. However, a -n 1
simulation
may take months to complete while a -n 64
one takes days - making your research much more productive even it if uses a moderately larger amount of HPC resources.
The print
is executed the same number of times given to -n
. The next section of this tutorial explains this in more detail.
Summary
In this section, you have executed a HOOMD-blue simulation script on 1, 2, and 4 CPU cores using MPI and observed the performance. The next section of this tutorial explains how HOOMD-blue splits the domain of the simulation and how you should structure your scripts.
Domain Decomposition
Overview
Questions
What is a MPI rank?
How does HOOMD-blue divide the simulation among the ranks?
What limitations prevent parallel execution?
How should I structure my scripts?
Objectives
Demonstrate how MPI ranks are assigned to processes.
Explain how HOOMD-blue divides the simulation State with a domain decomposition and how operations execute only on the local particles.
Demonstrate the minimum domain size.
Discuss how particles are placed in domains and how this can lead to uneven load balancing.
Emphasize that scripts are a single program that can execute in serial or parallel.
Show how to avoid deadlock when using the HOOMD-blue API.
Ranks and processes
When you call mpirun -n 4 python3 script.py
, mpirun
launches 4 separate instances of python
all executing script.py
at the same time. For example, a script that prints a message will repeat the output:
[1]:
%pycat hello_world.py
print('Hello, world')
[2]:
!mpirun -n 4 python3 hello_world.py
Hello, world
Hello, world
Hello, world
Hello, world
MPI launches n separate processes. These may or may not be on the same node in a HPC cluster, depending on how you request resources in your job script. Each process launched this way is called a rank and is given a rank index. In HOOMD-blue, the Communicator class (created by default with Device) gives you access to the rank index.
[3]:
%pycat hello_hoomd.py
import os
import hoomd
device = hoomd.device.CPU()
rank = device.communicator.rank
pid = os.getpid()
print(f'Hello HOOMD-blue rank {rank} from process id {pid}')
[4]:
!mpirun -n 4 python3 hello_hoomd.py
Hello HOOMD-blue rank 0 from process id 1883182
Hello HOOMD-blue rank 1 from process id 1883183
Hello HOOMD-blue rank 2 from process id 1883184
Hello HOOMD-blue rank 3 from process id 1883185
os.getpid
is Python method that returns the process id, a number assigned to every executing process by the operating system.
Domain decomposition
When you create the State object in an MPI simulation on more than 1 rank, HOOMD-blue splits the simulation box into k x l x m domains. The product of k, l and m is equal to the number of ranks you execute. Chose n values that factorize given the constraints of your HPC system, such as the number of cores per node. The domains are defined by planes that split the box. By default, the planes are evenly spaced and chosen to minimize the surface area between the domains.
[5]:
%pycat domain_decomposition.py
import hoomd
# Initialize the system.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Print the domain decomposition.
domain_decomposition = sim.state.domain_decomposition
if device.communicator.rank == 0:
print(domain_decomposition)
# Print the location of the split planes.
split_fractions = sim.state.domain_decomposition_split_fractions
if device.communicator.rank == 0:
print(split_fractions)
# Print the number of particles on each rank.
with sim.state.cpu_local_snapshot as snap:
N = len(snap.particles.position)
print(f'{N} particles on rank {device.communicator.rank}')
[6]:
!mpirun -n 4 python3 domain_decomposition.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
1743 particles on rank 1
1734 particles on rank 2
1659 particles on rank 3
(1, 2, 2)
([], [0.5], [0.5])
1776 particles on rank 0
For example, this script chooses a 1 x 2 x 2 decomposition with the split planes in the center of the box when launched with 4 ranks. domain_decomposition_split_fractions
reports relative values between 0 and 1, so in this case a hypothetical 10 x 10 x 10 box would have split planes at y=0 and z=0 creating 4 domains.
Each rank is assigned one of these domains and stores the particles located inside it. The operations execute on the particles local to each rank. When the density of the system is uniform, each rank has approximately the same number of particles (as in the example above). This is what allows the parallel simulations to run with faster performance: the same operation is being run on fewer particles so it takes less time.
However, when the density of the system is not uniform the default split planes lead to an uneven load balancing with a much greater number of particles on one rank compared to the others. The performance of the overall simulation is limited by that of the slowest rank. In the extreme case, imagine all the particles in the lower left of a very large box. In this 1 x 2 x 2 domain decomposition, all particles would be on one rank and the parallel simulation would take just as much time to execute as one rank alone.
Some computations, such as pair forces in MD or hard particle overlap checks in HPMC, need to compute interactions with particles from a neighboring domain. This establishes a lower limit on the domain size. Given an interaction range r_interaction (for MD, this is the sum of the largest pair potential r_cut and the neighbor list buffer), each x,y,z dimension of the domain must be larger than 2 * r_interaction. HOOMD-blue raises an exception when this is violated. For
example, here is the Lennard-Jones script run on the random.gsd
file before replicating to a larger size:
[7]:
%pycat lj_domain_error.py
import hoomd
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(
filename='../01-Introducing-Molecular-Dynamics/random.gsd')
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
sim.run(0)
[8]:
!mpirun -n 2 python3 lj_domain_error.py
notice(2): Using domain decomposition: n_x = 1 n_y = 1 n_z = 2.
Traceback (most recent call last):
File "03-Parallel-Simulations-With-MPI/lj_domain_error.py", line 17, in <module>
Traceback (most recent call last):
File "03-Parallel-Simulations-With-MPI/lj_domain_error.py", line 17, in <module>
sim.run(0)
File "/scratch/joaander/build/hoomd/hoomd/simulation.py", line 435, in run
sim.run(0)
File "/scratch/joaander/build/hoomd/hoomd/simulation.py", line 435, in run
self._cpp_sys.run(steps_int, write_at_start)
RuntimeError: Communication error -
Simulation box too small for domain decomposition.
r_ghost_max: 2.9
d.z/2: 2.275
self._cpp_sys.run(steps_int, write_at_start)
RuntimeError: Communication error -
Simulation box too small for domain decomposition.
r_ghost_max: 2.9
d.z/2: 2.275
--------------------------------------------------------------------------
MPI_ABORT was invoked on rank 1 in communicator MPI_COMM_WORLD
with errorcode 1.
NOTE: invoking MPI_ABORT causes Open MPI to kill all MPI processes.
You may or may not see output from other processes, depending on
exactly when Open MPI kills them.
--------------------------------------------------------------------------
[vance.engin.umich.edu:1883280] 1 more process has sent help message help-mpi-api.txt / mpi-abort
[vance.engin.umich.edu:1883280] Set MCA parameter "orte_base_help_aggregate" to 0 to see all help / error messages
Single program
HOOMD-blue scripts must be written as a single program. All ranks must load the same input file, define the same operations with the same parameters and triggers, and run the same number of time steps. HOOMD-blue requires this because it splits the system into smaller domains, one assigned to each rank, and executes same operations on each domain.
While there are many processes executing the same Python script in parallel, they are not independent. The ranks send messages back and forth as needed to combine the decomposed parts of simulation into a whole. If your script does not follow the single program requirement, it is likely at least one rank will deadlock while it waits for a message to be sent from another rank that will never be sent. A deadlock means that the execution continues while waiting for a condition that will never be true.
While you must create all HOOMD-blue operations, access properties, and call methods on all ranks, this may not be the case for other libraries used in your script. For example, calling print
on all ranks results in duplicated output. The same would occur when using open()
to open and write to a file. In cases like these, place your code in a if device.communicator.rank == 0:
check so that it only runs once on rank 0. For example, this script prints the total kinetic energy
of the system only once:
[9]:
%pycat lj_kinetic_energy.py
import hoomd
# Initialize the simulation.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Set the operations for a Lennard-Jones particle simulation.
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
# Instantiate a ThermodyanmicQuantities object to compute kinetic energy.
thermodynamic_properties = hoomd.md.compute.ThermodynamicQuantities(
filter=hoomd.filter.All())
sim.operations.computes.append(thermodynamic_properties)
# Run the simulation.
sim.run(1000)
# Access the system kinetic energy on all ranks.
kinetic_energy = thermodynamic_properties.kinetic_energy
# Print the kinetic energy only on rank 0.
if device.communicator.rank == 0:
print(kinetic_energy)
[10]:
!mpirun -n 4 python3 lj_kinetic_energy.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
14654.77706008575
The pattern used here is important:
kinetic_energy = thermodynamic_properties.kinetic_energy
if device.communicator.rank == 0:
print(kinetic_energy)
The property thermodynamic_properties.kinetic_energy
is accessed on all ranks, but printed only on rank 0. You must use this same pattern any time you access operation’s properties or call their methods, not just when calling print
.
To see why this is important, try the following code in an interactive job:
if device.communicator.rank == 0:
print(thermodynamic_properties.kinetic_energy)
When you execute this, you will find that it prints nothing and the execution continues indefinitely (press Ctrl-C to stop it).
Each rank stores only a fraction of the total particles in the system. ThermodynamicProperties
first computes the kinetic energy from the particles local to each rank, then communicates between the ranks to sum the total system kinetic energy. When you access kinetic_energy
only on rank 0, rank 0 sums the local kinetic energy and then deadlocks while it waits for messages from the other ranks. The messages will never arrive because none of the other ranks access the
kinetic_energy
property, so they do not compute the kinetic energy on their local particles, nor do they communicate with the other ranks.
So, be careful using if device.communicator.rank == 0:
. HOOMD-blue has a rich Python API, but any property access or method call on a HOOMD-blue object may result in a MPI communication that will deadlock when inside this condition.
Scripts using if device.communicator.rank == 0: are compatible with serial execution where rank is always 0.
Summary
In this section, you have seen how MPI ranks run as independent processes, learned how HOOMD splits particles across domains, understand why that HOOMD-blue scripts need to execute all operations identically on all ranks, and identified how to to print output only once in MPI simulations without causing deadlock. The next section of this tutorial shows you how to access the system configuration in MPI simulations.
Accessing System Configurations With MPI
Overview
Questions
How can I access the state of the simulation in parallel simulations?
What are the differences between local and global snapshots?
Objectives
Describe how to write GSD files in MPI simulations.
Show examples using local snapshots.
Show examples using global snapshots.
Writing GSD files in parallel jobs
You can write GSD files in parallel jobs just as you do in serial. Saving the simulation trajectory to a file is useful for visualization and analysis after the simulation completes. As mentioned in the previous section, write a single program and add the write.GSD
operation with identical parameters on all ranks:
[2]:
%pycat lj_trajectory.py
import hoomd
# Initialize the simulation.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Set the operations for a Lennard-Jones particle simulation.
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)
sim.operations.integrator = integrator
# Define and add the GSD operation.
gsd_writer = hoomd.write.GSD(filename='trajectory.gsd',
trigger=hoomd.trigger.Periodic(1000),
mode='xb')
sim.operations.writers.append(gsd_writer)
# Run the simulation.
sim.run(1000)
[3]:
!mpirun -n 4 python3 lj_trajectory.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
Modifying particle properties with local snapshots
Use snapshots when you need to modify particle properties during a simulation, or perform analysis where the results need to be known as the simulation progresses (e.g. umbrella sampling). Local snapshots provide high performance direct access to the particle data stored in HOOMD-blue. The direct access comes with several costs. Your script can only access particles local to the domain of the current rank. These particles may appear in any order in the local snapshot and a given particle is only present on one rank. To access the properties of a specific particle, find the index given the particle’s tag and handle the condition where it is not present on the rank.
The example below demonstrates this with an example that doubles the mass of all particles, and quadruples the mass of the particle with tag 100:
[4]:
%pycat local_snapshot.py
import hoomd
# Initialize the simulation.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Access the local snapshot.
with sim.state.cpu_local_snapshot as snapshot:
N = len(snapshot.particles.position)
# Double the mass of every particle.
snapshot.particles.mass *= 2
# Look up the index of the particle with tag 100.
idx = snapshot.particles.rtag[100]
# Modify the particle, but only if it is found.
# This condition will be true on one rank and false on the others.
if idx < N:
snapshot.particles.mass[idx] *= 2
[5]:
!mpirun -n 4 python3 local_snapshot.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
Notice how the example uses the rtag
lookup array to efficiently find the index of the particle with the given tag. When the particle is not present on the local rank, rtag
is set to a number greater than the local number of particles.
Any analysis you perform may require MPI communication to combine results across ranks using mpi4py (this is beyond the scope of this tutorial).
Using global snapshots with MPI
Global snapshots collect all particles onto rank 0 and sort them by tag. This removes a number of the inconveniences of the local snapshot API, but at the cost of much slower performance. When you use global snapshots in MPI simulations, you need to add if snapshot.communicator.rank == 0:
checks around all the code that accesses the data in the snapshot. The get_snapshot()
call itself MUST be made on all ranks. Here is an example that computes the total mass of the system
using a global snapshot:
[6]:
%pycat global_snapshot.py
import hoomd
import numpy
# Initialize the simulation.
device = hoomd.device.CPU()
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Call get_snapshot on all ranks.
snapshot = sim.state.get_snapshot()
# Access particle data on rank 0 only.
if snapshot.communicator.rank == 0:
total_mass = numpy.sum(snapshot.particles.mass)
print(total_mass)
[7]:
!mpirun -n 4 python3 global_snapshot.py
notice(2): Using domain decomposition: n_x = 1 n_y = 2 n_z = 2.
6912.0
Summary
In this section, you have written trajectories to a GSD file, modified the state of the system efficiently using local snapshots, and analyzed the state of the system with a global snapshot - all with conditions that work in both MPI parallel and serial simulations. The next section of this tutorial shows you how to use MPI to run many independent simulations with different inputs.
Running Multiple Simulations With Partitions
Overview
Questions
How can I partition a MPI communicator to run many independent simulations?
When are partitions useful?
Objectives
Show how to define a custom Communicator with more than one partition.
Demonstrate how to use this to run many independent simulations with one
mpirun
.Explain how this is useful to aggregate jobs on HPC systems.
Partitioning communicators
So far in this tutorial you have seen how executing mpirun -n 4 python3 script.py
will use domain decomposition to run 1 simulation split across 4 ranks via domain decomposition. What if you wanted to run 2 different simulations, each on 2 ranks with this command? Or 4 different simulations each on 1 rank? This is called partitioning the MPI communicator.
In HOOMD-blue, you can do this by defining a non-default Communicator and specifying the ranks_per_partition
argument. Then use communicator.partition
as an identifier in your script to change input parameters.
[2]:
%pycat hello_partition.py
import hoomd
communicator = hoomd.communicator.Communicator(ranks_per_partition=2)
print(f'Hello from partition {communicator.partition} rank {communicator.rank}')
[3]:
!mpirun -n 4 python3 hello_partition.py
Hello from partition 0 rank 0
Hello from partition 0 rank 1
Hello from partition 1 rank 0
Hello from partition 1 rank 1
In partitioned simulations, all ranks within a given partition must have the same input file, operations, parameters, and otherwise follow the single program guidelines outlined in the previous sections of this tutorial. However, the input file, operations and/or their parameters can vary from one partition to the next. For example, you could run many simulations with different temperatures, different initial configurations, or different random number seeds. The following example shows how to set different temperatures and random number seeds based on the partition index.
You MUST pass the partitioned Communicator object to the device constructor: hoomd.device.CPU(communicator=communicator) or hoomd.device.GPU(communicator=communicator)
[4]:
%pycat lj_partition.py
import hoomd
# kT values to execute at:
kT_values = [1.5, 2.0]
# Instantiate a Communicator with 2 ranks in each partition.
communicator = hoomd.communicator.Communicator(ranks_per_partition=2)
# Pass the communicator to the device.
device = hoomd.device.CPU(communicator=communicator)
# Initialize the simulation.
sim = hoomd.Simulation(device=device)
sim.create_state_from_gsd(filename='random.gsd')
# Choose system parameters based on the partition
sim.seed = communicator.partition
kT = kT_values[communicator.partition]
# Set the operations for a Lennard-Jones particle simulation.
integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell()
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
integrator.forces.append(lj)
langevin = hoomd.md.methods.Langevin(kT=kT, filter=hoomd.filter.All())
integrator.methods.append(langevin)
sim.operations.integrator = integrator
# Use the partition id in the output file name.
gsd_writer = hoomd.write.GSD(filename=f'trajectory{communicator.partition}.gsd',
trigger=hoomd.trigger.Periodic(1000),
mode='xb')
sim.operations.writers.append(gsd_writer)
# Run the simulation.
sim.run(1000)
[5]:
!mpirun -n 4 python3 lj_partition.py
notice(2): Using domain decomposition: n_x = 1 n_y = 1 n_z = 2.
notice(2): Using domain decomposition: n_x = 1 n_y = 1 n_z = 2.
Each partition is a separate Simulation that produces its own trajectory. You must choose filenames or directories so that different partitions produce different output files. The above example places the partition index in the filename:
[6]:
!ls trajectory?.gsd
trajectory0.gsd trajectory1.gsd
Motivation
Why use partitions in simulations where you can just write one script with parameters and execute it more than once? Some HPC systems only allow jobs to use whole nodes, and/or policies prefer fewer large jobs over many smaller jobs in the scheduler. On these systems, you can obtain better throughput for your research when you use partitions to aggregate many independent simulations together into one scheduler job.
While the details are beyond the scope of this tutorial, signac-flow can automate the aggregation process.
Summary
In this section, you have learned how to run many simulations with different parameters using a single mpirun
invocation. This is the end of the MPI tutorial.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Custom Actions in Python
This tutorial introduces the necessary information to create custom actions in Python. Briefly, custom actions allow users and developers to implement new functionality into HOOMD-blue without having to write C++ code.
Prerequisites:
This tutorial assumes you are familiar with the concepts presented in Introducting HOOMD-blue and Introducing Molecular Dyanamics. Throughout this tutorial we may use other libraries to introduce writing performant actions in Python. Familiarity with these packages may help, but are not necessary to learn from this tutorial.
What are Actions?
Overview
Questions
What are actions?
Why would I want to use custom actions?
What categories of actions exist for customization in HOOMD-blue?
Objectives
Explain the concept of an action in HOOMD-blue.
Discuss potential use cases for custom Python actions.
Provide the categories of actions in HOOMD-blue.
Actions
Actions are the objects that act or operate on a hoomd.Simulation
object. Looking at HOOMD-blue from the Python perspective, actions are wrapped or composed by operations. For example, objects like hoomd.update.BoxResize
and hoomd.hpmc.tune.MoveSize
contain actions internally. In other words, the actions implement the logic repsonsible for implementing the functionality of an operation (e.g. resizing the box for hoomd.update.BoxResize
), while the operation handles some
logistics like determining when the action will run using a hoomd.Trigger
object.
Actions can be written in Python using hoomd.custom.Action
. Through creating a subclass of Action
HOOMD-blue’s capabilities can be augmented and customized.
Why Python Custom Actions?
HOOMD-blue offers Python Action
s for a variety of reasons.
Enable more customization in Python.
Quicker prototyping of new simulation techniques.
Allow use of SciPy libraries for use cases like on-the-fly machine learning forcefields.
Serve as a foreign function interface from a compiled library through Python to HOOMD-blue’s run loop. For instance, a Python library that uses Rust as a backend could be used in a Python custom action.
Some example use cases are storing simulation data in a user’s desired format whether that is a database, file format like HDF5, or other storage medium, simulating a system under a radiation source, or advanced sampling techniques.
Categories of Actions?
Currently, HOOMD-blue offers three types of actions: updaters, writers, and tuners. These categories serve to distinguish how an action interacts with a simulation and its state
attribute.
Updaters modify the simulation state when triggered.
hoomd.update.BoxResize
is an example of an updater as it changes the simulation box.Writers observe the simulation state and write that data to a file or some other object (writers should not modify the simulation state).
hoomd.write.GSD
is an example of a writer; it does not change the simulation state, but writes it out to a GSD file.Tuners modify another object’s hyperparameters (or object attributes). Tuners should not modify state, but can modify another object to improve performance.
hoomd.hpmc.tune.MoveSize
is an example of this type of action.MoveSize
tunes the integrator’s trial move sizes to reach a specific acceptance rate performance but does not modify the simulation state.
Recap
Actions are objects that act on a
hoomd.Simulation
object.Actions can be written in Python using
hoomd.custom.Action
.There are three categories of actions.
Updaters: modify simulation state
Writers: doesn’t modify simulation state, writes out data
Tuners: doesn’t modify simulation state, modifies object hyperparameters
In the next section we start writing custom actions and using them in HOOMD-blue simulations.
An Initial Custom Action
Overview
Questions
How do I write a custom action in Python?
How do I wrap a custom action object?
How do I use a custom action in a simulation?
Objectives
Explain the steps in writing a custom action.
Demonstrate using a custom action in a simulation.
Writing a Custom Action
First, import hoomd
.
[1]:
import hoomd
We create a single particle snapshot for initializing a simulation’s state further down.
[2]:
snap = hoomd.Snapshot()
snap.particles.N = 1
snap.particles.position[:] = [0, 0, 0]
snap.particles.types = ['A']
snap.particles.typeid[:] = [0]
snap.configuration.box = [10, 10, 10, 0, 0, 0]
Create a custom action as a subclass of hoomd.custom.Action
. Here we will create an action that prints the timestep to standard out.
[3]:
class PrintTimestep(hoomd.custom.Action):
def act(self, timestep):
print(timestep)
We now have an action that can print out the simulation timestep. The logic of the action goes inside the act
method. All actions must define this function, and it must take in the simulation timestep; this is passed in when the action is called in the HOOMD-blue run loop. (If you are wondering how to access simulation data, there is a mechanism for that which we will go over in the next section).
Let’s go ahead and create a PrintTimestep
object.
[4]:
custom_action = PrintTimestep()
Wrapping Custom Actions
To let an Operations
object know what kind of action our custom action is, we must wrap it in a subclass of hoomd.custom.CustomOperation
. We have three options as discussed in the previous section: an updater, writer, or tuner. Since our object does not modify simulation state or an object’s hyperparameters, but writes the timestep to standard out, our action is a writer. hoomd.write.CustomWriter
then is the correct class to wrap our custom action (hoomd.update.CustomUpdater
and
hoomd.tune.CustomTuner
are for updaters and tuners respectively).
Create a CustomWriter
operation that will call the custom action when triggered:
[5]:
custom_op = hoomd.write.CustomWriter(action=custom_action,
trigger=hoomd.trigger.Periodic(100))
Notice that custom operations take triggers like other operations.
Using Custom Actions
To use a custom opeation we must add it to a hoomd.Operations
object. Thus, the steps to use a custom action in a simuluation are 1. Instantiate the custom action object. 2. Wrap the custom action in the appropriate custom operation class. 3. Add the custom operation object to the appropriate container in a hoomd.Operations
object.
[6]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
Initialize the state
[7]:
sim.create_state_from_snapshot(snap)
Add the custom action wrapped by a CustomWriter
:
[8]:
sim.operations.writers.append(custom_op)
We can now run our simulation to see our custom action in work!
[9]:
sim.run(1000)
100
200
300
400
500
600
700
800
900
1000
In the next section we discuss some of the features of custom actions, before getting into non-trival examples in later sections.
Custom Action Features
Overview
Questions
How do I access simulation state information?
How do I create loggable quantities in custom actions?
What are other features provided by the custom action/operation API?
Objectives
Explain how to access simulation state in a custom action.
Explain how to expose loggable quantities in a custom action.
Demonstrate other miscellaneous features of custom actions.
Boilerplate Code
[1]:
import hoomd
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu)
snap = hoomd.Snapshot()
snap.particles.N = 1
snap.particles.position[:] = [0, 0, 0]
snap.particles.types = ['A']
snap.particles.typeid[:] = [0]
snap.configuration.box = [10, 10, 10, 0, 0, 0]
sim.create_state_from_snapshot(snap)
How do I access simulation state?
By the time that a custom action will have its act
method called it will have an attribute _state
accessible to it which is the simulation state for the simulation it is associated with. The behavior of this is controlled in the hoomd.custom.Action.attach
method. The method takes in a simulation object and performs any necessary set-up for the action call act
. By default, the method stores the simulation state in the _state
attribute.
We will create two custom actions class to show this. In one, we will not modify the attach
method, and in the other we will make attach
method also print out some information.
[2]:
class PrintTimestep(hoomd.custom.Action):
def act(self, timestep):
print(timestep)
class NotifyAttachWithPrint(hoomd.custom.Action):
def attach(self, simulation):
print(f"Has '_state' attribute {hasattr(self, '_state')}.")
super().attach(simulation)
print(f"Has '_state' attribute {hasattr(self, '_state')}.")
def act(self, timestep):
print(timestep)
Like in the previous section these are both writers. We will go ahead and wrap them and see what happens when we try to run the simulation.
[3]:
print_timestep = PrintTimestep()
print_timestep_operation = hoomd.write.CustomWriter(
action=print_timestep, trigger=hoomd.trigger.Periodic(10))
sim.operations.writers.append(print_timestep_operation)
sim.run(0)
[4]:
sim.operations -= print_timestep_operation
print_timestep_with_notify = NotifyAttachWithPrint()
sim.operations.writers.append(
hoomd.write.CustomWriter(action=print_timestep_with_notify,
trigger=hoomd.trigger.Periodic(10)))
sim.run(0)
Has '_state' attribute False.
Has '_state' attribute True.
Loggable Quantities in Custom Actions
Custom actions can hook into HOOMD-blue’s logging subsystem by using the hoomd.logging.log
decorator to document which methods/properties of a custom action are loggable. See the documentation on hoomd.logging.log
and hoomd.logging.TypeFlags
for complete documenation of the decorator and loggable types.
In general, log
as a decorator takes optional arguments that control whether to make a method a property, what type the loggable quantity is, and whether the quantity should be logged by default.
Rather than elaborate, we will use an example to explain these attributes.
[5]:
class ActionWithLoggables(hoomd.custom.Action):
@hoomd.logging.log
def scalar_property_loggable(self):
return 42
@hoomd.logging.log(category='string')
def string_loggable(self):
return "I am a string loggable."
def act(self, timestep):
pass
action = ActionWithLoggables()
[6]:
action.scalar_property_loggable
[6]:
42
[7]:
action.string_loggable
[7]:
'I am a string loggable.'
Custom Operation Wrapping
Another feature of the custom action API is that when an object is wrapped by a custom operation object (which is necessary to add a custom action to a simulation), the action’s attributes are available through the operation object as if the operation were the action. For example, we will wrap action
from the previous code block in a CustomWriter
and access its attributes that way.
Due to this wrapping the attribute trigger
should not exist in your custom action.
[8]:
custom_op = hoomd.write.CustomWriter(action=action, trigger=100)
custom_op.scalar_property_loggable
[8]:
42
[9]:
custom_op.string_loggable
[9]:
'I am a string loggable.'
Summary
These summarize most of the unique features of custom actions in Python. They are - Accessing simulation state through _state
- Exposing loggable quantities - Accessing action attributes through custom operation wrapper
With this information, you could write almost any action that is possible to write in Python for use in HOOMD-blue. The remain tutorial sections will focus on concrete examples and show some tricks to get the best performance. For the full list of accessible features for custom actions see the reference documentation.
Custom Updater
Overview
Questions
How can I modify the state of a system in a custom updater?
Objectives
Show an example of a non-trival custom updater.
Boilerplate Code
[1]:
from numbers import Number
import hoomd
import hoomd.md as md
import numpy as np
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=1)
# Create a simple cubic configuration of particles
N = 5 # particles per box direction
box_L = 20 # box dimension
snap = hoomd.Snapshot(cpu.communicator)
snap.configuration.box = [box_L] * 3 + [0, 0, 0]
snap.particles.N = N**3
x, y, z = np.meshgrid(*(np.linspace(-box_L / 2, box_L / 2, N, endpoint=False),)
* 3)
positions = np.array((x.ravel(), y.ravel(), z.ravel())).T
snap.particles.position[:] = positions
snap.particles.types = ['A']
snap.particles.typeid[:] = 0
sim.create_state_from_snapshot(snap)
rng = np.random.default_rng(1245)
Problem
In this section, we will show how to create a custom updater that modifies the system state. To show this, we will create a custom updater that adds a prescribed amount of energy to a single particle simulating the bombardment of radioactive material into our system. For this problem, we pick a random particle and modify its velocity according to the radiation energy in a random direction.
[2]:
class InsertEnergyUpdater(hoomd.custom.Action):
def __init__(self, energy):
self.energy = energy
def act(self, timestep):
snap = self._state.get_snapshot()
if snap.communicator.rank == 0:
particle_i = rng.integers(snap.particles.N)
mass = snap.particles.mass[particle_i]
direction = self._get_direction()
magnitude = np.sqrt(2 * self.energy / mass)
velocity = direction * magnitude
old_velocity = snap.particles.velocity[particle_i]
new_velocity = old_velocity + velocity
snap.particles.velocity[particle_i] = velocity
self._state.set_snapshot(snap)
@staticmethod
def _get_direction():
theta, z = rng.random(2)
theta *= 2 * np.pi
z = 2 * (z - 0.5)
return np.array([
np.sqrt(1 - (z * z)) * np.cos(theta),
np.sqrt(1 - (z * z)) * np.sin(theta), z
])
We will now use our custom updater with an NVE
integrator. Particles will interact via a Lennard-Jones potential. Using the Table
writer and a hoomd.logging.Logger
, we will monitor the energy, which should be increasing as we are adding energy to the system. We will also thermalize our system to a kT == 1
.
[3]:
sim.state.thermalize_particle_momenta(filter=hoomd.filter.All(), kT=1.)
lj = md.pair.LJ(nlist=md.nlist.Cell(buffer=0.4))
lj.params[('A', 'A')] = {'epsilon': 1., 'sigma': 1.}
lj.r_cut[('A', 'A')] = 2.5
integrator = md.Integrator(methods=[md.methods.NVE(hoomd.filter.All())],
forces=[lj],
dt=0.005)
thermo = md.compute.ThermodynamicQuantities(hoomd.filter.All())
logger = hoomd.logging.Logger(categories=['scalar'])
logger.add(thermo, ['kinetic_energy', 'potential_energy'])
logger['total_energy'] = (
lambda: thermo.kinetic_energy + thermo.potential_energy, 'scalar')
table = hoomd.write.Table(100, logger, max_header_len=1)
sim.operations += integrator
sim.operations += thermo
sim.operations += table
# Create and add our custom updater
energy_operation = hoomd.update.CustomUpdater(action=InsertEnergyUpdater(10.),
trigger=100)
sim.operations += energy_operation
[4]:
sim.run(1000)
kinetic_energy potential_energy total_energy
189.55469 -0.16021 189.39447
203.13934 -5.51636 197.62298
214.05941 -7.90628 206.15314
219.49181 -8.47534 211.01647
230.38656 -9.71804 220.66852
237.66638 -9.07038 228.59601
245.73067 -10.18110 235.54957
254.95301 -12.21494 242.73808
258.55741 -6.01446 252.54296
269.38334 -8.12332 261.26002
As we can see the total energy of the system is indeed increasing. The energy isn’t increasing by 10 every time since we are adding the velocity in a random direction which may be against the current velocity.
Improving upon our Custom Action
Maybe we want to allow for the energy to be from a distribution. HOOMD-blue has a concept called a variant which allows for quantities that vary over time. Let’s change the InsertEnergyupdater
to use variants and create a custom variant that grabs a random number from a Gaussian distribution. (If you don’t understand the variant code, that is fine. We are just using this to showcase how you can iteratively improve custom actions).
Note:
Variant objects model a parameter as a function of the timestep, so to get the value for a particular timestep we have to call the variant. For more information see the documentation for hoomd.variant.
[5]:
class InsertEnergyUpdater(hoomd.custom.Action):
def __init__(self, energy):
self._energy = energy
@property
def energy(self):
"""A `hoomd.variant.Variant` object."""
return self._energy
@energy.setter
def energy(self, new_energy):
if isinstance(new_energy, Number):
self._energy = hoomd.variant.Constant(new_energy)
elif isinstance(new_energy, hoomd.variant.Variant):
self._energy = new_energy
else:
raise ValueError("energy must be a variant or real number.")
def act(self, timestep):
snap = self._state.get_snapshot()
if snap.communicator.rank == 0:
particle_i = rng.integers(snap.particles.N)
mass = snap.particles.mass[particle_i]
direction = self._get_direction()
magnitude = np.sqrt(2 * self.energy(timestep) / mass)
velocity = direction * magnitude
old_velocity = snap.particles.velocity[particle_i]
new_velocity = old_velocity + velocity
snap.particles.velocity[particle_i] = velocity
self._state.set_snapshot(snap)
@staticmethod
def _get_direction():
theta, z = rng.random(2)
theta *= 2 * np.pi
z = 2 * (z - 0.5)
return np.array([
np.sqrt(1 - (z * z)) * np.cos(theta),
np.sqrt(1 - (z * z)) * np.sin(theta), z
])
class GaussianVariant(hoomd.variant.Variant):
def __init__(self, mean, std):
hoomd.variant.Variant.__init__(self)
self.mean = mean
self.std = std
def __call__(self, timestep):
return rng.normal(self.mean, self.std)
We briefly show that the Gaussian Variant works.
[6]:
energy = GaussianVariant(mean=10., std=2.)
sample_energies = np.array([energy(0) for _ in range(1000)])
f"Mean: {sample_energies.mean()}, std. dev. {sample_energies.std()}"
[6]:
'Mean: 10.069550459202723, std. dev. 1.9965744919420398'
We now use the updated InsertEnergyUpdater
in the simulation.
[7]:
sim.operations.updaters.remove(energy_operation)
# Create and add our custom updater
energy_operation = hoomd.update.CustomUpdater(
action=InsertEnergyUpdater(energy), trigger=100)
sim.operations.updaters.append(energy_operation)
sim.run(1000)
279.83085 -11.21077 268.62009
289.14791 -9.62083 279.52708
302.04414 -9.22880 292.81534
312.06778 -11.05103 301.01675
324.69061 -11.95850 312.73211
332.29403 -9.80310 322.49093
345.55571 -14.83428 330.72143
357.07548 -16.49285 340.58263
357.62391 -11.70456 345.91935
372.21959 -15.91459 356.30500
We could continue to improve upon this updater and the execution of this operation. However, this suffices to showcase the ability of non-trivial updaters to affect the simulation state.
Custom Writer
Overview
Questions
How could I write a custom trajectory writer?
Objectives
Show an example custom writer
Boilerplate Code
[1]:
import h5py
import hoomd
import hoomd.hpmc as hpmc
import numpy as np
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(cpu, seed=1)
# Create a simple cubic configuration of particles
N = 5 # particles per box direction
box_L = 20 # box dimension
snap = hoomd.Snapshot(cpu.communicator)
snap.configuration.box = [box_L] * 3 + [0, 0, 0]
snap.particles.N = N**3
x, y, z = np.meshgrid(*(np.linspace(-box_L / 2, box_L / 2, N, endpoint=False),)
* 3)
positions = np.array((x.ravel(), y.ravel(), z.ravel())).T
snap.particles.position[:] = positions
snap.particles.types = ['A']
snap.particles.typeid[:] = 0
sim.create_state_from_snapshot(snap)
Problem
For this section, we will demonstrate writing a custom trajectory writer using h5py
. We will start by implementing the ability to store positions, timesteps, and box dimensions in an HDF5 file.
[2]:
class HDF5Writer(hoomd.custom.Action):
def __init__(self, filename, mode):
self.filename = filename
if mode not in {'w', 'w-', 'x', 'a', 'r+'}:
raise ValueError("mode must be writtable")
self.file = h5py.File(filename, mode)
self.write_metadata()
frames = list(self.file.keys())
if frames:
self._cur_frame = max(map(int, frames)) + 1
else:
self._cur_frame = 1
def write_metadata(self):
"""Write the file metadata that defines the type of hdf5 file"""
if 'app' in self.file.attrs:
if self.file.attrs.app != 'hoomd-v3':
raise RuntimeError(
'HDF5 file metadata "app" is not "hoomd-v3".')
else:
self.file.attrs.app = 'hoomd-v3'
if 'version' not in self.file.attrs:
self.file.attrs.version = '1.0'
def act(self, timestep):
"""Write out a new frame to the trajectory."""
new_frame = self.file.create_group(str(self._cur_frame))
self._cur_frame += 1
positions = new_frame.create_dataset('positions',
(self._state.N_particles, 3),
dtype='f8')
snapshot = self._state.get_snapshot()
positions[:] = snapshot.particles.position
new_frame.attrs['timestep'] = timestep
box_array = np.concatenate((self._state.box.L, self._state.box.tilts))
new_frame.attrs['box'] = box_array
def __del__(self):
self.file.close()
Define a function that creates a HDF5Writer
wrapped in a custom writer.
This function will make creating our custom writer easier. We will now add an HPMC sphere integrator and our custom writer to our simulation and run for 1000 steps.
(Note that the ‘w’ mode will truncate any existing file.)
[3]:
h5_writer = hoomd.write.CustomWriter(action=HDF5Writer('traj.h5', 'w'),
trigger=100)
integrator = hpmc.integrate.Sphere()
integrator.shape['A'] = {'diameter': 1.}
sim.operations += integrator
sim.operations += h5_writer
sim.run(1000)
We have run the simulation, and our HDF5 file has been written. Lets check the groups our file contains now.
[4]:
list(h5_writer.file.keys())
[4]:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
Ten frames have been written as expected. Let’s check the properties from the last frame and compare them to the simulation currently. We will open the file again in read only mode to check these properties. First we flush the open HDF5 file to ensure the data has been written to the OS buffer at least.
[5]:
h5_writer.file.flush()
with h5py.File('traj.h5', 'r') as traj:
assert traj['10'].attrs['timestep'] == sim.timestep
box_array = np.concatenate((sim.state.box.L, sim.state.box.tilts))
assert np.allclose(traj['10'].attrs['box'], box_array)
snapshot = sim.state.get_snapshot()
assert np.allclose(snapshot.particles.position, traj['10']['positions'][:])
Expanding on HDF5Writer
Our HDF5Writer
class is already sufficient for storing the trajectory. However, there are plenty of other features we could add. Examples include utilizing the HOOMD-blue logging subsystem to allow logging data to the HDF5 file, and adding support for MPI. Also, we could also add support for other system properties such as images, velocities, and others. We will focus on adding this feature.
We need to decide on a method of specifying properties to write. We will use a tuple system where we signify the property we want to store using a tuple that nests into a snapshot object. For example to write images we will use the tuple ('particles', 'image')
to signify we want to store images. We will let an user pass in a list of tuples of any length to specify what they want to store. (Positions will always be stored, and we will move them to the particles group).
[6]:
class HDF5Writer(hoomd.custom.Action):
def __init__(self, filename, mode, properties):
self.filename = filename
self.properties = set(properties) | {('particles', 'position')}
if mode not in {'w', 'w-', 'x', 'a', 'r+'}:
raise ValueError("mode must be writtable")
self.file = h5py.File(filename, mode)
self.write_metadata()
frames = list(self.file.keys())
if frames:
self._cur_frame = max(map(int, frames)) + 1
else:
self._cur_frame = 1
def write_metadata(self):
"""Write the file metadata that defines the type of hdf5 file"""
if 'app' in self.file.attrs:
if self.file.attrs.app != 'hoomd-v3':
raise RuntimeError(
'HDF5 file metadata "app" is not "hoomd-v3".')
else:
self.file.attrs.app = 'hoomd-v3'
if 'version' not in self.file.attrs:
self.file.attrs.version = '1.0'
def _set_property(self, base_group, prop):
# Get data array
data = self._state.get_snapshot()
for name in prop:
data = getattr(data, name)
# Get dataset
use_group = base_group
for name in prop[:-1]:
if name not in use_group:
use_group = base_group.create_group(name)
else:
use_group = base_group[name]
dataset = use_group.create_dataset(prop[-1],
data.shape,
dtype=str(data.dtype))
dataset[:] = data
def act(self, timestep):
"""Write out a new frame to the trajectory."""
new_frame = self.file.create_group(str(self._cur_frame))
self._cur_frame += 1
for prop in self.properties:
self._set_property(new_frame, prop)
new_frame.attrs['timestep'] = timestep
box_array = np.concatenate((self._state.box.L, self._state.box.tilts))
new_frame.attrs['box'] = box_array
def __del__(self):
self.file.close()
We will now use our extended trajectory writer to write out particle images as well.
[7]:
h5_writer.file.close()
sim.operations -= h5_writer
h5_writer = hoomd.write.CustomWriter(action=HDF5Writer(
'traj.h5', 'w', [('particles', 'image')]),
trigger=100)
sim.operations.writers.append(h5_writer)
sim.run(1000)
To see that this worked we will check the first frame for particle images.
[8]:
h5_writer.file.flush()
with h5py.File('traj.h5', 'r') as traj:
display(traj['1']['particles']['image'][:10])
display(traj['1']['particles']['position'][:10])
array([[-1, 0, 0],
[-1, 0, 0],
[-1, -1, 0],
[-1, 0, 0],
[-1, -1, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0]], dtype=int32)
array([[ 7.08916892, -9.1162494 , -9.03166465],
[ 7.17894751, -7.55565503, -4.1420896 ],
[ 6.84048969, 9.85875838, -0.14319672],
[ 9.42302572, -7.66224406, 1.71042043],
[ 4.04383384, 8.15467659, 9.35673311],
[-5.21819354, -9.57761671, -7.17922194],
[-6.56869188, -9.00928178, -7.91171588],
[-1.41025576, -9.14286987, -3.21326451],
[-3.29261443, -8.20593309, 2.56455928],
[-2.02993862, -3.93072604, 4.98365 ]])
We could continue add more features such as argument validation in the constructor, support for the logging subsystem of HOOMD-blue, a classmethod, or a number of other things. However, these are left as exercises. This section has shown a non-trivial application of the custom action feature in HOOMD-blue for custom writers.
Improving Performance
Overview
Questions
How can I write custom actions to be as efficient as possible?
Objectives
Mention common means for improving performance.
Demonstrate using the local snapshot API for increased performance.
Boilerplate Code
[1]:
from numbers import Number
import hoomd
import hoomd.md as md
import numpy as np
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(cpu, seed=1)
# Create a simple cubic configuration of particles
N = 12 # particles per box direction
box_L = 50 # box dimension
snap = hoomd.Snapshot(cpu.communicator)
snap.configuration.box = [box_L] * 3 + [0, 0, 0]
snap.particles.N = N**3
x, y, z = np.meshgrid(*(np.linspace(-box_L / 2, box_L / 2, N, endpoint=False),)
* 3)
positions = np.array((x.ravel(), y.ravel(), z.ravel())).T
snap.particles.position[:] = positions
snap.particles.types = ['A']
snap.particles.typeid[:] = 0
sim.create_state_from_snapshot(snap)
sim.state.thermalize_particle_momenta(hoomd.filter.All(), 1.)
lj = md.pair.LJ(nlist=md.nlist.Cell(buffer=0.4))
lj.params[('A', 'A')] = {'epsilon': 1., 'sigma': 1.}
lj.r_cut[('A', 'A')] = 2.5
integrator = md.Integrator(methods=[md.methods.NVE(hoomd.filter.All())],
forces=[lj],
dt=0.005)
sim.operations += integrator
class GaussianVariant(hoomd.variant.Variant):
def __init__(self, mean, std):
hoomd.variant.Variant.__init__(self)
self.mean = mean
self.std = std
def __call__(self, timestep):
return rng.normal(self.mean, self.std)
energy = GaussianVariant(0.1, 0.001)
sim.run(0)
rng = np.random.default_rng(1245)
General Guidelines
When trying to improve the performance of custom actions, the first step is always to profile the class. Python comes with profiling tools that can be used to determine bottlenecks in a custom action’s performance. In addition, there are many external visualization and profiling tools available. However, after profiling here are some tips that should help improve performance.
State.get_snapshot
aggregates data across MPI ranks and is \(O(n)\) to construct and setting the state to a new snapshot \(O(n)\) as well. However,hoomd.State.cpu_local_snaphshot
orhoomd.State.gpu_local_snapshot
are on order \(O(1)\) to construct and modifying data in a local snapshot is \(O(1)\) as well.HOOMD-blue makes use of properties heavily. Since users can change the system state in Python at any point, we must recompute many of these quantities every time they are queried. If you are using something like
hoomd.md.pair.LJ.energies
multiple times, it will be more performant to first store the values and then use that copy.Avoid for loops for numerical calculation. Try to utilize NumPy broadcasting or existing functions in NumPy or Scipy on the CPU or CuPy on the GPU.
Improve InsertEnergyUpdater
As an example, we will improve the performance of the InsertEnergyUpdater
. Specifically we will change to use the cpu_local_snapshot
to update particle velocity. We will use the %%timeit
magic function for timing the simulation’s run time before and after our optimization. To highlight the differnce, we will run the updater every timestep.
[2]:
class InsertEnergyUpdater(hoomd.custom.Action):
def __init__(self, energy):
self._energy = energy
@property
def energy(self):
return self._energy
@energy.setter
def energy(self, new_energy):
if isinstance(new_energy, Number):
self._energy = hoomd.variant.Constant(new_energy)
elif isinstance(new_energy, hoomd.variant.Variant):
self._energy = new_energy
else:
raise ValueError("energy must be a variant or real number.")
def act(self, timestep):
snap = self._state.get_snapshot()
if snap.communicator.rank == 0:
particle_i = rng.integers(snap.particles.N)
mass = snap.particles.mass[particle_i]
direction = self._get_direction()
magnitude = np.sqrt(2 * self.energy(timestep) / mass)
velocity = direction * magnitude
old_velocity = snap.particles.velocity[particle_i]
new_velocity = old_velocity + velocity
snap.particles.velocity[particle_i] = velocity
self._state.set_snapshot(snap)
@staticmethod
def _get_direction():
theta, z = rng.random(2)
theta *= 2 * np.pi
z = 2 * (z - 0.5)
return np.array([
np.sqrt(1 - (z * z)) * np.cos(theta),
np.sqrt(1 - (z * z)) * np.sin(theta), z
])
[3]:
energy_action = InsertEnergyUpdater(energy)
energy_operation = hoomd.update.CustomUpdater(action=energy_action, trigger=1)
sim.operations.updaters.append(energy_operation)
[4]:
%%timeit
sim.run(100)
84.7 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
We now show the profile for the optimized code which uses the cpu_local_snapshot
for updating velocities.
[5]:
class InsertEnergyUpdater(hoomd.custom.Action):
def __init__(self, energy):
self._energy = energy
@property
def energy(self):
return self._energy
@energy.setter
def energy(self, new_energy):
if isinstance(new_energy, Number):
self._energy = hoomd.variant.Constant(new_energy)
elif isinstance(new_energy, hoomd.variant.Variant):
self._energy = new_energy
else:
raise ValueError("energy must be a variant or real number.")
def attach(self, simulation):
self._state = simulation.state
self._comm = simulation.device.communicator
def detach(self):
del self._state
del self._comm
def act(self, timestep):
part_tag = rng.integers(self._state.N_particles)
direction = self._get_direction()
energy = self.energy(timestep)
with self._state.cpu_local_snapshot as snap:
# We restrict the computation to the MPI
# rank containing the particle if applicable.
# By checking if multiple MPI ranks exist first
# we can avoid for checking inclusion of a tag id
# in an array.
if (self._comm.num_ranks <= 1 or part_tag in snap.particles.tag):
i = snap.particles.rtag[part_tag]
mass = snap.particles.mass[i]
magnitude = np.sqrt(2 * energy / mass)
velocity = direction * magnitude
old_velocity = snap.particles.velocity[i]
new_velocity = old_velocity + velocity
snap.particles.velocity[i] = new_velocity
@staticmethod
def _get_direction():
theta, z = rng.random(2)
theta *= 2 * np.pi
z = 2 * (z - 0.5)
return np.array([
np.sqrt(1 - (z * z)) * np.cos(theta),
np.sqrt(1 - (z * z)) * np.sin(theta), z
])
[6]:
# Create and add our modified custom updater
sim.operations -= energy_operation
energy_action = InsertEnergyUpdater(energy)
energy_operation = hoomd.update.CustomUpdater(action=energy_action, trigger=1)
sim.operations.updaters.append(energy_operation)
[7]:
%%timeit
sim.run(100)
19.9 ms ± 800 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
As can be seen the simulation with the new EnergyInsertUpdater about an order of magnitude faster with a system size of \(12^3 = 1728\), by virtue of the local snapshot modification having \(O(1)\) time complexity. At larger system sizes this change will grow to be even more substantial.
This concludes the tutorial on custom actions in Python. For more information see the API documentation.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Organizing and Executing Simulations
This tutorial explains how to organize and execute many simulations.
Prerequisites:
You should be familiar with the concepts taught in Introducing HOOMD-blue. The “Submitting Cluster Jobs” section assumes you are familiar with HPC resources and schedulers.
Organizing Data
Overview
Questions
How can I organize data from many simulations?
How do I relate the parameters of the simulation to the data?
Objectives
Define a data space that organizes simulation output into directories based on state point parameters.
Demonstrate how to use signac to create a data space.
Initialize a data space with hard particle Monte Carlo simulations at a selected volume fractions.
Show how to store computed results in the job document.
Boilerplate code
[1]:
import itertools
import math
import gsd.hoomd
import hoomd
import numpy
Research question
The Introducing HOOMD-blue tutorial shows how to execute a single simulation of hard octahedra and how they self-assemble into a crystal structure. You might want to answer the question “At what volume fraction is the phase transition from fluid to crystal?”. One way to find out is to execute simulations at many volume fractions and examine the resulting equilibrium structures. When performing such a study, you may want to explore simulations at different system sizes, repeat the simulation with different random number seeds, or examine the effects of changing other parameters.
The unique set of parameters for each simulation is a state point which you can represent in a Python dictionary:
[3]:
statepoint = dict(N_particles=128, volume_fraction=0.6, seed=20)
statepoint
[3]:
{'N_particles': 128, 'volume_fraction': 0.6, 'seed': 20}
In your own research, you will execute different types of simulation with different parameters. Follow the example provided in this tutorial and apply the same concepts organize and execute the simulations for your work.
Data space
Each simulation you execute will generate several output files. Store these in a directory uniquely assigned to each state point. The collection of directories is a data space. Use signac to automatically name and create the directories.
[4]:
import signac
A signac project represents the entire data space stored on disk with associated metadata. The method init_project
creates a signac project in the current working directory by placing a signac.rc
file with the project metadata and a workspace
directory to hold the directories of the data space. The name
argument is required with signac 1.x, but the value of the name is used only to populate signac.rc
.
Create the project:
[5]:
project = signac.init_project(name="octahedra-assembly-project")
[6]:
!cat signac.rc
project = octahedra-assembly-project
schema_version = 1
A signac job is a container that holds the state point, assigned directory, and a job document.
[7]:
job = project.open_job(statepoint)
[8]:
job.statepoint
[8]:
{'N_particles': 128, 'volume_fraction': 0.6, 'seed': 20}
The job document is a persistent dictionary where you can record the job’s status.
[9]:
job.document
[9]:
{}
The first file for each simulation is the initial condition. Here is the initialization code from the Introducing HOOMD-blue tutorial, encapsulated in a function that takes a signac job as an argument:
[10]:
def init(job):
# Place a number of particles as indicated by the signac job's state point.
K = math.ceil(job.statepoint.N_particles**(1 / 3))
spacing = 1.2
L = K * spacing
x = numpy.linspace(-L / 2, L / 2, K, endpoint=False)
position = list(itertools.product(x, repeat=3))
position = position[0:job.statepoint.N_particles]
orientation = [(1, 0, 0, 0)] * job.statepoint.N_particles
snapshot = gsd.hoomd.Snapshot()
snapshot.particles.N = job.statepoint.N_particles
snapshot.particles.position = position
snapshot.particles.orientation = orientation
snapshot.particles.typeid = [0] * job.statepoint.N_particles
snapshot.particles.types = ['octahedron']
snapshot.configuration.box = [L, L, L, 0, 0, 0]
# Write `lattice.gsd` to the signac job's directory.
with gsd.hoomd.open(name=job.fn('lattice.gsd'), mode='xb') as f:
f.append(snapshot)
# Set the 'initialized' item in the job document.
job.document['initialized'] = True
The init
function uses job.statepoint.N_particles
to access the state point parameter and job.fn
to construct a filename in the assigned directory. init
also sets the 'initialized'
item in the job document to True
which will be used in the next section of the tutorial.
Call init
to initialize signac jobs at various volume fractions in the data space:
[11]:
for volume_fraction in [0.4, 0.5, 0.6]:
statepoint = dict(N_particles=128, volume_fraction=volume_fraction, seed=20)
job = project.open_job(statepoint)
job.init()
init(job)
This tutorial initializes only three jobs in the data space to keep the execution time and output short. In your own research, signac can help you organize and execute as many jobs as you need.
signac places the data space in a directory named workspace
. Here are the files the loop generated:
[12]:
!ls workspace/*
workspace/59363805e6f46a715bc154b38dffc4e4:
lattice.gsd signac_job_document.json signac_statepoint.json
workspace/972b10bd6b308f65f0bc3a06db58cf9d:
lattice.gsd signac_job_document.json signac_statepoint.json
workspace/c1a59a95a0e8b4526b28cf12aa0a689e:
lattice.gsd signac_job_document.json signac_statepoint.json
Each directory now contains the lattice.gsd
file created by init
as well as a signac_statepoint.json
and signac_job_document.json
files created by signac. The directory assigned to each signac job is a hash of the state point and is generated automatically by signac.
Summary
In this section of the tutorial, you created a data space with directories to store the simulation results for a number of state points. So far, the directory for each simulation contains only the initial configuration file lattice.gsd.
The remaining sections in this tutorial show you how to execute a workflow on this data space that randomizes, compresses, and equilibrates each simulation.
This tutorial only teaches the basics of signac. Read the signac documentation to learn how to loop through all signac jobs, search, filter, and much more.
Executing Simulations
Overview
Questions
How can I execute a series of workflow steps on many simulations?
Objectives
Introduce workflows.
Demonstrate how to use signac-flow to define workflow steps and their associated pre-conditions and post-conditions.
Execute the workflow to randomize and compress all state points in the data space.
Boilerplate code
[1]:
import math
import hoomd
import signac
Workflow steps
The Introducing HOOMD-blue tutorial employs distinct workflow steps that must be performed in sequence to complete the self-assembly study at a given state point. These are initialization, randomization, compression, equilibration, and analysis. The previous section in this tutorial initialized every state point in the data space. This section will randomize and compress them and the next section will equilibrate them. Analysis can also be implemented as a workflow step, but this is left as an exercise for the reader.
Use signac-flow to define these workflow steps as Python functions and execute them in the proper sequence on all state points in the data space.
[2]:
import flow
Define a function that creates a Simulation object based on the signac job:
[3]:
def create_simulation(job):
cpu = hoomd.device.CPU()
# Set the simulation seed from the statepoint.
sim = hoomd.Simulation(device=cpu, seed=job.statepoint.seed)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
return sim
This is the code from Introducing HOOMD-blue, adapted to use the seed for the current signac job with job.statepoint.seed
.
Subclass FlowProject by convention.
[4]:
class Project(flow.FlowProject):
pass
Define a function that executes the randomization step:
[5]:
@Project.operation # Workflow step.
@Project.pre.true('initialized') # Pre-condition in job document.
@Project.post.true('randomized') # Post-condition in job document.
def randomize(job):
sim = create_simulation(job)
# Read `lattice.gsd` from the signac job's directory.
sim.create_state_from_gsd(filename=job.fn('lattice.gsd'))
sim.run(10e3)
# Write `random.gsd` to the signac job's directory.
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('random.gsd'))
# Set the 'randomized' to satisfy the post-condition.
job.document['randomized'] = True
In signac-flow’s terminology, a project operation is a complete workflow step that modifies the signac job’s state. Recall that the similarly named HOOMD-blue Operation is a class that acts on the state of the simulation at defined time steps. This tutorial uses the term workflow step wherever possible to avoid ambiguity.
@Project.operation
is a decorator that declares the randomize function is a workflow step. @Project.pre
and @Project.post
define pre-conditions and post-conditions for this step, which return a boolean to indicate whether a workflow step is ready to start (pre-condition) or complete (post-condition). In this block, both conditions are evaluated by pre.true
and post.true
which examine the job document and check whether the item with the given key
evaluates to True
. Use pre- and post-conditions to define the sequence in which the workflow steps will execute. Here, the pre-condition checking 'initialized'
is satisfied for those signac jobs that were initialized in the previous section which set job.document['initialize'] = True
.
The body of the function creates the Simulation object using the create_simulation
method from above, completes the randomization as in the Introducing HOOMD-blue tutorial, and sets the 'randomized'
item in the job document to True
. The function writes randomized.gsd
to the signac job’s assigned directory using the job.fn
method.
Similarly define a function that executes the compression step:
[6]:
@Project.operation
@Project.pre.after(randomize) # Execute after randomize completes.
@Project.post.true('compressed_step')
def compress(job):
sim = create_simulation(job)
# Read `random.gsd` from the signac job directory.
sim.create_state_from_gsd(filename=job.fn('random.gsd'))
a = math.sqrt(2) / 2
V_particle = 1 / 3 * math.sqrt(2) * a**3
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box)
# Set the final box volume to the volume fraction for this signac job.
final_box.volume = (sim.state.N_particles * V_particle
/ job.statepoint.volume_fraction)
compress = hoomd.hpmc.update.QuickCompress(
trigger=hoomd.trigger.Periodic(10), target_box=final_box)
sim.operations.updaters.append(compress)
periodic = hoomd.trigger.Periodic(10)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(moves=['a', 'd'],
target=0.2,
trigger=periodic,
max_translation_move=0.2,
max_rotation_move=0.2)
sim.operations.tuners.append(tune)
while not compress.complete and sim.timestep < 1e6:
sim.run(1000)
if not compress.complete:
raise RuntimeError("Compression failed to complete")
# Write `compressed.gsd` to the job document.
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('compressed.gsd'))
# Set 'compressed step' in the signac job document.
job.document['compressed_step'] = sim.timestep
This workflow step executes after the randomize step completes using the pre.after(randomize)
pre-condition. The body of the function contains the code from the Introducing HOOMD-blue tutorial, changed to use the volume fraction for the current signac job with job.statepoint.volume_fraction
and to read and write files from the signac job’s directory with job.fn
.
The compress operation sets the compressed_step
item in the job document and uses that to evaluate the post-condition. The next section of the tutorial will use the value of compressed_step
.
Run the workflow
Now that you have defined the workflow steps, check the status of the workflow:
[7]:
project = Project()
project.print_status(overview=False,
detailed=True,
parameters=['volume_fraction'])
Detailed View:
job id operation volume_fraction labels
-------------------------------- ------------- ----------------- --------
59363805e6f46a715bc154b38dffc4e4 randomize [U] 0.6
972b10bd6b308f65f0bc3a06db58cf9d randomize [U] 0.4
c1a59a95a0e8b4526b28cf12aa0a689e randomize [U] 0.5
[U]:unknown [R]:registered [I]:inactive [S]:submitted [H]:held [Q]:queued [A]:active [E]:error
Each signac job is ready to execute randomize, the first step in the workflow. Run it:
[8]:
project.run(names=['randomize'])
Every signac job directory in the data space now has a random.gsd
file produced by randomize:
[9]:
!ls workspace/*
workspace/59363805e6f46a715bc154b38dffc4e4:
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
workspace/972b10bd6b308f65f0bc3a06db58cf9d:
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
workspace/c1a59a95a0e8b4526b28cf12aa0a689e:
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
Now, the status shows that the compress step is ready:
[10]:
project.print_status(overview=False,
detailed=True,
parameters=['volume_fraction'])
Detailed View:
job id operation volume_fraction labels
-------------------------------- ------------ ----------------- --------
59363805e6f46a715bc154b38dffc4e4 compress [U] 0.6
972b10bd6b308f65f0bc3a06db58cf9d compress [U] 0.4
c1a59a95a0e8b4526b28cf12aa0a689e compress [U] 0.5
[U]:unknown [R]:registered [I]:inactive [S]:submitted [H]:held [Q]:queued [A]:active [E]:error
Execute it:
[11]:
project.run(names=['compress'])
Every signac job directory in the data space now has a compressed.gsd
file produced by compress:
[12]:
!ls workspace/*
workspace/59363805e6f46a715bc154b38dffc4e4:
compressed.gsd random.gsd signac_statepoint.json
lattice.gsd signac_job_document.json
workspace/972b10bd6b308f65f0bc3a06db58cf9d:
compressed.gsd random.gsd signac_statepoint.json
lattice.gsd signac_job_document.json
workspace/c1a59a95a0e8b4526b28cf12aa0a689e:
compressed.gsd random.gsd signac_statepoint.json
lattice.gsd signac_job_document.json
Summary
In this section of the tutorial, you defined the workflow steps to randomize and compress the initial configuration using signac-flow, along with the pre- and post-conditions needed to sequence the steps. Then you executed the workflow steps on all state points in the dataset. The directory for each simulation now contains compressed.gsd
and is ready for equilibration at the target volume fraction.
The next section in this tutorial teaches you how to write a workflow step that can continue itself and complete over several submissions.
This tutorial only teaches the basics of signac-flow. Read the signac-flow documentation to learn more.
Continuing Simulations
Overview
Questions
How do I continue running a simulation?
Objectives
Explain why you may want to continue running a simulation, such as wall time limits for cluster jobs.
Describe what you need to consider when writing a workflow step that can continue.
Demonstrate how to append to trajectory files, write needed data to a restart file and limit the simulation run to a given wall time.
Boilerplate code
[1]:
import math
import flow
import hoomd
import signac
Workflow steps from the previous section
The code in the next block collects the workflow steps the previous tutorial section to define the whole workflow.
[2]:
def create_simulation(job):
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=job.statepoint.seed)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
return sim
class Project(flow.FlowProject):
pass
@Project.operation
@Project.pre.true('initialized')
@Project.post.true('randomized')
def randomize(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('lattice.gsd'))
sim.run(10e3)
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('random.gsd'))
job.document['randomized'] = True
@Project.operation
@Project.pre.after(randomize)
@Project.post.true('compressed_step')
def compress(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('random.gsd'))
a = math.sqrt(2) / 2
V_particle = 1 / 3 * math.sqrt(2) * a**3
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box)
final_box.volume = (sim.state.N_particles * V_particle
/ job.statepoint.volume_fraction)
compress = hoomd.hpmc.update.QuickCompress(
trigger=hoomd.trigger.Periodic(10), target_box=final_box)
sim.operations.updaters.append(compress)
periodic = hoomd.trigger.Periodic(10)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(moves=['a', 'd'],
target=0.2,
trigger=periodic,
max_translation_move=0.2,
max_rotation_move=0.2)
sim.operations.tuners.append(tune)
while not compress.complete and sim.timestep < 1e6:
sim.run(1000)
if not compress.complete:
raise RuntimeError("Compression failed to complete")
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('compressed.gsd'))
job.document['compressed_step'] = sim.timestep
Motivation
Let’s say your workflow’s equilibration step takes 96 hours to complete and your HPC resource limits wall times to 24 hours. What do you do?
One solution is to write the equilibration step so that it can continue where it left off. When you execute the workflow, each incomplete signac job will move toward completing the step’s post condition. After several rounds of submissions, all signac jobs will be complete.
This section of the tutorial teaches you how to write a workflow step that can limit its run time and continue. The next section will cover effectively run workflow steps in cluster jobs on HPC resources.
Considerations
You must carefully design your workflow step so that it can continue from where it left off:
Write the current state of the system to a GSD file and dynamic parameters to the job document (or other appropriate storage location).
Perform this write in a
finally:
block to ensure that it is written even when an exception is thrown.Use the saved state when continuing the workflow step.
Open output files in append mode so that the final file includes output from the first and all continued executions.
Use absolute time step values for triggers so they run consistently before and after continuing the workflow step.
Check the elapsed wall time in a loop and stop executing before the cluster job’s wall time limit. Provide some buffer to write the simulation state and exit cleanly.
Here is the equilibration code from the Introducing HOOMD-blue tutorial as a signac-flow operation that can continue:
[3]:
N_EQUIL_STEPS = 200000 # Number of timesteps to run during equilibration.
HOOMD_RUN_WALLTIME_LIMIT = 30 # Time in seconds at which to stop the operation.
@Project.operation
@Project.pre.after(compress) # Execute after compress completes.
# Complete after N_EQUIL_STEPS made by this workflow step.
@Project.post(lambda job: job.document.get('timestep', 0) - job.document[
'compressed_step'] >= N_EQUIL_STEPS)
def equilibrate(job):
end_step = job.document['compressed_step'] + N_EQUIL_STEPS
sim = create_simulation(job)
# Restore the tuned move size parameters from a previous execution.
sim.operations.integrator.a = job.document.get('a', {})
sim.operations.integrator.d = job.document.get('d', {})
if job.isfile('restart.gsd'):
# Read the final system configuration from a previous execution.
sim.create_state_from_gsd(filename=job.fn('restart.gsd'))
else:
# Or read `compressed.gsd` for the first execution of equilibrate.
sim.create_state_from_gsd(filename=job.fn('compressed.gsd'))
# Write `trajectory.gsd` in append mode.
gsd_writer = hoomd.write.GSD(filename=job.fn('trajectory.gsd'),
trigger=hoomd.trigger.Periodic(10_000),
mode='ab')
sim.operations.writers.append(gsd_writer)
# Tune move for the first 5000 steps of the equilibration step.
tune = hoomd.hpmc.tune.MoveSize.scale_solver(
moves=['a', 'd'],
target=0.2,
trigger=hoomd.trigger.And([
hoomd.trigger.Periodic(100),
hoomd.trigger.Before(job.document['compressed_step'] + 5_000)
]))
sim.operations.tuners.append(tune)
try:
# Loop until the simulation reaches the target timestep.
while sim.timestep < end_step:
# Run the simulation in chunks of 10,000 time steps.
sim.run(min(10_000, end_step - sim.timestep))
# End the workflow step early if the next run would exceed the
# alotted walltime. Use the walltime of the current run as
# an estimate for the next.
if (sim.device.communicator.walltime + sim.walltime >=
HOOMD_RUN_WALLTIME_LIMIT):
break
finally:
# Write the state of the system to `restart.gsd`.
hoomd.write.GSD.write(state=sim.state,
mode='wb',
filename=job.fn('restart.gsd'))
# Store the current timestep and tuned trial move sizes.
job.document['timestep'] = sim.timestep
job.document['a'] = sim.operations.integrator.a.to_base()
job.document['d'] = sim.operations.integrator.d.to_base()
if sim.device.communicator.rank == 0:
walltime = sim.device.communicator.walltime
print(f'{job.id} ended on step {sim.timestep} '
f'after {walltime} seconds')
When this workflow step is executed, it stores the trial move sizes a
, d
and the current timestep in the job document as well as the the state of the simulation in restart.gsd
. It reads these when starting again to continue from where the previous execution stopped. This is a large code block, see the comments for more details on how this workflow step can continue from where it stopped.
To limit the execution time, it splits the total simulation length into chunks and executes them in a loop. After each loop iteration, it checks to see whether the next call to run
is likely to exceed the given time limit. sim.device.communicator.walltime
gives the elapsed time from the start of the workflow step’s execution, and is identical on all MPI ranks. Using another source of time might lead to deadlocks. As a pedagogical example, this tutorial sets a 30 second wall time
limit and uses 10,000 timestep chunks - in practice you will likely set limits from hours to days and use larger 100,000 or 1,000,000 step sized chunks depending on your simulation’s performance. You should set the chunk size large enough to avoid the small overhead from each call to run
while at the same time breaking the complete execution into many chunks.
The equilibrate step is ready to execute:
[4]:
project = Project()
project.print_status(overview=False,
detailed=True,
parameters=['volume_fraction'])
Detailed View:
job id operation volume_fraction labels
-------------------------------- --------------- ----------------- --------
59363805e6f46a715bc154b38dffc4e4 equilibrate [U] 0.6
972b10bd6b308f65f0bc3a06db58cf9d equilibrate [U] 0.4
c1a59a95a0e8b4526b28cf12aa0a689e equilibrate [U] 0.5
[U]:unknown [R]:registered [I]:inactive [S]:submitted [H]:held [Q]:queued [A]:active [E]:error
Execute it:
[5]:
project.run()
972b10bd6b308f65f0bc3a06db58cf9d ended on step 42000 after 29.11949 seconds
59363805e6f46a715bc154b38dffc4e4 ended on step 33000 after 27.763527 seconds
c1a59a95a0e8b4526b28cf12aa0a689e ended on step 32000 after 23.5945 seconds
The equilibrate step executed for less than HOOMD_RUN_WALLTIME_LIMIT
seconds for each of the signac jobs in the dataspace. In a production environment, you would run the project repeatedly until it completes.
See that equilibrate step produced the trajectory.gsd
file and the 'a'
, 'd'
, and 'timestep'
items in the job document:
[6]:
!ls workspace/*
workspace/59363805e6f46a715bc154b38dffc4e4:
compressed.gsd restart.gsd trajectory.gsd
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
workspace/972b10bd6b308f65f0bc3a06db58cf9d:
compressed.gsd restart.gsd trajectory.gsd
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
workspace/c1a59a95a0e8b4526b28cf12aa0a689e:
compressed.gsd restart.gsd trajectory.gsd
lattice.gsd signac_job_document.json
random.gsd signac_statepoint.json
[7]:
job = project.open_job(dict(N_particles=128, volume_fraction=0.6, seed=20))
print(job.document)
{'initialized': True, 'randomized': True, 'compressed_step': 13000, 'timestep': 33000, 'a': {'octahedron': 0.04564840324176478}, 'd': {'octahedron': 0.02567136340037109}}
Summary
In this section of the tutorial, you defined the workflow step to equilibreate the hard particle simulation. It stores dynamic parameters and the state of the system needed to continue execution when executed again. Now, the directory for each simulation contains trajectory.gsd, and would be ready for analysis after executed to completion.
The next section in this tutorial will show you how to implement this workflow on the command line and submit cluster jobs that effectively use dense nodes.
This tutorial only teaches the basics of signac-flow. Read the signac-flow documentation to learn more.
Submitting Cluster Jobs
Overview
Questions
How do I submit workflows on HPC resources?
How can I combine many simulations into a single cluster job?
Objectives
Show how to structure the workflow in
project.py
and use signac-flow’s command line interface.Demonstrate the use of directives to set walltime limits and execute with MPI domain decomposition.
Explain how to use aggregate operations with MPI partitions to increase throughput.
Cluster jobs
On HPC resources, you submit cluster jobs to the queue which execute on the compute nodes. You can use signac-flow to generate cluster job submission scripts that execute the steps in your workflow. Use this to execute the expensive or time consuming workflow steps on HPC resources that provide access to many more CPU cores or GPUs than are available on the typical workstation. You can use these resources for to increase throughput (number of simulations per unit time) by executing many simulations at the same time, reduce latency (time to complete a single simulation) by executing each simulation on more than one MPI rank with domain decomposition, or some combination of the two.
This tutorial will demonstrate how to use signac-flow to submit HOOMD-blue workflow steps in cluster jobs. See Parallel Simulations with MPI to learn more about MPI domain decomposition in HOOMD-blue.
Command line interface
Use the command line interface to submit cluster jobs on HPC resources. Place the entire worfklow in a Python file and add a __main__
entry point that calls Project().main()
. project.py
contains the workflow step code from the previous two tutorial sections and the additional code.
Define parameters:
N_RANKS = 2
N_EQUIL_STEPS = 200000
CLUSTER_JOB_WALLTIME = 1
HOOMD_RUN_WALLTIME_LIMIT = CLUSTER_JOB_WALLTIME * 3600 - 10 * 60
The values used in this tutorial are for example purposes only. You should choose a number of MPI ranks, equilibration steps, and cluster job walltime appropriate for your project. In this tutorial, the workflow step stops 10 minutes before the end of the cluster job. In your own workflows you may need more or less time depending on how long it takes to write out the final system state and exit cleanly.
Set the number of MPI ranks and cluster job walltime for the equilibrate operation:
@flow.directives(nranks=N_RANKS, walltime=CLUSTER_JOB_WALLTIME)
signac flow directives set options for the generated cluster job. Here, nranks
sets the number of MPI ranks that the workflow step uses and waltime sets the cluster job walltime in hours.
Execute the entrypoint:
if __name__ == '__main__':
Project().main()
[3]:
%pycat project.py
import math
import flow
import hoomd
# parameters
N_RANKS = 2
N_EQUIL_STEPS = 200000
CLUSTER_JOB_WALLTIME = 1
HOOMD_RUN_WALLTIME_LIMIT = CLUSTER_JOB_WALLTIME * 3600 - 10 * 60
def create_simulation(job):
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=job.statepoint.seed)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
return sim
class Project(flow.FlowProject):
pass
@Project.operation
@Project.pre.true('initialized')
@Project.post.true('randomized')
def randomize(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('lattice.gsd'))
sim.run(10e3)
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('random.gsd'))
job.document['randomized'] = True
@Project.operation
@Project.pre.after(randomize)
@Project.post.true('compressed_step')
def compress(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('random.gsd'))
a = math.sqrt(2) / 2
V_particle = 1 / 3 * math.sqrt(2) * a**3
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box)
final_box.volume = (sim.state.N_particles * V_particle
/ job.statepoint.volume_fraction)
compress = hoomd.hpmc.update.QuickCompress(
trigger=hoomd.trigger.Periodic(10), target_box=final_box)
sim.operations.updaters.append(compress)
periodic = hoomd.trigger.Periodic(10)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(moves=['a', 'd'],
target=0.2,
trigger=periodic,
max_translation_move=0.2,
max_rotation_move=0.2)
sim.operations.tuners.append(tune)
while not compress.complete and sim.timestep < 1e6:
sim.run(1000)
if not compress.complete:
raise RuntimeError("Compression failed to complete")
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('compressed.gsd'))
job.document['compressed_step'] = sim.timestep
@Project.operation
@Project.pre.after(compress)
@Project.post(lambda job: job.document.get('timestep', 0) - job.document[
'compressed_step'] >= N_EQUIL_STEPS)
# Cluster job directives.
@flow.directives(nranks=N_RANKS, walltime=CLUSTER_JOB_WALLTIME)
def equilibrate(job):
end_step = job.document['compressed_step'] + N_EQUIL_STEPS
sim = create_simulation(job)
sim.operations.integrator.a = job.document.get('a', {})
sim.operations.integrator.d = job.document.get('d', {})
if job.isfile('restart.gsd'):
sim.create_state_from_gsd(filename=job.fn('restart.gsd'))
else:
sim.create_state_from_gsd(filename=job.fn('compressed.gsd'))
gsd_writer = hoomd.write.GSD(filename=job.fn('trajectory.gsd'),
trigger=hoomd.trigger.Periodic(10_000),
mode='ab')
sim.operations.writers.append(gsd_writer)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(
moves=['a', 'd'],
target=0.2,
trigger=hoomd.trigger.And([
hoomd.trigger.Periodic(100),
hoomd.trigger.Before(job.document['compressed_step'] + 5_000)
]))
sim.operations.tuners.append(tune)
try:
while sim.timestep < end_step:
sim.run(min(100_000, end_step - sim.timestep))
if (sim.device.communicator.walltime + sim.walltime >=
WALLTIME_LIMIT):
break
finally:
hoomd.write.GSD.write(state=sim.state,
mode='wb',
filename=job.fn('restart.gsd'))
job.document['timestep'] = sim.timestep
job.document['a'] = sim.operations.integrator.a.to_base()
job.document['d'] = sim.operations.integrator.d.to_base()
if sim.device.communicator.rank == 0:
walltime = sim.device.communicator.walltime
print(f'{job.id} ended on step {sim.timestep} '
f'after {walltime} seconds')
# Entrypoint.
if __name__ == '__main__':
Project().main()
Check the status using python3 project.py status
:
[4]:
!python3 project.py status --detailed --no-overview -p volume_fraction
Using environment configuration: StandardEnvironment
Fetching status: 100%|██████████████████████████| 9/9 [00:00<00:00, 3802.25it/s]
Fetching labels: 100%|████████████████████████| 3/3 [00:00<00:00, 165564.63it/s]
Detailed View:
job id operation volume_fraction labels
-------------------------------- --------------- ----------------- --------
59363805e6f46a715bc154b38dffc4e4 equilibrate [U] 0.6
972b10bd6b308f65f0bc3a06db58cf9d equilibrate [U] 0.4
c1a59a95a0e8b4526b28cf12aa0a689e equilibrate [U] 0.5
[U]:unknown [R]:registered [I]:inactive [S]:submitted [H]:held [Q]:queued [A]:active [E]:error
The equilibrate step is ready to execute. signac-flow automates the cluster job submission process with python3 project.py submit
. Use the --pretend
flag first to ensure that the generated cluster jobs are correct (this displays the generated submission scripts without submitting them):
$ python3 project.py submit --pretend
Submitting cluster job 'octahedra_se/972b10bd6b308f65f0bc3a06db58cf9d/equilibrate/cdc78829a46f27e11ee8a98049bf0575':
- Group: equilibrate(972b10bd6b308f65f0bc3a06db58cf9d)
# Submit command: sbatch
#!/bin/bash
#SBATCH --job-name="octahedra_se/972b10bd6b308f65f0bc3a06db58cf9d/equilibrate/cdc78829a46f27e11ee8a98049bf0575"
#SBATCH --partition=standard
#SBATCH -t 01:00:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
set -e
set -u
# equilibrate(972b10bd6b308f65f0bc3a06db58cf9d)
python project.py run -o equilibrate -j 972b10bd6b308f65f0bc3a06db58cf9d
# Eligible to run:
# mpiexec -n 2 python project.py exec equilibrate 972b10bd6b308f65f0bc3a06db58cf9d
Submitting cluster job 'octahedra_se/59363805e6f46a715bc154b38dffc4e4/equilibrate/2c15943de4918753dc2373cd33d527ec':
- Group: equilibrate(59363805e6f46a715bc154b38dffc4e4)
# Submit command: sbatch
#!/bin/bash
#SBATCH --job-name="octahedra_se/59363805e6f46a715bc154b38dffc4e4/equilibrate/2c15943de4918753dc2373cd33d527ec"
#SBATCH --partition=standard
#SBATCH -t 01:00:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
set -e
set -u
# equilibrate(59363805e6f46a715bc154b38dffc4e4)
python project.py run -o equilibrate -j 59363805e6f46a715bc154b38dffc4e4
# Eligible to run:
# mpiexec -n 2 python project.py exec equilibrate 59363805e6f46a715bc154b38dffc4e4
Submitting cluster job 'octahedra_se/c1a59a95a0e8b4526b28cf12aa0a689e/equilibrate/e1ffbf0eafe27af17b2ffc6e0c4c6dd1':
- Group: equilibrate(c1a59a95a0e8b4526b28cf12aa0a689e)
# Submit command: sbatch
#!/bin/bash
#SBATCH --job-name="octahedra_se/c1a59a95a0e8b4526b28cf12aa0a689e/equilibrate/e1ffbf0eafe27af17b2ffc6e0c4c6dd1"
#SBATCH --partition=standard
#SBATCH -t 01:00:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
set -e
set -u
# equilibrate(c1a59a95a0e8b4526b28cf12aa0a689e)
python project.py run -o equilibrate -j c1a59a95a0e8b4526b28cf12aa0a689e
# Eligible to run:
# mpiexec -n 2 python project.py exec equilibrate c1a59a95a0e8b4526b28cf12aa0a689e
In this configuration, signac flow submits one cluster job for each signac job. Each cluster job executes HOOMD-blue with 2 MPI ranks to domain decompose the simulation. You can use one cluster job for each signac job on HPC resources that have shared queues and allow you to submit many cluster jobs.
Partitioning jobs
Some HPC resources schedule jobs only by full node or limit the number of cluster jobs you can queue at one time. Or you may have many thousands of signac jobs and want to reduce time spent waiting in queue. In these cases, use MPI to partition one cluster job to executes many signac jobs in parallel (see Parallel Simulations with MPI for an introduction to MPI partitions). You can use MPI partitions alone (one rank per signac job) or in combination with MPI domain decomposition (more than one rank per signac job).
Aggregate operations in signac-flow are workflow steps that execute on a list of signac jobs. For example, you could use aggregate operations to loop over simulations and average results generated with different random number seeds. See the signac-flow documentation for more information on aggregation in general
This tutorial aggregates signac jobs in groups of a defined size and executes the group in parallel using MPI partitions. The example is small for demonstration purposes. It uses 2 MPI ranks per signac job and executes all three signac jobs in one cluster job. In production work you should choose the number of ranks per signac job (RANKS_PER_PARTITION
) and the number of signac jobs per cluster job (JOBS_PER_AGGREGATE
) to utilize an integer number of
whole nodes in each cluster job leaving no empty cores or GPUs. For example use 16 ranks per signac job and 32 signac jobs per cluster job to use 4 whole 128-core nodes per cluster job.
project_partitioned.py
modifies project.py
so that the equilibrate step executes in a partition:
[3]:
%pycat project_partitioned.py
import math
import flow
import hoomd
RANKS_PER_PARTITION = 2
JOBS_PER_AGGREGATE = 3
N_EQUIL_STEPS = 200000
WALLTIME_LIMIT = 50 * 60
def create_simulation(job, communicator):
cpu = hoomd.device.CPU(communicator=communicator)
sim = hoomd.Simulation(device=cpu, seed=job.statepoint.seed)
mc = hoomd.hpmc.integrate.ConvexPolyhedron()
mc.shape['octahedron'] = dict(vertices=[
(-0.5, 0, 0),
(0.5, 0, 0),
(0, -0.5, 0),
(0, 0.5, 0),
(0, 0, -0.5),
(0, 0, 0.5),
])
sim.operations.integrator = mc
return sim
class Project(flow.FlowProject):
pass
@Project.operation
@Project.pre.true('initialized')
@Project.post.true('randomized')
def randomize(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('lattice.gsd'))
sim.run(10e3)
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('random.gsd'))
job.document['randomized'] = True
@Project.operation
@Project.pre.after(randomize)
@Project.post.true('compressed_step')
def compress(job):
sim = create_simulation(job)
sim.create_state_from_gsd(filename=job.fn('random.gsd'))
a = math.sqrt(2) / 2
V_particle = 1 / 3 * math.sqrt(2) * a**3
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box)
final_box.volume = (sim.state.N_particles * V_particle
/ job.statepoint.volume_fraction)
compress = hoomd.hpmc.update.QuickCompress(
trigger=hoomd.trigger.Periodic(10), target_box=final_box)
sim.operations.updaters.append(compress)
periodic = hoomd.trigger.Periodic(10)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(moves=['a', 'd'],
target=0.2,
trigger=periodic,
max_translation_move=0.2,
max_rotation_move=0.2)
sim.operations.tuners.append(tune)
while not compress.complete and sim.timestep < 1e6:
sim.run(1000)
if not compress.complete:
raise RuntimeError("Compression failed to complete")
hoomd.write.GSD.write(state=sim.state,
mode='xb',
filename=job.fn('compressed.gsd'))
job.document['compressed_step'] = sim.timestep
def equilibrated(job):
return job.document.get(
'timestep', 0) - job.document['compressed_step'] >= N_EQUIL_STEPS
@Project.operation
@flow.aggregator.groupsof(num=JOBS_PER_AGGREGATE)
@Project.pre.true('compressed_step')
@Project.post(lambda *jobs: all(equilibrated(job) for job in jobs))
@flow.directives(nranks=lambda *jobs: RANKS_PER_PARTITION * len(jobs),
walltime=1)
def equilibrate(*jobs):
communicator = hoomd.communicator.Communicator(
ranks_per_partition=RANKS_PER_PARTITION)
job = jobs[communicator.partition]
end_step = job.document['compressed_step'] + N_EQUIL_STEPS
sim = create_simulation(job)
sim.operations.integrator.a = job.document.get('a', {})
sim.operations.integrator.d = job.document.get('d', {})
if job.isfile('restart.gsd'):
sim.create_state_from_gsd(filename=job.fn('restart.gsd'))
else:
sim.create_state_from_gsd(filename=job.fn('compressed.gsd'))
gsd_writer = hoomd.write.GSD(filename=job.fn('trajectory.gsd'),
trigger=hoomd.trigger.Periodic(10_000),
mode='ab')
sim.operations.writers.append(gsd_writer)
tune = hoomd.hpmc.tune.MoveSize.scale_solver(
moves=['a', 'd'],
target=0.2,
trigger=hoomd.trigger.And([
hoomd.trigger.Periodic(100),
hoomd.trigger.Before(job.document['compressed_step'] + 5_000)
]))
sim.operations.tuners.append(tune)
try:
while sim.timestep < end_step:
sim.run(min(100_000, end_step - sim.timestep))
if (sim.device.communicator.walltime + sim.walltime >=
WALLTIME_LIMIT):
break
finally:
hoomd.write.GSD.write(state=sim.state,
mode='wb',
filename=job.fn('restart.gsd'))
job.document['timestep'] = sim.timestep
job.document['a'] = sim.operations.integrator.a.to_base()
job.document['d'] = sim.operations.integrator.d.to_base()
if sim.device.communicator.rank == 0:
walltime = sim.device.communicator.walltime
print(f'{job.id} ended on step {sim.timestep} '
f'after {walltime} seconds')
if __name__ == '__main__':
Project().main()
Here are the differences between project.py
and project_partitioned.py
:
The variables
RANKS_PER_PARTITION
andJOBS_PER_AGGREGATE
set how signac-flow partitions signac jobs into cluster jobs.create_simulation
takes thecommunicator
argument and passes it to the device constructor.The directive
@flow.aggregator.groupsof(num=JOBS_PER_AGGREGATE)
definesequilibrate
as an aggregate with up toJOBS_PER_AGGREGATE
signac jobs contained in it.The pre and post conditions on
equilibrated
are now functions of an array of signac jobs:@Project.pre.true('compressed_step') @Project.post(lambda *jobs: all(equilibrated(job) for job in jobs))
The directives set the number of ranks needed by all jobs in the aggregate:
@flow.directives(nranks=lambda *jobs: RANKS_PER_PARTITION * len(jobs), walltime=CLUSTER_JOB_WALLTIME)
equilibrate
is now a function of an array of jobs and chooses the job based on the communicator’s partition.def equilibrate(*jobs): communicator = hoomd.communicator.Communicator(ranks_per_partition=RANKS_PER_PARTITION) job = jobs[communicator.partition]
(the remainder of
equilibrate
is unchanged fromproject.py
.
Here is the cluster job generated by project_partitioned.py
$ python3 project_partitioned.py submit --pretend
Submitting cluster job 'octahedra_se/agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d/equilibrate/614e7ec5470deb1e958ac9863ed1fb07':
- Group: equilibrate(agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d)
# Submit command: sbatch
#!/bin/bash
#SBATCH --job-name="octahedra_se/agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d/equilibrate/614e7ec5470deb1e958ac9863ed1fb07"
#SBATCH --partition=standard
#SBATCH -t 01:00:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=6
set -e
set -u
# equilibrate(agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d)
python project_partitioned.py run -o equilibrate -j agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d
# Eligible to run:
# mpiexec -n 6 python project_partitioned.py exec equilibrate agg-e202cc8c2ce0bc1ef7a9d9fcdcd62b6d
It generates only one cluster job that uses MPI to execute the workflow step on 6 ranks which equilibrate
splits into 3 partitions that each execute one signac job on 2 ranks each.
Esnure that your partitioned jobs set the product RANKS_PER_PARTITION * JOBS_PER_AGGREGATE to a number of CPU cores or GPUs equal to a whole number of cluster nodes on your HPC resource. Failure to do so will waste resources on HPC resources that schedule by node.
Summary
In this section of the tutorial, you defined the workflow in a file and used the signac flow command line interface to generate cluster jobs for submission. You also learned how to use partitions to more effectively use HPC resources by fully utilizing compute nodes with fewer cluster jobs.
This is the end of the tutorial on organizing and executing simulations.
This tutorial only teaches the basics of signac-flow. Read the signac-flow documentation to learn more.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
Modelling Rigid Bodies
This tutorial shows you how to run simulations of rigid bodies.
Prerequisites:
You should be familiar with the concepts taught in the tutorial Introducing HOOMD-blue, Introducing Molecular Dynamics, and have some background knowledge on statistical mechanics as well as linear algebra.
Introduction to Rigid Bodies
Overview
Questions
What is a rigid body?
How do I set rigid body parameters?
How do the rigid body parameters translate into the simulation box?
Objectives
Define a rigid body as central particle and a set of constituent particles.
Describe how body coordinates relate to global coordinates.
Enumerate the properties of rigid bodies.
Demonstrate setting the properties of a rigid dimer and creating an initial condition.
Boilerplate code
[1]:
import itertools
import math
import gsd.hoomd
import hoomd
import matplotlib
import numpy
%matplotlib inline
matplotlib.style.use('ggplot')
The render
function in the next (hidden) cell will render the system state using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Introduction
A rigid body is an incompressible body composed of one central and one or more constituent particles. All particles in a given rigid body interact with all other particles in the simulation. In molecular dynamics simulations, the central particle translates and rotates in response to the net force and torque on the body. The constituent particles follow the central particle.
Coordinate systems
You define the positions and orientations of the constituent particles in body coordinates, a coordinate system where the (0,0,0) is at the position of the central particle and the body is in a reference orientation.
For example, define the positions of two points in a rigid dimer:
[4]:
dimer_positions = [[-1.2, 0, 0], [1.2, 0, 0]]
Each instance of a rigid body in a simulation is placed in the system global coordinates, located by the position and orientation of the central particle.
[5]:
central_position = [10, 5, 0]
central_rotation = 0.9
To demonstrate, the following code block computes the global positions of the the dimer at the given central position and rotation (in 2D).
[6]:
cos_theta = math.cos(central_rotation)
sin_theta = math.sin(central_rotation)
global_positions = []
for i in range(len(dimer_positions)):
x, y = dimer_positions[i][:2]
global_positions.append(
[[central_position[0] + (x * cos_theta - y * sin_theta)],
[central_position[1] + (y * cos_theta + x * sin_theta)]])
Visualize the configuration:
[7]:
fig = matplotlib.figure.Figure(figsize=(10, 6.18), dpi=100)
ax = fig.add_subplot(aspect='equal')
ax.plot([central_position[0], central_position[0] - 3 * sin_theta],
[central_position[1], central_position[1] + 3 * cos_theta],
color='k')
ax.plot([central_position[0], central_position[0] + 3 * cos_theta],
[central_position[1], central_position[1] + 3 * sin_theta],
color='k')
ax.text(central_position[0] + 1.5 * cos_theta,
central_position[1] + 1.5 * sin_theta,
'Body X',
rotation=central_rotation * 180 / math.pi,
verticalalignment='center')
ax.text(central_position[0] - 2 * sin_theta,
central_position[1] + 2 * cos_theta,
'Body Y',
rotation=central_rotation * 180 / math.pi + 90,
verticalalignment='center')
ax.add_patch(
matplotlib.patches.Circle((central_position[0], central_position[1]),
0.1,
color='C0'))
for position in global_positions:
ax.add_patch(
matplotlib.patches.Circle((position[0], position[1]), 1.0, color='C1'))
ax.set_xlim(0, 20)
ax.set_ylim(0, 12)
ax.set_xlabel('Global X')
ax.set_ylabel('Global Y')
fig
[7]:

Properties of rigid bodies
The following rigid body properties are given by the properties of the central particle:
Mass - the total mass of the rigid body.
Moment of inertia tensor - how mass is distributed throughout the rigid body.
Velocity - velocity of the center of mass of the rigid body.
Angular momentum - angular momentum of the rigid body.
Position - the position in global coordinates. Example:
position = [1, 2, -3]
Orientation - a quaternion that rotates the rigid body about the central particle. Example:
orientation = [1, 0, 0, 0]
The following constituent particle properties are given by the properties of a given rigid body type:
Constituent Particle Positions - The vector from the center of the rigid body to the constituent particle in body coordinates.
Constituent Particle Orientation - A quaternion that rotates the constituent particle about its center.
Defining properties of the rigid dimer
Let each constituent particle in the dimer be a point particle of type A with mass 1 at the constituent positions previously defined in dimer_positions
. Each dimer will be located at the position of a particle of type dimer.
Let’s create an initial configuration of dimers. Start with a snapshot containing both particle types:
[8]:
snapshot = gsd.hoomd.Snapshot()
snapshot.particles.types = ['dimer', 'A']
Place dimer particles (typeid=0
) in the simulation box. Place them far enough apart so that the A particles will not touch in the initial condition:
[9]:
m = 4
N_particles = m**3
spacing = 5
K = math.ceil(N_particles**(1 / 3))
L = K * spacing
x = numpy.linspace(-L / 2, L / 2, K, endpoint=False)
position = list(itertools.product(x, repeat=3))
position = numpy.array(position) + [spacing / 2, spacing / 2, spacing / 2]
snapshot.particles.N = N_particles
snapshot.particles.position = position[0:N_particles, :]
snapshot.particles.typeid = [0] * N_particles
snapshot.configuration.box = [L, L, L, 0, 0, 0]
With two mass 1 particles, the total mass of the body is 2. Set the mass of each instance of the body:
[10]:
snapshot.particles.mass = [2] * N_particles
The moment of inertia of a point particle about a given axis is given by \(I_i = m r_i^2\), where \(r_i\) is the distance of the point from the axis. More generally, the moment of inertia is a tensor and includes off-diagonal values (you will learn more about this in a later tutorial section).
Compute the moment of inertia of the dimer:
[11]:
mass = 1
I = numpy.zeros(shape=(3, 3))
for r in dimer_positions:
I += mass * (numpy.dot(r, r) * numpy.identity(3) - numpy.outer(r, r))
I
[11]:
array([[0. , 0. , 0. ],
[0. , 2.88, 0. ],
[0. , 0. , 2.88]])
In this case, the tensor is diagonal. This is important as HOOMD-blue assumes that bodies have a diagonal moment of inertia in body coordinates in the form: \([I_{xx}, I_{yy}, I_{zz}]\). Set the moments of inertia of each body in the snapshot:
[12]:
snapshot.particles.moment_inertia = [I[0, 0], I[1, 1], I[2, 2]] * N_particles
Notice that \(I_{xx}\) is zero for this dimer while \(I_{yy}\) and \(I_{zz}\) are non-zero. HOOMD-blue checks which moments of inertia are non-zero and integrates degrees of freedom only for those axes with non-zero moments of inertia. In this example, the dimer will rotate about the body’s y and z axes, but not x.
HOOMD-blue represents orientations with quaternions. The quaternion \([1, 0, 0, 0]\) is the identity. Set the orientation of each body in the snapshot to the identity:
[13]:
snapshot.particles.orientation = [(1, 0, 0, 0)] * N_particles
Write the rigid centers to a GSD file for later use:
[14]:
with gsd.hoomd.open(name='dimer_centers.gsd', mode='xb') as f:
f.append(snapshot)
The hoomd.md.constrain.Rigid
class is responsible for applying the rigid body constraints:
[15]:
rigid = hoomd.md.constrain.Rigid()
Set the constituent particle properties in body coordinates for the rigid body type:
[16]:
rigid.body['dimer'] = {
"constituent_types": ['A', 'A'],
"positions": dimer_positions,
"orientations": [(1.0, 0.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0)],
"charges": [0.0, 0.0],
"diameters": [1.0, 1.0]
}
Rigid
will use positions and orientations to set the global positions and orientations of all constituent particles on every time step. The constituent_types
, charges
, and diameters
fields provide a template for create_bodies
(see below).
Placing constituent particles in the initial condition
So far, our snapshot has only the dimer central particles:
[17]:
sim = hoomd.Simulation(device=hoomd.device.CPU(), seed=4)
sim.create_state_from_gsd(filename='dimer_centers.gsd')
render(sim.state.get_snapshot())
[17]:

Rigid.create_bodies
will place constituent particles in the simulation state:
[18]:
rigid.create_bodies(sim.state)
Each central particle now has the two constituent particles of the dimer placed around it:
[19]:
render(sim.state.get_snapshot())
[19]:

Understand that Rigid
will overwrite the positions and orientations of the constituent particles in the simulation state. To demonstrate, let’s modify the positions of the constituents:
[20]:
with sim.state.cpu_local_snapshot as snapshot:
typeid = snapshot.particles.typeid
snapshot.particles.position[typeid == 1] = [0, 0, 0]
[21]:
render(sim.state.get_snapshot())
[21]:

Set the rigid
constraint with the MD integrator so it will take effect on the simulation. The next section of this tutorial will explain these steps in more detail:
[22]:
integrator = hoomd.md.Integrator(dt=0.005, integrate_rotational_dof=True)
integrator.rigid = rigid
sim.operations.integrator = integrator
Rigid
will apply the rigid body constraints at the start of a simulation run and on every timestep. Calling sim.run(0)
will restore the constituent particle positions:
[23]:
sim.run(0)
render(sim.state.get_snapshot())
[23]:

To change the position or orientation of a given body, change the properties of the central particle:
[24]:
with sim.state.cpu_local_snapshot as snapshot:
typeid = snapshot.particles.typeid
snapshot.particles.orientation[typeid == 0] = [
0.70710678, 0., 0.70710678, 0.
]
Again, execute sim.run(0)
for the changes to take effect on the constituent particles.
[25]:
sim.run(0)
render(sim.state.get_snapshot())
[25]:

Write the configuration to a file for use in the next tutorial section:
[26]:
hoomd.write.GSD.write(state=sim.state, mode='xb', filename='lattice.gsd')
In this section, you learned how HOOMD-blue composes rigid bodies of central and constituent particles and about all the properties of those bodies. You also saw how to define these parameters and how Rigid
updates them in the simulation state. The next section will explain how to run a molecular dynamics simulation of this system.
Running Rigid Body Simulations
Overview
Questions
How do I initialize rigid bodies from a GSD file?
How do I integrate the rigid bodies in my simulation?
How are thermodynamic quantities of rigid bodies measured?
Objectives
Describe how to continue simulations from a GSD file.
Explain integration of rotational degrees of freedom.
Show how to exclude intra-body pairwise interactions.
Run a rigid body MD simulation at constant temperature.
Demonstrate that rigid bodies equilibrate both translational and rotational degrees of freedom.
Boilerplate code
[1]:
import math
import hoomd
The render
function in the next (hidden) cell will render the system state using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Continuing the simulation from a GSD file.
The previous section created an initial condition containing dimer particles in lattice.gsd
. Initialize a new simulation from this file:
[3]:
cpu = hoomd.device.CPU()
sim = hoomd.Simulation(device=cpu, seed=1)
sim.create_state_from_gsd(filename='lattice.gsd')
hoomd.md.constrain.Rigid
is responsible for applying the rigid body constraints to the particles in the simulation.
Create the rigid constraint:
[4]:
rigid = hoomd.md.constrain.Rigid()
The body
property of Rigid
is not saved to the GSD file. You need to define the parameters again in the new simulation:
[5]:
rigid.body['dimer'] = {
"constituent_types": ['A', 'A'],
"positions": [[-1.2, 0, 0], [1.2, 0, 0]],
"orientations": [(1.0, 0.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0)],
"charges": [0.0, 0.0],
"diameters": [1.0, 1.0]
}
In workflows, you can store this in a file of your choosing or use the project document in signac.
Integrating rigid body degrees of freedom
Create an Integrator with the option integrate_rotational_dof=True
:
[6]:
integrator = hoomd.md.Integrator(dt=0.005, integrate_rotational_dof=True)
sim.operations.integrator = integrator
The default value of integrate_rotational_dof
is False
, When False
, the integrator will ignore all torques on particles and integrate only the translational degrees of freedom. When True
, the integrator will integrate both the translational and rotational degrees of freedom.
Assign the rigid constraint to the integrator’s rigid
attribute to apply the constraints during the simulation.
[7]:
integrator.rigid = rigid
The translational and rotational degrees of freedom are given to the central particles of the rigid bodies. Select only the rigid centers and free particles for the integration method:
[8]:
kT = 1.5
rigid_centers_and_free = hoomd.filter.Rigid(("center", "free"))
nvt = hoomd.md.methods.NVT(kT=kT, tau=1., filter=rigid_centers_and_free)
integrator.methods.append(nvt)
Defining Pair Potentials Between Bodies
Create a neighbor list with body exclusions so that the pair potential does not compute intra-body interactions:
[9]:
cell = hoomd.md.nlist.Cell(buffer=0, exclusions=['body'])
Without body exclusions, the simulation may be numerically unstable due to round-off errors when subtracting large numbers. In either case, the intra-body forces contribute 0 to the net force and 0 to the net torque, so there is no need to compute them.
Apply the Lennard-Jones potential between A-A particle pairs.
[10]:
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
The central particles (type dimer) are also present in the system. Make the dimer particles non-interacting with a 0 r_cut
:
[11]:
lj.params[('dimer', ['dimer', 'A'])] = dict(epsilon=0, sigma=0)
lj.r_cut[('dimer', ['dimer', 'A'])] = 0
You do not have to make the central particles non-interacting. You can choose any potential parameters suitable for your model.
[12]:
integrator.forces.append(lj)
Compressing the system
We have initialized the system state, added the integrator, set the rigid constraint, and defined the pairwise particle interactions. Before we run the simulation, we need to set initial velocities and angular momenta of the rigid body central particles and free particles:
[13]:
sim.state.thermalize_particle_momenta(filter=rigid_centers_and_free, kT=kT)
sim.run(0)
nvt.thermalize_thermostat_dof()
thermalize_particle_momenta
assigns gaussian distributed momenta to each translational and rotational degree of freedom for each particle given in the filter. In this case, it wil assign momenta about the y and z axes, but not x because \(I_{xx} = 0\).
Now we can run the simulation to randomize the body positions and orientations:
[14]:
sim.run(1000)
[15]:
render(sim.state.get_snapshot())
[15]:

This simulation box is dilute. Compress the box to a higher density state before continuing:
[16]:
initial_box = sim.state.box
final_box = hoomd.Box.from_box(initial_box) # make a copy of initial_box
final_box.volume = initial_box.volume / 16
box_resize_trigger = hoomd.trigger.Periodic(10)
ramp = hoomd.variant.Ramp(A=0, B=1, t_start=sim.timestep, t_ramp=20000)
box_resize = hoomd.update.BoxResize(box1=initial_box,
box2=final_box,
variant=ramp,
trigger=box_resize_trigger)
sim.operations.updaters.append(box_resize)
Run the simulation to compress the box:
[17]:
sim.run(30000)
[18]:
render(sim.state.get_snapshot())
[18]:

Thermodynamic properties of rigid bodies
Add the ThermodynamicQuantities
compute to the simulation:
[19]:
thermodynamic_quantities = hoomd.md.compute.ThermodynamicQuantities(
filter=hoomd.filter.All())
sim.operations.computes.append(thermodynamic_quantities)
ThermodynamicQuantities
computes translational and rotational kinetic energy separately:
[20]:
thermodynamic_quantities.translational_kinetic_energy
[20]:
136.95366173865793
[21]:
thermodynamic_quantities.rotational_kinetic_energy
[21]:
105.62170571721094
These values are consistent (within exepected thermodynamic fluctuations) with the equipartition theorem:
[22]:
translational_degrees_of_freedom = thermodynamic_quantities.translational_degrees_of_freedom
print('Translational degrees of freedom:', translational_degrees_of_freedom)
print('1/2 kT * translational degrees of freedom:',
1 / 2 * kT * translational_degrees_of_freedom)
Translational degrees of freedom: 189.0
1/2 kT * translational degrees of freedom: 141.75
[23]:
rotational_degrees_of_freedom = thermodynamic_quantities.rotational_degrees_of_freedom
print('Rotataional degrees of freedom:', rotational_degrees_of_freedom)
print('1/2 kT * rotational degrees of freedom:',
1 / 2 * kT * rotational_degrees_of_freedom)
Rotataional degrees of freedom: 128.0
1/2 kT * rotational degrees of freedom: 96.0
Note that the number of rotational degrees is freedom is 2 times the number of particles as we assigned 2 non-zero moments of inertia.
In this section, you learned how to continue running a simulation with rigid bodies in a GSD file, define inter-body pairwise interactions and integrate the translational and rotational degrees of freedom with an integration method. The next section will explain how to prepare general rigid bodies for HOOMD-blue.
Preparing a General Body
Overview
Questions
How do I input arbitrary rigid body into HOOMD-blue?
Objectives
Define an rigid body with an arbitrary inertia tensor.
Diagonalize the moment of inertia.
Reorient the constituent particles in the diagonal body coordinates.
Boilerplate code
[1]:
import math
import numpy
The render_rigid_body
function in the next (hidden) cell will render the rigid body using fresnel.
This is not intended as a full tutorial on fresnel - see the fresnel user documentation if you would like to learn more.
Diagonalized bodies:
HOOMD-blue assumes bodies are provided in a coordinate system where the moment of inertia tensor is diagonal.
Given a body with arbitrarily placed constituent particles, you can follow this procedure to prepare the body for use in HOOMD.
Step 1: Get the inertia tensor of your rigid body (non-diagonalized).
Step 2: Solve for the orientation of the body that diagonalizes the moment of inertia tensor.
Step 3: Reorient the rigid body so that the rigid body inertia tensor is diagonalized in global coordinates.
Step 4: Define the moments of inertia using the new diagonalized moments of inertia.
The remainder of this tutorial section demonstrates these steps for this body:
[3]:
general_positions = numpy.array([[.5, .5, 0], [-.5, -.5, 0], [-1, 1, 0],
[1, -1, 0]])
particle_mass = 1
particle_radius = 1
[4]:
render_rigid_body(general_positions)
[4]:

Step 1: Compute the inertia tensor
HOOMD-blue makes no assumptions about the distribution of mass in your body. For example, you can compute the moment of inertia assuming that each consituent particle is a uniform density ball. The moment of inertia of a single ball computed about the center of the ball is:
[5]:
I_ref = numpy.array([[2 / 5 * particle_mass * particle_radius**2, 0, 0],
[0, 2 / 5 * particle_mass * particle_radius**2, 0],
[0, 0, 2 / 5 * particle_mass * particle_radius**2]])
I_ref
[5]:
array([[0.4, 0. , 0. ],
[0. , 0.4, 0. ],
[0. , 0. , 0.4]])
Using the parallel axis theorem, compute the moment of inertia tensor for the general body as a sum of constituent particle inertia tensors: \(I = I_{ref} + m[(D\cdot D)E_3 - D\otimes D]\)
\(I_{ref}\) is the reference moment of inertia, m is the mass, D is the displacement (i.e. the position of the constituent particle in body coordinates) and \(E_3\) is the identity matrix.
[6]:
I_general = numpy.zeros(shape=(3, 3))
for r in general_positions:
I_general += I_ref + particle_mass * (numpy.dot(r, r) * numpy.identity(3)
- numpy.outer(r, r))
I_general
[6]:
array([[4.1, 1.5, 0. ],
[1.5, 4.1, 0. ],
[0. , 0. , 6.6]])
Notice that some of the off-diagonal elements are non-zero. These body coordinates are not appropriate for use in HOOMD-blue.
Step 2: Diagonalize the moment of inertia
First, find the eigenvalues of the general moment of inertia:
[7]:
I_diagonal, E_vec = numpy.linalg.eig(I_general)
The diagonalized moment of inertia are the \([I_{xx}, I_{yy}, I_{zz}]\) needed by HOOMD-blue:
[8]:
I_diagonal
[8]:
array([5.6, 2.6, 6.6])
The transpose of the eigenvector matrix rotates the original particles into the frame where the inertia tensor is diagonalized:
[9]:
R = E_vec.T
Rotate the particles by this matrix:
[10]:
diagonal_positions = numpy.dot(R, general_positions.T).T
diagonal_positions
[10]:
array([[ 7.07106781e-01, -5.55111512e-17, 0.00000000e+00],
[-7.07106781e-01, 5.55111512e-17, 0.00000000e+00],
[ 1.11022302e-16, 1.41421356e+00, 0.00000000e+00],
[-1.11022302e-16, -1.41421356e+00, 0.00000000e+00]])
[11]:
render_rigid_body(diagonal_positions)
[11]:

The rigid body has now been aligned its principle rotational axes with the x, y, and z body axes. Use diagonal_positions
as body coordinates along with I_diagonal
as the central particle’s moment_inertia
.
To check, let’s confirm that the directly calculated moment of inertia of the new coordinates is diagonal.
[12]:
I_check = numpy.zeros(shape=(3, 3))
for r in diagonal_positions:
I_check += I_ref + particle_mass * (numpy.dot(r, r) * numpy.identity(3)
- numpy.outer(r, r))
I_check
[12]:
array([[ 5.60000000e+00, -2.35513869e-16, 0.00000000e+00],
[-2.35513869e-16, 2.60000000e+00, 0.00000000e+00],
[ 0.00000000e+00, 0.00000000e+00, 6.60000000e+00]])
This moment of inertia is diagonal within numerical precision.
When the diagonalization process produces very small numerical values for the diagonal elements, set them to 0 explicitly to disable those degrees of freedom. Otherwise, HOOMD-blue will attempt to integrate them, resulting in numerical instabilities.
This is the end of the introduction to the modelling rigid bodies tutorial! It described the properties of rigid bodies, showed how to run a simulation of dimers, and demonstrated how to diagonalize the moment of inertia of general bodies. See the other HOOMD-blue tutorials to learn about other concepts, or browse the reference documentation for more information.
This tutorial is written with jupyter. You can download the source from the hoomd-examples repository.
How to model molecular systems
To model molecular systems using molecular dynamics in HOOMD-blue:
Define the bonds, angles, dihedrals, impropers, and constraints as needed to the system
State
.Add the needed potentials and/or constraints to the integrator (see
md.bond
,md.angle
,md.dihedral
,md.improper
, andmd.constrain
).
This code demonstrates bonds by modelling a Gaussian chain:
# Copyright (c) 2009-2022 The Regents of the University of Michigan.
# Part of HOOMD-blue, released under the BSD 3-Clause License.
import hoomd
import gsd.hoomd
snapshot = gsd.hoomd.Snapshot()
# Place a polymer in the box.
snapshot.particles.N = 5
snapshot.particles.position = [[-2, 0, 0], [-1, 0, 0], [0, 0, 0], [1, 0, 0],
[2, 0, 0]]
snapshot.particles.types = ['A']
snapshot.particles.typeid = [0] * 5
snapshot.configuration.box = [20, 20, 20, 0, 0, 0]
# Connect particles with bonds.
snapshot.bonds.N = 4
snapshot.bonds.types = ['A-A']
snapshot.bonds.typeid = [0] * 4
snapshot.bonds.group = [[0, 1], [1, 2], [2, 3], [3, 4]]
with gsd.hoomd.open(name='molecular.gsd', mode='xb') as f:
f.append(snapshot)
# Apply the harmonic potential on the bonds.
harmonic = hoomd.md.bond.Harmonic()
harmonic.params['A-A'] = dict(k=100, r0=1.0)
# Perform the MD simulation.
sim = hoomd.Simulation(device=hoomd.device.CPU(), seed=1)
sim.create_state_from_gsd(filename='molecular.gsd')
langevin = hoomd.md.methods.Langevin(filter=hoomd.filter.All(), kT=1.0)
integrator = hoomd.md.Integrator(dt=0.005,
methods=[langevin],
forces=[harmonic])
gsd_writer = hoomd.write.GSD(filename='molecular_trajectory.gsd',
trigger=hoomd.trigger.Periodic(1000),
mode='xb')
sim.operations.integrator = integrator
sim.operations.writers.append(gsd_writer)
sim.run(10e3)
Consider using a tool to build systems, such as the Molecular Simulation Design Framework (MoSDeF). For example, mBuild can assemble reusable components into complex molecular systems, and foyer can perform atom-typing and define classical molecular modeling force fields. The mosdef-workflows demonstrates how to use these tools with HOOMD-blue
hoomd
Overview
Define box dimensions. |
|
A mutable collection of operations which act on a |
|
Define a simulation. |
|
Self-contained copy of the simulation |
|
The state of a |
Details
HOOMD-blue python package.
hoomd
is the top level HOOMD-blue Python package. It consists of the common
code shared among all types of HOOMD-blue simulations. The core data structures
used to construct a simulation include:
See the table of contents or the modules section for a full list of classes, methods, and variables in the API.
hoomd
also contains subpackages that implement specific types of simulations:
hoomd.hpmc
- Hard particle Monte Carlo.hoomd.md
- Molecular dynamics.
See also
Tutorial: Introducing HOOMD-blue
- class hoomd.Box(Lx, Ly, Lz=0, xy=0, xz=0, yz=0)
Define box dimensions.
- Parameters
Lx (float) – box extent in the x direction \([\mathrm{length}]\).
Ly (float) – box extent in the y direction \([\mathrm{length}]\).
Lz (float) – box extent in the z direction \([\mathrm{length}]\).
xy (float) – tilt factor xy \([\mathrm{dimensionless}]\).
xz (float) – tilt factor xz \([\mathrm{dimensionless}]\).
yz (float) – tilt factor yz \([\mathrm{dimensionless}]\).
Particles in a simulation exist in a triclinic box with periodic boundary conditions. A triclinic box is defined by six values: the extents \(L_x\), \(L_y\) and \(L_z\) of the box in the three directions, and three tilt factors \(xy\), \(xz\) and \(yz\).
The parameter matrix is defined in terms of the lattice vectors \(\vec a_1\), \(\vec a_2\) and \(\vec a_3\):
\[\left( \vec a_1, \vec a_2, \vec a_3 \right)\]The first lattice vector \(\vec a_1\) is parallel to the unit vector \(\vec e_x = (1,0,0)\). The tilt factor \(xy\) indicates how the second lattice vector \(\vec a_2\) is tilted with respect to the first one. Similarly, \(xz\) and \(yz\) indicate the tilt of the third lattice vector \(\vec a_3\) with respect to the first and second lattice vector.
The full cell parameter matrix is:
\[\begin{split}\left(\begin{array}{ccc} L_x & xy L_y & xz L_z \\ 0 & L_y & yz L_z \\ 0 & 0 & L_z \\ \end{array}\right)\end{split}\]The tilt factors \(xy\), \(xz\) and \(yz\) are dimensionless. The relationships between the tilt factors and the box angles \(\alpha\), \(\beta\) and \(\gamma\) are as follows:
\[\begin{split}\cos\gamma &= \cos(\angle\vec a_1, \vec a_2) &=& \frac{xy}{\sqrt{1+xy^2}}\\ \cos\beta &= \cos(\angle\vec a_1, \vec a_3) &=& \frac{xz}{\sqrt{1+xz^2+yz^2}}\\ \cos\alpha &= \cos(\angle\vec a_2, \vec a_3) &=& \frac{xy \cdot xz + yz}{\sqrt{1+xy^2} \sqrt{1+xz^2+yz^2}}\end{split}\]Given an arbitrarily oriented lattice with box vectors \(\vec v_1, \vec v_2, \vec v_3\), the parameters for the rotated box can be found as follows:
\[\begin{split}L_x &= v_1\\ a_{2x} &= \frac{\vec v_1 \cdot \vec v_2}{v_1}\\ L_y &= \sqrt{v_2^2 - a_{2x}^2}\\ xy &= \frac{a_{2x}}{L_y}\\ L_z &= \vec v_3 \cdot \frac{\vec v_1 \times \vec v_2}{\left| \vec v_1 \times \vec v_2 \right|}\\ a_{3x} &= \frac{\vec v_1 \cdot \vec v_3}{v_1}\\ xz &= \frac{a_{3x}}{L_z}\\ yz &= \frac{\vec v_2 \cdot \vec v_3 - a_{2x}a_{3x}}{L_y L_z}\end{split}\]Box images
HOOMD-blue always stores particle positions \(\vec{r}\) inside the primary box image which includes the origin at the center. The primary box image include the left, bottom, and back face while excluding the right, top, and front face. In cubic boxes, this implies that the particle coordinates in the primary box image are in the interval \(\left[ -\frac{L}{2},\frac{L}{2} \right)\).
Unless otherwise noted in the documentation, operations apply the minimum image convention when computing pairwise interactions between particles:
\[\vec{r}_{ij} = \mathrm{minimum\_image}(\vec{r}_j - \vec{r}_i)\]When running simulations with a fixed box size, you use the particle images \(\vec{n}\) to compute the unwrapped coordinates:
\[\vec{r}_\mathrm{unwrapped} = \vec{r} + n_x \vec{a}_1 + n_y \vec{a}_2 + n_z \vec{a}_3\]The Box class
Simulation boxes in hoomd are specified by six parameters,
Lx
,Ly
,Lz
,xy
,xz
, andyz
.Box
provides a way to specify all six parameters for a given box and perform some common operations with them. ABox
can be stored in a GSD file, passed to an initialization method or to assigned to a savedState
variable (state.box = new_box
) to set the simulation box.Access attributes directly:
box = hoomd.Box.cube(L=20) box.xy = 1.0 box.yz = 0.5 box.Lz = 40
Two dimensional systems
Set
Lz == 0
to make the box 2D. 2D boxes ignorexz
andyz
. Changing the box dimensionality from 2D to 3D (or from 3D to 2D) during a simulation will result in undefined behavior.In 2D boxes, volume is in units of \([\mathrm{length}]^2\).
Factory Methods
Box
has factory methods to enable easier creation of boxes:cube
,square
,from_matrix
, andfrom_box
. See the method documentation for usage.Examples
Cubic box with given length:
hoomd.Box.cube(L=1)
Square box with given length:
hoomd.Box.square(L=1)
From an upper triangular matrix:
hoomd.Box.from_matrix(matrix)
Specify values:
hoomd.Box(Lx=1., Ly=2., Lz=3., xy=1., xz=2., yz=3.)
- property L
The box lengths,
[Lx, Ly, Lz]
\([\mathrm{length}]\).Can be set with a float which sets all lengths, or a length 3 vector.
- Type
(3, )
numpy.ndarray
offloat
- __eq__(other)
Test if boxes are equal.
- __neq__(other)
Test if boxes are not equal.
- __reduce__()
Reduce values to picklable format.
- __repr__()
Executable representation of the object.
- classmethod cube(L)
Create a cube with side lengths
L
.
- property dimensions
The dimensionality of the box.
If
Lz == 0
, the box is treated as 2D, otherwise it is 3D. This property is not settable.- Type
- classmethod from_box(box)
Initialize a Box instance from a box-like object.
- Parameters
box (box_like) – A box-like object.
Note
If all values are provided, a triclinic box will be constructed. If only
Lx, Ly, Lz
are provided, an orthorhombic box will be constructed. If onlyLx, Ly
are provided, a rectangular (2D) box will be constructed.- Returns
The resulting box object.
- Return type
- classmethod from_matrix(box_matrix)
Create a box from an upper triangular matrix.
- Parameters
box_matrix ((3, 3)
numpy.ndarray
offloat
) –An upper triangular matrix representing a box. The values for
Lx
,Ly
,Lz
,xy
,xz
, andyz
are related to the matrix by the following expressions.[[Lx, Ly * xy, Lz * xz], [0, Ly, Lz * yz], [0, 0, Lz]]
- Returns
The created box.
- Return type
- property is2D
Flag whether the box is 2D.
If
Lz == 0
, the box is treated as 2D, otherwise it is 3D. This property is not settable.- Type
- property periodic
The periodicity of each dimension.
- Type
(3, )
numpy.ndarray
ofbool
- scale(s)
Scale box dimensions.
Scales the box in place by the given scale factors. Tilt factors are not modified.
- classmethod square(L)
Create a square with side lengths
L
.
- property tilts
The box tilts,
[xy, xz, yz]
.Can be set using one tilt for all axes or three tilts. If the box is 2D
xz
andyz
will automatically be set to zero.- Type
(3, )
numpy.ndarray
offloat
- to_matrix()
(3, 3)
numpy.ndarray
float
: The upper triangular matrix that defines the box.[[Lx, Ly * xy, Lz * xz], [0, Ly, Lz * yz], [0, 0, Lz]]
- property volume
Volume of the box.
\([\mathrm{length}]^{2}\) in 2D and \([\mathrm{length}]^{3}\) in 3D.
When setting volume the aspect ratio of the box is maintained while the lengths are changed.
- Type
- class hoomd.Operations
A mutable collection of operations which act on a
Simulation
.An
Operations
class instance contains all the operations acting on a simulation. These operations are classes that perform various actions on ahoomd.Simulation
. Operations can be added and removed at any point from ahoomd.Operations
instance. The class provides the interface defined bycollections.abc.Collection
. Other methods for manipulating instances mimic Python objects where possible, but the class is not simply a mutable list or set.Operations
objects manage multiple independent sequences described below.The types of operations which can be added to an
Operations
object are tuners, updaters, integrators, writers, and computes. AnOperations
instance can have zero or one integrator and any number of tuners, updaters, writers, or computes. To see examples of these types of operations seehoomd.tune
(tuners),hoomd.update
(updaters),hoomd.hpmc.integrate
orhoomd.md.Integrator
(integrators),hoomd.write
(writers), andhoomd.md.compute.ThermodynamicQuantities
(computes).A given instance of an operation class can only be added to a single
Operations
container. Likewise, a single instance cannot be added to the sameOperations
container more than once.All
Operations
instances start with ahoomd.tune.ParticleSorter
instance in theirtuners
attribute. This increases simulation performance. However, users can choose to modify or remove this tuner if desired.Note
An
Operations
object is created by default when a new simulation is created.- __contains__(operation)
Whether an operation is contained in this container.
- Parameters
operation – Returns whether this exact operation is contained in the collection.
- __getstate__()
Get the current state of the operations container for pickling.
- __iadd__(operation)
Works the same as
Operations.add
.- Parameters
operation (hoomd.operation.Operation) – A HOOMD-blue tuner, updater, integrator, writer, or compute to add to the object.
- __isub__(operation)
Works the same as
Operations.remove
.- Parameters
operation (hoomd.operation.Operation) – A HOOMD-blue integrator, tuner, updater, integrator, analyzer, or compute to remove from the collection.
- __iter__()
Iterates through all contained operations.
- __len__()
Return the number of operations contained in this collection.
- add(operation)
Add an operation to this container.
Adds the provided operation to the appropriate attribute of the
Operations
instance.- Parameters
operation (hoomd.operation.Operation) – A HOOMD-blue tuner, updater, integrator, writer, or compute to add to the collection.
- Raises
TypeError – If
operation
is not of a valid type.
Note
Since only one integrator can be associated with an
Operations
object at a time, this removes the current integrator when called with an integrator operation. Also, theintegrator
property cannot be set toNone
using this function. Useoperations.integrator = None
explicitly for this.
- property computes
A list of compute operations.
Holds the list of computes associated with this collection. The list can be modified as a standard Python list.
- Type
list[
hoomd.operation.Compute
]
- property integrator
An MD or HPMC integrator object.
Operations
objects have an initialintegrator
property ofNone
. Can be set to MD or HPMC integrators. The property can also be set toNone
.
- property is_tuning_complete
Check whether all children have completed tuning.
True
whenis_tuning_complete
isTrue
for all children.Note
In MPI parallel execution,
is_tuning_complete
isTrue
only when all children on all ranks have completed tuning.- Type
- remove(operation)
Remove an operation from the
Operations
object.Remove the item from the collection whose Python object
id
is the same asoperation
.- Parameters
operation (hoomd.operation.Operation) – A HOOMD-blue integrator, tuner, updater, integrator, or compute to remove from the container.
- Raises
ValueError – If
operation
is not found in this container.TypeError – If
operation
is not of a valid type.
- tune_kernel_parameters()
Start tuning kernel parameters in all children.
- property tuners
A list of tuner operations.
Holds the list of tuners associated with this collection. The list can be modified as a standard Python list.
- Type
list[
hoomd.operation.Tuner
]
- property updaters
A list of updater operations.
Holds the list of updaters associated with this collection. The list can be modified as a standard Python list.
- Type
list[
hoomd.operation.Updater
]
- property writers
A list of writer operations.
Holds the list of writers associated with this collection. The list can be modified as a standard Python list.
- Type
list[
hoomd.operation.Writer
]
- class hoomd.Simulation(device, seed=None)
Define a simulation.
- Parameters
device (hoomd.device.Device) – Device to execute the simulation.
seed (int) – Random number seed.
Simulation
is the central class that defines a simulation, including thestate
of the system, theoperations
that apply to the state during a simulationrun
, and thedevice
to use when executing the simulation.seed
sets the seed for the random number generator used by all operations added to thisSimulation
.Newly initialized
Simulation
objects have no state. Callcreate_state_from_gsd
orcreate_state_from_snapshot
to initialize the simulation’sstate
.- property always_compute_pressure
Always compute the virial and pressure (defaults to
False
).By default, HOOMD only computes the virial and pressure on timesteps where it is needed (when
hoomd.write.GSD
writes log data to a file or when using an NPT integrator). Setalways_compute_pressure
to True to make the per particle virial, net virial, and system pressure available to query any time by property or through thehoomd.logging.Logger
interface.Note
Enabling this flag will result in a moderate performance penalty when using MD pair potentials.
- Type
- create_state_from_gsd(filename, frame=-1, domain_decomposition=(None, None, None))
Create the simulation state from a GSD file.
- Parameters
filename (str) – GSD file to read
frame (int) – Index of the frame to read from the file. Negative values index back from the last frame in the file.
domain_decomposition (tuple) – Choose how to distribute the state across MPI ranks with domain decomposition. Provide a tuple of 3 integers indicating the number of evenly spaced domains in the x, y, and z directions (e.g.
(8,4,2)
). Provide a tuple of 3 lists of floats to set the fraction of the simulation box to include in each domain. The sum of each list of floats must be 1.0 (e.g.([0.25, 0.75], [0.2, 0.8], [1.0])
).
When
timestep
isNone
before calling,create_state_from_gsd
setstimestep
to the value in the selected GSD frame in the file.Note
Set any or all of the
domain_decomposition
tuple elements toNone
andcreate_state_from_gsd
will select a value that minimizes the surface area between the domains (e.g.(2,None,None)
). The domains are spaced evenly along each automatically selected direction. The default value of(None, None, None)
will automatically select the number of domains in all directions.
- create_state_from_snapshot(snapshot, domain_decomposition=(None, None, None))
Create the simulation state from a
Snapshot
.- Parameters
snapshot (Snapshot or gsd.hoomd.Snapshot) – Snapshot to initialize the state from. A
gsd.hoomd.Snapshot
will first be converted to ahoomd.Snapshot
.domain_decomposition (tuple) – Choose how to distribute the state across MPI ranks with domain decomposition. Provide a tuple of 3 integers indicating the number of evenly spaced domains in the x, y, and z directions (e.g.
(8,4,2)
). Provide a tuple of 3 lists of floats to set the fraction of the simulation box to include in each domain. The sum of each list of floats must be 1.0 (e.g.([0.25, 0.75], [0.2, 0.8], [1.0])
).
When
timestep
isNone
before calling,create_state_from_snapshot
setstimestep
to 0.Note
Set any or all of the
domain_decomposition
tuple elements toNone
andcreate_state_from_snapshot
will select a value that minimizes the surface area between the domains (e.g.(2,None,None)
). The domains are spaced evenly along each automatically selected direction. The default value of(None, None, None)
will automatically select the number of domains in all directions.
- property device
Device used to execute the simulation.
- Type
- property final_timestep
run
will end at this timestep.final_timestep
is the timestep on which the currently executingrun
will complete.(
Loggable
: category=”scalar”)- Type
- property initial_timestep
run
started at this timestep.initial_timestep
is the timestep on which the currently executingrun
started.(
Loggable
: category=”scalar”)- Type
- property operations
The operations that apply to the state.
The operations apply to the state during the simulation run when scheduled.
See also
- Type
- run(steps, write_at_start=False)
Advance the simulation a number of steps.
- Parameters
Note
Initialize the simulation’s state before calling
run
.Simulation
applies itsoperations
to the state during each time step in the order: tuners, updaters, integrator, then writers following the logic in this pseudocode:if write_at_start: for writer in operations.writers: if writer.trigger(timestep): writer.write(timestep) end_step = timestep + steps while timestep < end_step: for tuner in operations.tuners: if tuner.trigger(timestep): tuner.tune(timestep) for updater in operations.updaters: if updater.trigger(timestep): updater.update(timestep) if operations.integrator is not None: operations.integrator(timestep) timestep += 1 for writer in operations.writers: if writer.trigger(timestep): writer.write(timestep)
This order of operations ensures that writers (such as
hoomd.write.GSD
) capture the final output of the last step of the run loop. For example, a writer with a triggerhoomd.trigger.Periodic(period=100, phase=0)
active during arun(500)
would write on steps 100, 200, 300, 400, and 500. Setwrite_at_start=True
on the first call torun
to also obtain output at step 0.Warning
Using
write_at_start=True
in subsequent calls torun
will result in duplicate output frames.
- property seed
Random number seed.
Seeds are in the range [0, 65535]. When set,
seed
will take only the lowest 16 bits of the given value.HOOMD-blue uses a deterministic counter based pseudorandom number generator. Any time a random value is needed, HOOMD-blue computes it as a function of the user provided seed
seed
(16 bits), the currenttimestep
(lower 40 bits), particle identifiers, MPI ranks, and other unique identifying values as needed to sample uncorrelated values:random_value = f(seed, timestep, ...)
(
Loggable
: category=”scalar”)- Type
- property state
The current simulation state.
- Type
- property timestep
The current simulation time step.
Note
Methods like
create_state_from_gsd
will set the initial timestep from the input. Settimestep
before creating the simulation state to override values fromcreate_
methods:sim.timestep = 5000 sim.create_state_from_gsd('gsd_at_step_10000000.gsd') assert sim.timestep == 5000
(
Loggable
: category=”scalar”)- Type
- property tps
The average number of time steps per second.
tps
is the number of steps executed divided by the elapsed walltime in seconds. It is updated during therun
loop and remains fixed afterrun
completes.Note
The start walltime and timestep are reset at the beginning of each call to
run
.(
Loggable
: category=”scalar”)- Type
- class hoomd.Snapshot(communicator=None)
Self-contained copy of the simulation
State
.- Parameters
communicator (Communicator) – MPI communicator to be used when accessing the snapshot.
See
State
andgsd.hoomd.Snapshot
for detailed documentation on the components ofSnapshot
.Note
Snapshot
is duck-type compatible withgsd.hoomd.Snapshot
except that arrays inSnapshot
are not assignable. You can edit their contents: e.g.snapshot.particles.typeid[:] == 0
.Warning
Data is only present on the root rank:
if snapshot.communicator.rank == 0: pos = snapshot.particles.position[0]
- communicator
MPI communicator.
- Type
- property angles
Angles.
- angles.typeid
Angle type id.
- Type
(N,)
numpy.ndarray
ofuint32
- angles.group
Tags of the particles in the angle.
- Type
(N, 3)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- property bonds
Bonds.
- bonds.typeid
Bond type id.
- Type
(N,)
numpy.ndarray
ofuint32
- bonds.group
Tags of the particles in the bond.
- Type
(N, 2)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- property configuration
Snapshot box configuration.
- box
Simulation box parameters
[Lx, Ly, Lz, xy, xz, yz]
.
Note
box
accepts any values thatBox.from_box
allows when setting.See also
- property constraints
Constraints.
- constraints.value
Constraint length.
- Type
(N, )
numpy.ndarray
offloat
- constraints.group
Tags of the particles in the constraint.
- Type
(N, 2)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- property dihedrals
Dihedrals.
- dihedrals.typeid
Dihedral type id.
- Type
(N,)
numpy.ndarray
ofuint32
- dihedrals.group
Tags of the particles in the dihedral.
- Type
(N, 4)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- classmethod from_gsd_snapshot(gsd_snap, communicator)
Constructs a
hoomd.Snapshot
from agsd.hoomd.Snapshot
object.- Parameters
gsd_snap (gsd.hoomd.Snapshot) – The gsd snapshot to convert to a
hoomd.Snapshot
.communicator (hoomd.communicator.Communicator) – The MPI communicator to use for the snapshot. This prevents the snapshot from being stored on every rank.
Tip
Use
Simulation.create_state_from_gsd
to efficiently initialize the system state from a GSD file.Note
from_gsd_snapshot
only accesses thegsd_snap
argument on rank 0. In MPI simulations, avoid duplicating memory and file reads by reading GSD files only on rank 0 and passinggsd_snap=None
on other ranks.
- property impropers
Impropers.
- impropers.typeid
Improper type id.
- Type
(N,)
numpy.ndarray
ofuint32
- impropers.group
Tags of the particles in the improper.
- Type
(N, 4)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- property pairs
Special pairs.
- pairs.typeid
Special pair type id.
- Type
(N,)
numpy.ndarray
ofuint32
- pairs.group
Tags of the particles in the special pair.
- Type
(N, 2)
numpy.ndarray
ofuint32
Note
Set
N
to change the size of the arrays.
- property particles
Particles.
- particles.position
Particle position \([\mathrm{length}]\).
- Type
(N, 3)
numpy.ndarray
offloat
- particles.orientation
Particle orientation.
- Type
(N, 4)
numpy.ndarray
offloat
- particles.typeid
Particle type id.
- Type
(N, )
numpy.ndarray
ofuint32
- particles.mass
Particle mass \([\mathrm{mass}]\).
- Type
(N, )
numpy.ndarray
offloat
- particles.charge
Particle charge \([\mathrm{charge}]\).
- Type
(N, )
numpy.ndarray
offloat
- particles.diameter
Particle diameter \([\mathrm{length}]\).
- Type
(N, )
numpy.ndarray
offloat
- particles.body
Particle body.
- Type
(N, )
numpy.ndarray
ofint32
- particles.moment_inertia
Particle moment of inertia \([\mathrm{mass} \cdot \mathrm{length}^2]\).
- Type
(N, 3)
numpy.ndarray
offloat
- particles.velocity
Particle velocity \([\mathrm{velocity}]\).
- Type
(N, 3)
numpy.ndarray
offloat
- particles.angmom
Particle angular momentum \([\mathrm{mass} \cdot \mathrm{velocity} \cdot \mathrm{length}]\).
- Type
(N, 4)
numpy.ndarray
offloat
- particles.image
Particle image.
- Type
(N, 3)
numpy.ndarray
ofint32
Note
Set
N
to change the size of the arrays.
- replicate(nx, ny, nz=1)
Replicate the snapshot along the periodic box directions.
- Parameters
Performs the same operation as
State.replicate
on aSnapshot
.- Returns
self
- wrap()
Wrap particles into the snapshot box.
- Returns
self
- class hoomd.State(simulation, snapshot, domain_decomposition)
The state of a
Simulation
object.Note
This object cannot be directly instantiated. Use
Simulation.create_state_from_gsd
andSimulation.create_state_from_snapshot
to instantiate aState
object as part of a simulation.Overview
State
stores the data that describes the thermodynamic microstate of aSimulation
object. This data consists of the box, particles, bonds, angles, dihedrals, impropers, special pairs, and constraints.Box
The simulation
box
describes the space that contains the particles as aBox
object.Particles
The state contains
N_particles
particles. Each particle has a position, orientation, type id, body, mass, moment of inertia, charge, diameter, velocity, angular momentum, image, and tag:\(\vec{r}\): position \([\mathrm{length}]\) - X,Y,Z cartesian coordinates defining the position of the particle in the box.
\(\mathbf{q}\): orientation \([\mathrm{dimensionless}]\) - Unit quaternion defining the rotation from the particle’s local reference frame to the box reference frame. The four components are in the order \(s\), \(a_x\), \(a_y\), \(a_z\) for the in complex notation \(s + a_x i + a_y j + a_z k\).
particle_typeid
: type id \([\mathrm{dimensionless}]\) - An integer in the interval[0,len(particle_types)
) that identifies the particle’s type.particle_types
maps type ids to names with:name = particle_types[particle_typeid]
.particle_body
: body id \([\mathrm{dimensionless}]\) - An integer that identifies the particle’s rigid body. A value of-1
indicates that this particle does not belong to a body. A positive value indicates that the particle belongs to the bodyparticle_body
. This particle is the central particle of a body when the body id is equal to the tag \(\mathrm{particle\_body} = \mathrm{particle\_tag}\). (used byhoomd.md.constrain.Rigid
)\(m\): mass \([\mathrm{mass}]\) - The particle’s mass.
\(I\): moment of inertia \([\mathrm{mass} \cdot \mathrm{length}^2]\) - \(I_{xx}\), \(I_{yy}\), \(I_{zz}\) elements of the diagonal moment of inertia tensor in the particle’s local reference frame. The off-diagonal elements are 0.
\(q\): charge \([\mathrm{charge}]\) - The particle’s charge.
\(d\): diameter \([\mathrm{length}]\) - Deprecated in v3.0.0. HOOMD-blue reads and writes particle diameters, but does not use them in any computations.
\(\vec{v}\): velocity \([\mathrm{velocity}]\) - X,Y,Z components of the particle’s velocity in the box’s reference frame.
\(\mathbf{P_S}\): angular momentum \([\mathrm{mass} \cdot \mathrm{velocity} \cdot \mathrm{length}]\) - Quaternion defining the particle’s angular momentum (see note).
\(\vec{n}\) : image \([\mathrm{dimensionless}]\) - Integers x,y,z that record how many times the particle has crossed each of the periodic box boundaries.
particle_tag
: tag \([\mathrm{dimensionless}]\) - An integer that uniquely identifies a given particle. The particles are stored in tag order when writing and initializing to/from a GSD file or snapshot: \(\mathrm{particle\_tag}_i = i\). When accessing data in local snapshots, particles may be in any order.
Note
HOOMD stores angular momentum as a quaternion because that is the form used when integrating the equations of motion (see Kamberaj 2005). The angular momentum quaternion \(\mathbf{P_S}\) is defined with respect to the orientation quaternion of the particle \(\mathbf{q}\) and the vector angular momentum of the particle, lifted into pure imaginary quaternion form \(\mathbf{S}^{(4)}\) as:
\[\mathbf{P_S} = 2 \mathbf{q} \times \mathbf{S}^{(4)}\]. Following this, the angular momentum vector \(\vec{S}\) in the particle’s local reference frame is:
\[\vec{S} = \frac{1}{2}im(\mathbf{q}^* \times \mathbf{P_S})\]Bonded groups
The state contains
N_bonds
bonds,N_angles
angles,N_dihedrals
dihedrals,N_impropers
impropers, andN_special_pairs
special pairs. Each of these data structures is similar, differing in the number of particles in the group and what operations use them. Bonds, angles, dihedrals, and impropers contain 2, 3, 4, and 4 particles per group respectively. Bonds specify the toplogy used when computing energies and forces inmd.bond
, angles define the same formd.angle
, dihedrals formd.dihedral
and impropers formd.improper
. These collectively implement bonding potentials used in molecular dynamics force fields. Like bonds, special pairs define connections between two particles, but special pairs are intended to adjust the 1-4 pairwise interactions in some molecular dynamics force fields: seemd.special_pair
. Each bonded group is defined by a type id, the group members, and a tag.bond_typeid
: type id \([\mathrm{dimensionless}]\) - An integer in the interval[0,len(bond_types))
that identifies the bond’s type.bond_types
maps type ids to names with:name = bond_types[bond_typeid]
. Similarly,angle_types
lists the angle types,dihedral_types
lists the dihedral types,improper_types
lists the improper types, andspecial_pair_types
lists the special pair types.bond_group
: A list of integers in the interval \([0, \max(\mathrm{particle\_tag})]\) that defines the tags of the particles in the bond (2), angle inangle_group
(3), dihedral indihedral_group
(4), improper inimproper_group
(4), or special pair inpair_group
(2).bond_tag
: tag \([\mathrm{dimensionless}]\) - An integer that uniquely identifies a given bond. The bonds are in tag order when writing and initializing to/from a GSD file or snapshot \(\mathrm{bond\_tag}_i = i\). When accessing data in local snapshots, bonds may be in any order. The same applies to angles withangle_tag
, dihedrals withdihedral_tag
, impropers withimproper_tag
, and special pairs withpair_tag
.
Constraints
The state contains
N_constraints
distance constraints between particles. These constraints are used byhoomd.md.constrain.Distance
. Each distance constraint consists of a distance value and the group members.constraint_group
: A list of 2 integers in the interval \([0, \max(\mathrm{particle\_tag})]\) that identifies the tags of the particles in the constraint.\(d\): constraint value \([\mathrm{length}]\) - The distance between particles in the constraint.
MPI domain decomposition
When running in serial or on 1 MPI rank, the entire simulation state is stored in that process. When using more than 1 MPI rank, HOOMD-blue employs a domain decomposition approach to split the simulation box an integer number of times in the x, y, and z directions (
domain_decomposition
). Each MPI rank stores and operates on the particles local to that rank. Local particles are those contained within the region defined by the split planes (domain_decomposition_split_fractions
). Each MPI rank communicates with its neighbors to obtain the properties of particles near the boundary between ranks (ghost particles) so that it can compute interactions across the boundary.Accessing Data
Two complementary APIs provide access to the state data: local snapshots that access data directly available on the local MPI rank (including the local and ghost particles) and global snapshots that collect the entire state on rank 0. See
State.cpu_local_snapshot
,State.gpu_local_snapshot
,get_snapshot
, andset_snapshot
for information about these data access patterns.See also
To write the simulation to disk, use
write.GSD
.- property cpu_local_snapshot
Expose simulation data on the CPU.
Provides access directly to the system state’s particle, bond, angle, dihedral, improper, constaint, and pair data through a context manager. Data in
State.cpu_local_snapshot
is MPI rank local, and thehoomd.data.LocalSnapshot
object is only usable within a context manager (i.e.with sim.state.cpu_local_snapshot as data:
). Attempts to assess data outside the context manager will result in errors. The local snapshot interface is similar to that ofSnapshot
.The
hoomd.data.LocalSnapshot
data access is mediated throughhoomd.data.array.HOOMDArray
objects. This lets us ensure memory safety when directly accessing HOOMD-blue’s data. The interface provides zero-copy access (zero-copy is guaranteed on CPU, access may be zero-copy if running on GPU).Changing the data in the buffers exposed by the local snapshot will change the data across the HOOMD-blue simulation. For a trivial example, this example would set all particle z-axis positions to 0.
with sim.state.cpu_local_snapshot as data: data.particles.position[:, 2] = 0
Note
The state’s box and the number of particles, bonds, angles, dihedrals, impropers, constaints, and pairs cannot change within the context manager.
Note
Getting a local snapshot object is order \(O(1)\) and setting a single value is of order \(O(1)\).
- property domain_decomposition
Number of domains in the x, y, and z directions.
- property domain_decomposition_split_fractions
Box fractions of the domain split planes in the x, y, and z directions.
- get_snapshot()
Make a copy of the simulation current state.
State.get_snapshot
makes a copy of the simulation state and makes it available in a single object.set_snapshot
resets the internal state to that in the given snapshot. Use these methods to implement techniques like hybrid MD/MC or umbrella sampling where entire system configurations need to be reset to a previous one after a rejected move.Note
Data across all MPI ranks and from GPUs is gathered on the root MPI rank’s memory. When accessing data in MPI simulations, use a
if snapshot.communicator.rank == 0:
conditional to access data arrays only on the root rank.Note
State.get_snapshot
is an order \(O(N_{particles} + N_{bonds} + \ldots)\) operation.See also
- Returns
The current simulation state
- Return type
- property gpu_local_snapshot
Expose simulation data on the GPU.
Provides access directly to the system state’s particle, bond, angle, dihedral, improper, constaint, and pair data through a context manager. Data in
State.gpu_local_snapshot
is GPU local, and thehoomd.data.LocalSnapshotGPU
object is only usable within a context manager (i.e.with sim.state.gpu_local_snapshot as data:
). Attempts to assess data outside the context manager will result in errors. The local snapshot interface is similar to that ofSnapshot
.The
hoomd.data.LocalSnapshotGPU
data access is mediated throughhoomd.data.array.HOOMDGPUArray
objects. This helps us maintain memory safety when directly accessing HOOMD-blue’s data. The interface provides zero-copy access on the GPU (assuming data was last accessed on the GPU).Changing the data in the buffers exposed by the local snapshot will change the data across the HOOMD-blue simulation. For a trivial example, this example would set all particle z-axis positions to 0.
with sim.state.gpu_local_snapshot as data: data.particles.position[:, 2] = 0
Warning
This property is only available when running on a GPU(s).
Note
The state’s box and the number of particles, bonds, angles, dihedrals, impropers, constaints, and pairs cannot change within the context manager.
Note
Getting a local snapshot object is order \(O(1)\) and setting a single value is of order \(O(1)\).
- replicate(nx, ny, nz=1)
Replicate the state of the system along the periodic box directions.
- Parameters
replicate
makes the system statenx * ny * nz
times larger. In each of the new periodic box images, it places a copy of the initial state with the particle positions offset to locate them in the image and the bond, angle, dihedral, improper, and pair group tags offset to apply to the copied particles. All other particle properties (mass, typeid, velocity, charge, …) are copied to the new particles without change.After placing the particles,
replicate
expands the simulation box by a factor ofnx
,ny
, andnz
in the direction of the first, second, and third box lattice vectors respectively and adjusts the particle positions to center them in the new box.
- set_box(box)
Set a new simulation box.
- Parameters
box (hoomd.box.box_like) – New simulation box.
Note
All particles must be inside the new box.
set_box
does not change any particle properties.See also
- set_snapshot(snapshot)
Restore the state of the simulation from a snapshot.
Also calls
update_group_dof
to count the number of degrees in the system with the new state.- Parameters
snapshot (Snapshot) – Snapshot of the system from
get_snapshot
Warning
set_snapshot
can only make limited changes to the simulation state. While it can change the number of particles/bonds/etc… or their properties, it cannot change the number or names of the particle/bond/etc.. types.Note
set_snapshot
is an order \(O(N_{particles} + N_{bonds} + \ldots)\) operation and is very expensive when the simulation device is a GPU.
- thermalize_particle_momenta(filter, kT)
Assign random values to particle momenta.
- Parameters
filter (hoomd.filter.filter_like) – Particles to modify
kT (float) – Thermal energy to set \([\mathrm{energy}]\)
thermalize_particle_momenta
assigns the selected particle’s velocities and angular momentum to random values drawn from a Gaussian distribution consistent with the given thermal energy kT.Velocity
thermalize_particle_momenta
assigns random velocities to the x and y components of each particle’s velocity. When the simulation box is 3D, it also assigns a random velocity to the z component. When the simulation box is 2D, it sets the z component to 0. Finally, sets the center of mass velocity of the selected particles to 0.Angular momentum
thermalize_particle_momenta
assigns random angular momenta to each rotational degree of freedom that has a non-zero moment of intertia. Each particle can have 0, 1, 2, or 3 rotational degrees of freedom as determine by its moment of inertia.
- property types
dictionary of all types in the state.
Combines the data from
particle_types
,bond_types
,angle_types
,dihedral_types
,improper_types
, andspecial_pair_types
into a dictionary with keys matching the property names.
- update_group_dof()
Schedule an update to the number of degrees of freedom in each group.
update_group_dof
requests thatSimulation
update the degrees of freedom provided to each group by the Integrator.Simulation
will perform this update at the start ofSimulation.run
or at the start of the next timestep during an ongoing call toSimulation.run
.This method is called automatically when:
An Integrator is assigned to the
Simulation
’s operations.The
hoomd.md.Integrator.integrate_rotational_dof
parameter is set.set_snapshot
is called.On timesteps where a
hoomd.update.FilterUpdater
triggers.
Call
update_group_dof
manually to force an update, such as when you modify particle moments of inertia withcpu_local_snapshot
.
Modules
hoomd.box
Overview
The class interface which HOOMD considers to be a box-like object. |
|
Objects that are or can be converted to |
Details
Implement Box.
- class hoomd.box.BoxInterface
The class interface which HOOMD considers to be a box-like object.
Note
This class is exclusively used for help with typing and documentation in HOOMD, and is not meant to be used.
- hoomd.box.box_like
Objects that are or can be converted to
Box
.This includes
hoomd.Box
objects.Objects with attributes
Lx, Ly, Lz, xy, xz, yz
.Lists like
[Lx, Ly, Lz, xy, xz, yz]
.Dictionaries with keys
'Lx', 'Ly', 'Lz', 'xy', 'xz', 'yz'
.3x3 NumPy arrays or objects convertible to a 3x3 array (see
hoomd.Box.from_matrix
).
Note
If any of
Lz, xy, xz, yz
for these different types are not provided, they are considered 0.alias of
Union
[Box
,BoxInterface
,Sequence
[float
],Mapping
[str
,float
],ndarray
]
hoomd.communicator
Overview
MPI communicator. |
Details
MPI communicator.
When compiled without MPI support, Communicator
acts as if there is one MPI
rank and 1 partition. To use MPI, compile HOOMD-blue with the
option ENABLE_MPI=on
and use the appropriate MPI launcher to launch Python.
Then the Communicator
class will configure and query MPI ranks and partitions.
By default, Communicator
starts with the MPI_COMM_WOLRD
MPI communicator,
and the communicator is not available for user scripts.
Communicator
also accepts MPI communicators from mpi4py
. Use this to
implement workflows with multiple simulations that communicate using mpi4py
calls in user code (e.g. genetic algorithms, umbrella sampling).
- class hoomd.communicator.Communicator(mpi_comm=None, ranks_per_partition=None)
MPI communicator.
- Parameters
mpi_comm – Accepts an mpi4py communicator. Use this argument to perform many independent hoomd simulations where you communicate between those simulations using mpi4py.
ranks_per_partition (int) – (MPI) Number of ranks to include in a partition.
The
Communicator
class initializes MPI communications for ahoomd.Simulation
and exposes rank and partition information to the user as properties. To use MPI, launch your Python script with an MPI launcher (e.g.mpirun
ormpiexec
). By default,Communicator
uses all ranks provided by the launchernum_launch_ranks
for a singlehoomd.Simulation
object which decomposes the state onto that many domains.Set
ranks_per_partition
to an integer to partition launched ranks intonum_launch_ranks / ranks_per_partition
communicators, each with their ownpartition
index. Use this to perform many simulations in parallel, for example by usingpartition
as an index into an array of state points to execute.- barrier()
Perform a barrier synchronization across all ranks in the partition.
Note
Does nothing in builds with ENABLE_MPI=off.
- barrier_all()
Perform a MPI barrier synchronization across all ranks.
Note
Does nothing in builds with ENABLE_MPI=off.
- localize_abort()
Localize MPI_Abort to this partition.
HOOMD calls
MPI_Abort
to tear down all running MPI processes whenever there is an uncaught exception. By default, this will abort the entire MPI execution. When using partitions, an uncaught exception on one partition will therefore abort all of them.Use the return value of
localize_abort()
as a context manager to tell HOOMD that all operations within the context will use only that MPI communicator so that an uncaught exception in one partition will only abort that partition and leave the others running.
- property num_partitions
The number of partitions in this execution.
Create partitions with the
ranks_per_partition
argument on initialization. Then, the number of partitions isnum_launch_ranks / ranks_per_partition
.Note
Returns 1 in builds with ENABLE_MPI=off.
- Type
- property num_ranks
The number of ranks in this partition.
When initialized with
ranks_per_partition=None
,num_ranks
is equal to thenum_launch_ranks
set by the MPI launcher. When using partitions,num_ranks
is equal toranks_per_partition
.Note
Returns 1 in builds with ENABLE_MPI=off.
- Type
- property rank
The current rank within the partition.
Note
Returns 0 in builds with ENABLE_MPI=off.
- Type
- property walltime
Wall clock time since creating the
Communicator
[seconds].walltime
returns the same value on each rank in the current partition.
hoomd.custom
Overview
Base class for user-defined actions. |
|
User defined operation. |
Details
Custom operations.
CustomOperation
provides a mechanism for users to insert Python code
via an Action
subclass that executes during the simulation’s run loop.
Use this to prototype new simulation methods in Python, analyze the system state
while the simulation progresses, or write output to custom file formats.
See also
- class hoomd.custom.Action
Bases:
object
Base class for user-defined actions.
To implement a custom operation in Python, subclass
Action
and implement theact()
method to perform the desired action. To include the action in the simulation run loop, pass an instance of the action tohoomd.update.CustomUpdater
,hoomd.write.CustomWriter
, orhoomd.tune.CustomTuner
.from hoomd.custom import Action class ExampleAction(Action): def act(self, timestep): self.com = self._state.snapshot.particles.position.mean(axis=0)
To request that HOOMD-blue compute virials, pressure, the rotational kinetic energy, or the external field virial, set the flags attribute with the appropriate flags from the internal
Action.Flags
enumeration.from hoomd.custom import Action class ExampleActionWithFlag(Action): flags = [Action.Flags.ROTATIONAL_KINETIC_ENERGY, Action.Flags.PRESSURE_TENSOR, Action.Flags.EXTERNAL_FIELD_VIRIAL] def act(self, timestep): pass
Use the
hoomd.logging.log
decorator to define loggable properties.from hoomd.python_action import Action from hoomd.logging import log class ExampleActionWithFlag(Action): @log def answer(self): return 42 def act(self, timestep): pass
- flags
List of flags from the
Action.Flags
. Used to tell the integrator if specific quantities are needed for the action.- Type
- class Flags(value)
Bases:
IntEnum
Flags to indictate the integrator should calculate quantities.
PRESSURE_TENSOR = 0
ROTATIONAL_KINETIC_ENERGY = 1
EXTERNAL_FIELD_VIRIAL = 2
- abstract act(timestep)
Performs whatever action a subclass implements.
- Parameters
timestep (int) – The current timestep in a simulation.
Note
Use
self._state
to access the simulation state viahoomd.State
when using the base classattach
.
- attach(simulation)
Attaches the Action to the
hoomd.Simulation
.- Parameters
simulation (hoomd.Simulation) – The simulation to attach the action to.
Stores the simulation state in
self._state
. Override this in derived classes to implement other behaviors.
- detach()
Detaches the Action from the
hoomd.Simulation
.
- class hoomd.custom.CustomOperation(trigger, action)
Bases:
TriggeredOperation
User defined operation.
This is the parent class for
hoomd.tune.CustomTuner
,hoomd.update.CustomUpdater
. andhoomd.write.CustomWriter
. These classes wrap Python objects that inherit fromhoomd.custom.Action
so they can be added to the simulation operations.This class also implements a “pass-through” system for attributes. Attributes and methods from the passed in
action
will be available directly in this class. This does not apply to attributes with these names:trigger
,_action
, andaction
.Note
Due to the pass through no attribute should exist both in
hoomd.custom.CustomOperation
and thehoomd.custom.Action
.Note
This object should not be instantiated or subclassed by an user.
- trigger
A trigger to determine when the wrapped
hoomd.custom.Action
is run.
- __getattr__(attr)
Pass through attributes/methods of the wrapped object.
- __setstate__(state)
Set object state from pickling or deepcopying.
- act(timestep)
Perform the action of the custom action if attached.
Calls through to the action property of the instance.
- Parameters
timestep (int) – The current timestep of the state.
- property action
hoomd.custom.Action
The action the operation wraps.
hoomd.data
Overview
Provides context manager access to HOOMD-blue CPU data buffers. |
|
Provides context manager access to HOOMD-blue GPU data buffers. |
|
Class for directly accessing HOOMD-blue angle data. |
|
Class for directly accessing HOOMD-blue bond data. |
|
Class for directly accessing HOOMD-blue constraint data. |
|
Class for directly accessing HOOMD-blue dihedral data. |
|
Class for directly accessing HOOMD-blue improper data. |
|
Class for directly accessing HOOMD-blue special pair data. |
|
Class for directly accessing HOOMD-blue particle data. |
|
Implement a type based mutable mapping. |
Details
Access State data on the local rank.
LocalSnapshot
, LocalSnapshotGPU
, and related classes provide direct access
to the data buffers managed by hoomd.State
.
See also
- class hoomd.data.LocalSnapshot(state)
Provides context manager access to HOOMD-blue CPU data buffers.
The interface of a
LocalSnapshot
is similar to that of thehoomd.Snapshot
. Data is MPI rank local so for MPI parallel simulations only the data possessed by a rank is exposed. This means that users must handle the domain decomposition directly. One consequence of this is that access to ghost particle data is provided. A ghost particle is a particle that is not owned by a rank, but nevertheless is required for operations that use particle neighbors. Also, changing the global or local box within aLocalSnapshot
context manager is not allowed.For every property (e.g.
data.particles.position
), only grabs the data for the regular (non-ghost) particles. The property can be prefixed withghost_
to grab the ghost particles in a read only manner. Likewise, suffixing with_with_ghost
will grab all data on the rank (regular and ghost particles) in a read only array.All array-like properties return a
hoomd.data.array.HOOMDArray
object which prevents invalid memory accesses.Note
For the
LocalAccess
classes the affixed attributes mentioned above are not shown. Also of interest, ghost data always come immediately after the regular data.- property angles
Local angle data.
- property bonds
Local bond data.
- property constraints
Local constraint data.
- property dihedrals
Local dihedral data.
- property impropers
Local improper data.
- property pairs
Local special pair data.
- property particles
Local particle data.
- class hoomd.data.LocalSnapshotGPU(*args, **kwargs)
Provides context manager access to HOOMD-blue GPU data buffers.
The interface of a
LocalSnapshot
is similar to that of thehoomd.Snapshot
. Data is MPI rank local so for MPI parallel simulations only the data possessed by a rank is exposed. This means that users must handle the domain decomposition directly. One consequence of this is that access to ghost particle data is provided. A ghost particle is a particle that is not owned by a rank, but nevertheless is required for operations that use particle neighbors. Also, changing the global or local box within aLocalSnapshot
context manager is not allowed.For every property (e.g.
data.particles.position
), only grabs the data for the regular (non-ghost) particles. The property can be prefixed withghost_
to grab the ghost particles in a read only manner. Likewise, suffixing with_with_ghost
will grab all data on the rank (regular and ghost particles) in a read only array.All array-like properties return a
hoomd.data.array.HOOMDGPUArray
object which prevents invalid memory accesses.- property angles
Local angle data.
- property bonds
Local bond data.
- property constraints
Local constraint data.
- property dihedrals
Local dihedral data.
- property impropers
Local improper data.
- property pairs
Local special pair data.
- property particles
Local particle data.
- class hoomd.data.typeparam.TypeParameter(name, type_kind, param_dict)
Implement a type based mutable mapping.
Implements the
collections.abc.MutableMapping
interface (__delitem__
is disallowed).TypeParameter
instances extend the base Python mapping interface with smart defaults, value/key validation/processing, and advanced indexing. The class’s intended purpose is to store data per type or per unique combinations of type (such as type pairs forhoomd.md.pair
potentials) of a prescribed length.Indexing
For getting and setting values, multiple index formats are supported. The base case is either a string representing the appropriate type or a tuple of such strings if multiple types are required per key. This is the exact same indexing behavior expect from a Python
dict
, and all functions (barring those that delete keys) should function as expected for a Pythoncollections.defaultdict
.Two ways to extend this base indexing are supported. First is using an iterator of the final key types. This will perform the method for all specified types in the iterator. Likewise, for each item in the final tuple (if the expected key type is a tuple of multiple string types), an iterator can be used instead of a string which will result in all permutations of such iterators in the tuple. Both advanced indexing methods can be combined.
Note
All methods support advanced indexing as well, and behave as one might expect. Methods that set values will do so for all keys specified, and methods that return values will return values for all keys (within a
dict
instance).Note
Ordering in tuples does not matter. Values in tuples are sorted before being stored or queried.
Below are some example indexing values for single and multiple key indexing.
# "A", "B", "C" ["A", "B", "C"] # ("A", "B") ("A", "B") # ("A", "B") and ("B", "C") [("A", "B"), ("B", "C")] # ("A", "B"), ("A", "C"), and ("A", "D") ("A", ["B", "C", "D"])
Defaults and setting values
TypeParameter
instances have default values that can be accessed viadefault
which will be used for all types not defined. In addition, when the type parameter expects adict
-like object, the default will be updated with the set value. This means that values that have defaults do not need to be explicitly specified.An example of “smart”-setting using the MD LJ potential,
lj = hoomd.md.pair.LJ(nlist=hoomd.md.nlist.Cell()) # params is a TypeParameter object. # We set epsilon to have a default but sigma is still required lj.params.default = {"epsilon": 4} print(lj.params.default) # {"epsilon": 4.0, "sigma": hoomd.data.typeconverter.RequiredArg} # We do not need to specify epsilon to use new default value when # setting lj.params[("A", "B")] = {"sigma": 1.0} print(lj.params[("A", "B")]) # {"epsilon": 4.0, "sigma": 1.0}
Note
Before calling
hoomd.Simulation.run
for theTypeParameter
instance’s associated simulation, keys are not checked that their types exist in thehoomd.State
object. After callingrun
, however, all such data for non-existent types is removed, and querying or attempting to set those keys will result in aKeyError
.- property default
The default value of the parameter.
- class hoomd.data.AngleLocalAccessBase(state)
Class for directly accessing HOOMD-blue angle data.
- typeid
The integer type of a angle.
- Type
(N_angles)
hoomd.data.array
object ofint
- members
The tags of particles in a angle.
- Type
(N_angles, 3)
hoomd.data.array
object ofint
- tag
The angle tags. MPI domain migration reorder angles in memory. The angle tag identifies each angle in the order it existed in the initial configuration.
- Type
(N_angles)
hoomd.data.array
object ofint
- rtag
The angle reverse tags. For a given angle tag
tag
,i = angles.rtag[tag]
is the array index holding that angle.- Type
(N_angles_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.BondLocalAccessBase(state)
Class for directly accessing HOOMD-blue bond data.
- typeid
The integer type of a bond.
- Type
(N_bonds)
hoomd.data.array
object ofint
- members
The tags of particles in a bond.
- Type
(N_bonds, 2)
hoomd.data.array
object ofint
- tag
The bond tags. MPI domain migration reorder bonds in memory. The bond tag identifies each bond in the order it existed in the initial configuration.
- Type
(N_bonds)
hoomd.data.array
object ofint
- rtag
the The bond reverse tags. For a given bond tag
tag
,i = bonds.rtag[tag]
is the array index holding that bond.- Type
(N_bonds_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.ConstraintLocalAccessBase(state)
Class for directly accessing HOOMD-blue constraint data.
- value
The constaint value.
- Type
(N_constraints)
hoomd.data.array
object offloat
- members
the tags of particles in a constraint.
- Type
(N_constraints, 3)
hoomd.data.array
object ofint
- tag
The constraint tags. MPI domain migration reorder constraints in memory. The constraint tag identifies each constraint in the order it existed in the initial configuration.
- Type
(N_constraints)
hoomd.data.array
object ofint
- rtag
The constraint reverse tags. For a given constraint tag
tag
,i = constraints.rtag[tag]
is the array index holding that constraint.- Type
(N_constraints_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.DihedralLocalAccessBase(state)
Class for directly accessing HOOMD-blue dihedral data.
- typeid
The integer type of a dihedral.
- Type
(N_dihedrals)
hoomd.data.array
object ofint
- members
the tags of particles in a dihedral.
- Type
(N_dihedrals, 4)
hoomd.data.array
object ofint
- tag
The dihedral tags. MPI domain migration reorder dihedrals in memory. The dihedral tag identifies each dihedral in the order it existed in the initial configuration.
- Type
(N_dihedrals)
hoomd.data.array
object ofint
- rtag
The dihedral reverse tags. For a given dihedral tag
tag
,i = dihedrals.rtag[tag]
is the array index holding that dihedral.- Type
(N_dihedrals_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.ImproperLocalAccessBase(state)
Class for directly accessing HOOMD-blue improper data.
- typeid
The integer type of a improper.
- Type
(N_impropers)
hoomd.data.array
object ofint
- members
The tags of particles in a improper.
- Type
(N_impropers, 3)
hoomd.data.array
object ofint
- tag
The improper tags. MPI domain migration reorder impropers in memory. The improper tag identifies each improper in the order it existed in the initial configuration.
- Type
(N_impropers)
hoomd.data.array
object ofint
- rtag
The improper reverse tags. For a given improper tag
tag
,i = impropers.rtag[tag]
is the array index holding that improper.- Type
(N_impropers_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.PairLocalAccessBase(state)
Class for directly accessing HOOMD-blue special pair data.
- typeid
The type of special pair.
- Type
(N_pairs)
hoomd.data.array
object offloat
- members
the tags of particles in a special pair.
- Type
(N_pairs, 3)
hoomd.data.array
object ofint
- tag
The special pair tags. MPI domain migration reorder special pairs in memory. The special pair tag identifies each special pair in the order it existed in the initial configuration.
- Type
(N_special_pairs)
hoomd.data.array
object ofint
- rtag
The special pair reverse tags. For a given special pair tag
tag
,i = pairs.rtag[tag]
is the array index holding that special pair.- Type
(N_special_pairs_global)
hoomd.data.array
object ofint
See also
- class hoomd.data.ParticleLocalAccessBase(state)
Class for directly accessing HOOMD-blue particle data.
- typeid
The integer type of a particle.
- Type
(N_particles)
hoomd.data.array
object offloat
- tag
The particle tags. Spatial sorting and MPI domain migration reorder particles in memory. The particle tag identifies each particle in the order it existed in the initial configuration.
- Type
(N_particles)
hoomd.data.array
object ofint
- rtag
The particle reverse tags. For a given particle tag
tag
,i = particles.rtag[tag]
is the array index holding that particle.- Type
(N_particles_global)
hoomd.data.array
object ofint
- position
Particle positions \([\mathrm{length}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- image
A count of how many times each particle crosses the periodic box boundaries.
- Type
(N_particles, 3)
hoomd.data.array
object ofint
- velocity
Particle velocities \([\mathrm{velocity}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- acceleration
Particle accelerations \([\mathrm{velocity} \cdot \mathrm{time}^{-1}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- mass
Particle masses \([\mathrm{mass}]\).
- Type
(N_particles)
hoomd.data.array
object offloat
- orientation
Particle orientations expressed as quaternions.
- Type
(N_particles, 4)
hoomd.data.array
object offloat
- angmom
Particle angular momenta expressed as quaternions \([\mathrm{mass} \cdot \mathrm{velocity} \cdot \mathrm{length}]\).
- Type
(N_particles, 4)
hoomd.data.array
object offloat
- moment_inertia
Particle principal moments of inertia \([\mathrm{mass} \cdot \mathrm{length}^2]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- charge
Particle electrical charges \([\mathrm{charge}]\).
- Type
(N_particles)
hoomd.data.array
object offloat
- diameter
Particle diameters \([\mathrm{length}]\).
- Type
(N_particles)
hoomd.data.array
object offloat
- body
The id of the rigid body the particle is in.
- Type
(N_particles)
hoomd.data.array
object ofint
- net_force
Net force on particle \([\mathrm{force}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- net_torque
Net torque on particle \([\mathrm{force} \cdot \mathrm{length}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- net_virial
Net virial on particle \([\mathrm{energy}]\).
- Type
(N_particles, 3)
hoomd.data.array
object offloat
- net_energy
Net energy of a particle \([\mathrm{energy}]\).
- Type
(N_particles,)
hoomd.data.array
object offloat
Note
Changing some attributes (such as
velocity
andacceleration
) may not alter the trajectory of the system as you would expect. Themd.Integrator
is responsible for integrating the equations of motion and manages the values in these arrays.See also
Modules
hoomd.data.array
Overview
A NumPy like interface to internal HOOMD-blue data. |
|
Exposes an internal HOOMD-blue GPU buffer. |
Details
Implement zero-copy array.
- class hoomd.data.array.HOOMDArray(buffer, callback, read_only=None)
A NumPy like interface to internal HOOMD-blue data.
These objects are returned by HOOMD-blue’s zero copy local snapshot API (
hoomd.State.cpu_local_snapshot
). This class acts like anumpy.ndarray
object through NumPy’s provided interface. Some exceptions are theview
,resize
,flat
andflatiter
methods and thedata
andbase
properties. For typical use cases, understanding this class is not necessary. Treat it as anumpy.ndarray
.In general, whenever possible (when an array pointing to a new buffer is returned) we return a
numpy.ndarray
. However, any array pointing to the same data will be returned as aHOOMDArray
. To ensure memory safety, aHOOMDArray
object cannot be accessed outside of the context manager in which it was created. To have access outside the manager an explicit copy must be made (e.g.numpy.array(obj, copy=True)
).In general this class should be nearly as fast as a standard NumPy array, but there is some overhead. This is mitigated by returning a
numpy.ndarray
whenever possible. If every ounce of performance is necessary,HOOMDArray._coerce_to_ndarray
can provide anumpy.ndarray
object inside the context manager. References to a HOOMDArray object’s buffer after leaving the context manager is UNSAFE. It can cause SEGFAULTs and cause your program to crash. Use this function only if absolutely necessary.Performance Tips
Assume
a
represents aHOOMDArray
for examples given.Place the
HOOMDArray
to the left of the expression (e.g.a + b + c
is faster thanb + a + c
). This has to do with the mechanismsHOOMDArray
has to do to hook into NumPy’s functionality.If a copy will need to be made, do it as early as possible. In other words, if you will need access outside the context manager, use
numpy.array(a, copy=True)
before doing any calculations.If you know that your access of the internal buffer is safe and we cannot detect this (i.e. we return a
HOOMDArray
), usingHOOMDArray._coerce_to_ndarray
should help. Note that for large arrays this only gives minimal performance improvements at greater risk of breaking your program.
- class hoomd.data.array.HOOMDGPUArray(*args, **kwargs)
Exposes an internal HOOMD-blue GPU buffer.
The HOOMDGPUArray object exposes a GPU data buffer using the __cuda_array_interface__. This class provides buffer access through a context manager to prevent invalid memory accesses (
hoomd.State.gpu_local_snapshot
). To avoid errors, do not use references to the data outside the context manager. For example:with sim.state.gpu_local_snapshot as data: # valid within context manager pos = cupy.array(data.particles.position, copy=False) # can use pos within manager pos[:, 2] += 1 # invalid data access can cause SEGFAULTs and other issues pos[:, 2] -= 1
In general, it is safer to not store any
HOOMDGPUArray
references to a data buffer. This can be done when necessary, but care must be taken not to use references to the data outside the context manager.Note
The full functionality of this class depends on whether, HOOMD-blue can import CuPy. If CuPy can be imported then, we wrap much of the
cupy.ndarray
class’s functionality. Otherwise, we just expose the buffer and provide a few basic properties.HOOMDGPUArray
always supports getting (but not setting) theshape
,strides
, andndim
properties.HOOMDGPUArray
never supports standard binary operators like (+
,-
,*
). This is a current limitation on external classes hooking into CuPy.When CuPy is imported, slice/element assignment (e.g.
array[0] = 1; array[:2] = 4
) and compound assignment operators (e.g.+=
,-=
,*=
) are available. In addition, most methods besidesview
,resize
,flat
,flatiter
are available. The same is true for properties except thedata
andbase
properties. See CuPy’s documentation for a list of methods.Tip
Use,
cupy.add
,cupy.multiply
, etc. for binary operations on the GPU.Note
Packages like Numba and PyTorch can use
HOOMDGPUArray
without CuPy installed. Any package that supports version 2 of the __cuda_array_interface__ should support the direct use ofHOOMDGPUArray
objects.
hoomd.device
Overview
Select the CPU to execute simulations. |
|
Base class device object. |
|
Select a GPU or GPU(s) to execute simulations. |
|
Automatically select the hardware device. |
Details
Devices.
Use a Device
class to choose which hardware device(s) should execute the
simulation. Device
also sets where to write log messages and how verbose
the message output should be. Pass a Device
object to hoomd.Simulation
on instantiation to set the options for that simulation.
User scripts may instantiate multiple Device
objects and use each with a
different hoomd.Simulation
object. One Device
object may also be shared
with many hoomd.Simulation
objects.
Tip
Reuse Device
objects when possible. There is a non-negligible overhead
to creating each Device
, especially on the GPU.
See also
- class hoomd.device.CPU(num_cpu_threads=None, communicator=None, msg_file=None, notice_level=2)
Bases:
Device
Select the CPU to execute simulations.
- Parameters
num_cpu_threads (int) – Number of TBB threads. Set to
None
to auto-select.communicator (hoomd.communicator.Communicator) – MPI communicator object. When
None
, create a default communicator that uses all MPI ranks.msg_file (str) – Filename to write messages to. When
None
usesys.stdout
andsys.stderr
. Messages from multiple MPI ranks are collected into this file.notice_level (int) – Minimum level of messages to print.
MPI
In MPI execution environments, create a
CPU
device on every rank.
- class hoomd.device.Device(communicator, notice_level, msg_file)
Bases:
object
Base class device object.
Provides methods and properties common to
CPU
andGPU
, including those that control where status messages are stored (msg_file
) how many status messages HOOMD-blue prints (notice_level
) and a method for user provided status messages (notice
).TBB threads
Set
num_cpu_threads
toNone
and TBB will auto-select the number of CPU threads to execute. If the environment variableOMP_NUM_THREADS
is set, HOOMD will use this value. You can also setnum_cpu_threads
explicitly.Note
At this time very few features use TBB for threading. Most users should employ MPI for parallel simulations. See Features for more information.
- property communicator
The MPI Communicator [read only].
- property msg_file
Filename to write messages to.
By default, HOOMD prints all messages and errors to Python’s
sys.stdout
andsys.stderr
(or the system’sstdout
andstderr
when running in an MPI environment).Set
msg_file
to a filename to redirect these messages to that file.Set
msg_file
toNone
to use the system’sstdout
andstderr
.Note
All MPI ranks within a given partition must open the same file. To ensure this, the given file name on rank 0 is broadcast to the other ranks. Different partitions may open separate files. For example:
communicator = hoomd.communicator.Communicator( ranks_per_partition=2) filename = f'messages.{communicator.partition}' device = hoomd.device.GPU(communicator=communicator, msg_file=filename)
- Type
- notice(message, level=1)
Write a notice message.
Write the given message string to the output defined by
msg_file
on MPI rank 0 whennotice_level
>=level
.
- property notice_level
Minimum level of messages to print.
notice_level
controls the verbosity of messages printed by HOOMD. The default level of 2 shows messages that the developers expect most users will want to see. Set the level lower to reduce verbosity or as high as 10 to get extremely verbose debugging messages.- Type
- class hoomd.device.GPU(gpu_ids=None, num_cpu_threads=None, communicator=None, msg_file=None, notice_level=2)
Bases:
Device
Select a GPU or GPU(s) to execute simulations.
- Parameters
gpu_ids (list[int]) – List of GPU ids to use. Set to
None
to let the driver auto-select a GPU.num_cpu_threads (int) – Number of TBB threads. Set to
None
to auto-select.communicator (hoomd.communicator.Communicator) – MPI communicator object. When
None
, create a default communicator that uses all MPI ranks.msg_file (str) – Filename to write messages to. When
None
, usesys.stdout
andsys.stderr
. Messages from multiple MPI ranks are collected into this file.notice_level (int) – Minimum level of messages to print.
Tip
Call
GPU.get_available_devices
to get a human readable list of devices.gpu_ids = [0]
will select the first device in this list,[1]
will select the second, and so on.The ordering of the devices is determined by the GPU driver and runtime.
Device auto-selection
When
gpu_ids
isNone
, HOOMD will ask the GPU driver to auto-select a GPU. In most cases, this will select device 0. When all devices are set to a compute exclusive mode, the driver will choose a free GPU.MPI
In MPI execution environments, create a
GPU
device on every rank. Whengpu_ids
is leftNone
, HOOMD will attempt to detect the MPI local rank environment and choose an appropriate GPU withid = local_rank % num_capable_gpus
. Setnotice_level
to 3 to see status messages from this process. Override this auto-selection by providing appropriate device ids on each rank.Multiple GPUs
Specify a list of GPUs to
gpu_ids
to activate a single-process multi-GPU code path.Note
Not all features are optimized to use this code path, and it requires that all GPUs support concurrent managed memory access and have high bandwidth interconnects.
- property compute_capability
Compute capability of the device.
The tuple includes the major and minor versions of the CUDA compute capability:
(major, minor)
.
- enable_profiling()
Enable GPU profiling.
When using GPU profiling tools on HOOMD, select the option to disable profiling on start. Initialize and run a simulation long enough that all autotuners have completed, then open
enable_profiling()
as a context manager and continue the simulation for a time. Profiling stops when the context manager closes.Example:
with device.enable_profiling(): sim.run(1000)
- static get_available_devices()
Get the available GPU devices.
Get messages describing the reasons why devices are unavailable.
- property gpu_error_checking
Whether to check for GPU error conditions after every call.
When
False
(the default), error messages from the GPU may not be noticed immediately. Set toTrue
to increase the accuracy of the GPU error messages at the cost of significantly reduced performance.- Type
- static is_available()
Test if the GPU device is available.
- property memory_traceback
Whether GPU memory tracebacks should be enabled.
Memory tracebacks are useful for developers when debugging GPU code.
Deprecated since version v3.4.0:
memory_traceback
has no effect.- Type
- hoomd.device.auto_select(communicator=None, msg_file=None, notice_level=2)
Automatically select the hardware device.
- Parameters
communicator (hoomd.communicator.Communicator) – MPI communicator object. When
None
, create a default communicator that uses all MPI ranks.msg_file (str) – Filename to write messages to. When
None
usesys.stdout
andsys.stderr
. Messages from multiple MPI ranks are collected into this file.notice_level (int) – Minimum level of messages to print.
- Returns
hoomd.error
Overview
Raised when data is inaccessible until the simulation is run. |
|
Error when converting a parameter. |
|
Raised when setting an attribute after a simulation has been run. |
Details
HOOMD-blue specific error classes.
These classes are subclasses of Python exception types. HOOMD-blue raises these exceptions when documented.
- exception hoomd.error.DataAccessError(data_name)
Bases:
RuntimeError
Raised when data is inaccessible until the simulation is run.
- __str__()
Returns the error message.
- exception hoomd.error.MutabilityError(attribute_name)
Bases:
AttributeError
Raised when setting an attribute after a simulation has been run.
- __str__()
Returns the error message.
- exception hoomd.error.TypeConversionError
Bases:
ValueError
Error when converting a parameter.
hoomd.filter
Overview
Base class for all particle filters. |
|
Select all particles in the system. |
|
Abstract base class for custom particle filters. |
|
Set intersection operation. |
|
Select no particles. |
|
Select particles based on inclusion in rigid bodies. |
|
Set difference operation. |
|
Select particles by tag. |
|
Select particles by type. |
|
Set union operation. |
|
An object that acts like a particle filter. |
Details
Particle filters.
Particle filters describe criteria to select subsets of particles in the
system for use by various operations throughout HOOMD. To maintain high
performance, filters are not re-evaluated on every use. Instead, each unique
particular filter (defined by the class name and hash) is mapped to a group,
an internally maintained list of the selected particles. Subsequent uses of the
same particle filter specification (in the same hoomd.Simulation
) will resolve
to the same group and the originally selected particles, even if the state
of the system has changed.
Groups are not completely static. HOOMD-blue automatically re-evaluates the
filter specifications and updates the group membership whenever the number of
particles in the simulation changes. Use hoomd.update.FilterUpdater
to
manually trigger updates to group membership.
For molecular dynamics simulations, each group maintains a count of the number
of degrees of freedom given to the group by integration methods. This count is
used by hoomd.md.compute.ThermodynamicQuantities
and the integration methods
themselves to compute the kinetic temperature. See
hoomd.State.update_group_dof
for details on when HOOMD-blue updates this
count.
- class hoomd.filter.ParticleFilter
Base class for all particle filters.
This class provides methods common to all particle filters.
Attention
Users should instantiate one of the subclasses. Calling
ParticleFilter
directly may result in an error.- __call__(state)
Evaluate the filter.
Note
This method may return tags that are only present on the local MPI rank. The full set of particles selected is the combination of these the lists across ranks with a set union operation.
- __eq__(other)
Test for equality between two particle filters.
- __hash__()
Return a hash of the filter parameters.
- __str__()
Format a human readable string describing the filter.
- class hoomd.filter.All
Select all particles in the system.
Base:
ParticleFilter
- class hoomd.filter.CustomFilter
Abstract base class for custom particle filters.
The class allows the definition of particle filters in Python (see
ParticleFilter
).Subclasses of this class must have
__hash__
,__eq__
, and__call__
methods. The__hash__
and__eq__
methods will be used to cache the particle tags associated with a filter, thus__eq__
must correctly disambiguate any filters that would choose different particles. For more information on the Python data model see https://docs.python.org/3/reference/datamodel.html#object.__hash__ and https://docs.python.org/3/reference/datamodel.html#object.__eq__.The example below creates a custom filter that filters out particles above and below a certain mass, and uses that filter in a
hoomd.write.GSD
object.Example:
class MassFilter(hoomd.filter.CustomFilter): def __init__(self, min_mass, max_mass): self.min_mass = min_mass self.max_mass = max_mass def __hash__(self): return hash((self.min_mass, self.max_mass)) def __eq__(self, other): return (isinstance(other, MassFilter) and self.min_mass == other.min_mass and self.max_mass == other.max_mass) def __call__(self, state): with state.cpu_local_snapshot as snap: masses = snap.particles.mass indices = ((masses > self.min_mass) & (masses < self.max_mass)) return np.copy(snap.particles.tag[indices]) # All particles with 1.0 < mass < 5.0 filter_ = MassFilter(1.0, 5.0) gsd = hoomd.write.GSD('example.gsd', 100, filter=filter_)
Warning
Custom filters will not work with the set operation particle filters (i.e.
hoomd.filter.Union
,hoomd.filter.Intersection
, orhoomd.filter.SetDifference
). This restriction may be lifted in a future version.- abstract __call__(state)
Return the local particle tags that match the filter.
Returns the tags that are local to an MPI rank that match the particle filter. Tag numbers in a
hoomd.Snapshot
object are just their index.Note
The exact requirements for the tags returned by custom filters on each MPI rank is that the set union of the returned arrays from each MPI rank be all particles that match the filter. For general use, however, it is recommended that each rank only return the tags for particles that are in the local MPI rank (excluding ghost particles). This is preferable for ease of use with local snapshots to avoid accidentally attempting to access invalid array indices from tags outside of the MPI rank.
- Parameters
state (
hoomd.State
) – The simulation state to return the filtered tags from.- Returns
An array of MPI local tags that match the filter.
- Return type
(N,)
numpy.ndarray
ofnumpy.uint64
- class hoomd.filter.Intersection(f, g)
Set intersection operation.
- Parameters
f (ParticleFilter) – First set in the intersection.
g (ParticleFilter) – Second set in the intersection.
Intersection
is a composite filter. It selects particles in the set intersection \(f \cap g\).Base:
ParticleFilter
- class hoomd.filter.Null
Select no particles.
Base:
ParticleFilter
- class hoomd.filter.Rigid(flags=('center',))
Select particles based on inclusion in rigid bodies.
- Parameters
flags (
tuple
[str
], optional) – A tuple of strings of values “center”, “constituent”, or “free”. These string flags specify what kinds of particles to filter: “center” will include central particles in a rigid body, “constituent” will include non-central particles in a rigid body, and “free” will include all particles not in a rigid body. Specifying all three is the same ashoomd.filter.All
. The default is("center",)
Base:
ParticleFilter
- class hoomd.filter.SetDifference(f, g)
Set difference operation.
- Parameters
f (ParticleFilter) – First set in the difference.
g (ParticleFilter) – Second set in the difference.
SetDifference
is a composite filter. It selects particles in the set difference \(f \setminus g\).Base:
ParticleFilter
- class hoomd.filter.Tags(tags)
Select particles by tag.
A particle tag is a unique identifier assigned to each particle in the simulation state. When the state is first initialized, it assigns tags 0 through
N_particles
to the particles in the order provided.Base:
ParticleFilter
- class hoomd.filter.Type(types)
Select particles by type.
Base:
ParticleFilter
- class hoomd.filter.Union(f, g)
Set union operation.
- Parameters
f (ParticleFilter) – First set in the union.
g (ParticleFilter) – Second set in the union.
Union
is a composite filter. It selects particles in the set union \(f \cup g\).Base:
ParticleFilter
- hoomd.filter.filter_like
An object that acts like a particle filter.
Either a subclass of
ParticleFilter
orCustomFilter
.alias of
Union
[ParticleFilter
,CustomFilter
]
hoomd.logging
Overview
Creates loggable quantities for classes of type Loggable. |
|
Modify a class's namespace to a manually assigned one. |
|
Logs HOOMD-blue operation data and custom quantities. |
|
Enum that marks all accepted logger types. |
Details
Logging infrastructure.
Use the Logger
class to collect loggable quantities (e.g. kinetic temperature,
pressure, per-particle energy) during the simulation run. Pass the Logger
to a
backend such as hoomd.write.GSD
or hoomd.write.Table
to write the logged
values to a file.
- class hoomd.logging.LoggerCategories(value)
Enum that marks all accepted logger types.
This class does not need to be used by users directly. We directly convert from strings to the enum wherever necessary in the API. This class is documented to show users what types of quantities can be logged, and what categories to use for limiting what data is logged, user specified logged quantities, and custom actions (
hoomd.custom.Action
).- sequence
Sequence (e.g.
list
,tuple
,numpy.ndarray
) of numbers of the same type.
- object
Any Python object outside a sequence, string, or scalar.
- angle
Per-angle quantity.
- bond
Per-bond quantity.
- constraint
Per-constraint quantity.
- dihedral
Per-dihedral quantity.
- improper
Per-improper quantity.
- pair
Per-pair quantity.
- particle
Per-particle quantity.
- ALL
A combination of all other categories.
- NONE
Represents no category.
- classmethod any(categories=None)
Return a LoggerCategories enum representing any of the categories.
- Parameters
categories (
list
[str
] orlist
[LoggerCategories
]) – A list ofstr
orLoggerCategories
objects that should be represented by the returnedLoggerCategories
object.- Returns
the
LoggerCategories
object that represents any of the given categories.- Return type
- class hoomd.logging.Logger(categories=None, only_default=True)
Logs HOOMD-blue operation data and custom quantities.
The
Logger
class provides an intermediary between a backend such ashoomd.write.GSD
orhoomd.write.Table
and loggable objects. TheLogger
class makes use of namespaces which organize logged quantities. For example internally all loggable quantities are ordered by the module and class they come from. For instance, thehoomd.md.pair.LJ
class has a namespace('md', 'pair', 'LJ')
. This ensures that logged quantities remain unambiguous. Useadd
or the+=
operator to add loggable objects to theLogger
.Example
logger = hoomd.logging.Logger() lj = md.pair.lj(neighbor_list) # Log all default quantities of the lj object logger += lj logger = hoomd.logging.Logger(categories=['scalar']) # Log all default scalar quantities of the lj object logger += lj
The
Logger
class also supports user specified quantities using namespaces as well.Example
logger = hoomd.logging.Logger() # Add quantity to ('custom', 'name') namespace logger[('custom', 'name')] = (lambda: 42, 'scalar') # Add quantity to ('custom_name',) namespace logger[('custom_name',)] = (lambda: 43, 'scalar')
Logger
objects support two ways of discriminating what loggable quantities they will accept:categories
andonly_default
(the constructor arguments). Both of these are static, meaning that once instantiated, aLogger
object will not change the values of these two properties.categories
determines what types of loggable quantities (seeLoggerCategories
) are appropriate for a givenLogger
object. This helps logging backends determine if aLogger
object is compatible. Theonly_default
flag prevents rarely-used quantities (e.g. the number of neighborlist builds) from being added to the logger when using`Logger.__iadd__` andLogger.add
without specifying them explicitly. InLogger.add
, you can override theonly_default
flag by explicitly listing the quantities you want to add. On the other hand,categories
is rigidly obeyed as it is a promise to logging backends.Note
The logger provides a way for users to create their own logger back ends. See
log
for details on the intermediate representation.LoggerCategories
defines the various categories available to specify logged quantities. Custom backends should be a subclass ofhoomd.custom.Action
and used withhoomd.write.CustomWriter
.Note
When logging multiple instances of the same class
add
provides a means of specifying the class level of the namespace (e.g.'LJ
in('md', 'pair', 'LJ')
). The default behavior (without specifying a user name) is to just append_{num}
wherenum
is the smallest positive integer which makes the full namespace unique. This appending will also occur for user specified names that are reused.- Parameters
categories (
list
ofstr
, optional) – A list of string categories (list of categories can be found inLoggerCategories
). These are the only types of loggable quantities that can be logged by this logger. Defaults to allowing every type.only_default (
bool
, optional) – Whether to log only quantities that are logged by default. Defaults toTrue
. Non-default quantities are typically measures of operation performance rather than information about simulation state.
- __eq__(other)
Check for equality.
- __iadd__(obj)
Add quantities from object or list of objects to logger.
Adds all quantities compatible with given categories and default value.
Examples
logger += lj logger += [lj, harmonic_bonds]
- __isub__(value)
Remove log entries for a list of quantities or objects.
Examples
logger -= ('md', 'pair', 'lj') logger -= [('md', 'pair', 'lj', 'energy'), ('md', 'pair', 'lj', 'forces')] logger -= lj logger -= [lj, harmonic_bonds]
- __setitem__(namespace, value)
Allows user specified loggable quantities.
- Parameters
namespace (tuple[str,] or str) – key or nested key to determine where to store logged quantity.
value (tuple[Callable, str] or tuple[object, str, str]) – Either a tuple with a callable and the
LoggerCategories
object or associated string or a object with a method/property name and category. If using a method it should not take arguments or have defaults for all arguments.
- add(obj, quantities=None, user_name=None)
Add loggables from obj to logger.
- Parameters
obj (object of class of type
Loggable
) – class of type loggable to add loggable quantities from.quantities (Sequence[str]) – list of str names of quantities to log.
user_name (
str
, optional) – A string to replace the class name in the loggable quantities namespace. This allows for easier differentiation in the output of theLogger
and anyWriter
which outputs its data.
- Returns
A list of namespaces added to the logger.
- Return type
- log()
Get a nested dictionary of the current values for logged quantities.
The nested dictionary consist of one level for each element of a namespace. The logged value and category for the namespace
('example', 'namespace')
would be accessible in the returned dictionary vialogger.log()['example']['namespace']
.- Returns
A nested dictionary of the current logged quantities. The end values are (value, category) pairs which hold the value along with its associated
LoggerCategories
category represented as a string (to get theLoggerCategories
enum value useLoggerCategories[category]
.- Return type
- property only_default
Whether the logger object should only grab default loggable quantities.
- Type
- remove(obj=None, quantities=None, user_name=None)
Remove specified quantities from the logger.
- Parameters
obj (object of class of type
Loggable
, optional) – Object to remove quantities from. Ifquantities
is None,obj
must be set. Ifobj
is set andquantities
is None, all logged quantities fromobj
will be removed from the logger.quantities (Sequence[tuple]) – a sequence of namespaces to remove from the logger. If specified with
obj
only remove quantities listed that are exposed fromobj
. Ifobj
is None, thenquantities
must be given.user_name (str) – A user name to specify the final entry in the namespace of the object. This must be used in
user_name
was specified inadd
.
- hoomd.logging.log(func=None, *, is_property=True, category='scalar', default=True, requires_run=False)
Creates loggable quantities for classes of type Loggable.
Use
log
withhoomd.custom.Action
to expose loggable quantities from a custom action.- Parameters
func (
method
) – class method to make loggable. If using non-default arguments, func should not be set.is_property (
bool
, optional) – Whether to make the method a property, defaults to True. Keyword only argument.category (
str
, optional) – The string represention of the type of loggable quantity, defaults to ‘scalar’. SeeLoggerCategories
for available types. Keyword only argument.default (
bool
, optional) – Whether the quantity should be logged by default. Defaults to True. This is orthogonal to the loggable quantity’s type. Many users may not want to log such quantities even when logging other quantities of that type. An example would be performance orientated loggable quantities, like the number of neighborlist builds. Thedefault
argument allows for these to be skipped byLogger
objects by default. Keyword only argument.requires_run (
bool
, optional) – Whether this property requires the simulation to run before being accessible.
Note
The namespace (where the loggable object is stored in the
Logger
object’s nested dictionary) is determined by the module/script and class name the loggable class comes from. In creating subclasses ofhoomd.custom.Action
, for instance, if the module the subclass is defined in isuser.custom.action
and the class name isFoo
then the namespace used will be('user', 'custom', 'action', 'Foo')
. This helps to prevent naming conflicts and automates the logging specification for developers and users.Example:
# Metaclass specification is not necessary for # subclasses of HOOMD classes as they already use this # metaclass. class LogExample(metaclass=hoomd.logging.Loggable) @log(category="string") def loggable(self): return "log_me" @log(is_property=False, default=False) def not_property(self, a=4): return 2 ** a
See also
Tutorial: Custom Actions in Python
- hoomd.logging.modify_namespace(cls, namespace=None)
Modify a class’s namespace to a manually assigned one.
- Parameters
Warning
This will only persist for the current class. All subclasses will have the standard namespace assignment.
hoomd.mesh
Overview
Data structure combining multiple particles into a mesh. |
Details
Triangulated mesh data structure.
The mesh data structure combines particles into a connected triangulated network. The particles act as vertices of the triangulation and are linked with their neighbors in both pairs via mesh bonds and triplets via mesh triangles.
Mesh triangles and mesh bonds
Mesh.triangles
is a list of triangle data that constitutes the
triangulation. Each triangle is defined by a triplet of particle tags.
For a given triangulation HOOMD-blue also constructs a list of mesh bonds
automatically. Each mesh bond is defined by a pair of particle tags. The
corresponding vertex particles share a common edge in the triangulation.
Mesh potentials
In MD simulations different bond potentials can be attached which connect the vertex particles with a bond potential. The mesh data structure is designed so that other potentials (like bending potentials or global conservation potentials) can be implemented later.
See also
See the documentation in hoomd.md.mesh
for more information on how
to apply potentials to the mesh object and in hoomd.md.nlist
on
adding mesh bond exceptions to the neighbor list.
- class hoomd.mesh.Mesh
Data structure combining multiple particles into a mesh.
The mesh is defined by an array of triangles that make up a triangulated surface of particles. Each triangle consists of three particle tags. The mesh object consists of only one mesh triangle type with the default type name “mesh”.
Examples:
mesh = mesh.Mesh() mesh.triangles = [[0,1,2],[0,2,3],[0,1,3],[1,2,3]]
- property bonds
Mesh bonds.
A list of tuples of particle ids which encodes the bonds within the mesh structure.
(
Loggable
: category=”sequence”)- Type
((N, 2)
numpy.ndarray
ofuint32
)
- property triangles
Mesh triangulation.
A list of triplets of particle tags which encodes the triangulation of the mesh structure.
(
Loggable
: category=”sequence”)- Type
((N, 3)
numpy.ndarray
ofuint32
)
hoomd.operation
Overview
An object with autotuned kernel parameters. |
|
Compute properties of the simulation's state. |
|
Advance the simulation state forward one time step. |
|
Represents an operation. |
|
Adjust the parameters of other operations to improve performance. |
|
Operations that include a trigger to determine when to run. |
|
Change the simulation's state. |
|
Write output that depends on the simulation's state. |
Details
Operation class types.
Operations act on the state of the system at defined points during the
simulation’s run loop. Add operation objects to the Simulation.operations
collection.
- class hoomd.operation.Operation
Represents an operation.
Operations in the HOOMD-blue data scheme are objects that operate on a
hoomd.Simulation
object. They broadly consist of 5 subclasses:Updater
,Writer
,Compute
,Tuner
, andIntegrator
. All HOOMD-blue operations inherit from one of these five base classes. To find the purpose of each class see its documentation.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.Note
Developers or those contributing to HOOMD-blue, see our architecture file for information on HOOMD-blue’s architecture decisions regarding operations.
- __dir__()
Expose all attributes for dynamic querying in notebooks and IDEs.
- property is_tuning_complete
Check if kernel parameter tuning is complete.
True
when tuning is complete andkernel_parameters
has locked optimal parameters for all active kernels used by this object.- Type
- property kernel_parameters
Kernel parameters.
The dictionary maps GPU kernel names to tuples of integers that control how the kernel executes on the GPU. These values will change during the tuning process and remain static after tuning completes. Set the kernel parameters for one or more kernels to force specific values and stop tuning.
Warning
The keys and valid values in this dictionary depend on the hardware device, the HOOMD-blue version, and the value of class attributes. Keys and/or valid values may change even with new patch releases of HOOMD-blue.
Provided that you use the same HOOMD-blue binary on the same hardware and execute a script with the same parameters, you may save the tuned values from one run and load them in the next.
- tune_kernel_parameters()
Start tuning kernel parameters.
After calling
tune_kernel_parameters
,AutotunedObject
will vary the kernel parameters in subsequent time steps, check the run time of each, and lock to the fastest performing parameters after the scan is complete.
- class hoomd.operation.AutotunedObject
Bases:
An object with autotuned kernel parameters.
AutotunedObject
instances may complete portions of their computation with one or more GPU kernels. Each GPU kernel is executed with a set of parameters (kernel_parameters
) that influence the run time of the execution. After initialization,AutotunedObject
varies these parameters as the simulation runs and searches for the best performing combination. The optimal parameters depend on your system’s size, density, force field parameters, the specific hardware you execute on, and more.Check
is_tuning_complete
to check if the search is complete. After the search is complete,AutotunedObject
holds the parameters constant at the optimal values. Typical operations require thousands of time steps to complete tuning. Some may take tens of thousands or more depending on the parameters you set.Tip
When you significantly change your system during the simulation (e.g. compress to a higher density), then you can tune the parameters again after with
tune_kernel_parameters
. This step is optional, but may increase performance as the new system parameters may lead to different optimal parameters.Note
In MPI parallel execution, all methods and attributes of
AutotunedObject
reference the rank local tuner objects. Different ranks may tune different optimal kernel parameters and may complete tuning at different times. Use onlyhoomd.Operations.is_tuning_complete
in control flow operations, as this method is reduced across all ranks.- property is_tuning_complete
Check if kernel parameter tuning is complete.
True
when tuning is complete andkernel_parameters
has locked optimal parameters for all active kernels used by this object.- Type
- property kernel_parameters
Kernel parameters.
The dictionary maps GPU kernel names to tuples of integers that control how the kernel executes on the GPU. These values will change during the tuning process and remain static after tuning completes. Set the kernel parameters for one or more kernels to force specific values and stop tuning.
Warning
The keys and valid values in this dictionary depend on the hardware device, the HOOMD-blue version, and the value of class attributes. Keys and/or valid values may change even with new patch releases of HOOMD-blue.
Provided that you use the same HOOMD-blue binary on the same hardware and execute a script with the same parameters, you may save the tuned values from one run and load them in the next.
- tune_kernel_parameters()
Start tuning kernel parameters.
After calling
tune_kernel_parameters
,AutotunedObject
will vary the kernel parameters in subsequent time steps, check the run time of each, and lock to the fastest performing parameters after the scan is complete.
- class hoomd.operation.Compute
Bases:
Operation
Compute properties of the simulation’s state.
A compute is an operation which computes some property for another operation or use by a user.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.operation.Integrator
Bases:
Operation
Advance the simulation state forward one time step.
An integrator is the operation which evolves a simulation’s state in time. In
hoomd.hpmc
, integrators perform particle based Monte Carlo moves. Inhoomd.md
, thehoomd.md.Integrator
class organizes the forces, equations of motion, and other factors of the given simulation.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.operation.TriggeredOperation(trigger)
Bases:
Operation
Operations that include a trigger to determine when to run.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.operation.Tuner(trigger)
Bases:
TriggeredOperation
Adjust the parameters of other operations to improve performance.
A tuner is an operation which tunes the parameters of another operation for performance or other reasons. A tuner does not modify the current microstate of the simulation. That is a tuner does not change quantities like temperature, particle position, or the number of bonds in a simulation.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.operation.Updater(trigger)
Bases:
TriggeredOperation
Change the simulation’s state.
An updater is an operation which modifies a simulation’s state.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.operation.Writer(trigger)
Bases:
TriggeredOperation
Write output that depends on the simulation’s state.
A writer is an operation which writes out a simulation’s state.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
hoomd.trigger
Overview
Trigger on all steps after a given step. |
|
Boolean and operation. |
|
Trigger on all steps before a given step. |
|
Negate a trigger. |
|
Trigger on a specific timestep. |
|
Boolean or operation. |
|
Trigger periodically. |
|
Base class trigger. |
|
An object that can serve as a trigger for an operation. |
Details
Triggers determine when hoomd.operation.Operation
instances activate.
A Trigger
is a boolean valued function of the timestep. The operation will
perform its action when Trigger returns True
. A single trigger object
may be assigned to multiple operations.
User defined triggers
You can define your own triggers by subclassing Trigger
in Python. When you do
so, override the Trigger.compute
method and explicitly call the base class
constructor in __init__
.
Example
Define a custom trigger:
class CustomTrigger(hoomd.trigger.Trigger):
def __init__(self):
hoomd.trigger.Trigger.__init__(self)
def compute(self, timestep):
return (timestep**(1 / 2)).is_integer()
- class hoomd.trigger.After(timestep)
Bases:
Trigger
Trigger on all steps after a given step.
- Parameters
timestep (int) – The step before the trigger will start.
After
returnsTrue
for all time steps greater thantimestep
:return t > timestep
Example:
# trigger every 100 time steps after 1000 time steps. trigger = hoomd.trigger.And([ hoomd.trigger.After(1000), hoomd.trigger.Periodic(100)])
- class hoomd.trigger.And(triggers)
Bases:
Trigger
Boolean and operation.
And
returnsTrue
when all the input triggers returnsTrue
:return all([f(t) for f in triggers])
Example:
# trigger every 100 time steps after 1000 time steps. trig = hoomd.trigger.And([ hoomd.trigger.After(1000), hoomd.trigger.Periodic(100)])
- triggers
List of triggers.
- Type
- class hoomd.trigger.Before(timestep)
Bases:
Trigger
Trigger on all steps before a given step.
- Parameters
timestep (int) – The step after the trigger ends.
Before
evaluatesTrue
for all time steps less than thetimestep
:return t < timestep
Example:
# trigger every 100 time steps at less than first 5000 steps. trigger = hoomd.trigger.And( [hoomd.trigger.Periodic(100), hoomd.trigger.Before(sim.timestep + 5000)])
- class hoomd.trigger.Not(trigger)
Bases:
Trigger
Negate a trigger.
- Parameters
trigger (hoomd.trigger.Trigger) – The trigger object to negate.
Not
returns the boolean negation oftrigger
:return not trigger(t)
Example:
trigger = hoomd.trigger.Not(hoomd.trigger.After(1000))
- trigger
The trigger object to negate.
- class hoomd.trigger.On(timestep)
Bases:
Trigger
Trigger on a specific timestep.
- Parameters
timestep (int) – The timestep to trigger on.
On
returnsTrue
for steps equal totimestep
:return t == timestep
Example:
# trigger at 1000 time steps trigger = hoomd.trigger.On(1000)
- class hoomd.trigger.Or(triggers)
Bases:
Trigger
Boolean or operation.
Or
returnsTrue
when any of the input triggers returnsTrue
:return any([f(t) for f in triggers])
Example:
# trigger every 100 time steps before at time step of 1000. # or every 10 time steps after at time step of 1000. trig = hoomd.trigger.Or([hoomd.trigger.And([ hoomd.trigger.Before(1000), hoomd.trigger.Periodic(100)]), [hoomd.trigger.And([ hoomd.trigger.After(1000), hoomd.trigger.Periodic(10)]) ])
- class hoomd.trigger.Periodic(period, phase)
Bases:
Trigger
Trigger periodically.
Periodic
evaluatesTrue
everyperiod
steps offset by phase:return (t - phase) % period == 0
Example:
trig = hoomd.trigger.Periodic(100)
- class hoomd.trigger.Trigger
Base class trigger.
Provides methods common to all triggers.
Attention
Users should instantiate the subclasses, using
Trigger
directly will result in an error.
- hoomd.trigger.trigger_like
An object that can serve as a trigger for an operation.
Any instance of a
Trigger
subclass is allowed, as well as an int instance or any object convertible to an int. The integer is converted to aPeriodic
trigger viaPeriodic(period=int(a))
wherea
is the passed integer.Note
Attributes that are
Trigger
objects can be set via atrigger_like
object.
hoomd.tune
Overview
User-defined tuner. |
|
Solves equations of \(min_x f(x)\) using gradient descent. |
|
Optimize by consistently narrowing the range where the extrema is. |
|
Adjusts the boundaries of the domain decomposition. |
|
Class for defining y = f(x) relationships for tuning x for a set y target. |
|
Abstract base class for optimizing \(f(x)\). |
|
Order particles in memory to improve performance. |
|
Abstract base class for finding x such that \(f(x) = 0\). |
|
Solves equations of f(x) = y using a ratio of y with the target. |
|
Solves equations of f(x) = y using the secant method. |
|
Abstract base class various solver types. |
Details
Tuners.
Tuner
operations make changes to the parameters of other operations (or the
simulation state) that adjust the performance of the simulation without changing
the correctness of the outcome. Every new hoomd.Simulation
object includes a
ParticleSorter
in its operations by default. ParticleSorter
rearranges the
order of particles in memory to improve cache-coherency.
This package also defines the CustomTuner
class and a number of helper
classes. Use these to implement custom tuner operations in Python code.
..rubric:: Solver
Most tuners explicitly involve solving some sort of mathematical problem (e.g.
root-finding or optimizationr). HOOMD provides infrastructure for solving these
problems as they appear in our provided hoomd.operation.Tuner
subclasses. All
tuners that involve iteratively solving a problem compose a SolverStep
subclass instance. The SolverStep
class implements the boilerplate to do
iterative solving given a simulation where calls to the “function” being solves
means running potentially 1,000’s of steps.
Every solver regardless of type has a solve
method which accepts a list of
tunable quantities. The method returns a Boolean indicating whether all
quantities are considered tuned or not. Tuners indicate they are tuned when two
successive calls to SolverStep.solve
return True
unless otherwise
documented.
Custom solvers can be created from inheriting from the base class of one of the
problem types (RootSolver
and Optimizer
) or SolverStep
if solving a
different problem type. All that is required is to implement the
SolverStep.solve_one
method, and the solver can be used by any HOOMD tuner
that expects a solver.
Custom Tuners
Through using SolverStep
subclasses and ManualTuneDefinition
most tuning
problems should be solvable for a CustomTuner
. To create a tuner define all
ManualTuneDefinition
interfaces for each tunable and plug into a solver in a
CustomTuner
.
- class hoomd.tune.ManualTuneDefinition(get_y, target, get_x, set_x, domain=None)
Class for defining y = f(x) relationships for tuning x for a set y target.
This class is made to be used with
hoomd.tune.SolverStep
subclasses. Here y represents a dependent variable of x. In general, x and y should be of typefloat
, but specifichoomd.tune.SolverStep
subclasses may accept other types.A special case for the return type of y is
None
. If the value is currently inaccessible or would be invalid, aManualTuneDefinition
object can return a y ofNone
to indicate this.hoomd.tune.SolverStep
objects will handle this automatically. Since we check forNone
internally inhoomd.tune.SolverStep
objects, aManualTuneDefinition
object’sy
property should be consistant when called multiple times within a timestep.When setting
x
the value is clamped between the given domain via,\[\begin{split}x &= x_{max}, \text{ if } x_n > x_{max},\\ x &= x_{min}, \text{ if } x_n < x_{min},\\ x &= x_n, \text{ otherwise}\end{split}\]- Parameters
get_y (
callable
) – A callable that gets the current value for y.target (
any
) – The target y value to approach.get_x (
callable
) – A callable that gets the current value for x.set_x (
callable
) – A callable that sets the current value for x.domain (
tuple
[any
,any
], optional) – A tuple pair of the minimum and maximum accepted values of x, defaults toNone
. When, the domain isNone
then any value of x is accepted. Either the minimum or maximum can be set toNone
as well which means there is no maximum or minimum. The domain is used to wrap values within the specified domain when setting x.
Note
Placing domain restrictions on x can lead to the target y value being impossible to converge to. This will lead to the
hoomd.tune.SolverStep
object passed this tunable to never finish solving regardless if all otherManualTuneDefinition
objects are converged.- __eq__(other)
Test for equality.
- __hash__()
Compute a hash of the tune definition.
- clamp_into_domain(value)
Return the closest value within the domain.
- Parameters
value (
any
) – A value of the same type as x.- Returns
The value clamps within the domains of x. Clamping here refers to returning the value or minimum or maximum of the domain if value is outside the domain.
- property domain
A tuple pair of the minimum and maximum accepted values of x.
When the domain is None, any value of x is accepted. Either the minimum or maximum can be set to
None
as well which means there is no maximum or minimum. The domain is used to wrap values within the specified domain when setting x.- Type
tuple[
any
,any
]
- in_domain(value)
Check whether a value is in the domain.
- Parameters
value (
any
) – A value that can be compared to the minimum and maximum of the domain.- Returns
Whether the value is in the domain of x.
- Return type
- property max_x
Maximum allowed x value.
- property min_x
Minimum allowed y value.
- property target
The targetted y value, can be set.
- property x
The dependent variable.
Can be set. When set the setting value is clamped within the provided domain. See
clamp_into_domain
for further explanation.
- property y
The independent variable, and is unsettable.
- class hoomd.tune.CustomTuner(trigger, action)
Bases:
CustomOperation
,Tuner
User-defined tuner.
- Parameters
action (hoomd.custom.Action) – The action to call.
trigger (hoomd.trigger.trigger_like) – Select the timesteps to call the action.
CustomTuner
is ahoomd.operation.Tuner
that wraps a user-definedhoomd.custom.Action
object so the action can be added to ahoomd.Operations
instance for use withhoomd.Simulation
objects.Tuners modify the parameters of other operations to improve performance. Tuners may read the system state, but not modify it.
See also
The base class
hoomd.custom.CustomOperation
.
- class hoomd.tune.GradientDescent(alpha: float = 0.1, kappa: Optional[ndarray] = None, tol: float = 1e-05, maximize: bool = True, max_delta: Optional[float] = None)
Bases:
Optimizer
Solves equations of \(min_x f(x)\) using gradient descent.
Derivatives are computed using the forward difference.
The solver updates
x
each step via,\[x_n = x_{n-1} - \alpha {\left (1 - \kappa) \nabla f + \kappa \Delta_{n-1} \right)}\]where \(\Delta\) is the last step size. This gives the optimizer a sense of momentum which for noisy (stochastic) optimization can lead to smoother optimization. Due to the need for two values to compute a derivative, then first time this is called it makes a slight jump higher or lower to start the method.
The solver will stop updating when a maximum is detected (i.e. the step size is smaller than
tol
).- Parameters
alpha (
hoomd.variant.variant_like
, optional) – Either a number between 0 and 1 used to dampen the rate of change in x or a variant that varies not by timestep but by the number of timessolve
has been called (i.e. the number of steps taken) (defaults to 0.1).alpha
scales the corrections to x each iteration. Larger values ofalpha
lead to larger changes while aalpha
of 0 leads to no change in x at all.kappa (
numpy.ndarray
, optional) – Real number array that determines how much of the previous steps’ directions to use (defaults toNone
which does no averaging over past step directions). The array values correspond to weight that the \(N\) last steps are weighted when combined with the current step. The current step is weighted by \(1 - \sum_{i=1}^{N} \kappa_i\).tol (
float
, optional) – The absolute tolerance for convergence of y, (defaults to1e-5
).maximize (
bool
, optional) – Whether or not to maximize function (defaults toTrue
).max_delta (
float
, optional) – The maximum step size to allow (defaults toNone
which allows a step size of any length).
- kappa
Real number array that determines how much of the previous steps’ directions to use. The array values correspond to weight that the \(N\) last steps are weighted when combined with the current step. The current step is weighted by \(1 - \sum_{i=1}^{N} \kappa_i\).
- Type
- __eq__(other)
Test for equality.
- property alpha
Number between 0 and 1 that dampens of change in x.
Larger values of
alpha
lead to larger changes while aalpha
of 0 leads to no change in x at all. The property returns the currentalpha
given the current number of steps.The property can be set as in the constructor.
- Type
- reset()
Reset all solving internals.
- solve(tunables)
Iterates towards a solution for a list of tunables.
If a y for one of the
tunables
isNone
then we skip thattunable
. Skipping implies that the quantity is not tuned andsolve
will returnFalse
.- Parameters
tunables (list[
hoomd.tune.ManualTuneDefinition
]) – A list of tunable objects that represent a relationship f(x) = y.- Returns
Returns whether or not all tunables were considered tuned by the object.
- Return type
- solve_one(tunable)
Solve one step.
- class hoomd.tune.GridOptimizer(n_bins: int = 5, n_rounds: int = 1, maximize: bool = True)
Bases:
Optimizer
Optimize by consistently narrowing the range where the extrema is.
The algorithm is as follows. Given a domain \(d = [a, b]\), \(d\) is broken up into
n_bins
subsequent bins. For the nextn_bins
calls, the optimizer tests the function value at each bin center. The next call does one of two things. If the number of rounds has reachedn_rounds
the optimization is done, and the center of the best bin is the solution. Otherwise, another round is performed where the bin’s extent is the new domain.Warning
Changing a tunables domain during usage of a
GridOptimizer
results in incorrect behavior.- Parameters
- __eq__(other)
Test for equality.
- reset()
Reset all solving internals.
- solve_one(tunable)
Perform one step of optimization protocol.
- class hoomd.tune.LoadBalancer(trigger, x=True, y=True, z=True, tolerance=1.02, max_iterations=1)
Bases:
Tuner
Adjusts the boundaries of the domain decomposition.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps on which to perform load balancing.
tolerance (float) – Load imbalance tolerance.
max_iterations (int) – Maximum number of iterations to attempt in a single step.
LoadBalancer
adjusts the boundaries of the MPI domains to distribute the particle load close to evenly between them. The load imbalance is defined as the number of particles owned by a rank divided by the average number of particles per rank if the particles had a uniform distribution:\[I = \frac{N_i}{N / P}\]where \(N_i\) is the number of particles on rank \(i\), \(N\) is the total number of particles, and \(P\) is the number of ranks.
In order to adjust the load imbalance,
LoadBalancer
scales by the inverse of the imbalance factor. To reduce oscillations and communication overhead, it does not move a domain more than 5% of its current size in a single rebalancing step, and not more than half the distance to its neighbors.Simulations with interfaces (so that there is a particle density gradient) or clustering should benefit from load balancing. The potential speedup is \(I-1.0\), so that if the largest imbalance is 1.4, then the user can expect a 40% speedup in the simulation. This is of course an estimate that assumes that all algorithms are linear in \(N\), all GPUs are fully occupied, and the simulation is limited by the speed of the slowest processor. If you have a simulation where, for example, some particles have significantly more pair force neighbors than others, this estimate of the load imbalance may not produce the optimal results.
A load balancing adjustment is only performed when the maximum load imbalance exceeds a tolerance. The ideal load balance is 1.0, so setting tolerance less than 1.0 will force an adjustment every update. The load balancer can attempt multiple iterations of balancing on each update, and up to maxiter attempts can be made. The optimal values of update and maxiter will depend on your simulation.
Load balancing can be performed independently and sequentially for each dimension of the simulation box. A small performance increase may be obtained by disabling load balancing along dimensions that are known to be homogeneous. For example, if there is a planar vapor-liquid interface normal to the \(z\) axis, then it may be advantageous to disable balancing along \(x\) and \(y\).
In systems that are well-behaved, there is minimal overhead of balancing with a small update. However, if the system is not capable of being balanced (for example, due to the density distribution or minimum domain size), having a small update and high maxiter may lead to a large performance loss. In such systems, it is currently best to either balance infrequently or to balance once in a short test run and then set the decomposition statically in a separate initialization.
Balancing is ignored if there is no domain decomposition available (MPI is not built or is running on a single rank).
- trigger
Select the timesteps on which to perform load balancing.
- class hoomd.tune.Optimizer
Bases:
SolverStep
Abstract base class for optimizing \(f(x)\).
- class hoomd.tune.ParticleSorter(trigger=200, grid=None)
Bases:
Tuner
Order particles in memory to improve performance.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps on which to sort. Defaults to a
hoomd.trigger.Periodic(200)
trigger.grid (int) – Resolution of the grid to use when sorting. The default value of
None
setsgrid=4096
in 2D simulations andgrid=256
in 3D simulations.
ParticleSorter
improves simulation performance by sorting the particles in memory along a space-filling curve. This takes particles that are close in space and places them close in memory, leading to a higher rate of cache hits when computing pair potentials.Note
New
hoomd.Operations
instances include aParticleSorter
constructed with default parameters.- trigger
Select the timesteps on which to sort.
- class hoomd.tune.RootSolver
Bases:
SolverStep
Abstract base class for finding x such that \(f(x) = 0\).
For solving for a non-zero value, \(f(x) - y_t = 0\) is solved.
- class hoomd.tune.ScaleSolver(max_scale=2.0, gamma=2.0, correlation='positive', tol=1e-05)
Bases:
RootSolver
Solves equations of f(x) = y using a ratio of y with the target.
Each time this solver is called it takes updates according to the following equation if the correlation is positive:
\[x_n = \min{\left(\frac{\gamma + t}{y + \gamma}, s_{max}\right)} \cdot x\]and
\[x_n = \min{\left(\frac{y + \gamma}{\gamma + t}, s_{max}\right)} \cdot x\]if the correlation is negative, where \(t\) is the target and \(x_n\) is the new x.
The solver will stop updating when \(\lvert y - t \rvert \le tol\).
- Parameters
max_scale (
float
, optional) – The maximum amount to scale the current x value with, defaults to 2.0.gamma (
float
, optional) – nonnegative real number used to dampen or increase the rate of change in x.gamma
is added to the numerator and denominator of they / target
ratio. Larger values ofgamma
lead to smaller changes while agamma
of 0 leads to scaling x by exactly they / target
ratio.correlation (
str
, optional) – Defines whether the relationship between x and y is of a positive or negative correlation, defaults to ‘positive’. This determines which direction to scale x in for a given y.tol (
float
, optional) – The absolute tolerance for convergence of y, defaults to 1e-5.
Note
This solver is only usable when quantities are strictly positive.
- __eq__(other)
Test for equality.
- reset()
Reset all solving internals.
- solve_one(tunable)
Solve one step.
- class hoomd.tune.SecantSolver(gamma=0.9, tol=1e-05)
Bases:
RootSolver
Solves equations of f(x) = y using the secant method.
The solver updates
x
each step via,\[x_n = x - \gamma \cdot (y - t) \cdot \frac{x - x_{o}}{y - y_{old}}\]where \(o\) represent the old values, \(n\) the new, and \(t\) the target. Due to the need for a previous value, then first time this is called it makes a slight jump higher or lower to start the method.
The solver will stop updating when \(\lvert y - t \rvert \le tol\).
- Parameters
gamma (
float
, optional) – real number between 0 and 1 used to dampen the rate of change in x.gamma
scales the corrections to x each iteration. Larger values ofgamma
lead to larger changes while agamma
of 0 leads to no change in x at all.tol (
float
, optional) – The absolute tolerance for convergence of y, defaults to 1e-5.
Note
Tempering the solver with a smaller than 1
gamma
value is crucial for numeric stability. If instability is found, then loweringgamma
accordingly should help.- __eq__(other)
Test for equality.
- reset()
Reset all solving internals.
- solve_one(tunable)
Solve one step.
- class hoomd.tune.SolverStep
Bases:
object
Abstract base class various solver types.
Requires a single method
solve_one
that steps forward one iteration in solving the given variable relationship. Users can use subclasses of this withhoomd.tune.ManualTuneDefinition
to tune attributes with a functional relation.Note
A
SolverStep
object requires manual iteration to converge. This is to support the use case of measuring quantities that require running the simulation for some amount of time after one iteration before remeasuring the dependent variable (i.e. the y).SolverStep
object can be used inhoomd.custom.Action
subclasses for user defined tuners and updaters.- abstract reset()
Reset all solving internals.
This should put the solver in its initial state as if it has not seen any tunables or done any solving yet.
- solve(tunables)
Iterates towards a solution for a list of tunables.
If a y for one of the
tunables
isNone
then we skip thattunable
. Skipping implies that the quantity is not tuned andsolve
will returnFalse
.- Parameters
tunables (list[
hoomd.tune.ManualTuneDefinition
]) – A list of tunable objects that represent a relationship f(x) = y.- Returns
Returns whether or not all tunables were considered tuned by the object.
- Return type
- abstract solve_one(tunable)
Takes in a tunable object and attempts to solve x for a specified y.
- Parameters
tunable (
hoomd.tune.ManualTuneDefinition
) – A tunable object that represents a relationship of f(x) = y.- Returns
Whether or not the tunable converged to the target.
- Return type
hoomd.update
Overview
Resizes the box between an initial and final box. |
|
User-defined updater. |
|
Update sets of particles associated with a filter. |
|
Remove the average drift from a restrained system. |
Details
Updaters.
Updater
operations modify the simulation state when they act.
- class hoomd.update.BoxResize(trigger, box1, box2, variant, filter=hoomd._hoomd.ParticleFilter)
Bases:
Updater
Resizes the box between an initial and final box.
BoxResize
resizes the box between gradually from the initial box to the final box. The simulation box follows the linear interpolation between the initial and final boxes where the minimum of the variant givesbox1
and the maximum givesbox2
:\[\begin{split}\begin{align*} L_{x}' &= \lambda L_{2x} + (1 - \lambda) L_{1x} \\ L_{y}' &= \lambda L_{2y} + (1 - \lambda) L_{1y} \\ L_{z}' &= \lambda L_{2z} + (1 - \lambda) L_{1z} \\ xy' &= \lambda xy_{2} + (1 - \lambda) xy_{2} \\ xz' &= \lambda xz_{2} + (1 - \lambda) xz_{2} \\ yz' &= \lambda yz_{2} + (1 - \lambda) yz_{2} \\ \end{align*}\end{split}\]Where
box1
is \((L_{1x}, L_{1y}, L_{1z}, xy_1, xz_1, yz_1)\),box2
is \((L_{2x}, L_{2y}, L_{2z}, xy_2, xz_2, yz_2)\), \(\lambda = \frac{f(t) - \min f}{\max f - \min f}\), \(t\) is the timestep, and \(f(t)\) is given byvariant
.For each particle \(i\) matched by
filter
,BoxResize
scales the particle to fit in the new box:\[\vec{r}_i \leftarrow s_x \vec{a}_1' + s_y \vec{a}_2' + s_z \vec{a}_3' - \frac{\vec{a}_1' + \vec{a}_2' + \vec{a}_3'}{2}\]where \(\vec{a}_k'\) are the new box vectors determined by \((L_x', L_y', L_z', xy', xz', yz')\) and the scale factors are determined by the current particle position \(\vec{r}_i\) and the old box vectors \(\vec{a}_k\):
\[\vec{r}_i = s_x \vec{a}_1 + s_y \vec{a}_2 + s_z \vec{a}_3 - \frac{\vec{a}_1 + \vec{a}_2 + \vec{a}_3}{2}\]After scaling particles that match the filter,
BoxResize
wraps all particles \(j\) back into the new box:\[\vec{r_j} \leftarrow \mathrm{minimum\_image}_{\vec{a}_k}' (\vec{r}_j)\]Important
The passed
Variant
must be bounded on the interval \(t \in [0,\infty)\) or the behavior of the updater is undefined.Warning
Rescaling particles fails in HPMC simulations with more than one MPI rank.
Note
When using rigid bodies, ensure that the
BoxResize
updater is last in the operations updater list. Immediately after theBoxResize
updater triggers, rigid bodies (hoomd.md.constrain.Rigid
) will be temporarily deformed.hoomd.md.Integrator
will run after the last updater and resets the constituent particle positions before computing forces.- Parameters
trigger (hoomd.trigger.trigger_like) – The trigger to activate this updater.
box1 (hoomd.box.box_like) – The box associated with the minimum of the passed variant.
box2 (hoomd.box.box_like) – The box associated with the maximum of the passed variant.
variant (hoomd.variant.variant_like) – A variant used to interpolate between the two boxes.
filter (hoomd.filter.filter_like) – The subset of particle positions to update.
- variant
A variant used to interpolate between the two boxes.
- trigger
The trigger to activate this updater.
- filter
The subset of particles to update.
- get_box(timestep)
Get the box for a given timestep.
- Parameters
timestep (int) – The timestep to use for determining the resized box.
- Returns
The box used at the given timestep.
None
before the first call toSimulation.run
.- Return type
- static update(state, box, filter=hoomd._hoomd.ParticleFilter)
Immediately scale the particle in the system state to the given box.
- Parameters
state (State) – System state to scale.
box (hoomd.box.box_like) – New box.
filter (hoomd.filter.filter_like) – The subset of particles to update.
- class hoomd.update.CustomUpdater(trigger, action)
Bases:
CustomOperation
,Updater
User-defined updater.
- Parameters
action (hoomd.custom.Action) – The action to call.
trigger (hoomd.trigger.trigger_like) – Select the timesteps to call the action.
CustomUpdater
is ahoomd.operation.Updater
that wraps a user-definedhoomd.custom.Action
object so the action can be added to ahoomd.Operations
instance for use withhoomd.Simulation
objects.Updaters modify the system state.
See also
The base class
hoomd.custom.CustomOperation
.
- class hoomd.update.FilterUpdater(trigger, filters)
Bases:
Updater
Update sets of particles associated with a filter.
hoomd.Simulation
caches the particles selected byhoomd.filter.filter_like
objects to avoid the cost of re-running the filter on every time step. The particles selected by a filter will remain static until recomputed. This class provides a mechanism to update the cached list of particles. For example, periodically update a MD integration method’s group so that the integration method applies to particles in a given region of space.Tip
To improve performance, use a
hoomd.trigger.Trigger
subclass, to update only when there is a known change to the particles that a filter would select.Note
Some actions automatically recompute all filter particles such as adding or removing particles to the
hoomd.Simulation.state
.- Parameters
trigger (hoomd.trigger.trigger_like) – A trigger to use for determining when to update particles associated with a filter.
filters (list[hoomd.filter.filter_like]) – A list of
hoomd.filter.filter_like
objects to update.
- trigger
The trigger associated with the updater.
- __eq__(other)
Return whether two objects are equivalent.
- property filters
filters to update select particles.
- Type
- class hoomd.update.RemoveDrift(reference_positions, trigger=1)
Bases:
Updater
Remove the average drift from a restrained system.
- Parameters
reference_positions ((N_particles, 3)
numpy.ndarray
offloat
) – the reference positions \([\mathrm{length}]\).trigger (hoomd.trigger.trigger_like) – Select the timesteps to remove drift.
RemoveDrift
computes the mean drift \(\vec{D}\) from the givenreference_positions
(\(\vec{r}_{ref, i}\)):\[\vec{D} = \frac{1}{\mathrm{N_{particles}}} \sum_{i=0}^\mathrm{N_{particles-1}} \mathrm{minimum\_image}(\vec{r}_i - \vec{r}_{ref,i})\]RemoveDrift
then shifts all particles in the system by \(-\vec{D}\):\[\vec{r}_i \leftarrow \mathrm{minimum\_image}(\vec{r}_i - \vec{D})\]Tip
Use
RemoveDrift
withhoomd.hpmc.external.field.Harmonic
to improve the accuracy of Frenkel-Ladd calculations.- reference_positions
the reference positions \([\mathrm{length}]\).
- Type
(N_particles, 3)
numpy.ndarray
offloat
- trigger
The timesteps to remove drift.
hoomd.variant
Overview
A constant value. |
|
A cycle of linear ramps. |
|
An approach from initial to final value following |
|
A linear ramp. |
|
Variant base class. |
|
Objects that are like a variant. |
Details
Define quantities that vary over the simulation.
A Variant
object represents a scalar function of the time step. Some
operations accept Variant
values for certain parameters, such as the
kT
parameter to hoomd.md.methods.NVT
.
Use one of the built in variant types, or define your own custom function in Python:
class CustomVariant(hoomd.variant.Variant):
def __init__(self):
hoomd.variant.Variant.__init__(self)
def __call__(self, timestep):
return (float(timestep)**(1 / 2))
def _min(self):
return 0.0
def _max(self):
return float('inf')
Note
Provide the minimum and maximum values in the _min
and _max
methods respectively.
- class hoomd.variant.Constant(value)
Bases:
Variant
A constant value.
- Parameters
value (float) – The value.
Constant
returnsvalue
at all time steps.- __eq__(other)
Return whether two variants are equivalent.
- class hoomd.variant.Cycle(A, B, t_start, t_A, t_AB, t_B, t_BA)
Bases:
Variant
A cycle of linear ramps.
- Parameters
Cycle
holds the value A until time t_start. It continues holding that value until t_start + t_A. Then it ramps linearly from A to B over t_AB steps and holds the value B for t_B steps. After this, it ramps back from B to A over t_BA steps and repeats the cycle starting with t_A.Cycle
repeats this cycle indefinitely.- __eq__(other)
Return whether two variants are equivalent.
- class hoomd.variant.Power(A, B, power, t_start, t_ramp)
Bases:
Variant
An approach from initial to final value following
t**power
.- Parameters
Power
holds the value A until time t_start. Then it progresses at \(t^{\mathrm{power}}\) from A to B over t_ramp steps and holds the value B after that.p = Power(A=2, B-8, power=1 / 10, t_start=10, t_ramp=20)
- __eq__(other)
Return whether two variants are equivalent.
- class hoomd.variant.Ramp(A, B, t_start, t_ramp)
Bases:
Variant
A linear ramp.
- Parameters
Ramp
holds the value A until time t_start. Then it ramps linearly from A to B over t_ramp steps and holds the value B.- __eq__(other)
Return whether two variants are equivalent.
- class hoomd.variant.Variant
Variant base class.
Variants are scalar valued functions of the simulation time step.
- __call__(timestep)
Evaluate the function.
- __getstate__()
Get the variant’s
__dict__
attribute.
- __setstate__(state)
Restore the state of the variant.
- property max
The maximum value of this variant for \(t \in [0,\infty)\).
- property min
The minimum value of this variant for \(t \in [0,\infty)\).
- hoomd.variant.variant_like
Objects that are like a variant.
Any subclass of
Variant
is accepted along with float instances and objects convertible to float. They are internally converted to variants of typeConstant
viaConstant(float(a))
wherea
is the float or float convertible object.Note
Attributes that are
Variant
objects can be set via avariant_like
object.
hoomd.version
Version and build information.
Use the values in hoomd.version
to query properties of the package set at
compile time.
- hoomd.version.floating_point_precision
The high precision floating point width in bits (element 0) and the reduced precision width in bits (element 1).
hoomd.wall
Overview
A right circular cylinder. |
|
A plane. |
|
A sphere. |
|
Abstract base class for a HOOMD wall geometry. |
Details
Wall geometries.
Walls define an oriented surface in space. Walls exist only in the primary box image and are not replicated across the periodic boundary conditions. Points on one side of the surface have a positive signed distance to that surface, and points on the other side have a negative signed distance.
Define individual walls with Cylinder
, Plane
, and Sphere
. Create lists of
these WallGeometry
objects to describe more complex geometries. Use walls to
confine particles to specific regions of space in HPMC and MD simulations.
- class hoomd.wall.Cylinder(radius, axis, origin=(0.0, 0.0, 0.0), inside=True, open=True)
Bases:
WallGeometry
A right circular cylinder.
- Parameters
radius (float) – The radius of the circle faces of the cylinder \([\mathrm{length}]\).
axis (
tuple
[float
,float
,float
]) – A vector perpendicular to the circular faces.origin (
tuple
[float
,float
,float
], optional) – The origin of the cylinder defined as the center of the circle along the cylinder’s axis \([\mathrm{length}]\).inside (
bool
, optional) – Whether positive signed distances are inside or outside the cylinder.open (
bool
, optional) – Whether to include the surface of the cylinder in the space.True
means do not include the surface, defaults toTrue
.
Cylinder walls in HOOMD span the simulation box in the direction given by the
axis
attribute.The signed distance from the wall surface is
\[d = \left( R - \lvert \left( \vec{r} - \vec{r}_o \right) - \left( \left( \vec{r} - \vec{r}_o \right) \cdot \hat{n} \right) \hat{n} \rvert \right)\]for
inside=True
, where \(r\) is the particle position, \(\vec{r}_o\) is the origin of the cylinder, \(\hat{n}\) is the cylinder’s unit axis, and \(R\) is the cylinder’s radius. The distance is negated wheninside=False
.Warning
When running MD simulations in 2D simulation boxes, set
axis=(0,0,1)
. Otherwise, the wall force will push particles off the xy plane.Note
Cylinder
objects are immutable.- origin
The origin of the cylinder defined as the center of the circle along the cylinder’s axis \([\mathrm{length}]\).
- open
Whether to include the surface of the cylinder in the space.
True
means do not include the surface.- Type
bool
, optional
- __repr__()
A string representation of the Cylinder.
- __str__()
A string representation of the Cylinder.
- class hoomd.wall.Plane(origin, normal, open=True)
Bases:
WallGeometry
A plane.
- Parameters
origin (
tuple
[float
,float
,float
]) – A point that lies on the plane \([\mathrm{length}]\).normal (
tuple
[float
,float
,float
]) – The normal vector to the plane. The vector will be converted to a unit vector \([\mathrm{dimensionless}]\).open (
bool
, optional) – Whether to include the surface of the plane in the space.True
means do not include the surface, defaults toTrue
.
The signed distance from the wall surface is:
\[d = \hat{n} \cdot \left( \vec{r} - \vec{r}_o \right)\]where \(\vec{r}\) is the particle position, \(\vec{r}_o\) is the origin of the plane, and \(\hat{n}\) is the plane’s unit normal. The normal points toward the points with a positive signed distance to the plane.
Warning
When running MD simulations in 2D simulation boxes, set
normal=(nx,ny,0)
. Otherwise, the wall force will push particles off the xy plane.Note
Plane
objects are immutable.- open
Whether to include the surface of the plane in the space.
True
means do not include the surface.- Type
- __repr__()
A string representation of the Plane.
- __str__()
A string representation of the Plane.
- class hoomd.wall.Sphere(radius, origin=(0.0, 0.0, 0.0), inside=True, open=True)
Bases:
WallGeometry
A sphere.
- Parameters
radius (float) – The radius of the sphere \([\mathrm{length}]\).
origin (
tuple
[float
,float
,float
], optional) – The origin of the sphere, defaults to(0, 0, 0)
\([\mathrm{length}]\).inside (
bool
, optional) – Whether positive signed distances are inside or outside the sphere, defaults toTrue
.open (
bool
, optional) – Whether to include the surface of the sphere in the space.True
means do not include the surface, defaults toTrue
.
The signed distance from the wall surface is:
\[d = \left( R - \lvert \vec{r} - \vec{r}_o \rvert \right)\]for
inside=True
, where \(r\) is the particle position, \(r_o\) is the origin of the sphere, and \(R\) is the sphere’s radius. The distance is negated wheninside=False
.Warning
When running MD simulations in 2D simulation boxes, set
origin[2]=(x,y,0)
. Otherwise, the wall force will push particles off the xy plane.Note
Sphere
objects are immutable.- open
Whether to include the surface of the sphere in the space. Open means do not include the surface.
- Type
- __repr__()
A string representation of the Sphere.
- __str__()
A string representation of the Sphere.
- class hoomd.wall.WallGeometry
Bases:
ABC
Abstract base class for a HOOMD wall geometry.
Walls are used in both HPMC and MD subpackages. Subclasses of
WallGeometry
abstract over the wall geometries for both use cases.
hoomd.write
Overview
Writes simulation trajectories in the DCD format. |
|
User-defined writer. |
|
Write simulation trajectories in the GSD format. |
|
Write delimiter separated values to a stream. |
Details
Writers.
Writers write the state of the simulation, logger quantities, or calculated results to output files or streams:
Combine
GSD
with ahoomd.logging.Logger
to save system properties or per-particle calculated results.Use
Table
to display the status of the simulation periodically to standard out.Implement custom output formats with
CustomWriter
.
Writers do not modify the system state.
Tip
OVITO has native support for GSD files, including logged per-particle array quantities and particle shapes.
- class hoomd.write.Table(trigger, logger, output=stdout, header_sep='.', delimiter=' ', pretty=True, max_precision=10, max_header_len=None)
Write delimiter separated values to a stream.
Use
Table
to write scalar and stringhoomd.logging.Logger
quantities to standard out or to a file.Warning
When logger quantities include strings with spaces, the default space delimiter will result in files that are not machine readable.
Important
All attributes for this class are static. They cannot be set to new values once created.
- Parameters
trigger (hoomd.trigger.trigger_like) – The trigger to determine when to run the Table backend.
logger (hoomd.logging.Logger) – The logger to query for output. The ‘scalar’ categories must be set on the logger, and the ‘string’ categories is optional.
output (
file-like
object , optional) – A file-like object to output the data from, defaults to standard out. The object must havewrite
andflush
methods and amode
attribute. Examples includesys.stdout
,sys.stderr
and the return value ofopen()
.header_sep (
str
, optional) – String to use to separate names in the logger’s namespace, defaults to'.'
. For example, if logging the total energy of anhoomd.md.pair.LJ
pair force object, the default header would bemd.pair.LJ.energy
(assuming thatmax_header_len
is not set).delimiter (
str
, optional) – String used to separate elements in the space delimited file, defaults to' '
.pretty (
bool
, optional) – Flags whether to attempt to make output prettier and easier to read, defaults to True. To make the output easier to read, the output will compromise on numerical precision for improved readability. In many cases, the precision will still be high with pretty set toTrue
.max_precision (
int
, optional) – If pretty is not set, then this controls the maximum precision to use when outputing numerical values, defaults to 10.max_header_len (
int
, optional) – If not None (the default), limit the outputted header names to lengthmax_header_len
. When not None, names are grabbed from the most specific to the least. For example, if set to 7 the namespace ‘hoomd.md.pair.LJ.energy’ would be set to ‘energy’. Note that at least the most specific part of the namespace will be used regardless of this setting (e.g. if set to 5 in the previous example, ‘energy’ would still be the header).
- trigger
The trigger to determine when to run the Table backend.
- logger
The logger to query for output. The ‘scalar’ categories must be set on the logger, and the ‘string’ categories is optional.
- Type
- output
A file-like object to output the data from. The object must have
write
andflush
methods and amode
attribute.- Type
file-like
object
- header_sep
String to use to separate names in the logger’s namespace.’. For example, if logging the total energy of an
hoomd.md.pair.LJ
pair force object, the default header would bemd.pair.LJ.energy
(assuming thatmax_header_len
is not set).- Type
- pretty
Flags whether to attempt to make output prettier and easier to read. To make the output easier to read, the output will compromise on outputted precision for improved readability. In many cases, though the precision will still be high with pretty set to
True
.- Type
- max_precision
If pretty is not set, then this controls the maximum precision to use when outputing numerical values, defaults to 10.
- Type
int
, optional
- max_header_len
Limits the outputted header names to length
max_header_len
when notNone
. Names are grabbed from the most specific to the least. For example, if set to 7 the namespace ‘hoomd.md.pair.LJ.energy’ would be set to ‘energy’. Note that at least the most specific part of the namespace will be used regardless of this setting (e.g. if set to 5 in the previous example, ‘energy’ would still be the header).- Type
- write()
Write out data to
self.output
.Writes a row from given
hoomd.logging.Logger
object data.
- class hoomd.write.CustomWriter(trigger, action)
Bases:
CustomOperation
,Writer
User-defined writer.
- Parameters
action (hoomd.custom.Action) – The action to call.
trigger (hoomd.trigger.trigger_like) – Select the timesteps to call the action.
CustomWriter
is ahoomd.operation.Writer
that wraps a user-definedhoomd.custom.Action
object so the action can be added to ahoomd.Operations
instance for use withhoomd.Simulation
objects.Writers may read the system state and generate output files or print to output streams. Writers should not modify the system state.
See also
The base class
hoomd.custom.CustomOperation
.
- class hoomd.write.DCD(trigger, filename, filter=hoomd._hoomd.ParticleFilter, overwrite=False, unwrap_full=False, unwrap_rigid=False, angle_z=False)
Bases:
Writer
Writes simulation trajectories in the DCD format.
- Parameters
trigger (hoomd.trigger.Periodic) – Select the timesteps to write.
filename (str) – File name to write.
filter (hoomd.filter.filter_like) – Select the particles to write. Defaults to
hoomd.filter.All
.overwrite (bool) – When False, (the default) an existing DCD file will be appended to. When True, an existing DCD file filename will be overwritten.
unwrap_full (bool) – When False, (the default) particle coordinates are always written inside the simulation box. When True, particles will be unwrapped into their current box image before writing to the DCD file.
unwrap_rigid (bool) – When False, (the default) individual particles are written inside the simulation box which breaks up rigid bodies near box boundaries. When True, particles belonging to the same rigid body will be unwrapped so that the body is continuous. The center of mass of the body remains in the simulation box, but some particles may be written just outside it. unwrap_rigid is ignored when unwrap_full is True.
angle_z (bool) – When True, the particle orientation angle is written to the z component (only useful for 2D simulations)
DCD
writes the simulation trajectory to the specified file in the DCD file format. DCD stores only particle positions and the box parameters, in length units, and is limited to simulations where the number of particles is fixed.Examples:
writer = hoomd.write.DCD("trajectory.dcd", hoomd.trigger.Periodic(1000)) dcd = hoomd.write.DCD(filename="data/dump.dcd", trigger=hoomd.trigger.Periodic(100, 10))
Warning
When you use
DCD
to append to an existing DCD file:The period must be the same or the time data in the file will not be consistent.
DCD
will not write out data at time steps that already are present in the DCD file.
- trigger
Select the timesteps to write.
- filter
Select the particles to write.
- overwrite
When False, an existing DCD file will be appended to. When True, an existing DCD file filename will be overwritten.
- Type
- unwrap_full
When False, particle coordinates are always written inside the simulation box. When True, particles will be unwrapped into their current box image before writing to the DCD file.
- Type
- unwrap_rigid
When False, individual particles are written inside the simulation box which breaks up rigid bodies near box boundaries. When True, particles belonging to the same rigid body will be unwrapped so that the body is continuous. The center of mass of the body remains in the simulation box, but some particles may be written just outside it. unwrap_rigid is ignored when unwrap_full is True.
- Type
- class hoomd.write.GSD(trigger, filename, filter=hoomd._hoomd.ParticleFilter, mode='ab', truncate=False, dynamic=None, log=None)
Bases:
Writer
Write simulation trajectories in the GSD format.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps to write.
filename (str) – File name to write.
filter (hoomd.filter.filter_like) – Select the particles to write. Defaults to
hoomd.filter.All
.mode (str) – The file open mode. Defaults to
'ab'
.truncate (bool) – When
True
, truncate the file and write a new frame 0 each time this operation triggers. Defaults toFalse
.dynamic (list[str]) – Quantity categories to save in every frame. Defaults to
['property']
.log (hoomd.logging.Logger) – Provide log quantities to write. Defaults to
None
.
GSD
writes the simulation trajectory to the specified file in the GSD format.GSD
can store all particle, bond, angle, dihedral, improper, pair, and constraint data fields in every frame of the trajectory.GSD
can write trajectories where the number of particles, number of particle types, particle types, diameter, mass, charge, or other quantities change over time.GSD
can also store scalar, string, and array quantities provided by ahoomd.logging.Logger
instance.Valid file open modes:
mode
description
'wb'
Open the file for writing. Create the file if needed, or overwrite an existing file.
'xb'
Create a GSD file exclusively. Raise an exception when the file exists.
'ab'
Create the file if needed, or append to an existing file.
To reduce file size,
GSD
does not write properties that are set to defaults. When masses, orientations, angular momenta, etc… are left default for all particles, these fields will not take up any space in the file. Additionally,GSD
only writes dynamic quantities to all frames. It writes non-dynamic quantities only the first frame. When reading a GSD file, the data in frame 0 is read when a quantity is missing in frame i, supplying data that is static over the entire trajectory. Set the dynamicSpecify the one or more of the following strings in dynamic to make the corresponding quantities dynamic (property is always dynamic):
property
particles/position
particles/orientation (only written when values are not the default: [1,0,0,0])
momentum
particles/velocity
particles/angmom (only written when values are not the default: [0,0,0,0])
particles/image (only written when values are not the default: [0,0,0])
attribute
particles/N
particles/types
particles/typeid
particles/mass
particles/charge
particles/diameter
particles/body
particles/moment_inertia
topology
bonds/*
angles/*
dihedrals/*
impropers/*
constraints/*
pairs/*
See also
See the GSD documentation, GSD HOOMD Schema, and GSD GitHub project for more information on GSD files.
Note
When you use
filter
to select a subset of the whole system,GSD
writes only the selected particles in ascending tag order and does not write out topology.Tip
All logged data chunks must be present in the first frame in the gsd file to provide the default value. To achieve this, set the
log
attribute before the operation is triggered to write the first frame in the file.Some (or all) chunks may be omitted on later frames. You can set
log
toNone
or remove specific quantities from the logger, but do not add additional quantities after the first frame.- trigger
Select the timesteps to write.
- filter
Select the particles to write.
- truncate
When
True
, truncate the file and write a new frame 0 each time this operation triggers.- Type
- static write(state, filename, filter=hoomd._hoomd.ParticleFilter, mode='wb', log=None)
Write the given simulation state out to a GSD file.
- Parameters
state (State) – Simulation state.
filename (str) – File name to write.
filter (hoomd.filter.filter_like) – Select the particles to write.
mode (str) – The file open mode. Defaults to
'wb'
.log (hoomd.logging.Logger) – Provide log quantities to write.
The valid file modes for
write
are'wb'
and'xb'
.
hoomd.hpmc
Details
Hard particle Monte Carlo.
In hard particle Monte Carlo (HPMC) simulations, the particles in the system
state have extended shapes. The potential energy of the system is infinite when
any particle shapes overlap. Pair (hoomd.hpmc.pair) and external
(hoomd.hpmc.external) potentials compute the potential energy when there
are no shape overlaps. hpmc
employs the Metropolis Monte Carlo algorithm to
sample equilibrium configurations of the system.
To perform HPMC simulations, assign a HPMC integrator (hoomd.hpmc.integrate
)
to the hoomd.Simulation
operations. The HPMC integrator defines the particle
shapes and performs local trial moves on the particle positions and
orientations. HPMC updaters (hoomd.hpmc.update
) interoperate with the
integrator to perform additional types of trial moves, including box moves,
cluster moves, and particle insertion/removal. Use HPMC computes
(hoomd.hpmc.compute
) to compute properties of the system state, such as the
free volume or pressure.
See also
Anderson 2016 further describes the theory and implementation.
Modules
hoomd.hpmc.compute
Overview
Compute the free volume available to a test particle. |
|
Compute the scale distribution function. |
Details
Compute properties of hard particle configurations.
The HPMC compute classes analyze the system configuration and provide results
as loggable quantities for use with hoomd.logging.Logger
or by direct access
via the Python API. FreeVolume
computes the free volume available to small
particles, such as depletants, and SDF
computes the pressure in system of
convex particles with a fixed box size.
- class hoomd.hpmc.compute.FreeVolume(test_particle_type, num_samples)
Compute the free volume available to a test particle.
- Parameters
FreeVolume
computes the free volume in the simulation state available to a given test particle shape using Monte Carlo integration. Use it in combination withhoomd.hpmc.integrate.HPMCIntegrator
, which defines the particle shape parameters. Particles oftest_particle_type
may or may not be present in the simulation state.FreeVolume
generatesnum_samples
(\(n_\mathrm{samples}\)) trial particle configurations with positions \(\vec{r}^t_j\) uniformly distributed in the simulation box, and orientations \(\mathbf{q}^t_j\) uniformly distributed among rotations matching the box dimensionality.FreeVolume
counts the number of successful samples that do not overlap particles in the simulation state:\[n_\mathrm{success} = \sum_{j=1}^{n_\mathrm{samples}} \prod_{i=0}^{N_\mathrm{particles}-1} \prod_{\vec{A} \in B_\mathrm{images}} \left[ \mathrm{overlap}\left( S_i(\mathbf{q}_i), S_t(\mathbf{q}^t_j, \vec{r}^t_j - (\vec{r}_i + \vec{A})) \right) = \emptyset \right]\]where \(\mathrm{overlap}\) is the shape overlap function defined in
hoomd.hpmc.integrate
, \(S_i\) is the shape of particle \(i\), \(S_t\) is the shape of the test particle, \(\vec{A} = h\vec{a}_1 + k\vec{a}_2 + l\vec{a}_3\) is a vector that translates by periodic box images, the set of box images includes all image vectors necessary to find overlaps between particles in the primary image with particles in periodic images, and the square brackets denote the Iverson bracket.The free volume \(V_\mathrm{free}\) is given by:
\[V_\mathrm{free} = \frac{n_\mathrm{success}} {n_\mathrm{samples}} V_\mathrm{box}\]where \(V_\mathrm{box}\) is the volume of the simulation box (or area in 2D).
Note
FreeVolume
respects the HPMC integrator’sinteraction_matrix
.Mixed precision
FreeVolume
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.Box images
On CPU devices,
FreeVolume
does not apply the minimum image convention. It supports small boxes where particles may overlap with non-primary images of other particles, including self overlap. On GPU devices,FreeVolume
applies the minimum image convention.Examples:
fv = hoomd.hpmc.compute.FreeVolume(test_particle_type='B', num_samples=1000)
- class hoomd.hpmc.compute.SDF(xmax, dx)
Compute the scale distribution function.
- Parameters
SDF
computes the proability distribution \(s(x)\) of particles overlapping as a function of separation. It estimates \(s(x)\) numerically by computing a histogram with \(\lfloor x_\mathrm{max}/ \delta x \rfloor\) bins of widthdx
(\(\delta x\)).See also
Anderson 2016 describes the theory relating
SDF
to the system pressure.Implementation
For each pair of particles \(i\) and \(j\)
SDF
scales the particle separation vector by the factor \((1-x)\) and finds the smallest positive value of \(x\) leading to either an overlap of the particle shapes (a “hard overlap”) or a discontinuous change in the pair energy \(U_{\mathrm{pair},ij}\) (a “soft overlap”):\[\begin{split}x_{ij}(\vec{A}) = \min \{ & x \in \mathbb{R}_{> 0} : \\ & \mathrm{overlap}\left( S_i(\mathbf{q}_i), S_j(\mathbf{q}_j, (1-x)(\vec{r}_j - (\vec{r}_i + \vec{A}))) \right) \ne \emptyset \\ &\lor \\ & U_{\mathrm{pair},ij}((1-x)(\vec{r}_j - (\vec{r}_i + \vec{A})), \mathbf{q}_i, \mathbf{q}_j) \ne U_{\mathrm{pair},ij}(\vec{r}_j - (\vec{r}_i + \vec{A}), \mathbf{q}_i, \mathbf{q}_j) \\ \} &\end{split}\]where \(\mathrm{overlap}\) is the shape overlap function defined in
hoomd.hpmc.integrate
, \(S_i\) is the shape of particle \(i\), and \(\vec{A} = h\vec{a}_1 + k\vec{a}_2 + l\vec{a}_3\) is a vector that translates by periodic box images.\(x_i\) is the minimum value of \(x_{ij}\) for a single particle:
\[x_i = \min \{ x_{ij} : \vec{A} \in B_\mathrm{images}, j \in [0,N_\mathrm{particles}) \}\]where the set of box images includes all image vectors necessary to find overlaps between particles in the primary image with particles in periodic images.
SDF
adds a single count to the histogram for each particle \(i\), weighted by a factor that is a function of the change in energy upon overlap:\[s(x + \delta x/2) = \frac{1}{N_\mathrm{particles} \cdot \delta x} \sum_{i=0}^{N_\mathrm{particles}-1} [x \le x_i < x + \delta x] \cdot (1 - \exp(-\beta \Delta U_{i}))\]where \(\Delta U_{i}\) is the change in energy associated with the first overlap involving particle \(i\) (\(\infty\) for hard overlaps), the square brackets denote the Iverson bracket, and \(s(x + \delta x/2)\) is evaluated for \(\{ x \in \mathbb{R}, 0 \le x < x_\mathrm{max}, x = k \cdot \delta x, k \in \mathbb{Z}^* \}\).
Pressure
The extrapolation of \(s(x)\) to \(x = 0\), \(s(0+)\) is related to the pressure \(P\):
\[\beta P = \rho \left(1 + \frac{s(0+)}{2d} \right)\]where \(d\) is the dimensionality of the system, \(\rho\) is the number density, and \(\beta = \frac{1}{kT}\). This measurement of the pressure is inherently noisy due to the nature of the sampling. Average
betaP
over many timesteps to obtain accurate results.Assuming particle diameters are ~1, these paramater values typically achieve good results:
xmax = 0.02
dx = 1e-4
In systems near densest packings,
dx=1e-5
may be needed along with smallerxmax
. Check that \(\sum_k s(x_k) \cdot dx \approx 0.5\).Warning
SDF
only considers negative volume perturbations, and therefore does not compute the correct pressure in simulations where positive volume perturbations may change the system’s potential energy, e.g., systems of concave particles or with non-monotonic enthalpic interactions.Warning
Because SDF samples pair configurations at discrete separations, the computed pressure is correct only for potentials with constant values and step discontinuities, e.g., square well potentials.
Note
SDF
always runs on the CPU.Mixed precision
SDF
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.Box images
SDF
does not apply the minimum image convention. It supports small boxes where particles may overlap with non-primary images of other particles, including self overlap.- property betaP
Beta times pressure in NVT simulations \(\left[ \mathrm{length}^{-d} \right]\).
Uses a polynomial curve fit of degree 5 to estimate \(s(0+)\) and computes the pressure via:
\[\beta P = \rho \left(1 + \frac{s(0+)}{2d} \right)\]where \(d\) is the dimensionality of the system, \(\rho\) is the number density, and \(\beta = \frac{1}{kT}\).
Attention
In MPI parallel execution,
betaP
is available on rank 0 only.betaP
isNone
on ranks >= 1.(
Loggable
: category=”scalar”)- Type
- property sdf
\(s[k]\) - The scale distribution function \([\mathrm{probability\ density}]\).
The \(x\) at the center of bin \(k\) is: \(x = k \cdot \delta x + \delta x/2\).
Attention
In MPI parallel execution, the array is available on rank 0 only.
sdf
isNone
on ranks >= 1.(
Loggable
: category=”sequence”)- Type
(N_bins,)
numpy.ndarray
offloat
)
hoomd.hpmc.integrate
Overview
Convex polygon hard particle Monte Carlo integrator. |
|
Convex polyhedron hard particle Monte Carlo integrator. |
|
Convex spheropolygon hard particle Monte Carlo integrator. |
|
Convex spheropolyhedron hard particle Monte Carlo integrator. |
|
Convex spheropolyhedron union hard particle Monte Carlo integrator. |
|
Ellipsoid hard particle Monte Carlo integrator. |
|
Faceted ellipsoid hard particle Monte Carlo integrator. |
|
Faceted ellispod union hard particle Monte Carlo integrator. |
|
Base class hard particle Monte Carlo integrator. |
|
Polyhedron hard particle Monte Carlo integrator. |
|
Simple polygon hard particle Monte Carlo integrator. |
|
Sphere hard particle Monte Carlo integrator. |
|
Sphere union hard particle Monte Carlo integrator. |
|
Sphinx hard particle Monte Carlo integrator. |
Details
Hard particle Monte Carlo integrators.
Metropolis Monte Carlo
The hard particle Monte Carlo (HPMC) integrator HPMCIntegrator
samples
equilibrium system states using the Metropolis Monte Carlo method. In this
method, HPMCIntegrator
takes the existing system state in the configuration
\(C = (\vec{r}_0, \vec{r}_1, \ldots \vec{r}_{N_\mathrm{particles}-1},
\mathbf{q}_0, \mathbf{q}_2, \ldots \mathbf{q}_{N_\mathrm{particles}-1})\) with
potential energy \(U\) and perturbs it to a trial configuration \(C^t\)
with potential energy \(U^t\) leading to an energy difference \(\Delta
U = U^t - U\). The trial move is accepted with the probability:
When the trial move is accepted, the system state is set to the the trial configuration. When it is not accepted, the move is rejected and the state is not modified.
Temperature
HPMC assumes that \(\beta = \frac{1}{kT} = 1\). This is not relevant to systems of purely hard particles where \(\Delta U\) is either 0 or \(\infty\). To adjust the effective temperature in systems with finite interactions (see Energy evaluation below), scale the magnitude of the energetic interactions accordingly.
Local trial moves
HPMCIntegrator
generates local trial moves for a single particle \(i\) at
a time. The move is either a translation move or a rotation move, selected
randomly with the probability of a translation move set by
HPMCIntegrator.translation_move_probability
(\(p_\mathrm{translation}\)).
The form of the trial move depends on the dimensionality of the system. Let \(u\) be a random value in the interval \([0,1]\), \(\vec{v}\) be a random vector uniformly distributed within the ball of radius 1, and \(\mathbf{w}\) be a random unit quaternion from the set of uniformly distributed rotations. Then the 3D trial move for particle \(i\) is:
where \(d_i\) is the translation move size for particle \(i\) (set by
particle type with HPMCIntegrator.d
) and \(a_i\) is the rotation move size
(set by particle type with HPMCIntegrator.a
).
In 2D boxes, let \(\vec{v}\) be a random vector uniformly distributed within the disk of radius 1 in the x,y plane and \(\alpha\) be a random angle in radians in the interval \([-a_i,a_i]\). Form a quaternion that rotates about the z axis by \(\alpha\): \(\mathbf{w} = (\cos(\alpha/2), 0, 0, \sin(\alpha/2))\). The 2D trial move for particle \(i\) is:
Note
For non-orientable spheres, \(p_\mathrm{translation} = 1\).
Timesteps
In the serial CPU implementation, HPMCIntegrator
performs nselect
trial moves per particle in each timestep (which
defaults to 4). To achieve detailed balance at the level of a timestep,
HPMCIntegrator
randomly chooses with equal probability to loop through
particles in forward index or reverse index order (random selection severely
degrades performance due to cache incoherency). In the GPU and MPI
implementations, trial moves are performed in parallel for particles in active
domains while leaving particles on the border fixed (see Anderson 2016 for a full description). As a
consequence, a single timestep may perform more or less than nselect
trial
moves per particle when using the parallel code paths. Monitor the number of
trial moves performed with HPMCIntegrator.translate_moves
and
HPMCIntegrator.rotate_moves
.
Random numbers
HPMCIntegrator
uses a pseudorandom number stream to generate the trial moves.
Set the seed using hoomd.Simulation.seed
. Given the same seed, the same
initial configuration, and the same execution configuration (device and MPI
configuration), HPMCIntegrator
, will produce exactly the same trajectory.
Note
Due to limited floating point precision, full trajectory reproducibility is only possible with the same binary installation running on the same hardware device. Compiler optimizations, changes to the HOOMD source code, and machine specific code paths may lead to different trajectories.
Energy evaluation
HPMCIntegrator
evaluates the energy of a configuration from a number of terms:
To enable simulations of small systems, the pair and shape energies evaluate interactions between pairs of particles in multiple box images:
where \(\vec{A} = h\vec{a}_1 + k\vec{a}_2 + l\vec{a}_3\) is a vector that
translates by periodic box images and the set of box images includes all image
vectors necessary to find interactions between particles in the primary image
with particles in periodic images The first sum evaluates interactions between
particle \(i\) with other particles (not itself) in the primary box image.
The second sum evaluates interactions between particle \(i\) and all
potentially interacting periodic images of all particles (including itself).
HPMCIntegrator
computes \(U_{\mathrm{shape}}\) similarly (see below).
External potentials apply to each particle individually:
Potential classes in hoomd.hpmc.pair evaluate
\(U_{\mathrm{pair},ij}\). Assign a class instance to
HPMCIntegrator.pair_potential
to apply it during integration. Similarly,
potential classes in hoomd.hpmc.external evaluate
\(U_{\mathrm{external},i}\). Assign a class instance to
HPMCIntegrator.external_potential
to apply it during integration.
Shape overlap tests
HPMCIntegrator
performs shape overlap tests to evaluate
\(U_{\mathrm{shape}}\). Let \(S\) be the set of all points inside the
shape in the local coordinate system of the shape:
See the subclasses of HPMCIntegrator
for formal definitions of the shapes,
whose parameters are set by particle type. Let \(S_i\) refer specifically
to the shape for particle \(i\).
The quaternion \(\mathbf{q}\) represents a rotation of the shape from its local coordinate system to the given orientation:
The full transformation from the local shape coordinate system to the simulation box coordinate system includes a rotation and translation:
HPMCIntegrator
defines the shape overlap test for two shapes:
To check for overlaps between two particles in the box, rotating both shapes from their local frame to the box frame, and translate \(S_2\) relative to particle 1:
The complete hard shape interaction energy for a given configuration is:
where the square brackets denote the Iverson bracket.
Note
While this notation is written in as sums over all particles
HPMCIntegrator
uses spatial data structures to evaluate these calculations
efficiently. Similarly, while the overlap test is notated as a set
intersection, HPMCIntegrator
employs efficient computational geometry
algorithms to determine whether there is or is not an overlap.
Implicit depletants
Set HPMCIntegrator.depletant_fugacity
to activate the implicit depletant code
path. This inerts depletant particles during every trial move and modifies the
acceptance criterion accordingly. See Glaser 2015 for details.
- class hoomd.hpmc.integrate.ConvexPolygon(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Convex polygon hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of convex polygons. The shape \(S\) of a convex polygon includes the points inside and on the surface of the convex hull of the vertices (see
shape
). For example:Important
ConvexPolygon
simulations must be performed in 2D systems.See also
Use
SimplePolygon
for concave polygons.Wall support.
ConvexPolygon
supports nohoomd.wall
geometries.Examples:
mc = hoomd.hpmc.integrate.ConvexPolygon(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(vertices=[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)]); print('vertices = ', mc.shape["A"]["vertices"])
- shape
The shape parameters for each particle type. The dictionary has the following keys.
vertices
(list
[tuple
[float
,float
]], required) - vertices of the polygon \([\mathrm{length}]\).Vertices MUST be specified in a counter-clockwise order.
The origin MUST be contained within the polygon.
Points inside the polygon MUST NOT be included.
The origin centered circle that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - Ignored, but present becauseConvexPolygon
shares data structures withConvexSpheropolygon
\([\mathrm{length}]\).
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.ConvexPolyhedron(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Convex polyhedron hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of convex polyhedra. The shape \(S\) of a convex polyhedron includes the points inside and on the surface of the convex hull of the vertices (see
shape
). For example:See also
Use
Polyhedron
for concave polyhedra.Wall support.
ConvexPolyhedron
supports allhoomd.wall
geometries.Example:
mc = hpmc.integrate.ConvexPolyhedron(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(vertices=[(0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5)]); print('vertices = ', mc.shape["A"]["vertices"])
- shape
The shape parameters for each particle type. The dictionary has the following keys.
vertices
(list
[tuple
[float
,float
,float
]], required) - vertices of the polyhedron \([\mathrm{length}]\).The origin MUST be contained within the polyhedron.
The origin centered sphere that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - Ignored, but present becauseConvexPolyhedron
shares data structures withConvexSpheropolyhedron
\([\mathrm{length}]\).
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.ConvexSpheropolygon(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Convex spheropolygon hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of convex spheropolygons. The shape \(S\) of a convex spheropolygon includes the points inside and on the surface of the convex hull of the vertices plus a disk (with radius
sweep_radius
)swept along the perimeter (seeshape
). For example:Important
ConvexSpheropolygon
simulations must be performed in 2D systems.Tip
To model mixtures of convex polygons and convex spheropolygons, use
ConvexSpheropolygon
and set the sweep radius to 0 for some shape types.Tip
A 1-vertex spheropolygon is a disk and a 2-vertex spheropolygon is a rectangle with half disk caps.
Wall support.
ConvexSpheropolygon
supports nohoomd.wall
geometries.Examples:
mc = hoomd.hpmc.integrate.ConvexSpheropolygon(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(vertices=[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)], sweep_radius=0.1); mc.shape["A"] = dict(vertices=[(0,0)], sweep_radius=0.5, ignore_statistics=True); print('vertices = ', mc.shape["A"]["vertices"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
vertices
(list
[tuple
[float
,float
]], required) - vertices of the polygon \([\mathrm{length}]\).The origin MUST be contained within the spheropolygon.
Points inside the polygon should not be included.
The origin centered circle that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(default: 0.0) - radius of the disk swept around the edges of the polygon \([\mathrm{length}]\). Set a non-zerosweep_radius
to create a spheropolygon.
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.ConvexSpheropolyhedron(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Convex spheropolyhedron hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of convex spheropolyhedra. The shape \(S\) of a convex spheropolyhedron includes the points inside and on the surface of the convex hull of the vertices plus a sphere (with radius
sweep_radius
) swept along the perimeter (seeshape
). SeeConvexSpheropolygon
for a visual example in 2D.Tip
A 1-vertex spheropolygon is a sphere and a 2-vertex spheropolygon is a spherocylinder.
Wall support.
ConvexSpheropolyhedron
supports thehoomd.wall.Sphere
andhoomd.wall.Plane
geometries.Example:
mc = hpmc.integrate.ConvexSpheropolyhedron(default_d=0.3, default_a=0.4) mc.shape['tetrahedron'] = dict(vertices=[(0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5)]); print('vertices = ', mc.shape['tetrahedron']["vertices"]) mc.shape['SphericalDepletant'] = dict(vertices=[], sweep_radius=0.1, ignore_statistics=True);
Depletants example:
mc = hpmc.integrate.ConvexSpheropolyhedron(default_d=0.3, default_a=0.4) mc.shape["tetrahedron"] = dict(vertices=[(0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5)]); mc.shape["SphericalDepletant"] = dict(vertices=[], sweep_radius=0.1); mc.depletant_fugacity["SphericalDepletant"] = 3.0
- shape
The shape parameters for each particle type. The dictionary has the following keys:
vertices
(list
[tuple
[float
,float
,float
]], required) - vertices of the polyhedron \([\mathrm{length}]\).The origin MUST be contained within the polyhedron.
The origin centered sphere that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - radius of the sphere swept around the surface of the polyhedron \([\mathrm{length}]\). Set a non-zero sweep_radius to create a spheropolyhedron.
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.ConvexSpheropolyhedronUnion(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Convex spheropolyhedron union hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of unions of convex sphereopolyhedra. The union shape \(S\) is the set union of the given convex spheropolyhedra:
\[S = \bigcup_k S_k(\mathbf{q}_k, \vec{r}_k)\]Each constituent shape in the union has its own shape parameters \(S_k\), position \(\vec{r}_k\), and orientation \(\mathbf{q}_k\) (see
shape
).Note
This shape uses an internal OBB tree for fast collision queries. Depending on the number of constituent spheropolyhedra in the tree, different values of the number of spheropolyhedra per leaf node may yield different performance. The capacity of leaf nodes is configurable.
Wall support.
ConvexSpheropolyhedronUnion
supports nohoomd.wall
geometries.Example:
mc = hoomd.hpmc.integrate.ConvexSpheropolyhedronUnion(default_d=0.3, default_a=0.4) cube_verts = [[-1,-1,-1], [-1,-1,1], [-1,1,1], [-1,1,-1], [1,-1,-1], [1,-1,1], [1,1,1], [1,1,-1]] mc.shape["A"] = dict(shapes=[cube_verts, cube_verts], positions=[(0, 0, 0), (0, 0, 1)], orientations=[(1, 0, 0, 0), (1, 0, 0, 0)], overlap=[1, 1]); print('vertices of the first cube = ', mc.shape["A"]["shapes"][0]["vertices"]) print('center of the first cube = ', mc.shape["A"]["positions"][0]) print('orientation of the first cube = ', mc.shape_param["A"]["orientations"][0])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
shapes
(list
[dict
], required) - Shape parameters for each spheropolyhedron in the union. SeeConvexSpheropolyhedron.shape
for the accepted parameters.positions
(list
[tuple
[float
,float
,float
]], required) - Position of each spheropolyhedron in the union. \([\mathrm{length}]\)orientations
(list
[tuple
[float
,float
,float
,float
]], default: None) - Orientation of each spheropolyhedron in the union. When notNone
,orientations
must have a length equal to that ofpositions
. WhenNone
(the default),orientations
is initialized with all [1,0,0,0]’s.overlap
(list
[int
], default:None
) - Check for overlaps between constituent particles whenoverlap [i] & overlap[j]
is nonzero (&
is the bitwise AND operator). When notNone
,overlap
must have a length equal to that ofpositions
. WhenNone
(the default),overlap
is initialized with all 1’s.capacity
(int
, default: 4) - set the maximum number of particles per leaf node to adjust performance.ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.Ellipsoid(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Ellipsoid hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of ellipsoids. The shape \(S\) includes all points inside and on the surface of an ellipsoid:
\[S = \left \{ \vec{r} : \frac{r_x^2}{a^2} + \frac{r_y^2}{b^2} + \frac{r_z^2}{c^2} \le 1 \right\}\]where \(r_x\), \(r_y\), \(r_z\) are the components of \(\vec{r}\), and the parameters \(a\), \(b\), and \(c\) are the half axes of the ellipsoid set in
shape
.Wall support.
Ellipsoid
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.Ellipsoid(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(a=0.5, b=0.25, c=0.125); print('ellipsoids parameters (a,b,c) = ', mc.shape["A"]["a"], mc.shape["A"]["b"], mc.shape["A"]["c"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
a
(float
, required) - half axis of ellipsoid in the x direction \([\mathrm{length}]\)b
(float
, required) - half axis of ellipsoid in the y direction \([\mathrm{length}]\)c
(float
, required) - half axis of ellipsoid in the z direction \([\mathrm{length}]\)ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.FacetedEllipsoid(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Faceted ellipsoid hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of faceted ellipsoids. The shape \(S\) of a faceted ellipsoid is the intersection of an ellipsoid with a convex polyhedron defined through halfspaces (see
shape
). The equation defining each halfspace is given by:\[\vec{n}_i\cdot \vec{r} + b_i \le 0\]where \(\vec{n}_i\) is the face normal, and \(b_i\) is the offset.
Wall support.
FacetedEllipsoid
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.FacetedEllipsoid(default_d=0.3, default_a=0.4) # half-space intersection slab_normals = [(-1,0,0),(1,0,0),(0,-1,0),(0,1,0),(0,0,-1),(0,0,1)] slab_offsets = [-0.1,-1,-.5,-.5,-.5,-.5] # polyedron vertices slab_verts = [[-.1,-.5,-.5], [-.1,-.5,.5], [-.1,.5,.5], [-.1,.5,-.5], [1,-.5,-.5], [1,-.5,.5], [1,.5,.5], [1,.5,-.5]] mc.shape["A"] = dict(normals=slab_normals, offsets=slab_offsets, vertices=slab_verts, a=1.0, b=0.5, c=0.5); print('a = {}, b = {}, c = {}', mc.shape["A"]["a"], mc.shape["A"]["b"], mc.shape["A"]["c"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
normals
(list
[tuple
[float
,float
,float
]], required) - facet normals \(\\vec{n}_i\).offsets
(list
[float
], required) - list of offsets \(b_i\) \([\mathrm{length}^2]\)a
(float
, required) - half axis of ellipsoid in the x direction \([\mathrm{length}]\)b
(float
, required) - half axis of ellipsoid in the y direction \([\mathrm{length}]\)c
(float
, required) - half axis of ellipsoid in the z direction \([\mathrm{length}]\)vertices
(list
[tuple
[float
,float
,float
]], default: []) - list of vertices for intersection polyhedron (see note below). \([\mathrm{length}]\)origin
(tuple
[float
,float
,float
], default: (0,0,0)) - A point inside the shape. \([\mathrm{length}]\)ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
Important
The origin must be chosen so as to lie inside the shape, or the overlap check will not work. This condition is not checked.
Warning
Planes must not be coplanar.
Note
For simple intersections with planes that do not intersect within the sphere, the vertices list can be left empty. When specified, the half-space intersection of the normals must match the convex polyhedron defined by the vertices (if non-empty), the half-space intersection is not calculated automatically.
- Type
TypeParameter[
particle type
, dict]
- class hoomd.hpmc.integrate.FacetedEllipsoidUnion(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Faceted ellispod union hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of unions of faceted ellipsoids. The union shape \(S\) is the set union of the given faceted ellipsoids:
\[S = \bigcup_k S_k(\mathbf{q}_k, \vec{r}_k)\]Each constituent shape in the union has its own shape parameters \(S_k\), position \(\vec{r}_k\), and orientation \(\mathbf{q}_k\) (see
shape
).Note
This shape uses an internal OBB tree for fast collision queries. Depending on the number of constituent faceted ellipsoids in the tree, different values of the number of faceted ellipsoids per leaf node may yield different performance. The capacity of leaf nodes is configurable.
Wall support.
FacetedEllipsoidUnion
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.FacetedEllipsoidUnion(default_d=0.3, default_a=0.4) # make a prolate Janus ellipsoid # cut away -x halfspace normals = [(-1,0,0)] offsets = [0] slab_normals = [(-1,0,0),(1,0,0),(0,-1,0),(0,1,0),(0,0,-1),(0,0,1)] slab_offsets = [-0.1,-1,-.5,-.5,-.5,-.5) # polyedron vertices slab_verts = [[-.1,-.5,-.5], [-.1,-.5,.5], [-.1,.5,.5], [-.1,.5,-.5], [1,-.5,-.5], [1,-.5,.5], [1,.5,.5], [1,.5,-.5]] faceted_ellipsoid1 = dict(normals=slab_normals, offsets=slab_offsets, vertices=slab_verts, a=1.0, b=0.5, c=0.5); faceted_ellipsoid2 = dict(normals=slab_normals, offsets=slab_offsets, vertices=slab_verts, a=0.5, b=1, c=1); mc.shape["A"] = dict(shapes=[faceted_ellipsoid1, faceted_ellipsoid2], positions=[(0, 0, 0), (0, 0, 1)], orientations=[(1, 0, 0, 0), (1, 0, 0, 0)], overlap=[1, 1]); print('offsets of the first faceted ellipsoid = ', mc.shape["A"]["shapes"][0]["offsets"]) print('normals of the first faceted ellipsoid = ', mc.shape["A"]["shapes"][0]["normals"]) print('vertices of the first faceted ellipsoid = ', mc.shape["A"]["shapes"][0]["vertices"]
- shape
The shape parameters for each particle type. The dictionary has the following keys:
shapes
(list
[dict
], required) - Shape parameters for each faceted ellipsoid in the union. SeeFacetedEllipsoid.shape
for the accepted parameters.positions
(list
[tuple
[float
,float
,float
]], required) - Position of each faceted ellipsoid in the union. \([\mathrm{length}]\)orientations
(list
[tuple
[float
,float
,float
,float
]], default:None
) - Orientation of each faceted ellipsoid in the union. When notNone
,orientations
must have a length equal to that ofpositions
. WhenNone
(the default),orientations
is initialized with all [1,0,0,0]’s.overlap
(list
[int
], default:None
) - Check for overlaps between constituent particles whenoverlap [i] & overlap[j]
is nonzero (&
is the bitwise AND operator). When notNone
,overlap
must have a length equal to that ofpositions
. WhenNone
(the default),overlap
is initialized with all 1’s.capacity
(int
, default: 4) - set the maximum number of particles per leaf node to adjust performance.ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.HPMCIntegrator(default_d, default_a, translation_move_probability, nselect)
Bases:
Integrator
Base class hard particle Monte Carlo integrator.
HPMCIntegrator
is the base class for all HPMC integrators. The attributes documented here are available to all HPMC integrators.See also
The module level documentation
hoomd.hpmc.integrate
describes the hard particle Monte Carlo algorithm.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.Ignoring overlap checks
Set elements of
interaction_matrix
toFalse
to disable overlap checks between specific pairs of particle types.Writing type_shapes to GSD files.
Use a Logger in combination with a HPMC integrator and a GSD writer to write
type_shapes
to the GSD file for use with OVITO. For example:mc = hoomd.hpmc.integrate.Sphere() log = hoomd.logging.Logger() log.add(mc, quantities=['type_shapes']) gsd = hoomd.write.GSD( 'trajectory.gsd', hoomd.trigger.Periodic(1000), log=log)
Threading
HPMC integrators use threaded execution on multiple CPU cores only when placing implicit depletants (
depletant_fugacity != 0
).Mixed precision
All HPMC integrators use reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.
Parameters
- a
Maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
- Type
TypeParameter
[particle type
,float
]
- d
Maximum size of displacement trial moves \([\mathrm{length}]\).
- Type
TypeParameter
[particle type
,float
]
- depletant_fugacity
Depletant fugacity \([\mathrm{volume}^{-1}]\) (default: 0)
Allows setting the fugacity per particle type, e.g.
'A'
refers to a depletant of type A.- Type
TypeParameter
[particle type
,float
]
- depletant_ntrial
Multiplicative factor for the number of times a depletant is inserted. This factor is accounted for in the acceptance criterion so that detailed balance is unchanged. Higher values of ntrial (than one) can be used to reduce the variance of the free energy estimate and improve the acceptance rate of the Markov chain.
- Type
TypeParameter
[particle type
,int
]
- interaction_matrix
Set to
False
for a pair of particle types to disable overlap checks between particles of those types (default:True
).- Type
TypeParameter
[tuple
[particle type
,particle type
],bool
]
Attributes
- __dir__()
Expose all attributes for dynamic querying in notebooks and IDEs.
- property counters
Trial move counters.
The counter object has the following attributes:
translate
:tuple
[int
,int
] - Number of accepted and rejected translate trial moves.rotate
:tuple
[int
,int
] - Number of accepted and rejected rotate trial moves.overlap_checks
:int
- Number of overlap checks performed.overlap_errors
:int
- Number of overlap checks that were too close to resolve.
Note
The counts are reset to 0 at the start of each
hoomd.Simulation.run
.- Type
- property external_potential
The user-defined potential energy field integrator.
Defines the external energy \(U_{\mathrm{external},i}\). Defaults to
None
. May be set to an object from hoomd.hpmc.external.
- property is_tuning_complete
Check if kernel parameter tuning is complete.
True
when tuning is complete andkernel_parameters
has locked optimal parameters for all active kernels used by this object.- Type
- property kernel_parameters
Kernel parameters.
The dictionary maps GPU kernel names to tuples of integers that control how the kernel executes on the GPU. These values will change during the tuning process and remain static after tuning completes. Set the kernel parameters for one or more kernels to force specific values and stop tuning.
Warning
The keys and valid values in this dictionary depend on the hardware device, the HOOMD-blue version, and the value of class attributes. Keys and/or valid values may change even with new patch releases of HOOMD-blue.
Provided that you use the same HOOMD-blue binary on the same hardware and execute a script with the same parameters, you may save the tuned values from one run and load them in the next.
- property map_overlaps
List of overlapping particles.
The list contains one entry for each overlapping pair of particles. When a tuple
(i,j)
is present in the list, there is an overlap between the particles with tagsi
andj
.Attention
map_overlaps
does not support MPI parallel simulations. It returnsNone
when there is more than one MPI rank.(
Loggable
: category=”sequence”)
- property mps
Number of trial moves performed per second.
Note
The count is reset at the start of each
hoomd.Simulation.run
.(
Loggable
: category=”scalar”)- Type
- property pair_potential
The user-defined pair potential.
Defines the pairwise particle interaction energy \(U_{\mathrm{pair},ij}\). Defaults to
None
. May be set to an object from hoomd.hpmc.pair.
- property rotate_moves
Count of the accepted and rejected rotate moves.
Note
The counts are reset to 0 at the start of each
hoomd.Simulation.run
.(
Loggable
: category=”sequence”)
- property translate_moves
Count of the accepted and rejected translate moves.
Note
The counts are reset to 0 at the start of each
hoomd.Simulation.run
.(
Loggable
: category=”sequence”)
- tune_kernel_parameters()
Start tuning kernel parameters.
After calling
tune_kernel_parameters
,AutotunedObject
will vary the kernel parameters in subsequent time steps, check the run time of each, and lock to the fastest performing parameters after the scan is complete.
- class hoomd.hpmc.integrate.Polyhedron(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Polyhedron hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of general polyhedra. The shape \(S\) contains the points inside the polyhedron defined by vertices and faces (see
shape
).Polyhedron
supports triangle meshes and spheres only. The mesh must be free of self-intersections.See also
Use
ConvexPolyhedron
for faster performance with convex polyhedra.Note
This shape uses an internal OBB tree for fast collision queries. Depending on the number of constituent faces in the tree, different values of the number of faces per leaf node may yield different optimal performance. The capacity of leaf nodes is configurable.
Wall support.
Polyhedron
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.Polyhedron(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(vertices=[(-0.5, -0.5, -0.5), (-0.5, -0.5, 0.5), (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5), (0.5, 0.5, -0.5), (0.5, 0.5, 0.5)], faces=[[0, 2, 6], [6, 4, 0], [5, 0, 4], [5, 1, 0], [5, 4, 6], [5, 6, 7], [3, 2, 0], [3, 0, 1], [3, 6, 2], [3, 7, 6], [3, 1, 5], [3, 5, 7]]) print('vertices = ', mc.shape["A"]["vertices"]) print('faces = ', mc.shape["A"]["faces"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
vertices
(list
[tuple
[float
,float
,float
]], required) - vertices of the polyhedron \([\mathrm{length}]\).The origin MUST strictly be contained in the generally nonconvex volume defined by the vertices and faces.
The origin centered sphere that encloses all vertices should be of minimal size for optimal performance.
faces
(list
[tuple
[int
,int
,int
], required) - Vertex indices for every triangle in the mesh.For visualization purposes, the faces MUST be defined with a counterclockwise winding order to produce an outward normal.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - radius of the sphere swept around the surface of the polyhedron \([\mathrm{length}]\). Set a non-zero sweep_radius to create a spheropolyhedron.overlap
(list
[int
], default: None) - Check for overlaps between faces whenoverlap [i] & overlap[j]
is nonzero (&
is the bitwise AND operator). When notNone
,overlap
must have a length equal to that offaces
. WhenNone
(the default),overlap
is initialized with all 1’s.capacity
(int
, default: 4) - set the maximum number of particles per leaf node to adjust performance.origin
(tuple
[float
,float
,float
], default: (0,0,0)) - a point strictly inside the shape, needed for correctness of overlap checks.hull_only
(bool
, default:False
) - WhenTrue
, only check for intersections between the convex hulls.
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.SimplePolygon(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Simple polygon hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of simple polygons. The shape \(S\) of a simple polygon includes the points inside and on the surface of the simple polygon defined by the vertices (see
shape
). For example:Important
SimplePolygon
simulations must be performed in 2D systems.See also
Use
ConvexPolygon
for faster performance with convex polygons.Wall support.
SimplePolygon
supports nohoomd.wall
geometries.Examples:
mc = hpmc.integrate.SimplePolygon(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(vertices=[(0, 0.5), (-0.5, -0.5), (0, 0), (0.5, -0.5)]); print('vertices = ', mc.shape["A"]["vertices"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
vertices
(list
[tuple
[float
,float
]], required) - vertices of the polygon \([\mathrm{length}]\).Vertices MUST be specified in a counter-clockwise order.
The polygon may be concave, but edges must not cross.
The origin may be inside or outside the shape.
The origin centered circle that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - Ignored, but present becauseSimplePolygon
shares data structures withConvexSpheropolygon
\([\mathrm{length}]\).
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.Sphere(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Sphere hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of spheres. The shape \(S\) includes all points inside and on the surface of a sphere:
\[S = \left \{ \vec{r} : \frac{\vec{r}\cdot\vec{r}}{(d/2)^2} \le 1 \right\}\]where \(d\), is the diameter set in
shape
. When the shape parameterorientable
isFalse
(the default),Sphere
only applies translation trial moves and ignorestranslation_move_probability
.Tip
Use spheres with
diameter=0
in conjunction with pair potentials for Monte Carlo simulations of particles with no hard core.Tip
Use
Sphere
in a 2D simulation to perform Monte Carlo on hard disks.Wall support.
Sphere
supports allhoomd.wall
geometries.Examples:
mc = hoomd.hpmc.integrate.Sphere(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(diameter=1.0) mc.shape["B"] = dict(diameter=2.0) mc.shape["C"] = dict(diameter=1.0, orientable=True) print('diameter = ', mc.shape["A"]["diameter"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
diameter
(float
, required) - Sphere diameter \([\mathrm{length}]\).ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.orientable
(bool
, default:False
) - set toTrue
to allow rotation moves on this particle type.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.integrate.SphereUnion(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Sphere union hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of unions of spheres. The union shape \(S\) is the set union of the given spheres:
\[S = \bigcup_k S_k(\mathbf{q}_k, \vec{r}_k)\]Each constituent shape in the union has its own shape parameters \(S_k\), position \(\vec{r}_k\), and orientation \(\mathbf{q}_k\) (see
shape
).Note
This shape uses an internal OBB tree for fast collision queries. Depending on the number of constituent spheres in the tree, different values of the number of spheres per leaf node may yield different performance. The capacity of leaf nodes is configurable.
Wall support.
SphereUnion
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.SphereUnion(default_d=0.3, default_a=0.4) sphere1 = dict(diameter=1) sphere2 = dict(diameter=2) mc.shape["A"] = dict(shapes=[sphere1, sphere2], positions=[(0, 0, 0), (0, 0, 1)], orientations=[(1, 0, 0, 0), (1, 0, 0, 0)], overlap=[1, 1]) print('diameter of the first sphere = ', mc.shape["A"]["shapes"][0]["diameter"]) print('center of the first sphere = ', mc.shape["A"]["positions"][0])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
shapes
(list
[dict
], required) - Shape parameters for each sphere in the union. SeeSphere.shape
for the accepted parameters.positions
(list
[tuple
[float
,float
,float
]], required) - Position of each sphere in the union. \([\mathrm{length}]\)orientations
(list
[tuple
[float
,float
,float
,float
]], default:None
) - Orientation of each sphere in the union. When notNone
,orientations
must have a length equal to that ofpositions
. WhenNone
(the default),orientations
is initialized with all [1,0,0,0]’s.overlap
(list
[int
], default:None
) - Check for overlaps between constituent particles whenoverlap [i] & overlap[j]
is nonzero (&
is the bitwise AND operator). When notNone
,overlap
must have a length equal to that ofpositions
. WhenNone
(the default),overlap
is initialized with all 1’s.capacity
(int
, default: 4) - set the maximum number of particles per leaf node to adjust performance.ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
- Type
TypeParameter
[particle type
,dict
]
- property type_shapes
Description of shapes in
type_shapes
format.Examples
The type will be ‘SphereUnion’ regardless of dimensionality.
>>> mc.type_shapes [{'type': 'SphereUnion', 'centers': [[0, 0, 0], [0, 0, 1]], 'diameters': [1, 0.5]}, {'type': 'SphereUnion', 'centers': [[1, 2, 3], [4, 5, 6]], 'diameters': [0.5, 1]}]
(
Loggable
: category=”object”)
- class hoomd.hpmc.integrate.Sphinx(default_d=0.1, default_a=0.1, translation_move_probability=0.5, nselect=4)
Bases:
HPMCIntegrator
Sphinx hard particle Monte Carlo integrator.
- Parameters
default_d (float) – Default maximum size of displacement trial moves \([\mathrm{length}]\).
default_a (float) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\).
translation_move_probability (float) – Fraction of moves that are translation moves.
nselect (int) – Number of trial moves to perform per particle per timestep.
Perform hard particle Monte Carlo of sphere unions and differences, depending on the sign of the diameter. The shape \(S\) is:
\[S = \left(\bigcup_{k,d_k\ge 0} S_k((1, 0, 0, 0), \vec{r}_k) \right) \setminus \left(\bigcup_{k,d_k < 0} S_k((1, 0, 0, 0), \vec{r}_k) \right)\]Where \(d_k\) is the diameter given in
shape
, \(\vec{r}_k\) is the center given inshape
and \(S_k\) is the set of points in a sphere or diameter \(|d_k|\).Wall support.
Sphinx
supports nohoomd.wall
geometries.Example:
mc = hpmc.integrate.Sphinx(default_d=0.3, default_a=0.4) mc.shape["A"] = dict(centers=[(0,0,0),(1,0,0)], diameters=[1,.25]) print('diameters = ', mc.shape["A"]["diameters"])
- shape
The shape parameters for each particle type. The dictionary has the following keys:
diameters
(list
[float
], required) - diameters of spheres (positive OR negative real numbers) \([\mathrm{length}]\).centers
(list
[tuple
[float
,float
,float
], required) - centers of spheres in local coordinate frame \([\mathrm{length}]\).ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.
- Type
TypeParameter
[particle type
,dict
]
hoomd.hpmc.nec
Newtonian event chain Monte Carlo.
The integrators in hoomd.hpmc.nec
implement Newtonian event chain Monte Carlo
as described in Klement 2021.
Newtonian event chain Monte Carlo combines rejection free particle chain translation moves with traditional local rotation trial moves to explore phase space. This combination can lead to more efficient simulations. See the paper for a full description of the method.
A chain move is rejection free and changes the positions of many particles, but
does not change their orientations. Mix one chain move with many rotation moves
to effectively explore phase space. The author suggests setting
chain_probability
to a low value, such as 0.1. As with traditional HPMC,
tune the maximum rotation move size a
to achieve a target acceptance ratio,
such as 20%.
Important
Chain moves translate particles along their velocity vectors. You must set a non-zero velocity for every particle in the simulation state to use NEC. For example, start with a thermal distribution using:
sim.state.thermalize_particle_momenta(hoomd.filter.All(), kT=1)
The chain_time
parameter determines the total length of each chain move.
Like the d
parameter in HPMC with local trial moves, the value of
chain_time
greatly impacts the rate at which the simulation explores phase
space. See Klement 2021 for a
full description on how to choose chain_time
optimally. As a starting point,
use hoomd.hpmc.nec.tune.ChainTime
to attain an average of 20 particles per
chain move.
The NEC method uses the d
parameter as a search radius for collisions and
updates the translation move acceptance counter when it finds a collision
within the distance d
. Changing d
will not change the chain moves NEC
makes, but it will adjust the wall time needed to complete the moves. Set d
too high and performance will slow due to many narrow phase collisions checks.
See d
too low and performance will slow due to many broad phase collision
checks. Adjust d
to obtain optimal performance. The code author suggests
tuning d
to an “acceptance ratio” of 10% as a starting point.
See also
Modules
hoomd.hpmc.nec.integrate
Overview
HPMC integration for convex polyhedra (3D) with nec. |
|
HPMC Chain Integrator base class. |
|
HPMC chain integration for spheres (2D/3D). |
Details
Newtonain Event-Chain Integrators for Hard Particle Monte Carlo.
- class hoomd.hpmc.nec.integrate.ConvexPolyhedron(default_d=0.1, default_a=0.1, chain_probability=0.5, chain_time=0.5, update_fraction=0.5, nselect=1)
Bases:
HPMCNECIntegrator
HPMC integration for convex polyhedra (3D) with nec.
- Parameters
default_d (
float
, optional) – Default colission search distance \([\mathrm{length}]\), defaults to 0.1.default_a (
float
, optional) – Default maximum size of rotation trial moves \([\mathrm{dimensionless}]\), defaults to 0.1.chain_probability (
float
, optional) – Probability of making a chain move instead of a rotation move, defaults to 0.5.chain_time (
float
, optional) – Length of a chain \([\mathrm{time}]\), defaults to 0.5.update_fraction (
float
, optional) – Number of chains to be done as fraction of N, defaults to 0.5.nselect (
int
, optional) – Number of repeated updates for the cell/system, defaults to 1.
Perform Newtonian event chain Monte Carlo integration of convex polyhedra.
Wall support.
ConvexPolyhedron
supports nohoomd.wall
geometries.Potential support.
ConvexPolyhedron
does not supportpair_potential
orexternal_potential
.Attention
ConvexPolyhedron
does not support execution on GPUs.Attention
ConvexPolyhedron
does not support MPI parallel simulations.Example:
mc = hoomd.hpmc.nec.integrate.ConvexPolyhedron(d=1.0, a=0.05, chain_probability=0.1, nselect=10) mc.shape['A'] = dict(vertices=[[1,1,1], [1,1,-1], [1,-1,1], [1,-1,-1], [-1,1,1], [-1,1,-1], [-1,-1,1], [-1,-1,-1]])
- shape
The shape parameters for each particle type. The dictionary has the following keys.
vertices
(list
[tuple
[float
,float
,float
]], required) - vertices of the polyhedron \([\mathrm{length}]\).The origin MUST be contained within the polyhedron.
The origin centered sphere that encloses all vertices should be of minimal size for optimal performance.
ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.sweep_radius
(float
, default: 0.0) - Ignored, but present becauseConvexPolyhedron
shares data structures withConvexSpheropolyhedron
\([\mathrm{length}]\).
Warning
HPMC does not check that all vertex requirements are met. Undefined behavior will result when they are violated.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.nec.integrate.HPMCNECIntegrator(default_d=0.1, default_a=0.1, chain_probability=0.5, chain_time=0.5, update_fraction=0.5, nselect=1)
Bases:
HPMCIntegrator
HPMC Chain Integrator base class.
HPMCNECIntegrator
is the base class for all HPMC Newtonian event chain integrators. The attributes documented here are available to all HPMC integrators.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- property chains_in_space
rate of chain events that did neither collide nor end.
Note
The statistics are reset at every
hoomd.Simulation.run
.(
Loggable
: category=”scalar”)- Type
- property nec_counters
Trial move counters.
The counter object has the following attributes:
chain_start_count
:int
Number of chainschain_at_collision_count
:int
Number of collisionschain_no_collision_count
:int
Number of chain events that are no collision (i.e. no collision partner found or end of chain)distance_queries
:int
Number of sweep distances calculatedoverlap_errors
:int
Number of errors during sweep calculations
Note
The counts are reset to 0 at the start of each
hoomd.Simulation.run
.
- property particles_per_chain
particles per chain.
Note
The statistics are reset at every
hoomd.Simulation.run
.(
Loggable
: category=”scalar”)- Type
- class hoomd.hpmc.nec.integrate.Sphere(default_d=0.1, chain_time=0.5, update_fraction=0.5, nselect=1)
Bases:
HPMCNECIntegrator
HPMC chain integration for spheres (2D/3D).
- Parameters
default_d (
float
, optional) – Default colission search distance \([\mathrm{length}]\), defaults to 0.1.chain_time (
float
, optional) – Length of a chain \([\mathrm{time}]\), defaults to 0.5.update_fraction (
float
, optional) – Number of chains to be done as fraction of N, defaults to 0.5.nselect (
int
, optional) – The number of repeated updates to perform in each cell, defaults to 1.
Perform Newtonian event chain Monte Carlo integration of spheres.
Wall support.
Sphere
supports nohoomd.wall
geometries.Potential support.
Sphere
does not supportpair_potential
orexternal_potential
.Attention
Sphere
does not support execution on GPUs.Attention
Sphere
does not support MPI parallel simulations.Example:
mc = hoomd.hpmc.integrate.nec.Sphere(d=0.05, update_fraction=0.05) mc.chain_time = 0.05
- shape
The shape parameters for each particle type. The dictionary has the following keys:
diameter
(float
, required) - Sphere diameter \([\mathrm{length}]\).ignore_statistics
(bool
, default:False
) - set toTrue
to ignore tracked statistics.orientable
(bool
, default:False
) - set toTrue
to allow rotation moves on this particle type.
- Type
TypeParameter
[particle type
,dict
]
hoomd.hpmc.nec.tune
Overview
Tunes HPMCNECIntegrator chain time to targeted mean particles per chain. |
Details
Tune Newtonian event chain parameters.
- class hoomd.hpmc.nec.tune.ChainTime(trigger, *args, **kwargs)
Tunes HPMCNECIntegrator chain time to targeted mean particles per chain.
Tip
For the most common creation of a
ChainTime
tuner seeChainTime.secant_solver
andChainTime.scale_solver
respectively.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
solver (
hoomd.tune.RootSolver
) – A solver that tunes chain times to reach the specified target.max_chain_time (float) – The maximum value of chain time to attempt.
- trigger
Trigger
to determine when to run the tuner.
- target
The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
- Type
- solver
A solver that tunes move sizes to reach the specified target.
- classmethod scale_solver(trigger, target, max_chain_time=None, max_scale=2.0, gamma=1.0, tol=0.01)
Create a
ChainTime
tuner with ahoomd.tune.ScaleSolver
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.target (float) – The number of collisions in a chain that is desired.
max_chain_time (float) – The maximum value of chain time to attempt.
max_scale (float) – The maximum amount to scale the current chain_time value with.
gamma (float) – The value of gamma to pass through to
hoomd.tune.ScaleSolver
. Controls the size of corrections to the move size (larger values increase stability while increasing convergence time).tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
- classmethod secant_solver(trigger, target, max_chain_time=None, gamma=0.8, tol=0.01)
Create a
ChainTime
tuner with ahoomd.tune.SecantSolver
.This solver can be faster than
hoomd.tune.ScaleSolver
, but depending on the system slightly less stable. In general, with the default value of gamma this should not be a problem.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.target (float) – The number of collisions in a chain that is desired.
max_chain_time (float) – The maximum value of chain time to attempt, defaults to
None
which represents no maximum chain time.gamma (float) – The value of gamma to pass through to
hoomd.tune.SecantSolver
. Controls the size of corrections to the move size (smaller values increase stability). Should be between 0 and 1, defaults to 0.8.tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
Note
Increasing
gamma
towards 1 does not necessarily speed up convergence and can slow it done. In addition, large values ofgamma
can make the solver unstable especially when tuning frequently.
hoomd.hpmc.tune
Overview
Tunes |
|
Tunes HPMCIntegrator move sizes to targeted acceptance rate. |
Details
Tuners for HPMC.
- class hoomd.hpmc.tune.BoxMCMoveSize(trigger, *args, **kwargs)
Tunes
BoxMC
move sizes to targeted acceptance rate.Tip
For most common creation of a
BoxMCMoveSize
tuner seeBoxMCMoveSize.secant_solver
andBoxMCMoveSize.scale_solver
respectively.The tuner will continue tuning despite being
tuned
. Thus, if simulation conditions change the move sizes will continue to change and the tuner will no longer betuned
. The changes to the move size are completely controlled by the givenhoomd.tune.RootSolver
instance. See the doumentation athoomd.tune
for more information.Warning
The tuner should be removed from the simulation once tuned to prevent invalid results due to the breaking of balance.
- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.boxmc (hoomd.hpmc.update.BoxMC) – The
hoomd.hpmc.update.BoxMC
object to tune.moves (list[str]) – A list of types of moves to tune. Available options are ‘volume’, ‘aspect’, ‘shear_{x,y,z}’, and ‘length_{x,y,z}’ where brackets denote multiple options. For shear and length moves each dimension is tuned independently.
target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
solver (
hoomd.tune.RootSolver
) – A solver that tunes move sizes to reach the specified target.max_move_size (
dict
[str
,float
], optional) – The maximum volume move size to attempt for each move time. See the available moves in themoves
attribute documentation. Defaults to no maximumNone
for each move type.
- trigger
Trigger
to determine when to run the tuner.
- boxmc
The
hoomd.hpmc.update.BoxMC
object to tune.
- moves
A list of types of moves to tune. Available options are ‘volume’, ‘aspect’, ‘shear_{x,y,z}’, and ‘length_{x,y,z}’ where brackets denote multiple options. For shear and length moves each dimension is tuned independently.
- target
The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
- Type
- solver
A solver that tunes move sizes to reach the specified target.
- max_move_size
The maximum volume move size to attempt for each move time. See the available moves in the
moves
attribute documentation.- Type
Warning
Over-limiting the maximum move sizes can lead to the inability to converge to the desired acceptance rate.
Warning
Since each dimension of length and shear moves are tuned independently but the acceptance statistics are collected collectively, the reachable target acceptance rates is limited by the other dimensions.
- classmethod scale_solver(trigger, boxmc, moves, target, max_move_size=None, max_scale=2.0, gamma=1.0, tol=0.01)
Create a
BoxMCMoveSize
tuner with ahoomd.tune.ScaleSolver
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.boxmc (hoomd.hpmc.update.BoxMC) – The
hoomd.hpmc.update.BoxMC
object to tune.moves (list[str]) – A list of types of moves to tune. Available options are ‘volume’, ‘aspect’, ‘shear_{x,y,z}’, and ‘length_{x,y,z}’ where brackets denote multiple options. For shear and length moves each dimension is tuned independently.
target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
max_move_size (float) – The maximum value of a volume move size to attempt.
max_scale (float) – Maximum scale factor.
gamma (float) – The value of gamma to pass through to
hoomd.tune.ScaleSolver
. Controls the size of corrections to the move size (larger values increase stability while increasing convergence time).tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
- classmethod secant_solver(trigger, boxmc, moves, target, max_move_size=None, gamma=0.8, tol=0.01)
Create a
BoxMCMoveSize
tuner with ahoomd.tune.SecantSolver
.This solver can be faster than
hoomd.tune.ScaleSolver
, but depending on the system slightly less stable. In general, with the default value of gamma this should not be a problem.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.boxmc (hoomd.hpmc.update.BoxMC) – The
hoomd.hpmc.update.BoxMC
object to tune.moves (list[str]) – A list of types of moves to tune. Available options are ‘volume’, ‘aspect’, ‘shear_{x,y,z}’, and ‘length_{x,y,z}’ where brackets denote multiple options. For shear and length moves each dimension is tuned independently.
target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
max_move_size (float) – The maximum value of a volume move size to attempt, defaults to
None
which represents no maximum move size.gamma (float) – The value of gamma to pass through to
hoomd.tune.SecantSolver
. Controls the size of corrections to the move size (smaller values increase stability). Should be between 0 and 1, defaults to 0.8.tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
Note
Increasing
gamma
towards 1 does not necessarily speed up convergence and can slow it done. In addition, large values ofgamma
can make the solver unstable especially when tuning frequently.
- class hoomd.hpmc.tune.MoveSize(trigger, *args, **kwargs)
Tunes HPMCIntegrator move sizes to targeted acceptance rate.
Tip
Direct instantiation of this class requires a
hoomd.tune.RootSolver
that determines how move sizes are updated. This class also provides class methods to create aMoveSize
tuner with built-in solvers; seeMoveSize.secant_solver
andMoveSize.scale_solver
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.moves (list[str]) – A list of types of moves to tune. Available options are
'a'
and'd'
.target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
solver (
hoomd.tune.RootSolver
) – A solver that tunes move sizes to reach the specified target.types (list[str]) – A list of string particle types to tune the move size for, defaults to None which upon attaching will tune all types in the system currently.
max_translation_move (float) – The maximum value of a translational move size to attempt \([\mathrm{length}]\).
max_rotation_move (float) – The maximum value of a rotational move size to attempt.
- trigger
Trigger
to determine when to run the tuner.
- target
The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
- Type
- solver
A solver that tunes move sizes to reach the specified target.
- types
A list of string particle types to tune the move size for, defaults to None which upon attaching will tune all types in the system currently.
- max_translation_move
The maximum value of a translational move size to attempt \([\mathrm{length}]\).
- Type
Note
Limiting the maximum move sizes can lead to the inability to converge to the desired acceptance rate. Also, not limiting the move size can lead to move sizes that require the use of multiple periodic images to check for overlaps, especially in low density systems since the acceptance rate tends towards 1. Therefore, it is recommended to pick a moderate maximum move size for at least the translational moves to prevent requiring checking periodic images.
Note
In systems containing disparate particle shapes and/or sizes, move sizes for the different types should be tuned independently so that the acceptances rates for the different particles are each near the target acceptance ratio. Otherwise, the global acceptance ratio, a weighted average of the acceptance ratios for each individual particle type, will approach the target value, while the per-type acceptance ratios may not be close to the target value. This requires setting the
types
attribute to be one type at a time while setting theignore_statistics
flag of the shape property of the HPMC integrator for all other types toTrue
.- classmethod scale_solver(trigger, moves, target, types=None, max_translation_move=None, max_rotation_move=None, max_scale=2.0, gamma=1.0, tol=0.01)
Create a
MoveSize
tuner with ahoomd.tune.ScaleSolver
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.moves (list[str]) – A list of types of moves to tune. Available options are
'a'
and'd'
.target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
types (list[str]) – A list of string particle types to tune the move size for, defaults to None which upon attaching will tune all types in the system currently.
max_translation_move (float) – The maximum value of a translational move size to attempt \([\mathrm{length}]\).
max_rotation_move (float) – The maximum value of a rotational move size to attempt.
max_scale (float) – Maximum scale factor.
gamma (float) – The value of gamma to pass through to
hoomd.tune.ScaleSolver
. Controls the size of corrections to the move size (larger values increase stability while increasing convergence time).tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
- classmethod secant_solver(trigger, moves, target, types=None, max_translation_move=None, max_rotation_move=None, gamma=0.8, tol=0.01)
Create a
MoveSize
tuner with ahoomd.tune.SecantSolver
.This solver can be faster than
hoomd.tune.ScaleSolver
, but depending on the system slightly less stable. In general, with the default value of gamma this should not be a problem.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.moves (list[str]) – A list of types of moves to tune. Available options are
'a'
and'd'
.target (float) – The acceptance rate for trial moves that is desired. The value should be between 0 and 1.
types (list[str]) – A list of string particle types to tune the move size for, defaults to None which upon attaching will tune all types in the system currently.
max_translation_move (float) – The maximum value of a translational move size to attempt, defaults to
None
which represents no maximum move size \([\mathrm{length}]\).max_rotation_move (float) – The maximum value of a rotational move size to attempt, defaults to
None
which represents no maximum move size.gamma (float) – The value of gamma to pass through to
hoomd.tune.SecantSolver
. Controls the size of corrections to the move size (smaller values increase stability). Should be between 0 and 1, defaults to 0.8.tol (float) – The absolute tolerance to allow between the current acceptance rate and the target before the move sizes are considered tuned. The tolerance should not be too much lower than the default of 0.01 as acceptance rates can vary significantly at typical tuning rates.
Note
Increasing
gamma
towards 1 does not necessarily speed up convergence and can slow it down. In addition, large values ofgamma
can make the solver unstable, especially when tuning frequently.
hoomd.hpmc.update
Overview
Apply box updates to sample isobaric and related ensembles. |
|
Apply geometric cluster algorithm (GCA) moves. |
|
Insert and remove particles in the muVT ensemble. |
|
Quickly compress a hard particle system to a target box. |
|
Apply shape updates to the shape definitions defined in the integrator. |
Details
HPMC updaters.
HPMC updaters work with the hpmc.integrate.HPMCIntegrator
to apply changes to
the system consistent with the particle shape and defined interaction energies.
The BoxMC
, Clusters
, and MuVT
updaters apply trial moves that enable
enhanced sampling or the equilibration of different ensembles. QuickCompress
helps prepare non-overlapping configurations of particles in a given box shape.
- class hoomd.hpmc.update.BoxMC(trigger, betaP)
Bases:
Updater
Apply box updates to sample isobaric and related ensembles.
- Parameters
betaP (hoomd.variant.variant_like) – \(\frac{p}{k_{\mathrm{B}}T}\) \([\mathrm{length}^{-2}]\) in 2D or \([\mathrm{length}^{-3}]\) in 3D.
trigger (hoomd.trigger.trigger_like) – Select the timesteps to perform box trial moves.
Use
BoxMC
in conjunction with an HPMC integrator to allow the simulation box to undergo random fluctuations at constant pressure, or random deformations at constant volume.BoxMC
supports both isotropic and anisotropic volume change moves as well as shearing of the simulation box. A singleBoxMC
instance may apply multiple types of box moves during a simulation run.Box move types
By default, no moves are applied (the weight values for all move types default to 0). In a given timestep, the type of move is selected randomly with probability:
\[p = \frac{w_k}{\sum_k w_k}\]where \(w_k\) is the weight of the move type.
A given box move proposes a trial simulation box \((L_x^t, L_y^t, L_z^t, xy^t, xz^t, yz^t)\) as a change from the current box: \((L_x, L_y, L_z, xy, xz, yz)\). The form of the change depends on the selected move type:
volume
(mode='standard'
): Change the volume (or area in 2D) of the simulation box while maining fixed aspect ratios \(Lx/Ly\), \(Lx/Lz\). In 3D:\[\begin{split}V^t &= V + u \\ L_x^t &= \left( \frac{Lx}{Ly} \frac{Lx}{Lz} V^t \right)^{1/3} \\ L_y^t &= L_x^t \frac{Ly}{Lx} \\ L_z^t &= L_x^t \frac{Lz}{Lx} \\ xy^t &= xy \\ xz^t &= xz \\ yz^t &= yz \\\end{split}\]where \(u\) is a random value uniformly distributed in the interval \([-\delta_\mathrm{volume}, \delta_\mathrm{volume}]\).
In 2D:
\[\begin{split}V^t &= V + u \\ L_x^t &= \left( \frac{Lx}{Ly} V^t \right)^{1/2} \\ L_y^t &= L_x^t \frac{Ly}{Lx} \\ xy^t &= xy \\\end{split}\]volume
(mode='ln'
): Change the volume (or area in 2D) of the simulation box while maining fixed aspect ratios \(Lx/Ly\), \(Lx/Lz\). In 3D:\[\begin{split}V^t &= V e^u \\ L_x^t &= \left( \frac{Lx}{Ly} \frac{Lx}{Lz} V^t \right)^{1/3} \\ L_y^t &= L_x^t \frac{Ly}{Lx} \\ L_z^t &= L_x^t \frac{Lz}{Lx} \\ xy^t &= xy \\ xz^t &= xz \\ yz^t &= yz \\\end{split}\]where \(u\) is a random value uniformly distributed in the interval \([-\delta_\mathrm{volume}, \delta_\mathrm{volume}]\).
In 2D:
\[\begin{split}V^t &= V e^u \\ L_x^t &= \left( \frac{Lx}{Ly} V^t \right)^{1/2} \\ L_y^t &= L_x^t \frac{Ly}{Lx} \\ xy^t &= xy \\\end{split}\]aspect
: Change the aspect ratio of the simulation box while maintaining a fixed volume. In 3D:\[\begin{split}L_k^t & = \begin{cases} L_k(1 + a) & u < 0.5 \\ L_k \frac{1}{1+a} & u \ge 0.5 \end{cases} \\ L_{m \ne k}^t & = L_m \sqrt{\frac{L_k}{L_k^t}} & xy^t &= xy \\ xz^t &= xz \\ yz^t &= yz \\\end{split}\]where \(u\) is a random value uniformly distributed in the interval \([0, 1]\), \(a\) is a random value uniformly distributed in the interval \([0, \delta_\mathrm{aspect}]\) and \(k\) is randomly chosen uniformly from the set \(\{x, y, z\}\).
In 2D:
\[\begin{split}L_k^t & = \begin{cases} L_k(1 + a) & u < 0.5 \\ L_k \frac{1}{1+a} & u \ge 0.5 \end{cases} \\ L_{m \ne k}^t & = L_m \frac{L_k}{L_k^t} \\ xy^t &= xy \\\end{split}\]length
: Change the box lengths:\[L_k^t = L_k + u\]where \(u\) is a random value uniformly distributed in the interval \([-\delta_{\mathrm{length},k}, -\delta_{\mathrm{length},k}]\), and \(k\) is randomly chosen uniformly from the set \(\{a : a \in \{x, y, z\}, \delta_{\mathrm{length},a} \ne 0 \}\).
shear
: Change the box shear parameters. In 3D:\[\begin{split}(xy^t, xz^t, yz^t) = \begin{cases} \left(xy + s_{xy}, \enspace xz, \enspace yz \right) & u < \frac{1}{3} \\ \left( xy^t = xy, \enspace xz + s_{xz}, \enspace yz \right) & \frac{1}{3} \le u < \frac{2}{3} \\ \left( xy^t = xy, \enspace xz, \enspace yz + s_{yz} \right) & \frac{2}{3} \le u \le 1 \\ \end{cases} \\\end{split}\]where \(u\) is a random value uniformly distributed in the interval \([0, 1]\) and \(s_k\) is a random value uniformly distributed in the interval \([-\delta_{\mathrm{shear},k}, \delta_{\mathrm{shear},k}]\).
BoxMC
attempts and records trial moves for shear parameters even when \(\delta_{\mathrm{shear},k}=0\).In 2D:
\[xy^t = xy + s_{xy}\]
Acceptance
All particle particle positions are scaled into the trial box to form the trial configuration \(C^t\):
\[\vec{r}_i^t = s_x \vec{a}_1^t + s_y \vec{a}_2^t + s_z \vec{a}_3^t - \frac{\vec{a}_1^t + \vec{a}_2^t + \vec{a}_3^t}{2}\]where \(\vec{a}_k^t\) are the new box vectors determined by \((L_x^t, L_y^t, L_z^t, xy^t, xz^t, yz^t)\) and the scale factors are determined by the current particle position \(\vec{r}_i\) and the box vectors \(\vec{a}_k\):
\[\vec{r}_i = s_x \vec{a}_1 + s_y \vec{a}_2 + s_z \vec{a}_3 - \frac{\vec{a}_1 + \vec{a}_2 + \vec{a}_3}{2}\]The trial move is accepted with the probability:
\[\begin{split}p_\mathrm{accept} = \begin{cases} \exp(-(\beta \Delta H + \beta \Delta U)) & \beta \Delta H + \beta \Delta U > 0 \\ 1 & \beta \Delta H + \beta \Delta U \le 0 \\ \end{cases}\end{split}\]where \(\Delta U = U^t - U\) is the difference in potential energy, \(\beta \Delta H = \beta P (V^t - V) - N_\mathrm{particles} \cdot \ln(V^t / V)\) for most move types. It is \(\beta P (V^t - V) - (N_\mathrm{particles}+1) \cdot \ln(V^t / V)\) for ln volume moves.
When the trial move is accepted, the system state is set to the the trial configuration. When it is not accepted, the move is rejected and the state is not modified.
Mixed precision
BoxMC
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.- volume
Parameters for isobaric volume moves that scale the box lengths uniformly. The dictionary has the following keys:
weight
(float) - Relative weight of volume box moves.mode
(str) -standard
proposes changes to the box volume andln
proposes changes to the logarithm of the volume. Initially starts off in ‘standard’ mode.delta
(float) - Maximum change in V or ln(V) where V is box area (2D) or volume (3D) \(\delta_\mathrm{volume}\).
- Type
- aspect
Parameters for isovolume aspect ratio moves. The dictionary has the following keys:
weight
(float) - Relative weight of aspect box moves.delta
(float) - Maximum relative change of box aspect ratio \(\delta_\mathrm{aspect} [\mathrm{dimensionless}]\).
- Type
- length
Parameters for isobaric box length moves that change box lengths independently. The dictionary has the following keys:
weight
(float) - Maximum change of HOOMD-blue box parameters Lx, Ly, and Lz.delta
(tuple[float, float, float]) - Maximum change of the box lengths \((\delta_{\mathrm{length},x}, \delta_{\mathrm{length},y}, \delta_{\mathrm{length},z}) [\mathrm{length}]\).
- Type
- shear
Parameters for isovolume box shear moves. The dictionary has the following keys:
weight
(float) - Relative weight of shear box moves.delta
(tuple[float, float, float]) - maximum change of the box tilt factor \((\delta_{\mathrm{shear},xy}, \delta_{\mathrm{shear},xz}, \delta_{\mathrm{shear},yz}) [\mathrm{dimensionless}]\).reduce
(float) - Maximum number of lattice vectors of shear to allow before applying lattice reduction. Values less than 0.5 disable shear reduction.
- Type
- instance
When using multiple
BoxMC
updaters in a single simulation, give each a unique value forinstance
so they generate different streams of random numbers.- Type
- property aspect_moves
The accepted and rejected aspect moves.
(0, 0) before the first call to
Simulation.run
.(
Loggable
: category=”sequence”)
- property counter
Trial move counters.
The counter object has the following attributes:
volume
:tuple
[int
,int
] - Number of accepted and rejected volume and length moves.shear
:tuple
[int
,int
] - Number of accepted and rejected shear moves.aspect
:tuple
[int
,int
] - Number of accepted and rejected aspect moves.
Note
The counts are reset to 0 at the start of each call to
hoomd.Simulation.run
. Before the first call toSimulation.run
,counter
isNone
.
- property shear_moves
The accepted and rejected shear moves.
(0, 0) before the first call to
Simulation.run
.(
Loggable
: category=”sequence”)
- class hoomd.hpmc.update.Clusters(pivot_move_probability=0.5, flip_probability=0.5, trigger=1)
Bases:
Updater
Apply geometric cluster algorithm (GCA) moves.
- Parameters
pivot_move_probability (float) – Set the probability for attempting a pivot move.
flip_probability (float) – Set the probability for transforming an individual cluster.
trigger (hoomd.trigger.trigger_like) – Select the timesteps on which to perform cluster moves.
The GCA as described in Liu and Lujten (2004), http://doi.org/10.1103/PhysRevLett.92.035504 is used for hard shape, patch interactions and depletants. Implicit depletants are supported and simulated on-the-fly, as if they were present in the actual system.
Supported moves include pivot moves (point reflection) and line reflections (pi rotation around an axis). With anisotropic particles, the pivot move cannot be used because it would create a chiral mirror image of the particle, and only line reflections are employed. In general, line reflections are not rejection free because of periodic boundary conditions, as discussed in Sinkovits et al. (2012), http://doi.org/10.1063/1.3694271 . However, we restrict the line reflections to axes parallel to the box axis, which makes those moves rejection-free for anisotropic particles, but the algorithm is then no longer ergodic for those and needs to be combined with local moves.
Mixed precision
Clusters
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.
- class hoomd.hpmc.update.MuVT(transfer_types, ngibbs=1, max_volume_rescale=0.1, volume_move_probability=0.5, trigger=1)
Bases:
Updater
Insert and remove particles in the muVT ensemble.
- Parameters
trigger (int) – Number of timesteps between grand canonical insertions
transfer_types (list) – List of type names that are being transferred from/to the reservoir or between boxes
ngibbs (int) – The number of partitions to use in Gibbs ensemble simulations (if == 1, perform grand canonical muVT)
max_volume_rescale (float) – maximum step size in ln(V) (applies to Gibbs ensemble)
move_ratio (float) – (if set) Set the ratio between volume and exchange/transfer moves (applies to Gibbs ensemble)
The muVT (or grand-canonical) ensemble simulates a system at constant fugacity.
Gibbs ensemble simulations are also supported, where particles and volume are swapped between two or more boxes. Every box correspond to one MPI partition, and can therefore run on multiple ranks. Use the
ranks_per_partition
argument ofhoomd.communicator.Communicator
to enable partitioned simulations.Mixed precision
MuVT
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.Note
Multiple Gibbs ensembles are also supported in a single parallel job, with the
ngibbs
option to update.muvt(), where the number of partitions can be a multiple ofngibbs
.- transfer_types
List of type names that are being transferred from/to the reservoir or between boxes
- Type
- move_ratio
The ratio between volume and exchange/transfer moves (applies to Gibbs ensemble)
- Type
- fugacity
Particle fugacity \([\mathrm{volume}^{-1}]\) (default: 0).
- Type
TypeParameter
[particle type
,float
]
- property N
Map of number of particles per type.
None when not attached.
(
Loggable
: category=”object”)- Type
- property exchange_moves
Count of the accepted and rejected paricle exchange moves.
None when not attached
(
Loggable
: category=”sequence”)
- property insert_moves
Count of the accepted and rejected paricle insertion moves.
None when not attached
(
Loggable
: category=”sequence”)
- class hoomd.hpmc.update.QuickCompress(trigger, target_box, max_overlaps_per_particle=0.25, min_scale=0.99)
Bases:
Updater
Quickly compress a hard particle system to a target box.
- Parameters
trigger (hoomd.trigger.trigger_like) – Update the box dimensions on triggered time steps.
target_box (hoomd.box.box_like) – Dimensions of the target box.
max_overlaps_per_particle (float) – The maximum number of overlaps to allow per particle (may be less than 1 - e.g. up to 250 overlaps would be allowed when in a system of 1000 particles when max_overlaps_per_particle=0.25).
min_scale (float) – The minimum scale factor to apply to box dimensions.
Use
QuickCompress
in conjunction with an HPMC integrator to scale the system to a target box size.QuickCompress
can typically compress dilute systems to near random close packing densities in tens of thousands of time steps.It operates by making small changes toward the
target_box
, but only when there are no particle overlaps in the current simulation state. In 3D:\[\begin{split}L_x' &= \begin{cases} \max( L_x \cdot s, L_{\mathrm{target},x} ) & L_{\mathrm{target},x} < L_x \\ \min( L_x / s, L_{\mathrm{target},x} ) & L_{\mathrm{target},x} \ge L_x \end{cases} \\ L_y' &= \begin{cases} \max( L_y \cdot s, L_{\mathrm{target},y} ) & L_{\mathrm{target},y} < L_y \\ \min( L_y / s, L_{\mathrm{target},y} ) & L_{\mathrm{target},y} \ge L_y \end{cases} \\ L_z' &= \begin{cases} \max( L_z \cdot s, L_{\mathrm{target},z} ) & L_{\mathrm{target},z} < L_z \\ \min( L_z / s, L_{\mathrm{target},z} ) & L_{\mathrm{target},z} \ge L_z \end{cases} \\ xy' &= \begin{cases} \max( xy \cdot s, xy_\mathrm{target} ) & xy_\mathrm{target} < xy \\ \min( xy / s, xy_\mathrm{target} ) & xy_\mathrm{target} \ge xy \end{cases} \\ xz' &= \begin{cases} \max( xz \cdot s, xz_\mathrm{target} ) & xz_\mathrm{target} < xz \\ \min( xz / s, xz_\mathrm{target} ) & xz_\mathrm{target} \ge xz \end{cases} \\ yz' &= \begin{cases} \max( yz \cdot s, yz_\mathrm{target} ) & yz_\mathrm{target} < yz \\ \min( yz / s, yz_\mathrm{target} ) & yz_\mathrm{target} \ge yz \end{cases} \\\end{split}\]and in 2D:
\[\begin{split}L_x' &= \begin{cases} \max( L_x \cdot s, L_{\mathrm{target},x} ) & L_{\mathrm{target},x} < L_x \\ \min( L_x / s, L_{\mathrm{target},x} ) & L_{\mathrm{target},x} \ge L_x \end{cases} \\ L_y' &= \begin{cases} \max( L_y \cdot s, L_{\mathrm{target},y} ) & L_{\mathrm{target},y} < L_y \\ \min( L_y / s, L_{\mathrm{target},y} ) & L_{\mathrm{target},y} \ge L_y \end{cases} \\ L_z' &= L_z \\ xy' &= \begin{cases} \max( xy \cdot s, xy_\mathrm{target} ) & xy_\mathrm{target} < xy \\ \min( xy / s, xy_\mathrm{target} ) & xy_\mathrm{target} \ge xy \end{cases} \\ xz' &= xz \\ yz' &= yz \\\end{split}\]where the current simulation box is \((L_x, L_y, L_z, xy, xz, yz)\), the target is \((L_{\mathrm{target},x}, L_{\mathrm{target},y}, L_{\mathrm{target},z}, xy_\mathrm{target}, xz_\mathrm{target}, yz_\mathrm{target})\), the new simulation box set is \((L_x', L_y', L_z', xy', xz', yz')\) and \(s\) is the scale factor chosen for this step (see below).
QuickCompress
scales particle coordinates (seeBoxMC
for details) when it sets a new box.When there are more than
max_overlaps_per_particle * N_particles
hard particle overlaps in the system in the new box, the box move is rejected. Otherwise, the small number of overlaps remain when the new box is set.QuickCompress
then waits untilhoomd.hpmc.integrate.HPMCIntegrator
makes local MC trial moves that remove all overlaps.QuickCompress
adjusts the value of \(s\) based on the particle and translational trial move sizes to ensure that the trial moves will be able to remove the overlaps. It randomly chooses a value of \(s\) uniformly distributed betweenmax(min_scale, 1.0 - min_move_size / max_diameter)
and 1.0 wheremin_move_size
is the smallest MC translational move size adjusted by the acceptance ratio andmax_diameter
is the circumsphere diameter of the largest particle type.Tip
Use the
hoomd.hpmc.tune.MoveSize
in conjunction withQuickCompress
to adjust the move sizes to maintain a constant acceptance ratio as the density of the system increases.Warning
When the smallest MC translational move size is 0,
QuickCompress
will scale the box by 1.0 and not progress toward the target box.Warning
Use
QuickCompress
ORBoxMC
. Do not use both at the same time.Mixed precision
QuickCompress
uses reduced precision floating point arithmetic when checking for particle overlaps in the local particle reference frame.- max_overlaps_per_particle
The maximum number of overlaps to allow per particle (may be less than 1 - e.g. up to 250 overlaps would be allowed when in a system of 1000 particles when max_overlaps_per_particle=0.25).
- Type
- instance
When using multiple
QuickCompress
updaters in a single simulation, give each a unique value forinstance
so that they generate different streams of random numbers.- Type
- property complete
True when the box has achieved the target.
- class hoomd.hpmc.update.Shape(trigger, shape_move, pretend=False, type_select=1, nsweeps=1)
Bases:
Updater
Apply shape updates to the shape definitions defined in the integrator.
See also
hoomd.hpmc.shape_move
describes the shape alchemy algorithm.- Parameters
trigger (hoomd.trigger.trigger_like) – Call the updater on triggered time steps.
shape_move (ShapeMove) – Type of shape move to apply when updating shape definitions
pretend (
bool
, optional) – When True the updater will not actually update the shape definitions. Instead, moves will be proposed and the acceptance statistics will be updated correctly (default:False
).type_select (
int
, optional) – Number of types to change every time the updater is called (default: 1).nsweeps (
int
, optional) – Number of times to update shape definitions during each triggered timesteps (default: 1).
Shape support.
See
hoomd.hpmc.shape_move
for supported shapes.Example:
mc = hoomd.hpmc.integrate.ConvexPolyhedron() mc.shape["A"] = dict(vertices=numpy.asarray([(1, 1, 1), (-1, -1, 1), (1, -1, -1), (-1, 1, -1)])) vertex_move = hoomd.hpmc.shape_move.Vertex(stepsize={'A': 0.01}, param_ratio=0.2, volume=1.0) updater = hoomd.hpmc.update.Shape(shape_move=vertex_move, trigger=hoomd.trigger.Periodic(1), type_select=1, nsweeps=1)
- pretend
When True the updater will not actually update the shape definitions, instead moves will be proposed and the acceptance statistics will be updated correctly.
- Type
hoomd.hpmc.pair
Pair Potentials for Monte Carlo.
Define \(U_{\mathrm{pair},ij}\) for use with
hoomd.hpmc.integrate.HPMCIntegrator
. Assign a pair potential instance to
hpmc.integrate.HPMCIntegrator.pair_potential
to activate the potential.
Modules
hoomd.hpmc.pair.user
Overview
Base class for interaction between pairs of particles given in C++. |
|
Define an energetic interaction between pairs of particles. |
|
Define an arbitrary energetic interaction between unions of particles. |
Details
User-defined pair potentials for HPMC simulations.
Set \(U_{\mathrm{pair},ij}\) evaluated in
hoomd.hpmc.integrate.HPMCIntegrator
to a user-defined expression.
See also
Features explains the compile time options needed for user defined pair potentials.
- class hoomd.hpmc.pair.user.CPPPotentialBase
Base class for interaction between pairs of particles given in C++.
Pair potential energies define energetic interactions between pairs of particles in
hoomd.hpmc.integrate.HPMCIntegrator
. Particles within a cutoff distance interact with an energy that is a function the type and orientation of the particles and the vector pointing from the i particle to the j particle center.Classes derived from
CPPPotentialBase
take C++ code, compile it at runtime, and execute the code natively in the MC loop.Warning
CPPPotentialBase
is experimental and subject to change in future minor releases.C++ code
Classes derived from
CPPPotentialBase
will compile the code provided by the user and call it to evaluate the energy \(U_{\mathrm{pair},ij}\). The text provided is the body of a function with the following signature:float eval(const vec3<float>& r_ij, unsigned int type_i, const quat<float>& q_i, float d_i, float charge_i, unsigned int type_j, const quat<float>& q_j, float d_j, float charge_j )
r_ij
is a vector pointing from the center of particle i to the center of particle j.type_i
is the integer type id of particle iq_i
is the quaternion orientation of particle id_i
is the diameter of particle icharge_i
is the charge of particle itype_j
is the integer type id of particle jq_j
is the quaternion orientation of particle jd_j
is the diameter of particle jcharge_j
is the charge of particle j
Note
vec3
andquat
are defined in the file VectorMath.h in the HOOMD-blue source code.Note
Your code must return a value.
Mixed precision
CPPPotentialBase
uses 32-bit precision floating point arithmetic when computing energies in the local particle reference frame.
- class hoomd.hpmc.pair.user.CPPPotential(r_cut, code, param_array)
Bases:
CPPPotentialBase
Define an energetic interaction between pairs of particles.
Adjust parameters within the code with the
param_array
attribute without requiring a recompile. These arrays are read-only during function evaluation.- Parameters
r_cut (float) – Particle center to center distance cutoff beyond which all pair interactions are 0.
code (str) – C++ code defining the function body for pair interactions between particles.
param_array (list[float]) – Parameter values to make available in
float *param_array
in the compiled code. If no adjustable parameters are needed in the C++ code, pass an empty array.
See also
CPPPotentialBase
for the documentation of the parent class.Warning
CPPPotential
is experimental and subject to change in future minor releases.- code
The C++ code that defines the body of the patch energy function. After running zero or more steps, this property cannot be changed.
- Type
- param_array
Numpy array containing dynamically adjustable elements in the potential energy function as defined by the user. After running zero or more steps, the array cannot be set, although individual values can still be changed.
- Type
(N, )
numpy.ndarray
offloat
- energy
The potential energy resulting from the interactions defind in the C++ code at the current timestep.
- Type
Examples
sq_well = '''float rsq = dot(r_ij, r_ij); if (rsq < 1.21f) return -1.0f; else return 0.0f; ''' patch = hoomd.hpmc.pair.user.CPPPotential(r_cut=1.1, code=sq_well, param_array=[]) mc.pair_potential = patch sim.run(1000)
- class hoomd.hpmc.pair.user.CPPPotentialUnion(r_cut_constituent, code_constituent, r_cut_isotropic, code_isotropic, param_array_constituent, param_array_isotropic)
Bases:
CPPPotentialBase
Define an arbitrary energetic interaction between unions of particles.
- Parameters
r_cut_constituent (
float
) – Constituent particle center to center distance cutoff beyond which all pair interactions are 0.code_constituent (
str
) – C++ code defining the custom pair interactions between constituent particles.r_cut_isotropic (
float
) – Cut-off for isotropic interaction between centers of union particles.code_isotropic (
str
) – C++ code for isotropic part of the interaction. Must be''
when executing on a GPU.param_array_constituent (list[float]) – Parameter values to make available in
float *param_array_constituent
in the compiled code. Pass an empty array if no adjustable parameters are needed for the constituent interactions.param_array_isotropic (list[float]) – Parameter values to make available in
float *param_array_isotropic
in the compiled code. Pass an empty array if no adjustable parameters are needed for the isotropic interactions.
Note
Code passed into
code_isotropic
is not used when executing on the GPU. ARuntimeError
is raised on attachment if the value of this argument is anything besides''
on the GPU.Note
This class uses an internal OBB tree for fast interaction queries between constituents of interacting particles. Depending on the number of constituent particles per type in the tree, different values of the particles per leaf node may yield different optimal performance. The capacity of leaf nodes is configurable.
See also
CPPPotentialBase
for the documentation of the parent class.Warning
CPPPotentialUnion
is experimental and subject to change in future minor releases.Threading
CPPPotentialUnion uses threaded execution on multiple CPU cores.
- positions
The positions of the constituent particles.
Type:
TypeParameter
[particle type
,list
[tuple
[float
,float
,float
]]]
- orientations
The orientations of the constituent particles.
Type:
TypeParameter
[particle type
,list
[tuple
[float
,float
,float
,float
]]]
- diameters
The diameters of the constituent particles.
- Type
TypeParameter
[particle type
,list
[float
]]
- charges
The charges of the constituent particles.
- Type
TypeParameter
[particle type
,list
[float
]]
- typeids
The integer types of the constituent particles.
- Type
TypeParameter
[particle type
,list
[float
]]
- leaf_capacity
The number of particles in a leaf of the internal tree data structure (default: 4).
- Type
- code_constituent
The C++ code that defines the body of the patch energy function between the constituent particles. This property cannot be modified after running for zero or more steps.
- Type
- code_isotropic
The C++ code that defines the body of the patch energy function between the centers of the particles. This property cannot be modified after running for zero or more steps.
- Type
- param_array_isotropic
Numpy array containing dynamically adjustable elements in the isotropic part of the potential as defined by the user. After running zero or more steps, the array cannot be set, although individual values can still be changed.
- Type
(N, )
numpy.ndarray
offloat
- param_array_constituent
Numpy array containing dynamically adjustable elements in the constituent part of the potential part of the potential as defined by the user. After running zero or more steps, the array cannot be set, although individual values can still be changed.
- Type
(N, )
numpy.ndarray
offloat
- energy
The potential energy resulting from the interactions defind in the C++ code at the current timestep.
- Type
Example without isotropic interactions:
square_well = '''float rsq = dot(r_ij, r_ij); if (rsq < 1.21f) return -1.0f; else return 0.0f; ''' patch = hoomd.hpmc.pair.user.CPPPotentialUnion( r_cut_constituent=1.1, r_cut_isotropic=0.0 code_constituent=square_well, code_isotropic='', param_array_constituent=[], param_array_isotropic=[] ) patch.positions['A'] = [ (0, 0, -0.5), (0, 0, 0.5) ] patch.diameters['A'] = [0, 0] patch.typeids['A'] = [0, 0] mc.pair_potential = patch
Example with added isotropic interactions:
# square well attraction on constituent spheres square_well = '''float rsq = dot(r_ij, r_ij); float r_cut = param_array_constituent[0]; if (rsq < r_cut*r_cut) return param_array_constituent[1]; else return 0.0f; ''' # soft repulsion between centers of unions soft_repulsion = '''float rsq = dot(r_ij, r_ij); float r_cut = param_array_isotropic[0]; if (rsq < r_cut*r_cut) return param_array_isotropic[1]; else return 0.0f; ''' patch = hoomd.hpmc.pair.user.CPPPotentialUnion( r_cut_constituent=2.5, r_cut_isotropic=5.0, code_union=square_well, code_isotropic=soft_repulsion, param_array_constituent=[2.0, -5.0], param_array_isotropic=[2.5, 1.3], ) patch.positions['A'] = [ (0, 0, -0.5), (0, 0, 0.5) ] patch.typeids['A'] = [0, 0] patch.diameters['A'] = [0, 0] mc.pair_potential = patch
hoomd.hpmc.external
External fields for Monte Carlo.
Define \(U_{\mathrm{external},i}\) for use with
hoomd.hpmc.integrate.HPMCIntegrator
. Assign an external field instance to
hpmc.integrate.HPMCIntegrator.external_potential
to activate the potential.
Modules
hoomd.hpmc.external.user
Overview
Define an external potential energy field imposed on all particles in the system. |
Details
User-defined external fields for HPMC simulations.
Set \(U_{\mathrm{external},i}\) evaluated in
hoomd.hpmc.integrate.HPMCIntegrator
to a user-defined expression.
See also
Features explains the compile time options needed for user defined external potentials.
- class hoomd.hpmc.external.user.CPPExternalPotential(code)
Bases:
ExternalField
Define an external potential energy field imposed on all particles in the system.
- Parameters
code (str) – C++ function body to compile.
Potentials added using
CPPExternalPotential
are added to the total energy calculation inhoomd.hpmc.integrate.HPMCIntegrator
.CPPExternalPotential
takes C++ code, compiles it at runtime, and executes the code natively in the MC loop with full performance. It enables researchers to quickly and easily implement custom energetic field intractions without the need to modify and recompile HOOMD.C++ code
Supply C++ code to the code argument and
CPPExternalPotential
will compile the code and call it to evaluate the energy. The text provided in code is the body of a function with the following signature:float eval(const BoxDim& box, unsigned int type_i, const vec3<Scalar>& r_i, const quat<Scalar>& q_i Scalar diameter, Scalar charge )
box is the system box.
type_i is the (integer) particle type.
r_i is the particle position
q_i the quaternion representing the particle orientation.
diameter the particle diameter.
charge the particle charge.
Note
vec3
andquat
are defined in the file VectorMath.h in the HOOMD-blue source code, andBoxDim
is defined in he file BoxDim.h in the HOOMD-blue source code.Note
Your code must return a value.
Example
gravity_code = "return r_i.z + box.getL().z/2;" gravity = hoomd.hpmc.external.user.CPPExternalPotential( code=gravity_code) mc.external_potential = gravity
Note
CPPExternalPotential
does not support execution on GPUs.Warning
CPPExternalPotential
is experimental and subject to change in future minor releases.- code
The code of the body of the external field energy function. After running zero or more steps, this property cannot be modified.
- Type
hoomd.hpmc.external.field
Overview
Base class external field. |
|
Restrain particle positions and orientations with harmonic springs. |
Details
Apply external fields to HPMC simulations.
- class hoomd.hpmc.external.field.ExternalField
Bases:
Base class external field.
Provides common methods for all external field subclasses.
Note
Users should use the subclasses and not instantiate
ExternalField
directly.
- class hoomd.hpmc.external.field.Harmonic(reference_positions, reference_orientations, k_translational, k_rotational, symmetries)
Bases:
ExternalField
Restrain particle positions and orientations with harmonic springs.
- Parameters
reference_positions ((N_particles, 3)
numpy.ndarray
offloat
) – the reference positions to which particles are restrained \([\mathrm{length}]\).reference_orientations ((N_particles, 4)
numpy.ndarray
offloat
) – the reference orientations to which particles are restrained \([\mathrm{dimensionless}]\).k_translational (hoomd.variant.variant_like) – translational spring constant \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\).
k_rotational (hoomd.variant.variant_like) – rotational spring constant \([\mathrm{energy}]\).
symmetries ((N_symmetries, 4)
numpy.ndarray
offloat
) – the orientations that are equivalent through symmetry, i.e., the rotation quaternions that leave the particles unchanged. At a minimum, the identity quaternion ([1, 0, 0, 0]
) must be included here \([\mathrm{dimensionless}]\).
Harmonic
computes harmonic spring energies between the particle positions/orientations and given reference positions/orientations:\[\begin{split}U_{\mathrm{external},i} & = U_{\mathrm{translational},i} + U_{\mathrm{rotational},i} \\ U_{\mathrm{translational},i} & = \frac{1}{2} k_{translational} \cdot (\vec{r}_i-\vec{r}_{0,i})^2 \\ U_{\mathrm{rotational},i} & = \frac{1}{2} k_{rotational} \cdot \min_j \left[ (\mathbf{q}_i-\mathbf{q}_{0,i} \cdot \mathbf{q}_{\mathrm{symmetry},j})^2 \right]\end{split}\]where \(k_{translational}\) and \(k_{rotational}\) correspond to the parameters
k_translational
andk_rotational
, respectively, \(\vec{r}_i\) and \(\mathbf{q}_i\) are the position and orientation of particle \(i\), the \(0\) subscripts denote the given reference quantities, and \(\mathbf{q}_{\mathrm{symmetry}}\) is the given set of symmetric orientations from thesymmetries
parameter.Note
Harmonic
does not support execution on GPUs.- k_translational
The translational spring constant \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\).
- k_rotational
The rotational spring constant \([\mathrm{energy}]\).
- reference_positions
The reference positions to which particles are restrained \([\mathrm{length}]\).
- Type
(N_particles, 3)
numpy.ndarray
offloat
- reference_orientations
The reference orientations to which particles are restrained \([\mathrm{dimensionless}]\).
- Type
(N_particles, 4)
numpy.ndarray
offloat
- symmetries
The orientations that are equivalent through symmetry, i.e., the rotation quaternions that leave the particles unchanged \([\mathrm{dimensionless}]\).
- Type
(N_symmetries, 4)
numpy.ndarray
offloat
- property energy
The total energy of the harmonic field \([\mathrm{energy}]\).
\[\sum_{i=0}^\mathrm{N_particles-1} U_{\mathrm{external},i}\](
Loggable
: category=”scalar”)- Type
hoomd.hpmc.external.wall
Overview
HPMC wall potential. |
Details
Wall potentials HPMC simulations.
Set \(U_{\mathrm{external},i}\) evaluated in
hoomd.hpmc.integrate.HPMCIntegrator
to a hard particle-wall interaction.
- class hoomd.hpmc.external.wall.WallPotential(walls)
Bases:
ExternalField
HPMC wall potential.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions that confine particles to specific regions of space.
WallPotential
adds hard walls to HPMC simulations. Define the wall geometry with a collection ofwall.WallGeometry
objects. These walls break space into forbidden and allowed regions, controlled by theinside
argument for spherical and cylindrical walls and thenormal
argument for planar walls. HPMC rejects trial moves that cause any part of the particle’s shape to enter the the space defined by the points with a negative signed distance from any wall in the collection. Formally, the contribution of the particle-wall interactions to the potential energy of the system is given by\[U_{\mathrm{walls}} = \sum_{i=0}^{N_{\mathrm{particles}-1}} \sum_{j=0}^{N_{\mathrm{walls}-1}} U_{i,j},\]where the energy of interaction \(U_{i,j}\) between particle \(i\) and wall \(j\) is given by
\[\begin{split}U_{i,j} = \begin{cases} \infty & d_{i,j} <= 0 \\ 0 & d_{i,j} > 0 \\ \end{cases}\end{split}\]where \(d_{i,j} = \min{\{(\vec{r}_i - \vec{r}_j) \cdot \vec{n}_j : \vec{r}_i \in V_I, \vec{r}_j \in W_J\}}\) is the minimum signed distance between all pairs of points \(\vec{r}_i\) on the body of the particle \(V_I\) and \(\vec{r}_j\) on the surface of the wall \(W_J\) and \(\vec{n}_j\) is the vector normal to the surface of the wall at \(\vec{r}_j\) pointing to the allowed region of space defined by the wall.
Walls are enforced by the HPMC integrator. Assign a
WallPotential
instance tohpmc.integrate.HPMCIntegrator.external_potential
to activate the wall potential. Not all combinations of HPMC integrators and wall geometries have overlap checks implemented, and aNotImplementedError
is raised if a wall geometry is attached to a simulation with a specific HPMC integrator attached and the overlap checks between the specific shape and wall geometry are not implemented. See the individual subclasses ofhoomd.hpmc.integrate.HPMCIntegrator
for their wall support.Note
WallPotential
does not support execution on GPUs.See also
Example:
mc = hoomd.hpmc.integrate.Sphere() walls = [hoomd.wall.Sphere(radius=4.0)] wall_potential = hoomd.hpmc.external.wall.WallPotential(walls) mc.external_potential = wall_potential
- property overlaps
The total number of overlaps between particles and walls.
(
Loggable
: category=”scalar”)- Type
- property walls
The wall geometries associated with this potential.
- Type
hoomd.hpmc.shape_move
Overview
Elastic shape move. |
|
Base class for all shape moves. |
|
Apply shape moves in a \(N\) dimensional shape space. |
|
Apply shape moves where particle vertices are translated. |
Details
Shape moves for a for alchemical simulations in extended ensembles.
ShapeMove
subclasses extend the Hamiltonian of the system by adding degrees of
freedom to the shape of the hard particle.
See also
- class hoomd.hpmc.shape_move.Elastic(stiffness, mc, default_step_size=None, normal_shear_ratio=0.5)
Bases:
ShapeMove
Elastic shape move.
Apply volume preserving normal and shear shape moves to particles with a deformation energy penalty. When volume preserving deformations, the strain energy penalty is approximated as:
\[U \approx \mu \text{Tr}[\boldsymbol{\varepsilon}^2]V\]where \(\mu\) is the stiffness constant, \(\text{Tr}\) is the trace operator, \(\boldsymbol{\varepsilon}\) is the strain tensor and \(V\) is the particle volume.
- Parameters
stiffness (hoomd.variant.variant_like) – Shape stiffness against deformations.
mc (
type
orhoomd.hpmc.integrate.HPMCIntegrator
) – The class of the MC shape integrator or an instance (seehoomd.hpmc.integrate
) to use with this elastic shape. Must be a compatible class. We use this argument to create validation forreference_shape
.default_step_size (
float
, optional) – Default maximum size of shape trial moves (default: None). By default requires setting step size for all types.normal_shear_ratio (
float
, optional) – Fraction of normal to shear deformation trial moves (default: 0.5).
Shape support.
The following shapes are supported:
Note
An instance is only able to be used with the passed HPMC integrator class.
Example:
mc = hoomd.hpmc.integrate.ConvexPolyhedron() verts = [(1, 1, 1), (-1, -1, 1), (1, -1, -1), (-1, 1, -1)] mc.shape["A"] = dict(vertices=verts) elastic_move = hoomd.hpmc.shape_move.Elastic(stiffness=10, mc) elastic_move.stiffness = 100 elastic_move.reference_shape["A"] = verts
- stiffness
Shape stiffness against deformations.
- step_size
Maximum size of shape trial moves.
- Type
TypeParameter
[particle type
,float
]
- reference_shape
Reference shape against to which compute the deformation energy.
- Type
TypeParameter
[particle type
,dict
]
- class hoomd.hpmc.shape_move.ShapeMove(default_step_size=None)
Bases:
Base class for all shape moves.
- Parameters
default_step_size (
float
, optional) – Default maximum size of shape trial moves (default: None). By default requires setting step size for all types.
Note
See the documentation of each derived class for a list of supported shapes.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- step_size
Maximum size of shape trial moves.
- Type
TypeParameter
[particle type
,float
]
- class hoomd.hpmc.shape_move.ShapeSpace(callback, default_step_size=None, param_move_probability=1)
Bases:
ShapeMove
Apply shape moves in a \(N\) dimensional shape space.
- Parameters
callback (
callable
[str
,list
],dict
]) – The python callable that will be called to map the given shape parameters to a shape definition. The callable takes the particle type and a list of parameters as arguments and return a dictionary with the shape definition whose keys must match the shape definition of the integrator:callable[[str, list], dict]
. There is no type validation of the callback.default_step_size (
float
, optional) – Default maximum size of shape trial moves (default: None). By default requires setting step size for all types.param_move_probability (
float
, optional) – Average fraction of shape parameters to change each timestep (default: 1).
Shape support.
The following shapes are supported:
Attention
ShapeSpace
only works with spheropolyhedra that have zero rounding or are spheres.Note
Parameters must be given for every particle type and must be between 0 and 1. The class does not performs any consistency checks internally. Therefore, any shape constraint (e.g. constant volume, etc) must be performed within the callback.
Example:
mc = hoomd.hpmc.integrate.ConvexPolyhedron() mc.shape["A"] = dict(vertices=[(1, 1, 1), (-1, -1, 1), (1, -1, -1), (-1, 1, -1)]) # example callback class ExampleCallback: def __init__(self): default_dict = dict(sweep_radius=0, ignore_statistics=True) def __call__(self, type, param_list): # do something with params and define verts return dict("vertices":verts, **self.default_dict)) move = hpmc.shape_move.ShapeSpace(callback = ExampleCallback)
- callback
The python function that will be called to map the given shape parameters to a shape definition. The function takes the particle type and a list of parameters as arguments and return a dictionary with the shape definition whose keys must match the shape definition of the integrator:
callable[[str, list], dict]
.
- step_size
Maximum size of shape trial moves.
- Type
TypeParameter
[particle type
,float
]
- params
List of tunable parameters to be updated. The length of the list defines the dimension of the shape space for each particle type.
- Type
TypeParameter
[particle type
,list
]
- class hoomd.hpmc.shape_move.Vertex(default_step_size=None, vertex_move_probability=1)
Bases:
ShapeMove
Apply shape moves where particle vertices are translated.
Vertices are rescaled during each shape move to ensure that the shape maintains a constant volume. To preserve detail balance, the maximum step size is rescaled by volume**(1/3) every time a move is accepted.
- Parameters
Vertex
moves apply a uniform move on each vertex with probabilityvertex_move_probability
in a shape up to a maximum displacement ofstep_size
for the composing instance. The shape volume is rescaled at the end of all the displacements to the specified volume. To preserve detail balance, the maximum step size is rescaled by \(V^{1 / 3}\) every time a move is accepted.Shape support.
The following shapes are supported:
Note
hoomd.hpmc.integrate.ConvexPolyhedron
models shapes that are the the convex hull of the given vertices.Example:
mc = hoomd.hpmc.integrate.ConvexPolyhedron(23456) cube_verts = [(1, 1, 1), (1, 1, -1), (1, -1, 1), (-1, 1, 1), (1, -1, -1), (-1, 1, -1), (-1, -1, 1), (-1, -1, -1)]) mc.shape["A"] = dict(vertices=numpy.asarray(cube_verts) / 2) vertex_move = shape_move.Vertex() vertex_move.volume["A"] = 1
- step_size
Maximum size of shape trial moves.
- Type
TypeParameter
[particle type
,float
]
- volume
Volume of the particles to hold constant. The particles size is always rescaled to maintain this volume.
- Type
TypeParameter
[particle type
,float
]
hoomd.md
Details
Molecular dynamics.
In molecular dynamics simulations, HOOMD-blue numerically integrates the degrees
of freedom in the system as a function of time under the influence of forces. To
perform MD simulations, assign a MD Integrator
to the hoomd.Simulation
operations. Provide the Integrator
with lists of integration methods, forces,
and constraints to apply during the integration. Use hoomd.md.minimize.FIRE
to perform energy minimization.
MD updaters (hoomd.md.update
) perform additional operations during the
simulation, including rotational diffusion and establishing shear flow.
Use MD computes (hoomd.md.compute
) to compute the thermodynamic properties of
the system state.
See also
Tutorial: Introducing Molecular Dynamics
- class hoomd.md.HalfStepHook(*args: Any, **kwargs: Any)
HalfStepHook base class.
HalfStepHook provides an interface to perform computations during the half-step of a hoomd.md.Integrator.
- update(timestep)
Called during the half-step of a
hoomd.md.Integrator
.This method should provide the implementation of any computation that the user wants to execute at each timestep in the middle of the integration routine.
- class hoomd.md.Integrator(dt, integrate_rotational_dof=False, forces=None, constraints=None, methods=None, rigid=None, half_step_hook=None)
Molecular dynamics time integration.
- Parameters
dt (float) – Integrator time step size \([\mathrm{time}]\).
methods (Sequence[hoomd.md.methods.Method]) – Sequence of integration methods. The default value of
None
initializes an empty list.forces (Sequence[hoomd.md.force.Force]) – Sequence of forces applied to the particles in the system. The default value of
None
initializes an empty list.integrate_rotational_dof (bool) – When True, integrate rotational degrees of freedom.
constraints (Sequence[hoomd.md.constrain.Constraint]) – Sequence of constraint forces applied to the particles in the system. The default value of
None
initializes an empty list. Rigid body objects (i.e.hoomd.md.constrain.Rigid
) are not allowed in the list.rigid (hoomd.md.constrain.Rigid) – An object defining the rigid bodies in the simulation.
half_step_hook (hoomd.md.HalfStepHook) – Enables the user to perform arbitrary computations during the half-step of the integration.
Integrator
is the top level class that orchestrates the time integration step in molecular dynamics simulations. The integrationmethods
define the equations of motion to integrate under the influence of the givenforces
andconstraints
.Each method applies the given equations of motion to a subset of particles in the simulation state. See the documentation for each method for details on what equations of motion it solves. The intersection of the subsets must be null.
Integrator
computes the net force, torque, energy, and virial on each particle as a sum of those applied byhoomd.md.force.Force
objects in theforces
andconstraints
lists:\[\begin{split}\vec{F}_{\mathrm{net},i} &= \sum_{f \in \mathrm{forces}} \vec{F}_i^f \\ \vec{\tau}_{\mathrm{net},i} &= \sum_{f \in \mathrm{forces}} \vec{\tau}_i^f \\ U_{\mathrm{net},i} &= \sum_{f \in \mathrm{forces}} U_i^f \\ W_{\mathrm{net},i} &= \sum_{f \in \mathrm{forces}} W_i^f \\\end{split}\]Integrator
also computes the net additional energy and virial\[\begin{split}U_{\mathrm{net},\mathrm{additional}} &= \sum_{f \in \mathrm{forces}} U_\mathrm{additional}^f \\ W_{\mathrm{net},\mathrm{additional}} &= \sum_{f \in \mathrm{forces}} W_\mathrm{additional}^f \\\end{split}\]See
md.force.Force
for definitions of these terms. Constraints are a special type of force used to enforce specific constraints on the system state, such as distances between particles withhoomd.md.constrain.Distance
.Integrator
handles rigid bodies as a special case, as it only integrates the degrees of freedom of each body’s center of mass. Seehoomd.md.constrain.Rigid
for details.Degrees of freedom
Integrator
always integrates the translational degrees of freedom. It optionally integrates one or more rotational degrees of freedom for a given particle i when all the following conditions are met:The intergration method supports rotational degrees of freedom.
integrate_rotational_dof
isTrue
.The moment of inertia is non-zero \(I^d_i > 0\).
Each particle may have zero, one, two, or three rotational degrees of freedom.
Note
By default,
integrate_rotational_dof
isFalse
.gsd
andhoomd.Snapshot
also set particle moments of inertia to 0 by default.Classes
Classes of the following modules can be used as elements in
methods
:The classes of following modules can be used as elements in
forces
:The classes of the following module can be used as elements in
constraints
:Examples:
nlist = hoomd.md.nlist.Cell() lj = hoomd.md.pair.LJ(nlist=nlist) lj.params.default = dict(epsilon=1.0, sigma=1.0) lj.r_cut[('A', 'A')] = 2**(1/6) nve = hoomd.md.methods.NVE(filter=hoomd.filter.All()) integrator = hoomd.md.Integrator(dt=0.001, methods=[nve], forces=[lj]) sim.operations.integrator = integrator
- methods
List of integration methods.
- Type
- forces
List of forces applied to the particles in the system.
- Type
- constraints
List of constraint forces applied to the particles in the system.
- rigid
The rigid body definition for the simulation associated with the integrator.
- half_step_hook
User defined implementation to perform computations during the half-step of the integration.
- __setattr__(attr, value)
Hande group DOF update when setting integrate_rotational_dof.
Modules
md.alchemy
Details
Alchemical molecular dynamics.
Implements molecular dynamics simulations of an extended statistical mechanical ensemble that includes alchemical degrees of freedom describing particle attributes as thermodynamic variables.
Example:
nvt = hoomd.md.methods.NVT(...)
integrator.methods.append(nvt)
ljg = hoomd.md.alchemy.pair.LJGauss(...)
integrator.forces.append(ljg)
r0_alchemical_dof = ljg.r0[('A', 'A')]
alchemostat = hoomd.md.alchemy.methods.NVT(
period=period,
alchemical_dof=[r0_alchemical_dof],
alchemical_kT=hoomd.variant.Constant(0.1),
)
integrator.methods.insert(0, alchemostat)
sim.run(n_steps)
New in version 3.1.0.
Modules
md.alchemy.pair
Overview
Alchemical degree of freedom \(\alpha_i\) associated with a specific pair force. |
|
A read-only mapping of alchemical degrees of freedom accessed by type. |
|
Alchemical Lennard Jones Gauss pair force. |
Details
Alchemical pair forces.
- class hoomd.md.alchemy.pair.AlchemicalDOF
Alchemical degree of freedom \(\alpha_i\) associated with a specific pair force.
AlchemicalDOF
represents an alchemical degree of freedom to be numerically integrated via analchemical integration method
.Note
To access an alchemical degree of freedom for a particular type pair, query the corresponding attribute in the alchemical pair force instance.
New in version 3.1.0.
- property alchemical_forces
Per particle forces in alchemical alpha space.
\[F_{\mathrm{alchemical},i} = -\frac{\mathrm{d}U_i}{\mathrm{d}\alpha}\](
Loggable
: category=”particle”, default=False)
- class hoomd.md.alchemy.pair.AlchemicalDOFStore(name, pair_instance, dof_cls)
Bases:
Mapping
A read-only mapping of alchemical degrees of freedom accessed by type.
The class acts as a cache so once an alchemical DOF is queried it is returned and not recreated when queried again.
New in version 3.1.0.
- __contains__(key)
Return whether the key is in the mapping.
- __getitem__(key)
Get the alchemical degree of freedom for the given type pair.
- __iter__()
Iterate over keys.
- __len__()
Get the length of the mapping.
- class hoomd.md.alchemy.pair.LJGauss(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
LJGauss
Alchemical Lennard Jones Gauss pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
LJGauss
computes the Lennard-Jones Gauss force on all particles in the simulation state, with additional alchemical degrees of freedom:\[U(r) = 1\ [\mathrm{energy}] \cdot \left[ \left ( \frac{1\ [\mathrm{length}]}{r} \right)^{12} - \left ( \frac{2\ [\mathrm{length}]}{r} \right)^{6} \right] - \alpha_{1}\epsilon \exp \left[ - \frac{\left(r - \alpha_{2}r_{0}\right)^{2}}{2 (\alpha_{3}\sigma)^{2}} \right],\]where \(\alpha_i\) are the alchemical degrees of freedom.
Note
\(\alpha_i\) not accessed are set to 1.
Attention
hoomd.md.alchemy.pair.LJGauss
does not support execution on GPUs.Attention
hoomd.md.alchemy.pair.LJGauss
does not support MPI parallel simulations.New in version 3.1.0.
- params
The potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - Gaussian width \(\sigma\) \([\mathrm{length}]\)r0
(float
, required) - Gaussian center \(r_0\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- epsilon
Alchemical degrees of freedom for the potential parameter \(\epsilon\).
Type:
AlchemicalDOFStore
[tuple
[particle_type
,particle_type
],AlchemicalDOF
])
- sigma
Alchemical degrees of freedom for the potential parameter \(\sigma\).
Type:
AlchemicalDOFStore
[tuple
[particle_type
,particle_type
],AlchemicalDOF
])
- r0
Alchemical degrees of freedom for the potential parameter \(r_0\).
Type:
AlchemicalDOFStore
[tuple
[particle_type
,particle_type
],AlchemicalDOF
])
md.alchemy.methods
Overview
Alchemostat base class. |
|
Alchemical NVT integration. |
Details
Alchemical MD integration methods.
- class hoomd.md.alchemy.methods.Alchemostat(alchemical_dof)
Alchemostat base class.
Note
Alchemostat
is the base class for all alchemical integration methods. Users should use the subclasses and not instantiateAlchemostat
directly.New in version 3.1.0.
- property alchemical_dof
List of alchemical degrees of freedom.
- class hoomd.md.alchemy.methods.NVT(alchemical_kT, alchemical_dof, period=1)
Alchemical NVT integration.
Implements molecular dynamics simulations of an extended statistical mechanical ensemble that includes alchemical degrees of freedom describing particle attributes as thermodynamic variables.
- Parameters
alchemical_kT (hoomd.variant.variant_like) – Temperature set point for the alchemostat \([\mathrm{energy}]\).
alchemical_dof (
list
[hoomd.md.alchemy.pair.AlchemicalDOF
]) – List of alchemical degrees of freedom.period (int) – Timesteps between applications of the alchemostat.
Attention
hoomd.md.alchemy.methods.NVT
does not support execution on GPUs.Attention
hoomd.md.alchemy.methods.NVT
does not support MPI parallel simulations.Attention
hoomd.md.alchemy.methods.NVT
objects are not picklable.Danger
NVT
must be the first item in thehoomd.md.Integrator.methods
list.See also
New in version 3.1.0.
- alchemical_kT
Temperature set point for the alchemostat \([\mathrm{energy}]\).
- alchemical_dof
List of alchemical degrees of freedom.
md.angle
Overview
Base class angle force. |
|
Harmonic angle force. |
|
Cosine squared angle force. |
|
Tabulated bond force. |
Details
Angle forces.
Angle force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
Each angle is defined by an ordered triplet of particle tags in the
hoomd.State
member angle_group
. HOOMD-blue does not construct angle
groups, users must explicitly define angles in the initial condition.
In the angle group (i,j,k), \(\theta\) is the angle between the vectors \(\vec{r}_{ij}\) and \(\vec{r}_{kj}\).
Angle force classes assign 1/3 of the potential energy to each of the particles in the angle group:
and similarly for virials.
- class hoomd.md.angle.Angle
Bases:
Force
Base class angle force.
Angle
is the base class for all angle forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.md.angle.CosineSquared
Bases:
Angle
Cosine squared angle force.
CosineSquared
computes forces, virials, and energies on all angles in the simulation state with:\[U(\theta) = \frac{1}{2} k \left( \cos\theta - \cos\theta_0 \right)^2\]CosineSquared
is used in the gromos96 and MARTINI force fields.- params
The parameter of the harmonic bonds for each particle type. The dictionary has the following keys:
k
(float
, required) - potential constant \(k\) \([\mathrm{energy}]\)t0
(float
, required) - rest angle \(\theta_0\) \([\mathrm{radians}]\)
- Type
TypeParameter[
angle type
, dict]
Examples:
cosinesq = angle.CosineSquared() cosinesq.params['A-A-A'] = dict(k=3.0, t0=0.7851) cosinesq.params['A-B-A'] = dict(k=100.0, t0=1.0)
- class hoomd.md.angle.Harmonic
Bases:
Angle
Harmonic angle force.
Harmonic
computes forces, virials, and energies on all angles in the simulation state with:\[U(\theta) = \frac{1}{2} k \left( \theta - \theta_0 \right)^2\]- params
The parameter of the harmonic bonds for each particle type. The dictionary has the following keys:
k
(float
, required) - potential constant \(k\) \([\mathrm{energy} \cdot \mathrm{radians}^{-2}]\)t0
(float
, required) - rest angle \(\theta_0\) \([\mathrm{radians}]\)
- Type
TypeParameter[
angle type
, dict]
Examples:
harmonic = angle.Harmonic() harmonic.params['A-A-A'] = dict(k=3.0, t0=0.7851) harmonic.params['A-B-A'] = dict(k=100.0, t0=1.0)
- class hoomd.md.angle.Table(width)
Bases:
Angle
Tabulated bond force.
- Parameters
width (int) – Number of points in the table.
Table
computes computes forces, virials, and energies on all angles in the simulation given the user defined tables \(U\) and \(\tau\).The torque \(\tau\) is:
\[\tau(\theta) = \tau_\mathrm{table}(\theta)\]and the potential \(V(\theta)\) is:
\[U(\theta) =U_\mathrm{table}(\theta)\]Provide \(\tau_\mathrm{table}(\theta)\) and \(U_\mathrm{table}(\theta)\) on evenly spaced grid points points in the range \(\theta \in [0,\pi]\).
Table
linearly interpolates values when \(\theta\) lies between grid points. The torque must be specificed commensurate with the potential: \(\tau = -\frac{\partial U}{\partial \theta}\).- params
The potential parameters. The dictionary has the following keys:
U
((width,)numpy.ndarray
offloat
, required) - the tabulated energy values \([\mathrm{energy}]\). Must have a size equal towidth
.tau
((width,)numpy.ndarray
offloat
, required) - the tabulated torque values \([\mathrm{force} \cdot \mathrm{length}]\). Must have a size equal towidth
.
- Type
TypeParameter
[angle type
,dict
]
md.bond
Overview
Base class bond force. |
|
FENE and WCA bond force. |
|
Harmonic bond force. |
|
Tabulated bond force. |
|
Tether bond force. |
Details
Bond forces.
Bond force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
Each bond is defined by an ordered pair of particle tags in the
hoomd.State
member bond_group
. HOOMD-blue does not construct bond groups,
users must explicitly define bonds in the initial condition.
In the bond group (j,k), \(r\) is the length of the bond between the particle positions \(r= |\mathrm{minimum\_image}(\vec{r}_k - \vec{r}_j)|\).
Bond force classes assign 1/2 of the potential energy to each of the particles in the bond group:
and similarly for virials.
- class hoomd.md.bond.Bond
Bases:
Force
Base class bond force.
Bond
is the base class for all bond forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.md.bond.FENEWCA
Bases:
Bond
FENE and WCA bond force.
FENEWCA
computes forces, virials, and energies on all bonds in the simulation state with:\[V(r) = - \frac{1}{2} k r_0^2 \ln \left( 1 - \left( \frac{r - \Delta}{r_0} \right)^2 \right) + U_{\mathrm{WCA}}(r)\]where
\[\begin{split}U_{\mathrm{WCA}}(r) = \begin{cases} 4 \varepsilon \left[ \left( \frac{\sigma}{r - \Delta} \right)^{12} - \left( \frac{\sigma}{r - \Delta} \right)^{6} \right] + \varepsilon & r-\Delta < 2^{\frac{1}{6}}\sigma\\ 0 & r-\Delta \ge 2^{\frac{1}{6}}\sigma \end{cases}\end{split}\], \(k\) is the attractive force strength, \(r_0\) is the size of the bond, \(\varepsilon\) is the repulsive interaction energy, and \(\sigma\) is the repulsive interaction width.
- params
The parameter of the FENEWCA potential bonds. The dictionary has the following keys:
k
(float
, required) - attractive force strength \(k\) \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\).r0
(float
, required) - size parameter \(r_0\) \([\mathrm{length}]\).epsilon
(float
, required) - repulsive force strength \(\varepsilon\) \([\mathrm{energy}]\).sigma
(float
, required) - repulsive force interaction width \(\sigma\) \([\mathrm{length}]\).delta
(float
, required) - radial shift \(\Delta\) \([\mathrm{length}]\).
- Type
TypeParameter[
bond type
, dict]
Examples:
fenewca = bond.FENEWCA() fenewca.params['A-A'] = dict(k=3.0, r0=2.38, epsilon=1.0, sigma=1.0, delta=0.0) fenewca.params['A-B'] = dict(k=10.0, r0=1.0, epsilon=0.8, sigma=1.2, delta=0.0)
- class hoomd.md.bond.Harmonic
Bases:
Bond
Harmonic bond force.
Harmonic
computes forces, virials, and energies on all bonds in the simulation state with:\[U(r) = \frac{1}{2} k \left( r - r_0 \right)^2\]- params
The parameter of the harmonic bonds for each particle type. The dictionary has the following keys:
k
(float
, required) - potential constant \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\)r0
(float
, required) - rest length \([\mathrm{length}]\)
- Type
TypeParameter[
bond type
, dict]
Examples:
harmonic = bond.Harmonic() harmonic.params['A-A'] = dict(k=3.0, r0=2.38) harmonic.params['A-B'] = dict(k=10.0, r0=1.0)
- class hoomd.md.bond.Table(width)
Bases:
Bond
Tabulated bond force.
- Parameters
width (int) – Number of points in the table.
Table
computes computes forces, virials, and energies on all bonds in the simulation given the user defined tables \(U\) and \(F\).Note
For potentials that diverge near r=0, to set r_min to a non-zero value.
The force \(\vec{F}\) is:
\[\begin{split}\vec{F}(\vec{r}) = \begin{cases} 0 & r < r_{\mathrm{min}} \\ F_\mathrm{table}(r)\hat{r} & r_{\mathrm{min}} \le r < r_{\mathrm{max}} \\ 0 & r \ge r_{\mathrm{max}} \\ \end{cases}\end{split}\]and the potential \(U(r)\) is:
\[\begin{split}U(r) = \begin{cases} 0 & r < r_{\mathrm{min}} \\ U_\mathrm{table}(r) & r_{\mathrm{min}} \le r < r_{\mathrm{max}} \\ 0 & r \ge r_{\mathrm{max}} \\ \end{cases}\end{split}\]where \(\vec{r}\) is the vector pointing from one particle to the other in the bond.
Warning
Bonds that stretch to a length \(r \ge r_{\mathrm{max}}\) result in an error.
Provide \(F_\mathrm{table}(r)\) and \(U_\mathrm{table}(r)\) on evenly spaced grid points points between \(r_{\mathrm{min}}\) and \(r_{\mathrm{max}}\).
Table
linearly interpolates values when \(r\) lies between grid points and between the last grid point and \(r=r_{\mathrm{max}}\). The force must be specificed commensurate with the potential: \(F = -\frac{\partial U}{\partial r}\).- params
The potential parameters. The dictionary has the following keys:
r_min
(float
, required) - the minimum distance to apply the tabulated potential, corresponding to the first element of the energy and force arrays \([\mathrm{length}]\).r_max
(float
, required) - the minimum distance to apply the tabulated potential, corresponding to the first element of the energy and force arrays \([\mathrm{length}]\).U
((width,)numpy.ndarray
offloat
, required) - the tabulated energy values \([\mathrm{energy}]\). Must have a size equal towidth
.F
((width,)numpy.ndarray
offloat
, required) - the tabulated force values \([\mathrm{force}]\). Must have a size equal towidth
.
- Type
TypeParameter
[bond type
,dict
]
- class hoomd.md.bond.Tether
Bases:
Bond
Tether bond force.
The tethered network is described in Refs. Gompper, G. & Kroll, D. M. Statistical Mechanics of Membranes and Surfaces 2nd edn (eds Nelson, D. R. et al.) 359-426 (World Scientific, 2004) and Noguchi, H. & Gompper, G., Phys. Rev. E 72 011901 (2005).
Tether
computes forces, virials, and energies on all bonds in the simulation state with:\[U(r) = U_{\mathrm{att}}(r) + U_{\mathrm{rep}}(r)\]where \(r\) is the distance from one particle to the other in the bond.
\[\begin{split}U_{\mathrm{att}}(r) = \begin{cases} k_b \frac{\exp(1/(l_{c0}-r)}{l_{max}-r} & r > l_{c0} \\ 0 & r \leq l_{c0} \\ \end{cases}\end{split}\]\[\begin{split}U_{\mathrm{rep}}(r) = \begin{cases} k_b \frac{\exp(1/(r-l_{c1})}{r-l_{min}} & r < l_{c1}\\ 0 & r \ge l_{c1} \end{cases}\end{split}\]\[l_{min} < l_{c1} < l_{c0} < l_{max}\]- params
The parameter of the Tethering potential bonds. The dictionary has the following keys:
k_b
(float
, required) - bond stiffness \([\mathrm{energy}]\)l_min
(float
, required) - minimum bond length \([\mathrm{length}]\)l_c1
(float
, required) - cutoff distance of repulsive part \([\mathrm{length}]\)l_c0
(float
, required) - cutoff distance of attractive part \([\mathrm{length}]\)l_max
(float
, required) - maximum bond length \([\mathrm{length}]\)
- Type
TypeParameter[
bond type
, dict]
Examples:
bond_potential = bond.Tether() bond_potential.params['A-A'] = dict(k_b=10.0, l_min=0.9, l_c1=1.2, l_c0=1.8, l_max=2.1)
md.constrain
Overview
Constraint force base class. |
|
Constrain pairwise particle distances. |
|
Constrain particles in rigid bodies. |
Details
Constraints.
Constraint force classes apply forces and the resulting virial to particles that enforce specific constraints on the positions of the particles. The constraint is satisfied at all times, so there is no potential energy associated with the constraint.
Each constraint removes a number of degrees of freedom from the system.
hoomd.md.compute.ThermodynamicQuantities
accounts for these lost degrees of
freedom when computing kinetic temperature and pressure. See
hoomd.State.update_group_dof
for details on when the degrees of freedom for a
group are calculated.
Warning
Do not apply multiple constraint class instances to the same particle. Each instance solves for its constraints independently.
- class hoomd.md.constrain.Constraint
Bases:
Force
Constraint force base class.
Constraint
is the base class for all constraint forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.md.constrain.Distance(tolerance=0.001)
Bases:
Constraint
Constrain pairwise particle distances.
- Parameters
tolerance (float) – Relative tolerance for constraint violation warnings.
Distance
applies forces between particles that constrain the distances between particles to specific values. The algorithm implemented is described in:M. Yoneya, H. J. C. Berendsen, and K. Hirasawa, “A Non-Iterative Matrix Method for Constraint Molecular Dynamics Simulations,” Molecular Simulation, vol. 13, no. 6, pp. 395–405, 1994.
M. Yoneya, “A Generalized Non-iterative Matrix Method for Constraint Molecular Dynamics Simulations,” Journal of Computational Physics, vol. 172, no. 1, pp. 188–197, Sep. 2001.
Each distance constraint takes the form:
\[\chi_{ij}(r) = \mathrm{minimum\_image}(\vec{r}_j - \vec{r}_i)^2 - d_{ij}^2 = 0\]Where \(i\) and \(j\) are the the particle tags in the
constraint_group
and \(d_{ij}\) is the constraint distance as given by the system state.The method sets the second derivative of the Lagrange multipliers with respect to time to zero, such that both the distance constraints and their time derivatives are conserved within the accuracy of the Velocity Verlet scheme (\(O(\delta t^2)\). It solves the corresponding linear system of equations to determine the force. The constraints are satisfied at \(t + 2 \delta t\), so the scheme is self-correcting and avoids drifts.
Add an instance of
Distance
to the integrator constraints listhoomd.md.Integrator.constraints
to apply the force during the simulation.Warning
In MPI simulations, it is an error when molecules defined by constraints extend over more than half the local domain size because all particles connected through constraints will be communicated between ranks as ghost particles.
Note
tolerance
sets the tolerance to detect constraint violations and issue a warning message. It does not influence the computation of the constraint force.
- class hoomd.md.constrain.Rigid
Bases:
Constraint
Constrain particles in rigid bodies.
Overview
Rigid bodies are defined by a single central particle and a number of constituent particles. All of these are particles in the simulation state and can interact with other particles via forces. The mass and moment of inertia of the central particle set the full mass and moment of inertia of the rigid body (constituent particle mass is ignored).
The central particle is at the center of mass of the rigid body and the particle’s orientation quaternion defines the rotation from the body space into the simulation box. Body space refers to a rigid body viewed in a particular reference frame. In body space, the center of mass of the body is at \((0,0,0)\) and the moment of inertia is diagonal.
Constituent particles
Select one or more particle types in the simulation to use as the central particles. For each rigid body particle type, ou specify the constituent particle position and orientations in body coordinates (see
body
). Then,Rigid
takes control of the constituent particles and sets their position and orientation in the simulation box relative to the position and orientation of the central particle:\[\begin{split}\vec{r}_c &= \vec{r}_b + \mathbf{q}_b \vec{r}_{c,\mathrm{body}} \mathbf{q}_b^* \\ \mathbf{q}_c &= \mathbf{q}_b \mathbf{q}_{c,\mathrm{body}}\end{split}\]where \(\vec{r}_c\) and \(\mathbf{q}_c\) are the position and orientation of a constituent particle in the simulation box, \(\vec{r}_{c,\mathrm{body}}\) and \(\mathbf{q}_{c,\mathrm{body}}\) are the position and orientation of that particle in body coordinates, and \(\vec{r}_b\) and \(\mathbf{q}_b\) are the position and orientation of the central particle of that rigid body.
Rigid
also sets the constituent particle image consistent with the image of the central particle and the location of the constituent particle wrapped back into the box.Rigid
does not modify the constituent particle type ids, charge, or diameter.Warning
Rigid
overwrites the constituent particle positions and orientations. To change the position and orientation of a body, set the desired position and orientation of the central particle and callrun(0)
to triggerRigid
to update the particles.In the simulation state, the
body
particle property defines the particle tag of the central particle:b = body[c]
. In setting thebody
array, set central particles to their tag \(b_i = t_i\), constituent particles to their central particle’s tag \(b_i = t_{center}\), and free particles to -1: \(b_i = -1\). Free particles are particles that are not part of a rigid body.The central particle of a rigid body must have a tag smaller than all of its constituent particles. Constituent particles follow in monotonically increasing tag order, corresponding to the order they are defined in the argument to
Rigid
initialization. The central and constituent particles do not need to be contiguous.Tip
To create constituent particles, initialize a simulation state containing only central particles (but both rigid body and constituent particle types). Then call
create_bodies
to add all the constituent particles to the state.Net force and torque
Rigid
transfers forces, energies, and torques from constituent particles to the central particle and adds them to those from the interaction on the central particle itself. The integration methods use these forces and torques to integrate the equations of motion of the central particles (representing the whole rigid body) forward in time.\[\begin{split}\vec{F}_b' &= \vec{F}_b + \sum_c \vec{F}_c \\ \vec{U}_b' &= U_b + \sum_c U_c \\ \vec{\tau}_b' &= \vec{\tau}_b + \sum_c \vec{\tau}_c + (\mathbf{q}_b \vec{r}_{c,\mathrm{body}} \mathbf{q}_b^*) \times \vec{F}_c\end{split}\]Rigid
also computes the corrected virial accounting for the effective constraint force (see Glaser 2020).Integrating bodies
Set the
rigid
attribute ofhoomd.md.Integrator
to an instance ofRigid
to apply rigid body constraints and apply an integration method (or methods) to the central and non-rigid particles (leave the constituent particles out -Rigid
will set their position and orientation). Most integration methods support the integration of rotational degrees of freedom.Example:
rigid_centers_and_free_filter = hoomd.filter.Rigid( ("center", "free")) langevin = hoomd.md.methods.Langevin( filter=rigid_centers_and_free_filter, kT=1.0)
Thermodynamic quantities of bodies
hoomd.md.compute.ThermodynamicQuantities
computes thermodynamic quantities (temperature, kinetic energy, etc.) over the central and non-rigid particles in the system, ignoring the consitutent particles. The body central particles contribute translational and rotational energies to the total.Continuing simulations with rigid bodies.
To continue a simulation, write the simulation state to a file with
hoomd.write.GSD
and initialize the newSimulation
usingcreate_state_from_gsd
. GSD stores all the particle data fields needed to reconstruct the state of the system, including the body, angular momentum, and orientation of the body. You must specify the same local body space environment tobody
as you did in the earlier simulation - GSD does not store this information.Example:
rigid = constrain.Rigid() rigid.body['A'] = { "constituent_types": ['A_const', 'A_const'], "positions": [(0,0,1),(0,0,-1)], "orientations": [(1.0, 0.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0)], "charges": [0.0, 0.0], "diameters": [1.0, 1.0] } rigid.body['B'] = { "constituent_types": ['B_const', 'B_const'], "positions": [(0,0,.5),(0,0,-.5)], "orientations": [(1.0, 0.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0)], "charges": [0.0, 1.0], "diameters": [1.5, 1.0] } # Can set rigid body definition to be None explicitly. rigid.body["A"] = None
Warning
Rigid
will significantly slow simulation performance when frequently changing rigid body definitions or adding/removing particles from the simulation.- body
body
is a mapping from the central particle type to a body definition represented as a dictionary. The mapping respectsNone
as meaning that the type is not a rigid body center. All types are set toNone
by default. The keys for the body definition are:constituent_types
(list
[str
]): List of types of constituent particles.positions
(list
[tuple
[float
,float
,float
]]): List of relative positions of constituent particles.orientations
(list
[tuple
[float
,float
,float
,float
]]): List of orientations (as quaternions) of constituent particles.charges
(list
[float
]): List of charges of constituent particles.Deprecated since version v3.7.0:
charges
will be removed in v4.diameters
(list
[float
]): List of diameters of constituent particles.Deprecated since version v3.7.0:
diameters
will be removed in v4.
Of these,
Rigid
usespositions
andorientation
to set the constituent particle positions and orientations every time step.create_bodies
usesconstituent_types
,charges
, anddiameters
to populate those particle properties when creating constituent particles.Type:
TypeParameter
[particle_type
,dict
]
- create_bodies(state)
Create rigid bodies from central particles in state.
- Parameters
state (hoomd.State) – The state in which to create rigid bodies.
create_bodies
removes any existing constituent particles and adds new ones based on the body definitions inbody
. It overwrites all existing particlebody
tags in the state.
md.compute
Overview
Compute harmonic averaged thermodynamic properties of particles. |
|
Compute thermodynamic properties of a subset of the system. |
Details
Compute properties of molecular dynamics simulations.
The MD compute classes compute instantaneous properties of the simulation state
and provide results as loggable quantities for use with hoomd.logging.Logger
or by direct access via the Python API.
- class hoomd.md.compute.HarmonicAveragedThermodynamicQuantities(filter, kT, harmonic_pressure=0)
Bases:
Compute
Compute harmonic averaged thermodynamic properties of particles.
- Parameters
filter (hoomd.filter.filter_like) – Particle filter to compute thermodynamic properties for.
kT (float) – Temperature of the system \([\mathrm{energy}]\).
harmonic_pressure (float) – Harmonic contribution to the pressure \([\mathrm{pressure}]\). If omitted, the HMA pressure can still be computed, but will be similar in precision to the conventional pressure.
HarmonicAveragedThermodynamicQuantities
acts on a given subset of particles and calculates harmonically mapped average (HMA) properties of those particles when requested. HMA computes properties more precisely (with less variance) for atomic crystals in NVT simulations. The presence of diffusion (vacancy hopping, etc.) will prevent HMA from providing improvement. HMA tracks displacements from the lattice positions, which are saved either during first call toSimulation.run
or when the compute is first added to the simulation, whichever occurs last.Note
HarmonicAveragedThermodynamicQuantities
is an implementation of the methods section of Sabry G. Moustafa, Andrew J. Schultz, and David A. Kofke. (2015). “Very fast averaging of thermal properties of crystals by molecular simulation”. Phys. Rev. E 92, 043303 doi:10.1103/PhysRevE.92.043303Examples:
hma = hoomd.compute.HarmonicAveragedThermodynamicQuantities( filter=hoomd.filter.Type('A'), kT=1.0)
- filter
Subset of particles compute thermodynamic properties for.
- class hoomd.md.compute.ThermodynamicQuantities(filter)
Bases:
Compute
Compute thermodynamic properties of a subset of the system.
- Parameters
filter (
hoomd.filter
) – Particle filter to compute thermodynamic properties for.
ThermodynamicQuantities
acts on a subset of particles in the system and calculates thermodynamic properties of those particles. Add aThermodynamicQuantities
instance to a logger to save these quantities to a file, seehoomd.logging.Logger
for more details.Note
For compatibility with
hoomd.md.constrain.Rigid
,ThermodynamicQuantities
performs all sums \(\sum_{i \in \mathrm{filter}}\) over free particles and rigid body centers - ignoring constituent particles to avoid double counting.Examples:
f = filter.Type('A') compute.ThermodynamicQuantities(filter=f)
- property degrees_of_freedom
Number of degrees of freedom in the subset \(N_{\mathrm{dof}}\).
\[N_\mathrm{dof} = N_\mathrm{dof, translational} + N_\mathrm{dof, rotational}\]See also
hoomd.State.update_group_dof
describes when \(N_{\mathrm{dof}}\) is updated.(
Loggable
: category=”scalar”)
- property kinetic_energy
Total kinetic energy \(K\) of the subset \([\mathrm{energy}]\).
\[K = K_\mathrm{rotational} + K_\mathrm{translational}\](
Loggable
: category=”scalar”)
- property kinetic_temperature
Instantaneous thermal energy \(kT_k\) of the subset \([\mathrm{energy}]\).
\[kT_k = 2 \cdot \frac{K}{N_{\mathrm{dof}}}\](
Loggable
: category=”scalar”)
- property potential_energy
Potential energy \(U\) that the subset contributes to the system \([\mathrm{energy}]\).
\[U = U_{\mathrm{net},\mathrm{additional}} + \sum_{i \in \mathrm{filter}} U_{\mathrm{net},i},\]where the net energy terms are computed by
hoomd.md.Integrator
over all of the forces inhoomd.md.Integrator.forces
.(
Loggable
: category=”scalar”)
- property pressure
Instantaneous pressure \(P\) of the subset \([\mathrm{pressure}]\).
\[P = \frac{ 2 \cdot K_{\mathrm{translational}} + W_\mathrm{isotropic} }{D \cdot V},\]where \(D\) is the dimensionality of the system, \(V\) is the volume of the simulation box (or area in 2D), and \(W_\mathrm{isotropic}\) is the isotropic virial:
\[\begin{split}W_\mathrm{isotropic} = & \frac{1}{D} \left( W_{\mathrm{net},\mathrm{additional}}^{xx} + W_{\mathrm{net},\mathrm{additional}}^{yy} + W_{\mathrm{net},\mathrm{additional}}^{zz} \right) \\ + & \frac{1}{D} \sum_{i \in \mathrm{filter}} \left( W_\mathrm{{net},i}^{xx} + W_\mathrm{{net},i}^{yy} + W_\mathrm{{net},i}^{zz} \right)\end{split}\]where the net virial terms are computed by
hoomd.md.Integrator
over all of the forces inhoomd.md.Integrator.forces
and \(W^{zz}=0\) in 2D simulations.(
Loggable
: category=”scalar”)
- property pressure_tensor
Instantaneous pressure tensor of the subset \([\mathrm{pressure}]\).
The six components of the pressure tensor are given in the order: (\(P^{xx}\), \(P^{xy}\), \(P^{xz}\), \(P^{yy}\), \(P^{yz}\), \(P^{zz}\)):
\[P^{kl} = \frac{1}{V} \left( W_{\mathrm{net},\mathrm{additional}}^{kl} + \sum_{i \in \mathrm{filter}} m_i \cdot v_i^k \cdot v_i^l + W_{\mathrm{net},i}^{kl} \right),\]where the net virial terms are computed by
hoomd.md.Integrator
over all of the forces inhoomd.md.Integrator.forces
, \(v_i^k\) is the k-th component of the velocity of particle \(i\) and \(V\) is the total simulation box volume (or area in 2D).(
Loggable
: category=”sequence”)
- property rotational_degrees_of_freedom
Number of rotational degrees of freedom in the subset \(N_\mathrm{dof, rotational}\).
Integration methods (
hoomd.md.methods
) determine the number of degrees of freedom they give to each particle. Each integration method operates on a subset of the system \(\mathrm{filter}_m\) that may be distinct from the subset from the subset given toThermodynamicQuantities
.When
hoomd.md.Integrator.integrate_rotational_dof
isFalse
, \(N_\mathrm{dof, rotational} = 0\). When it isTrue
, the given degrees of freedom depend on the dimensionality of the system.In 2D:
\[N_\mathrm{dof, rotational} = \sum_{m \in \mathrm{methods}} \; \sum_{i \in \mathrm{filter} \cup \mathrm{filter}_m} \left[ I_{z,i} > 0 \right]\]where \(I\) is the particles’s moment of inertia.
In 3D:
\[N_\mathrm{dof, rotational} = \sum_{m \in \mathrm{methods}} \; \sum_{i \in \mathrm{filter} \cup \mathrm{filter}_m} \left[ I_{x,i} > 0 \right] + \left[ I_{y,i} > 0 \right] + \left[ I_{z,i} > 0 \right]\]See also
hoomd.State.update_group_dof
describes when \(N_{\mathrm{dof, rotational}}\) is updated.(
Loggable
: category=”scalar”)
- property rotational_kinetic_energy
Rotational kinetic energy \(K_\mathrm{rotational}\) of the subset \([\mathrm{energy}]\).
\[ \begin{align}\begin{aligned}\begin{split}K_\mathrm{rotational,d} = \frac{1}{2} \sum_{i \in \mathrm{filter}} \begin{cases} \frac{L_{d,i}^2}{I_{d,i}} & I^d_i > 0 \\ 0 & I^d_i = 0 \end{cases}\end{split}\\K_\mathrm{rotational} = K_\mathrm{rotational,x} + K_\mathrm{rotational,y} + K_\mathrm{rotational,z}\end{aligned}\end{align} \]\(I\) is the moment of inertia and \(L\) is the angular momentum in the (diagonal) reference frame of the particle.
(
Loggable
: category=”scalar”)
- property translational_degrees_of_freedom
Number of translational degrees of freedom in the subset \(N_{\mathrm{dof, translational}}\).
When using a single integration method on all particles that is momentum conserving, the center of mass motion is conserved and the number of translational degrees of freedom is:
\[N_\mathrm{dof, translational} = DN - D\frac{N}{N_\mathrm{particles}} - N_\mathrm{constraints}(\mathrm{filter})\]where \(D\) is the dimensionality of the system and \(N_\mathrm{constraints}(\mathrm{filter})\) is the number of degrees of freedom removed by constraints (
hoomd.md.constrain
) in the subset. The fraction \(\frac{N}{N_\mathrm{particles}}\) distributes the momentum conservation constraint evenly whenThermodynamicQuantities
is applied to multiple subsets.When using multiple integration methods, a single integration method on fewer than all particles, or a single integration method that is not momentum conserving,
hoomd.md.Integrator
assumes that linear momentum is not conserved and counts the center of mass motion in the degrees of freedom:\[N_{\mathrm{dof, translational}} = DN - N_\mathrm{constraints}(\mathrm{filter})\](
Loggable
: category=”scalar”)
md.data
Overview
Access HOOMD-Blue force data buffers on the CPU. |
|
Access HOOMD-Blue force data buffers on the GPU. |
|
Access HOOMD-Blue neighbor list data buffers on the CPU. |
|
Access HOOMD-Blue neighbor list data buffers on the GPU. |
Details
Force data local access.
ForceLocalAccess
, ForceLocalAccessGPU
, and related classes provide direct
access to the data buffers managed by hoomd.md.force.Force
. This means that
MPI rank locality must be considered in accessing the arrays in a multi-rank
simulation.
- class hoomd.md.data.ForceLocalAccess(force_obj, state)
Access HOOMD-Blue force data buffers on the CPU.
- force
Local force data. \([\mathrm{force}]\)
- Type
(N_particles, 3)
hoomd.data.array
offloat
- potential_energy
Local potential energy data. \([\mathrm{energy}]\)
- Type
(N_particles,)
hoomd.data.array
offloat
- torque
Local torque data. \([\mathrm{force} \cdot \mathrm{length}]\)
- Type
(N_particles, 3)
hoomd.data.array
offloat
- virial
Local virial data. \([\mathrm{energy}]\)
- Type
(N_particles, 6)
hoomd.data.array
offloat
- class hoomd.md.data.ForceLocalAccessGPU(*args, **kwargs)
Access HOOMD-Blue force data buffers on the GPU.
- force
Local force data. \([\mathrm{force}]\)
- Type
(N_particles, 3)
hoomd.data.array
offloat
- potential_energy
Local potential energy data. \([\mathrm{energy}]\)
- Type
(N_particles,)
hoomd.data.array
offloat
- torque
Local torque data. \([\mathrm{force} \cdot \mathrm{length}]\)
- Type
(N_particles, 3)
hoomd.data.array
offloat
- virial
Local virial data. \([\mathrm{energy}]\)
- Type
(N_particles, 6)
hoomd.data.array
offloat
- class hoomd.md.data.NeighborListLocalAccess(nlist_obj, state)
Access HOOMD-Blue neighbor list data buffers on the CPU.
The internal
NeighborList
implementation of HOOMD is comprised of essentially three array buffers. The buffers are:nlist
: Ragged array of neighbor data.head_list
: Indexes for particles to read from the neighbor list.n_neigh
: Number of neighbors for each particle.
The neighbor indices of particle \(i\) are stored in the slice
nlist[head_list[i]:head_list[i]+n_neigh[i]]
. The result of access outside of these bounds is undefined. Thehalf_nlist
property is used to query whether the neighbor list stores a single copy for each pair (True), or two copies for each pair (False). Under MPI, pairs that cross domains are stored twice, once in each domain rank.- head_list
Local head list.
- Type
(N_particles,)
hoomd.data.array
ofunsigned long
- n_neigh
Number of neighbors.
- Type
(N_particles,)
hoomd.data.array
ofunsigned int
- nlist
Raw neighbor list data.
- Type
(…)
hoomd.data.array
ofunsigned int
- half_nlist
Convenience property to check if the storage mode is ‘half’.
- Type
bool
- class hoomd.md.data.NeighborListLocalAccessGPU(*args, **kwargs)
Access HOOMD-Blue neighbor list data buffers on the GPU.
The internal
NeighborList
implementation of HOOMD is comprised of essentially three array buffers. The buffers are:nlist
: Ragged array of neighbor data.head_list
: Indexes for particles to read from the neighbor list.n_neigh
: Number of neighbors for each particle.
The neighbor indices of particle \(i\) are stored in the slice
nlist[head_list[i]:head_list[i]+n_neigh[i]]
. The result of access outside of these bounds is undefined. Thehalf_nlist
property is used to query whether the neighbor list stores a single copy for each pair (True), or two copies for each pair (False). Under MPI, pairs that cross domains are stored twice, once in each domain rank.- head_list
Local head list.
- Type
(N_particles,)
hoomd.data.array
ofunsigned long
- n_neigh
Number of neighbors.
- Type
(N_particles,)
hoomd.data.array
ofunsigned int
- nlist
Raw neighbor list data.
- Type
(…)
hoomd.data.array
ofunsigned int
- half_nlist
Convenience property to check if the storage mode is ‘half’.
- Type
bool
Modules
md.dihedral
Overview
Base class dihedral force. |
|
Periodic dihedral force. |
|
Periodic dihedral force. |
|
OPLS dihedral force. |
|
Tabulated dihedral force. |
Details
Dihedral forces.
Dihedral force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
Each dihedral is defined by an ordered quadruplet of particle tags in the
hoomd.State
member dihedral_group
. HOOMD-blue does not construct dihedral
groups, users must explicitly define dihedrals in the initial condition.
In the dihedral group (i,j,k,l), \(\phi\) is the signed dihedral angle between the planes passing through (\(\vec{r}_i, \vec{r}_j, \vec{r}_k\)) and (\(\vec{r}_j, \vec{r}_k, \vec{r}_l\)).
Dihedral force classes assign 1/4 of the potential energy to each of the particles in the dihedral group:
and similarly for virials.
Important
There are multiple conventions pertaining to the dihedral angle in the literature. HOOMD-blue utilizes the convention where \(\phi = \pm \pi\) in the anti-parallel stretched state ( /\/ ) and \(\phi = 0\) in the parallel compact state ( |_| ).
- class hoomd.md.dihedral.Dihedral
Bases:
Force
Base class dihedral force.
Dihedral
is the base class for all dihedral forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.md.dihedral.Harmonic
Bases:
Periodic
Periodic dihedral force.
Deprecated since version v3.7.0: Use
Periodic
.
- class hoomd.md.dihedral.OPLS
Bases:
Dihedral
OPLS dihedral force.
OPLS
computes forces, virials, and energies on all dihedrals in the simulation state with:\[U(\phi) = \frac{1}{2}k_1 \left( 1 + \cos\left(\phi \right) \right) + \frac{1}{2}k_2 \left( 1 - \cos\left(2 \phi \right) \right) + \frac{1}{2}k_3 \left( 1 + \cos\left(3 \phi \right) \right) + \frac{1}{2}k_4 \left( 1 - \cos\left(4 \phi \right) \right)\]\(k_n\) are the force coefficients in the Fourier series.
- params
The parameter of the OPLS bonds for each particle type. The dictionary has the following keys:
k1
(float
, required) - force constant of the first term \([\mathrm{energy}]\)k2
(float
, required) - force constant of the second term \([\mathrm{energy}]\)k3
(float
, required) - force constant of the third term \([\mathrm{energy}]\)k4
(float
, required) - force constant of the fourth term \([\mathrm{energy}]\)
- Type
TypeParameter
[dihedral type
,dict
]
Examples:
opls = dihedral.OPLS() opls.params['A-A-A-A'] = dict(k1=1.0, k2=1.0, k3=1.0, k4=1.0)
- class hoomd.md.dihedral.Periodic
Bases:
Dihedral
Periodic dihedral force.
Periodic
computes forces, virials, and energies on all dihedrals in the simulation state with:\[U(\phi) = \frac{1}{2}k \left( 1 + d \cos\left(n \phi - \phi_0 \right) \right)\]- params
The parameter of the harmonic bonds for each dihedral type. The dictionary has the following keys:
k
(float
, required) - potential constant \(k\) \([\mathrm{energy}]\)d
(float
, required) - sign factor \(d\)n
(int
, required) - angle multiplicity factor \(n\)phi0
(float
, required) - phase shift \(\phi_0\) \([\mathrm{radians}]\)
- Type
TypeParameter
[dihedral type
,dict
]
Examples:
harmonic = dihedral.Harmonic() harmonic.params['A-A-A-A'] = dict(k=3.0, d=-1, n=3, phi0=0) harmonic.params['A-B-C-D'] = dict(k=100.0, d=1, n=4, phi0=math.pi/2)
- class hoomd.md.dihedral.Table(width)
Bases:
Dihedral
Tabulated dihedral force.
- Parameters
width (int) – Number of points in the table.
Table
computes computes forces, virials, and energies on all dihedrals in the simulation given the user defined tables \(U\) and \(\tau\).The torque \(\tau\) is:
\[\tau(\phi) = \tau_\mathrm{table}(\phi)\]and the potential \(U(\phi)\) is:
\[U(\phi) = U_\mathrm{table}(\phi)\]Provide \(\tau_\mathrm{table}(\phi)\) and \(U_\mathrm{table}(\phi)\) on evenly spaced grid points points in the range \(\phi \in [-\pi,\pi]\).
Table
linearly interpolates values when \(\phi\) lies between grid points. The torque must be specificed commensurate with the potential: \(\tau = -\frac{\partial U}{\partial \phi}\).- params
The potential parameters. The dictionary has the following keys:
U
((width,)numpy.ndarray
offloat
, required) - the tabulated energy values \([\mathrm{energy}]\). Must have a size equal towidth
.tau
((width,)numpy.ndarray
offloat
, required) - the tabulated torque values \([\mathrm{force} \cdot \mathrm{length}]\). Must have a size equal towidth
.
- Type
TypeParameter
[dihedral type
,dict
]
md.external
External forces for molecular dynamics.
External force classes apply forces to particles that result from an external field as a function of particle position and orientation:
Modules
md.external.field
Overview
Base class external field force. |
|
Electric field force. |
|
One-dimension periodic force. |
Details
External field forces.
- class hoomd.md.external.field.Electric
Electric field force.
Electric
computes forces, and virials, and energies on all particles in the in the simulation state with consistent with:\[U_i = - q_i \vec{E} \cdot \vec{r}_i\]where \(q_i\) is the particle charge and \(\vec{E}\) is the field vector. The field vector \(\vec{E}\) must be set per unique particle type.
- E
The electric field vector \(\vec{E}\) as a tuple \((E_x, E_y, E_z)\) \([\mathrm{energy} \cdot \mathrm{charge}^{-1} \cdot \mathrm{length^{-1}}]\).
Type:
TypeParameter
[particle_type
,tuple
[float
,float
,float
]]
Example:
# Apply an electric field in the x-direction e_field = external.field.Electric() e_field.E['A'] = (1, 0, 0)
- class hoomd.md.external.field.Field
Base class external field force.
External potentials represent forces which are applied to all particles in the simulation by an external agent.
Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
- class hoomd.md.external.field.Periodic
One-dimension periodic force.
Periodic
computes forces and energies that induce a periodic modulation in the particle concentration. The modulation is one-dimensional and extends along the lattice vector \(\mathbf{a}_i\) of the simulation cell. This force can, for example, be used to induce an ordered phase in a block-copolymer melt.The force is computed commensurate with the potential energy:
\[U_i(\vec{r_j}) = A \tanh\left[\frac{1}{2 \pi p w} \cos\left( p \vec{b}_i\cdot\vec{r_j}\right)\right]\]Periodic
results in no virial stress due functional dependence on box scaled coordinates.- params
The
Periodic
external potential parameters. The dictionary has the following keys:A
(float
, required) - Ordering parameter \(A\) \([\mathrm{energy}]\).i
(int
, required) - \(\vec{b}_i\), \(i=0, 1, 2\), is the simulation box’s reciprocal lattice vector in the \(i\) direction \([\mathrm{dimensionless}]\).w
(float
, required) - The interface width \(w\) relative to the distance \(2\pi/|\mathbf{b_i}|\) between planes in the \(i\)-direction \([\mathrm{dimensionless}]\).p
(int
, required) - The periodicity \(p\) of the modulation \([\mathrm{dimensionless}]\).
Type:
TypeParameter
[particle_type
,dict
]
Example:
# Apply a periodic composition modulation along the first lattice vector periodic = external.field.Periodic() periodic.params['A'] = dict(A=1.0, i=0, w=0.02, p=3) periodic.params['B'] = dict(A=-1.0, i=0, w=0.02, p=3)
md.external.wall
Overview
Force-shifted Lennard-Jones wall force. |
|
Gaussian wall force. |
|
Lennard-Jones wall force. |
|
Mie wall force. |
|
Morse wall force. |
|
Yukawa wall force. |
|
Base class wall force. |
Details
Wall forces.
Wall potential classes compute forces, virials, and energies between all particles and the given walls consistent with the energy:
where \(d_i\) is the signed distance between particle \(i\) and the wall \(w\).
The potential \(U_w(d)\) is a function of the signed cutoff distance between
the particle and a wall’s surface \(d\). The resulting force \(\vec{F}\)
is is parallel to \(\vec{d}\), the vector pointing from the closest point on
the wall’s surface to the particle. \(U_w(d)\) is related to a pair
potential \(U_{\mathrm{pair}}\) as defined below and each subclass of
WallPotential
implements a different functional form of
\(U_{\mathrm{pair}}\).
Walls are two-sided surfaces with positive signed distances to points on the
active side of the wall and negative signed distances to points on the inactive
side. Additionally, the wall’s mode controls how forces and energies are
computed for particles on or near the inactive side. The inside
flag (or
normal
in the case of hoomd.wall.Plane
) determines which side of the
surface is active.
Standard Mode
In the standard mode, when \(r_{\mathrm{extrap}} \le 0\), the potential
energy is only computed on the active side. \(U(d)\) is evaluated in the
same manner as when the mode is shift for the analogous pair
potentials within the boundaries of the active space:
For open=True
spaces:
For open=False
(closed) spaces:
Below we show the potential for a hoomd.wall.Sphere
with radius 5 in 2D,
using the Gaussian potential with \(\epsilon=1, \sigma=1\) and
inside=True
:
When inside=False
, the potential becomes:
Extrapolated Mode:
The wall potential can be linearly extrapolated starting at \(d = r_{\mathrm{extrap}}\) on the active side and continuing to the inactive side. This can be useful to move particles from the inactive side to the active side.
The extrapolated potential has the following form:
where \(\vec{n}\) is such that the force points towards the active space for repulsive potentials. This gives an effective force on the particle due to the wall:
Below is an example of extrapolation with r_extrap=1.1
for a LJ
potential with \(\epsilon=1, \sigma=1\).
To use extrapolated mode r_extrap
must be set per particle type.
Attention
Walls are fixed in space and do not adjust with the box size. For example, NPT simulations may not behave as expected.
Note
The virial due to walls is computed, but the pressure computed and reported by
hoomd.md.compute.ThermodynamicQuantities
is not well defined. The volume (or area) of the box enters into the pressure computation, which is not correct in a confined system. It may not even be possible to define an appropriate volume with soft walls.An effective use of wall forces requires considering the geometry of the system. Each wall is only evaluated in one simulation box and thus is not periodic. Forces will be evaluated and added to all particles from all walls. Additionally there are no safeguards requiring a wall to exist inside the box to have interactions. This means that an attractive force existing outside the simulation box would pull particles across the periodic boundary where they would immediately cease to have any interaction with that wall. It is therefore up to the user to use walls in a physically meaningful manner. This includes the geometry of the walls, their interactions, and as noted here their location.
When \(r_{\mathrm{cut}} \le 0\) or is set to
False
the particle type wall interaction is excluded.While wall potentials are based on the same potential energy calculations as pair potentials, features of pair potentials such as specified neighborlists, and alternative force shifting modes are not supported.
- class hoomd.md.external.wall.ForceShiftedLJ(walls)
Force-shifted Lennard-Jones wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Force-shifted Lennard-Jones force. See
hoomd.md.pair.ForceShiftedLJ
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] shifted_lj_wall = hoomd.md.external.wall.ForceShiftedLJ( walls=walls) shifted_lj_wall.params['A'] = { "epsilon": 1.0, "sigma": 1.0, "r_cut": 3.0} shifted_lj_wall.params[['A','B']] = { "epsilon": 0.5, "sigma": 3.0, "r_cut": 3.2}
- walls
A list of wall definitions to use for the force.
- Type
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential, defaults to 0 \([\mathrm{length}]\)
Type:
TypeParameter
[particle_types
,dict
]
- class hoomd.md.external.wall.Gauss(walls)
Gaussian wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Gaussian force. See
hoomd.md.pair.Gauss
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] gaussian_wall = hoomd.md.external.wall.Gauss(walls=walls) gaussian_wall.params['A'] = {"epsilon": 1.0, "sigma": 1.0, "r_cut": 2.5} gaussian_wall.params[['A','B']] = { "epsilon": 2.0, "sigma": 1.0, "r_cut": 1.0}
- walls
A list of wall definitions to use for the force.
- Type
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential \([\mathrm{length}]\), defaults to 0.
Type:
TypeParameter
[particle_types
,dict
]
- class hoomd.md.external.wall.LJ(walls)
Lennard-Jones wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Lennard-Jones force. See
hoomd.md.pair.LJ
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] lj = hoomd.md.external.wall.LJ(walls=walls) lj.params['A'] = {"sigma": 1.0, "epsilon": 1.0, "r_cut": 2.5} lj.params[['A','B']] = {"epsilon": 2.0, "sigma": 1.0, "r_cut": 2.8} lj.params["A"] = {"r_extrap": 1.1}
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential, defaults to 0 \([\mathrm{length}]\).
Type:
TypeParameter
[particle_types
,dict
]
- class hoomd.md.external.wall.Mie(walls)
Mie wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Mie force. See
hoomd.md.pair.Mie
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] mie_wall = hoomd.md.external.wall.Mie(walls=walls) mie_wall.params['A'] = { "epsilon": 1.0, "sigma": 1.0, "n": 12, "m": 6, "r_cut": 3.0} mie_wall.params[['A','B']] = { "epsilon": 0.5, "sigma": 3.0, "n": 49, "m": 50, "r_cut": 3.2}
- walls
A list of wall definitions to use for the force.
- Type
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential, defaults to 0 \([\mathrm{length}]\)
Type:
TypeParameter
[particle_types
,dict
]
- class hoomd.md.external.wall.Morse(walls)
Morse wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Morse force. See
hoomd.md.pair.Morse
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] morse_wall = hoomd.md.external.wall.Morse(walls=walls) morse_wall.params['A'] = { "D0": 1.0, "alpha": 1.0, "r0": 1.0, "r_cut": 3.0} morse_wall.params[['A','B']] = { "D0": 0.5, "alpha": 3.0, "r0": 1.0, "r_cut": 3.2}
- walls
A list of wall definitions to use for the force.
- Type
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential, defaults to 0 \([\mathrm{length}]\)
Type:
TypeParameter
[particle_types
,dict
]
- class hoomd.md.external.wall.WallPotential(walls)
Base class wall force.
Warning
WallPotential
should not be used directly. It is a base class that provides features and documentation common to all standard wall potentials.- property walls
The walls associated with this wall potential.
- Type
- class hoomd.md.external.wall.Yukawa(walls)
Yukawa wall force.
- Parameters
walls (
list
[hoomd.wall.WallGeometry
]) – A list of wall definitions to use for the force.
Wall force evaluated using the Yukawa force. See
hoomd.md.pair.Yukawa
for the functional form of the force and parameter definitions.Example:
walls = [hoomd.wall.Sphere(radius=4.0)] yukawa_wall = hoomd.md.external.wall.Yukawa(walls=walls) yukawa_wall.params['A'] = { "epsilon": 1.0, "kappa": 1.0, "r_cut": 3.0} yukawa_wall.params[['A','B']] = { "epsilon": 0.5, "kappa": 3.0, "r_cut": 3.2}
- walls
A list of wall definitions to use for the force.
- Type
- params
The potential parameters per type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)r_cut
(float
, required) - The cut off distance for the wall potential \([\mathrm{length}]\)r_extrap
(float
, optional) - The distance to extrapolate the potential, defaults to 0 \([\mathrm{length}]\)
Type:
TypeParameter
[particle_types
,dict
]
md.force
Overview
Defines a force for molecular dynamics simulations. |
|
Active force. |
|
Active force on a manifold. |
|
Constant force. |
|
Custom forces implemented in python. |
Details
Apply forces to particles.
- class hoomd.md.force.Force
Defines a force for molecular dynamics simulations.
Force
is the base class for all molecular dynamics forces and provides common methods.A
Force
class computes the force and torque on each particle in the simulation state \(\vec{F}_i\) and \(\vec{\tau}_i\). With a few exceptions (noted in the documentation of the specific force classes),Force
subclasses also compute the contribution to the system’s potential energy \(U\) and the the virial tensor \(W\).Force
breaks the computation of the total system \(U\) and \(W\) into per-particle and additional terms as detailed in the documentation for each specificForce
subclass.\[\begin{split}U & = U_\mathrm{additional} + \sum_{i=0}^{N_\mathrm{particles}-1} U_i \\ W & = W_\mathrm{additional} + \sum_{i=0}^{N_\mathrm{particles}-1} W_i\end{split}\]Force
represents virial tensors as six element arrays listing the components of the tensor in this order:\[(W^{xx}, W^{xy}, W^{xz}, W^{yy}, W^{yz}, W^{zz}).\]The components of the virial tensor for a force on a single particle are:
\[W^{kl}_i = F^k \cdot r_i^l\]where the superscripts select the x,y, and z components of the vectors. To properly account for periodic boundary conditions, pairwise interactions evaluate the virial:
\[W^{kl}_i = \sum_j F^k_{ij} \cdot \mathrm{minimum\_image}(\vec{r}_j - \vec{r}_i)^l\]Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- property additional_energy
Additional energy term \(U_\mathrm{additional}\) \([\mathrm{energy}]\).
(
Loggable
: category=”scalar”)- Type
- property additional_virial
Additional virial tensor term \(W_\mathrm{additional}\) \([\mathrm{energy}]\).
(
Loggable
: category=”sequence”)- Type
(1, 6)
numpy.ndarray
offloat
- property cpu_local_force_arrays
Expose force arrays on the CPU.
Provides direct access to the force, potential energy, torque, and virial data of the particles in the system on the cpu through a context manager. All data is MPI rank-local.
The
hoomd.md.data.ForceLocalAccess
object returned by this property has four arrays through which one can modify the force data:Note
The local arrays are read only for built-in forces. Use
Custom
to implement custom forces.Examples:
with self.cpu_local_force_arrays as arrays: arrays.force[:] = ... arrays.potential_energy[:] = ... arrays.torque[:] = ... arrays.virial[:] = ...
- property energies
Energy contribution \(U_i\) from each particle \([\mathrm{energy}]\).
Attention
In MPI parallel execution, the array is available on rank 0 only.
energies
isNone
on ranks >= 1.(
Loggable
: category=”particle”)- Type
(N_particles, )
numpy.ndarray
offloat
- property energy
The potential energy \(U\) of the system from this force \([\mathrm{energy}]\).
(
Loggable
: category=”scalar”)- Type
- property forces
The force \(\vec{F}_i\) applied to each particle \([\mathrm{force}]\).
Attention
In MPI parallel execution, the array is available on rank 0 only.
forces
isNone
on ranks >= 1.(
Loggable
: category=”particle”)- Type
(N_particles, 3)
numpy.ndarray
offloat
- property gpu_local_force_arrays
Expose force arrays on the GPU.
Provides direct access to the force, potential energy, torque, and virial data of the particles in the system on the gpu through a context manager. All data is MPI rank-local.
The
hoomd.md.data.ForceLocalAccessGPU
object returned by this property has four arrays through which one can modify the force data:Note
The local arrays are read only for built-in forces. Use
Custom
to implement custom forces.Examples:
with self.gpu_local_force_arrays as arrays: arrays.force[:] = ... arrays.potential_energy[:] = ... arrays.torque[:] = ... arrays.virial[:] = ...
Note
GPU local force data is not available if the chosen device for the simulation is
hoomd.device.CPU
.
- property torques
The torque \(\vec{\tau}_i\) applied to each particle \([\mathrm{force} \cdot \mathrm{length}]\).
Attention
In MPI parallel execution, the array is available on rank 0 only.
torques
isNone
on ranks >= 1.(
Loggable
: category=”particle”)- Type
(N_particles, 3)
numpy.ndarray
offloat
- property virials
Virial tensor contribution \(W_i\) from each particle \([\mathrm{energy}]\).
Attention
To improve performance
Force
objects only compute virials when needed. When not computed,virials
isNone
. Virials are computed on every step when using amd.methods.NPT
ormd.methods.NPH
integrator, on steps where a writer is triggered (such aswrite.GSD
which may log pressure or virials), or whenSimulation.always_compute_pressure
isTrue
.Attention
In MPI parallel execution, the array is available on rank 0 only.
virials
isNone
on ranks >= 1.(
Loggable
: category=”particle”)- Type
(N_particles, 6)
numpy.ndarray
offloat
- class hoomd.md.force.Active(filter)
Bases:
Force
Active force.
- Parameters
filter (
hoomd.filter
) – Subset of particles on which to apply active forces.
Active
computes an active force and torque on all particles selected by the filter:\[\begin{split}\vec{F}_i = \mathbf{q}_i \vec{f}_i \mathbf{q}_i^* \\ \vec{\tau}_i = \mathbf{q}_i \vec{u}_i \mathbf{q}_i^*,\end{split}\]where \(\vec{f}_i\) is the active force in the local particle coordinate system (set by type
active_force
) and \(\vec{u}_i\) is the active torque in the local particle coordinate system (set by type inactive_torque
.Note
To introduce rotational diffusion to the particle orientations, use
create_diffusion_updater
.Examples:
all = hoomd.filter.All() active = hoomd.md.force.Active( filter=hoomd.filter.All() ) active.active_force['A','B'] = (1,0,0) active.active_torque['A','B'] = (0,0,0) rotational_diffusion_updater = active.create_diffusion_updater( trigger=10) sim.operations += rotational_diffusion_updater
Note
The energy and virial associated with the active force are 0.
- filter
Subset of particles on which to apply active forces.
- Type
- active_force
Active force vector in the local reference frame of the particle \([\mathrm{force}]\). It is defined per particle type and stays constant during the simulation.
Type:
TypeParameter
[particle_type
,tuple
[float
,float
,float
]]
- active_torque
Active torque vector in the local reference frame of the particle \([\mathrm{force} \cdot \mathrm{length}]\). It is defined per particle type and stays constant during the simulation.
Type:
TypeParameter
[particle_type
,tuple
[float
,float
,float
]]
- create_diffusion_updater(trigger, rotational_diffusion)
Create a rotational diffusion updater for this active force.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps to update rotational diffusion.
rotational_diffusion (hoomd.variant.variant_like) – The rotational diffusion as a function of time or a constant.
- Returns
The rotational diffusion updater.
- Return type
- class hoomd.md.force.ActiveOnManifold(filter, manifold_constraint)
Bases:
Active
Active force on a manifold.
- Parameters
filter (
hoomd.filter
) – Subset of particles on which to apply active forces.manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
ActiveOnManifold
computes a constrained active force and torque on all particles selected by the filter similar toActive
.ActiveOnManifold
restricts the forces to the local tangent plane of the manifold constraint. For more information seeActive
.Hint
Use
ActiveOnManifold
with amd.methods.rattle
integration method with the same manifold constraint.Note
To introduce rotational diffusion to the particle orientations, use
create_diffusion_updater
. The rotational diffusion occurs in the local tangent plane of the manifold.Examples:
all = filter.All() sphere = hoomd.md.manifold.Sphere(r=10) active = hoomd.md.force.ActiveOnManifold( filter=hoomd.filter.All(), rotation_diff=0.01, manifold_constraint = sphere ) active.active_force['A','B'] = (1,0,0) active.active_torque['A','B'] = (0,0,0)
- filter
Subset of particles on which to apply active forces.
- Type
- manifold_constraint
Manifold constraint.
- active_force
Active force vector in the local reference frame of the particle \([\mathrm{force}]\). It is defined per particle type and stays constant during the simulation.
Type:
TypeParameter
[particle_type
,tuple
[float
,float
,float
]]
- active_torque
Active torque vector in local reference frame of the particle \([\mathrm{force} \cdot \mathrm{length}]\). It is defined per particle type and stays constant during the simulation.
Type:
TypeParameter
[particle_type
,tuple
[float
,float
,float
]]
- create_diffusion_updater(trigger, rotational_diffusion)
Create a rotational diffusion updater for this active force.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps to update rotational diffusion.
rotational_diffusion (hoomd.variant.variant_like) – The rotational diffusion as a function of time or a constant.
- Returns
The rotational diffusion updater.
- Return type
- class hoomd.md.force.Constant(filter)
Constant force.
- Parameters
filter (
hoomd.filter
) – Subset of particles on which to apply constant forces.
Constant
applies a type dependent constant force and torque on all particles selected by the filter.Constant
sets the force and torque to(0,0,0)
for particles not selected by the filter.Examples:
constant = hoomd.md.force.Constant( filter=hoomd.filter.All() ) constant.constant_force['A'] = (1,0,0) constant.constant_torque['A'] = (0,0,0)
Note
The energy and virial associated with the constant force are 0.
- filter
Subset of particles on which to apply constant forces.
- Type
- class hoomd.md.force.Custom(aniso=False)
Custom forces implemented in python.
Derive a custom force class from
Custom
, and override theset_forces
method to compute forces on particles. Users have direct, zero-copy access to the C++ managed buffers via either thecpu_local_force_arrays
orgpu_local_force_arrays
property. Choose the property that corresponds to the device you wish to alter the data on. In addition to zero-copy access to force buffers, custom forces have access to the local snapshot API via the_state.cpu_local_snapshot
or the_state.gpu_local_snapshot
property.See also
See the documentation in
hoomd.State
for more information on the local snapshot API.Examples:
class MyCustomForce(hoomd.force.Custom): def __init__(self): super().__init__(aniso=True) def set_forces(self, timestep): with self.cpu_local_force_arrays as arrays: arrays.force[:] = -5 arrays.torque[:] = 3 arrays.potential_energy[:] = 27 arrays.virial[:] = np.arange(6)[None, :]
In addition, since data is MPI rank-local, there may be ghost particle data associated with each rank. To access this read-only ghost data, access the property name with either the prefix
ghost_
of the suffix_with_ghost
.Note
Pass
aniso=True
to themd.force.Custom
constructor if your custom force produces non-zero torques on particles.Examples:
class MyCustomForce(hoomd.force.Custom): def __init__(self): super().__init__() def set_forces(self, timestep): with self.cpu_local_force_arrays as arrays: # access only the ghost particle forces ghost_force_data = arrays.ghost_force # access torque data on this rank and ghost torque data torque_data = arrays.torque_with_ghost
Note
When accessing the local force arrays, always use a context manager.
Note
The shape of the exposed arrays cannot change while in the context manager.
Note
All force data buffers are MPI rank local, so in simulations with MPI, only the data for a single rank is available.
Note
Access to the force buffers is constant (O(1)) time.
Changed in version 3.1.0:
Custom
zeros the force, torque, energy, and virial arrays before calling the user-providedset_forces
.
md.improper
Overview
Base class improper force. |
|
Harmonic improper force. |
Details
Improper forces.
Improper force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
Each improper is defined by an ordered quadruplet of particle tags in the
hoomd.State
member improper_group
. HOOMD-blue does not construct improper
groups, users must explicitly define impropers in the initial condition.
In an improper group (i,j,k,l), \(\chi\) is the signed improper angle between the planes passing through (\(\vec{r}_i, \vec{r}_j, \vec{r}_k\)) and (\(\vec{r}_j, \vec{r}_k, \vec{r}_l\)). This is the same definition used in dihedrals. Typically, researchers use impropers to force molecules to be planar.
Improper force classes assign 1/4 of the potential energy to each of the particles in the improper group:
and similarly for virials.
- class hoomd.md.improper.Harmonic
Bases:
Improper
Harmonic improper force.
Harmonic
computes forces, virials, and energies on all impropers in the simulation state with:\[U(r) = \frac{1}{2}k \left( \chi - \chi_{0} \right )^2\]- params
The parameter of the harmonic impropers for each improper type. The dictionary has the following keys:
k
(float
, required), potential constant \(k\) \([\mathrm{energy}]\).chi0
(float
, required), equilibrium angle \(\chi_0\) \([\mathrm{radian}]\).
- Type
TypeParameter
[improper type
,dict
]
Example:
harmonic = hoomd.md.improper.Harmonic() harmonic.params['A-B-C-D'] = dict(k=1.0, chi0=0)
- class hoomd.md.improper.Improper
Bases:
Force
Base class improper force.
Improper
is the base class for all improper forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
md.long_range
Overview
Details
Long-range potentials for molecular dynamics.
Modules
md.long_range.pppm
Overview
Reciprocal space part of the PPPM Coulomb forces. |
|
Long range Coulomb interactions evaluated using the PPPM method. |
Details
Long-range potentials evaluated using the PPPM method.
- class hoomd.md.long_range.pppm.Coulomb(nlist, resolution, order, r_cut, alpha, pair_force)
Bases:
Force
Reciprocal space part of the PPPM Coulomb forces.
Note
Use
make_pppm_coulomb_forces
to create a connected pair ofmd.pair.Ewald
andmd.long_range.pppm.Coulomb
instances that together implement the PPPM method for electrostatics.- resolution
Number of grid points in the x, y, and z directions \(\mathrm{[dimensionless]}\).
- order
Number of grid points in each direction to assign charges to \(\mathrm{[dimensionless]}\).
- Type
- r_cut
Cutoff distance between the real space and reciprocal space terms \(\mathrm{[length]}\).
- Type
- property nlist
Neighbor list used to compute the real space term.
- hoomd.md.long_range.pppm.make_pppm_coulomb_forces(nlist, resolution, order, r_cut, alpha=0)
Long range Coulomb interactions evaluated using the PPPM method.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
resolution (tuple[int, int, int]) – Number of grid points in the x, y, and z directions \(\mathrm{[dimensionless]}\).
order (int) – Number of grid points in each direction to assign charges to \(\mathrm{[dimensionless]}\).
r_cut (float) – Cutoff distance between the real space and reciprocal space terms \(\mathrm{[length]}\).
alpha (float) – Debye screening parameter \(\mathrm{[length^{-1}]}\).
Evaluate the potential energy \(U_\mathrm{coulomb}\) and apply the corresponding forces to the particles in the simulation.
\[U_\mathrm{coulomb} = \frac{1}{2} \sum_\vec{n} \sum_{i=0}^{N-1} \sum_{j=0}^{N-1} u_\mathrm{coulomb}(\vec{r}_j - \vec{r}_i + n_1 \cdot \vec{a}_1 + n_2 \cdot \vec{a}_2 + n_3 \cdot \vec{a}_3, q_i, q_j)\]\[u_\mathrm{coulomb}(\vec{r}, q_i, q_j) = \frac{q_i q_j}{r} e^{-\alpha r}\]where the infinite sum includes all periodic images \(\vec{n}\), \(N\) is the number of particles, \(\vec{r}_i\) is the position of particle \(i\), \(q_i\) is the charge of particle \(i\), \(\alpha\) is the Debye screening parameter, and \(\vec{a}_k\) are the periodic simulation box lattice vectors.
Note
In HOOMD-blue, the \(\frac{1}{4\pi\epsilon_0}\) factor is included in the units of charge.
The particle particle particle mesh (PPPM) method splits this computation into real space and reciprocal space components.
\[U_\mathrm{coulomb} = U_\mathrm{real\ space} + U_\mathrm{reciprocal\ space}\]md.pair.Ewald
to computes the real space term directly andmd.long_range.pppm.Coulomb
computes the reciprocal space term using fast Fourier transforms performed on a charge density grid. The accuracy of the method is sensitive to the cutoff for the real space part, the order of interpolation and grid resolution.J. W. Eastwood, R. W. Hockney, and D. N. Lawrence 1980 describes the algorithm.
D. LeBard et. al. 2012 describes the implementation in HOOMD-blue. Please cite it if you utilize this functionality in your work.
Exclusions
When
nlist
contains exclusions,md.pair.Ewald
skips the computation of the excluded real space particle-particle interactions.md.long_range.pppm.Coulomb
must correct the reciprocal space computation for this. The full energy (Coulomb.energy + Ewald.energy
) is the sum of the following terms:\(U_\mathrm{coulomb,additional}\) (
Coulomb.additional_energy
): Energy from the reciprocal space calculation plus any correction due to'body'
exclusions in the neighbor list.\(U_{\mathrm{coulomb},i}\) (
Coulomb.energies
): Energies from the non-body neighbor list exclusions.\(U_\mathrm{ewald,additional}\) (
Ewald.additional_energy
): 0.\(U_\mathrm{ewald,i}\) (
Ewald.additional_energy
): Energies from the real space calculation for non-excluded particle pairs.
Warning
Do not apply bonds, angles, dihedrals, or impropers between particles in the same rigid body. Doing so will cause the exclusions to be double counted (once in \(U_\mathrm{coulomb,additional}\) and again in \(U_{\mathrm{coulomb},i}\)).
Screening
The Debye screening parameter \(\alpha\) enables the screening of electrostatic interactions with the same functional form as the short range
md.pair.Yukawa
potential. Usemd.long_range.pppm.Coulomb
with a non-zeo \(\alpha\) to compute screened electrostatic interactions when the cutoff is so large that the short ranged interactions are inefficient. See Salin, G and Caillol, J. 2000 for details.Important
In MPI simulations with multiple ranks, the grid resolution must be a power of two in each dimension.
- Returns
real_space_force
,reciprocal_space_force
Add both of these forces to the integrator.
Warning
make_pppm_coulomb_forces
sets all parameters for the returnedForce
objects given the input resolution and order. Do not change the parameters of the returned objects directly.
md.manifold
Overview
Base class manifold object. |
|
Cylinder manifold. |
|
Triply periodic diamond manifold. |
|
Ellipsoid manifold. |
|
Triply periodic gyroid manifold. |
|
Plane manifold. |
|
Triply periodic primitive manifold. |
|
Sphere manifold. |
Details
Manifolds.
A Manifold
defines a lower dimensional manifold embedded in 3D space with an
implicit function \(F(x,y,z) = 0\). Use Manifold
classes to define
positional constraints to a given set of particles with:
- class hoomd.md.manifold.Cylinder(r, P=(0, 0, 0))
Bases:
Manifold
Cylinder manifold.
- Parameters
Cylinder
defines a right circular cylinder along the z axis:\[F(x,y,z) = (x - P_x)^{2} + (y - P_y)^{2} - r^{2}\]Example:
cylinder1 = manifold.Cylinder(r=10) cylinder2 = manifold.Cylinder(r=5,P=(1,1,1))
- class hoomd.md.manifold.Diamond(N, epsilon=0)
Bases:
Manifold
Triply periodic diamond manifold.
- Parameters
Diamond
defines a periodic diamond surface . The diamond (or Schwarz D) belongs to the family of triply periodic minimal surfaces:\[F(x,y,z) = \cos{\frac{2 \pi}{B_x} x} \cdot \cos{\frac{2 \pi}{B_y} y} \cdot \cos{\frac{2 \pi}{B_z} z} - \sin{\frac{2 \pi}{B_x} x} \cdot \sin{\frac{2 \pi}{B_y} y} \cdot \sin{\frac{2 \pi}{B_z} z} - \epsilon\]is the nodal approximation of the diamond surface where \([B_x,B_y,B_z]\) is the periodicity length in the x, y and z direction. The periodicity length B is defined by the current box size L and the number of unit cells N \(B_i=\frac{L_i}{N_i}\).
Example:
diamond1 = manifold.Diamond(N=1) diamond2 = manifold.Diamond(N=(1,2,2))
- class hoomd.md.manifold.Ellipsoid(a, b, c, P=(0, 0, 0))
Bases:
Manifold
Ellipsoid manifold.
- Parameters
a (float) – length of the a-axis of the ellipsoidal constraint \([\mathrm{length}]\).
b (float) – length of the b-axis of the ellipsoidal constraint \([\mathrm{length}]\).
c (float) – length of the c-axis of the ellipsoidal constraint \([\mathrm{length}]\).
P (
tuple
[float
,float
,float
]) – center of the ellipsoid constraint (default origin) \([\mathrm{length}]\).
Ellipsoid
defines an ellipsoid:Implicit function
\[F(x,y,z) = \frac{(x-P_x)^{2}}{a^{2}} + \frac{(y-P_y)^{2}}{b^{2}} + \frac{(z-P_z)^{2}}{c^{2}} - 1\]Example:
ellipsoid1 = manifold.Ellipsoid(a=10,b=5,c=5) ellipsoid2 = manifold.Ellipsoid(a=5,b=10,c=10,P=(1,0.5,1))
- class hoomd.md.manifold.Gyroid(N, epsilon=0)
Bases:
Manifold
Triply periodic gyroid manifold.
- Parameters
Gyroid
defines a periodic gyroid surface. The gyroid belongs to the family of triply periodic minimal surfaces:\[F(x,y,z) = \sin{\frac{2 \pi}{B_x} x} \cdot \cos{\frac{2 \pi}{B_y} y} + \sin{\frac{2 \pi}{B_y} y} \cdot \cos{\frac{2 \pi}{B_z} z} + \sin{\frac{2 \pi}{B_z} z} \cdot \cos{\frac{2 \pi}{B_x} x} - \epsilon\]is the nodal approximation of the diamond surface where \([B_x,B_y,B_z]\) is the periodicity length in the x, y and z direction. The periodicity length B is defined by the current box size L and the number of unit cells N \(B_i=\frac{L_i}{N_i}\).
Example:
gyroid1 = manifold.Gyroid(N=1) gyroid2 = manifold.Gyroid(N=(1,2,2))
- class hoomd.md.manifold.Manifold
Bases:
Base class manifold object.
Warning
Users should not instantiate
Manifold
directly, but should instead instantiate one of its subclasses defining a specific manifold geometry.Warning
Only one manifold can be applied to a given method or active forces.
- __eq__(other)
Test for equality.
- class hoomd.md.manifold.Plane(shift=0)
Bases:
Manifold
Plane manifold.
- Parameters
shift (float) – z-shift of the xy-plane \([\mathrm{length}]\).
Plane
defines an xy-plane at a given value of z:\[F(x,y,z) = z - \textrm{shift}\]Example:
plane1 = manifold.Plane() plane2 = manifold.Plane(shift=0.8)
- class hoomd.md.manifold.Primitive(N, epsilon=0)
Bases:
Manifold
Triply periodic primitive manifold.
- Parameters
Primitive
specifies a periodic primitive surface as a constraint. The primitive (or Schwarz P) belongs to the family of triply periodic minimal surfaces:\[F(x,y,z) = \cos{\frac{2 \pi}{B_x} x} + \cos{\frac{2 \pi}{B_y} y} + \cos{\frac{2 \pi}{B_z} z} - \epsilon\]is the nodal approximation of the diamond surface where \([B_x,B_y,B_z]\) is the periodicity length in the x, y and z direction. The periodicity length B is defined by the current box size L and the number of unit cells N. \(B_i=\frac{L_i}{N_i}\)
Example:
primitive1 = manifold.Primitive(N=1) primitive2 = manifold.Primitive(N=(1,2,2))
md.many_body
Overview
Base class triplet force. |
|
Reversible crosslinker three-body force. |
|
Soft force for simulating a van der Waals liquid. |
|
Tersoff force. |
Details
Implement many body potentials.
Triplet force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
where \(\vec{r}_{ij} = \mathrm{minimum\_image}(\vec{r}_j - \vec{r}_i)\).
Triplet
applies a short range cutoff for performance and assumes that both
\(U(\vec{r}_{ij}, \vec{r}_{ik})\) and its derivatives are 0 when
\(r_{ij} > r_\mathrm{cut}\) or \(r_{ik} > r_\mathrm{cut}\).
Specifically, the force \(\vec{F}\) applied to each particle \(i\) is:
The per particle energy terms are:
- class hoomd.md.many_body.RevCross(nlist, default_r_cut=None)
Bases:
Triplet
Reversible crosslinker three-body force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
RevCross
computes the revcross three-body force on every particle in the simulation state. Despite the fact that the revcross potential accounts for the effects of third bodies, it is actually just a combination of two body potential terms. It can thus use type-pair parameters similar to those of the pair potentials.The RevCross potential has been described in detail in S. Ciarella and W.G. Ellenbroek 2019. It is based on a generalized Lennard-Jones pairwise attraction to form bonds between interacting particles:
\[\begin{split}U_{ij}(r) = \begin{cases} 4 \varepsilon \left[ \left( \dfrac{ \sigma}{r_{ij}} \right)^{2n} - \left( \dfrac{ \sigma}{r_{ij}} \right)^{n} \right] & r < r_\mathrm{cut} \\ 0 & r \ge r_\mathrm{cut} \end{cases}\end{split}\]Then an additional three-body repulsion is evaluated to compensate the bond energies imposing single bond per particle condition:
\[v^{\left( 3b \right)}_{ijk} = \lambda \epsilon \hat{v}^{ \left( 2b \right)}_{ij} \left(\vec{r}_{ij}\right) \cdot \hat{v}^{ \left( 2b \right)}_{ik} \left(\vec{r}_{ik}\right)~,\]where the two body potential is rewritten as:
\[\begin{split}\hat{v}^{ \left( 2b \right)}_{ij}\left(\vec{r}_{ij}\right) = \begin{cases} 1 & r \le r_{min} \\ - \dfrac{v_{ij}\left(\vec{r}_{ij}\right)}{\epsilon} & r > r_{min} \\ \end{cases}\end{split}\]Attention
The RevCross potential models an asymmetric interaction between two different chemical moieties that can form a reversible bond. This requires the definition of (at least) two different types of particles. A reversible bond is only possible between two different species, otherwise \(v^{\left( 3b \right)}_{ijk}\), would prevent any bond. In our example we then set the interactions for types A and B with
rev_c.params[[('A','B'),('A','B')]]
to{"sigma": 0.0, "n": 0, "epsilon": 0, "lambda3": 0}
and the only non-zero energy only between the different types with settingrev_c.params[('A','B')]
to{"sigma":1, "n": 100, "epsilon": 100, "lambda3": 1}
. Notice that the number of the minority species corresponds to the maximum number of bonds.This three-body term also tunes the energy required for a bond swap through the coefficient:- \(\lambda\) - lambda3 (unitless) in S. Ciarella and W.G. Ellenbroek 2019 is explained that setting \(\lambda=1\) corresponds to no energy requirement to initiate bond swap, while this energy barrier scales roughly as \(\beta \Delta E_\text{sw} =\beta \varepsilon(\lambda-1)\).
Note
Choosing \(\lambda=1\) pushes the system to cluster because the three-body term is not enough to compensate the energy of multiple bonds, so it may cause nonphysical situations.
- params
The revcross potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - \(\sigma\) \([\mathrm{length}]\)n
(float
, required) - \(n\) \([\mathrm{dimensionless}]\)lambda3
(float
, required) - \(\lambda_3\) \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
Example:
nl = md.nlist.Cell() bond_swap = md.many_body.RevCross(default_r_cut=1.3,nlist=nl) bond_swap.params[('A', 'A'), ('B', 'B')] = { "sigma":0,"n": 0, "epsilon": 0, "lambda3": 0} # a bond can be made only between A-B and not A-A or B-B bond_swap.params[('A','B')] = { "sigma": 1, "n": 100, "epsilon": 10, "lambda3": 1}
- class hoomd.md.many_body.SquareDensity(nlist, default_r_cut=None)
Bases:
Triplet
Soft force for simulating a van der Waals liquid.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
SquareDensity
that the square density three-body force should on every particle in the simulation state.The self energy per particle takes the form:
\[\Psi^{ex} = B (\rho - A)^2\]which gives a pair-wise additive, three-body force:
\[\vec{f}_{ij} = \left( B (n_i - A) + B (n_j - A) \right) w'_{ij} \vec{e}_{ij}\]Here, \(w_{ij}\) is a quadratic, normalized weighting function,
\[w(x) = \frac{15}{2 \pi r_{c,\mathrm{weight}}^3} (1-r/r_{c,\mathrm{weight}})^2\]The local density at the location of particle i is defined as
\[n_i = \sum\limits_{j\neq i} w_{ij} \left(\big| \vec r_i - \vec r_j \big|\right)\]- params
The SquareDensity potential parameters. The dictionary has the following keys:
A
(float
, required) - \(A\) - mean density (default:0) \([\mathrm{length}^{-2}]\) in 2D and \([\mathrm{length}^{-3}]\) in 3DB
(float
, required) - \(B\) - coefficient of the harmonic density term \([\mathrm{energy} \cdot \mathrm{length}^4]\) in 2D and \([\mathrm{energy} \cdot \mathrm{length}^6]\) in 3D
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
Example:
nl = nlist.Cell() sqd = md.many_body.SquareDensity(nl, default_r_cut=3.0) sqd.params[('A', 'B')] = dict(A=1.0, B=2.0) sqd.params[('B', 'B')] = dict(A=2.0, B=2.0, default_r_on=1.0)
For further details regarding this multibody potential, see
[1] P. B. Warren, “Vapor-liquid coexistence in many-body dissipative particle dynamics” Phys. Rev. E. Stat. Nonlin. Soft Matter Phys., vol. 68, no. 6 Pt 2, p. 066702, 2003.
- class hoomd.md.many_body.Tersoff(nlist, default_r_cut=None)
Bases:
Triplet
Tersoff force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
The Tersoff potential is a bond-order potential based on the Morse potential that accounts for the weakening of individual bonds with increasing coordination number. It does this by computing a modifier to the attractive term of the potential. The modifier contains the effects of third-bodies on the bond energies. The potential also includes a smoothing function around the cutoff. The implemented smoothing function is exponential in nature as opposed to the sinusoid used by J. Tersoff 1988.
Tersoff
computes the Tersoff three-body force on every particle in the simulation state. Despite the fact that the Tersoff potential accounts for the effects of third bodies, the species of the third body is irrelevant. It can thus use type-pair parameters similar to those of the pair potentials:\[U_{ij}(r) = \frac{1}{2} f_C(r_{ij}) \left[f_R(r_{ij}) + b_{ij}f_A(r_{ij})\right]\]where
\[ \begin{align}\begin{aligned}f_R(r) = A_1e^{\lambda_1(r_D-r)}\\f_A(r) = A_2e^{\lambda_2(r_D-r)}\end{aligned}\end{align} \]\[\begin{split}f_C(r) = \begin{cases} 1 & r < r_{\mathrm{cut}} - r_{CT} \\ \exp \left[-\alpha\frac{x(r)^3}{x(r)^3 - 1} \right] & r_{\mathrm{cut}} - r_{CT} < r < r_{\mathrm{cut}} \\ 0 & r > r_{\mathrm{cut}} \end{cases}\end{split}\]\[b_{ij} = (1 + \gamma^n\chi_{ij}^n)^{\frac{-1}{2n}}\]In the definition of \(f_C(r)\), there is a quantity \(x(r)\), which is defined as
\[x(r) = \frac{r - (r_{\mathrm{cut}} - r_{CT})}{r_{CT}}\]which ensures continuity between the different regions of the potential. In the definition of \(b_{ij}\), there is a quantity \(\chi_{ij}\) which is defined as
\[ \begin{align}\begin{aligned}\chi_{ij} = \sum_{k \neq i,j} f_C(r_{ik}) \cdot e^{\lambda_3^3 |r_{ij} - r_{ik}|^3} \cdot g(\theta_{ijk})\\g(\theta_{ijk}) = 1 + \frac{c^2}{d^2} - \frac{c^2}{d^2 + |m - \cos(\theta_{ijk})|^2}\end{aligned}\end{align} \]- params
The Tersoff potential parameters. The dictionary has the following keys:
magnitudes
(tuple[float
,float
]) - \((A_1, A_2)\) - Magnitudes of the repulsive and attractive terms (default: (1.0, 1.0)) \([\mathrm{energy}]\)exp_factors
(tuple[float
,float
]) - \((\lambda_1, \lambda_2)\) - exponential factors of the repulsive and attractive terms (default: 2.0) \([\mathrm{length}^{-1}]\)lambda3
(float
) - \(\lambda_3\) - exponential factor in \(\chi_{ij}\) (default: 0.0) \([\mathrm{length}^{-1}]\)dimer_r
(float
) - \(r_D\) - length shift in attractive and repulsive terms (default: 1.5) \([\mathrm{length}]\)cutoff_thickness
(float
) - \(r_{CT}\) - distance which defines the different regions of the potential (default: 0.2) \([\mathrm{length}]\)alpha
(float
) - \(\alpha\) - decay rate of the cutoff term \(f_C(r)\) (default: 3.0) \([\mathrm{dimensionless}]\)n
(float
) - \(n\) - power in \(b_{ij}\) (default: 0.0) \([\mathrm{dimensionless}]\)gamma
(float
) - \(\gamma\) - coefficient in \(b_{ij}\) (default: 0.0) \([\mathrm{dimensionless}]\)c
(float
) - \(c\) - coefficient in \(g(\theta)\) (default: 0.0) \([\mathrm{dimensionless}]\)d
(float
) - \(d\) - coefficient in \(g(\theta)\) (default: 1.0) \([\mathrm{dimensionless}]\)m
(float
) - \(m\) - coefficient in \(g(\theta)\) (default: 0.0) \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
Example:
nl = md.nlist.Cell() tersoff = md.many_body.Tersoff(default_r_cut=1.3, nlist=nl) tersoff.params[('A', 'B')] = dict(magnitudes=(2.0, 1.0), lambda3=5.0)
- class hoomd.md.many_body.Triplet(nlist, default_r_cut=None)
Bases:
Force
Base class triplet force.
Triplet
is the base class for many-body triplet forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- r_cut
r_cut \([\mathrm{length}]\), optional: defaults to the value
default_r_cut
specified on construction.Type:
TypeParameter
[tuple
[particle_type
,particle_type
],float
])
- nlist
Neighbor list used to compute the triplet potential.
Warning
Currently HOOMD-blue does not support reverse force communication between MPI domains on the GPU. Since reverse force communication is required for the calculation of three-body forces, attempting to use this potential on the GPU with MPI will result in an error.
md.methods
Overview
Base class integration method. |
|
Applies the Berendsen thermostat. |
|
Brownian dynamics. |
|
Newtonian dynamics with a cap on the maximum displacement per time step. |
|
Langevin dynamics. |
|
Constant pressure, constant enthalpy dynamics. |
|
Constant pressure, constant temperature dynamics. |
|
Constant volume, constant energy dynamics. |
|
Constant volume, constant temperature dynamics. |
|
Overdamped viscous dynamics. |
Details
Integration methods for molecular dynamics.
Integration methods work with hoomd.md.Integrator
to define the equations
of motion for the system. Each individual method applies the given equations
of motion to a subset of particles.
Integration methods with constraints
For methods that constrain motion to a manifold see hoomd.md.methods.rattle
- class hoomd.md.methods.Berendsen(filter, kT, tau)
Bases:
Method
Applies the Berendsen thermostat.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
kT (hoomd.variant.variant_like) – Temperature of the simulation. \([energy]\)
tau (float) – Time constant of thermostat. \([time]\)
Berendsen
rescales the velocities of all particles on each time step. The rescaling is performed so that the difference in the current temperature from the set point decays exponentially: Berendsen et. al. 1984.\[\frac{dT_\mathrm{cur}}{dt} = \frac{T - T_\mathrm{cur}}{\tau}\]Attention
Berendsen
does not function with MPI parallel simulations.Attention
Berendsen
does not integrate rotational degrees of freedom.Examples:
berendsen = hoomd.md.methods.Berendsen( filter=hoomd.filter.All(), kT=0.2, tau=10.0) integrator = hoomd.md.Integrator( dt=0.001, methods=[berendsen], forces=[lj])
- filter
Subset of particles to apply this method to.
- kT
Temperature of the simulation. \([energy]\)
- class hoomd.md.methods.Brownian(filter, kT, alpha=None, default_gamma=1.0, default_gamma_r=(1.0, 1.0, 1.0))
Bases:
Method
Brownian dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
kT (hoomd.variant.variant_like) – Temperature of the simulation \([\mathrm{energy}]\).
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to
None
default_gamma (float) – Default drag coefficient for all particle types \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).
default_gamma_r ([
float
,float
,float
]) – Default rotational drag coefficient tensor for all particles \([\mathrm{time}^{-1}]\).
Brownian
integrates particles forward in time according to the overdamped Langevin equations of motion, sometimes called Brownian dynamics or the diffusive limit. It integrates both the translational and rotational degrees of freedom.The translational degrees of freedom follow:
\[ \begin{align}\begin{aligned}\frac{d\vec{r}}{dt} &= \frac{\vec{F}_\mathrm{C} + \vec{F}_\mathrm{R}}{\gamma},\\\langle \vec{F}_\mathrm{R} \rangle &= 0,\\\langle |\vec{F}_\mathrm{R}|^2 \rangle &= 2 d k T \gamma / \delta t,\\\langle \vec{v}(t) \rangle &= 0,\\\langle |\vec{v}(t)|^2 \rangle &= d k T / m,\end{aligned}\end{align} \]where \(\vec{F}_\mathrm{C} = \vec{F}_\mathrm{net}\) is the net force on the particle from all forces (
hoomd.md.Integrator.forces
) and constraints (hoomd.md.Integrator.constraints
), \(\gamma\) is the translational drag coefficient (gamma
), \(\vec{F}_\mathrm{R}\) is a uniform random force, \(\vec{v}\) is the particle’s velocity, and \(d\) is the dimensionality of the system. The magnitude of the random force is chosen via the fluctuation-dissipation theorem to be consistent with the specified drag and temperature, \(T\).About axes where \(I^i > 0\), the rotational degrees of freedom follow:
\[ \begin{align}\begin{aligned}\frac{d\mathbf{q}}{dt} &= \frac{\vec{\tau}_\mathrm{C} + \vec{\tau}_\mathrm{R}}{\gamma_r},\\\langle \vec{\tau}_\mathrm{R} \rangle &= 0,\\\langle \tau_\mathrm{R}^i \cdot \tau_\mathrm{R}^i \rangle &= 2 k T \gamma_r^i / \delta t,\\\langle \vec{L}(t) \rangle &= 0,\\\langle L^i(t) \cdot L^i(t) \rangle &= k T \cdot I^i,\end{aligned}\end{align} \]where \(\vec{\tau}_\mathrm{C} = \vec{\tau}_\mathrm{net}\), \(\gamma_r^i\) is the i-th component of the rotational drag coefficient (
gamma_r
), \(\tau_\mathrm{R}^i\) is a component of the uniform random the torque, \(L^i\) is the i-th component of the particle’s angular momentum and \(I^i\) is the i-th component of the particle’s moment of inertia. The magnitude of the random torque is chosen via the fluctuation-dissipation theorem to be consistent with the specified drag and temperature, \(T\).Brownian
uses the numerical integration method from I. Snook 2007, The Langevin and Generalised Langevin Approach to the Dynamics of Atomic, Polymeric and Colloidal Systems, section 6.2.5, with the exception that \(\vec{F}_\mathrm{R}\) is drawn from a uniform random number distribution.In Brownian dynamics, particle velocities and angular momenta are completely decoupled from positions. At each time step,
Brownian
draws a new velocity distribution consistent with the current set temperature so thathoomd.md.compute.ThermodynamicQuantities
will report appropriate temperatures and pressures when logged or used by other methods.Brownian dynamics neglects the acceleration term in the Langevin equation. This assumption is valid when overdamped: \(\frac{m}{\gamma} \ll \delta t\). Use
Langevin
if your system is not overdamped.You can set \(\gamma\) in two ways:
Specify \(\alpha\) which scales the particle diameter to \(\gamma = \alpha d_i\).
After the method object is created, specify the attribute
gamma
andgamma_r
for rotational damping or random torque to assign them directly, with independent values for each particle type in the system.
Examples:
brownian = hoomd.md.methods.Brownian(filter=hoomd.filter.All(), kT=0.2, alpha=1.0) integrator = hoomd.md.Integrator(dt=0.001, methods=[brownian], forces=[lj])
Examples of using
gamma
andgamma_r
:brownian = hoomd.md.methods.Brownian(filter=hoomd.filter.All(), kT=0.2) brownian.gamma.default = 2.0 brownian.gamma_r.default = [1.0, 2.0, 3.0]
- filter
Subset of particles to apply this method to.
- kT
Temperature of the simulation \([\mathrm{energy}]\).
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\).
- Type
- class hoomd.md.methods.DisplacementCapped(filter, maximum_displacement: Union[Variant, float])
Bases:
NVE
Newtonian dynamics with a cap on the maximum displacement per time step.
The method employs a maximum displacement allowed each time step. This method can be helpful to relax a system with too much overlaps without “blowing up” the system.
Warning
This method does not conserve energy or momentum.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
maximum_displacement (hoomd.variant.variant_like) – The maximum displacement allowed for a particular timestep \([\mathrm{length}]\).
DisplacementCapped
integrates integrates translational and rotational degrees of freedom using modified microcanoncial dynamics. SeeNVE
for the basis of the algorithm.Examples:
relaxer = hoomd.md.methods.DisplacementCapped( filter=hoomd.filter.All(), maximum_displacement=1e-3) integrator = hoomd.md.Integrator( dt=0.005, methods=[relaxer], forces=[lj])
- filter
Subset of particles on which to apply this method.
- maximum_displacement
The maximum displacement allowed for a particular timestep \([\mathrm{length}]\).
- class hoomd.md.methods.Langevin(filter, kT, alpha=None, tally_reservoir_energy=False, default_gamma=1.0, default_gamma_r=(1.0, 1.0, 1.0))
Bases:
Method
Langevin dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
kT (hoomd.variant.variant_like) – Temperature of the simulation \([\mathrm{energy}]\).
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
tally_reservoir_energy (bool) – When True, track the energy exchange between the thermal reservoir and the particles. Defaults to False \([\mathrm{energy}]\).
default_gamma (float) – Default drag coefficient for all particle types \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).
default_gamma_r ([
float
,float
,float
]) – Default rotational drag coefficient tensor for all particles \([\mathrm{time}^{-1}]\).
Langevin
integrates particles forward in time according to the Langevin equations of motion.The translational degrees of freedom follow:
\[ \begin{align}\begin{aligned}m \frac{d\vec{v}}{dt} &= \vec{F}_\mathrm{C} - \gamma \cdot \vec{v} + \vec{F}_\mathrm{R}\\\langle \vec{F}_\mathrm{R} \rangle &= 0\\\langle |\vec{F}_\mathrm{R}|^2 \rangle &= 2 d kT \gamma / \delta t\end{aligned}\end{align} \]where \(\vec{F}_\mathrm{C}\) is the force on the particle from all potentials and constraint forces, \(\gamma\) is the drag coefficient, \(\vec{v}\) is the particle’s velocity, \(\vec{F}_\mathrm{R}\) is a uniform random force, and \(d\) is the dimensionality of the system (2 or 3). The magnitude of the random force is chosen via the fluctuation-dissipation theorem to be consistent with the specified drag and temperature, \(T\).
About axes where \(I^i > 0\), the rotational degrees of freedom follow:
\[ \begin{align}\begin{aligned}I \frac{d\vec{L}}{dt} &= \vec{\tau}_\mathrm{C} - \gamma_r \cdot \vec{L} + \vec{\tau}_\mathrm{R}\\\langle \vec{\tau}_\mathrm{R} \rangle &= 0,\\\langle \tau_\mathrm{R}^i \cdot \tau_\mathrm{R}^i \rangle &= 2 k T \gamma_r^i / \delta t,\end{aligned}\end{align} \]where \(\vec{\tau}_\mathrm{C} = \vec{\tau}_\mathrm{net}\), \(\gamma_r^i\) is the i-th component of the rotational drag coefficient (
gamma_r
), \(\tau_\mathrm{R}^i\) is a component of the uniform random the torque, \(\vec{L}\) is the particle’s angular momentum and \(I\) is the the particle’s moment of inertia. The magnitude of the random torque is chosen via the fluctuation-dissipation theorem to be consistent with the specified drag and temperature, \(T\).Langevin
numerically integrates the translational degrees of freedom using Velocity-Verlet and the rotational degrees of freedom with a scheme based on Kamberaj 2005.Langevin dynamics includes the acceleration term in the Langevin equation. This assumption is valid when underdamped: \(\frac{m}{\gamma} \gg \delta t\). Use
Brownian
if your system is not underdamped.You can set \(\gamma\) in two ways:
Specify \(\alpha\) which scales the particle diameter to \(\gamma = \alpha d_i\).
After the method object is created, specify the attribute
gamma
andgamma_r
for rotational damping or random torque to assign them directly, with independent values for each particle type in the system.
Examples:
langevin = hoomd.md.methods.Langevin(filter=hoomd.filter.All(), kT=0.2, alpha=1.0) integrator = hoomd.md.Integrator(dt=0.001, methods=[langevin], forces=[lj])
Examples of using
gamma
andgamma_r
:langevin = hoomd.md.methods.Langevin(filter=hoomd.filter.All(), kT=0.2) langevin.gamma.default = 2.0 langevin.gamma_r.default = [1.0,2.0,3.0]
Warning
When restarting a simulation, the energy of the reservoir will be reset to zero.
- filter
Subset of particles to apply this method to.
- kT
Temperature of the simulation \([\mathrm{energy}]\).
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
- Type
- tally_reservoir_energy
When True, track the energy exchange between the thermal reservoir and the particles. \([\mathrm{energy}]\).
- Type
- gamma
The drag coefficient for each particle type. Used when
alpha
isNone
. \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).- Type
TypeParameter[
particle type
,float
]
- gamma_r
The rotational drag coefficient tensor for each particle type \([\mathrm{time}^{-1}]\).
- property reservoir_energy
Energy absorbed by the reservoir \([\mathrm{energy}]\).
Set
tally_reservoir_energy
toTrue
to track the reservoir energy.(
Loggable
: category=”scalar”)
- class hoomd.md.methods.Method
Bases:
AutotunedObject
Base class integration method.
Provides common methods for all subclasses.
Note
Users should use the subclasses and not instantiate
Method
directly.
- class hoomd.md.methods.NPH(filter, S, tauS, couple, box_dof=(True, True, True, False, False, False), rescale_all=False, gamma=0.0)
Bases:
Method
Constant pressure, constant enthalpy dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
S (tuple[hoomd.variant.variant_like, ...] or hoomd.variant.variant_like) –
Stress components set point for the barostat.
In Voigt notation: \([S_{xx}, S_{yy}, S_{zz}, S_{yz}, S_{xz}, S_{xy}]\) \([\mathrm{pressure}]\). In case of isotropic pressure P (\([p, p, p, 0, 0, 0]\)), use
S = p
.tauS (float) – Coupling constant for the barostat \([\mathrm{time}]\).
couple (str) – Couplings of diagonal elements of the stress tensor, can be “none”, “xy”, “xz”,”yz”, or “all”, default to “all”.
box_dof (
tuple
[bool
]) – Box degrees of freedom with six boolean elements corresponding to x, y, z, xy, xz, yz, each. Default to [True,True,True,False,False,False]). If turned on to True, rescale corresponding lengths or tilt factors and components of particle coordinates and velocities.rescale_all (bool) – if True, rescale all particles, not only those in the group, Default to False.
gamma (float) – Dimensionless damping factor for the box degrees of freedom, Default to 0.
NPH
integrates translational and rotational degrees of freedom forward in time in the Isoenthalpic-isobaric ensemble. The barostat is introduced as additional degrees of freedom in the Hamiltonian that couple with the box parameters.The barostat tensor is \(\nu_{\mathrm{ij}}\). Access these quantities
barostat_dof
.See also
Except for the thermostat,
NPH
shares parameters withNPT
. SeeNPT
for descriptions of the coupling and other barostat parameters.Examples:
dt = 0.005 tauS = 1000 * dt nph = hoomd.md.methods.NPH(filter=hoomd.filter.All(), tauS=tauS, S=2.0) # orthorhombic symmetry nph = hoomd.md.methods.NPH(filter=hoomd.filter.All(), tauS=tauS, S=2.0, couple="none") # tetragonal symmetry nph = hoomd.md.methods.NPH(filter=hoomd.filter.All(), tauS=tauS, S=2.0, couple="xy") # triclinic symmetry nph = hoomd.md.methods.NPH(filter=hoomd.filter.All(), tauS=tauS, S=2.0, couple="none", rescale_all=True) integrator = hoomd.md.Integrator(dt=dt, methods=[nph], forces=[lj])
- filter
Subset of particles on which to apply this method.
- S
Stress components set point for the barostat totalling 6 components. In Voigt notation, \([S_{xx}, S_{yy}, S_{zz}, S_{yz}, S_{xz}, S_{xy}]\) \([\mathrm{pressure}]\). Stress can be reset after method object is created. For example, an isotopic pressure can be set by
nph.S = 4.
- Type
- couple
Couplings of diagonal elements of the stress tensor, can be “none”, “xy”, “xz”,”yz”, or “all”.
- Type
- box_dof
Box degrees of freedom with six boolean elements corresponding to x, y, z, xy, xz, yz, each.
- barostat_dof
Additional degrees of freedom for the barostat (\(\nu_{xx}\), \(\nu_{xy}\), \(\nu_{xz}\), \(\nu_{yy}\), \(\nu_{yz}\), \(\nu_{zz}\))
- property barostat_energy
Energy the barostat contributes to the Hamiltonian \([\mathrm{energy}]\).
(
Loggable
: category=”scalar”)
- thermalize_barostat_dof()
Set the barostat momentum to random values.
thermalize_barostat_dof
sets a random value for the barostat \(\nu_{\mathrm{ij}}\). Callthermalize_barostat_dof
to set a new random state for the barostat.Important
You must call
Simulation.run
beforethermalize_barostat_dof
. Callrun(steps=0)
to prepare a newly createdhoomd.Simulation
.See also
- class hoomd.md.methods.NPT(filter, kT, tau, S, tauS, couple, box_dof=[True, True, True, False, False, False], rescale_all=False, gamma=0.0)
Bases:
Method
Constant pressure, constant temperature dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
kT (hoomd.variant.variant_like) – Temperature set point for the thermostat \([\mathrm{energy}]\).
tau (float) – Coupling constant for the thermostat \([\mathrm{time}]\).
S (tuple[hoomd.variant.variant_like, ...] or hoomd.variant.variant_like) –
Stress components set point for the barostat.
In Voigt notation: \([S_{xx}, S_{yy}, S_{zz}, S_{yz}, S_{xz}, S_{xy}]\) \([\mathrm{pressure}]\). In case of isotropic pressure P (\([p, p, p, 0, 0, 0]\)), use
S = p
.tauS (float) – Coupling constant for the barostat \([\mathrm{time}]\).
couple (str) – Couplings of diagonal elements of the stress tensor, can be “none”, “xy”, “xz”,”yz”, or “xyz”.
box_dof (
list
[bool
]) – Box degrees of freedom with six boolean elements corresponding to x, y, z, xy, xz, yz, each. Default to [True,True,True,False,False,False]). If turned on to True, rescale corresponding lengths or tilt factors and components of particle coordinates and velocities.rescale_all (bool) – if True, rescale all particles, not only those in the group, Default to False.
gamma (float) – Dimensionless damping factor for the box degrees of freedom, Default to 0.
NPT
integrates integrates translational and rotational degrees of freedom in the Isothermal-isobaric ensemble. The thermostat and barostat are introduced as additional degrees of freedom in the Hamiltonian that couple with the particle velocities and angular momenta and the box parameters.The translational thermostat has a momentum \(\xi\) and position \(\eta\). The rotational thermostat has momentum \(\xi_{\mathrm{rot}}\) and position \(\eta_\mathrm{rot}\). The barostat tensor is \(\nu_{\mathrm{ij}}\). Access these quantities using
translational_thermostat_dof
,rotational_thermostat_dof
, andbarostat_dof
.By default,
NPT
performs integration in a cubic box under hydrostatic pressure by simultaneously rescaling the lengths Lx, Ly and Lz of the simulation box. Set the integration mode to change this default.The integration mode is defined by a set of couplings and by specifying the box degrees of freedom that are put under barostat control. Couplings define which diagonal elements of the pressure tensor \(P_{\alpha,\beta}\) should be averaged over, so that the corresponding box lengths are rescaled by the same amount.
Valid couplings are:
'none'
(all box lengths are updated independently)'xy`'
(Lx and Ly are coupled)'xz`'
(Lx and Lz are coupled)'yz`'
(Ly and Lz are coupled)'xyz`'
(Lx, Ly, and Lz are coupled)
Degrees of freedom of the box specify which lengths and tilt factors of the box should be updated, and how particle coordinates and velocities should be rescaled. The
box_dof
tuple controls the way the box is rescaled and updated. The first three elementsbox_dof[:3]
controls whether the x, y, and z box lengths are rescaled and updated, respectively. The last three entriesbox_dof[3:]
control the rescaling or the tilt factors xy, xz, and yz. All options also appropriately rescale particle coordinates and velocities.By default, the x, y, and z degrees of freedom are updated.
[True,True,True,False,False,False]
Note
If any of the diagonal x, y, z degrees of freedom is not being integrated, pressure tensor components along that direction are not considered for the remaining degrees of freedom.
For example:
Specifying all couplings and x, y, and z degrees of freedom amounts to cubic symmetry (default)
Specifying xy couplings and x, y, and z degrees of freedom amounts to tetragonal symmetry.
Specifying no couplings and all degrees of freedom amounts to a fully deformable triclinic unit cell
NPT
numerically integrates the equations of motion using the symplectic Martyna-Tobias-Klein equations of motion for NPT. For optimal stability, the update equations leave the phase-space measure invariant and are manifestly time-reversible.See also
Note
The coupling constant
tau
should be set within a reasonable range to avoid abrupt fluctuations in the kinetic temperature and to avoid long time to equilibration. The recommended value for most systems is \(\tau = 100 \delta t\).Note
The barostat coupling constant
tauS
should be set within a reasonable range to avoid abrupt fluctuations in the box volume and to avoid long time to equilibration. The recommend value for most systems is \(\tau_S = 1000 \delta t\).Important
Ensure that your initial condition includes non-zero particle velocities and angular momenta (when appropriate). The coupling between the thermostat and the velocities and angular momenta occurs via multiplication, so
NPT
cannot convert a zero velocity into a non-zero one except through particle collisions.Examples:
npt = hoomd.md.methods.NPT(filter=hoomd.filter.All(), tau=1.0, kT=0.65, tauS = 1.2, S=2.0, couple="xyz") # orthorhombic symmetry npt = hoomd.md.methods.NPT(filter=hoomd.filter.All(), tau=1.0, kT=0.65, tauS = 1.2, S=2.0, couple="none") # tetragonal symmetry npt = hoomd.md.methods.NPT(filter=hoomd.filter.All(), tau=1.0, kT=0.65, tauS = 1.2, S=2.0, couple="xy") # triclinic symmetry npt = hoomd.md.methods.NPT(filter=hoomd.filter.All(), tau=1.0, kT=0.65, tauS = 1.2, S=2.0, couple="none", rescale_all=True) integrator = hoomd.md.Integrator(dt=0.005, methods=[npt], forces=[lj])
- filter
Subset of particles on which to apply this method.
- kT
Temperature set point for the thermostat \([\mathrm{energy}]\).
- S
Stress components set point for the barostat. In Voigt notation, \([S_{xx}, S_{yy}, S_{zz}, S_{yz}, S_{xz}, S_{xy}]\) \([\mathrm{pressure}]\). Stress can be reset after the method object is created. For example, an isotropic pressure can be set by
npt.S = 4.
- Type
- couple
Couplings of diagonal elements of the stress tensor, can be “none”, “xy”, “xz”,”yz”, or “xyz”.
- Type
- box_dof
Box degrees of freedom with six boolean elements corresponding to x, y, z, xy, xz, yz, each.
- translational_thermostat_dof
Additional degrees of freedom for the translational thermostat (\(\xi\), \(\eta\))
- rotational_thermostat_dof
Additional degrees of freedom for the rotational thermostat (\(\xi_\mathrm{rot}\), \(\eta_\mathrm{rot}\))
- barostat_dof
Additional degrees of freedom for the barostat (\(\nu_{xx}\), \(\nu_{xy}\), \(\nu_{xz}\), \(\nu_{yy}\), \(\nu_{yz}\), \(\nu_{zz}\))
- property barostat_energy
Energy the barostat contributes to the Hamiltonian \([\mathrm{energy}]\).
(
Loggable
: category=”scalar”)
- thermalize_thermostat_and_barostat_dof()
Set the thermostat and barostat momenta to random values.
thermalize_thermostat_and_barostat_dof
sets a random value for the momentum \(\xi\) and the barostat \(\nu_{\mathrm{ij}}\). WhenIntegrator.integrate_rotational_dof
isTrue
, it also sets a random value for the rotational thermostat momentum \(\xi_{\mathrm{rot}}\). Callthermalize_thermostat_and_barostat_dof
to set a new random state for the thermostat and barostat.Important
You must call
Simulation.run
beforethermalize_thermostat_and_barostat_dof
. Callrun(steps=0)
to prepare a newly createdhoomd.Simulation
.See also
- class hoomd.md.methods.NVE(filter)
Bases:
Method
Constant volume, constant energy dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
NVE
integrates integrates translational and rotational degrees of freedom in the microcanonical ensemble. The equations of motion are derived from the hamiltonian:\[H = U + K_\mathrm{translational} + K_\mathrm{rotational}\]NVE
numerically integrates the translational degrees of freedom using Velocity-Verlet and the rotational degrees of freedom with a scheme based on Kamberaj 2005.Examples:
nve = hoomd.md.methods.NVE(filter=hoomd.filter.All()) integrator = hoomd.md.Integrator(dt=0.005, methods=[nve], forces=[lj])
- filter
Subset of particles on which to apply this method.
- class hoomd.md.methods.NVT(filter, kT, tau)
Bases:
Method
Constant volume, constant temperature dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
kT (hoomd.variant.variant_like) – Temperature set point for the Nosé-Hoover thermostat \([\mathrm{energy}]\).
tau (float) – Coupling constant for the Nosé-Hoover thermostat \([\mathrm{time}]\).
NVT
integrates integrates translational and rotational degrees of freedom in the canonical ensemble using the Nosé-Hoover thermostat. The thermostat is introduced as additional degrees of freedom in the Hamiltonian that couple with the velocities and angular momenta of the particles.The translational thermostat has a momentum \(\xi\) and position \(\eta\). The rotational thermostat has momentum \(\xi_{\mathrm{rot}}\) and position \(\eta_\mathrm{rot}\). Access these quantities using
translational_thermostat_dof
androtational_thermostat_dof
.NVT
numerically integrates the equations of motion using the symplectic Martyna-Tobias-Klein formalism described refs. G. J. Martyna, D. J. Tobias, M. L. Klein 1994 and J. Cao, G. J. Martyna 1996.Note
The coupling constant
tau
should be set within a reasonable range to avoid abrupt fluctuations in the kinetic temperature and to avoid long time to equilibration. The recommended value for most systems is \(\tau = 100 \delta t\).Important
Ensure that your initial condition includes non-zero particle velocities and angular momenta (when appropriate). The coupling between the thermostat and the velocities and angular momenta occurs via multiplication, so
NVT
cannot convert a zero velocity into a non-zero one except through particle collisions.Examples:
nvt=hoomd.md.methods.NVT(filter=hoomd.filter.All(), kT=1.0, tau=0.5) integrator = hoomd.md.Integrator(dt=0.005, methods=[nvt], forces=[lj])
- filter
Subset of particles on which to apply this method.
- kT
Temperature set point for the Nosé-Hoover thermostat \([\mathrm{energy}]\).
- translational_thermostat_dof
Additional degrees of freedom for the translational thermostat (\(\xi\), \(\eta\))
- rotational_thermostat_dof
Additional degrees of freedom for the rotational thermostat (\(\xi_\mathrm{rot}\), \(\eta_\mathrm{rot}\))
- thermalize_thermostat_dof()
Set the thermostat momenta to random values.
thermalize_thermostat_dof
sets a random value for the momentum \(\xi\). WhenIntegrator.integrate_rotational_dof
isTrue
, it also sets a random value for the rotational thermostat momentum \(\xi_{\mathrm{rot}}\). Callthermalize_thermostat_dof
to set a new random state for the thermostat.Important
You must call
Simulation.run
beforethermalize_thermostat_dof
. Callrun(steps=0)
to prepare a newly createdhoomd.Simulation
.See also
- class hoomd.md.methods.OverdampedViscous(filter, alpha=None, default_gamma=1.0, default_gamma_r=(1.0, 1.0, 1.0))
Bases:
Method
Overdamped viscous dynamics.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to
None
default_gamma (float) – Default drag coefficient for all particle types \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).
default_gamma_r ([
float
,float
,float
]) – Default rotational drag coefficient tensor for all particles \([\mathrm{time}^{-1}]\).
OverdampedViscous
integrates particles forward in time following Newtonian dynamics in the overdamped limit where there is no inertial term. (in the limit that the mass \(m\) and moment of inertia \(I\) go to 0):\[ \begin{align}\begin{aligned}\frac{d\vec{r}}{dt} &= \vec{v}\\\vec{v(t)} &= \frac{\vec{F}_\mathrm{C}}{\gamma}\\\frac{d\mathbf{q}}{dt} &= \vec{\tau}\\\tau^i &= \frac{\tau_\mathrm{C}^i}{\gamma_r^i}\end{aligned}\end{align} \]where \(\vec{F}_\mathrm{C} = \vec{F}_\mathrm{net}\) is the net force on the particle from all forces (
hoomd.md.Integrator.forces
) and constraints (hoomd.md.Integrator.constraints
), \(\gamma\) is the translational drag coefficient (gamma
) \(\vec{v}\) is the particle’s velocity, \(d\) is the dimensionality of the system, \(\tau_\mathrm{C}^i\) is the i-th component of the net torque from all forces and constraints, and \(\gamma_r^i\) is the i-th component of the rotational drag coefficient (gamma_r
).You can set \(\gamma\) in two ways:
Specify \(\alpha\) which scales the particle diameter to \(\gamma = \alpha d_i\).
After the method object is created, specify the attribute
gamma
andgamma_r
for rotational damping or random torque to assign them directly, with independent values for each particle type in the system.
Tip
OverdampedViscous
can be used to simulate systems of athermal active matter, such as athermal Active Brownian Particles.Note
Even though
OverdampedViscous
models systems in the limit that \(m\) and moment of inertia \(I\) go to 0, you must still set non-zero moments of inertia to enable the integration of rotational degrees of freedom.Examples:
odv = hoomd.md.methods.OverdampedViscous(filter=hoomd.filter.All()) odv.gamma.default = 2.0 odv.gamma_r.default = [1.0, 2.0, 3.0]
- filter
Subset of particles to apply this method to.
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\).
- Type
Modules
md.methods.rattle
Overview
Base class RATTLE integration method. |
|
Brownian dynamics with RATTLE constraint. |
|
Newtonian dynamics with a cap on the maximum displacement per time step. |
|
Langevin dynamics with RATTLE constraint. |
|
NVE Integration via Velocity-Verlet with RATTLE constraint. |
|
Overdamped viscous dynamics with RATTLE constraint. |
Details
MD integration methods with manifold constraints.
- class hoomd.md.methods.rattle.Brownian(filter, kT, manifold_constraint, tolerance=1e-06, alpha=None)
Brownian dynamics with RATTLE constraint.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
kT (hoomd.variant.variant_like) – Temperature of the simulation \([\mathrm{energy}]\).
manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter. Defaults to None \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\).
tolerance (float) – Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
Brownian
uses the same integrator ashoomd.md.methods.Brownian
, which follows the overdamped Langevin equations of motion with the additional force term \(- \lambda \vec{F}_\mathrm{M}\). The force \(\vec{F}_\mathrm{M}\) keeps the particles on the manifold constraint, where the Lagrange multiplier \(\lambda\) is calculated via the RATTLE algorithm. For more details about Brownian dynamics seehoomd.md.methods.Brownian
.Examples of using
manifold_constraint
:sphere = hoomd.md.manifold.Sphere(r=10) brownian_rattle = hoomd.md.methods.rattle.Brownian( filter=hoomd.filter.All(), kT=0.2, manifold_constraint=sphere, seed=1, alpha=1.0) integrator = hoomd.md.Integrator(dt=0.001, methods=[brownian_rattle], forces=[lj])
- filter
Subset of particles to apply this method to.
- kT
Temperature of the simulation \([\mathrm{energy}]\).
- manifold_constraint
Manifold constraint which is used by and as a trigger for the RATTLE algorithm of this method.
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
- Type
- tolerance
Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
- Type
- gamma
The drag coefficient can be directly set instead of the ratio of particle diameter (\(\gamma = \alpha d_i\)). The type of
gamma
parameter is either positive float or zero \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).- Type
TypeParameter[
particle type
,float
]
- gamma_r
The rotational drag coefficient can be set. The type of
gamma_r
parameter is a tuple of three float. The type of each element of tuple is either positive float or zero \([\mathrm{force} \cdot \mathrm{length} \cdot \mathrm{radian}^{-1} \cdot \mathrm{time}^{-1}]\).
- class hoomd.md.methods.rattle.DisplacementCapped(filter: Union[ParticleFilter, CustomFilter], maximum_displacement: Union[Variant, float], manifold_constraint: Manifold, tolerance: float = 1e-06)
Newtonian dynamics with a cap on the maximum displacement per time step.
Integration is via a maximum displacement capped Velocity-Verlet with RATTLE constraint. This class is useful to relax a simulation on a manifold.
Warning
This method does not conserve energy or momentum.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
maximum_displacement (hoomd.variant.variant_like) – The maximum displacement allowed for a particular timestep \([\mathrm{length}]\).
manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
tolerance (
float
, optional) – Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
DisplacementCapped
performs constant volume simulations as described inhoomd.md.methods.DisplacementCapped
. In addition the particles are constrained to a manifold by using the RATTLE algorithm.Examples:
sphere = hoomd.md.manifold.Sphere(r=10) relax_rattle = hoomd.md.methods.rattle.DisplacementCapped( filter=hoomd.filter.All(), maximum_displacement=0.01, manifold=sphere) integrator = hoomd.md.Integrator( dt=0.005, methods=[relax_rattle], forces=[lj])
- filter
Subset of particles on which to apply this method.
- maximum_displacement
The maximum displacement allowed for a particular timestep \([\mathrm{length}]\).
- manifold_constraint
Manifold constraint which is used by and as a trigger for the RATTLE algorithm of this method.
- class hoomd.md.methods.rattle.Langevin(filter, kT, manifold_constraint, alpha=None, tally_reservoir_energy=False, tolerance=1e-06)
Langevin dynamics with RATTLE constraint.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
kT (hoomd.variant.variant_like) – Temperature of the simulation \([\mathrm{energy}]\).
manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
tally_reservoir_energy (bool) – If true, the energy exchange between the thermal reservoir and the particles is tracked. Total energy conservation can then be monitored by adding
langevin_reservoir_energy_groupname
to the logged quantities. Defaults to False \([\mathrm{energy}]\).tolerance (float) – Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
Translational degrees of freedom
Langevin
uses the same integrator ashoomd.md.methods.Langevin
, which follows the Langevin equations of motion with the additional force term \(- \lambda \vec{F}_\mathrm{M}\). The force \(\vec{F}_\mathrm{M}\) keeps the particles on the manifold constraint, where the Lagrange multiplier \(\lambda\) is calculated via the RATTLE algorithm. For more details about Langevin dynamics seehoomd.md.methods.Langevin
.Use
Brownian
if your system is not underdamped.Examples:
sphere = hoomd.md.manifold.Sphere(r=10) langevin_rattle = hoomd.md.methods.rattle.Langevin( filter=hoomd.filter.All(), kT=0.2, manifold_constraint=sphere, seed=1, alpha=1.0)
Examples of using
gamma
orgamma_r
on drag coefficient:sphere = hoomd.md.manifold.Sphere(r=10) langevin_rattle = hoomd.md.methods.rattle.Langevin( filter=hoomd.filter.All(), kT=0.2, manifold_constraint = sphere, seed=1, alpha=1.0)
- filter
Subset of particles to apply this method to.
- kT
Temperature of the simulation \([\mathrm{energy}]\).
- manifold_constraint
Manifold constraint which is used by and as a trigger for the RATTLE algorithm of this method.
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
- Type
- tolerance
Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
- Type
- class hoomd.md.methods.rattle.MethodRATTLE(manifold_constraint, tolerance)
Base class RATTLE integration method.
Provides common methods for all integration methods which implement the RATTLE algorithm to constrain particles to a manifold surface.
Warning
The particles should be initialised close to the implicit surface of the manifold. Even though the particles are mapped to the set surface automatically, the mapping can lead to small inter-particle distances and, hence, large forces between particles!
See Also: * Paquay and Kusters 2016
Note
Users should use the subclasses and not instantiate
MethodRATTLE
directly.
- class hoomd.md.methods.rattle.NVE(filter, manifold_constraint, tolerance=1e-06)
NVE Integration via Velocity-Verlet with RATTLE constraint.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this method.
manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
tolerance (float) – Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
NVE
performs constant volume, constant energy simulations as described inhoomd.md.methods.NVE
. In addition the particles are constrained to a manifold by using the RATTLE algorithm.Examples:
sphere = hoomd.md.manifold.Sphere(r=10) nve_rattle = hoomd.md.methods.rattle.NVE( filter=hoomd.filter.All(),maifold=sphere) integrator = hoomd.md.Integrator( dt=0.005, methods=[nve_rattle], forces=[lj])
- filter
Subset of particles on which to apply this method.
- manifold_constraint
Manifold constraint which is used by and as a trigger for the RATTLE algorithm of this method.
- class hoomd.md.methods.rattle.OverdampedViscous(filter, manifold_constraint, tolerance=1e-06, alpha=None)
Overdamped viscous dynamics with RATTLE constraint.
- Parameters
filter (hoomd.filter.filter_like) – Subset of particles to apply this method to.
manifold_constraint (hoomd.md.manifold.Manifold) – Manifold constraint.
alpha (float) – When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter. Defaults to None \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\).
tolerance (float) – Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
OverdampedViscous
uses the same integrator ashoomd.md.methods.OverdampedViscous
, with the additional force term \(- \lambda \vec{F}_\mathrm{M}\). The force \(\vec{F}_\mathrm{M}\) keeps the particles on the manifold constraint, where the Lagrange multiplier \(\lambda\) is calculated via the RATTLE algorithm. For more details about overdamped viscous dynamics seehoomd.md.methods.OverdampedViscous
.Examples of using
manifold_constraint
:sphere = hoomd.md.manifold.Sphere(r=10) odv_rattle = hoomd.md.methods.rattle.OverdampedViscous( filter=hoomd.filter.All(), manifold_constraint=sphere, seed=1, alpha=1.0) integrator = hoomd.md.Integrator( dt=0.001, methods=[odv_rattle], forces=[lj])
- filter
Subset of particles to apply this method to.
- manifold_constraint
Manifold constraint which is used by and as a trigger for the RATTLE algorithm of this method.
- alpha
When set, use \(\alpha d_i\) for the drag coefficient where \(d_i\) is particle diameter \([\mathrm{mass} \cdot \mathrm{length}^{-1} \cdot \mathrm{time}^{-1}]\). Defaults to None.
- Type
- tolerance
Defines the tolerated error particles are allowed to deviate from the manifold in terms of the implicit function. The units of tolerance match that of the selected manifold’s implicit function. Defaults to 1e-6
- Type
- gamma
The drag coefficient can be directly set instead of the ratio of particle diameter (\(\gamma = \alpha d_i\)). The type of
gamma
parameter is either positive float or zero \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\).- Type
TypeParameter[
particle type
,float
]
- gamma_r
The rotational drag coefficient can be set. The type of
gamma_r
parameter is a tuple of three float. The type of each element of tuple is either positive float or zero \([\mathrm{force} \cdot \mathrm{length} \cdot \mathrm{radian}^{-1} \cdot \mathrm{time}^{-1}]\).
md.mesh
Overview
Constructs the bond potential applied to a mesh. |
Details
Mesh potentials for molecular dynamics.
- class hoomd.md.mesh.MeshPotential(mesh)
Constructs the bond potential applied to a mesh.
MeshPotential
is the base class for all bond potentials applied to meshes.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- property mesh
Mesh data structure used to compute the bond potential.
Modules
md.mesh.bond
Overview
FENE and WCA bond potential. |
|
Harmonic bond potential. |
|
Tethering bond potential. |
Details
Mesh Bond forces.
Mesh bond force classes apply a force and virial between every mesh vertex particle and their neighbors based on the given mesh triangulation.
The connectivity and, thus the neighbor set \(\mathrm{Neigh}\) of each vertex particle \(j\) is defined by a mesh triangulation.
See also
See the documentation in hoomd.mesh.Mesh
for more information on the
initialization of the mesh object.
In the mesh bond (j,k), \(r\) is the length of the edge between the mesh vertex particles \(r= |\mathrm{minimum\_image}(\vec{r}_k - \vec{r}_j)|\).
Note
The mesh bond forces are computed over the mesh data structure and not the
separate bond data structure. Hence, the mesh bonds are defined exclusively
by the mesh triangulation as HOOMD-blue automatically constructs the mesh
bond pairs based on triangulation
in the hoomd.mesh.Mesh
object.
The bonds should not be defined separately in the hoomd.State
member
bond_group
!
Mesh bond force classes assign 1/2 of the potential energy to each of the particles in the bond group:
and similarly for virials.
- class hoomd.md.mesh.bond.FENEWCA(mesh)
Bases:
MeshPotential
FENE and WCA bond potential.
FENEWCA
computes forces, virials, and energies on all mesh bonds inmesh
with the harmonic potential (seehoomd.md.bond.FENEWCA
).- Parameters
mesh (hoomd.mesh.Mesh) – Mesh data structure constraint.
- params
The parameter of the FENEWCA potential bonds. The mesh type name defaults to “mesh”. The dictionary has the following keys:
k
(float
, required) - attractive force strength \(k\) \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\).r0
(float
, required) - size parameter \(r_0\) \([\mathrm{length}]\).epsilon
(float
, required) - repulsive force strength \(\varepsilon\) \([\mathrm{energy}]\).sigma
(float
, required) - repulsive force interaction width \(\sigma\) \([\mathrm{length}]\).delta
(float
, required) - radial shift \(\Delta\) \([\mathrm{length}]\).
- Type
TypeParameter[
bond type
, dict]
Examples:
bond_potential = hoomd.md.mesh.bond.FENEWCA(mesh) bond_potential.params["mesh"] = dict(k=10.0, r0=1.0, epsilon=0.8, sigma=1.2, delta=0.0)
- class hoomd.md.mesh.bond.Harmonic(mesh)
Bases:
MeshPotential
Harmonic bond potential.
Harmonic
computes forces, virials, and energies on all mesh bonds inmesh
with the harmonic potential (seehoomd.md.bond.Harmonic
).- Parameters
mesh (hoomd.mesh.Mesh) – Mesh data structure constraint.
- params
The parameter of the harmonic bonds for the defined mesh. The mesh type name defaults to “mesh”. The dictionary has the following keys:
k
(float
, required) - potential constant \([\mathrm{energy} \cdot \mathrm{length}^{-2}]\)r0
(float
, required) - rest length \([\mathrm{length}]\)
- Type
TypeParameter[
mesh name
,dict]
Examples:
harmonic = hoomd.md.mesh.bond.Harmonic(mesh) harmonic.params["mesh"] = dict(k=10.0, r0=1.0)
- class hoomd.md.mesh.bond.Tether(mesh)
Bases:
MeshPotential
Tethering bond potential.
Tether
computes forces, virials, and energies on all mesh bonds inmesh
with the harmonic potential (seehoomd.md.bond.Tether
).- Parameters
mesh (hoomd.mesh.Mesh) – Mesh data structure constraint.
- params
The parameter of the Tether bonds for the defined mesh. The mesh type name defaults to “mesh”. The dictionary has the following keys:
k_b
(float
, required) - bond stiffness \([\mathrm{energy}]\)l_min
(float
, required) - minimum bond length \([\mathrm{length}]\)l_c1
(float
, required) - cutoff distance of repulsive part \([\mathrm{length}]\)l_c0
(float
, required) - cutoff distance of attractive part \([\mathrm{length}]\)l_max
(float
, required) - maximum bond length \([\mathrm{length}]\)
- Type
TypeParameter[
mesh name
,dict]
Examples:
bond_potential = hoomd.md.mesh.bond.Tether(mesh) bond_potential.params["mesh"] = dict(k_b=10.0, l_min=0.9, l_c1=1.2, l_c0=1.8, l_max=2.1)
md.minimize
Overview
Energy Minimizer (FIRE). |
Details
Energy minimizer for molecular dynamics.
- class hoomd.md.minimize.FIRE(dt, force_tol, angmom_tol, energy_tol, integrate_rotational_dof=False, forces=None, constraints=None, methods=None, rigid=None, min_steps_adapt=5, finc_dt=1.1, fdec_dt=0.5, alpha_start=0.1, fdec_alpha=0.99, min_steps_conv=10)
Energy Minimizer (FIRE).
- Parameters
dt (float) – This is the maximum step size the minimizer is permitted to use \([\mathrm{time}]\). Consider the stability of the system when setting.
integrate_rotational_dof (bool) – When True, integrate rotational degrees of freedom.
forces (Sequence[hoomd.md.force.Force]) – Sequence of forces applied to the particles in the system. All the forces are summed together. The default value of
None
initializes an empty list.methods (Sequence[hoomd.md.methods.Method]) – Sequence of integration methods. Each integration method can be applied to only a specific subset of particles. The intersection of the subsets must be null. The default value of
None
initializes an empty list.constraints (Sequence[hoomd.md.constrain.Constraint]) – Sequence of constraint forces applied to the particles in the system. The default value of
None
initializes an empty list. Rigid body objects (i.e.hoomd.md.constrain.Rigid
) are not allowed in the list.rigid (hoomd.md.constrain.Rigid) – A rigid bodies object defining the rigid bodies in the simulation.
min_steps_adapt (int) – Number of steps energy change is negative before allowing \(\alpha\) and \(\delta t\) to adapt.
finc_dt (float) – Factor to increase \(\delta t\) by \([\mathrm{dimensionless}]\).
fdec_dt (float) – Factor to decrease \(\delta t\) by \([\mathrm{dimensionless}]\).
alpha_start (float) – Initial (and maximum) \(\alpha [\mathrm{dimensionless}]\).
fdec_alpha (float) – Factor to decrease \(\alpha t\) by \([\mathrm{dimensionless}]\).
force_tol (float) – Force convergence criteria \([\mathrm{force} / \mathrm{mass}]\).
angmom_tol (float) – Angular momentum convergence criteria \([\mathrm{energy} * \mathrm{time}]\).
energy_tol (float) – Energy convergence criteria \([\mathrm{energy}]\).
min_steps_conv (int) – A minimum number of attempts before convergence criteria are considered.
FIRE
is ahoomd.md.Integrator
that uses the Fast Inertial Relaxation Engine (FIRE) algorithm to minimize the potential energy for a group of particles while keeping all other particles fixed. This method is published in Bitzek, et. al., PRL, 2006. HOOMD-blue’s implementation extends the original formulation to include rotational degrees of freedom.At each time step, \(\delta t\), the algorithm uses the supplied integration methods to generate \(\vec{r}\), \(\vec{v}\), and \(\vec{F}\), and then adjusts \(\vec{v}\) according to
\[\vec{v} = (1-\alpha)\vec{v} + \alpha \hat{F}|\vec{v}|\]where \(\alpha\) and \(\delta t\) are dynamically adaptive quantities. While a current search has been lowering the energy of system for more than \(N_{min}\) steps, \(\alpha\) is decreased by \(\alpha \rightarrow \alpha \cdot \mathrm{fdec}_{\alpha}\) and \(\delta t\) is increased by \(\delta t \rightarrow \max(\delta t \cdot \mathrm{finc}_{dt}, \ \delta t_{max})\). If the energy of the system increases (or stays the same), the velocity of the particles is set to 0, \(\alpha \rightarrow \ \alpha_{start}\) and \(\delta t \rightarrow \delta t \cdot \mathrm{fdec}_{\alpha}\). The method converges when the force per particle is below
force_tol
, the angular momentum is belowangmom_tol
and the change in potential energy from one step to the next is belowenergy_tol
:\[\frac{\sum |F|}{N*\sqrt{N_{dof}}} < \mathrm{\text{force_tol}} \;\;, \;\ \Delta \frac{\sum|E|}{N} < \mathrm{\text{energy_tol}} \;\;, and \;\ \frac{\sum|L|}{N} < \mathrm{\text{angmom_tol}}\]where \(N_{\mathrm{dof}}\) is the number of degrees of freedom the minimization is acting over. Any of the criterion can be effectively disabled by setting the tolerance to a large number.
If the minimization acts on a subset of all the particles in the system, the other particles will be kept frozen but will still interact with the particles being moved.
Examples:
fire = md.minimize.FIRE(dt=0.05, force_tol=1e-2, angmom_tol=1e-2, energy_tol=1e-7) fire.methods.append(md.methods.NVE(hoomd.filter.All())) sim.operations.integrator = fire while not(fire.converged): sim.run(100) fire = md.minimize.FIRE(dt=0.05) fire.methods.append(md.methods.NPH( hoomd.filter.All(), S=1, tauS=1, couple='none')) sim.operations.integrator = fire while not(fire.converged): sim.run(100)
Note
To use
FIRE
, set it as the simulation’s integrator in place of the typicalhoomd.md.Integrator
.Note
The algorithm requires an integration method to update the particle position and velocities. This should either be either
hoomd.md.methods.NVE
(to minimize energy) orhoomd.md.methods.NPH
(to minimize energy and relax the box). The quantity minimized is in any case the potential energy (not the enthalpy or any other quantity).Note
In practice, the default parameters prevents the simulation from making too aggressive a first step, but also from quitting before having found a good search direction. Adjust the parameters as needed for your simulations.
- dt
This is the maximum step size the minimizer is permitted to use \([\mathrm{time}]\). Consider the stability of the system when setting.
- Type
- forces
Sequence of forces applied to the particles in the system. All the forces are summed together. The default value of
None
initializes an empty list.- Type
Sequence[hoomd.md.force.Force]
- methods
Sequence of integration methods. Each integration method can be applied to only a specific subset of particles. The intersection of the subsets must be null. The default value of
None
initializes an empty list.- Type
Sequence[hoomd.md.methods.Method]
- constraints
Sequence of constraint forces applied to the particles in the system. The default value of
None
initializes an empty list. Rigid body objects (i.e.hoomd.md.constrain.Rigid
) are not allowed in the list.- Type
Sequence[hoomd.md.constrain.Constraint]
- rigid
A rigid bodies object defining the rigid bodies in the simulation.
- min_steps_adapt
Number of steps energy change is negative before allowing \(\alpha\) and \(\delta t\) to adapt.
- Type
- property converged
True when the minimizer has converged, else False.
(
Loggable
: category=”scalar”, default=False)- Type
- property energy
Get the energy after the last iteration of the minimizer.
(
Loggable
: category=”scalar”)- Type
- reset()
Reset the minimizer to its initial state.
md.nlist
Overview
Base class neighbor list. |
|
Neighbor list computed via a cell list. |
|
Cell list based neighbor list using stencils. |
|
Bounding volume hierarchy based neighbor list. |
Details
Neighbor list acceleration structures.
Pair forces (hoomd.md.pair
) use neighbor list data structures to find
neighboring particle pairs (those within a distance of \(r_\mathrm{cut}\))
efficiently. HOOMD-blue provides a several types of neighbor list construction
algorithms that you can select from: Cell
, Tree
, and Stencil
.
Multiple pair force objects can share a single neighbor list, or use independent neighbor list objects. When neighbor lists are shared, they find neighbors within the the maximum \(r_{\mathrm{cut},i,j}\) over the associated pair potentials.
Buffer distance
Set the NeighborList.buffer
distance to amortize the cost of the neighbor list
build. When buffer > 0
, a neighbor list computed on one step can be reused
on subsequent steps until a particle moves a distance buffer/2
. When
NeighborList.check_dist
is True
, NeighborList
starts checking how far
particles have moved NeighborList.rebuild_check_delay
time steps after the
last build and performs a rebuild when any particle has moved a distance
buffer/2
. When NeighborList.check_dist
is False
, NeighborList
always
rebuilds after NeighborList.rebuild_check_delay
time steps.
Note
With the default settings (check_dist=True
and
rebuild_check_delay=1
), changing NeighborList.buffer
only impacts
simulation performance and not correctness.
Set the buffer too small and the neighbor list will need to be updated
often, slowing simulation performance. Set the buffer too large, and
hoomd.md.pair.Pair
will need to needlessly calculate many non-interacting
particle pairs and slow the simulation. There is an optimal value for
NeighborList.buffer
between the two extremes that provides the best
performance.
Base distance cutoff
The NeighborList.r_cut
attribute can be used to set the base cutoff distance
for neighbor list queries. The actual cutoff distance is always the maximum
\(r_{\mathrm{cut},i,j}\) of the base cutoff and associated pair potentials.
Note
This attribute is particularly useful for implementing custom pair forces in Python.
Attention
Users should only set this attribute when utilizing the accessor APIs,
pair_list
, local_pair_list
, cpu_local_nlist_arrays
, or
gpu_local_nlist_arrays
.
Exclusions
Neighbor lists nominally include all particles within the chosen cutoff
distances. The NeighborList.exclusions
attribute defines which particles will
be excluded from the list, even if they are within the cutoff.
NeighborList.exclusions
is a tuple of strings that enable one more more types
of exclusions. The valid exclusion types are:
'angle'
: Exclude the first and third particles in each angle.'body'
: Exclude particles that belong to the same rigid body.'bond'
: Exclude particles that are directly bonded together.'meshbond'
: Exclude particles that are bonded together via a mesh.'constraint'
: Exclude particles that have a distance constraint applied between them.'dihedral'
: Exclude the first and fourth particles in each dihedral.'special_pair'
: Exclude particles that are part of a special pair.'1-3'
: Exclude particles i and k whenever there is a bond (i,j) and a bond (j,k).'1-4'
: Exclude particles i and m whenever there are bonds (i,j), (j,k), and (k,m).
- class hoomd.md.nlist.NeighborList(buffer, exclusions, rebuild_check_delay, check_dist, mesh, default_r_cut)
Base class neighbor list.
NeighborList
is the base class for all neighbor lists.Warning
Users should not instantiate this class directly. The class can be used for
isinstance
orissubclass
checks.- exclusions
Defines which particles to exclude from the neighbor list, see more details above.
- r_cut
Base cutoff radius for neighbor list queries. \([\mathrm{length}]\). Optional: defaults to the value
default_r_cut
specified on construction.Type:
TypeParameter
[tuple
[particle_type
,particle_type
],float
])
- property cpu_local_nlist_arrays
Expose nlist arrays on the CPU.
Provides direct acces to the neighbor list arrays on the cpu. All data is MPI rank-local.
The
hoomd.md.data.NeighborListLocalAccess
object exposes the internal data representation to efficently iterate over the neighbor list.Note
The local arrays are read only.
Examples:
with self.cpu_local_nlist_arrays as arrays: nlist_iter = zip(arrays.head_list, arrays.n_neigh) for i, (head, nn) in enumerate(nlist_iter): for j_idx in range(head, head + nn): j = arrays.nlist[j_idx] # i and j are "neighbor" indices
- property gpu_local_nlist_arrays
Expose nlist arrays on the GPU.
Provides direct access to the neighbor list arrays on the gpu. All data is MPI rank-local.
The
hoomd.md.data.NeighborListLocalAccessGPU
object exposes the internal data representation to efficently iterate over the neighbor list.Note
The local arrays are read only.
See also
Examples:
get_local_pairs = cupy.RawKernel(r''' extern "C" __global__ void get_local_pairs( const unsigned int N, const unsigned long* heads, const unsigned int* nns, const unsigned int* nlist, const unsigned int* tags, const unsigned long* offsets, unsigned long* pairs) { unsigned int i = (unsigned int) (blockDim.x * blockIdx.x + threadIdx.x); if (i >= N) return; uint2* pair = (uint2*)pairs; unsigned long head = heads[i]; unsigned int nn = nns[i]; unsigned long offset = offsets[i]; unsigned int tag_i = tags[i]; for (unsigned int idx = 0; idx < nn; idx++) { unsigned int j = nlist[head + idx]; pair[offset + idx] = make_uint2(tag_i, tags[j]); } } ''', 'get_local_pairs') with nlist.gpu_local_nlist_arrays as data: with sim.state.gpu_local_snapshot as snap_data: tags = snap_data.particles.tag_with_ghost tags = tags._coerce_to_ndarray() head_list = data.head_list._coerce_to_ndarray() n_neigh = data.n_neigh._coerce_to_ndarray() raw_nlist = data.nlist._coerce_to_ndarray() N = int(head_list.size) n_pairs = int(cupy.sum(n_neigh)) offsets = cupy.cumsum(n_neigh.astype(cupy.uint64) offsets -= n_neigh[0] device_local_pairs = cupy.zeros( (n_pairs, 2), dtype=cupy.uint32) block = 256 n_grid = (N + 255) // 256 get_local_pairs( (n_grid,), (block,), ( N, head_list, n_neigh, raw_nlist, tags, offsets, device_local_pairs ))
Note
GPU local nlist data is not available if the chosen device for the simulation is
hoomd.device.CPU
.
- property local_pair_list
Local pair list.
Note
The local pair list returns rank-local indices, not particle tags.
- Type
(N_pairs, 2)
numpy.ndarray
ofnumpy.uint32
- property num_builds
The number of neighbor list builds.
num_builds
is the number of neighbor list rebuilds performed since the last call toSimulation.run
.(
Loggable
: category=”scalar”, default=False)- Type
- property pair_list
Global pair list.
Note
The pair list returns particle tags, not rank-local indices.
Attention
In MPI parallel execution, the array is available on rank 0 only.
pair_list
isNone
on ranks >= 1.- Type
(N_pairs, 2)
numpy.ndarray
ofnumpy.uint32
- property shortest_rebuild
The shortest period between neighbor list rebuilds.
shortest_rebuild
is the smallest number of time steps between neighbor list rebuilds since the last call toSimulation.run
.(
Loggable
: category=”scalar”)- Type
- class hoomd.md.nlist.Cell(buffer, exclusions=('bond',), rebuild_check_delay=1, check_dist=True, deterministic=False, mesh=None, default_r_cut=0.0)
Bases:
NeighborList
Neighbor list computed via a cell list.
- Parameters
buffer (float) – Buffer width \([\mathrm{length}]\).
exclusions (tuple[str]) – Defines which particles to exclude from the neighbor list, see more details in
NeighborList
.rebuild_check_delay (int) – How often to attempt to rebuild the neighbor list.
check_dist (bool) – Flag to enable / disable distance checking.
deterministic (bool) – When
True
, sort neighbors to help provide deterministic simulation runs.mesh (Mesh) – When a mesh object is passed, the neighbor list uses the mesh to determine the bond exclusions in addition to all other set exclusions.
default_r_cut –
Cell
finds neighboring particles using a fixed width cell list, allowing for O(kN) construction of the neighbor list where k is the number of particles per cell. Cells are sized to the largest \(r_\mathrm{cut}\). This method is very efficient for systems with nearly monodisperse cutoffs, but performance degrades for large cutoff radius asymmetries due to the significantly increased number of particles per cell. In practice,Cell
is usually the best option for most users when the asymmetry between the largest and smallest cutoff radius is less than 2:1.Note
Cell
may consume a significant amount of memory, especially on GPU devices. One cause of this can be non-uniform density distributions because the memory allocated for the cell list is proportional the maximum number of particles in any cell. Another common cause is large box volumes combined with small cutoffs, which results in a very large number of cells in the system. In these cases, consider usingStencil
orTree
, which can use less memory.Examples:
cell = nlist.Cell()
- property allocated_particles_per_cell
Number of particle slots allocated per cell.
The total memory usage of
Cell
is proportional to the product of the three cell listdimensions
and theallocated_particles_per_cell
.(
Loggable
: category=”scalar”, default=False)- Type
- property dimensions
Cell list dimensions.
dimensions
is the number of cells in the x, y, and z directions.See also
(
Loggable
: category=”sequence”, default=False)
- class hoomd.md.nlist.Stencil(cell_width, buffer, exclusions=('bond',), rebuild_check_delay=1, check_dist=True, deterministic=False, mesh=None, default_r_cut=0.0)
Bases:
NeighborList
Cell list based neighbor list using stencils.
- Parameters
cell_width (float) – The underlying stencil bin width for the cell list \([\mathrm{length}]\).
buffer (float) – Buffer width \([\mathrm{length}]\).
exclusions (tuple[str]) – Defines which particles to exclude from the neighbor list, see more details in
NeighborList
.rebuild_check_delay (int) – How often to attempt to rebuild the neighbor list.
check_dist (bool) – Flag to enable / disable distance checking.
deterministic (bool) – When
True
, sort neighbors to help provide deterministic simulation runs.mesh (Mesh) – When a mesh object is passed, the neighbor list uses the mesh to determine the bond exclusions in addition to all other set exclusions.
Stencil
finds neighboring particles using a fixed width cell list, for O(kN) construction of the neighbor list where k is the number of particles per cell. In contrast withCell
,Stencil
allows the user to choose the cell width:cell_width
instead of fixing it to the largest cutoff radius (P.J. in’t Veld et al. 2008):This neighbor list style differs from
Cell
in how the adjacent cells are searched for particles. One stencil is computed per particle type based on the value ofcell_width
set by the user, which defines the bins that the particle must search in. Distances to the bins in the stencil are precomputed so that certain particles can be quickly excluded from the neighbor list, leading to improved performance compared toCell
when there is size disparity in the cutoff radius. The memory demands ofStencil
can also be lower thanCell
if your system is large and has many small cells in it; however,Tree
is usually a better choice for these systems.The performance of
Stencil
depends strongly on the choice of cell_width. The best performance is obtained when the cutoff radii are multiples of the cell_width, and when the cell_width covers the simulation box with a roughly integer number of cells.Examples:
nl_s = nlist.Stencil(cell_width=1.5)
Important
M.P. Howard et al. 2016 describes this neighbor list implementation. Cite it if you utilize
Stencil
in your research.
- class hoomd.md.nlist.Tree(buffer, exclusions=('bond',), rebuild_check_delay=1, check_dist=True, mesh=None, default_r_cut=0.0)
Bases:
NeighborList
Bounding volume hierarchy based neighbor list.
- Parameters
buffer (float) – Buffer width \([\mathrm{length}]\).
exclusions (tuple[str]) – Defines which particles to exclude from the neighbor list, see more details in
NeighborList
.rebuild_check_delay (int) – How often to attempt to rebuild the neighbor list.
check_dist (bool) – Flag to enable / disable distance checking.
mesh (Mesh) – When a mesh object is passed, the neighbor list uses the mesh to determine the bond exclusions in addition to all other set exclusions.
Tree
creates a neighbor list using a bounding volume hierarchy (BVH) tree traversal in \(O(N \log N)\) time. A BVH tree of axis-aligned bounding boxes is constructed per particle type, and each particle queries each tree to determine its neighbors. This method of searching leads to significantly improved performance compared to cell lists in systems with moderate size asymmetry, but has slower performance for monodisperse systems.Tree
can also be slower thanCell
if there are multiple types in the system, but the cutoffs between types are identical. (This is because one BVH is created per type.) The user should carefully benchmark neighbor list build times to select the appropriate neighbor list construction type.Tree
’s memory requirements scale with the number of particles in the system rather than the box volume, which may be particularly advantageous for large, sparse systems.Important
M.P. Howard et al. 2016 describes the original implementation of this algorithm for HOOMD-blue. M.P. Howard et al. 2019 describes the improved algorithm that is currently implemented. Cite both if you utilize this neighbor list style in your work.
Examples:
nl_t = nlist.Tree(check_dist=False)
md.pair
Overview
Buckingham pair force. |
|
DLVO colloidal interaction. |
|
Dissipative Particle Dynamics. |
|
Dissipative Particle Dynamics with the LJ conservative force. |
|
DPD Conservative pair force. |
|
Ewald pair force. |
|
Expanded Lennard-Jones pair force. |
|
Expanded Mie pair force. |
|
Force-shifted Lennard-Jones pair force. |
|
Fourier pair force. |
|
Gaussian pair force. |
|
Lennard-Jones pair force. |
|
Lennard-Jones 12-8 pair force. |
|
Lennard-Jones 8-4 pair force. |
|
Lennard-Jones-Gauss pair potential. |
|
Mie pair force. |
|
Morse pair force. |
|
Moliere pair force. |
|
Oscillating pair force. |
|
Base class pair force. |
|
Onsager reaction field pair force. |
|
Tabulated pair force. |
|
Pair potential model for globular proteins. |
|
Yukawa pair force. |
|
ZBL pair force. |
Details
Pair Potentials for molecular dynamics.
Pair force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
where \(\vec{r}_{ij} = \mathrm{minimum\_image}(\vec{r}_j - \vec{r}_i)\).
Pair
applies a short range cutoff using a hoomd.md.nlist.NeighborList
for
performance and assumes that both \(U(r)\) and its derivatives are 0 when
\(r_{ij} \ge r_\mathrm{cut}\). Pair
also ignores particle pairs that are
excluded in the neighbor list.
Specifically, the force \(\vec{F}\) on each pair of particles \(i,j\) is:
where the cutoff radius \(r_{\mathrm{cut}}\) is given by Pair.r_cut
.
Tip
Set Pair.r_cut
to 0 to skip computations for non-interacting pairs.
Pair
splits half the energy from each pair interaction onto particles
\(i\) and \(j\):
and similarly for virials.
Shifting/smoothing mode
The function \(U_\mathrm{pair}(r)\) depends on the chosen form of the pair
potential \(U(r)\) (by the Pair
subclass) and the mode (Pair.mode
):
where \(S(r)\) is the XPLOR smoothing function:
where \(r_{\mathrm{on}}\) is given by Pair.r_on
.
The XPLOR smoothing function \(S(r)\) ensures that both the potential energy and the force going smoothly to 0 at \(r = r_{\mathrm{cut}}\), reducing the rate of energy drift in long simulations. \(r_{\mathrm{on}}\) controls the point at which the smoothing starts. Set it to modify only the tail of the potential. The WCA potential and it’s first derivative already go smoothly to 0 at the cutoff, so there is no need to apply the smoothing function. In such mixed systems, set \(r_{\mathrm{on}}\) to a value greater than \(r_{\mathrm{cut}}\) for those pairs that interact via WCA in order to enable shifting of the WCA potential to 0 at the cutoff.
Tail correction
Some pair potentials can optionally apply isotropic integrated long range tail
corrections when the tail_correction
parameter is True
. These
corrections are only valid when the shifting/smoothing mode is set to
"none"
. Following Sun 1998, the
pressure and energy corrections \(\Delta P\) and \(\Delta E\) are given
by:
and
where \(n\) is the number of unique particle types in the system, \(\rho_i\) is the number density of particles of type \(i\) in the system, \(U_{ij}(r)\) is the pair potential between particles of type \(i\) and \(j\), and \(N_i\) is the number of particles of type \(i\) in the system. These expressions assume that the radial pair distribution functions \(g_{ij}(r)\) are unity at the cutoff and beyond.
The pressure shift \(\Delta P\) appears in the additional virial term
\(W_\mathrm{additional}\) (Force.additional_virial
) and the energy shift
appears in the additional energy \(U_\mathrm{additional}\)
(Force.additional_energy
).
Warning
The value of the tail corrections depends on the number of each type of particle in the system, and these are precomputed when the pair potential object is initialized. If the number of any of the types of particles changes, the tail corrections will yield invalid results.
Anisotropic potentials
For anisotropic potentials see hoomd.md.pair.aniso
- class hoomd.md.pair.Buckingham(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Buckingham pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Buckingham
computes the Buckingham pair force on every particle in the simulation state with:\[U(r) = A \exp\left(-\frac{r}{\rho}\right) - \frac{C}{r^6}\]Example:
nl = nlist.Cell() buck = pair.Buckingham(nl, default_r_cut=3.0) buck.params[('A', 'A')] = {'A': 2.0, 'rho'=0.5, 'C': 1.0} buck.params[('A', 'B')] = dict(A=1.0, rho=1.0, C=1.0) buck.params[('B', 'B')] = dict(A=2.0, rho=2.0, C=2.0)
- class hoomd.md.pair.DLVO(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
DLVO colloidal interaction.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
name (str) – Name of the force instance.
mode (str) – Energy shifting mode.
DLVO
computes the DLVO dispersion and electrostatic interaction pair force on every particle in the simulation state with:\[\begin{split}V_{\mathrm{DLVO}}(r) = &- \frac{A}{6} \left[ \frac{2a_1a_2}{r^2 - (a_1+a_2)^2} + \frac{2a_1a_2}{r^2 - (a_1-a_2)^2} \\ + \log \left( \frac{r^2 - (a_1+a_2)^2}{r^2 - (a_1-a_2)^2} \right) \right] \\ & + \frac{a_1 a_2}{a_1+a_2} Z e^{-\kappa(r - (a_1+a_2))}\end{split}\]where \(a_1\) is the radius of first particle in the pair, \(a_2\) is the radius of second particle in the pair, \(A\) is the Hamaker constant, \(Z\) is proportional to the surface electric potential, and \(\kappa\) is the screening parameter.
The first term corresponds to the attractive van der Waals interaction with and the second term to the repulsive double-layer interaction between two spherical surfaces. See “Intermolecular and Surface Forces” Israelachvili 2011, pp. 317.
Example:
nl = hoomd.md.nlist.Cell() dlvo = hoomd.md.pair.DLVO(nlist=nl) dlvo.params[('A', 'A')] = dict(A=1.0, kappa=1.0, Z=2, a1=1, a2=1) dlvo.params[('A', 'B')] = dict(A=2.0, kappa=0.5, Z=3, a1=1, a2=3) dlvo.params[('B', 'B')] = dict(A=2.0, kappa=0.5, Z=3, a1=3, a2=3)
- params
The potential parameters. The dictionary has the following keys:
A
(float
, required) - Hamaker constant \(A\) \([\mathrm{energy}]\)a1
(float
, required) - Radius of first particle \(a_1\) \([\mathrm{length}]\)a2
(float
, required) - Radius of second particle \(a_2\) \([\mathrm{length}]\)kappa
(float
, required) - screening parameter \(\kappa\) \([\mathrm{length}^{-1}]\)Z
surface electric potential (float
, required) - \(Z\) \([\mathrm{energy} \cdot \mathrm{length}^{-1}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.DPD(nlist, kT, default_r_cut=None)
Bases:
Pair
Dissipative Particle Dynamics.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
kT (
hoomd.variant
orfloat
) – Temperature of thermostat \([\mathrm{energy}]\).default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
DPD
computes the DPD pair force on every particle in the simulation state. DPD includes a an interaction potential, pairwise drag force, and pairwise random force. See Groot and Warren 1997:\[F = F_{\mathrm{C}}(r) + F_{\mathrm{R,ij}}(r_{ij}) + F_{\mathrm{D,ij}}(v_{ij})\]where
\[\begin{split}F_{\mathrm{C}}(r) &= A \cdot w(r_{ij}), \\ F_{\mathrm{R, ij}}(r_{ij}) &= - \theta_{ij}\sqrt{3} \sqrt{\frac{2k_b\gamma T}{\Delta t}}\cdot w(r_{ij}), \\ F_{\mathrm{D, ij}}(r_{ij}) &= - \gamma w^2(r_{ij})\left( \hat r_{ij} \circ v_{ij} \right), \\ w(r_{ij}) &= \begin{cases} \left( 1 - r/r_{\mathrm{cut}} \right) & r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases},\end{split}\]\(\hat r_{ij}\) is a normalized vector from particle i to particle j, \(v_{ij} = v_i - v_j\), and \(\theta_{ij}\) is a uniformly distributed random number in the range \([-1, 1]\).
C. L. Phillips et. al. 2011 describes the DPD implementation details. Cite it if you utilize the DPD functionality in your work.
DPD
does not implement any energy shift / smoothing modes due to the function of the force.To use the DPD thermostat, apply the
hoomd.md.methods.NVE
integration method along withDPD
forces. Use of the DPD thermostat pair force with other integrators will result in nonphysical behavior. To useDPD
with a different conservative potential than \(F_C\), set A to zero and define the conservative pair force separately.Example:
nl = nlist.Cell() dpd = pair.DPD(nlist=nl, kT=1.0, default_r_cut=1.0) dpd.params[('A', 'A')] = dict(A=25.0, gamma=4.5) dpd.params[('A', 'B')] = dict(A=40.0, gamma=4.5) dpd.params[('B', 'B')] = dict(A=25.0, gamma=4.5) dpd.params[(['A', 'B'], ['C', 'D'])] = dict(A=40.0, gamma=4.5)
- class hoomd.md.pair.DPDConservative(nlist, default_r_cut=None)
Bases:
Pair
DPD Conservative pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
DPDConservative
computes the conservative part of theDPD
pair force on every particle in the simulation state with:\[U(r) = A \cdot \left( r_{\mathrm{cut}} - r \right) - \frac{1}{2} \cdot \frac{A}{r_{\mathrm{cut}}} \cdot \left(r_{\mathrm{cut}}^2 - r^2 \right).\]DPDConservative
does not implement any energy shift / smoothing modes due to the function of the force.Example:
nl = nlist.Cell() dpdc = pair.DPDConservative(nlist=nl, default_r_cut=3.0) dpdc.params[('A', 'A')] = dict(A=1.0) dpdc.params[('A', 'B')] = dict(A=2.0, r_cut = 1.0) dpdc.params[(['A', 'B'], ['C', 'D'])] = dict(A=3.0)
- params
The potential parameters. The dictionary has the following keys:
A
(float
, required) - \(A\) \([\mathrm{force}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.DPDLJ(nlist, kT, default_r_cut=None, mode='none')
Bases:
Pair
Dissipative Particle Dynamics with the LJ conservative force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
kT (
hoomd.variant
orfloat
) – Temperature of thermostat \([\mathrm{energy}]\).default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
mode (str) – Energy shifting mode.
DPDLJ
computes theDPD
thermostat combined with theLJ
pair force on every particle in the simulation state with:\[\begin{split}F &= F_{\mathrm{C}}(r) + F_{\mathrm{R,ij}}(r_{ij}) + F_{\mathrm{D,ij}}(v_{ij}), \\ F_{\mathrm{C}}(r) &= \partial U / \partial r, \\ F_{\mathrm{R, ij}}(r_{ij}) &= - \theta_{ij}\sqrt{3} \sqrt{\frac{2k_b\gamma T}{\Delta t}}\cdot w(r_{ij}), \\ F_{\mathrm{D, ij}}(r_{ij}) &= - \gamma w^2(r_{ij}) \left( \hat r_{ij} \circ v_{ij} \right), \\ U(r) &= 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right], \\ w(r_{ij}) &= \begin{cases} \left( 1 - r/r_{\mathrm{cut}} \right) & r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases},\end{split}\]\(\hat r_{ij}\) is a normalized vector from particle i to particle j, \(v_{ij} = v_i - v_j\), and \(\theta_{ij}\) is a uniformly distributed random number in the range [-1, 1].
C. L. Phillips et. al. 2011 describes the DPD implementation details. Cite it if you utilize the DPD functionality in your work.
To use the DPD thermostat, apply the
hoomd.md.methods.NVE
integration method along withDPD
forces. Use of the DPD thermostat pair force with other integrators will result in nonphysical behavior.Example:
nl = nlist.Cell() dpdlj = pair.DPDLJ(nlist=nl, kT=1.0, default_r_cut=2.5) dpdlj.params[('A', 'A')] = dict(epsilon=1.0, sigma=1.0, gamma=4.5) dpdlj.params[(['A', 'B'], ['C', 'D'])] = dict( epsilon=3.0, sigma=1.0, gamma=1.2) dpdlj.r_cut[('B', 'B')] = 2.0**(1.0/6.0)
- params
The DPDLJ potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - \(\sigma\) \([\mathrm{length}]\)gamma
(float
, required) - \(\gamma\) \([\mathrm{mass} \cdot \mathrm{time}^{-1}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Ewald(nlist, default_r_cut=None)
Bases:
Pair
Ewald pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
Ewald
computes the Ewald pair force on every particle in the simulation state:\[U(r) = q_i q_j \left[\mathrm{erfc}\left(\kappa r + \frac{\alpha}{2\kappa}\right) \exp(\alpha r) + \mathrm{erfc}\left(\kappa r - \frac{\alpha}{2 \kappa}\right) \exp(-\alpha r)\right]\]Call
md.long_range.pppm.make_pppm_coulomb_forces
to create an instance ofEwald
andmd.long_range.pppm.Coulomb
that together implement the PPPM method for electrostatics.Example:
nl = nlist.Cell() ewald = pair.Ewald(default_r_cut=3.0, nlist=nl) ewald.params[('A', 'A')] = dict(kappa=1.0, alpha=1.5) ewald.r_cut[('A', 'B')] = 3.0
- params
The Ewald potential parameters. The dictionary has the following keys:
kappa
(float
, required) - Splitting parameter \(\kappa\) \([\mathrm{length}^{-1}]\)alpha
(float
, required) - Debye screening length \(\alpha\) \([\mathrm{length}^{-1}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.ExpandedLJ(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Expanded Lennard-Jones pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting mode.
ExpandedLJ
computes the radially-shifted Lennard-Jones pair force on every particle in the simulation state:\[U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r - \Delta} \right)^{12} - \left( \frac{\sigma}{r - \Delta} \right)^{6} \right]\]Note
To replicate the behavior of the SLJ potential in HOOMD-blue v2, set
hoomd.md.pair.Pair.r_cut
tor_cut_unshifted + delta
.Example:
nl = nlist.Cell() expanded_lj = pair.ExpandedLJ(default_r_cut=3.0, nlist=nl) expanded_lj.params[('A', 'A')] = dict(epsilon=1.0, sigma=1.0, delta=1.0) expanded_lj.params[('A', 'B')] = dict( epsilon=2.0, sigma=1.0, delta=0.75) expanded_lj.params[('B', 'B')] = dict(epsilon=1.0, sigma=1.0, delta=0.5)
- params
The potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)delta
(float
, required) - radial shift \(\Delta\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.ExpandedMie(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Expanded Mie pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
ExpandedMie
computes the radially shifted Mie pair force on every particle in the simulation state:\[U(r) = \left( \frac{n}{n-m} \right) {\left( \frac{n}{m} \right)}^{\frac{m}{n-m}} \varepsilon \left[ \left( \frac{\sigma}{r-\Delta} \right)^{n} - \left( \frac {\sigma}{r-\Delta} \right)^{m} \right]\]Example:
nl = nlist.Cell() expanded_mie = pair.ExpandedMie(nlist=nl, default_r_cut=3.0) mie.params[('A', 'B')] = { "epsilon": 1.0, "sigma": 1.0, "n": 12, "m": 6, "delta": 0.5} expanded_mie.r_cut[('A', 'B')] = 2**(1.0 / 6.0) expanded_mie.params[(['A', 'B'], ['C', 'D'])] = { "epsilon": 1.5, "sigma": 2.0, "n": 12, "m": 6, "delta": 0.5}
- params
The Expanded Mie potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\epsilon\) \([\mathrm{energy}]\).sigma
(float
, required) - \(\sigma\) \([\mathrm{length}]\).n
(float
, required) - \(n\) \([\mathrm{dimensionless}]\).m
(float
, required) - \(m\) \([\mathrm{dimensionless}]\).delta
(float
, required) - \(\Delta\) \([\mathrm{length}]\).
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.ForceShiftedLJ(nlist, default_r_cut=None)
Bases:
Pair
Force-shifted Lennard-Jones pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
ForceShiftedLJ
computes the modified Lennard-Jones pair force on every particle in the simulation state.\[U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right] + \Delta V(r)\]\[\Delta V(r) = -(r - r_{\mathrm{cut}}) \frac{\partial V_{\mathrm{LJ}}}{\partial r}(r_{\mathrm{cut}})\]The force differs from the one calculated by
LJ
by the subtraction of the value of the force at \(r_{\mathrm{cut}}\), such that the force smoothly goes to zero at the cut-off. The potential is modified by a linear function. See Toxvaerd et. al. 2011 for a discussion of this potential.Example:
nl = nlist.Cell() fslj = pair.ForceShiftedLJ(nlist=nl, default_r_cut=1.5) fslj.params[('A', 'A')] = dict(epsilon=1.0, sigma=1.0)
- class hoomd.md.pair.Fourier(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Fourier pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Fourier
computes the Fourier pair force on every particle in the simulation state:\[U(r) = \frac{1}{r^{12}} + \frac{1}{r^2}\sum_{n=1}^4 \left[ a_n cos \left( \frac{n \pi r}{r_{cut}} \right) + b_n sin \left( \frac{n \pi r}{r_{cut}} \right) \right]\]where
\[\begin{split}a_1 &= \sum_{n=2}^4 (-1)^n a_n \\ b_1 &= \sum_{n=2}^4 n (-1)^n b_n \\\end{split}\]enforce \(U(r_\mathrm{cut}) = 0\).
Example:
nl = nlist.Cell() fourier = pair.Fourier(default_r_cut=3.0, nlist=nl) fourier.params[('A', 'A')] = dict(a=[a2,a3,a4], b=[b2,b3,b4])
- params
The Fourier potential parameters. The dictionary has the following keys:
a
(float
, required) - array of 3 values corresponding to a2, a3 and a4 in the Fourier series \([\mathrm{dimensionless}]\)b
(float
, required) - array of 3 values corresponding to b2, b3 and b4 in the Fourier series \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Gauss(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Gaussian pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Gauss
computes the Gaussian pair force should on every particle in the simulation state:\[U(r) = \varepsilon \exp \left( -\frac{1}{2} \left( \frac{r}{\sigma} \right)^2 \right)\]Example:
nl = nlist.Cell() gauss = pair.Gauss(default_r_cut=3.0, nlist=nl) gauss.params[('A', 'A')] = dict(epsilon=1.0, sigma=1.0) gauss.r_cut[('A', 'B')] = 3.0
- class hoomd.md.pair.LJ(nlist, default_r_cut=None, default_r_on=0.0, mode='none', tail_correction=False)
Bases:
Pair
Lennard-Jones pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
tail_correction (bool) – Whether to apply the isotropic integrated long range tail correction.
LJ
computes the Lennard-Jones pair force on every particle in the simulation state.\[U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right]\]Example:
nl = nlist.Cell() lj = pair.LJ(nl, default_r_cut=3.0) lj.params[('A', 'A')] = {'sigma': 1.0, 'epsilon': 1.0} lj.r_cut[('A', 'B')] = 3.0
- class hoomd.md.pair.LJ0804(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Lennard-Jones 8-4 pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
LJ0804
computes the Lennard-Jones 8-4 pair force on every particle in the simulation state:\[U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{8} - \left( \frac{\sigma}{r} \right)^{4} \right]\]Example:
nl = nlist.Cell() lj0804 = pair.LJ0804(nl, default_r_cut=3.0) lj0804.params[('A', 'A')] = {'sigma': 1.0, 'epsilon': 1.0} lj0804.params[('A', 'B')] = dict(epsilon=2.0, sigma=1.0) lj0804.r_cut[('A', 'B')] = 3.0
- class hoomd.md.pair.LJ1208(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Lennard-Jones 12-8 pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
LJ1208
computes the Lennard-Jones 12-8 pair force on every particle in the simulation state.Example:
nl = nlist.Cell() lj1208 = pair.LJ1208(nl, default_r_cut=3.0) lj1208.params[('A', 'A')] = {'sigma': 1.0, 'epsilon': 1.0} lj1208.params[('A', 'B')] = dict(epsilon=2.0, sigma=1.0)
\[U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{8} \right]\]
- class hoomd.md.pair.LJGauss(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Lennard-Jones-Gauss pair potential.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
LJGauss
computes the Lennard-Jones Gauss force on all particles in the simulation state:\[U(r) = 1\ [\mathrm{energy}] \cdot \left[ \left ( \frac{1\ [\mathrm{length}]}{r} \right)^{12} - 2\ \left(\frac{1 [\mathrm{length}]}{r} \right)^{6} \right] - \epsilon \exp \left[- \frac{\left(r - r_{0}\right)^{2}}{2 \sigma^{2}} \right]\]- params
The potential parameters. The dictionary has the following keys:
Example:
nl = hoomd.md.nlist.Cell() ljg = pair.LJGauss(nl) ljg.params[('A', 'A')] = dict(epsilon=1.0, sigma=0.02, r0=1.6) ljg.params[('A', 'B')] = {'epsilon' : 2.0, 'sigma' : 0.02, 'r0' : 1.6} ljg.params[('A', 'B')] = {'epsilon' : 2.0, 'sigma' : 0.02, 'r0' : 1.6}
New in version 3.1.0.
- class hoomd.md.pair.Mie(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Mie pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Mie
computes the Mie pair force on every particle in the simulation state.\[U(r) = \left( \frac{n}{n-m} \right) {\left( \frac{n}{m} \right)}^{\frac{m}{n-m}} \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{n} - \left( \frac{\sigma}{r} \right)^{m} \right]\]Example:
nl = nlist.Cell() mie = pair.Mie(nlist=nl, default_r_cut=3.0) mie.params[('A', 'A')] = dict(epsilon=1.0, sigma=1.0, n=12, m=6) mie.r_cut[('A', 'A')] = 2**(1.0/6.0) mie.r_on[('A', 'A')] = 2.0 mie.params[(['A', 'B'], ['C', 'D'])] = dict(epsilon=1.5, sigma=2.0)
- params
The potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - \(\sigma\) \([\mathrm{length}]\)n
(float
, required) - \(n\) \([\mathrm{dimensionless}]\)m
(float
, required) - \(m\) \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Moliere(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Moliere pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Moliere
computes the Moliere pair force on every particle in the simulation state:\[\begin{split}U(r) = \frac{Z_i Z_j e^2}{4 \pi \epsilon_0 r_{ij}} \left[ 0.35 \exp \left( -0.3 \frac{r_{ij}}{a_F} \right) + \\ 0.55 \exp \left( -1.2 \frac{r_{ij}}{a_F} \right) + 0.10 \exp \left( -6.0 \frac{r_{ij}}{a_F} \right) \right]\end{split}\]Where each parameter is defined as:
\(Z_i\) - Z_i - Atomic number of species i \([\mathrm{dimensionless}]\)
\(Z_j\) - Z_j - Atomic number of species j \([\mathrm{dimensionless}]\)
\(e\) - elementary_charge - The elementary charge \([\mathrm{charge}]\)
\(a_F = \frac{0.8853 a_0}{\left( \sqrt{Z_i} + \sqrt{Z_j} \right)^{2/3}}\), where \(a_0\) is the Bohr radius \([\mathrm{length}]\)
Example:
nl = nlist.Cell() moliere = pair.Moliere(default_r_cut = 3.0, nlist=nl) Zi = 54 Zj = 7 e = 1 a0 = 1 aF = 0.8853 * a0 / (np.sqrt(Zi) + np.sqrt(Zj))**(2/3) moliere.params[('A', 'B')] = dict(qi=Zi*e, qj=Zj*e, aF=aF)
- params
The potential parameters. The dictionary has the following keys:
qi
(float
, required) - \(q_i = Z_i \frac{e}{\sqrt{4 \pi \epsilon_0}}\) \([\mathrm{charge}]\)qj
(float
, required) - \(q_j = Z_j \frac{e}{\sqrt{4 \pi \epsilon_0}}\) \([\mathrm{charge}]\)aF
(float
, required) - \(a_F = \frac{0.8853 a_0}{\left( \sqrt{Z_i} + \sqrt{Z_j} \right)^{2/3}}\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Morse(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Morse pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Morse
computes the Morse pair force on every particle in the simulation state:\[U(r) = D_0 \left[ \exp \left(-2\alpha\left( r-r_0\right)\right) -2\exp \left(-\alpha\left(r-r_0\right) \right) \right]\]Example:
nl = nlist.Cell() morse = pair.Morse(default_r_cut=3.0, nlist=nl) morse.params[('A', 'A')] = dict(D0=1.0, alpha=3.0, r0=1.0) morse.r_cut[('A', 'B')] = 3.0
- params
The potential parameters. The dictionary has the following keys:
D0
(float
, required) - depth of the potential at its minimum \(D_0\) \([\mathrm{energy}]\)alpha
(float
, required) - the width of the potential well \(\alpha\) \([\mathrm{length}^{-1}]\)r0
(float
, required) - position of the minimum \(r_0\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.OPP(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Oscillating pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
OPP
computes the oscillating pair force on all particles in the simulation state:\[U(r) = C_1 r^{-\eta_1} + C_2 r^{-\eta_2} \cos{\left(k r - \phi\right)}\]The potential was introduced in Marek Mihalkovič and C. L. Henley 2012.
Example:
nl = nlist.Cell() opp = pair.OPP(nl, default_r_cut=3.0) opp.params[('A', 'A')] = { 'C1': 1., 'C2': 1., 'eta1': 15, 'eta2': 3, 'k': 1.0, 'phi': 3.14} opp.r_cut[('A', 'B')] = 3.0
- params
The OPP potential parameters. The dictionary has the following keys:
C1
(float
, required) - Energy scale of the first term \(C_1\) \([\mathrm{energy}]\)C2
(float
, required) - Energy scale of the second term \(C_2\) \([\mathrm{energy}]\)eta1
(float
, required) - The inverse power to take \(r\) to in the first term, \(\eta_1\) \([\mathrm{dimensionless}]\).eta2
(float
, required) - The inverse power to take \(r\) to in the second term \(\eta_2\) \([\mathrm{dimensionless}]\).k
(float
, required) - oscillation frequency \(k\) \([\mathrm{length}^{-1}]\)phi
(float
, required) - potential phase shift \(\phi\) \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Pair(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Force
Base class pair force.
Pair
is the base class for all pair forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- r_cut
Cuttoff radius beyond which the energy and force are 0 \([\mathrm{length}]\). Optional: defaults to the value
default_r_cut
specified on construction.Type:
TypeParameter
[tuple
[particle_type
,particle_type
],float
])
- r_on
Radius at which the smoothing modification to the potential starts \([\mathrm{length}]\). Optional: defaults to the value
default_r_on
specified on construction.Type:
TypeParameter
[tuple
[particle_type
,particle_type
],float
])
- nlist
Neighbor list used to compute the pair force.
- compute_energy(tags1, tags2)
Compute the energy between two sets of particles.
- Parameters
tags1 (
ndarray<int32>
) – a numpy array of particle tags in the first group.tags2 (
ndarray<int32>
) – a numpy array of particle tags in the second group.
\[U = \sum_{i \in \mathrm{tags1}, j \in \mathrm{tags2}} V_{ij}(r)\]where \(V_{ij}(r)\) is the pairwise energy between two particles \(i\) and \(j\).
Assumed properties of the sets tags1 and tags2 are:
tags1 and tags2 are disjoint
all elements in tags1 and tags2 are unique
tags1 and tags2 are contiguous numpy arrays of dtype int32
None of these properties are validated.
Examples:
tags=numpy.linspace(0,N-1,1, dtype=numpy.int32) # computes the energy between even and odd particles U = mypair.compute_energy(tags1=numpy.array(tags[0:N:2]), tags2=numpy.array(tags[1:N:2]))
- class hoomd.md.pair.ReactionField(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Onsager reaction field pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
ReactionField
computes the Onsager reaction field pair force on all particles in the simulation state.Reaction field electrostatics is an approximation to the screened electrostatic interaction, which assumes that the medium can be treated as an electrostatic continuum of dielectric constant \(\epsilon_{RF}\) outside the cutoff sphere of radius \(r_{\mathrm{cut}}\). See: Barker et. al. 1973.
By default (
use_charge=False
), the reaction field potential ignores the particle charges. Two parameters, \(\varepsilon\) and \(\epsilon_{RF}\) are needed. If \(\epsilon_{RF}\) is specified as zero, it will represent infinity:\[U(r) = \varepsilon \left[ \frac{1}{r} + \frac{(\epsilon_{RF}-1) r^2}{(2 \epsilon_{RF} + 1) r_c^3} \right]\]When use_charge is set to
True
, the following formula is evaluated instead:\[U(r) = q_i q_j \varepsilon \left[ \frac{1}{r} + \frac{(\epsilon_{RF}-1) r^2}{(2 \epsilon_{RF} + 1) r_c^3} \right]\]where \(q_i\) and \(q_j\) are the charges of the particle pair.
Example:
nl = nlist.Cell() reaction_field = pair.reaction_field(nl, default_r_cut=3.0) reaction_field.params[('A', 'B')] = dict(epsilon=1.0, eps_rf=1.0) reaction_field.params[('B', 'B')] = dict( epsilon=1.0, eps_rf=0.0, use_charge=True)
- params
The potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\varepsilon\) \([\mathrm{energy} \cdot \mathrm{length}]\)eps_rf
(float
, required) - \(\epsilon_{RF}\) \([\mathrm{dimensionless}]\)use_charge
(bool
, optional) - evaluate pair force using particle charges (default: False)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.TWF(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Pair potential model for globular proteins.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
TWF
computes the Ten-wolde Frenkel potential on all particles in the simulation state:\[U(r) = \frac{4 \epsilon}{\alpha^2} {\left[ {\left(\frac{\sigma^2}{r^2} - 1 \right)}^6 - \alpha {\left(\frac{\sigma^2}{r^2} - 1 \right)}^3\right]}\]The potential was introdcued in Pieter Rein ten Wolde and Daan Frenkel 1997.
Example:
nl = nlist.Cell() twf = hoomd.md.pair.TWF(nl, default_r_cut=3.0) twf.params[('A', 'A')] = {'sigma': 1.0, 'epsilon': 1.0, 'alpha': 50.0} twf.r_cut[('A', 'B')] = 3.0
- params
The LJ potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)sigma
(float
, required) - particle size \(\sigma\) \([\mathrm{length}]\)alpha
(float
, required) - controls well-width \(\alpha\) \([\mathrm{dimensionless}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Table(nlist, default_r_cut=None)
Bases:
Pair
Tabulated pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
Table
computes the tabulated pair force on every particle in the simulation state.The force \(\vec{F}\) is:
\[\begin{split}\vec{F}(\vec{r}) = \begin{cases} 0 & r < r_{\mathrm{min}} \\ F_\mathrm{table}(r)\hat{r} & r_{\mathrm{min}} \le r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases}\end{split}\]and the potential \(U(r)\) is:
\[\begin{split}U(r) = \begin{cases} 0 & r < r_{\mathrm{min}} \\ U_\mathrm{table}(r) & r_{\mathrm{min}} \le r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases}\end{split}\]where \(\vec{r}\) is the vector pointing from one particle to the other in the pair,
r_min
is defined inparams
, andr_cut
is defined inPair.r_cut
.Provide \(F_\mathrm{table}(r)\) and \(U_\mathrm{table}(r)\) on evenly spaced grid points points between \(r_{\mathrm{min}}\) and \(r_{\mathrm{cut}}\).
Table
linearly interpolates values when \(r\) lies between grid points and between the last grid point and \(r=r_{\mathrm{cut}}\). The force must be specificed commensurate with the potential: \(F = -\frac{\partial U}{\partial r}\).Table
does not support energy shifting or smoothing modes.Note
For potentials that diverge near r=0, to set r_min to a non-zero value.
Note
The implicitly defined \(r\) values are those that would be returned by
numpy.linspace(r_min, r_cut, len(U), endpoint=False)
.Tip
Define non-interacting potentials with:
table.params[(type1, type2)] = dict(r_min=0, U=[0], F=[0]) table.r_cut[(type1, type2)] = 0
There must be at least one element in U and F, and the
r_cut
value of 0 disables the interaction entirely.- params
The potential parameters. The dictionary has the following keys:
r_min
(float
, required) - the minimum distance to apply the tabulated potential, corresponding to the first element of the energy and force arrays \([\mathrm{length}]\).U
((N,)numpy.ndarray
offloat
, required) - the tabulated energy values \([\mathrm{energy}]\).F
((N,)numpy.ndarray
offloat
, required) - the tabulated force values \([\mathrm{force}]\). Must have the same length asU
.
- Type
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.Yukawa(nlist, default_r_cut=None, default_r_on=0.0, mode='none')
Bases:
Pair
Yukawa pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
mode (str) – Energy shifting/smoothing mode.
Yukawa
computes the Yukawa pair force son every particle in the simulation state:\[U(r) = \varepsilon \frac{ \exp \left( -\kappa r \right) }{r}\]Example:
nl = nlist.Cell() yukawa = pair.Yukawa(default_r_cut=3.0, nlist=nl) yukawa.params[('A', 'A')] = dict(epsilon=1.0, kappa=1.0) yukawa.r_cut[('A', 'B')] = 3.0
- params
The Yukawa potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \(\varepsilon\) \([\mathrm{energy}]\)kappa
(float
, required) - scaling parameter \(\kappa\) \([\mathrm{length}^{-1}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.ZBL(nlist, default_r_cut=None, default_r_on=0.0)
Bases:
Pair
ZBL pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list.
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
default_r_on (float) – Default turn-on radius \([\mathrm{length}]\).
ZBL
computes the Ziegler-Biersack-Littmark pair force on every particle in the simulation state:\[\begin{split}U(r) = \frac{Z_i Z_j e^2}{4 \pi \epsilon_0 r_{ij}} \left[ 0.1818 \exp \left( -3.2 \frac{r_{ij}}{a_F} \right) \right. \\ + 0.5099 \exp \left( -0.9423 \frac{r_{ij}}{a_F} \right) \\ + 0.2802 \exp \left( -0.4029 \frac{r_{ij}}{a_F} \right) \\ + \left. 0.02817 \exp \left( -0.2016 \frac{r_{ij}}{a_F} \right) \right]\end{split}\]Where each parameter is defined as:
\(Z_i\) - Z_i - Atomic number of species i \([\mathrm{dimensionless}]\)
\(Z_j\) - Z_j - Atomic number of species j \([\mathrm{dimensionless}]\)
\(e\) - elementary_charge - The elementary charge \([\mathrm{charge}]\)
\(a_F = \frac{0.8853 a_0}{ Z_i^{0.23} + Z_j^{0.23} }\), where \(a_0\) is the Bohr radius \([\mathrm{length}]\)
Example:
nl = nlist.Cell() zbl = pair.ZBL(default_r_cut=3.0, nlist=nl) Zi = 54 Zj = 7 e = 1 a0 = 1 aF = 0.8853 * a0 / (Zi**(0.23) + Zj**(0.23)) zbl.params[('A', 'B')] = dict(qi=Zi*e, qj=Zj*e, aF=aF)
- params
The ZBL potential parameters. The dictionary has the following keys:
q_i
(float
, required) - \(q_i=Z_i \frac{e}{\sqrt{4 \pi \epsilon_0}}\) \([\mathrm{charge}]\)q_j
(float
, required) - \(q_j=Z_j \frac{e}{\sqrt{4 \pi \epsilon_0}}\) \([\mathrm{charge}]\)a_F
(float
, required) - \(a_F = \frac{0.8853 a_0}{ Z_i^{0.23} + Z_j^{0.23} }\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
Modules
md.pair.aniso
Overview
Anistropic LJ force. |
|
Base class anisotropic pair force. |
|
Screened dipole-dipole pair forces. |
|
Gay-Berne anisotropic pair force. |
Details
Anisotropic pair forces.
Anisotropic pair force classes apply a force, torque, and virial on every particle in the simulation state commensurate with the potential energy:
AnisotropicPair
applies cuttoffs, exclusions, and assigns per particle
energies and virials in the same manner as hoomd.md.pair.Pair
AnisotropicPair
does not support the 'xplor'
shifting mode or the r_on
parameter.
- class hoomd.md.pair.aniso.ALJ(nlist, default_r_cut=None, mode='none')
Bases:
AnisotropicPair
Anistropic LJ force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([length]\).
mode (
str
, optional) –the energy shifting mode, defaults to “none”. Computes the same energy regardless of value passed.
Deprecated since version v3.1.0.
ALJ
computes the Lennard-Jones force between anisotropic particles as described in Ramasubramani, V. et al. 2020, using the formula:\[U(r, r_c) = U_0(r) + U_c(r_c)\]The first term is the central interaction \(U_0\), the standard center-center interaction between two Lennard-Jones particles with center-center distance \(r\). The second term is the contact interaction \(U_c\), computed from the smallest distance between the surfaces of the two shapes \(r_c\). The central and contact interactions are defined as follows:
\[ \begin{align}\begin{aligned}&U_0(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right]\\&U_c(r_c) = 4 \varepsilon_c(\varepsilon) \left[ \left( \frac{\sigma_c}{r_c} \right)^{12} - \left( \frac{\sigma_c}{r_c} \right)^{6} \right]\end{aligned}\end{align} \]where \(\varepsilon\) (
epsilon
) affects strength of both the central and contact interactions, \(\varepsilon_c\) is an energy coefficient set proportional to \(\varepsilon\) to preserve the shape, \(\sigma\) is the interaction distance of the central term computed as the average of \(\sigma_i\) (sigma_i
) and \(\sigma_j\) (sigma_j
). Lastly,ALJ
uses the contact ratios \(\beta_i\) (contact_ratio_i
) and \(\beta_j\) (contact_ratio_j
) to compute the contact sigma \(\sigma_c\) as follows:\[ \begin{align}\begin{aligned}\sigma_c &= \frac{1}{2} \left[\sigma_{ci} + \sigma_{cj} \right]\\\sigma_{ci} &= \beta_i \cdot \sigma_i\\\sigma_{cj} &= \beta_j \cdot \sigma_j\end{aligned}\end{align} \]The total potential energy is therefore the sum of two interactions, a central Lennard-Jones potential and a radially-shifted Lennard-Jones potential where the shift is anisotropic and depends on the extent of the shape in each direction.
Each term has an independent cutoff at which the energy is set to zero. The behavior of these cutoffs is dependent on whether a user requires LJ or Weeks-Chandler-Anderson (WCA)-like (repulsive-only) behavior. This behavior is controlled using the
alpha
parameter, which can take on the following values:Set alpha based on range of the center-center and contact-contact interactions. center-center repulsive only
center-center full-range
contact-contact repulsive only
alpha = 0
alpha = 1
contact-contact full-range
alpha = 2
alpha = 3
For polytopes, computing interactions using a single contact point leads to significant instabilities in the torques because the contact point can jump from one end of a face to another in an arbitrarily small time interval. To ameliorate this, the ALJ potential performs a local averaging over all the features associated with the closest simplices on two polytopes. This averaging can be turned off by setting the
average_simplices
key for the type pair toFalse
.Specifying only
rounding_radii
creates an ellipsoid, while specifying onlyvertices
creates a convex polytope (setvertices
andfaces
to empty lists to create the ellipsoid).Important
The repulsive part of the contact interaction \(U_c(r_c)\) prevents two
ALJ
particles from approaching closely, effectively rounding the shape by a radius \(\sigma_c\). For this reason, the shape written bytype_shapes
includes the rounding due torounding_radii
and that due to \(\sigma_c\).Choosing
r_cut
:Set
r_cut
for each pair of particle types so thatALJ
can compute interactions for all possible relative placements and orientations of the particles. The farthest apart two particles can be while still interacting depends on the value ofalpha
.In the following list, the first argument to the \(\max\) function is for the center-center interaction. The second argument is for the contact-contact interaction, where \(R_i\) is the radius of the shape’s minimal origin-centered bounding sphere of the particle with type \(i\).
Let \(\lambda_{min} = 2^{1/6}\) be the position of the potential energy minimum of the Lennard-Jones potential and \(\lambda_{cut}^{attractive}\) be a larger value, such as 2.5 (typically used in isotropic LJ systems).
For alpha=0:
\[\begin{split}r_{\mathrm{cut},ij} = \max \bigg( & \frac{\lambda_{min}}{2} (\sigma_i + \sigma_j), \\ & R_i + R_j + R_{\mathrm{rounding},i} + R_{\mathrm{rounding},j} + \frac{\lambda_{min}}{2} (\beta_i \cdot \sigma_i + \beta_j \cdot \sigma_j) \bigg)\end{split}\]For alpha=1:
\[\begin{split}r_{\mathrm{cut},ij} = \max \bigg( & \frac{\lambda_{cut}^{attractive}}{2} (\sigma_i + \sigma_j), \\ & R_i + R_j + R_{\mathrm{rounding},i} + R_{\mathrm{rounding},j}+ \frac{\lambda_{min}}{2} (\beta_i \cdot \sigma_i + \beta_j \cdot \sigma_j) \bigg)\end{split}\]For alpha=2:
\[\begin{split}r_{\mathrm{cut},ij} = \max \bigg( & \frac{\lambda_{min}}{2} (\sigma_i + \sigma_j)), \\ & R_i + R_j + R_{\mathrm{rounding},i} + R_{\mathrm{rounding},j} + \frac{\lambda_{cut}^{attractive}}{2} (\beta_i \cdot \sigma_i + \beta_j \cdot \sigma_j) \bigg)\end{split}\]For alpha=3:
\[\begin{split}r_{\mathrm{cut},ij} = \max \bigg( & \frac{\lambda_{cut}^{attractive}}{2} (\sigma_i + \sigma_j), \\ & R_i + R_j + R_{\mathrm{rounding},i} + R_{\mathrm{rounding},j} + \frac{\lambda_{cut}^{attractive}}{2} (\beta_i \cdot \sigma_i + \beta_j \cdot \sigma_j) \bigg)\end{split}\]
Warning
Changing dimension in a simulation will invalidate this force and will lead to error or unrealistic behavior.
- params
The ALJ potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - base energy scale \(\varepsilon\) \([energy]\).sigma_i
(float
, required) - the insphere diameter of the first particle type, \(\sigma_i\) \([length]\).sigma_j
(float
, required) - the insphere diameter of the second particle type, \(\sigma_j\) \([length]\).alpha
(int
, required) - Integer 0-3 indicating whether or not to include the attractive component of the interaction (see above for details).contact_ratio_i
(float
, optional) - \(\beta_i\), the ratio of the contact sphere diameter of the first type withsigma_i
. Defaults to 0.15.contact_ratio_j
(float
, optional) - \(\beta_j\), the ratio of the contact sphere diameter of the second type withsigma_j
. Defaults to 0.15.average_simplices
(bool
, optional) - Whether to average over simplices. Defaults toTrue
. See class documentation for more information.
Type:
hoomd.data.typeparam.TypeParameter
[tuple
[particle_types
,particle_types
],dict
]
Note
While the evaluation of the potential is symmetric with respect to the potential parameter labels
i
andj
, the parameters which physically represent a specific particle type must appear in all sets of pair parameters which include that particle type.- shape
The shape of a given type. The dictionary has the following keys per type:
vertices
(list
[tuple
[float
,float
,float
]], required) - The vertices of a convex polytope in 2 or 3 dimensions. The third dimension in 2D is ignored.rounding_radii
(tuple
[float
,float
,float
] orfloat
, required) - The semimajor axes of a rounding ellipsoid \(R_{\mathrm{rounding},i}\). If a single value is specified, the rounding ellipsoid is a sphere. Defaults to (0.0, 0.0, 0.0).faces
(list
[list
[int
]], required) - The faces of the polyhedron specified as a list of list of integers. The indices corresponding to the vertices must be ordered counterclockwise with respect to the face normal vector pointing outward from the origin.
Type:
hoomd.data.typeparam.TypeParameter
[particle_types
,dict
]
Example:
nl = hoomd.md.nlist.Cell(buffer=0.4) alj = hoomd.md.pair.aniso.ALJ(nl, r_cut=2.5) cube_verts = [(-0.5, -0.5, -0.5), (-0.5, -0.5, 0.5), (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5), (0.5, 0.5, -0.5), (0.5, 0.5, 0.5)]; cube_faces = [[0, 2, 6], [6, 4, 0], [5, 0, 4], [5,1,0], [5,4,6], [5,6,7], [3,2,0], [3,0,1], [3,6,2], [3,7,6], [3,1,5], [3,5,7]] alj.params[("A", "A")] = dict(epsilon=2.0, sigma_i=1.0, sigma_j=1.0, alpha=1, ) alj.shape["A"] = dict(vertices=cube_verts, faces=cube_faces)
The following example shows how to easily get the faces, with vertex indices properly ordered, for a shape with known vertices by using the coxeter package:
Example:
import coxeter nl = hoomd.md.nlist.Cell(buffer=0.4) alj = hoomd.md.pair.aniso.ALJ(nl, r_cut=2.5) cube_verts = [[-0.5, -0.5, -0.5], [-0.5, -0.5, 0.5], [-0.5, 0.5, -0.5], [-0.5, 0.5, 0.5], [0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5], [0.5, 0.5, 0.5]] cube = coxeter.shapes.ConvexPolyhedron(cube_verts) alj.params[("A", "A")] = dict(epsilon=2.0, sigma_i=1.0, sigma_j=1.0, alpha=1, ) alj.shape["A"] = dict(vertices=cube.vertices, faces=cube.faces)
- property type_shapes
The shape specification for use with GSD files for visualization.
This is not meant to be used for access to shape information in Python. See the attribute
shape
for programatic assess. Use this property to log shape for visualization and storage through the GSD file type.(
Loggable
: category=”object”)
- class hoomd.md.pair.aniso.AnisotropicPair(nlist, default_r_cut=None, mode='none')
Bases:
Pair
Base class anisotropic pair force.
AnisotropicPair
is the base class for all anisotropic pair forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.- Parameters
nlist (hoomd.md.nlist.NeighborList) – The neighbor list.
default_r_cut (
float
, optional) – The default cutoff for the potential, defaults toNone
which means no cutoff \([\mathrm{length}]\).mode (
str
, optional) – the energy shifting mode, defaults to “none”.
- class hoomd.md.pair.aniso.Dipole(nlist, default_r_cut=None, mode='none')
Bases:
AnisotropicPair
Screened dipole-dipole pair forces.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
mode (str) –
energy shifting/smoothing mode (ignored).
Deprecated since version v3.1.0.
Dipole
computes the (screened) interaction between pairs of particles with dipoles and electrostatic charges:\[ \begin{align}\begin{aligned}U &= U_{dd} + U_{de} + U_{ee}\\U_{dd} &= A e^{-\kappa r} \left(\frac{\vec{\mu_i}\cdot\vec{\mu_j}}{r^3} - 3\frac{(\vec{\mu_i}\cdot \vec{r_{ji}}) (\vec{\mu_j}\cdot \vec{r_{ji}})} {r^5} \right)\\U_{de} &= A e^{-\kappa r} \left(\frac{(\vec{\mu_j}\cdot \vec{r_{ji}})q_i}{r^3} - \frac{(\vec{\mu_i}\cdot \vec{r_{ji}})q_j}{r^3} \right)\\U_{ee} &= A e^{-\kappa r} \frac{q_i q_j}{r}\end{aligned}\end{align} \]Note
All units are documented electronic dipole moments. However,
Dipole
can also be used to represent magnetic dipoles.Note
Dipole
accepts themode
parameter, but computes the same energy regardless of the value ofmode
(starting with v3.0.0).Example:
nl = nlist.Cell() dipole = md.pair.ansio.Dipole(nl, default_r_cut=3.0) dipole.params[('A', 'B')] = dict(A=1.0, kappa=4.0) dipole.mu['A'] = (4.0, 1.0, 0.0)
- params
The dipole potential parameters. The dictionary has the following keys:
A
(float
, required) - \(A\) - electrostatic energy scale (default: 1.0) \([\mathrm{energy} \cdot \mathrm{length} \cdot \mathrm{charge}^{-2}]\)kappa
(float
, required) - \(\kappa\) - inverse screening length \([\mathrm{length}^{-1}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
- class hoomd.md.pair.aniso.GayBerne(nlist, default_r_cut=None, mode='none')
Bases:
AnisotropicPair
Gay-Berne anisotropic pair force.
- Parameters
nlist (hoomd.md.nlist.NeighborList) – Neighbor list
default_r_cut (float) – Default cutoff radius \([\mathrm{length}]\).
mode (str) – energy shifting/smoothing mode.
GayBerne
computes the Gay-Berne anisotropic pair force on every particle in the simulation state. This version of the Gay-Berne force supports identical pairs of uniaxial ellipsoids, with orientation-independent energy-well depth. The potential comes from the following paper Allen et. al. 2006.\[\begin{split}U(\vec r, \vec e_i, \vec e_j) = \begin{cases} 4 \varepsilon \left[ \zeta^{-12} - \zeta^{-6} \right] & \zeta < \zeta_{\mathrm{cut}} \\ 0 & \zeta \ge \zeta_{\mathrm{cut}} \\ \end{cases}\end{split}\]where
\[ \begin{align}\begin{aligned}\zeta &= \left(\frac{r-\sigma+\sigma_{\mathrm{min}}} {\sigma_{\mathrm{min}}}\right),\\\sigma^{-2} &= \frac{1}{2} \hat{\vec{r}} \cdot \vec{H^{-1}} \cdot \hat{\vec{r}},\\\vec{H} &= 2 \ell_\perp^2 \vec{1} + (\ell_\parallel^2 - \ell_\perp^2) (\vec{e_i} \otimes \vec{e_i} + \vec{e_j} \otimes \vec{e_j}),\end{aligned}\end{align} \]and \(\sigma_{\mathrm{min}} = 2 \min(\ell_\perp, \ell_\parallel)\).
The cut-off parameter \(r_{\mathrm{cut}}\) is defined for two particles oriented parallel along the long axis, i.e. \(\zeta_{\mathrm{cut}} = \left(\frac{r-\sigma_{\mathrm{max}} + \sigma_{\mathrm{min}}}{\sigma_{\mathrm{min}}}\right)\) where \(\sigma_{\mathrm{max}} = 2 \max(\ell_\perp, \ell_\parallel)\) .
The quantities \(\ell_\parallel\) and \(\ell_\perp\) denote the semi-axis lengths parallel and perpendicular to particle orientation.
Example:
nl = nlist.Cell() gay_berne = md.pair.aniso.GayBerne(nlist=nl, default_r_cut=2.5) gay_berne.params[('A', 'A')] = dict(epsilon=1.0, lperp=0.45, lpar=0.5) gay_berne.r_cut[('A', 'B')] = 2 ** (1.0 / 6.0)
- params
The Gay-Berne potential parameters. The dictionary has the following keys:
epsilon
(float
, required) - \(\varepsilon\) \([\mathrm{energy}]\)lperp
(float
, required) - \(\ell_\perp\) \([\mathrm{length}]\)lpar
(float
, required) - \(\ell_\parallel\) \([\mathrm{length}]\)
Type:
TypeParameter
[tuple
[particle_type
,particle_type
],dict
]
md.special_pair
Overview
Base class special pair forces. |
|
LJ special pair force. |
|
Coulomb special pair force. |
Details
Special pair forces.
Special pair force classes apply a force and virial on every particle in the simulation state commensurate with the potential energy:
Special pairs are used to implement interactions between designated pairs of particles. They act much like bonds, except that the interaction potential is typically a pair potential, such as LJ.
Each special pair is defined by an ordered pair of particle tags in the
hoomd.State
member pair_group
. HOOMD-blue does not compute special pair
groups, users must explicitly define special pairs in the initial condition.
In the special pair group (j,k), \(r\) is the length of the vector between the particle positions \(r= |\mathrm{minimum\_image}(\vec{r}_k - \vec{r}_j)|\).
Special pair force classes assign 1/2 of the potential energy to each of the particles in the bond group:
and similarly for virials.
- class hoomd.md.special_pair.Coulomb
Bases:
SpecialPair
Coulomb special pair force.
Coulomb
computes forces, virials, and energies on all special pairs in the simulation state with:\[\begin{split}U(r) = \begin{cases} \alpha \cdot \left[ \frac{q_{a}q_{b}}{r} \right] & r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases}\end{split}\]Note
Use
Coulomb
to implement special 1-4 interactions in atomistic force fields, such as the scaled 1-4 interactions in OPLS where both the 1-4LJ
andCoulomb
interactions are scaled by 0.5.- params
The parameter of the Coulomb forces for each particle type. The dictionary has the following keys:
alpha
(float
, required) - Coulomb scaling factor \([\mathrm{energy}]\)
- Type
TypeParameter[
special pair type
, dict]
- r_cut
The cut-off distance for special pair potential \([\mathrm{length}]\)
- Type
TypeParameter[
special pair type
, float]
Examples:
coulomb = special_pair.Coulomb() coulomb.params['cluster'] = dict(alpha=1.0) coulomb.r_cut['cluster'] = 2
- class hoomd.md.special_pair.LJ
Bases:
SpecialPair
LJ special pair force.
LJ
computes forces, virials, and energies on all special pairs in the simulation state with:\[\begin{split}U(r) = \begin{cases} 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right] & r < r_{\mathrm{cut}} \\ 0 & r \ge r_{\mathrm{cut}} \\ \end{cases}\end{split}\]Note
Use
LJ
to implement special 1-4 interactions in atomistic force fields, such as the scaled 1-4 interactions in OPLS where both the 1-4LJ
andCoulomb
interactions are scaled by 0.5.- params
The parameter of the lj forces for each particle type. The dictionary has the following keys:
epsilon
(float
, required) - energy parameter \([\mathrm{energy}]\)sigma
(float
, required) - particle size \([\mathrm{length}]\)
- Type
TypeParameter[
special pair type
, dict]
- r_cut
The cut-off distance for special pair potential \([\mathrm{length}]\)
- Type
TypeParameter[
special pair type
, float]
Examples:
lj = special_pair.LJ() lj.params['cluster'] = dict(epsilon=3, sigma=0.5) lj.r_cut['cluster'] = 5
- class hoomd.md.special_pair.SpecialPair
Bases:
Force
Base class special pair forces.
SpecialPair
is the base class for all special pair forces.Warning
This class should not be instantiated by users. The class can be used for
isinstance
orissubclass
checks.
md.tune
Overview
Optimize neighbor list buffer size for maximum TPS. |
Details
Tuners for the MD subpackage.
- class hoomd.md.tune.NeighborListBuffer(self, trigger: hoomd.trigger.Trigger, nlist: hoomd.md.nlist.NeighborList, solver: hoomd.tune.solve.Optimizer, maximum_buffer: float)
Optimize neighbor list buffer size for maximum TPS.
Tip
Direct instantiation of this class requires a
hoomd.tune.Optimizer
that determines how move sizes are updated. This class also provides class methods to create aNeighborListBuffer
tuner with built-in solvers; seeNeighborListBuffer.with_grid
andNeighborListBuffer.with_gradient_descent
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.nlist (hoomd.md.nlist.NeighborList) – Neighbor list instance to tune.
solver (
hoomd.tune.solve.Optimizer
) – A solver that tunes the neighbor list buffer to maximize TPS.maximum_buffer (float) – The largest buffer value to allow.
minimum_buffer (
float
, optional) – The smallest buffer value to allow (defaults to 0).
- trigger
Trigger
to determine when to run the tuner.
- solver
A solver that tunes the neighbor list buffer to maximize TPS.
Warning
When using with a
hoomd.device.GPU
device, kernel launch parameter autotuning can prevent convergence. Run the simulation for 25,000 steps before adding the tuner to allow the autotuning to converge first results in better TPS optimization.Note
NeighborListBuffer.with_grid
generally performs better thanNeighborListBuffer.with_gradient_descent
due to the stocastic nature of TPS.- property best_buffer_size
The buffer size corresponding to
max_tps
during tuning.(
Loggable
: category=”scalar”)- Type
- property final_bin
Boundaries of grid search optimization.
Property is only available when a
hoomd.tune.GridOptimizer
is used, and tuning is finished. Otherwise, the property isNone
.
- property tuned
Whether the neighbor list buffer is considered tuned.
The tuner is considered tune when the specified solver returns
True
when solving twice consecutively. Seehoomd.tune
for more information on tuning criteria.- Type
- classmethod with_gradient_descent(trigger: Union[Trigger, int], nlist: NeighborList, maximum_buffer: float, minimum_buffer: float = 0.0, alpha: Union[Variant, float] = hoomd._hoomd.VariantRamp, kappa: Optional[ndarray] = (0.33, 0.165), tol: float = 1e-05, max_delta: Optional[float] = None)
Create a
NeighborListBuffer
with a gradient descent solver.See
hoomd.tune.solve.GradientDescent
for more information on the solver.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.nlist (hoomd.md.nlist.NeighborList) – Neighbor list buffer to maximize TPS.
maximum_buffer (float) – The largest buffer value to allow.
minimum_buffer (
float
, optional) – The smallest buffer value to allow (defaults to 0).alpha (
hoomd.variant.variant_like
, optional) – Number between 0 and 1 or variant used to dampen the rate of change in x (defaults tohoomd.variant.Ramp(1e-5, 1e-6, 0, 30)
).alpha
scales the corrections to x each iteration. Larger values ofalpha
lead to larger changes while aalpha
of 0 leads to no change in x at all.kappa (
numpy.ndarray
offloat
, optional) – A NumPy array of floats which are weight applied to the last \(N\) of the gradients to add to the current gradient as well, where \(N\) is the size of the array (defaults to(0.33, 0.165)
).tol (
float
, optional) – The absolute tolerance for convergence of y (defaults to 1e-5).max_delta (
float
, optional) – The maximum iteration step allowed (defaults toNone
which does not limit step size).
Note
Given the stocasticity of TPS, a non none
kappa
is recommended.Tip
For better convergence choose an alpha in the range of 0.01 divided by the expected order of magnitude of the TPS. The default value assumes a TPS in the thousands.
Tip
When using the
hoomd.tune.solve.GradientDescent
, optimization is improved by starting at lower buffer values, as this has the steepest gradient.
- classmethod with_grid(trigger: Union[Trigger, int], nlist: NeighborList, maximum_buffer: float, minimum_buffer: float = 0.0, n_bins: int = 5, n_rounds: int = 1)
Create a
NeighborListBuffer
with ahoomd.tune.GridOptimizer
.- Parameters
trigger (hoomd.trigger.trigger_like) –
Trigger
to determine when to run the tuner.nlist (hoomd.md.nlist.NeighborList) – Neighbor list buffer to maximize TPS.
maximum_buffer (float) – The largest buffer value to allow.
minimum_buffer (
float
, optional) – The smallest buffer value to allow (defaults to 0).n_bins (
int
, optional) – The number of bins in the range to test (defaults to 2).n_rounds (
int
, optional) – The number of rounds to perform the optimization over (defaults to 1).
Note
Using this method adds another attribue
final_bin
which gives the final bin boundaries after tuning forn_rounds
.
md.update
Overview
Updater to introduce rotational diffusion with an active force. |
|
Reverse Perturbation method to establish shear flow. |
|
Zeroes system momentum. |
Details
MD updaters.
- class hoomd.md.update.ActiveRotationalDiffusion(trigger, active_force, rotational_diffusion)
Bases:
Updater
Updater to introduce rotational diffusion with an active force.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps to update rotational diffusion.
active_force (hoomd.md.force.Active) – The active force associated with the updater can be any subclass of the class
hoomd.md.force.Active
.rotational_diffusion (hoomd.variant.variant_like) – The rotational diffusion as a function of time.
ActiveRotationalDiffusion
works directly withhoomd.md.force.Active
orhoomd.md.force.ActiveOnManifold
to apply rotational diffusion to the particle quaternions \(\mathbf{q}_i\) in simulations with active forces. The persistence length of an active particle’s path is \(v_0 / D_r\).In 2D, the diffusion follows \(\delta \theta / \delta t = \Gamma \sqrt{2 D_r / \delta t}\), where \(D_r\) is the rotational diffusion constant and the \(\Gamma\) unit-variance random variable.
In 3D, \(\hat{p}_i\) is a unit vector in 3D space, and the diffusion follows \(\delta \hat{p}_i / \delta t = \Gamma \sqrt{2 D_r / \delta t} (\hat{p}_i (\cos \theta - 1) + \hat{p}_r \sin \theta)\), where \(\hat{p}_r\) is an uncorrelated random unit vector.
When used with
hoomd.md.force.ActiveOnManifold
, rotational diffusion is performed in the tangent plane of the manifold.Tip
Use
hoomd.md.force.Active.create_diffusion_updater
to construct aActiveRotationalDiffusion
instance.- trigger
Select the timesteps to update rotational diffusion.
- active_force
The active force associated with the updater. This is not settable after construction.
- rotational_diffusion
The rotational diffusion as a function of time.
- class hoomd.md.update.ReversePerturbationFlow(filter, flow_target, slab_direction, flow_direction, n_slabs, max_slab=-1, min_slab=-1)
Bases:
Updater
Reverse Perturbation method to establish shear flow.
“Florian Mueller-Plathe. Reversing the perturbation in nonequilibrium molecular dynamics: An easy way to calculate the shear viscosity of fluids. Phys. Rev. E, 59:4894-4898, May 1999.”
The simulation box is divided in a number of slabs. Two distinct slabs of those are chosen. The “max” slab searches for the maximum velocity component in flow direction while the “min” slab searches for the minimum velocity component. Afterward, both velocity components are swapped.
This introduces a momentum flow, which drives the flow. The strength of this flow is set through the
flow_target
argument, which defines a target value for the time-integrated momentum flux. The searching and swapping is repeated until the target is reached. Depending on the target sign, the “max” and “min” slab might be swapped.- Parameters
filter (hoomd.filter.filter_like) – Subset of particles on which to apply this updater.
flow_target (hoomd.variant.variant_like) – Target value of the time-integrated momentum flux. \([\delta t \cdot \mathrm{mass} \cdot \mathrm{length} \cdot \mathrm{time}^{-1}]\) - where \(\delta t\) is the integrator step size.
slab_direction (str) – Direction perpendicular to the slabs. Can be “x”, “y”, or “z”
flow_direction (str) – Direction of the flow. Can be “x”, “y”, or “z”
n_slabs (int) – Number of slabs used to divide the simulation box along the shear gradient. Using too few slabs will lead to a larger volume being disturbed by the momentum exchange, while using too many slabs may mean that there are not enough particles to exchange the target momentum.
max_slab (int) – Id < n_slabs where the max velocity component is search for. If set < 0 the value is set to its default n_slabs/2.
min_slab (int) – Id < n_slabs where the min velocity component is search for. If set < 0 the value is set to its default 0.
Attention
This updater uses
hoomd.trigger.Periodic(1)
as a trigger, meaning it is applied every timestep.This updater works currently only with orthorhombic boxes.
Note
The attributes of this updater are immutable once the updater is attached to a simulation.
Examples:
# const integrated flow with 0.1 slope for max 1e8 timesteps ramp = hoomd.variant.Ramp(0.0, 0.1e8, 0, int(1e8)) # velocity gradient in z direction and shear flow in x direction. mpf = hoomd.md.update.ReversePerturbationFlow(filter=hoomd.filter.All(), flow_target=ramp, slab_direction="Z", flow_direction="X", n_slabs=20)
- filter
Subset of particles on which to apply this updater.
- flow_target
Target value of the time-integrated momentum flux.
- class hoomd.md.update.ZeroMomentum(trigger)
Bases:
Updater
Zeroes system momentum.
- Parameters
trigger (hoomd.trigger.trigger_like) – Select the timesteps to zero momentum.
ZeroMomentum
computes the center of mass linear momentum of the system:\[\vec{p} = \frac{1}{N_\mathrm{free,central}} \sum_{i \in \mathrm{free,central}} m_i \vec{v}_i\]and removes it:
\[\vec{v}_i' = \vec{v}_i - \frac{\vec{p}}{m_i}\]where the index \(i\) includes only free and central particles (and excludes consitutent particles of rigid bodies).
Note
ZeroMomentum
executes on the CPU even when using a GPU device.Examples:
zero_momentum = hoomd.md.update.ZeroMomentum( hoomd.trigger.Periodic(100))
Contributing
Contributions are welcomed via pull requests on GitHub. Contact the HOOMD-blue developers before starting work to ensure it meshes well with the planned development direction and standards set for the project.
Features
Implement functionality in a general and flexible fashion
New features should be applicable to a variety of use-cases. The HOOMD-blue developers can assist you in designing flexible interfaces.
Maintain performance of existing code paths
Expensive code paths should only execute when requested.
Optimize for the current GPU generation
Write, test, and optimize your GPU kernels on the latest generation of GPUs.
Version control
Base your work off the correct branch
Base backwards compatible bug fixes on
trunk-patch
.Base additional functionality on
trunk-minor
.Base API incompatible changes on
trunk-major
.
Agree to the Contributor Agreement
All contributors must agree to the Contributor Agreement before their pull request can be merged.
Source code
Use a consistent style
The Code style section of the documentation sets the style guidelines for HOOMD-blue code.
Document code with comments
Use doxygen header comments for classes, functions, etc. Also comment complex sections of code so that other developers can understand them.
Compile without warnings
Your changes should compile without warnings.
Tests
Write unit tests
Add unit tests for all new functionality.
Validity tests
The developer should run research-scale simulations using the new functionality and ensure that it behaves as intended.
User documentation
Write user documentation
Document public-facing API with Python docstrings in Google style.
Document version status
Add versionadded, versionchanged, and deprecated Sphinx directives to each user-facing Python class, method, etc., so that users will be aware of how functionality changes from version to version. Remove this when breaking APIs in major releases.
Add developer to the credits
Update the credits documentation to list the name and affiliation of each individual that has contributed to the code.
Propose a change log entry
Propose a short concise entry describing the change in the pull request description.
Code style
All code in HOOMD-blue follows a consistent style to ensure readability. We provide configuration files for linters (specified below) so that developers can automatically validate and format files.
These tools are configured for use with pre-commit in
.pre-commit-config.yaml
. You can install pre-commit hooks to validate your
code. Checks will run on pull requests. Run checks manually with:
pre-commit run --all-files
Python
Python code in HOOMD-blue should follow PEP8 with the formatting performed by
yapf (configuration in setup.cfg
). Code should pass all flake8 tests
and formatted by yapf.
Tools
Documentation
Python code should be documented with docstrings and added to the Sphinx
documentation index in doc/
. Docstrings should follow Google style
formatting for use in Napoleon.
Simulation operations should unambiguously document what calculations they perform using formal mathematical notation and use a consistent set of symbols and across the whole codebase. HOOMD-blue documentation should follow standard physics and statistical mechanics notation with consistent use of symbols detailed in Notation.
When referencing classes, methods, and properties in documentation, use name
to refer to names
in the local scope (class method or property, or classes in the same module). For classes outside
the module, use the fully qualified name (e.g. numpy.ndarray
or
hoomd.md.compute.ThermodynamicQuantities
).
C++/CUDA
Style is set by clang-format
Whitesmith’s indentation style.
100 character line width.
Indent only with spaces.
4 spaces per indent level.
See
.clang-format
for the full clang-format configuration.
Naming conventions:
Namespaces: All lowercase
somenamespace
Class names:
UpperCamelCase
Methods:
lowerCamelCase
Member variables:
m_
prefix followed by lowercase with words separated by underscoresm_member_variable
Constants: all upper-case with words separated by underscores
SOME_CONSTANT
Functions:
lowerCamelCase
Tools
Autoformatter: clang-format.
Documentation
Documentation comments should be in Javadoc format and precede the item they document for
compatibility with many source code editors. Multi-line documentation comment blocks start with
/**
and single line ones start with
///
.
/** Describe a class
*
* Note the second * above makes this a documentation comment. Some
* editors like to add the additional *'s on each line. These may be
* omitted
*/
class SomeClass
{
public:
/// Single line doc comments should have three /'s
Trigger() { }
/** This is a brief description of a method
This is a longer description.
@param arg This is an argument.
@returns This describes the return value
*/
virtual bool method(int arg)
{
return false;
}
private:
/// This is a member variable
int m_var;
};
See Trigger.h
for a good example.
Other file types
Use your best judgment and follow existing patterns when styling CMake, restructured text, markdown, and other files. The following general guidelines apply:
100 character line width.
4 spaces per indent level.
4 space indent.
Editor configuration
Visual Studio Code users: Open the provided
workspace file (hoomd.code-workspace
) which provides configuration
settings for these style guidelines.
Testing
All code in HOOMD must be tested to ensure that it operates correctly.
Unit tests check that basic functionality works, one class at a time. Unit tests assume internal knowledge about how classes work and may use unpublished APIs to stress test all possible input and outputs of a given class in order to exercise all code paths. For example, test that the box class properly wraps vectors back into the minimum image. Unit tests should complete in a fraction of a second.
System integration tests check that many classes work together to produce correct output. These tests are black box tests and should only use user-facing APIs to provide inputs and check for correct outputs. For example, test that the hard sphere HPMC simulation executes for several steps. System integration tests may take several seconds.
Long running tests check for correct behavior, but require up to a minute to execute. Mark long
running tests with the validate
label.
Validation tests rigorously check that simulations sample the correct statistical ensembles. These tests take hours to execute on many CPU cores or GPUs. Find HOOMD’s validation tests in the hoomd-validation repository.
Requirements
The following Python packages are required to execute tests. Some tests will be skipped when optional requirements are missing.
gsd (optional)
mpi4py (optional)
pytest
rowan (optional)
CuPy (optional)
Running tests
Change to the build directory and execute the following commands to run the tests:
ctest
- Executes C++ testspython3 -m pytest hoomd
pytest may be run outside the build directory by:
Passing a full path to the build:
python3 -m pytest <build-directory>/hoomd
After installing to an environment:
python3 -m pytest --pyargs hoomd
Note
python3 -m pytest --pyargs hoomd
tests the hoomd installation it finds by import hoomd
,
which may not be the one you just built. You must also change to a directory outside the
source, otherwise import hoomd
attempts to import the uncompiled source.
See also
See the pytest documentation for information on how to control output, select specific tests, and more.
Running tests with MPI
When ENABLE_MPI=ON
, CTest will execute some tests with mpirun -n 1
, some with -n 2
and some with -n 8
. Make sure your test environment (e.g. interactive cluster job) is correctly
configured before running ctest
.
pytest tests may also be executed with MPI with 2 ranks. pytest does not natively support MPI. Execute it with the provided wrapper script in the build directory:
mpirun -n 2 build/hoomd/hoomd/pytest/pytest-openmpi.sh -v -x build/hoomd
The wrapper script displays the outout of rank 0 and redirects rank 1’s output to a file. Inspect
this file when a test fails on rank 1. This will result in an MPI_ABORT
on rank 0 (assuming the
-x
argument is passed):
cat pytest.out.1
Warning
Pass the -x
option to prevent deadlocks when tests fail on only 1 rank.
Note
The provided wrapper script supports OpenMPI.
Executing long runing tests
Longer running tests do not execute by default. Run these with the --validate
command line
option to pytest:
$ python3 -m pytest build/hoomd --validate -m validate
$ mpirun -n 2 hoomd/pytest/pytest-openmpi.sh build/hoomd -v -x -ra --validate -m validate
Note
The -m validate
option selects only the long running tests.
Note
To run long running tests on an installed hoomd
package, you need to specify additional
options:
python3 -m pytest --pyargs hoomd -p hoomd.pytest_plugin_validate -m validate --validate
Implementing tests
Most tests should be implemented in pytest. HOOMD’s test rig provides a device
fixture that
most tests should use to cache the execution device across multiple tests and reduce test execution
time.
Important
Add any new test_*.py
files to the list in the corresponding CMakeLists.txt
file.
Only add C++ tests for classes that have no Python interface or otherwise require low level testing. If you are unsure, please check with the lead developers prior to adding new C++ tests. Add new validation tests to the hoomd-validation repository.
Components
Extend HOOMD-blue with a component implemented in C++ for performance-critical tasks, such
as pair potential evaluation. A component provides a number of related functionalities. For example,
the hoomd.hpmc
component enables hard particle Monte Carlo methods with HOOMD-blue.
Compile and install components built-in or as external components. The HOOMD-blue build process compiles all core and built-in components together, requiring one only one set of configure, make, and install commands. External components compile and link against a HOOMD-blue installation from a separate build directory with their own set of configure, make, and install commands. You may compile a component either way. When the end user is compiling HOOMD-blue and components from source, built-in components compile and install everything at once which minimizes chances for errors (e.g. building HOOMD-blue against python 3.6, but the component against python 3.7). External components provide more flexibility for packaging purposes.
The HOOMD-Blue source provides example component templates in the example_plugins
subdirectory. updater_plugin
demonstrates how to add a new update
command with both CPU and GPU
implementations, and pair_plugin
shows how to add a new MD pair potential.
Built-in components
You can fork HOOMD-blue and add your component directly, or you can create a separate source
repository for your component. Create a symbolic link to the component in the hoomd
source
directory to compile it as a built-in component:
$ ln -s <path-to-component>/<component> hoomd-blue/hoomd/<component>
Note
Built-in components may be used directly from the build directory or installed.
External components
To compile an external component, you must first install HOOMD-blue. Then, configure your component
with CMake and install it into the hoomd python library. Point CMAKE_PREFIX_PATH
at your virtual
environment (if needed) so that cmake can find HOOMD-blue:
$ cmake -B build/<component> -S <path-to-component>
$ cmake --build build/<component>
$ cmake --install build/<component>
The component build environment, including the compiler, CUDA, MPI, python, and other libraries, must match exactly with those used to build HOOMD-blue.
Note
External components must be installed before use.
Notation
The HOOMD-blue documentation uses the following mathematical notation.
General notation:
\(x\) |
Scalar. |
\(\vec{a}\) |
Vector. |
\(a\) |
Magnitude of the vector \(\vec{a}\). |
\(\hat{a}\) |
Unit vector in the direction of \(\vec{a}\). |
\(\mathbf{A}\) |
Matrix. |
\(\mathbf{b}\) |
Quaternion. |
\(\vert \mathbf{b} \vert\) |
Magnitude of a quaternion. |
\(i\), \(j\), \(k\) |
Indices. |
\(i\) |
\(\sqrt{-1}\) in some contexts. |
\(\mathrm{function}\) |
A mathematical function. |
a \([\mathrm{length}]^2\) |
The quantity “a” has dimensions of \(\mathrm{length}^2\). |
Symbol definitions:
\(\vec{v}_{ij}\) |
\(\vec{v}_j - \vec{v}_j\) |
\(\vec{r}\) |
Position. |
\(\vec{v}\) |
Velocity. |
\(\mathbf{q}\) |
Orientation. |
\(m\) |
Mass. |
\(\vec{p}\) |
Momentum. |
\(I\) |
Moment of inertia. |
\(q\) |
Charge. |
\(N\) |
Number. |
\(L\) |
Length. |
\(V\) |
Volume. |
\(P\) |
Pressure. |
\(\rho\) |
Number density. |
\(\vec{a}_1\), \(\vec{a}_2\), \(\vec{a}_3\) |
Box unit cell vectors. |
\(\vec{F}\) |
Force. |
\(\vec{\tau}\) |
Torque. |
\(U\) |
Potential energy. |
\(K\) |
Kinetic energy. |
\(E\) |
Total energy. |
\(T\) |
Temperature. |
\(k\) |
Boltzmann’s constant in some contexts. Typically appears multiplying temperature: \(kT\). |
\(k\) |
Spring constant in some contexts. |
\(\beta\) |
\(\frac{1}{kT}\) |
\(t\) |
Time. |
Units
HOOMD-blue does not adopt a particular system of units, nor does it offer a variety of systems to choose from. Instead, it follows a self-consistent system of units where all derived units (e.g. force) are defined in terms of base units (e.g. energy / length). To adopt a system of units for your simulations, choose a set of base units (e.g. meters versus centimeters for length), and then determine what the derived units are.
Base Units
The base units are:
\([\mathrm{energy}]\)
\([\mathrm{length}]\)
\([\mathrm{mass}]\)
Unit Conversion
Example unit conversions between derived units and base units:
Derived units |
Relation to base units |
---|---|
\([\mathrm{area}]\) |
\([\mathrm{length}]^2\) |
\([\mathrm{volume}]\) |
\([\mathrm{length}]^3\) |
\([\mathrm{time}]\) |
\([\mathrm{energy}]^{-1/2} \cdot [\mathrm{length}] \cdot [\mathrm{mass}]^{1/2}\) |
\([\mathrm{velocity}]\) |
\([\mathrm{energy}]^{1/2} \cdot [\mathrm{mass}]^{-1/2}\) |
\([\mathrm{force}]\) |
\([\mathrm{energy}] \cdot [\mathrm{length}]^{-1}\) |
\([\mathrm{pressure}]\) |
\([\mathrm{energy}] \cdot [\mathrm{length}]^{-3}\) |
\([\mathrm{charge}]\) |
\(\left(4 \pi \epsilon_{0} \cdot [\mathrm{energy}] \cdot [\mathrm{length}] \right)^{1/2}\) - where \(\epsilon_{0}\) is permittivity of free space |
Note
Most of the units on this page apply to MD simulations.
In HPMC, the primary unit is that of length. Mass is factored out of the partition function and does not enter into the simulation. In addition, the energy scale is irrelevant in athermal HPMC systems where overlapping energies are infinite and valid configurations have zero potential energy. However, energy does appear implicitly in derived units like \([\mathrm{pressure}] = [\mathrm{energy}] \cdot [\mathrm{length}]^{-3}\). In HPMC, \(kT\) is set to 1 \(\mathrm{energy}\).
Common unit systems
Example base and derived units for common MD unit systems.
Note
All conversion factors given here are computed with Wolfram Alpha using the provided links.
Unit |
AKMA |
MD |
---|---|---|
\([\mathrm{energy}]\) |
kcal/mol |
kJ/mol |
\([\mathrm{length}]\) |
Å |
nm |
\([\mathrm{mass}]\) |
atomic mass unit |
atomic mass unit |
\([\mathrm{area}]\) |
\(\mathrm{Å}^2\) |
\(\mathrm{nm}^2\) |
\([\mathrm{volume}]\) |
\(\mathrm{Å}^3\) |
\(\mathrm{nm}^3\) |
\([\mathrm{time}]\) |
||
\([\mathrm{velocity}]\) |
1 nm/ps |
|
\([\mathrm{force}]\) |
kcal/mol/Å |
kJ/mol/nm |
\([\mathrm{pressure}]\) |
||
\([\mathrm{charge}]\) |
||
\(k\) (Boltzmann’s constant) |
Deprecated
Features deprecated in v3.x may be removed in a future v4.0.0 release.
v3.x
Feature |
Replace with |
Deprecated in |
---|---|---|
Particle diameters |
Potentials such as |
v3.0.0 |
|
n/a: |
v3.1.0 |
|
n/a: |
v3.1.0 |
|
n/a: |
v3.4.0 |
|
|
v3.7.0 |
|
n/a |
v3.7.0 |
|
n/a |
v3.7.0 |
|
Pass charges to |
v3.7.0 |
|
Set diameters in system state. |
v3.7.0 |
Logo
Download the HOOMD-blue logo for use in posters and presentations.
Vertical:
Horizontal:
License
Copyright (c) 2009-2022 The Regents of the University of Michigan.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Libraries
HOOMD: HOOMD-blue is a continuation of the HOOMD project (http://www.ameslab.gov/hoomd/). The code from the original project is used under the following license:
Highly Optimized Object-Oriented Molecular Dynamics (HOOMD) Open
Source Software License
Copyright (c) 2008 Ames Laboratory Iowa State University
All rights reserved.
Redistribution and use of HOOMD, in source and binary forms, with or
without modification, are permitted, provided that the following
conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names HOOMD's
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
Disclaimer
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND
CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
Additionally, HOOMD-blue links to or compiles in code from the following libraries:
Sockets code from VMD, used under the UIUC Open Source License.
Molfile plugin code from VMD, used under the UIUC Open Source License:
University of Illinois Open Source License
Copyright 2006 Theoretical and Computational Biophysics Group,
All rights reserved.
Developed by: Theoretical and Computational Biophysics Group
University of Illinois at Urbana-Champaign
http://www.ks.uiuc.edu/
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the Software), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to
do so, subject to the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the documentation
and/or other materials provided with the distribution.
Neither the names of Theoretical and Computational Biophysics Group,
University of Illinois at Urbana-Champaign, nor the names of its contributors
may be used to endorse or promote products derived from this Software without
specific prior written permission.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS WITH THE SOFTWARE.
CUDA, used under the NVIDIA Software License Agreement.
kissFFT, used under the following license:
Copyright (c) 2003-2010 Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the author nor the names of any contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CUB, used under the following license:
Copyright (c) 2011, Duane Merrill. All rights reserved.
Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the NVIDIA CORPORATION nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Eigen, used under the Mozilla Public License v.2.0 (http://mozilla.org/MPL/2.0/).
BVLSSolver, is embedded in HOOMD’s package and is made available under the following license:
Copyright (c) 2015, Michael P. Howard. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
pybind11, used under the following license:
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You are under no obligation whatsoever to provide any bug fixes, patches, or
upgrades to the features, functionality or performance of the source code
("Enhancements") to anyone; however, if you choose to make your Enhancements
available either publicly, or directly to the author of this software, without
imposing a separate written license agreement for such Enhancements, then you
hereby grant the following license: a non-exclusive, royalty-free perpetual
license to install, use, modify, prepare derivative works, incorporate into
other computer software, distribute, and sublicense such enhancements or
derivative works thereof, in binary and source code form.
cereal, used under the BSD license:
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Random123, used under the following license:
Copyright 2010-2012, D. E. Shaw Research.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
A CUDA neighbor search library, used under the following license:
Copyright (c) 2018-2019, Michael P. Howard. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
LLVM, used under the Apache 2.0 license.
nano-signal-slot, used under the following license:
Copyright (c) 2012-2015 ApEk, NoAvailableAlias, Nano-signal-slot Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
hipper, used under the following license:
Copyright (c) 2020, Michael P. Howard. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
HIP is included under the following license:
Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
hipCUB, used under the following license:
Copyright (c) 2010-2011, Duane Merrill. All rights reserved.
Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved.
Modifications Copyright (c) 2019, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the NVIDIA CORPORATION nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rocPRIM, used under the following license:
Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
rocThrust, used under the Apache 2.0 license
rocFFT, used under the following license:
Copyright (c) 2016 Advanced Micro Devices, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
HOOMD-blue uses headers from jitify under the following license:
BSD 3-Clause License
Copyright (c) 2017-2019, NVIDIA Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
HOOMD uses the ECL code for connected components under the following license:
ECL-CC code: ECL-CC is a connected components algorithm. The CUDA
implementation thereof is very fast. It operates on graphs stored in
binary CSR format.
Copyright (c) 2017, Texas State University. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted for academic, research, experimental, or personal use provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Texas State University nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
For all other uses, please contact the Office for Commercialization and Industry
Relations at Texas State University <http://www.txstate.edu/ocir/>.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Authors: Jayadharini Jaiganesh and Martin Burtscher
Python, Used under the Python license
Other Attributions
HOOMD’s synced collection infrastructure is inspired from and in part derived from signac
’s
GitHub SyncedCollection
implementation under the
following license:
BSD 3-Clause License for the software signac.
Copyright (c) 2016, The Regents of the University of Michigan
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Credits
The following people have contributed to the to HOOMD-blue:
Aaron Keys, University of Michigan
Alain Kadar, University of Michigan
Alex Travesset, Iowa State University and Ames Laboratory
Alex Yang, Vanderbilt University
Alexander Hudson
Allen LaCour, University of Michigan
Alyssa Travitz, University of Michigan
Andrew Schultz, University at Buffalo
Andrew Mark, Max Planck Institute
Andrey Kazennov, Joint Institute for High Temperatures of RAS
Antonio Osorio, University of Michigan
Avisek Das, University of Michigan
Axel Kohlmeyer, Temple University
Ben Levine, Temple University
Ben Swerdlow, University of Michgan
Benjamin Schultz, University of Michgan
Bjørnar Jensen, University of Bergen
Bradley Dice, University of Michigan
Brandon Butler, University of Michigan
Brandon Denis Smith, University of Michigan
Bryan VanSaders, University of Michgan
Carl Simon Adorf, University of Michigan
Carolyn Phillips, University of Michigan
Charlie Slominski, Caltech
Chengyu Dai, University of Michigan
Chris Jones, Boise State University
Christoph Junghans
Christoph Klein, Vanderbilt University
Chrisy Du, University of Michigan
Cong Qiao, Brandeis University
Corwin Kerr, University of Michigan
Charlotte Zhao, University of Michigan
Dan Evans, University of Michigan
David LeBard, Temple University
Elizabeth R Chen, University of Michigan
Eric Harper, University of Michigan
Eric Irrgang, University of Michigan
Eric Jankowski, Boise State University
Erin Teich, University of Michigan
Fengyi Gao, University of Michigan
Gabrielle Jones, University of Michigan
Geert Kapteijns, University of Amsterdam
Greg van Anders, University of Michigan
Grey Garrett, University of Michigan
Ian Graham, University of Pennsylvania
Igor Morozov, Joint Institute for High Temperatures of RAS
Isaac Bruss, University of Michigan
Jakin B. Delony, University of South Florida
James Antonaglia, University of Michigan
James Proctor, University of Michigan
James W. Swan, Massachusetts Institute of Technology
Jenny Fothergill, Boise State University
Jens Glaser, Oak Ridge National Laboratory
Joseph Berleant, University of Michigan
Joshua A. Anderson, University of Michigan
Kelly Wang, University of Michigan
Kevin Daly, Princeton University
Kevin Kohlstedt, University of Michigan
Kevin Silmore, Princeton University
Khalid Ahmed, University of Michigan
Kody Takada, University of Michigan
Kristi Pepa, University of Michigan
Kwanghwi Je, University of Michigan
Lin Yang, Iowa State University
Ludwig Schneider, Georg-August Univeristy Goettingen
Luis Y. Rivera-Rivera, University of Michigan
Malcolm Ramsay
Marco Klement, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
Matthew Spellings, University of Michgan
Michael Howard, University of Texas
Mike Henry, Boise State University
Nathan Horst
Nipuli Gunaratne, University of Michigan
Pablo Zubieta, PME, The University of Chicago
Patrick Lawton, University of Michigan
Paul Dodd, University of Michigan
Pavani Medapuram Lakshmi Narasimha, University of Minnesota
Pengji Zhou, University of Michgan
Peter Palm, Leipzig University
Peter Schwendeman, University of Michigan
Philipp Mertmann, Ruhr University Bochum
Philipp Schönhöfer, University of Michigan
Praharsh Suryadevara, New York University
Rastko Sknepnek, Northwestern
Raymond Asare, University of Michigan
Richmond Newman, University of Michigan
Roman Bystryi, Joint Institute for High Temperatures of RAS
Ross Smith, University of Michigan
Ryan Marson, University of Michigan
Sam Nola, University of Michigan
Simone Ciarella, Eindhoven University of Technology
Shannon Moran, University of Michigan
Sophie YouJung Lee, University of Michigan
Stephen Thomas, Boise State University
Steve Barr, Princeton University
Sumedh R. Risbud, Massachusetts Institute of Technology
Thi Vo, University of Michigan
Tim Moore, University of Michigan
Tobias Dwyer, University of Michigan
Tommy Waltmann, University of Michigan
Trung Dac Nguyen, University of Michigan
Vyas Ramasubramani, University of Michigan
Wenbo Shen, University of Michigan
William Zygmunt, University of Michigan
Wouter Ellenbroek, Eindhoven University of Technology
Yuan Zhou, University of Michigan
Åsmund Ervik, SINTEF
Nathan Barrett, Pritzker School of Molecular Engineering