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