def empty_collection(self, item_cls, attached, attach_items): list_ = SyncedList(validation=_PartialIsInstance(item_cls), attach_members=attach_items) if attached: self._synced_list = [] list_._sync(DummySimulation(), self._synced_list) return list_
def test_init(op_list): def validate(x): return isinstance(x, DummyOperation) # Test automatic to_synced_list function generation slist = SyncedList(validation_func=validate) assert slist._validate == validate op = DummyOperation() assert slist._to_synced_list_conversion(op) is op # Test specified to_synced_list def cpp_identity(x): return x._cpp_obj slist = SyncedList(validation_func=validate, to_synced_list=cpp_identity) assert slist._to_synced_list_conversion == cpp_identity op._cpp_obj = 2 assert slist._to_synced_list_conversion(op) == 2 # Test full initialziation slist = SyncedList(validation_func=validate, to_synced_list=cpp_identity, iterable=op_list) assert len(slist._list) == 3 assert all(op._added for op in slist)
def __init__(self, walls=None, to_cpp=identity): self._walls = [] self._backend_list_index = [] self._backend_lists = { Sphere: SyncedList(Sphere, to_synced_list=to_cpp, attach_members=False), Cylinder: SyncedList(Cylinder, to_synced_list=to_cpp, attach_members=False), Plane: SyncedList(Plane, to_synced_list=to_cpp, attach_members=False) } if walls is None: return self.extend(walls)
def __init__(self, forces, constraints, methods): forces = [] if forces is None else forces constraints = [] if constraints is None else constraints methods = [] if methods is None else methods self._forces = SyncedList(lambda x: isinstance(x, Force), to_synced_list=lambda x: x._cpp_obj, iterable=forces) self._constraints = SyncedList( lambda x: isinstance(x, ConstraintForce), to_synced_list=lambda x: x._cpp_obj, iterable=constraints) self._methods = SyncedList(lambda x: isinstance(x, _Method), to_synced_list=lambda x: x._cpp_obj, iterable=methods)
def __init__(self): self._compute = list() self._scheduled = False self._updaters = SyncedList(OnlyType(Updater), _triggered_op_conversion) self._writers = SyncedList(OnlyType(Writer), _triggered_op_conversion) self._tuners = SyncedList(OnlyType(Tuner), lambda x: x._cpp_obj) self._computes = SyncedList(OnlyType(Compute), lambda x: x._cpp_obj) self._integrator = None self._tuners.append(ParticleSorter())
def test_synced(self): test_list = SyncedList(lambda x: x) assert not test_list._synced test_list._sync(None, []) assert test_list._synced test_list._unsync() assert not test_list._synced
def test_attach(): triggered_op = DummyTriggeredOp(trigger=1) sim = DummySimulation() slist = SyncedList(lambda x: isinstance(x, DummyTriggeredOp), lambda x: (x._cpp_obj, x.trigger)) slist.append(triggered_op) triggered_op._cpp_obj = DummyCppObj() slist._sync(sim, sim._cpp_sys.dummy_list) assert len(sim._cpp_sys.dummy_list) == 1 assert len(sim._cpp_sys.dummy_list[0]) == 2 assert triggered_op._cpp_obj == sim._cpp_sys.dummy_list[0][0] assert triggered_op.trigger == sim._cpp_sys.dummy_list[0][1]
def test_init(self, generate_plain_collection, item_cls): validate = _PartialIsInstance(item_cls) # Test automatic to_synced_list function generation synced_list = SyncedList(validation=validate) assert synced_list._validate == validate op = item_cls() assert synced_list._to_synced_list_conversion(op) is op # Test specified to_synced_list def cpp_identity(x): return x._cpp_obj # Test full initialziation plain_list = generate_plain_collection(5) synced_list = SyncedList(validation=validate, to_synced_list=cpp_identity, iterable=plain_list) assert synced_list._to_synced_list_conversion == cpp_identity op._cpp_obj = 2 assert synced_list._to_synced_list_conversion(op) == 2 assert all(op._added for op in synced_list) self.check_equivalent(plain_list, synced_list)
class Operations(Collection): """A mutable collection of operations which act on a `hoomd.Simulation`. The `Operations` class contains all the operations acting on a simulation. These operations are classes that perform various actions on a `hoomd.Simulation`. Operations can be added and removed at any point from a `hoomd.Operations` instance. The class provides the interface defined by `collections.abc.Collection`. Other methods for manipulating instances attempt to mimic Python objects where possible, but the class is not simply a mutable list or set. Since there are multiple types of operations in HOOMD-blue, `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. An `Operations` can only ever hold one integrator at a time. On the other hand, an `Operations` object can hold any number of tuners, updaters, writers, or computes. To see examples of these types of operations see `hoomd.tune` (tuners), `hoomd.update` (updaters), `hoomd.hpmc.integrate` or `hoomd.md.integrate` (integrators), , `hoomd.write` (writers), and `hoomd.md.thermo` (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 same `Operations` container more than once. All `Operations` instances start with a `hoomd.tune.ParticleSorter` instance in their ``tuners`` 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. """ def __init__(self): self._compute = list() self._scheduled = False self._updaters = SyncedList(OnlyType(Updater), _triggered_op_conversion) self._writers = SyncedList(OnlyType(Writer), _triggered_op_conversion) self._tuners = SyncedList(OnlyType(Tuner), lambda x: x._cpp_obj) self._computes = SyncedList(OnlyType(Compute), lambda x: x._cpp_obj) self._integrator = None self._tuners.append(ParticleSorter()) def _get_proper_container(self, operation): if isinstance(operation, Updater): return self._updaters elif isinstance(operation, Writer): return self._writers elif isinstance(operation, Tuner): return self._tuners elif isinstance(operation, Compute): return self._computes else: raise TypeError( f"{type(operation)} is not a valid operation type.") def add(self, operation): """Add an operation to this container. Adds the provided operation to the appropriate attribute of the `Operations` instance. Args: operation (`hoomd.operation.Operation`): A HOOMD-blue tuner, updater, integrator, writer, or compute, to add to the collection. Raises: ValueError: If ``operation`` already belongs to this or another `Operations` instance. 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, the ``integrator`` property cannot be set to ``None`` using this function. Use ``operations.integrator = None`` explicitly for this. """ # calling _add is handled by the synced lists and integrator property. # we raise this error here to provide a more clear error message. if operation._added: raise ValueError("The provided operation has already been added " "to an Operations instance.") if isinstance(operation, hoomd.integrate.BaseIntegrator): self.integrator = operation else: try: container = self._get_proper_container(operation) except TypeError: raise TypeError(f"Type {type(operation)} is not a valid " f"type to add to Operations.") container.append(operation) def __iadd__(self, operation): """Works the same as `Operations.add`. Args: operation (`hoomd.operation.Operation`): A HOOMD-blue tuner, updater, integrator, writer, or compute to add to the object. """ self.add(operation) return self def remove(self, operation): """Remove an operation from the `Operations` object. Remove the item from the collection whose id is the same as ``operation``. See `<https://docs.python.org/3/library/functions.html#id>`_ for the concept of a Python object id. Args: 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. """ if isinstance(operation, hoomd.integrate.BaseIntegrator): self.integrator = None else: try: container = self._get_proper_container(operation) except TypeError: raise TypeError(f"Type {type(operation)} is not a valid " f"type to remove from Operations.") container.remove(operation) def __isub__(self, operation): """Works the same as `Operations.remove`. Args: operation (`hoomd.operation.Operation`): A HOOMD-blue integrator, tuner, updater, integrator, analzyer, or compute to remove from the collection. """ self.remove(operation) return self @property def _sys_init(self): if self._simulation is None or self._simulation.state is None: return False else: return True def _schedule(self): """Prepares all operations for a `hoomd.Simulation.run` call. Creates the internal C++ objects for all operations. Raises: RuntimeError: raises when not associated with a `hoomd.Simulation` object. """ if not self._sys_init: raise RuntimeError("System not initialized yet") sim = self._simulation if not (self.integrator is None or self.integrator._attached): self.integrator._attach() if not self.updaters._synced: self.updaters._sync(sim, sim._cpp_sys.updaters) if not self.writers._synced: self.writers._sync(sim, sim._cpp_sys.analyzers) if not self.tuners._synced: self.tuners._sync(sim, sim._cpp_sys.tuners) if not self.computes._synced: self.computes._sync(sim, sim._cpp_sys.computes) self._scheduled = True def _unschedule(self): """Undo the effects of `Operations._schedule`.""" self._integrator._detach() self._writers._unsync() self._updaters._unsync() self._tuners._unsync() self._computes._unsync() self._scheduled = False def _store_reader(self, reader): # TODO pass def __contains__(self, operation): """Whether an operation is contained in this container. Args: operation: Returns whether this exact operation is contained in the collection. """ return any(op is operation for op in self) def __iter__(self): """Iterates through all contained operations.""" integrator = (self._integrator, ) if self._integrator else [] yield from chain(self._tuners, self._updaters, integrator, self._writers, self._computes) def __len__(self): """Return the number of operations contained in this collection.""" return len(list(self)) @property def integrator(self): """`hoomd.integrate.BaseIntegrator`: An MD or HPMC integrator object. `Operations` objects have an initial ``integrator`` property of ``None``. Can be set to MD or HPMC integrators. The property can also be set to ``None``. """ return self._integrator @integrator.setter def integrator(self, op): if op is not None: if not isinstance(op, hoomd.integrate.BaseIntegrator): raise TypeError("Cannot set integrator to a type not derived " "from hoomd.integrate.BaseIntegrator") if op._added: raise RuntimeError("Integrator cannot be added to twice to " "Operations collection.") else: op._add(self._simulation) old_ref = self.integrator self._integrator = op # Handle attaching and detaching integrators dealing with None values if self._scheduled: if op is not None: op._attach() if old_ref is not None: old_ref._notify_disconnect(self._simulation) old_ref._detach() old_ref._remove() @property def updaters(self): """list[`hoomd.operation.Updater`]: A list of updater operations. Holds the list of updaters associated with this collection. The list can be modified as a standard Python list. """ return self._updaters @property def writers(self): """list[`hoomd.operation.Writer`]: A list of writer operations. Holds the list of writers associated with this collection. The list can be modified as a standard Python list. """ return self._writers @property def tuners(self): """list[`hoomd.operation.Tuner`]: A list of tuner operations. Holds the list of tuners associated with this collection. The list can be modified as a standard Python list. """ return self._tuners @property def computes(self): """list[`hoomd.operation.Compute`]: A list of tuner operations. Holds the list of tuners associated with this collection. The list can be modified as a standard Python list. """ return self._computes
def islist(slist_empty): return SyncedList(lambda x: isinstance(x, int), iterable=[OpInt(i) for i in [1, 2, 3]])
def slist_empty(): return SyncedList(lambda x: isinstance(x, Operation))
def islist(slist_empty): return SyncedList(_PartialIsInstance(int), iterable=[OpInt(i) for i in [1, 2, 3]])
def slist_empty(): return SyncedList(_PartialIsInstance(Operation))