Skip to content

Commit

Permalink
Merge pull request #1628 from glotzerlab/yet-more-sybil
Browse files Browse the repository at this point in the history
Add Sybil examples to most classes in the root hoomd namespace.
  • Loading branch information
joaander committed Oct 10, 2023
2 parents 7540cb4 + 98041de commit da748d0
Show file tree
Hide file tree
Showing 37 changed files with 1,016 additions and 365 deletions.
3 changes: 0 additions & 3 deletions hoomd/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ def setup_sybil_tests(namespace):
pattern='*.py',
# exclude files not yet tested with sybil
excludes=[
'custom/custom_action.py',
'data/typeconverter.py',
'data/typeparam.py',
'hpmc/pair/user.py',
],
setup=setup_sybil_tests,
Expand Down
43 changes: 23 additions & 20 deletions hoomd/custom/custom_action.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Copyright (c) 2009-2023 The Regents of the University of Michigan.
# Part of HOOMD-blue, released under the BSD 3-Clause License.

"""Implement Action."""
"""Implement Action.
.. invisible-code-block: python
simulation = hoomd.util.make_example_simulation()
logger = hoomd.logging.Logger()
"""

from abc import ABCMeta, abstractmethod
from enum import IntEnum
Expand All @@ -20,55 +26,52 @@ def __init__(cls, name, base, dct):
class Action(metaclass=_AbstractLoggable):
"""Base class for user-defined actions.
To implement a custom operation in Python, subclass `Action` and
implement the :meth:`~.act` method to perform the desired action. To
To implement a custom operation in Python, subclass `hoomd.custom.Action`
and implement the :meth:`~.act` method to perform the desired action. To
include the action in the simulation run loop, pass an instance of the
action to `hoomd.update.CustomUpdater`, `hoomd.write.CustomWriter`, or
`hoomd.tune.CustomTuner`.
.. code-block:: python
from hoomd.custom import Action
.. rubric:: Examples:
.. code-block:: python
class ExampleAction(Action):
class ExampleAction(hoomd.custom.Action):
def act(self, timestep):
self.com = self._state.snapshot.particles.position.mean(axis=0)
snapshot = self._state.get_snapshot()
if snapshot.communicator.rank == 0:
self.com = 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.
appropriate flags from the internal `Action.Flags` enumeration:
.. code-block:: python
from hoomd.custom import Action
class ExampleActionWithFlag(Action):
class ExampleAction(hoomd.custom.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.
Use the `hoomd.logging.log` decorator to define loggable properties:
.. code-block:: python
from hoomd.python_action import Action
from hoomd.logging import log
class ExampleAction(hoomd.custom.Action):
class ExampleActionWithFlag(Action):
@log
@hoomd.logging.log
def answer(self):
return 42
def act(self, timestep):
pass
example_action = ExampleAction()
logger.add(example_action, quantities=['answer'])
Attributes:
flags (list[Action.Flags]): List of flags from the
`Action.Flags`. Used to tell the integrator if
Expand Down
60 changes: 21 additions & 39 deletions hoomd/data/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,44 +334,35 @@ def coerce_mock_to_array(val):


class HOOMDArray(metaclass=_wrap_class_factory(_wrap_list)):
"""A NumPy like interface to internal HOOMD-blue data.
"""A numpy.ndarray-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 a `numpy.ndarray` object through NumPy's provided
HOOMD-blue's zero copy local snapshot API
(`hoomd.State.cpu_local_snapshot`) returns `HOOMDArray` objects.
`HOOMDArray` acts like `numpy.ndarray` through NumPy's provided
`interface <https://numpy.org/doc/stable/reference/arrays.classes.html>`_.
Some exceptions are the ``view``, ``resize``, ``flat`` and ``flatiter``
methods and the ``data`` and ``base`` properties. For typical use cases,
understanding this class is not necessary. Treat it as a ``numpy.ndarray``.
methods and the ``data`` and ``base`` properties.
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 a `HOOMDArray`. To ensure memory safety, a
`HOOMDArray` 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)``).
To ensure memory safety, a `HOOMDArray` object cannot be accessed outside of
the context manager in which it was created. Make an explicit copy to use
the array elsewhere (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 a ``numpy.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.
``numpy.ndarray`` whenever possible.
.. rubric:: Performance Tips
*Assume* ``a`` *represents a* `HOOMDArray` *for examples given.*
*Let* ``a`` *represent a* `HOOMDArray`.
* Place the ``HOOMDArray`` to the left of the expression
(e.g. ``a + b + c`` is faster than ``b + a + c``). This has to do with
the mechanisms ``HOOMDArray`` 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.
* Make copies 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``), using
Expand Down Expand Up @@ -725,41 +716,32 @@ class HOOMDGPUArray(_NoGPU):


_gpu_array_docs = """
Exposes an internal HOOMD-blue GPU buffer.
A __cuda_array_interface__ to internal HOOMD-blue data on the GPU.
The HOOMDGPUArray object exposes a GPU data buffer using the
The HOOMDGPUArray object exposes a GPU data buffer using
`__cuda_array_interface__
<https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html>`_.
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:
memory accesses (`hoomd.State.gpu_local_snapshot`). To avoid errors, use arrays
only within the relevant context manager. For example:
.. code-block:: python
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.
When CuPy can be imported, then this class wraps much of the
``cupy.ndarray`` class's functionality. Otherwise, this class exposes only
the buffer.
`HOOMDGPUArray` always supports getting (but not setting) the ``shape``,
``strides``, and ``ndim`` 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.
When CuPy can be imported, slice/element assignment (e.g.
``array[0] = 1; array[:2] = 4``) and compound assignment operators (e.g. ``+=``,
``-=``, ``*=``) are available. In addition, most methods besides ``view``,
``resize``, ``flat``, ``flatiter`` are available. The same is true for
Expand Down
68 changes: 41 additions & 27 deletions hoomd/data/local_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ def _exit(self):
class ParticleLocalAccessBase(_LocalAccess):
"""Class for directly accessing HOOMD-blue particle data.
Note:
Changing some attributes (such as ``velocity`` and ``acceleration``)
may not alter the trajectory of the system as you would expect.
The `md.Integrator` is responsible for integrating the equations of
motion and manages the values in these arrays.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_particles) `hoomd.data.array` object of ``float``):
The integer type of a particle.
Expand Down Expand Up @@ -133,15 +144,6 @@ class ParticleLocalAccessBase(_LocalAccess):
Net virial on particle :math:`[\\mathrm{energy}]`.
net_energy ((N_particles,) `hoomd.data.array` object of ``float``):
Net energy of a particle :math:`[\\mathrm{energy}]`.
Note:
Changing some attributes (such as ``velocity`` and ``acceleration``)
may not alter the trajectory of the system as you would expect.
The `md.Integrator` is responsible for integrating the equations of
motion and manages the values in these arrays.
See Also:
`hoomd.State`
"""

@property
Expand Down Expand Up @@ -203,6 +205,11 @@ def __init__(self, state):
class BondLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue bond data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_bonds) `hoomd.data.array` object of ``int``):
The integer type of a bond.
Expand All @@ -216,16 +223,18 @@ class BondLocalAccessBase(_GroupLocalAccess):
The bond reverse tags. For a given bond tag ``tag``,
``i = bonds.rtag[tag]`` is the array index holding that
bond.
See Also:
`hoomd.State`
"""
_cpp_get_data_method_name = "getBondData"


class AngleLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue angle data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_angles) `hoomd.data.array` object of ``int``):
The integer type of a angle.
Expand All @@ -238,16 +247,18 @@ class AngleLocalAccessBase(_GroupLocalAccess):
rtag ((N_angles_global) `hoomd.data.array` object of ``int``):
The angle reverse tags. For a given angle tag ``tag``, ``i =
angles.rtag[tag]`` is the array index holding that angle.
See Also:
`hoomd.State`
"""
_cpp_get_data_method_name = "getAngleData"


class DihedralLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue dihedral data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_dihedrals) `hoomd.data.array` object of ``int``): The integer
type of a dihedral.
Expand All @@ -260,16 +271,18 @@ class DihedralLocalAccessBase(_GroupLocalAccess):
rtag ((N_dihedrals_global) `hoomd.data.array` object of ``int``):
The dihedral reverse tags. For a given dihedral tag ``tag``, ``i
= dihedrals.rtag[tag]`` is the array index holding that dihedral.
See Also:
`hoomd.State`
"""
_cpp_get_data_method_name = "getDihedralData"


class ImproperLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue improper data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_impropers) `hoomd.data.array` object of ``int``):
The integer type of a improper.
Expand All @@ -282,16 +295,18 @@ class ImproperLocalAccessBase(_GroupLocalAccess):
rtag ((N_impropers_global) `hoomd.data.array` object of ``int``):
The improper reverse tags. For a given improper tag ``tag``, ``i
= impropers.rtag[tag]`` is the array index holding that improper.
See Also:
`hoomd.State`
"""
_cpp_get_data_method_name = "getImproperData"


class ConstraintLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue constraint data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
value ((N_constraints) `hoomd.data.array` object of ``float``): The
constaint value.
Expand All @@ -305,9 +320,6 @@ class ConstraintLocalAccessBase(_GroupLocalAccess):
The constraint reverse tags. For a given constraint tag ``tag``,
``i = constraints.rtag[tag]`` is the array index holding that
constraint.
See Also:
`hoomd.State`
"""
_fields = {
'value': 'getTypeVal',
Expand All @@ -321,6 +333,11 @@ class ConstraintLocalAccessBase(_GroupLocalAccess):
class PairLocalAccessBase(_GroupLocalAccess):
"""Class for directly accessing HOOMD-blue special pair data.
See Also:
* `hoomd.State`
* `hoomd.data.LocalSnapshot`
* `hoomd.data.LocalSnapshotGPU`
Attributes:
typeid ((N_pairs) `hoomd.data.array` object of ``float``): The type of
special pair.
Expand All @@ -334,9 +351,6 @@ class PairLocalAccessBase(_GroupLocalAccess):
The special pair reverse tags. For a given special pair tag
``tag``, ``i = pairs.rtag[tag]`` is the array index holding that
special pair.
See Also:
`hoomd.State`
"""
_cpp_get_data_method_name = "getPairData"

Expand Down
4 changes: 4 additions & 0 deletions hoomd/data/local_access_cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ class LocalSnapshot(_LocalSnapshot):
For the ``LocalAccess`` classes the affixed attributes mentioned above
are not shown. Also of interest, ghost data always come immediately
after the regular data.
See Also:
Access the local snapshot of a state via
`hoomd.State.cpu_local_snapshot`.
"""

def __init__(self, state):
Expand Down
4 changes: 4 additions & 0 deletions hoomd/data/local_access_gpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ class LocalSnapshotGPU(_NoGPU, _LocalSnapshot):
All array-like properties return a `hoomd.data.array.HOOMDGPUArray` object which
prevents invalid memory accesses.
See Also:
Access the local snapshot of a state via
`hoomd.State.gpu_local_snapshot`.
"""

LocalSnapshotGPU.__doc__ = _gpu_snapshot_docs

0 comments on commit da748d0

Please sign in to comment.