def parse_inputs(name="config"): """Convert the string values of the diciontary to the appropriate types""" inputs = complete_config(name) inputs["bond_thresh"] = float(inputs["bond_thresh"]) if type(inputs["atom_label"]) == str: inputs["atom_label"] = [int(inputs["atom_label"]) - 1] else: inputs["atom_label"] = [int(i) - 1 for i in inputs["atom_label"]] inputs["ewald"] = bool_cast(inputs["ewald"]) inputs["nchk"] = int(inputs["nchk"]) inputs["nat"] = int(inputs["nat"]) inputs["an"] = int(inputs["an"]) inputs["bn"] = int(inputs["bn"]) inputs["cn"] = int(inputs["cn"]) inputs["clust_rad"] = float(inputs["clust_rad"]) inputs["traan"] = int(inputs["traan"]) inputs["trabn"] = int(inputs["trabn"]) inputs["tracn"] = int(inputs["tracn"]) inputs["self_consistent"] = bool_cast(inputs["self_consistent"]) inputs["dev_tol"] = float(inputs["dev_tol"]) inputs["a_vec"] = np.array([float(i) for i in inputs["a_vec"]]) inputs["b_vec"] = np.array([float(i) for i in inputs["b_vec"]]) inputs["c_vec"] = np.array([float(i) for i in inputs["c_vec"]]) inputs["damping"] = float(inputs["damping"]) inputs["print_tweak"] = bool_cast(inputs["print_tweak"]) # specified in config inputs["vectors"] = np.zeros((3, 3)) if all( len(i) == 3 for i in [inputs["a_vec"], inputs["b_vec"], inputs["c_vec"]]): a_vec = inputs["a_vec"] b_vec = inputs["b_vec"] c_vec = inputs["c_vec"] inputs["vectors"][0] = a_vec inputs["vectors"][1] = b_vec inputs["vectors"][2] = c_vec else: # from external file inputs["vectors"] = rf.read_vectors(inputs["vectors_file"]) return inputs
def main(args): # read input file all_atoms = fro.mol_from_file(args.input) # specify bonding all_atoms.set_bonding(bonding=args.bonding, thresh=args.thresh) # if the bonding is specified all in one string if args.bonding_string: all_atoms.set_bonding_str(args.bonding_string) # if periodic if args.vectors: prints("Vectors detected") vectors = rf.read_vectors(args.vectors) all_atoms.vectors = vectors # if we are forbidding some atoms if args.no_atom_label: forbidden_kinds = [] # for each atom to forbid for label in args.no_atom_label: mol_of_interest = all_atoms.per_select(label - 1) mol_of_interest.set_connectivity() for atom in mol_of_interest: if atom == all_atoms[label - 1]: forbidden_kinds.append(atom.kind) all_atoms, molecules = all_atoms.complete_cell() prints("{} molecules detected after reconstitution".format( len(molecules))) else: # if we are forbidding some atoms if args.no_atom_label: forbidden_kinds = [] # for each atom to forbid for label in args.no_atom_label: mol_of_interest = all_atoms.select(label - 1) mol_of_interest.set_connectivity() for atom in mol_of_interest: if atom == all_atoms[label - 1]: forbidden_kinds.append(atom.kind) # separate into molecules molecules = all_atoms.segregate(diff_mols=False) prints("{} molecules detected".format(len(molecules))) # ignore hydrogens if args.no_hydrogens: for mol in molecules: mol.geom.ignore_hydrogens = True # ignore certain atoms if args.no_atom_label: zero_vectors = np.array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) for mol in molecules: mol.vectors = zero_vectors mol.set_connectivity() mol.geom.ignore_kinds = forbidden_kinds # get dimers dimers_raw = all_dimers(molecules) prints("{} dimers in the input geometry".format(len(dimers_raw))) # if periodic if args.vectors: # get all the dimers generated by extra periodic images dimers_per = [] for dimer in dimers_raw: images = dimer.images(vectors) dimers_per.extend(images) dimers_raw = dimers_per prints("{} dimers considering periodicity".format(len(dimers_raw))) if args.linear: for dimer in dimers_raw: dimer.mols_are_linear() # filter out dimers if args.dimtype == 'centroid': method = 'centroid' mode = 'dis' else: method = 'atomic' if args.dimtype == 'dis': mode = 'dis' elif args.dimtype == 'cov': mode = 'cov' elif args.dimtype == 'vdw': mode = 'vdw' selected_dimers = [] for dimer in dimers_raw: if dimer.inter_distance(method=method, mode=mode) <= args.dist: selected_dimers.append(dimer) prints("{} dimers selected from distance criterion".format( len(selected_dimers))) # remove repeated dimers keep_these = [] for i, dimer_i in enumerate(selected_dimers[:-1]): keep = True for dimer_j in selected_dimers[i + 1:]: if dimer_i.same_geom(dimer_j, tol=args.tol_duplicate): keep = False break if keep: keep_these.append(dimer_i) # don't forget that the last one was not included in the parent loop keep_these.append(selected_dimers[-1]) selected_dimers = keep_these prints("{} dimers remaining after removing duplicates".format( len(selected_dimers))) if args.output_geometry_data: data_file = open(args.output_geometry_data, "w") header_str = "{:>13}{:>10}{:>10}{:>10}{:>17}{:>13}{:>11}\n".format( "Dimer number", "Alpha", "Beta", "Gamma", "Centroid dist", "Slip angle", "Category") data_file.write(header_str) for i, dimer in enumerate(selected_dimers): if args.output_geometry_data: cen_dist = dimer.inter_distance(method='centroid') angles = dimer.angles() slip_angle = dimer.slip_angle() # classify if 20 < angles[2] < 160: category = "E-F" elif slip_angle > 60: category = "S-S" else: category = "F-F" data_file.write( "{:>7}{:17.3f}{:10.3f}{:10.3f}{:12.3f}{:15.3f}{:>10}\n".format( i + 1, angles[0], angles[1], angles[2], cen_dist, slip_angle, category)) if args.print_dimers: out_name = str(args.input[:-4]) + "_dimer_" + str(i + 1) + ".xyz" dimer.write_xyz(out_name) if args.output_geometry_data: data_file.close()
def pery_cell(): """Return a Mol object of the uncharged perylene cell""" out_cell = rf.mol_from_file("perylene_cell.xyz") out_cell.vectors = rf.read_vectors("perylene_vectors") return out_cell
def main(in_xyz, vectors_file, complete, confine, frac, dupli, output, bonding, thresh, bonding_str, print_mono, trans, clust_rad, inclusivity, center_label): vectors = rf.read_vectors(vectors_file) atoms = rf.mol_from_file(in_xyz, vectors=vectors) if thresh == 999: thresh = None atoms.set_bonding(bonding=bonding, thresh=thresh) # if the bonding is specified all in one string if bonding_str: atoms.set_bonding_str(bonding_str) if print_mono and not complete: print("-c is required for -m") return if sum([complete, confine, frac]) > 1: print("-c, -C and -f are mutually exclusive") return print_now = True centered = False if center_label: central_mol, atoms = atoms.centered_mols(center_label - 1) # -1 for Python index centered = True if complete: # get the modified (uncropped) unit cell mod_cell, mols = atoms.complete_cell() elif confine: # get the cell confined to primitive mod_cell = atoms.confined() elif frac: # get the cell in fractional coordinates mod_cell = atoms.dir_to_frac_pos() elif centered: mod_cell = atoms.copy() else: mod_cell = deepcopy(atoms) print_now = False if dupli: # purge duplicate atoms mod_cell.remove_duplicates() print_now = True if print_now: mod_cell.write_xyz(output) if trans: translation = np.array(trans) new_atoms = mod_cell.supercell(translation) new_vec = (vectors.T * translation.transpose()).T new_atoms.write_xyz("supercell_out.xyz") ef.write_lat_vec("supercell_vectors", new_vec) if clust_rad > 0.0: clust = atoms.make_cluster(clust_rad, mode=inclusivity) clust.write_xyz("cluster_out.xyz") if print_mono: identities = [] # for each molecule of the modified unit cell for mol_i in mols: # get the rest of the molecules rest = [] for mol_j in mols: if mol_j != mol_i: rest.append(mol_j) identity = [] # for each dimer including the selected molecule for mol_j in rest: dimer_distances = [] # get all of the interatomic distances across the dimer using the # shortest lattice distance for at_i in mol_i: for at_j in mol_j: dimer_distances.append(at_i.per_dist(at_j, vectors)) dimer_distances.sort() identity.append(dimer_distances) identity.sort() identities.append(identity) identities = np.array(identities) # list of each molecules paired with its identity # in Python 2 we could just use a zip but for compatibility with Python3 # we need a list of tuples mols_ids = [(mol_i, iden_i) for mol_i, iden_i in zip(mols, identities)] # list of each molecule paired with its identity separated by equivalent # molecule sep_mols_ids = [] while len(mols_ids) > 0: sep_mol_id = [mols_ids[0]] for mol_i, id_i in mols_ids[1:]: comp = compare_id(mols_ids[0][1], id_i) # if the identities being compared don't have the same dimension, # the comparison will return None. This implies that the molecules # are not equivalent. This case only happens in crystals with # different monomers if comp: if comp < 0.001: sep_mol_id.append((mol_i, id_i)) mols_ids.remove((mol_i, id_i)) del mols_ids[0] sep_mols_ids.append(sep_mol_id) for counter, equimols in enumerate(sep_mols_ids): # only the list of lists of atoms i.e. list of molecules which are # equivalent fequimols = [i[0] for i in equimols] # make it a flat list fequimols = [inner for outer in fequimols for inner in outer] ef.write_xyz("mono_" + str(counter + 1) + ".xyz", fequimols) return