def react_dots( params, dot_size1, dot_size2, prior_run_name1, prior_run_name2, random_seed=1, run_name_prefix="react_", on_queue=True, method="metadynamics", ): random_s = str(random_seed) random.seed(random_seed) run_name = run_name_prefix + str(dot_size1) + "_" + str(dot_size2) spoc = utils.Molecule("/fs/home/jms875/Documents/nanocrystals/pb_oleate_hydrate_morse/" + spoc_name + ".arc") atoms1, bonds1, angles1, dihedrals1 = cPickle.load(open("lammps/" + prior_run_name1 + ".pickle", "rb")) atoms1, bonds1, angles1, dihedrals1 = remove_unattached_ligands(atoms1, bonds1, angles1, dihedrals1, spoc) atoms2, bonds2, angles2, dihedrals2 = cPickle.load(open("lammps/" + prior_run_name2 + ".pickle", "rb")) atoms2, bonds2, angles2, dihedrals2 = remove_unattached_ligands(atoms2, bonds2, angles2, dihedrals2, spoc) atoms1_xyz = filetypes.parse_xyz(prior_run_name1 + ".xyz") atoms2_xyz = filetypes.parse_xyz(prior_run_name2 + ".xyz") goal_atoms = filetypes.parse_xyz("dot" + str(dot_size1 + dot_size2) + ".xyz") # set starting coordinates for a, b in zip(atoms1, atoms1_xyz): a.x = b.x a.y = b.y a.z = b.z for a, b in zip(atoms2, atoms2_xyz): a.x = b.x a.y = b.y a.z = b.z atoms = atoms1 + atoms2 bonds = bonds1 + bonds2 angles = angles1 + angles2 dihedrals = dihedrals1 + dihedrals2 # make sure atom types are the same in atom1 and atom2 atom_types_by_type_index = dict([(t.type.index, t.type) for t in atoms]) for i, a in enumerate(atoms): a.type = atom_types_by_type_index[a.type.index] a.index = i + 1 if coul_on and a.type.index in params: a.charge = params[a.type.index] else: a.charge = a.type.charge atom_types = dict([(t.type, True) for t in atoms]).keys() atom_types.sort(key=lambda t: -t.element - t.index * 0.00001) offset = ( radius_of_gyration([a for a in atoms1 if (a.type.notes == "PbS Nanocrystal Pb" or a.element == "S")]) + radius_of_gyration([a for a in atoms2 if (a.type.notes == "PbS Nanocrystal Pb" or a.element == "S")]) + 10.0 ) offset_vector = utils.matvec(utils.rand_rotation(), [offset, offset, offset]) rot = utils.rand_rotation() for a in atoms2: # offset by random orientation vector a.x, a.y, a.z = utils.matvec(rot, [a.x, a.y, a.z]) a.x += offset_vector[0] a.y += offset_vector[1] a.z += offset_vector[2] box_size = [ 15.0 + max([a.x for a in atoms]) - min([a.x for a in atoms]), 15.0 + max([a.y for a in atoms]) - min([a.y for a in atoms]), 15.0 + max([a.z for a in atoms]) - min([a.z for a in atoms]), ] # goal_atoms = cPickle.load( open('lammps/dot'+str(dot_size1+dot_size2)+'.pickle', 'rb') )[0] # filetypes.write_xyz('out_meta', atoms) # exit() os.chdir("lammps") save_to_file(atoms, bonds, angles, dihedrals, atom_types, run_name) lammps.write_data_file_general( atoms, bonds, angles, dihedrals, box_size, run_name, atom_types=atom_types, pair_coeffs_included=False ) os.system("cp ../" + sys.argv[0] + " " + run_name + ".py") starting_rxn_coord = radius_of_gyration( [a for a in atoms if (a.type.notes == "PbS Nanocrystal Pb" or a.element == "S")] ) print len([a for a in atoms if (a.type.notes == "PbS Nanocrystal Pb" or a.element == "S")]) goal_rxn_coord = radius_of_gyration(goal_atoms[0 : 2 * (dot_size1 + dot_size2)]) colvars_file = open(run_name + ".colvars", "w") colvars_file.write( """ colvarsTrajFrequency 10000 colvarsRestartFrequency 100000 colvar { name gyr width 0.1 #size of bins, in Angstroms upperBoundary """ + str(starting_rxn_coord) + """ #two separate dots lowerBoundary """ + str(goal_rxn_coord) + """ #one unified dot lowerwallconstant 10.0 upperwallconstant 10.0 gyration { atoms { atomNumbers """ + (" ".join([str(a.index) for a in atoms if (a.type.notes == "PbS Nanocrystal Pb" or a.element == "S")])) + """ } } } """ ) if method.lower() == "abf": colvars_file.write( """ abf { colvars gyr hideJacobian # when using distance-based colvar: makes pmf flat at infinity fullSamples 1000 } """ ) elif method.lower() == "metadynamics": colvars_file.write( """ metadynamics { colvars gyr hillWeight 0.1 newHillFrequency 1000 } """ ) else: raise Exception('Invalid free energy method "%s"' % method) colvars_file.close() f = open(run_name + ".in", "w") write_input_header(f, run_name, atom_types, read_restart=False) f.write( """ dump 1 all xyz 10000 """ + run_name + """.xyz minimize 0.0 1.0e-8 10000 1000 neigh_modify check yes every 1 delay 0 thermo_style custom pe temp thermo 10000 restart 100000 """ + run_name + """.restart1 """ + run_name + """.restart2 fix motion all nve fix implicit_solvent all langevin 400.0 400.0 100.0 """ + random_s + """ zero yes gjf yes fix col all colvars """ + run_name + """.colvars output """ + run_name + """ seed """ + random_s + """ tstat implicit_solvent velocity all create 400.0 """ + random_s + """ mom yes timestep 2.0 thermo_style custom step temp etotal pe ke epair ebond f_col tpcpu run """ + str(int(1e7)) + """ write_restart """ + run_name + """.restart """ ) f.close() # run_job(run_name, on_queue) os.chdir("..")
def build_dot(N, spoc, monomer, atoms, bonds, angles, dihedrals, random_seed=1): random.seed(random_seed) pb_type = monomer.atoms[0].type s_type = monomer.atoms[1].type Q = 2.968 L = int(math.ceil((2 * N) ** 0.333)) center = utils.Struct(x=0.0, y=0.0, z=0.0) core_atoms = [] if L * Q < 30: # octahedron L += 6 for zi in range(L): # L2 = int(( math.sqrt(3)*( L/2-abs(zi-L/2) ) )) L2 = (L / 2 - abs(zi - L / 2)) * 2 for xi in range(L2): for yi in range(L2): x = (xi - L2 * 0.5 + 0.5) * Q y = (yi - L2 * 0.5 + 0.5) * Q z = (zi - L * 0.5 + 0.5) * Q core_atoms.append( utils.Struct( x=x, y=y, z=z, element="Pb" if (xi + yi + zi) % 2 else "S", type=pb_type if (xi + yi + zi) % 2 else s_type, ) ) else: # cube L += 2 for xi in range(L): for yi in range(L): for zi in range(L): x = (xi - L * 0.5 + 0.5) * Q y = (yi - L * 0.5 + 0.5) * Q z = (zi - L * 0.5 + 0.5) * Q core_atoms.append( utils.Struct( x=x, y=y, z=z, element="Pb" if (xi + yi + zi) % 2 else "S", type=pb_type if (xi + yi + zi) % 2 else s_type, ) ) # filetypes.write_xyz('out', core_atoms) # sys.exit() for a in core_atoms: a.dist = dist = utils.dist(a, center) a.neighbors = [] for b in core_atoms: if a is not b and utils.dist_squared(a, b) < Q ** 2 + 0.1: a.neighbors.append(b) core_atoms.sort(key=lambda a: a.dist) s_atoms = [a for a in core_atoms if a.element == "S"][:N] pb_atoms = {} for s in s_atoms: for a in s.neighbors: if a.type is pb_type: pb_atoms[a] = True pb_atoms = pb_atoms.keys() pb_atoms.sort(key=lambda a: a.dist) # excess_pb_atoms = pb_atoms[N:] #tends to pick all from one side closest_dist_to_remove = pb_atoms[N].dist core_pb_atoms = [a for a in pb_atoms if a.dist < closest_dist_to_remove - 0.01] marginal_pb_atoms = [ a for a in pb_atoms if (abs(a.dist - closest_dist_to_remove) < 0.01 and a not in core_pb_atoms) ] random.shuffle(marginal_pb_atoms) core_pb_atoms = core_pb_atoms + marginal_pb_atoms[: N - len(core_pb_atoms)] excess_pb_atoms = [a for a in pb_atoms if a not in core_pb_atoms] for a in s_atoms + core_pb_atoms: atoms.append(a) import numpy def add_spoc_at_pb(pb): spoc.add_to(0.0, 0.0, 0.0, atoms, bonds, angles, dihedrals) direction = [pb.x, pb.y, pb.z] direction /= numpy.linalg.norm(direction) dot = numpy.dot(direction, [1.0, 0.0, 0.0]) theta = math.acos(dot) cross = numpy.cross(direction, [1.0, 0.0, 0.0]) cross /= -numpy.linalg.norm(cross) w = numpy.array(cross) for a in atoms[-len(spoc.atoms) :]: v = numpy.array([a.x, a.y, a.z]) a.x, a.y, a.z = ( v * math.cos(theta) + numpy.cross(w, v) * math.sin(theta) + w * numpy.dot(w, v) * (1 - math.cos(theta)) ) # Rodrigues' rotation formula a.x += pb.x a.y += pb.y a.z += pb.z for pb in excess_pb_atoms: add_spoc_at_pb(pb) # add more Pb complexes as needed new_pb = 0 while new_pb < N + 3: x, y, z = [Q * (3 + (2 * N) ** 0.333) / 2] * 3 M = utils.rand_rotation() x, y, z = utils.matvec(M, [x, y, z]) pb = utils.Struct(x=x, y=y, z=z, element="Pb", type=pb_type) too_close = False for a in atoms: if utils.dist_squared(a, pb) < (Q + 2) ** 2: too_close = True break if not too_close: add_spoc_at_pb(pb) new_pb += 1