def calculate(coords): coord_count = 0 for s in NEB.states[1:-1]: for a in s: a.x, a.y, a.z = coords[coord_count], coords[coord_count+1], coords[coord_count+2] coord_count += 3 #start DFT jobs running_jobs = [] for i,state in enumerate(NEB.states[1:-1]): guess = '' if NEB.step==0 else ' Guess=Read' running_jobs.append( job('%s-%d-%d'%(NEB.name,NEB.step,i), NEB.theory+' Force'+guess, state, queue=queue, force=True, previous=('%s-%d-%d'%(NEB.name,NEB.step-1,i)) if NEB.step>0 else None, extra_section=extra_section) ) #wait for jobs to finish for j in running_jobs: j.wait() #get forces and energies from DFT calculations energies = [] for i,state in enumerate(NEB.states[1:-1]): try: new_energy, new_atoms = parse_atoms('%s-%d-%d'%(NEB.name,NEB.step,i)) except: print 'Job failed: %s-%d-%d'%(NEB.name,NEB.step,i); exit() energies.append(new_energy) for a,b in zip(state, new_atoms): a.fx = b.fx; a.fy = b.fy; a.fz = b.fz dft_energies = copy.deepcopy(energies) #add spring forces to atoms for i,state in enumerate(NEB.states[1:-1]): for j,b in enumerate(state): a,c = NEB.states[i-1][j], NEB.states[i+1][j] if j in spring_atoms: b.fx += NEB.k*(a.x-b.x) + NEB.k*(c.x-b.x) b.fy += NEB.k*(a.y-b.y) + NEB.k*(c.y-b.y) b.fz += NEB.k*(a.z-b.z) + NEB.k*(c.z-b.z) energies[i] += 0.5*NEB.k*(utils.dist_squared(a,b) + utils.dist_squared(b,c)) #set error NEB.error = sum(energies) #set forces NEB.forces = [] for state in NEB.states[1:-1]: for a in state: NEB.forces += [-a.fx, -a.fy, -a.fz] #derivative of the error #increment step NEB.step += 1 #write to xyz file NEB.xyz = open(name+'.xyz', 'w') for state in NEB.states: files.write_xyz(state, NEB.xyz) NEB.xyz.close() #print data print NEB.step, NEB.error, ('%10.7g '*len(dft_energies)) % tuple(dft_energies)
def remove_unattached_ligands(atoms, bonds, angles, dihedrals, spoc): sulfurs = [a for a in atoms if a.element == "S"] remove_count = 0 atoms_to_remove = {} for i, a in enumerate(atoms): if a.element == "Pb": nearest_sulfur = min([utils.dist_squared(a, b) for b in sulfurs]) if nearest_sulfur > 5 ** 2: # remove whole spoc, based on size of spoc and where pb is within it (always first?) remove_count = len(spoc.atoms) if remove_count > 0: remove_count -= 1 atoms_to_remove[a] = True atoms = [a for a in atoms if a not in atoms_to_remove] bonds = [b for b in bonds if b.atoms[0] not in atoms_to_remove and b.atoms[1] not in atoms_to_remove] angles = [ a for a in angles if a.atoms[0] not in atoms_to_remove and a.atoms[1] not in atoms_to_remove and a.atoms[2] not in atoms_to_remove ] dihedrals = [ d for d in dihedrals if d.atoms[0] not in atoms_to_remove and d.atoms[1] not in atoms_to_remove and d.atoms[2] not in atoms_to_remove and d.atoms[3] not in atoms_to_remove ] return atoms, bonds, angles, dihedrals
def do_route(route, limit): # return new route if limit == 0: return route # don't change depot for i in range(0, len(route)-2): u_1 = route[i].pos u_2 = route[i+1].pos for j in range(i+1, len(route)-1): v_1 = route[j].pos v_2 = route[j+1].pos if ( dist_squared(u_1, u_2) + dist_squared(v_1, v_2) ) > \ ( dist_squared(u_1, v_1) + dist_squared(u_2, v_2) ): # is better, put v_1 after u_1, then in reverse order until u_2, then v_2 # TODO: do in place? route_prime = route[:i+1] + list(reversed(route[i+1:j+1])) + route[j+1:] return do_route(route_prime, limit-1) return route # nothing found
def get_bonds(atoms): bonds = [] for a in atoms: a.bonded = [] for i,a in enumerate(atoms): for b in atoms[i+1:]: d = utils.dist_squared(a,b)**0.5 if (a.element not in [1,'H'] and b.element not in [1,'H'] and d<2.) or (d < 1.2 and (a.element in [1,'H'])!=(b.element in [1,'H']) ): bonds.append( utils.Struct(atoms=(a,b), d=d, e=None) ) #offset from current, distance a.bonded.append(b) b.bonded.append(a) return bonds
def do_route(route, limit): # return new route if limit == 0: return route # don't change depot for i in range(0, len(route) - 2): u_1 = route[i].pos u_2 = route[i + 1].pos for j in range(i + 1, len(route) - 1): v_1 = route[j].pos v_2 = route[j + 1].pos if ( dist_squared(u_1, u_2) + dist_squared(v_1, v_2) ) > \ ( dist_squared(u_1, v_1) + dist_squared(u_2, v_2) ): # is better, put v_1 after u_1, then in reverse order until u_2, then v_2 # TODO: do in place? route_prime = route[:i + 1] + list( reversed(route[i + 1:j + 1])) + route[j + 1:] return do_route(route_prime, limit - 1) return route # nothing found
def _get_closest_depots(instance, genotype): """Returns the closest depots for the genotype values. Currently unrandomized.""" raise RuntimeError("don't use anymore") closest_depots=[] for vehicle_base in genotype: #pprint.pprint(list( ( ( (vehicle_base[0]-d.pos[0])**2 + (vehicle_base[1]-d.pos[1])**2 ), d_id) for (d_id, d) in enumerate(instance.depots) ) ) # use squared dist closest = min( (dist_squared(vehicle_base, d.pos), d_id) for (d_id, d) in enumerate(instance.depots) ) closest_depots.append( instance.depots[ closest[1] ] ) return closest_depots
def _get_closest_depots(instance, genotype): """Returns the closest depots for the genotype values. Currently unrandomized.""" raise RuntimeError("don't use anymore") closest_depots = [] for vehicle_base in genotype: #pprint.pprint(list( ( ( (vehicle_base[0]-d.pos[0])**2 + (vehicle_base[1]-d.pos[1])**2 ), d_id) for (d_id, d) in enumerate(instance.depots) ) ) # use squared dist closest = min((dist_squared(vehicle_base, d.pos), d_id) for (d_id, d) in enumerate(instance.depots)) closest_depots.append(instance.depots[closest[1]]) return closest_depots
def parse_tinker_arc(molecule_file, parameter_file=None): if parameter_file: elements, atom_types, bond_types, angle_types, dihedral_types = lammps.parse_opls_parameters(parameter_file) atoms = [] for line in open(molecule_file): columns = line.split() if len(columns)>3: atoms.append( utils.Struct(index=int(columns[0]), element=columns[1], x=float(columns[2]), y=float(columns[3]), z=float(columns[4]), bonded=[int(s) for s in columns[6:]], type=([t for t in atom_types if t.index==int(columns[5][-3:])][0] if parameter_file else None), charge=None) ) if len(columns[5])>3: atom_types.append( copy.deepcopy(atoms[-1].type) ) atoms[-1].type.index = int(columns[5]) bond_set = {} for a in atoms: a.bonded = [atoms[i-1] for i in a.bonded] for b in a.bonded: if (b,a) not in bond_set: bond_set[(a,b)] = True bonds = [utils.Struct(atoms=b, d=utils.dist_squared(b[0],b[1])**0.5, e=None, type=None) for b in bond_set.keys()] angles, dihedrals = get_angles_and_dihedrals(atoms, bonds) return atoms, bonds, angles, dihedrals
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
def radius_of_gyration(atoms): center = center_of_geometry(atoms) return math.sqrt(1.0 / len(atoms) * sum([utils.dist_squared(a, center) for a in atoms]))
def calculate(coords): coord_count = 0 for s in NEB.states[1:-1]: for a in s: a.x, a.y, a.z = coords[coord_count], coords[ coord_count + 1], coords[coord_count + 2] coord_count += 3 #start DFT jobs running_jobs = [] for i, state in enumerate(NEB.states[1:-1]): guess = '' if NEB.step == 0 else ' Guess=Read' running_jobs.append( job('%s-%d-%d' % (NEB.name, NEB.step, i), NEB.theory + ' Force' + guess, state, queue=queue, force=True, previous=('%s-%d-%d' % (NEB.name, NEB.step - 1, i)) if NEB.step > 0 else None, extra_section=extra_section)) #wait for jobs to finish for j in running_jobs: j.wait() #get forces and energies from DFT calculations energies = [] for i, state in enumerate(NEB.states[1:-1]): try: new_energy, new_atoms = parse_atoms( '%s-%d-%d' % (NEB.name, NEB.step, i)) except: print 'Job failed: %s-%d-%d' % (NEB.name, NEB.step, i) exit() energies.append(new_energy) for a, b in zip(state, new_atoms): a.fx = b.fx a.fy = b.fy a.fz = b.fz dft_energies = copy.deepcopy(energies) #add spring forces to atoms for i, state in enumerate(NEB.states[1:-1]): for j, b in enumerate(state): a, c = NEB.states[i - 1][j], NEB.states[i + 1][j] if j in spring_atoms: b.fx += NEB.k * (a.x - b.x) + NEB.k * (c.x - b.x) b.fy += NEB.k * (a.y - b.y) + NEB.k * (c.y - b.y) b.fz += NEB.k * (a.z - b.z) + NEB.k * (c.z - b.z) energies[i] += 0.5 * NEB.k * (utils.dist_squared( a, b) + utils.dist_squared(b, c)) #set error NEB.error = sum(energies) #set forces NEB.forces = [] for state in NEB.states[1:-1]: for a in state: NEB.forces += [-a.fx, -a.fy, -a.fz] #derivative of the error #increment step NEB.step += 1 #write to xyz file NEB.xyz = open(name + '.xyz', 'w') for state in NEB.states: files.write_xyz(state, NEB.xyz) NEB.xyz.close() #print data print NEB.step, NEB.error, ( '%10.7g ' * len(dft_energies)) % tuple(dft_energies)