Source code for snap_simulate.system.molecules.grafted_colloid

import numpy as np


[docs] def make_grafted_colloid(mol_specs, particle_specs): mol_type = mol_specs.pop("molecule_type") if mol_type != "grafted_colloid": raise Exception(f"Cannot turn molecule of type {mol_type} into a grafted colloid") colloid_type = mol_specs["colloid_type"] M = mol_specs["arm_beads"] N = mol_specs["num_arms"] arm_type = mol_specs["arm_type"] end_type = mol_specs["end_type"] bond_type = mol_specs["bond_type"] # Convert arm_type to a list if a single int is provided if isinstance(arm_type, int): arm_types = [arm_type] * M else: arm_types = list(arm_type) if len(arm_types) != M: raise Exception("Length of arm_type list must match arm_beads count") diameters = particle_specs["diameters"] d_colloid = diameters[colloid_type] r_colloid = d_colloid / 2.0 # Pre-calculate arm bead types and distances from colloid center arm_bead_types = [] arm_distances = [] for bead in range(M): bead_type = end_type if bead == M - 1 else arm_types[bead] arm_bead_types.append(bead_type) r_curr = diameters[bead_type] / 2.0 if bead == 0: dist = r_colloid + r_curr else: r_prev = diameters[arm_bead_types[bead - 1]] / 2.0 dist = arm_distances[bead - 1] + r_prev + r_curr arm_distances.append(dist) Ntot = 1 + N * M nbonds = N * M particle_positions = np.zeros((Ntot, 3), dtype=float) particle_typeid = np.zeros(Ntot, dtype=int) particle_typeid[0] = colloid_type bond_groups = np.zeros((nbonds, 2), dtype=int) bond_typeid = np.zeros(nbonds, dtype=int) + bond_type # Generate Fibonacci sphere discretization of points on the unit sphere golden_ratio = (1.0 + np.sqrt(5.0)) / 2.0 points = np.arange(0, N, dtype=int) theta = 2.0 * np.pi * points / golden_ratio phi = np.arccos(1.0 - 2.0 * (points + 0.5) / N) for arm in range(N): # Calculate arm direction vector sin_phi = np.sin(phi[arm]) ux = np.cos(theta[arm]) * sin_phi uy = np.sin(theta[arm]) * sin_phi uz = np.cos(phi[arm]) for bead in range(M): idx = 1 + arm * M + bead bead_type = arm_bead_types[bead] particle_typeid[idx] = bead_type # Position computation r = arm_distances[bead] particle_positions[idx] = (r * ux, r * uy, r * uz) # Bonds structure bond_idx = arm * M + bead if bead == 0: bond_groups[bond_idx] = [0, idx] else: bond_groups[bond_idx] = [idx - 1, idx] 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