def lmps_min(s, name, settings): """pysimm.apps.polymatic.lmps_min Runs LAMMPS minimization for the Polymatic algorithm. Args: s: :class:`~pysimm.system.System` to minimize name: name of simulation settings: object containing Polymatic settings Returns: result from :func:`~pysimm.lmps.minimize` """ if settings.polym.min.cluster: nanohub = {'cores': int(settings.polym.min.nanohub_cores), 'walltime': int(settings.polym.min.nanohub_walltime)} log_name = '%s' % '_'.join(name.split()) else: nanohub = {} log_name = 'logs/%s' % '_'.join(name.split()) if settings.polym.min.user_input: sim = lmps.Simulation(s, name='initial optimization', print_to_screen=False, nanohub=nanohub, custom=True) sim.add(settings.polym.min.min_in) sim.run(np=settings.np, nanohub=nanohub) else: sim = lmps.Simulation(s, name='initial optimization', print_to_screen=False, nanohub=nanohub, log=log_name ) sim.add(lmps.Init(cutoff=settings.polym.min.nb_cutoff, forcefield=settings.forcefield)) sim.add_min( min_style='sd', etol=settings.polym.min.sd_etol, ftol=settings.polym.min.sd_ftol, maxiter=settings.polym.min.sd_maxiter, maxeval=settings.polym.min.sd_maxeval, ) sim.add_min( min_style='cg', etol=settings.polym.min.cg_etol, ftol=settings.polym.min.cg_ftol, maxiter=settings.polym.min.cg_maxiter, maxeval=settings.polym.min.cg_maxeval, ) sim.run(np=settings.np, nanohub=nanohub) if settings.polym.min.cluster: shutil.move(log_name, 'logs') return True
def equil(s, **kwargs): """pysimm.apps.equilibrate.equil Runs a 21-step compression/decompression equilibration algorithm Args: s: :class:`~pysimm.system.System` object tmax: maximum temperature during equilibration pmax: maximum pressure during equilibration tfinal: desired final temperature of final system pfinal: desired final pressure of final system np: number of processors to use during equilibration simulations p_steps: list of pressures to use during equilibration (must match length of length_list) length_list: list of simulation durations to use during equilibration (must match length of p_steps) Returns: None """ nb_cutoff = kwargs.get('nb_cutoff', 12.0) tmax = kwargs.get('tmax', 1000) pmax = kwargs.get('pmax', 50000) tfinal = kwargs.get('tfinal', 300) pfinal = kwargs.get('pfinal', 1) nanohub = kwargs.get('nanohub') np = kwargs.get('np') p_list = kwargs.get('p_steps') if not p_list: p_list = [0.02*pmax, 0.6*pmax, pmax, 0.5*pmax, 0.1*pmax, 0.01*pmax, pfinal] length_list = kwargs.get('length_list') if not length_list: length_list = [100000, 100000, 100000, 100000, 100000, 100000, 100000] dump = kwargs.get('dump') or 1000 dump_append = kwargs.get('dump_append') if kwargs.get('dump_append') is not None else True scale_v = kwargs.get('scale_v') if kwargs.get('scale_v') is not None else True settings = {'dump': dump, 'cutoff': nb_cutoff, 'dump_append': dump_append, 'scale_v': scale_v} sim = lmps.Simulation(s, name='equil') sim.add_min(nanohub=nanohub, cutoff=nb_cutoff, np=np) sim.add_md(new_v=True, temp=tfinal, nanohub=nanohub, cutoff=nb_cutoff, np=np) step = 0 for p, l in izip(p_list, length_list): step += 1 if l: sim.add_md(length=l/2, temp=tmax, **settings) sim.add_md(length=l, temp=tfinal, **settings) sim.add_md(length=l/2, ensemble='npt', temp=tfinal, pressure=p, **settings) sim.run(np=np, nanohub=nanohub) s.write_lammps('equil.lmps') s.write_xyz('equil.xyz')
def run(test=False): logFileName = 'steps.log' # use an import from .yaml to get of previously created pmma-based 4-chain polymer structure polymer = system.read_yaml(os.path.join(os.path.dirname(os.path.realpath(__file__)), "polymer.yaml")) polymer.forcefield = 'dreiding' # Initialize the wrapper object around the polymer that will organize the work with LAMMPS print('Creating Simulation object with log-file in "{0:s}"\n'.format(logFileName)) sim = lmps.Simulation(polymer, log= 'steps.log') # setting up the parameters for the energy optimization # add_min() method will add the "Minimization" task to the task que of the # Simulation object that is stored in sim.sim list print('Creating and running energy-minimization task:') sim.add_min(min_style = 'fire', name = 'min_fire', etol = 1.0e-5, ftol = 1.0e-5) print('Creating and running molecular dynamics task:') # Let's set up the Molecular dynamics task sim.add_md(ensemble='nvt', timestep=0.5) print('List of simulation tasks ready to run:') print(sim.sim) print('Input that will be passed to LAMMPS when the simulation is performed:') sim.write_input() print(sim.input) # call run to run the simulation sim.run()
def constrained_opt(s, m, active): """pysimm.apps.random_walk.constrained_opt This function is called by redo_monomer_insertion and optimizes polymer chain s while keeping the last monomer fixed. Args: s: :class:`~pysimm.system.System` is a polymer chain in which the last monomer insertion has generated a hardcore overlap m: reference monomer :class:`~pysimm.system.System`. Must be a capped monomer, with headCap and tail_cap as the first and last atoms in the .mol file. Returns: nothing; all changes to the polymer chain are written to the argument s_ """ print("Constrained Opt...") sim = lmps.Simulation(s, name='constrained_opt') total_atoms = s.particles.count monomer_atoms = m.particles.count p = s.particles[total_atoms] sim.add_custom("group last_monomer id " + str(total_atoms - monomer_atoms) + ":" + str(total_atoms)) sim.add_custom( "group prev_two_monomers id " + str(total_atoms - 3 * monomer_atoms) + ":" + str(total_atoms - monomer_atoms)) sim.add_custom("group non_last_monomers subtract all last_monomer") sim.add_custom("region insertion_area sphere {0} {1} {2} 20 side out units box".format(p.x, p.y, p.z)) sim.add_custom("group 20_ang_away region insertion_area") sim.add_custom("group last_monomer_and_far union 20_ang_away last_monomer") if (active == "system"): sim.add_custom("fix freeze last_monomer setforce 0.0 0.0 0.0") elif (active == "monomer"): sim.add_custom("fix freeze non_last_monomers setforce 0.0 0.0 0.0") elif (active == "nearby"): sim.add_custom("fix freeze last_monomer_and_far setforce 0.0 0.0 0.0") sim.add_min(min_style="cg") sim.run()
def cap_with_methyls(input_sst, ff): ''' An utility method that implements capping of free ends of polymer chains with methyl groups in all-atom forcefield representation ''' # Let's cap the oligomer with the methyl (-CH3) group captypes = [] for cpn in ['CG331', 'HGA3']: tmp = input_sst.particle_types.get(cpn) if tmp: cpt = tmp[0] else: cpt = ff.particle_types.get(cpn)[0].copy() input_sst.particle_types.add(cpt) captypes.append(cpt) for p in input_sst.particles: if p.linker is not None: if len(p.bonded_to) < 4: # assuming that the linker atom is sp3 hybridised C let's define the last non-occupied direction # of the tetrahedron dir = numpy.zeros(3) for p_ in p.bonded_to: dir += numpy.array([p.x, p.y, p.z]) - numpy.array([p_.x, p_.y, p_.z]) dir = dir / numpy.linalg.norm(dir) cap_c = system.Particle(x=p.x + 1.53 * dir[0], y=p.y + 1.53 * dir[1], z=p.z + 1.53 * dir[2], type=captypes[0]) input_sst.add_particle_bonded_to(cap_c, p, f=ff) dir_h = numpy.array([1.0, 1.0, 1.0]) dir_h[0] = -(dir_h[1] * dir[1] + dir_h[2] * dir[2]) / dir[0] dir_h = dir_h / numpy.linalg.norm(dir_h) dir_h2 = numpy.array([1.0, 1.0, -1.0]) dir_h2[1] = (dir[2] / dir[0] - dir_h[2] / dir_h[0]) / (dir[1] / dir[0] - dir_h[1] / dir_h[0]) dir_h2[0] = dir[2] / dir[0] - dir[1] * dir_h2[1] / dir[0] dir_h2 = dir_h2 / numpy.linalg.norm(dir_h2) stretch = 0.78 input_sst.add_particle_bonded_to(system.Particle(x=cap_c.x + stretch * dir[0] + stretch * dir_h[0], y=cap_c.y + stretch * dir[1] + stretch * dir_h[1], z=cap_c.z + stretch * dir[2] + stretch * dir_h[2], type=captypes[1]), cap_c, f=ff) input_sst.add_particle_bonded_to(system.Particle(x=cap_c.x + stretch * dir[0] + stretch * dir_h2[0], y=cap_c.y + stretch * dir[1] + stretch * dir_h2[1], z=cap_c.z + stretch * dir[2] + stretch * dir_h2[2], type=captypes[1]), cap_c, f=ff) input_sst.add_particle_bonded_to(system.Particle(x=cap_c.x + stretch * dir[0] - stretch * dir_h2[0], y=cap_c.y + stretch * dir[1] - stretch * dir_h2[1], z=cap_c.z + stretch * dir[2] - stretch * dir_h2[2], type=captypes[1]), cap_c, f=ff) input_sst.objectify() input_sst.center(what='particles', at=[0.0, 0.0, 0.0], move_both=False) sim = lmps.Simulation(input_sst, log='capping_opt.log') sim.add_min(min_style='cg', name='min_cg', etol=1.0e-6, ftol=1.0e-6, maxiter=int(1e+6), maxeval=int(1e+7)) sim.run()
def lmps_cycle_npt_md(s, bonds, settings): """pysimm.apps.polymatic.lmps_cycle_npt_md Runs LAMMPS npt cycle md for the Polymatic algorithm. Args: s: :class:`~pysimm.system.System` to minimize bonds: number of bond to be made settings: object containing Polymatic settings Returns: result from lmps.md """ if settings.polym.cycle_npt.cluster: nanohub = {'cores': int(settings.polym.cycle_npt.nanohub_cores), 'walltime': int(settings.polym.cycle_npt.nanohub_walltime)} log_name = 'cycle_npt_%03d' % bonds else: nanohub = {} log_name = 'logs/cycle_npt_%03d' % bonds if settings.polym.cycle_npt.user_input: sim = lmps.Simulation(s, name='bond %d cycle npt' % bonds, print_to_screen=False, nanohub=nanohub, custom=True) sim.add(settings.polym.cycle_npt.step_in) sim.run(np=settings.np, nanohub=nanohub) else: sim = lmps.Simulation(s, name='bond %d cycle npt' % bonds, print_to_screen=False, nanohub=nanohub, log=log_name ) sim.add(lmps.Init(cutoff=settings.polym.cycle_npt.nb_cutoff, forcefield=settings.forcefield)) sim.add(lmps.Velocity(temperature=settings.polym.cycle_npt.temp)) sim.add_md( ensemble='npt', temperature=settings.polym.cycle_npt.nb_cutoff, run=settings.polym.cycle_npt.length, pressure=settings.polym.cycle_npt.pressure, ) sim.run(np=settings.np, nanohub=nanohub) if settings.polym.cycle_npt.cluster: shutil.move(log_name, 'logs') return True
def lmps_step_md(s, bonds, attempt, settings): """pysimm.apps.polymatic.lmps_step_md Runs LAMMPS step md for the Polymatic algorithm. Args: s: :class:`~pysimm.system.System` to minimize bonds: number of bond to be made attempt: number of bonding attempt settings: object containing Polymatic settings Returns: result from :func:`~pysimm.lmps.md` """ if settings.polym.step.cluster: nanohub = {'cores': int(settings.polym.step.nanohub_cores), 'walltime': int(settings.polym.step.nanohub_walltime)} log_name = 'step_%03d_%03d' % (bonds, attempt) else: nanohub = {} log_name = 'logs/step_%03d_%03d' % (bonds, attempt) if settings.polym.step.user_input: sim = lmps.Simulation(s, name='bond %s attempt #%d' % (bonds + 1, attempt), print_to_screen=False, nanohub=nanohub, custom=True) sim.add(settings.polym.step.step_in) sim.run(np=settings.np, nanohub=nanohub) else: sim = lmps.Simulation(s, name='bond %s: attempt #%d' % (bonds + 1, attempt), print_to_screen=False, nanohub=nanohub, log=log_name ) sim.add(lmps.Init(cutoff=settings.polym.step.nb_cutoff, forcefield=settings.forcefield)) sim.add(lmps.Velocity(temperature=settings.polym.step.temp)) sim.add_md( ensemble='nvt', temperature=settings.polym.step.temp, run=settings.polym.step.length, ) sim.run(np=settings.np, nanohub=nanohub) if settings.polym.step.cluster: shutil.move(log_name, 'logs') return True
def equilibrate_npt(self): sim = lmps.Simulation(self.polymer) sim.add( lmps.OutputSettings(dump={ 'freq': 10000, 'filename': 'dump.equil.npt.*' }, thermo={'freq': 1000})) sim.add_md(ensemble='npt', temperature=self.equil_temp, length=self.equil_npt_length) sim.run(np=self.nproc)
def equil(s, **kwargs): """pysimm.apps.equilibrate.equil Runs a 21-step compression/decompression equilibration algorithm Args: s: :class:`~pysimm.system.System` object tmax: maximum temperature during equilibration pmax: maximum pressure during equilibration tfinal: desired final temperature of final system pfinal: desired final pressure of final system np: number of processors to use during equilibration simulations p_steps: list of pressures to use during equilibration (must match length of length_list) length_list: list of simulation durations to use during equilibration (must match length of p_steps) Returns: None """ tmax = kwargs.get('tmax', 1000) pmax = kwargs.get('pmax', 50000) tfinal = kwargs.get('tfinal', 300) pfinal = kwargs.get('pfinal', 1) init = kwargs.get('init') output_settings = kwargs.get('output_settings') np = kwargs.get('np') p_list = kwargs.get('p_steps', [0.02*pmax, 0.6*pmax, pmax, 0.5*pmax, 0.1*pmax, 0.01*pmax, pfinal]) length_list = kwargs.get('length_list', [100000, 100000, 100000, 100000, 100000, 100000, 100000]) sim = lmps.Simulation(s, name='equil', **kwargs) if init: sim.add(init) if output_settings: sim.add(output_settings) sim.add(lmps.Velocity(temperature=tfinal)) step = 0 for p, l in izip(p_list, length_list): step += 1 if l: sim.add_md(length=l/2, ensemble='nvt', temperature=tmax, **kwargs) sim.add_md(length=l, ensemble='nvt', temperature=tfinal, **kwargs) sim.add_md(length=l/2, ensemble='npt', temperature=tfinal, pressure=p, **kwargs) sim.run(np=np) s.write_lammps('equil.lmps') s.write_xyz('equil.xyz')
def stepwise_cooling(self): sim = lmps.Simulation(self.polymer, name='cool', log='log.cool') if self.calc_voronoi: sim.add('compute voronoi all voronoi/atom') sim.add(self.cool_output) for temp in self.cool_temp_range: velocity = lmps.Velocity(style='scale', temperature=temp) md = lmps.MolecularDynamics(ensemble='npt', temperature=temp, pressure=1., run=self.cool_step_time, timestep=1) sim.add(velocity) sim.add(md) sim.run(np=self.nproc)
def monomer(ff, is_capped=False): try: s = system.read_pubchem_smiles('CCc1=cc=cc=c1') except: import os s = system.read_mol( os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, 'topologies', 'CCc1=cc=cc=c1.mol')) for b in s.bonds: if b.a.bonds.count == 3 and b.b.bonds.count == 3: b.order = 4 c1 = s.particles[1] c5 = s.particles[5] c1.linker = 'head' c5.linker = 'tail' if not is_capped: for b in c1.bonds: if b.a.elem == 'H' or b.b.elem == 'H': pb = b.a if b.b is c1 else b.b s.particles.remove(pb.tag, update=False) break for b in c5.bonds: if b.a.elem == 'H' or b.b.elem == 'H': pb = b.a if b.b is c5 else b.b s.particles.remove(pb.tag, update=False) break s.remove_spare_bonding() s.apply_forcefield(ff, charges='gasteiger') s.set_box(padding=10) sim = lmps.Simulation(s, print_to_screen=False, log='ps_mon_relax.log') sim.add(lmps.Init()) sim.add_min(min_style='fire') sim.run() s.add_particle_bonding() return s
def run(test=False): try: ethanol = system.read_pubchem_smiles('CCO') except: import os ethanol = system.read_mol(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'CCO.mol')) try: acetone = system.read_pubchem_smiles('CC(=O)C') except: import os acetone = system.read_mol(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'CC(=O)C.mol')) f = forcefield.Gaff2() ethanol.apply_forcefield(f, charges='gasteiger') acetone.apply_forcefield(f, charges='gasteiger') # amber.calc_charges(ethanol) # amber.calc_charges(acetone) lmps.quick_min(ethanol, min_style='fire') lmps.quick_min(acetone, min_style='fire') molecule_list = [ethanol, acetone] if test: n_molecules = [20, 20] else: n_molecules = [200, 200] s = system.replicate(molecule_list, n_molecules, density=0.3) min_settings = { 'name': 'cg_min', 'min_style': 'cg', 'maxiter': int(5e+5), 'maxeval': int(5e+6), } nvt_settings = { 'name': 'nvt_md', 'print_to_screen': True, 'ensemble': 'nvt', 'temperature': { 'start': 100, 'stop': 300 }, 'new_v': True, 'length': 2500 } npt_settings = { 'name': 'npt_md', 'print_to_screen': True, 'ensemble': 'npt', 'temperature': 300, 'new_v': True, 'pressure': { 'start': 1000, 'stop': 1 }, 'length': 5000, } npt_settings_add = { 'name': 'npt_md', 'print_to_screen': True, 'ensemble': 'npt', 'temperature': 300, 'new_v': True, 'pressure': { 'start': 1, 'stop': 1 }, 'length': 5000, } if test: nvt_settings['length'] = 2000 npt_settings['length'] = 2000 sim = lmps.Simulation(s) sim.add_min(**min_settings) sim.add(lmps.OutputSettings(thermo={'freq': 500, 'style': 'custom', 'args': ['step', 'temp', 'etotal', 'press', 'density']})) sim.add_md(**nvt_settings) sim.add_md(**npt_settings) sim.add_md(**npt_settings_add) sim.run() s.write_yaml('mixture.yaml') s.write_lammps('mixture.lmps')
def random_walk_tacticity(m, nmon, s_=None, **kwargs): """pysimm.apps.random_walk.random_walk_tacticity Builds homopolymer with controllable tacticity from capped monomer structure Args: m: reference monomer :class:`~pysimm.system.System`. Must be a capped monomer, with headCap and tail_cap as the first and last atoms in the .mol file. nmon: total number of monomers to add to chain s_: :class:`~pysimm.system.System` in which to build polymer chain (None) extra_bonds: EXPERMINTAL, True if making ladder backbone polymer settings: dictionary of simulation settings density: density at which to build polymer (0.3) forcefield: :class:`~pysimm.forcefield.Forcefield` object to acquire new force field parameters unwrap: True to unwrap final system debug: Boolean; print extra-output (False) traj: True to build xyz trajectory of polymer growth (True) limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY) sim: :class:`~pysimm.lmps.Simulation` object for relaxation between polymer growth tacticity: float between 0 and 1. 1 = 100% isotactic insertions 0 = 100% syndiotactic insertions 0.5 = equal changes of isotactic or syndiotactic insertions (i.e. atactic) rotation: degrees to rotate monomer per insertion md_spacing: how many monomer insertion steps to perform between MD relaxation steps (1) error_check: True/False for if monomers should be checked for hardcore overlaps after insertion Returns: new polymer :class:`~pysimm.system.System` """ m = m.copy() extra_bonds = kwargs.get('extra_bonds', False) settings = kwargs.get('settings', {}) density = kwargs.get('density', 0.3) f = kwargs.get('forcefield') unwrap = kwargs.get('unwrap') traj = kwargs.get('traj', True) debug = kwargs.get('debug', False) limit = kwargs.get('limit', 0.1) sim = kwargs.get('sim') tacticity = kwargs.get('tacticity', 0.5) if tacticity == 'atactic': tacticity = 0.5 elif tacticity == 'isotactic': tacticity = 1 elif tacticity == 'syndiotactic': tacticity = 0 elif not (0 <= tacticity <= 1): sys.exit("tacticity must be a number between 0 and 1, or 'atactic' (0.5), " "'isotactic' (1), or 'syndiotactic' (0)") tact_seq = [False] * round((nmon - 1) * tacticity) + [True] * ((nmon - 1) - round((nmon - 1) * tacticity)) random.shuffle(tact_seq) rotation = kwargs.get('rotation', 0) md_spacing = kwargs.get('md_spacing', 1) error_check = kwargs.get('error_check', False) m.add_particle_bonding() if error_check: lmps.quick_min(m, min_style='fire') # Automatically redefine linkers if they have specially defined names for p in m.particles: if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'): p.linker = 'head' elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('T'): p.linker = 'tail' m.remove_linker_types() # Check whether the monomer is decorated correctly if not __check_tags__(m.particles): sys.exit("random_walk:random_walk_tacticity() requires a **monomer capped with a single atom** as an input" " (i.e. to model polyethylene, ethane as a monomer is required). \n" "\tIn addition to 'head' and 'tail', 3 other tags should be defined: \n" "\t\t(i) p.linker = 'mirror' for a particle that defines plane for iso- syndio- tactic reflection \n" "\t\t(ii) p.rnd_wlk_tag = 'head_cap' and p.rnd_wlk_tag = 'tail_cap' for particles that capping head " "and tail linkers correspondingly \n \t\t(see the example #13 of this distribution for details)") # Remove tail-cap if it exists for p in m.particles: if p.linker == 'tail': for p_ in p.bonded_to: if p_.rnd_wlk_tag == 'tail_cap': p.charge += p_.charge # unite charge of tailcap into head m.particles.remove(p_.tag) # remove tailcap of monomer m.remove_spare_bonding() break # Add first monomer to the output system if s_ is None: s = system.replicate(m, 1, density=density / nmon) else: s = system.replicate(m, 1, s_=s_, density=None) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon)) if traj: s.write_xyz('random_walk.xyz') s.add_particle_bonding() # Main polymerisation loop for insertion in range(nmon - 1): n = m.copy() head = None tail = None mirror_atom = None for p in n.particles: if p.linker == 'head': head = p elif p.linker == 'tail': tail = p elif p.linker == 'mirror': mirror_atom = p backbone_vector = np.array(find_last_backbone_vector(s, m)) tail_vector = np.array(find_last_tail_vector(s.particles[-n.particles.count:])) for p, p_ in zip(s.particles[-1 * n.particles.count:], n.particles): # translate monomer a = 1.1 # coefficient of displacement of a new monomer along the head--tail direction b = 2.4 # coefficient of displacement of a new monomer along the head--headcap direction p_.x = p.x + a * backbone_vector[0] + b * tail_vector[0] p_.y = p.y + a * backbone_vector[1] + b * tail_vector[1] p_.z = p.z + a * backbone_vector[2] + b * tail_vector[2] if tact_seq[insertion]: # if syndiotactic insertion, reflect monomer print("syndiotactic insertion...") mirrorPlane = define_plane(head, tail, mirror_atom) for p in n.particles: p.x, p.y, p.z = reflect_coords_thru_plane([p.x, p.y, p.z], mirrorPlane) else: # else isotatic insertion, rotate monomer if necessary print("isotatic insertion...") if rotation != 0: # rotate monomer, if necessary rot_mat = rot_mat_about_axis(backbone_vector, rotation) n.rotate(around=head, rot_matrix=rot_mat) for p_ in s.particles[-n.particles.count:]: if p_.rnd_wlk_tag == 'head_cap': head.charge += p_.charge # unite charge of head_cap into tail atom s.particles.remove(p_.tag) # Removing head_cap atom from growing chain s.remove_spare_bonding() break if extra_bonds: heads = [] for p in s.particles[-n.particles.count:]: if p.linker == 'head': heads.append(p) else: for p in s.particles[-n.particles.count:]: if p.linker == 'head': head = p s.add(n, change_dim=False) s.add_particle_bonding() if extra_bonds: tails = [] for p in s.particles[-n.particles.count:]: if p.linker == 'tail': tails.append(p) else: for p in s.particles[-n.particles.count:]: if p.linker == 'tail': tail = p if debug: for p in s.particles: if not p.bonded_to: print(p.tag) if head and tail: s.make_new_bonds(head, tail, f) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) elif extra_bonds and len(heads) == len(tails): for h, t in zip(heads, tails): s.make_new_bonds(h, t, f) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) else: print('cannot find head and tail') if sim is None: sim = lmps.Simulation(s, name='relax_%03d' % (insertion + 2), log='relax.log', **settings) if (insertion + 2) % md_spacing == 0: sim.add_md(ensemble='nve', limit=limit, **settings) # sim.add_min(**settings) if isinstance(sim, lmps.Simulation): s_ = s.copy() sim.system = s sim.name = 'relax_%03d' % (insertion + 2) sim.run(np=settings.get('np')) energy = lmps.energy(s) print("LAMMPS Energy = " + str(energy)) print("LAMMPS Energy/#ofAtoms = " + str(energy / s.particles.count)) if error_check == True: # check for hardcore overlap print("checking for hardcore overlap") if s.quality(tolerance=0.3) > 0: print("Found bad quality monomer insertion. Redoing last insertion...") s.unwrap() s.write_xyz('bad_insertion_' + str(insertion + 2) + '.xyz') s.wrap() redo_monomer_insertion(s_, n, insertion + 2) s = s_.copy() if traj: s.unwrap() s.write_xyz('random_walk.xyz', append=True) # Removing the very last 'head_cap' at the end of the chain for p_ in s.particles[-n.particles.count:]: if p_.rnd_wlk_tag == 'head_cap': head.charge += p_.charge # unite charge of head_cap into tail atom s.particles.remove(p_.tag) # Removing head_cap atom from growing chain s.remove_spare_bonding() # Syncronizing molecule representation with particles ItemContainer representation for the chain s.objectify() if debug: s.write_lammps('polymer.lmps') s.write_xyz('polymer.xyz') s.unwrap() return s
def run(test=False): # we'll make a polystyrene monomer from the pysimm models database A = NbTMS(isomer="exoexo") # we'll instantiate a Dreiding forcefield object for use later f = forcefield.Dreiding() # the monomers do not have any charges, so we will derive partial charges using the gasteiger algorithm A.apply_charges(f, charges='gasteiger') # the buckingham potential isn't great at small distances, and therefore we use the LJ potential while growing the polymer A.pair_style = 'lj/cut' # run the polymer random walk tacticity method with 10 total repeat units polymer = random_walk_tacticity(A, 20, forcefield=f, capped=True, tacticity='syndiotactic', rotation=180, errorCheck=False, sim=0) writeFileFormats(polymer, "polymer", unwrap=True) #quick opt of polymer lmps.quick_min(polymer, min_style='fire', etol=1.0e-4, maxiter=100000) # write a few different file formats polymer.unwrap() writeFileFormats(polymer, "polymer_fired") #pack multiple copies of polymer polymers = system.replicate(polymer, 8, density=0.005) #polymers = polymer writeFileFormats(polymers, "polymers") lmps.quick_min(polymers, min_style='fire', etol=1.0e-4, maxiter=100000) writeFileFormats(polymers, "polymers_fired") #quickmd nvt_settings = { 'name': 'nvt_md', 'print_to_screen': True, 'ensemble': 'nvt', 'temperature': { 'start': 100, 'stop': 300 }, 'new_v': True, 'length': 10000 } npt_settings = { 'name': 'npt_md', 'print_to_screen': True, 'ensemble': 'npt', 'temperature': 300, 'new_v': True, 'pressure': { 'start': 1000, 'stop': 1 }, 'length': 100000, 'thermo_style': 'custom step temp press density' } #nvt runs okay, but npt fails...need to add neigh_modify command to reneighbor more often during compression of npt step #lmps.quick_md(polymers, debug=True, **nvt_settings) #writeFileFormats(polymers,"polymers_nvt") #lmps.quick_md(polymers, debug=True, **npt_settings) #lmps.quick_md(polymers) #writeFileFormats(polymers,"polymers_npt") sim = lmps.Simulation(polymers, name='nptAndReneighbor', debug=True) sim.add_custom('neigh_modify delay 0') sim.add(lmps.Velocity(temperature=1000)) sim.add_md(length=10000, ensemble='npt', temperature=1000, pressure=5000) sim.run() writeFileFormats(polymers, "polymers_npt") writeFileFormats(polymers, "polymers_npt_unwrapped", unwrap=True) #21-step equilibration equil(polymers, np=1, pmax=50000) writeFileFormats(polymers, "polymers_equil") polymers.unwrap() writeFileFormats(polymers, "polymers_equil_unwrap")
def random_walk(m, nmon, s_=None, **kwargs): """pysimm.apps.random_walk.random_walk Builds homopolymer using random walk methodology Args: m: reference monomer :class:`~pysimm.system.System` nmon: total number of monomers to add to chain s_: :class:`~pysimm.system.System` in which to build polymer chain (None) extra_bonds: EXPERMINTAL, True if making ladder backbone polymer geometry_rule: a pointer to a method that orients series of atoms of the next repetitive unit in random run settings: dictionary of simulation settings density: density at which to build polymer (0.3) forcefield: :class:`~pysimm.forcefield.Forcefield` object to acquire new force field parameters capped: True/False if monomers are capped unwrap: True to unwrap final system traj: True to build xyz trajectory of polymer growth (True) limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY) sim: :class:`~pysimm.lmps.Simulation` object for relaxation between polymer growth debug: Boolean; print extra-output Returns: new polymer :class:`~pysimm.system.System` """ m = m.copy() extra_bonds = kwargs.get('extra_bonds', False) displ_next_unit = kwargs.get('geometry_rule', displ_next_unit_default) settings = kwargs.get('settings', {}) density = kwargs.get('density', 0.3) f = kwargs.get('forcefield') capped = kwargs.get('capped') unwrap = kwargs.get('unwrap') traj = kwargs.get('traj', True) limit = kwargs.get('limit', 0.1) sim = kwargs.get('sim') debug = kwargs.get('debug', False) m.add_particle_bonding() for p in m.particles: if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'): p.linker = 'head' elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('T'): p.linker = 'tail' m.remove_linker_types() if s_ is None: s = system.replicate(m, 1, density=density/nmon) else: s = system.replicate(m, 1, s_=s_, density=None) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon)) if traj: s.write_xyz('random_walk.xyz') # Remove tail-cap if it exists if capped: if __check_tags__(m, req_tags=['tail', 'tail_cap']): for p in m.particles: if p.linker == 'tail': for p_ in p.bonded_to: if p_.rnd_wlk_tag == 'tail_cap': p.charge += p_.charge # unite charge of tailcap into head m.particles.remove(p_.tag) # remove tailcap of monomer m.remove_spare_bonding() break m.add_particle_bonding() else: sys.exit("The capped flag is on, however, the 'tail_cap' atom is not defined") for insertion in range(nmon - 1): head = None tail = None info = displ_next_unit(m, s.particles[-1 * m.particles.count:]) n = m.copy() if extra_bonds: heads = [] for p in s.particles[-1*n.particles.count:]: if p.linker == 'head': heads.append(p) else: for p in s.particles[-1*n.particles.count:]: if p.linker == 'head': head = p # Remove head-cap if it exists if capped: if __check_tags__(m, req_tags=['head_cap']): for p_ in s.particles[-m.particles.count:]: if p_.rnd_wlk_tag == 'head_cap': head.charge += p_.charge # unite charge of head_cap into tail atom s.particles.remove(p_.tag) # Removing head_cap atom from growing chain s.remove_spare_bonding() break s.add_particle_bonding() else: sys.exit("The capped flag is on, however, the 'head_cap' atom is not defined") s.add(n, change_dim=False) s.add_particle_bonding() if extra_bonds: tails = [] for p in s.particles[-1*n.particles.count:]: if p.linker == 'tail': tails.append(p) else: for p in s.particles[-1*n.particles.count:]: if p.linker == 'tail': tail = p if debug: for p in s.particles: if not p.bonded_to: print(p.tag) if head and tail: s.make_new_bonds(head, tail, f) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) elif extra_bonds and (len(heads) == len(tails)): order = [(0, 0), (1, 1)] if len(info) == 2: order = [(0, info[0]), (1, info[1])] for elm in order: s.make_new_bonds(heads[elm[0]], tails[elm[1]], f) ''' for h, t, ord in zip(heads, tails, extra_bonds): s.make_new_bonds(h, tails[ord], f) ''' print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) s.write_lammps('curr_progress.lmps') else: print('cannot find head and tail') if sim is None: sim = lmps.Simulation(s, name='relax_%03d' % (insertion + 2), log='relax.log', **settings) sim.add_md(ensemble='nve', limit=limit, **settings) sim.add_min(**settings) if isinstance(sim, lmps.Simulation): sim.system = s sim.name = 'relax_%03d' % (insertion + 2) sim.run(np=settings.get('np')) if traj: s.unwrap() s.write_xyz('random_walk.xyz', append=True) if unwrap: s.wrap() for p in s.particles: if p not in s.molecules[p.molecule.tag].particles: s.molecules[p.molecule.tag].particles.add(p) if debug: s.write_lammps('polymer.lmps') s.write_xyz('polymer.xyz') s.unwrap() return s
def copolymer(m, nmon, s_=None, **kwargs): """pysimm.apps.random_walk.copolymer Builds copolymer using random walk methodology using pattern Args: m: list of reference monomer :class:`~pysimm.system.System`s nmon: total number of monomers to add to chain s_: :class:`~pysimm.system.System` in which to build polymer chain (None) settings: dictionary of simulation settings density: density at which to build polymer (0.3) forcefield: :class:`~pysimm.forcefield.Forcefield` object to acquire new force field parameters capped: True/False if monomers are capped unwrap: True to unwrap final system traj: True to build xyz trajectory of polymer growth (True) pattern: list of pattern for monomer repeat units, should match length of m ([1 for _ in range(len(m))]) limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY) sim: :class:`~pysimm.lmps.Simulation` object for relaxation between polymer growth Returns: new copolymer :class:`~pysimm.system.System` """ m = [x.copy() for x in m] settings = kwargs.get('settings', {}) density = kwargs.get('density', 0.3) f = kwargs.get('forcefield') capped = kwargs.get('capped') unwrap = kwargs.get('unwrap') traj = kwargs.get('traj', True) pattern = kwargs.get('pattern', [1 for _ in range(len(m))]) limit = kwargs.get('limit', 0.1) sim = kwargs.get('sim') for m_ in m: m_.add_particle_bonding() for p in m_.particles: if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'): p.linker = 'head' elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('T'): p.linker = 'tail' m_.remove_linker_types() if s_ is None: s = system.replicate(m[0], 1, density=density/nmon) else: s = system.replicate(m[0], 1, s_=s_, density=density/nmon) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon)) for p in s.particles: if p.linker == 'head': last_head = p elif p.linker == 'tail': last_tail = p for m_ in m: if capped: m_.particles.remove(1) m_.remove_spare_bonding() m_.add_particle_bonding() s.add_particle_bonding() if traj: s.write_xyz('random_walk.xyz') temp_nmon = 1 while True: m_ = m.pop(0) m.append(m_) p_ = pattern.pop(0) pattern.append(p_) if temp_nmon == 1 and p_ == 1: m_ = m.pop(0) m.append(m_) p_ = pattern.pop(0) pattern.append(p_) elif temp_nmon == 1: p_ -= 1 for insert in range(p_): head = None tail = None backbone_vector = np.array([last_head.x - last_tail.x, last_head.y - last_tail.y, last_head.z - last_tail.z]) ref_head = None ref_tail = None for p in m_.particles: if p.linker == 'head': ref_head = p elif p.linker == 'tail': ref_tail = p if ref_head and ref_tail: ref_backbone_vector = np.array([ref_head.x - ref_tail.x, ref_head.y - ref_tail.y, ref_head.z - ref_tail.z]) rot_matrix = calc.find_rotation(ref_backbone_vector, backbone_vector) m_.rotate(around=ref_tail, rot_matrix=rot_matrix) translation_vector = [last_tail.x - ref_tail.x, last_tail.y - ref_tail.y, last_tail.z - ref_tail.z] for p in m_.particles: p.x = p.x + translation_vector[0] + 3*backbone_vector[0] p.y = p.y + translation_vector[1] + 3*backbone_vector[1] p.z = p.z + translation_vector[2] + 3*backbone_vector[2] else: print('reference molecule has no head or tail') n = m_.copy() if capped: s.particles.remove(s.particles.count) s.remove_spare_bonding() s.add_particle_bonding() s.add(n, change_dim=False) s.add_particle_bonding() head = last_head for p in s.particles[-1*n.particles.count:]: if p.linker == 'tail': tail = p s.make_new_bonds(head, tail, f) temp_nmon += 1 print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), temp_nmon, nmon)) if unwrap: s.unwrap() if sim is None: sim = lmps.Simulation(s, name='relax_%03d' % (temp_nmon), log='relax.log', **settings) sim.add_md(ensemble='nve', limit=limit, **settings) sim.add_min(**settings) if isinstance(sim, lmps.Simulation): sim.system = s sim.name = 'relax_%03d' % (temp_nmon) sim.run(np=settings.get('np')) if unwrap: s.unwrap() if unwrap: s.wrap() for p in s.particles[-1*n.particles.count:]: if p.linker == 'head': last_head = p elif p.linker == 'tail': last_tail = p if temp_nmon >= nmon: break if unwrap: if not s.unwrap(): error_print('something went wrong') return s if traj: s.write_xyz('random_walk.xyz', append=True) if unwrap: s.wrap() for p in s.particles: if p not in s.molecules[p.molecule.tag].particles: s.molecules[p.molecule.tag].particles.add(p) s.write_lammps('polymer.lmps') s.unwrap() s.write_xyz('polymer.xyz') return s
def mc_md(gas_sst, fixed_sst=None, mc_props=None, md_props=None, **kwargs): """pysimm.apps.mc_md Performs the iterative hybrid Monte-Carlo/Molecular Dynamics (MC/MD) simulations using :class:`~pysimm.lmps` for MD and :class:`~pysimm.cassandra` for MC Args: gas_sst (list of :class:`~pysimm.system.System`) : list items describe a different molecule to be inserted by MC fixed_sst (:class:`~pysimm.system.System`) : fixed during th MC steps group of atoms (default: None) Keyword Args: mcmd_niter (int) : number of MC-MD iterations (default: 10) sim_folder (str): relative path to the folder with all simulation files (default: 'results') mc_props (dictionary) : description of all MC properties needed for simulations (see :class:`~pysimm.cassandra.GCMC` and :class:`~pysimm.cassandra.GCMC.props` for details) md_props (dictionary): description of all Molecular Dynamics settings needed for simulations (see :class:`~pysimm.lmps.Simulation` and :class:`~pysimm.lmps.MolecularDynamics` for details) Returns: :class:`~pysimm.system.System`: Final state of the simulated system """ nonrig_group_name = 'nonrigid_b' rig_group_name = 'rigid_b' n_iter = kwargs.get('mcmd_niter', 10) sim_folder = kwargs.get('sim_folder', 'results') xyz_fname = os.path.join(sim_folder, '{:}.md_out.xyz') lmps_fname = os.path.join(sim_folder, '{:}.before_md.lmps') # Define whether the simulations should be continued or start from the scratch l = 1 is_restart = kwargs.get('restart') if is_restart: for f in glob.glob(lmps_fname.format('*')): l = max(l, int(re.match('\A\d+', os.path.split(f)[1]).group())) to_purge = glob.glob(os.path.join(sim_folder, '{:}.*'.format(l + 1))) + \ glob.glob(os.path.join(sim_folder, '{:}.md*'.format(l))) for f in to_purge: os.remove(f) # Creating fixed polymer system fs = None if fixed_sst: if isinstance(fixed_sst, system.System): fs = fixed_sst fs.wrap() else: print('Cannot setup the fixed system for the simulations. Skipping this') # Set the one-molecule gas systems gases = [] if gas_sst: if isinstance(gas_sst, system.System): gases = [gas_sst] elif isinstance(gas_sst, types.ListType): for g in cassandra.make_iterable(gas_sst): if isinstance(g, system.System): gases.append(g) if not gases: print('There are no gas molecules were specified correctely\nThe gas molecules are needed to start the ' 'MC-MD simulations\nExiting...') exit(1) css = cassandra.Cassandra(fixed_sst) # Set the Monte-Carlo properties: mcp = mc_props if mcp: CHEM_POT = cassandra.make_iterable(mcp.get('Chemical_Potential_Info')) if not CHEM_POT: print('Missing chemical potential info\nExiting...') exit(1) else: print('Missing the MC Simulation settings\nExiting...') exit(1) mcp['Start_Type'] = OrderedDict([('species', [1] + [0] * len(CHEM_POT))]) # Set the Molecular-Dynamics properties: sim = None mdp = md_props if not mdp: print('Missing the MD Simulation settings\nExiting...') exit(1) # De-synchronizing type names of the framework and the gases to avoid consolidation of types that PySIMM system does for gi, g in enumerate(gases): for pt in g.particle_types: pt.name += '_g' + str(gi + 1) while l < n_iter + 1: # >>> MC (CASSANDRA) step: mcp['Run_Name'] = str(l) + '.gcmc' css.add_gcmc(species=gases, is_new=True, chem_pot=CHEM_POT, is_rigid=mcp.get('rigid_type') or [False] * len(gases), out_folder=sim_folder, props_file=str(l) + '.gcmc_props.inp', **mcp) if is_restart: # Set gas particles positions from the .chk file, and update some properties css.run_queue[-1].upd_simulation() css.system = css.run_queue[-1].tot_sst.copy() # Set frame particles position and box size dimension from the .lmps file tmp_sst = system.read_lammps(lmps_fname.format(l)) for p in css.system.particles: p.x = tmp_sst.particles[p.tag].x p.y = tmp_sst.particles[p.tag].y p.z = tmp_sst.particles[p.tag].z css.system.dim = tmp_sst.dim is_restart = False else: css.run() css.system.write_lammps(lmps_fname.format(l)) nm_treads = '1' if 'OMP_NUM_THREADS' in os.environ.keys(): nm_treads = os.environ['OMP_NUM_THREADS'] os.environ['OMP_NUM_THREADS'] = '1' # >>> MD (LAMMPS) step: sim_sst = css.system.copy() sim_sst.write_lammps(os.path.join(sim_folder, str(l) + '.before_md.lmps')) sim = lmps.Simulation(sim_sst, print_to_screen=mdp.get('print_to_screen', False), log=os.path.join(sim_folder, str(l) + '.md.log')) sim.add(lmps.Init(cutoff=mdp.get('cutoff'), special_bonds=mdp.get('special_bonds'), pair_modify=mdp.get('pair_modify'))) # custom definitions for the neighbour list updates sim.add_custom('neighbor 1.0 nsq \nneigh_modify once no every 1 delay 0 check yes') # adding group definitions to separate rigid and non-rigid bodies sim.add(lmps.Group('matrix', 'id', css.run_queue[0].group_by_id('matrix')[0])) sim.add(lmps.Group(nonrig_group_name, 'id', css.run_queue[0].group_by_id('nonrigid')[0])) rigid_mols = css.run_queue[0].group_by_id('rigid')[0] if rigid_mols: sim.add(lmps.Group(rig_group_name, 'id', rigid_mols)) # create the description of the molecular dynamics simulation if type(mdp.get('timestep')) == list: sim.add(lmps.OutputSettings(thermo=mdp.get('thermo'), dump={'filename': os.path.join(sim_folder, str(l) + '.md.dump'), 'freq': int(mdp.get('dump'))})) for it, (t, lng) in enumerate(zip(mdp.get('timestep'), mdp.get('length'))): sim.add(lmps.Velocity(style='create')) # adding "run 0" line before velocities rescale for correct temperature init of the # system with rigid molecules if rigid_mols: sim.add_custom('run 0') sim.add(lmps.Velocity(style='scale')) sim.add_md(lmps.MolecularDynamics(name='main_fix_{}'.format(it), group=nonrig_group_name if rigid_mols else 'all', ensemble='npt', timestep=t, temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False, extra_keywords={'dilate': 'all'} if rigid_mols else {})) # create the second NVT fix for rigid molecules that cannot be put in NPT fix if rigid_mols: sim.add(lmps.MolecularDynamics(name='rig_fix_{}'.format(it), ensemble='rigid/nvt/small molecule', timestep=t, length=mdp.get('length'), group=rig_group_name, temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False)) sim.add_custom('fix tether_fix_{} matrix spring tether 30.0 0.0 0.0 0.0 0.0'.format(it)) sim.add_custom('run {:}\n'.format(lng)) sim.add_custom('unfix main_fix_{:}'.format(it)) sim.add_custom('unfix rig_fix_{:}'.format(it)) sim.add_custom('unfix tether_fix_{:}'.format(it)) else: sim.add_md(lmps.MolecularDynamics(name='main_fix', group=nonrig_group_name if rigid_mols else 'all', ensemble='npt', timestep=mdp.get('timestep'), temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False, extra_keywords={'dilate': 'all'} if rigid_mols else {})) # create the second NVT fix for rigid molecules that cannot be put in NPT fix if rigid_mols: sim.add(lmps.MolecularDynamics(name='rig_fix', ensemble='rigid/nvt/small molecule', timestep=mdp.get('timestep'), length=mdp.get('length'), group=rig_group_name, temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False)) # add the "spring tether" fix to the geometrical center of the system to avoid system creep sim.add_custom('fix tether_fix matrix spring tether 30.0 0.0 0.0 0.0 0.0') sim.add(lmps.OutputSettings(thermo=mdp.get('thermo'), dump={'filename': os.path.join(sim_folder, str(l) + '.md.dump'), 'freq': int(mdp.get('dump'))})) sim.add_custom('run {:}\n'.format(mdp.get('length'))) # The input for correct simulations is set, starting LAMMPS: sim.run(prefix=['']) os.environ['OMP_NUM_THREADS'] = nm_treads # Updating the size of the fixed system from the MD simulations and saving the coordinates for the next MC # css.system.dim = sim.system.dim css.system = sim.system.copy() css.unwrap_gas() css.system.write_xyz(xyz_fname.format(l)) mcp['Start_Type']['file_name'] = xyz_fname.format(l) mcp['Start_Type']['species'] = [1] + css.run_queue[-1].mc_sst.made_ins l += 1 return sim.system if sim else None
def pack_and_equil(A, n, x, f, prefix): # A: monomer # n: number of monomers # x: number of chains # f: forcefield # prefix: prefix for output files # run the polymer random walk tacticity method with n total repeat units polymer = random_walk_tacticity(A, n, forcefield=f, capped=True, tacticity='syndiotactic', rotation=180, error_check=False, sim=0) write_file_formats(polymer, prefix + "_1", unwrap=True) # quick opt of polymer lmps.quick_min(polymer, min_style='fire', etol=1.0e-4, maxiter=100000) # write a few different file formats polymer.unwrap() write_file_formats(polymer, prefix + "_1_fire") # pack x copies of polymer polymers = system.replicate(polymer, x, density=0.005) # polymers = polymer write_file_formats(polymers, prefix + "_" + str(x)) lmps.quick_min(polymers, min_style='fire', etol=1.0e-4, maxiter=100000) write_file_formats(polymers, prefix + "_" + str(x) + "_fire") # quickmd nvt_settings = { 'name': 'nvt_md', 'print_to_screen': True, 'ensemble': 'nvt', 'temperature': { 'start': 100, 'stop': 300 }, 'new_v': True, 'length': 10000 } npt_settings = { 'name': 'npt_md', 'print_to_screen': True, 'ensemble': 'npt', 'temperature': 300, 'new_v': True, 'pressure': { 'start': 1000, 'stop': 1 }, 'length': 100000, 'thermo_style': 'custom step temp press density' } # npt calcs need "add neigh_modify" command to reneighbor more often during compression of npt step sim = lmps.Simulation(polymers, name='npt_reneighbor', debug=True) sim.add_custom('neigh_modify delay 0') sim.add(lmps.Velocity(temperature=1000)) sim.add_md(length=10000, ensemble='npt', temperature=1000, pressure=5000) sim.run() write_file_formats(polymers, prefix + "_" + str(x) + "_npt") write_file_formats(polymers, prefix + "_" + str(x) + "_npt_unwrapped", unwrap=True) # 21-step equilibration equil(polymers, np=1, pmax=50000) write_file_formats(polymers, prefix + "_" + str(x) + "_equil") write_file_formats(polymers, prefix + "_" + str(x) + "_equil_unwrapped", unwrap=True)
dist = numpy.linalg.norm(numpy.array([prt.x, prt.y, prt.z]) - numpy.array([p, q, t])) flags.append(dist > 1.7) if all(flags): count += 1 tmp = solvnt.copy(dx=p, dy=q, dz=t) sst.add(tmp, change_dim=False, update_properties=False) # because 2 systems have been combined let's reassign non-diagonal LJ interactions ff.assign_extra_ljtypes(sst) sst.write_lammps('to_sim.lmps') # Create simulation and directly add all nondiagonal LJ parameters to the run file # (that is how LAMMPS operates) sim = lmps.Simulation(sst, log='simulation.log', cutoff={'inner_lj': 10.0, 'lj': 12.0}) if sst.nondiag_lj_types: for nd_lj in sst.nondiag_lj_types: sim.add_custom('pair_coeff {} {} {}'.format(' '.join(map(str, nd_lj.atm_types)), nd_lj.epsilon, nd_lj.sigma)) # define velocities and output settings sim.add(lmps.Velocity(temperature=300.0, style='create')) sim.add(lmps.OutputSettings(thermo={'args': ['step', 'time', 'temp', 'density', 'etotal', 'epair']})) # setup shake for H-O bond and H-O-H angle for the whole simulation system sim.add_custom('fix shck_fix all shake 0.001 40 0 b {:} a {:}\n'.format(sst.bond_types.get('H,O')[0].tag, sst.angle_types.get('H,O,H')[0].tag)) sim.add(lmps.MolecularDynamics(name='main', pressure={'iso': 'iso', 'damp': 100}, ensemble='npt', timestep=1,
def random_walk(m, nmon, s_=None, **kwargs): """pysimm.apps.random_walk.random_walk Builds homopolymer using random walk methodology Args: m: reference monomer :class:`~pysimm.system.System` nmon: total number of monomers to add to chain s_: :class:`~pysimm.system.System` in which to build polymer chain (None) extra_bonds: EXPERMINTAL, True if making ladder backbone polymer settings: dictionary of simulation settings density: density at which to build polymer (0.3) forcefield: :class:`~pysimm.forcefield.Forcefield` object to acquire new force field parameters capped: True/False if monomers are capped unwrap: True to unwrap final system traj: True to build xyz trajectory of polymer growth (True) limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY) sim: :class:`~pysimm.lmps.Simulation` object for relaxation between polymer growth Returns: new polymer :class:`~pysimm.system.System` """ m = m.copy() extra_bonds = kwargs.get('extra_bonds', False) settings = kwargs.get('settings', {}) density = kwargs.get('density', 0.3) f = kwargs.get('forcefield') capped = kwargs.get('capped') unwrap = kwargs.get('unwrap') traj = kwargs.get('traj', True) limit = kwargs.get('limit', 0.1) sim = kwargs.get('sim') m.add_particle_bonding() for p in m.particles: if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'): p.linker = 'head' elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find( 'T'): p.linker = 'tail' m.remove_linker_types() if s_ is None: s = system.replicate(m, 1, density=density / nmon) else: s = system.replicate(m, 1, s_=s_, density=None) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon)) if traj: s.write_xyz('random_walk.xyz') if capped: m.particles.remove(1) m.remove_spare_bonding() m.add_particle_bonding() for insertion in range(nmon - 1): head = None tail = None backbone_vector = np.array(find_last_backbone_vector(s, m)) for p, p_ in zip(s.particles[-1 * m.particles.count:], m.particles): p_.x = p.x + 3 * backbone_vector[0] p_.y = p.y + 3 * backbone_vector[1] p_.z = p.z + 3 * backbone_vector[2] n = m.copy() if capped: s.particles.remove(s.particles.count) s.remove_spare_bonding() s.add_particle_bonding() if extra_bonds: heads = [] for p in s.particles[-1 * n.particles.count:]: if p.linker == 'head': heads.append(p) else: for p in s.particles[-1 * n.particles.count:]: if p.linker == 'head': head = p s.add(n, change_dim=False) s.add_particle_bonding() if extra_bonds: tails = [] for p in s.particles[-1 * n.particles.count:]: if p.linker == 'tail': tails.append(p) else: for p in s.particles[-1 * n.particles.count:]: if p.linker == 'tail': tail = p for p in s.particles: if not p.bonded_to: print(p.tag) if head and tail: s.make_new_bonds(head, tail, f) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) elif extra_bonds and len(heads) == len(tails): for h, t in zip(heads, tails): s.make_new_bonds(h, t, f) print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion + 2, nmon)) else: print('cannot find head and tail') if sim is None: sim = lmps.Simulation(s, name='relax_%03d' % (insertion + 2), log='relax.log', **settings) sim.add_md(ensemble='nve', limit=limit, **settings) sim.add_min(**settings) if isinstance(sim, lmps.Simulation): sim.system = s sim.name = 'relax_%03d' % (insertion + 2) sim.run(np=settings.get('np')) s.unwrap() if traj: s.write_xyz('random_walk.xyz', append=True) if unwrap: s.wrap() for p in s.particles: if p not in s.molecules[p.molecule.tag].particles: s.molecules[p.molecule.tag].particles.add(p) s.write_lammps('polymer.lmps') s.unwrap() s.write_xyz('polymer.xyz') return s
def mc_md(gas_sst, fixed_sst=None, mcmd_niter=None, sim_folder=None, mc_props=None, md_props=None, **kwargs): """pysimm.apps.mc_md Performs the iterative hybrid Monte-Carlo/Molecular Dynamics (MC/MD) simulations using :class:`~pysimm.lmps` for MD and :class:`~pysimm.cassandra` for MC Args: gas_sst (list of :class:`~pysimm.system.System`) : list items describe a different molecule to be inserted by MC fixed_sst (:class:`~pysimm.system.System`) : fixed during th MC steps group of atoms (default: None) Keyword Args: mcmd_niter (int) : number of MC-MD iterations (default: 10) sim_folder (str): relative path to the folder with all simulation files (default: 'results') mc_props (dictionary) : description of all MC properties needed for simulations (see :class:`~pysimm.cassandra.GCMC` and :class:`~pysimm.cassandra.GCMC.props` for details) md_props (dictionary): description of all Molecular Dynamics settings needed for simulations (see :class:`~pysimm.lmps.Simulation` and :class:`~pysimm.lmps.MolecularDynamics` for details) Returns: :class:`~pysimm.system.System`: Final state of the simulated system """ nonrig_group_name = 'nonrigid_b' rig_group_name = 'rigid_b' n_iter = mcmd_niter or 10 sim_folder = sim_folder or 'results' xyz_fname = os.path.join(sim_folder, 'MD{:}_out.xyz') l = 1 # Creating fixed polymer system fs = None if fixed_sst: if isinstance(fixed_sst, system.System): fs = fixed_sst fs.wrap() else: print( 'Cannot setup the fixed system for the simulations. Skipping this' ) # Set the one-molecule gas systems gases = [] if gas_sst: if isinstance(gas_sst, system.System): gases = [gas_sst] elif isinstance(gas_sst, types.ListType): for g in cassandra.make_iterable(gas_sst): if isinstance(g, system.System): gases.append(g) if not gases: print( 'There are no gas molecules were specified correctely\nThe gas molecules are needed to start the ' 'MC-MD simulations\nExiting...') exit(1) css = cassandra.Cassandra(fixed_sst) # Set the Monte-Carlo properties: mcp = mc_props if mcp: CHEM_POT = cassandra.make_iterable(mcp.get('Chemical_Potential_Info')) if not CHEM_POT: print('Missing chemical potential info\nExiting...') exit(1) else: print('Missing the MC Simulation settings\nExiting...') exit(1) mcp['Start_Type'] = OrderedDict([('species', [1] + [0] * len(CHEM_POT))]) # Set the Molecular-Dynamics properties: sim = None mdp = md_props if not mdp: print('Missing the MD Simulation settings\nExiting...') exit(1) while l < n_iter + 1: mcp['Run_Name'] = str(l) + '.gcmc' css.add_gcmc(species=gases, is_new=True, chem_pot=CHEM_POT, is_rigid=mcp.get('rigid_type') or [False] * len(gases), out_folder=sim_folder, props_file=str(l) + '.gcmc_props.inp', **mcp) css.run() # >>> 2N: MD (LAMMPS) step: sim_sst = css.system sim_sst.write_lammps( os.path.join(sim_folder, str(l) + '.before_md.lmps')) sim = lmps.Simulation(sim_sst, debug=True, log=os.path.join(sim_folder, str(l) + '.md.log')) sim.add(lmps.Init(cutoff=mdp.get('cutoff'))) # custom definitions for the neighbour list updates sim.add_custom( 'neighbor 1.0 nsq \nneigh_modify once no every 1 delay 0 check yes' ) # adding group definitions to separate rigid and non-rigid bodies sim.add( lmps.Group('matrix', 'id', css.run_queue[0].group_by_id('matrix')[0])) sim.add( lmps.Group(nonrig_group_name, 'id', css.run_queue[0].group_by_id('nonrigid')[0])) rigid_mols = css.run_queue[0].group_by_id('rigid')[0] if rigid_mols: sim.add(lmps.Group(rig_group_name, 'id', rigid_mols)) # adding "run 0" line before velocities rescale for correct temperature init of the system with rigid molecules sim.add(lmps.Velocity(style='create')) if rigid_mols: sim.add_custom('run 0') sim.add(lmps.Velocity(style='scale')) # create the description of the molecular dynamics simulation sim.add_md( lmps.MolecularDynamics( name='main_fix', group=nonrig_group_name if rigid_mols else 'all', ensemble='npt', timestep=mdp.get('timestep'), temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False, extra_keywords={'dilate': 'all'} if rigid_mols else {})) # create the second NVT fix for rigid molecules that cannot be put in NPT fix if rigid_mols: sim.add( lmps.MolecularDynamics(name='rig_fix', ensemble='rigid/nvt/small molecule', timestep=mdp.get('timestep'), length=mdp.get('length'), group=rig_group_name, temperature=mdp.get('temp'), pressure=mdp.get('pressure'), run=False)) # add the "spring tether" fix to the geometrical center of the system to avoid system creep sim.add_custom( 'fix tether_fix matrix spring tether 30.0 0.0 0.0 0.0 0.0') sim.add( lmps.OutputSettings(thermo=mdp.get('thermo'), dump={ 'filename': os.path.join(sim_folder, str(l) + '.md.dump'), 'freq': int(mdp.get('dump')) })) sim.add_custom('run {:}\n'.format(mdp.get('length'))) # The input for correct simulations is set, starting LAMMPS: sim.run(np=mdp.get('np', 1)) # Updating the size of the fixed system from the MD simulations and saving the coordinates for the next MC css.system.dim = sim.system.dim sim.system.write_xyz(xyz_fname.format(l)) mcp['Start_Type']['file_name'] = xyz_fname.format(l) mcp['Start_Type']['species'] = [1] + [0] * len(CHEM_POT) l += 1 return sim.system if sim else None
pim1_ld.dim.dx = ld_box_size pim1_ld.dim.dy = ld_box_size pim1_ld.dim.dz = ld_box_size for idx in range(10): tmp = chains[idx].copy() tmp.shift_particles(*displ[2 * idx]) pim1_ld.add(tmp, change_dim=False) pim1_ld.wrap() pim1_ld.set_density() print('Density of the system is: {:} g/cc'.format(pim1_ld.density)) # pim1_ld = system.replicate(new_chains, [1] * len(new_chains), density=0.05, rand=False) mimi = lmps.Simulation(pim1_ld, print_to_screen=False, log='mimimization.log') mimi.add( lmps.Init(cutoff=14.0, special_bonds='amber', pair_modify={'mix': 'arithmetic'})) mimi.add_min(min_style='sd', eol=1e-5, ftol=1e-5, maxiter=int(1e+5), maxeval=int(1e+6)) mimi.add_min(min_style='cg', eol=1e-5, ftol=1e-5, maxiter=int(1e+5), maxeval=int(1e+6)) mimi.run(np=6)
def mc_md(gas_sst, fixed_sst=None, **kwargs): """pysimm.apps.mc_md Performs the iterative hybrid Monte-Carlo/Molecular Dynamics (MC-MD) simulations using pysimm.lmps for MD and pysimm.cassandra for MD Args: gas_sst: list of pysimm.system.System objects each of which describes a different molecule to be inserted by MC fixed_sst: fixed during th MC steps group of atoms (default: None) mcmd_niter: number of MC-MD iteradions (default: 10) sim_folder: relative path to the folder with all simulation files (default: 'results') mc_props: dictionary describing all MC properties needed for simulations (see pysimm.cassandra.GCMC and pysimm.cassandra.GCMC.props for details) md_props: dictionary containing all Molecular Dynamics settings needed for simulations (see pysimm.lmps.Simulation and pysimm.lmps.MolecularDynamics for details) """ nonrig_group_name = 'nonrigid_b' rig_group_name = 'rigid_b' n_iter = kwargs.get('mcmd_niter') or 10 sim_folder = kwargs.get('sim_folder') or 'results' xyz_fname = os.path.join(sim_folder, 'MD{:}_out.xyz') l = 1 # Creating fixed polymer system fs = None if fixed_sst: if isinstance(fixed_sst, str): fs = system.read_lammps(fixed_sst) fs.wrap() elif isinstance(fixed_sst, system.System): fs = fixed_sst fs.wrap() else: print('Cannot setup the fixed system for the simulations. Skipping this') # Set the one-molecule gas systems gases = [] for g in cassandra.make_iterable(gas_sst): if isinstance(g, str): try: gases.append(system.read_lammps(g)) except IOError: print('Cannot read file: {}\nExiting...'.format(g)) exit(1) if isinstance(g, system.System): gases.append(g) if not gases: print('There are no gas molecules were specified correctely\nThe gas molecules are needed to start the ' 'MC-MD simulations\nExiting...') exit(1) css = cassandra.Cassandra(fixed_sst) # Set the Monte-Carlo properties: mcp = kwargs.get('mc_props') if mcp: CHEM_POT = cassandra.make_iterable(mcp.get('Chemical_Potential_Info')) if not CHEM_POT: print('Missing chemical potential info\nExiting...') exit(1) else: print('Missing the MC Simulation settings\nExiting...') exit(1) mcp['Start_Type'] = OrderedDict([('species', [1] + [0] * len(CHEM_POT))]) # Set the Molecular-Dynamics properties: mdp = kwargs.get('md_props') if not mdp: print('Missing the MD Simulation settings\nExiting...') exit(1) while l < n_iter + 1: mcp['Run_Name'] = str(l) + '.gcmc' css.add_gcmc(species=gases, is_new=True, chem_pot=CHEM_POT, is_rigid=mcp.get('rigid_type') or [False] * len(gases), out_folder=sim_folder, props_file=str(l) + '.gcmc_props.inp', **mcp) css.run() # >>> 2N: MD (LAMMPS) step: sim_sst = css.final_sst sim_sst.write_lammps(os.path.join(sim_folder, str(l) + '.before_md.lmps')) sim = lmps.Simulation(sim_sst, log=os.path.join(sim_folder, str(l) + '.md.log'), print_to_screen=mdp.get('print_to_screen'), cutoff=mdp.get('cutoff')) # custom definitions for the neighbour list updates sim.add_custom('neighbor 1.0 nsq \nneigh_modify once no every 1 delay 0 check yes') # adding group definitions to separate rigid and non-rigid bodies grp_tmpl = 'group {:} id {:}' sim.add_custom(grp_tmpl.format('matrix', css.run_queue[0].group_by_id('matrix')[0])) sim.add_custom(grp_tmpl.format(nonrig_group_name, css.run_queue[0].group_by_id('nonrigid')[0])) rigid_mols = css.run_queue[0].group_by_id('rigid')[0] if rigid_mols: sim.add_custom(grp_tmpl.format(rig_group_name, rigid_mols)) # create the description of the molecular dynamics simulation tmp_md = lmps.MolecularDynamics(ensemble=mdp.get('ensemble'), timestep=mdp.get('timestep'), length=int(mdp.get('length')), thermo=mdp.get('thermo'), temp=mdp.get('temp'), pressure=mdp.get('pressure'), dump=int(mdp.get('dump')), dump_name=os.path.join(sim_folder, str(l) + '.md.dump'), scale_v=True) # obtain the simulation (LAMMPS) input in order to customly modify it later tmp_md.write(sim) # replace single default fix with two separate fixes for rigid and nonrigid bodies separately old_line = re.search('(?<=(\nfix)).*', tmp_md.input).group(0) corr_fix = re.sub('all', nonrig_group_name, old_line) if rigid_mols: corr_fix += ' dilate all\n' else: corr_fix += '\n' if rigid_mols: corr_fix += 'fix' + re.sub('iso\s+\d+[.\d]*\s+\d+[.\d]*\s+\d+[.\d]*', '', old_line).\ replace('1', '2', 1). \ replace('all', rig_group_name). \ replace('npt', 'rigid/nvt/small molecule') + '\n' # adding the spring fix to the geometrical center of the system to avoid system creep corr_fix += 'fix {:} {:} spring tether {:} {:} {:} {:} {:}\n'.format(3, 'matrix', 30.0, 0.0, 0.0, 0.0, 0.0) # saving all fixes to the input tmp_md.input = tmp_md.input.replace(old_line, corr_fix) # adding "run 0" line for correct temperature scaling of the system with rigid molecules tmp_md.input = tmp_md.input.replace('velocity all scale', 'velocity all create {:} {:}\nrun 0\nvelocity all scale' .format(mdp.get('temp'), random.randint(int(1e+5), int(1e+6) - 1))) # The input for correct simulations is set, starting LAMMPS: sim.add_custom(tmp_md.input) sim.run(np=1) # Updating the size of the fixed system from the MD simulations and saving the coordinates for the next MC css.init_sst.dim = sim.system.dim sim.system.write_xyz(xyz_fname.format(l)) mcp['Start_Type']['file_name'] = xyz_fname.format(l) mcp['Start_Type']['species'] = [1] + [0] * len(CHEM_POT) l += 1 return sim.system