def add_capsule(self, particle_type, force_constant, center, direction, length, radius): force_constant = self._units.convert(force_constant, self._units.force_constant_unit) center = self._units.convert(center, self._units.length_unit) direction = self._units.convert(direction, self._units.length_unit) length = self._units.convert(length, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) self._registry.add_capsule(particle_type, force_constant, _v3_of(center), _v3_of(direction), length, radius)
def add_box(self, particle_type, force_constant, origin, extent): """ Adds a box potential acting with a harmonic force on particles of the given type once they leave the area spanned by the cuboid that has `origin` as its front lower left and `origin+extent` as its back upper right vertex, respectively. :param particle_type: the particle type for which the potential is registered :param force_constant: the force constant [energy/length**2] :param origin: the origin of the box [length] :param extent: the extent of the box [length] """ force_constant = self._units.convert(force_constant, self._units.force_constant_unit) origin = self._units.convert(origin, self._units.length_unit) extent = self._units.convert(extent, self._units.length_unit) self._registry.add_box(particle_type, force_constant, _v3_of(origin), _v3_of(extent))
def add_sphere(self, conversions, name, origin, radius, larger_or_less=False): """ Registers a spherical compartment. The sphere is defined by an origin and a radius. Depending on the flag `larger_or_less`, the compartment will be the outside (True) of the sphere or the inside (False) of the sphere. The characteristic function of the sphere compartment for a position x is | x - origin | > radius (`larger_or_less` = True) or | x - origin | < radius (`larger_or_less` = False) If the characteristic function evaluates to True for a particle position, the conversions will be applied. :param conversions: dictionary of particle types, converting keys to values :param name: label for the compartment :param origin: origin of the sphere :param radius: radius of the sphere :param larger_or_less: determines if the compartment is outside/True or inside/False of the sphere """ origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) if not isinstance(conversions, dict) or len(conversions) == 0: raise ValueError("conversions must be a dictionary with at least one entry") if not isinstance(name, str): raise ValueError("name must be a string") if not radius > 0.: raise ValueError("radius must be positive") if not isinstance(larger_or_less, bool): raise ValueError("larger_or_less must be a bool") self._compartments.add_sphere(conversions, name, _v3_of(origin), radius, larger_or_less)
def add_plane(self, conversions, name, normal_coefficients, distance, larger_or_less=True): """ Registers a planar compartment. The plane is defined in Hesse normal form by a normal vector and a distance. Depending on the flag `larger_or_less`, the compartment will be where the normal points or on the other side. The characteristic function of the plane compartment for a position x is x * normal_coefficients - distance > 0 (`larger_or_less` = True) or x * normal_coefficients - distance < 0 (`larger_or_less` = False) If the characteristic function evaluates to True for a particle position, the conversions will be applied. :param conversions: dictionary of particle types, converting keys to values :param name: label for the compartment :param normal_coefficients: normal coefficients of the plane according to Hesse normal form :param distance: shorted distance of the plane from the origin (0,0,0) according to Hesse normal form :param larger_or_less: determines if the compartment is where the normal points/True or on the other side/False """ normal_coefficients = self._units.convert(normal_coefficients, self._units.length_unit) distance = self._units.convert(distance, self._units.length_unit) if not isinstance(conversions, dict) or len(conversions) == 0: raise ValueError("conversions must be a dictionary with at least one entry") if not isinstance(name, str): raise ValueError("name must be a string") if not distance >= 0.: raise ValueError("distance must be non-negative") if not isinstance(larger_or_less, bool): raise ValueError("larger_or_less must be a bool") self._compartments.add_plane(conversions, name, _v3_of(normal_coefficients), distance, larger_or_less)
def add_plane(self, conversions, name, normal_coefficients, distance, larger_or_less=True): """ Registers a planar compartment. The plane is defined in Hesse normal form by a normal vector and a distance. Depending on the flag `larger_or_less`, the compartment will be where the normal points or on the other side. The characteristic function of the plane compartment for a position x is x * normal_coefficients - distance > 0 (`larger_or_less` = True) or x * normal_coefficients - distance < 0 (`larger_or_less` = False) If the characteristic function evaluates to True for a particle position, the conversions will be applied. :param conversions: dictionary of particle types, converting keys to values :param name: label for the compartment :param normal_coefficients: normal coefficients of the plane according to Hesse normal form :param distance: shorted distance of the plane from the origin (0,0,0) according to Hesse normal form :param larger_or_less: determines if the compartment is where the normal points/True or on the other side/False """ normal_coefficients = self._units.convert(normal_coefficients, self._units.length_unit) distance = self._units.convert(distance, self._units.length_unit) if not isinstance(conversions, dict) or len(conversions) == 0: raise ValueError("conversions must be a dictionary with at least one entry") if not isinstance(name, str): raise ValueError("name must be a string") if not distance >= 0.: raise ValueError("distance must be non-negative") if not isinstance(larger_or_less, bool): raise ValueError("larger_or_less must be a bool") self._compartments.add_plane(conversions, name, _v3_of(normal_coefficients), distance, larger_or_less)
def add_sphere(self, conversions, name, origin, radius, larger_or_less=False): """ Registers a spherical compartment. The sphere is defined by an origin and a radius. Depending on the flag `larger_or_less`, the compartment will be the outside (True) of the sphere or the inside (False) of the sphere. The characteristic function of the sphere compartment for a position x is | x - origin | > radius (`larger_or_less` = True) or | x - origin | < radius (`larger_or_less` = False) If the characteristic function evaluates to True for a particle position, the conversions will be applied. :param conversions: dictionary of particle types, converting keys to values :param name: label for the compartment :param origin: origin of the sphere :param radius: radius of the sphere :param larger_or_less: determines if the compartment is outside/True or inside/False of the sphere """ origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) if not isinstance(conversions, dict) or len(conversions) == 0: raise ValueError("conversions must be a dictionary with at least one entry") if not isinstance(name, str): raise ValueError("name must be a string") if not radius > 0.: raise ValueError("radius must be positive") if not isinstance(larger_or_less, bool): raise ValueError("larger_or_less must be a bool") self._compartments.add_sphere(conversions, name, _v3_of(origin), radius, larger_or_less)
def box_size(self, value): """ Sets the system's box size :param value: the box size (list or tuple of length 3, numpy scalar array of squeezed shape (3,)) [length] """ value = self._unit_conf.convert(value, self.length_unit) v3 = _v3_of(value) self._context.box_size = [v3[0], v3[1], v3[2]]
def box_size(self, value): """ Sets the system's box size :param value: the box size (list or tuple of length 3, numpy scalar array of squeezed shape (3,)) [length] """ value = self._unit_conf.convert(value, self.length_unit) v3 = _v3_of(value) self._context.box_size = [v3[0], v3[1], v3[2]]
def add_particle(self, type, position): """ Adds a particle of a certain type to a certain position in the simulation box. :param type: the type :param position: the position (ndarray or tuple or list of length 3) [length] """ position = self._unit_conf.convert(position, self.length_unit) self._simulation.add_particle(type, _v3_of(position))
def change_particle_position(self, vertex, new_position): """ Changes the particle position of the to vertex associated particle to the given position. :param vertex: the vertex or its index (obtainable from `topology.get_graph().get_vertices()`) :param type_to: the target particle type :return: a reference to this recipe to enable a fluent interface """ self._recipe.change_particle_position(vertex, _v3_of(new_position)) return self
def change_particle_position(self, vertex, new_position): """ Changes the particle position of the to vertex associated particle to the given position. :param vertex: the vertex or its index (obtainable from `topology.get_graph().get_vertices()`) :param type_to: the target particle type :return: a reference to this recipe to enable a fluent interface """ self._recipe.change_particle_position(vertex, _v3_of(new_position)) return self
def add_particle(self, type, position): """ Adds a particle of a certain type to a certain position in the simulation box. :param type: the type :param position: the position (ndarray or tuple or list of length 3) [length] """ position = self._unit_conf.convert(position, self.length_unit) self._simulation.add_particle(type, _v3_of(position))
def add_cylinder(self, particle_type, force_constant, origin, normal, radius, inclusion: bool): """ A potential that keeps particles inside or outside a cylindrical volume. Particles penetrating the boundary are harmonically pushed back again. :param particle_type: the particle type :param force_constant: the strength of the confining force [energy/length**2] :param origin: any point on the axis of the cylinder [length] :param normal: direction of the axis of the cylinder [length] :param radius: radius of the cylinder [length] :param inclusion: if true, the potential will include particles, otherwise exclude them from the volume """ force_constant = self._units.convert(force_constant, self._units.force_constant_unit) origin = self._units.convert(origin, self._units.length_unit) normal = self._units.convert(normal, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) assert force_constant > 0, "force_constant has to be positive" assert radius > 0, "radius has to be positive" self._registry.add_cylinder(particle_type, force_constant, _v3_of(origin), _v3_of(normal), radius, inclusion)
def append_particle(self, neighbor_vertices, particle_type, position): """ Creates a new particle of type `particle_type` (which should be a topology particle type) at position `position`, inserts it into the topology and connects the newly created particles' vertex to the given `neighbor_vertices`. :param neighbor_vertices: the neighbors of the newly inserted vertex :param particle_type: the to-be created particle's type :param position: the position :return: a reference to this recipe to enable a fluent interface """ self._recipe.append_particle(neighbor_vertices, particle_type, _v3_of(position)) return self
def append_particle(self, neighbor_vertices, particle_type, position): """ Creates a new particle of type `particle_type` (which should be a topology particle type) at position `position`, inserts it into the topology and connects the newly created particles' vertex to the given `neighbor_vertices`. :param neighbor_vertices: the neighbors of the newly inserted vertex :param particle_type: the to-be created particle's type :param position: the position :return: a reference to this recipe to enable a fluent interface """ self._recipe.append_particle(neighbor_vertices, particle_type, _v3_of(position)) return self
def add_sphere_in(self, particle_type, force_constant, origin, radius): """ Adds a spherical potential that keeps particles of a certain type restrained to the inside of the specified sphere. :param particle_type: the particle type :param force_constant: strength of the potential [energy/length**2] :param origin: origin of the sphere [length] :param radius: radius of the sphere [length] """ force_constant = self._units.convert(force_constant, self._units.force_constant_unit) origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) assert radius > 0, "radius has to be positive" self._registry.add_sphere_in(particle_type, force_constant, _v3_of(origin), radius)
def add_sphere(self, particle_type, force_constant, origin, radius, inclusion: bool): """ Adds a spherical potential that keeps particles of a certain type restrained to the inside or outside of the specified sphere. :param particle_type: the particle type :param force_constant: strength of the potential [energy/length**2] :param origin: origin of the sphere [length] :param radius: radius of the sphere [length] :param inclusion: if true, the potential will include particles, otherwise exclude them from the volume """ force_constant = self._units.convert(force_constant, self._units.force_constant_unit) origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) assert radius > 0, "radius has to be positive" self._registry.add_sphere(particle_type, force_constant, _v3_of(origin), radius, inclusion)
def add_sphere_in(self, particle_type, force_constant, origin, radius): """ Adds a spherical potential that keeps particles of a certain type restrained to the inside of the specified sphere. :param particle_type: the particle type :param force_constant: strength of the potential [energy/length**2] :param origin: origin of the sphere [length] :param radius: radius of the sphere [length] """ force_constant = self._units.convert(force_constant, self._units.force_constant_unit) origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) assert radius > 0, "radius has to be positive" self._registry.add_sphere_in(particle_type, force_constant, _v3_of(origin), radius)
def add_spherical_barrier(self, particle_type, height, width, origin, radius): """ A potential that forms a concentric barrier at a certain radius around a given origin. It is given a height (in terms of energy) and a width. Note that the height can also be negative, then this potential acts as a 'sticky' sphere. The potential consists of harmonic snippets, such that the energy landscape is continuous and differentiable, the force is only continuous and not differentiable. :param particle_type: the particle type :param height: the height of the barrier [energy] :param width: the width of the barrier [length] :param origin: the origin of the sphere [length] :param radius: the radius of the sphere [length] """ height = self._units.convert(height, self._units.energy_unit) width = self._units.convert(width, self._units.length_unit) origin = self._units.convert(origin, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) assert radius > 0, "radius has to be positive" assert height > 0, "height has to be positive" assert width > 0, "width has to be positive" self._registry.add_spherical_barrier(particle_type, height, width, _v3_of(origin), radius)
def create_capsule(self, center, direction, radius, length): center = self._units.convert(center, self._units.length_unit) direction = self._units.convert(direction, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) length = self._units.convert(length, self._units.length_unit) return _geom.Capsule(_v3_of(center), _v3_of(direction), radius, length)
def create_sphere(self, center, radius): center = self._units.convert(center, self._units.length_unit) radius = self._units.convert(radius, self._units.length_unit) return _geom.Sphere(_v3_of(center), radius)
def create_box(self, v0, v1): v0 = self._units.convert(v0, self._units.length_unit) v1 = self._units.convert(v1, self._units.length_unit) return _geom.Box(_v3_of(v0), _v3_of(v1))