Source code for snap_simulate.system.molecules.ring_polymer
import numpy as np
[docs]
def make_ring_polymer(mol_specs, particle_specs):
mol_type = mol_specs.pop("molecule_type")
if mol_type != "ring_polymer":
raise Exception(f"Cannot turn molecule of type {mol_type} into a ring polymer")
beads = mol_specs["beads"]
bead_type = mol_specs.get("bead_type")
if bead_type is None:
bead_type = mol_specs["bead_types"] # fallback if they specify bead_types
bond_type = mol_specs["bond_type"]
# Convert bead_type to a list if a single int is provided
if isinstance(bead_type, int):
bead_type_list = [bead_type] * beads
else:
bead_type_list = list(bead_type)
if len(bead_type_list) != beads:
raise Exception("Length of bead_type list must match beads count")
diameters = particle_specs["diameters"]
particle_typeid = np.zeros(beads, dtype=int)
for i in range(beads):
particle_typeid[i] = bead_type_list[i]
# Calculate average diameter
d_avg = np.mean([diameters[t] for t in bead_type_list])
# Calculate radius of the ring
# Circumference = beads * d_avg = 2 * pi * R => R = beads * d_avg / (2 * pi)
R = (beads * d_avg) / (2 * np.pi)
particle_positions = np.zeros((beads, 3), dtype=float)
for i in range(beads):
theta = 2.0 * np.pi * i / beads
particle_positions[i, 0] = R * np.cos(theta)
particle_positions[i, 1] = R * np.sin(theta)
particle_positions[i, 2] = 0.0
# Generate bonds (closed loop)
nbonds = beads
bond_groups = np.zeros((nbonds, 2), dtype=int)
bond_typeid = np.zeros(nbonds, dtype=int) + bond_type
for i in range(beads - 1):
bond_groups[i] = [i, i+1]
bond_groups[beads - 1] = [beads - 1, 0]
new_mol_specs = dict(
bond_typeid=bond_typeid.tolist(),
bond_groups=bond_groups.tolist(),
angle_typeid=[],
angle_groups=[],
particle_typeid=particle_typeid.tolist(),
particle_positions=particle_positions.tolist()
)
return new_mol_specs