Composite objects in hoobas¶
The core component of hoobas is the hoobas.Composite.CompositeObject, a structure used to represent any
complex object: individual molecules, colloids, lipid bilayers, etc. The builder class, meant
to represent the whole system is also a composite object.
Prototype-builder design pattern
Composite objects are based on a prototype-builder design pattern. When an composite object is instanciated, it does not have any beads or bonds. For the purpose of demonstrating how it works internally, let us use a polydisperse Kremer-Grest model, a series of beads connected by bonds, where each chain has a different number of bonds. The prototype part is the constructor, which may look like
class KremerGrestChain(Composite.CompositeObject):
def __init__(self, length):
self.len = length
To make a polydisperse chain, one may initialize this class with a function, like so
import numpy as np
polydisperse_kremergrest = KremerGrestChain(lambda: return np.random.randint(10, 20))
The builder part comes into play when an actual chain needs to be included somewhere. This happens whenever an already built object tries to incorporate a non-built object.
The hoobas.Build.Builder class is always built as it represents the simulation as
a whole and adding any composite object to it will result in copying the prototype and building it. For instance, the following
code would result in the Kremer-Grest object to be copied and built 10 times
domain = hoobas.SimulationDomain.EmptyBox(10.0)
builder = hoobas.Build.Builder(domain)
builder.add_N_ext_objects(polydisperse_kremergrest, 10)
The act of building an object in hoobas is simply a call to hoobas.Composite.CompositeObject.build()
method, followed by a call to hoobas.Composite.CompositeObject.build_finalize() method. The first
one generates the current object, while the second takes care of any topology modifications, for insteance
if polydisperse Kremer-Grest chains were grafted to polydisperse Kremer-Grest chains. Since prototypes
are copied, values can normally be safely overwritten. The builder part for our chain may look like
class KremerGrestChain(Composite.CompositeObject):
def build():
self.len = length()
self.beads += hoobas.CGBead.Bead()
for i in range(1, self.len):
self.beads += hoobas.CGBead.Bead()
self.bonds += ['KGBond', i-1, i]
Moving through topology
Topology is managed by various classes in hoobas. For the user, bonded classes (bonds, angles, dihedrals) can be thought as simple objects with 2 attributes, a tuple for which particles are bonded and a name for the type of bond. A three particle bond (angle) can be thought of the following class:
class Angle()
def __init__(self, idict):
self.topology_tuple = idict['topology_tuple']
self.topology_name = idict['topology_name']
Where topology_tuple may be (0,1,2) for instance and topology_name the string ‘SomeAngle’. The constructor also support lists, for which the argument would be [‘SomeAngle’, 0, 1, 2]. The collection of bonds, angle, dihedrals, impropers and distance constraints can be thought as a simple list. It can be iterated over, which yields objects of the appropriate class, addressed by index, supports a contains method and augmented addition. This means that the following python code is valid syntax
for angle in composite.angles:
print angle.topology_tuple
if 'SomeAngle' in composite.angles:
print 'This will print if any angle has the topology_name SomeAngle'
composite.angles += hoobas.Composite.Angle(['AnotherAngleType', 0, 1, 2])
composite.angles += anothercomposite.angles
first_angle_in_list = composite.angles[0]
A graph is also kept of all bonded particles through the use of networkx package.
Topology force-fields
Hoobas keeps track of bonded force-fields