def read_molecule(string: str) -> Union[Molecule, Literal["read"]]: """ Read molecule from string. Args: string (str): String Returns: Molecule """ charge = None spin_mult = None patterns = { "read": r"^\s*\$molecule\n\s*(read)", "charge": r"^\s*\$molecule\n\s*((?:\-)*\d+)\s+\d", "spin_mult": r"^\s*\$molecule\n\s(?:\-)*\d+\s*(\d)", } matches = read_pattern(string, patterns) if "read" in matches.keys(): return "read" if "charge" in matches.keys(): charge = float(matches["charge"][0][0]) if "spin_mult" in matches.keys(): spin_mult = int(matches["spin_mult"][0][0]) header = r"^\s*\$molecule\n\s*(?:\-)*\d+\s*\d" row = r"\s*((?i)[a-z]+)\s+([\d\-\.]+)\s+([\d\-\.]+)\s+([\d\-\.]+)" footer = r"^\$end" mol_table = read_table_pattern(string, header_pattern=header, row_pattern=row, footer_pattern=footer) species = [val[0] for val in mol_table[0]] coords = [[float(val[1]), float(val[2]), float(val[3])] for val in mol_table[0]] if charge is None: mol = Molecule(species=species, coords=coords) else: mol = Molecule(species=species, coords=coords, charge=charge, spin_multiplicity=spin_mult) return mol
def MakesGauInputs(mol_file, dihed_atoms_file, w, num_conform=19): """ Creates Gaussian input files in its own folder for mol_file structues that freezes the central angle at iterations of 180/num_conform degrees. This function requires Gaussian output file of molecule in question and file with dihedral atoms to be in the current working directory. """ molecule_name = mol_file.split('/')[-1][:-12] mol_pymat = Molecule.from_file(mol_file) molecule = pmgmol_to_rdmol(mol_pymat)[0] with open(dihed_atoms_file, 'r') as fn: data = fn.readlines() dihedral1 = data[0].split(',')[0] dihedral2 = data[0].split(',')[1] d1atom1_num = int(dihedral1.split()[0]) d1atom2_num = int(dihedral1.split()[1]) d1atom3_num = int(dihedral1.split()[2]) d1atom4_num = int(dihedral1.split()[3]) phi = np.linspace(start=0, stop=180, num=num_conform) for P in phi: dir_name = "{}/{}_{:.0f}deg/".format(os.getcwd(), molecule_name, P) os.mkdir(dir_name) file_name = "{}/{}_{:.0f}deg".format(dir_name, molecule_name, P) SetDihedralDeg(molecule.GetConformer(), d1atom1_num, d1atom2_num, d1atom3_num, d1atom4_num, P) with open(dir_name + "temp.xyz", 'w+') as fout: fout.write(str(MolToXYZBlock(molecule))) mol = Molecule.from_file(dir_name + 'temp.xyz') os.remove(dir_name + 'temp.xyz') gau = GaussianInput(mol=mol, charge=0, spin_multiplicity=1, functional='uLC-wPBE', basis_set='cc-pVDZ', route_parameters={ "iop(3/107={}, 3/108={})".format(w, w): "", "opt": "modredundant" }, link0_parameters={ '%mem': '5GB', '%chk': '{}.chk'.format(file_name.split('/')[-1]) }) gjf_file = gau.write_file(dir_name + 'temp.gjf') with open(dir_name + 'temp.gjf') as temp: lines = temp.readlines() os.remove(dir_name + 'temp.gjf') with open(file_name + '.gjf', 'w') as gjf: gjf.writelines([item for item in lines[:-2]]) gjf.write("D * {} {} * F\n\n".format(d1atom2_num + 1, d1atom3_num + 1)) print( "Torsion Gaussian input files for {} finsihed!".format(molecule_name))
def make_mols(molecule_subgraphs=molecule_subgraphs, center=False): # pylint:disable=dangerous-default-value molecules = [] indices = [] indices_here = [] mol_centers = [] coordinates = [] for subgraph in molecule_subgraphs: coords = [ supercell_sg.structure[node].coords for node in subgraph.nodes() ] species = [ supercell_sg.structure[node].specie for node in subgraph.nodes() ] # binding = [ # supercell_sg.structure[n].properties["binding"] # for n in subgraph.nodes() # ] idx = [subgraph.nodes[node]["idx"] for node in subgraph.nodes()] idx_here = subgraph.nodes() molecule = Molecule( species, coords) # site_properties={"binding": binding} mol_centers.append( np.mean(supercell_sg.structure.cart_coords[idx_here], axis=0)) # shift so origin is at center of mass if center: molecule = molecule.get_centered_molecule() indices.append(idx) molecules.append(molecule) indices_here.append(idx_here) coordinates.append(coords) return molecules, indices, indices_here, mol_centers, coordinates
def test_double_FF_opt(self): # location of test files test_double_FF_files = os.path.join(module_dir, "..", "..", "test_files", "double_FF_wf") # define starting molecule and workflow object initial_qcin = QCInput.from_file( os.path.join(test_double_FF_files, "block", "launcher_first", "mol.qin.opt_0")) initial_mol = initial_qcin.molecule real_wf = get_wf_double_FF_opt( molecule=initial_mol, pcm_dielectric=10.0, max_cores=32, qchem_input_params={ "basis_set": "6-311++g**", "overwrite_inputs": { "rem": { "sym_ignore": "true" } } }) # use powerup to replace run with fake run ref_dirs = { "first_FF_no_pcm": os.path.join(test_double_FF_files, "block", "launcher_first"), "second_FF_with_pcm": os.path.join(test_double_FF_files, "block", "launcher_second") } fake_wf = use_fake_qchem(real_wf, ref_dirs) self.lp.add_wf(fake_wf) rapidfire( self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) wf_test = self.lp.get_wf_by_fw_id(1) self.assertTrue( all([s == "COMPLETED" for s in wf_test.fw_states.values()])) first_FF = self.get_task_collection().find_one({ "task_label": "first_FF_no_pcm" }) self.assertEqual(first_FF["calcs_reversed"][0]["input"]["solvent"], None) self.assertEqual(first_FF["num_frequencies_flattened"], 1) first_FF_final_mol = Molecule.from_dict( first_FF["output"]["optimized_molecule"]) second_FF = self.get_task_collection().find_one({ "task_label": "second_FF_with_pcm" }) self.assertEqual(second_FF["calcs_reversed"][0]["input"]["solvent"], {"dielectric": "10.0"}) self.assertEqual(second_FF["num_frequencies_flattened"], 1) second_FF_initial_mol = Molecule.from_dict( second_FF["input"]["initial_molecule"]) self.assertEqual(first_FF_final_mol, second_FF_initial_mol)
def test_double_FF_opt(self): # location of test files test_double_FF_files = os.path.join(module_dir, "..", "..", "test_files", "double_FF_wf") # define starting molecule and workflow object initial_qcin = QCInput.from_file( os.path.join(test_double_FF_files, "block", "launcher_first", "mol.qin.opt_0")) initial_mol = initial_qcin.molecule real_wf = get_wf_double_FF_opt( molecule=initial_mol, pcm_dielectric=10.0, qchem_input_params={ "basis_set": "6-311++g**", "scf_algorithm": "diis", "overwrite_inputs": { "rem": { "sym_ignore": "true" } } }) # use powerup to replace run with fake run ref_dirs = { "first_FF_no_pcm": os.path.join(test_double_FF_files, "block", "launcher_first"), "second_FF_with_pcm": os.path.join(test_double_FF_files, "block", "launcher_second") } fake_wf = use_fake_qchem(real_wf, ref_dirs) self.lp.add_wf(fake_wf) rapidfire( self.lp, fworker=FWorker(env={"max_cores": 32, "db_file": os.path.join(db_dir, "db.json")})) wf_test = self.lp.get_wf_by_fw_id(1) self.assertTrue( all([s == "COMPLETED" for s in wf_test.fw_states.values()])) first_FF = self.get_task_collection().find_one({ "task_label": "first_FF_no_pcm" }) self.assertEqual(first_FF["calcs_reversed"][0]["input"]["solvent"], None) self.assertEqual(first_FF["num_frequencies_flattened"], 1) first_FF_final_mol = Molecule.from_dict( first_FF["output"]["optimized_molecule"]) second_FF = self.get_task_collection().find_one({ "task_label": "second_FF_with_pcm" }) self.assertEqual(second_FF["calcs_reversed"][0]["input"]["solvent"], {"dielectric": "10.0"}) self.assertEqual(second_FF["num_frequencies_flattened"], 1) second_FF_initial_mol = Molecule.from_dict( second_FF["input"]["initial_molecule"]) self.assertEqual(first_FF_final_mol, second_FF_initial_mol)
def setUpClass(cls): cls.pt_mol = Molecule.from_file( os.path.join(module_dir, "..", "..", "test_files", "pt_gs_wb97mv_tz_initial.xyz")) cls.pt_rot_90_mol = Molecule.from_file( os.path.join(module_dir, "..", "..", "test_files", "pt_rotated_90.0.xyz"))
def mol_from_pymatgen(mol: Molecule): """ Args: mol(Molecule) """ mol = pybel.Molecule(BabelMolAdaptor(mol).openbabel_mol) mol.make3D() return mol
def get_subgraphs_as_molecules_all( structure_graph: pymatgen.analysis.graphs.StructureGraph, ): """Copied from http://pymatgen.org/_modules/pymatgen/analysis/graphs.html#StructureGraph.get_subgraphs_as_molecules and removed the duplicate check Args: structure_graph ( pymatgen.analysis.graphs.StructureGraph): Structuregraph Returns: List: list of molecules """ # creating a supercell is an easy way to extract # molecules (and not, e.g., layers of a 2D crystal) # without adding extra logic supercell_sg = structure_graph * (3, 3, 3) # make undirected to find connected subgraphs supercell_sg.graph = nx.Graph(supercell_sg.graph) # find subgraphs all_subgraphs = [ supercell_sg.graph.subgraph(c) for c in nx.connected_components(supercell_sg.graph) ] # discount subgraphs that lie across *supercell* boundaries # these will subgraphs representing crystals molecule_subgraphs = [] for subgraph in all_subgraphs: intersects_boundary = any([ d["to_jimage"] != (0, 0, 0) for u, v, d in subgraph.edges(data=True) ]) if not intersects_boundary: molecule_subgraphs.append(nx.MultiDiGraph(subgraph)) # add specie names to graph to be able to test for isomorphism for subgraph in molecule_subgraphs: for node in subgraph: subgraph.add_node(node, specie=str(supercell_sg.structure[node].specie)) # get Molecule objects for each subgraph molecules = [] for subgraph in molecule_subgraphs: coords = [supercell_sg.structure[n].coords for n in subgraph.nodes()] species = [supercell_sg.structure[n].specie for n in subgraph.nodes()] molecule = Molecule(species, coords) # shift so origin is at center of mass molecule = molecule.get_centered_molecule() molecules.append(molecule) return molecules
def test_random_seed(self, water, ethanol): """ Confirm that seed = -1 generates random structures while seed = 1 is deterministic """ # deterministic output with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolWrapper( scratch_dir, molecules=[ { "name": "water", "number": 10, "coords": water }, { "name": "ethanol", "number": 20, "coords": ethanol }, ], seed=1, inputfile="input.in", outputfile="output.xyz", ) pw.make_packmol_input() pw.run_packmol() out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) pw.run_packmol() out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) assert np.array_equal(out1.cart_coords, out2.cart_coords) # randomly generated structures with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolWrapper( scratch_dir, molecules=[ { "name": "water", "number": 10, "coords": water }, { "name": "ethanol", "number": 20, "coords": ethanol }, ], seed=-1, inputfile="input.in", outputfile="output.xyz", ) pw.make_packmol_input() pw.run_packmol() out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) pw.run_packmol() out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) assert not np.array_equal(out1.cart_coords, out2.cart_coords)
def test_random_seed(self, water, ethanol): """ Confirm that seed = -1 generates random structures while seed = 1 is deterministic """ mm = MoleculeMatcher() # deterministic output with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolBoxGen( seed=1, inputfile="input.in", outputfile="output.xyz", ).get_input_set( # scratch_dir, molecules=[ { "name": "water", "number": 10, "coords": water }, { "name": "ethanol", "number": 20, "coords": ethanol }, ], ) pw.write_input(scratch_dir) pw.run(scratch_dir) out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) pw.run(scratch_dir) out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) assert mm.fit(out1, out2) # randomly generated structures with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolBoxGen( seed=-1, inputfile="input.in", outputfile="output.xyz", ).get_input_set(molecules=[ { "name": "water", "number": 10, "coords": water }, { "name": "ethanol", "number": 20, "coords": ethanol }, ], ) pw.write_input(scratch_dir) pw.run(scratch_dir) out1 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) pw.run(scratch_dir) out2 = Molecule.from_file(os.path.join(scratch_dir, "output.xyz")) assert not mm.fit(out1, out2)
def update(self, coords, lattice=None, absolute=False, update_mol=True): """ After the geometry relaxation, the returned atomic coordinates maybe rescaled to [0, 1] bound. In this case, we need to refind the molecular coordinates according to the original neighbor list. If the list does not change, we return the new coordinates otherwise, terminate the calculation. """ from pyxtal.molecule import compare_mol_connectivity, Orientation try: from openbabel import pybel, openbabel except: import pybel, openbabel if lattice is not None: self.lattice = lattice if not absolute: coords = coords.dot(self.lattice.matrix) #mol = Molecule(self.symbols, coords-np.mean(coords, axis=0)) center = self.molecule.get_center(coords) mol = Molecule(self.symbols, coords - center) #match, _ = compare_mol_connectivity(mol, self.mol, True) match, _ = compare_mol_connectivity(mol, self.mol) if match: #position = np.mean(coords, axis=0).dot(self.lattice.inv_matrix) position = center.dot(self.lattice.inv_matrix) #position -= np.floor(position) self.position = position - np.floor(position) if update_mol: self.orientation = Orientation(np.eye(3)) self.mol = mol else: m1 = pybel.readstring('xyz', self.mol.to('xyz')) m2 = pybel.readstring('xyz', mol.to('xyz')) aligner = openbabel.OBAlign(True, False) aligner.SetRefMol(m1.OBMol) aligner.SetTargetMol(m2.OBMol) if aligner.Align(): print("RMSD: ", aligner.GetRMSD()) rot = np.zeros([3, 3]) for i in range(3): for j in range(3): rot[i, j] = aligner.GetRotMatrix().Get(i, j) if abs(np.linalg.det(rot) - 1) < 1e-2: self.orientation.matrix = rot self.orientation.r = R.from_matrix(rot) else: raise ValueError("rotation matrix is wrong") else: import pickle with open('wrong.pkl', "wb") as f: pickle.dump([mol, self.mol], f) mol.to(filename='Wrong.xyz', fmt='xyz') self.mol.to(filename='Ref.xyz', fmt='xyz') raise ValueError("molecular connectivity changes! Exit")
def setUpClass(cls): # head molecule cls.peo_head = Molecule.from_file( os.path.join(test_dir, "peo_head.xyz")) charges = [ -0.1187, 0.0861, 0.0861, 0.0861, -0.2792, -0.0326, 0.0861, 0.0861 ] cls.peo_head.add_site_property("charge", charges) s_head = 0 s_tail = 5 # chain molecule cls.peo_bulk = Molecule.from_file( os.path.join(test_dir, "peo_bulk.xyz")) charges = [-0.0326, 0.0861, 0.0861, -0.2792, -0.0326, 0.0861, 0.0861] cls.peo_bulk.add_site_property("charge", charges) head = 0 tail = 4 # terminal molecule cls.peo_tail = Molecule.from_file( os.path.join(test_dir, "peo_tail.xyz")) charges = [ -0.0326, 0.0861, 0.0861, -0.2792, -0.1187, 0.0861, 0.0861, 0.0861 ] cls.peo_tail.add_site_property("charge", charges) e_head = 0 e_tail = 4 cls.n_units = 25 link_distance = 1.5075 # create the polymer cls.peo_polymer = Polymer(cls.peo_head, s_head, s_tail, cls.peo_bulk, head, tail, cls.peo_tail, e_head, e_tail, cls.n_units, link_distance) # linear chain cls.peo_polymer_linear = Polymer(cls.peo_head, s_head, s_tail, cls.peo_bulk, head, tail, cls.peo_tail, e_head, e_tail, cls.n_units, link_distance, linear_chain=True)
def setUpClass(cls): co_species = ['C', 'O'] co_coords = [[0.0, 0.0, 0.0], [1.3, 0.0, 0.0]] cls.co_mol = Molecule(co_species, co_coords) cls.co_opt_ref_in = QCInput.from_file( os.path.join(module_dir, "..", "..", "test_files", "co_qc.in"))
def from_dict(cls, d): mol = Molecule.from_dict(d["mol"]) return NwTask(mol, charge=d["charge"], spin_multiplicity=d["spin_multiplicity"], title=d["title"], theory=d["theory"], operation=d["operation"], basis_set=d["basis_set"], theory_directives=d["theory_directives"])
def parse_symmetry(pos): mol = Molecule(["C"] * len(pos), pos) try: symbol = PointGroupAnalyzer(mol, tolerance=0.1).sch_symbol except: symbol = "N/A" return symbol
def setUpClass(cls): cls.structure = Structure.from_file( os.path.join(MODULE_DIR, "cifs", "BaTiO3_mp-2998_computed.cif")) cls.molecule = Molecule(["C", "O", "O"], [[0, 0, 0], [-1, 0, 0], [1, 0, 0]]) cls.mall = MinimumDistanceNNAll(4) cls.aapair = AllAtomPairs()
def test_coordination(self): molecule = Molecule(["C", "C"], [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]]) mg = MoleculeGraph.with_empty_graph(molecule) self.assertEqual(mg.get_coordination_of_site(0), 0) self.assertEqual(self.cyclohexene.get_coordination_of_site(0), 4)
def test_simple_molecule_graph(self): mol = Molecule(["C", "H", "O"], [[0, 0, 0], [1, 0, 0], [2, 0, 0]]) graph = SimpleMolGraph().convert(mol) self.assertListEqual(to_list(graph["atom"]), [6, 1, 8]) self.assertTrue(np.allclose(graph["bond"], [1, 2, 1, 1, 2, 1])) self.assertListEqual(to_list(graph["index1"]), [0, 0, 1, 1, 2, 2]) self.assertListEqual(to_list(graph["index2"]), [1, 2, 0, 2, 0, 1])
def from_dict(cls, d): return FiestaInput(Molecule.from_dict(d["mol"]), correlation_grid=d["correlation_grid"], Exc_DFT_option=d["Exc_DFT_option"], COHSEX_options=d["geometry_options"], GW_options=d["symmetry_options"], BSE_TDDFT_options=d["memory_options"])
def generate_gjf(in_fn, out_dir, functional='LC-wHPBE', basis_set='TZVP', charge=0, calculation='opt', omega=None, oldchk=None): """ Convert an individually inputted xyz file to a gjf Gaussian input file """ mol = Molecule.from_file(in_fn) mol.perturb(0.1) mol_name = in_fn.split('/')[-1][:14] link0_parameters = {'%mem': '5GB', '%chk': '{}.chk'.format(calculation)} route_parameters = { calculation: '', 'SCF': '(MaxCycle=250)', 'Int': '(Grid=Ultrafine)' } if calculation == 'tddft': route_parameters = {'TD(NStates=5, 50-50)': ''} if omega is not None: route_parameters["iop(3/107={}, 3/108={})".format(omega, omega)] = '' if oldchk: link0_parameters['%oldchk'] = '{}.chk'.format(oldchk) route_parameters['Geom'] = 'AllCheck' gau = GaussianInput(mol=mol, charge=charge, functional=functional, basis_set=basis_set, route_parameters=route_parameters, link0_parameters=link0_parameters) gjf_file = gau.write_file('{}/{}.gjf'.format(out_dir, calculation)) return gjf_file
def WriteXYZ(in_file, out_dir): """ Write xyz file. """ mol = Molecule.from_file(in_file) fout = os.path.join(out_dir, in_file.split('/')[-1]) mol.to(filename=fout)
def _read_species_and_inital_geometry(self): """ Parses species and initial geometry. """ header_pattern = r"Standard Nuclear Orientation \(Angstroms\)\s+I\s+Atom\s+X\s+Y\s+Z\s+-+" table_pattern = r"\s*\d+\s+([a-zA-Z]+)\s*([\d\-\.]+)\s*([\d\-\.]+)\s*([\d\-\.]+)\s*" footer_pattern = r"\s*-+" temp_geom = read_table_pattern(self.text, header_pattern, table_pattern, footer_pattern) if temp_geom == None or len(temp_geom) == 0: self.data["species"] = None self.data["initial_geometry"] = None self.data["initial_molecule"] = None else: temp_geom = temp_geom[0] species = [] geometry = np.zeros(shape=(len(temp_geom), 3), dtype=float) for ii, entry in enumerate(temp_geom): species += [entry[0]] for jj in range(3): geometry[ii, jj] = float(entry[jj + 1]) self.data["species"] = species self.data["initial_geometry"] = geometry self.data["initial_molecule"] = Molecule( species=species, coords=geometry, charge=self.data.get('charge'), spin_multiplicity=self.data.get('multiplicity'))
def _read_optimized_geometry(self): """ Parses optimized XYZ coordinates. If not present, parses optimized Z-matrix. """ header_pattern = r"\*+\s+OPTIMIZATION\s+CONVERGED\s+\*+\s+\*+\s+Coordinates \(Angstroms\)\s+ATOM\s+X\s+Y\s+Z" table_pattern = r"\s+\d+\s+\w+\s+([\d\-\.]+)\s+([\d\-\.]+)\s+([\d\-\.]+)" footer_pattern = r"\s+Z-matrix Print:" parsed_optimized_geometry = read_table_pattern(self.text, header_pattern, table_pattern, footer_pattern) if parsed_optimized_geometry == [] or None: self.data["optimized_geometry"] = None header_pattern = r"^\s+\*+\s+OPTIMIZATION CONVERGED\s+\*+\s+\*+\s+Z-matrix\s+Print:\s+\$molecule\s+[\d\-]+\s+[\d\-]+\n" table_pattern = r"\s*(\w+)(?:\s+(\d+)\s+([\d\-\.]+)(?:\s+(\d+)\s+([\d\-\.]+)(?:\s+(\d+)\s+([\d\-\.]+))*)*)*(?:\s+0)*" footer_pattern = r"^\$end\n" self.data["optimized_zmat"] = read_table_pattern( self.text, header_pattern, table_pattern, footer_pattern) else: self.data["optimized_geometry"] = process_parsed_coords( parsed_optimized_geometry[0]) if self.data.get('charge') != None: self.data["molecule_from_optimized_geometry"] = Molecule( species=self.data.get('species'), coords=self.data.get('optimized_geometry'), charge=self.data.get('charge'), spin_multiplicity=self.data.get('multiplicity'))
def test_packmol_with_molecule(self, water, ethanol): """ Test coords input as Molecule """ with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolWrapper( scratch_dir, molecules=[ { "name": "water", "number": 10, "coords": water }, { "name": "ethanol", "number": 20, "coords": ethanol }, ], ) pw.make_packmol_input() pw.run_packmol() assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) out = Molecule.from_file( os.path.join(scratch_dir, "packmol_out.xyz")) assert out.composition.num_atoms == 10 * 3 + 20 * 9
def test_coulomb_matrix(self): # flat cm = CoulombMatrix(flatten=True) df = pd.DataFrame({"s": [self.diamond, self.nacl]}) with self.assertRaises(NotFittedError): df = cm.featurize_dataframe(df, "s") df = cm.fit_featurize_dataframe(df, "s") labels = cm.feature_labels() self.assertListEqual(labels, ["coulomb matrix eig 0", "coulomb matrix eig 1"]) self.assertArrayAlmostEqual(df[labels].iloc[0], [49.169453, 24.546758], decimal=5) self.assertArrayAlmostEqual(df[labels].iloc[1], [153.774731, 452.894322], decimal=5) # matrix species = ["C", "C", "H", "H"] coords = [[0, 0, 0], [0, 0, 1.203], [0, 0, -1.06], [0, 0, 2.263]] acetylene = Molecule(species, coords) morig = CoulombMatrix(flatten=False).featurize(acetylene) mtarget = [[36.858, 15.835391290, 2.995098235, 1.402827813], \ [15.835391290, 36.858, 1.4028278132103624, 2.9950982], \ [2.9368896127, 1.402827813, 0.5, 0.159279959], \ [1.4028278132, 2.995098235, 0.159279959, 0.5]] self.assertAlmostEqual(int(np.linalg.norm(morig - np.array(mtarget))), 0) m = CoulombMatrix(diag_elems=False, flatten=False).featurize(acetylene)[0] self.assertAlmostEqual(m[0][0], 0.0) self.assertAlmostEqual(m[1][1], 0.0) self.assertAlmostEqual(m[2][2], 0.0) self.assertAlmostEqual(m[3][3], 0.0)
def test_packmol_with_path(self): """ Test coords input as Path. Use a subdirectory with spaces. """ p1 = Path(os.path.join(test_dir, "subdir with spaces", "EMC.xyz")) p2 = Path(os.path.join(test_dir, "LiTFSi.xyz")) with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolWrapper( scratch_dir, molecules=[ { "name": "EMC", "number": 10, "coords": p1 }, { "name": "LiTFSi", "number": 20, "coords": p2 }, ], ) pw.make_packmol_input() pw.run_packmol() assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) out = Molecule.from_file( os.path.join(scratch_dir, "packmol_out.xyz")) assert out.composition.num_atoms == 10 * 15 + 20 * 16
def get_mol_object(self, id=0): """ make the pymatgen molecule object Args: id: the index of molecules in the given site Returns: a molecule object """ coord0 = self.mol.cart_coords.dot(self.orientation.matrix.T) # # Obtain the center in absolute coords if id <= len(self.wp.generators): op = self.wp.generators[id] center_relative = op.operate(self.position) center_relative -= np.floor(center_relative) #print(center_relative) center_absolute = np.dot(center_relative, self.lattice.matrix) # Rotate the molecule (Euclidean metric) op_m = self.wp.generators_m[id] rot = op_m.affine_matrix[0:3][:, 0:3].T tau = op_m.affine_matrix[0:3][:, 3] tmp = np.dot(coord0, rot) + tau # Add absolute center to molecule tmp += center_absolute return Molecule(self.symbols, tmp) else: raise ValueError("id is greater than the number of molecules")
def run_task(self, fw_spec): self["constituent_molecules"] self["mols_number"] input_filename = self["input_filename"] forcefield = self["forcefield"] topologies = self["topologies"] user_settings = self.get("user_settings", {}) data_filename = self.get("data_filename", user_settings.get("data_file", "lammps.data")) final_molecule = self["final_molecule"] # if the final molecule was generated using packmol if fw_spec.get("packed_mol", None): final_molecule = fw_spec["packed_mol"] elif isinstance(final_molecule, str): final_molecule = Molecule.from_file(final_molecule) # molecules, mols_number, final_molecule lammps_ff_data = LammpsData.from_ff_and_topologies( forcefield, topologies, self["box_size"]) lammps_input_set = LammpsInputSet.from_file( "ff-inputset", self["input_file"], user_settings=user_settings, lammps_data=lammps_ff_data, data_filename=data_filename, is_forcefield=True, ) lammps_input_set.write_input(input_filename, data_filename)
def read_molecule(string): charge = None spin_mult = None patterns = { "read": r"^\s*\$molecule\n\s*(read)", "charge": r"^\s*\$molecule\n\s*((?:\-)*\d+)\s+\d", "spin_mult": r"^\s*\$molecule\n\s*\d+\s*(\d)" } matches = read_pattern(string, patterns) if "read" in matches.keys(): return "read" if "charge" in matches.keys(): charge = float(matches["charge"][0][0]) if "spin_mult" in matches.keys(): spin_mult = int(matches["spin_mult"][0][0]) header = r"^\s*\$molecule\n\s*(?:\-)*\d+\s*\d" row = r"\s*((?i)[a-z]+)\s+([\d\-\.]+)\s+([\d\-\.]+)\s+([\d\-\.]+)" footer = r"^\$end" mol_table = read_table_pattern(string, header_pattern=header, row_pattern=row, footer_pattern=footer) species = [val[0] for val in mol_table[0]] coords = [[float(val[1]), float(val[2]), float(val[3])] for val in mol_table[0]] mol = Molecule(species=species, coords=coords, charge=charge, spin_multiplicity=spin_mult) return mol
def test_isomorphic(self): ethylene = Molecule.from_file( os.path.join( PymatgenTest.TEST_FILES_DIR, "graphs/ethylene.xyz", )) # switch carbons ethylene[0], ethylene[1] = ethylene[1], ethylene[0] eth_copy = MoleculeGraph.with_edges( ethylene, { (0, 1): { "weight": 2 }, (1, 2): { "weight": 1 }, (1, 3): { "weight": 1 }, (0, 4): { "weight": 1 }, (0, 5): { "weight": 1 }, }, ) # If they are equal, they must also be isomorphic eth_copy = copy.deepcopy(self.ethylene) self.assertTrue(self.ethylene.isomorphic_to(eth_copy)) self.assertFalse(self.butadiene.isomorphic_to(self.ethylene))
def from_dict(cls, d): return NwInput(Molecule.from_dict(d["mol"]), tasks=[NwTask.from_dict(dt) for dt in d["tasks"]], directives=[tuple(li) for li in d["directives"]], geometry_options=d["geometry_options"], symmetry_options=d["symmetry_options"], memory_options=d["memory_options"])
def test_packmol_with_str(self): """ Test coords input as strings """ with tempfile.TemporaryDirectory() as scratch_dir: pw = PackmolBoxGen().get_input_set(molecules=[ { "name": "EMC", "number": 10, "coords": os.path.join(test_dir, "subdir with spaces", "EMC.xyz") }, { "name": "LiTFSi", "number": 20, "coords": os.path.join(test_dir, "LiTFSi.xyz") }, ], ) pw.write_input(scratch_dir) pw.run(scratch_dir) assert os.path.exists(os.path.join(scratch_dir, "packmol_out.xyz")) out = Molecule.from_file( os.path.join(scratch_dir, "packmol_out.xyz")) assert out.composition.num_atoms == 10 * 15 + 20 * 16
def test_parse_pass_rotate_write(self): input_file = "pt_gs_wb97mv_tz_initial.in" output_file = "pt_gs_wb97mv_tz_initial_1_job.out" calc_dir = os.path.join(module_dir, "..", "..", "test_files") p_task = QChemToDb(calc_dir=calc_dir, input_file=input_file, output_file=output_file, db_file=">>db_file<<") fw1 = Firework([p_task]) atom_indexes = [6, 8, 9, 10] angle = 90.0 rot_task = RotateTorsion(atom_indexes=atom_indexes, angle=angle) w_task = WriteInputFromIOSet(qchem_input_set="OptSet", write_to_dir=module_dir) fw2 = Firework([rot_task, w_task], parents=fw1) wf = Workflow([fw1, fw2]) self.lp.add_wf(wf) rapidfire( self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) test_mol = QCInput.from_file(os.path.join(module_dir, "mol.qin")).molecule act_mol = Molecule.from_file( os.path.join(module_dir, "..", "..", "test_files", "pt_rotated_90.0.xyz")) np.testing.assert_equal(act_mol.species, test_mol.species) np.testing.assert_allclose(act_mol.cart_coords, test_mol.cart_coords, atol=0.0001)
def from_dict(cls, d): return GaussianInput(mol=Molecule.from_dict(d["molecule"]), functional=d["functional"], basis_set=d["basis_set"], route_parameters=d["route_parameters"], title=d["title"], charge=d["charge"], spin_multiplicity=d["spin_multiplicity"], input_parameters=d["input_parameters"], link0_parameters=d["link0_parameters"])
def setUpClass(cls): # head molecule cls.peo_head = Molecule.from_file(os.path.join(test_dir, "peo_head.xyz")) charges = [-0.1187, 0.0861, 0.0861, 0.0861, -0.2792, -0.0326, 0.0861, 0.0861] cls.peo_head.add_site_property("charge", charges) s_head = 0 s_tail = 5 # chain molecule cls.peo_bulk = Molecule.from_file(os.path.join(test_dir, "peo_bulk.xyz")) charges = [-0.0326, 0.0861, 0.0861, -0.2792, -0.0326, 0.0861, 0.0861] cls.peo_bulk.add_site_property("charge", charges) head = 0 tail = 4 # terminal molecule cls.peo_tail = Molecule.from_file(os.path.join(test_dir, "peo_tail.xyz")) charges = [-0.0326, 0.0861, 0.0861, -0.2792, -0.1187, 0.0861, 0.0861, 0.0861] cls.peo_tail.add_site_property("charge", charges) e_head = 0 e_tail = 4 cls.n_units = 25 link_distance = 1.5075 # create the polymer cls.peo_polymer = Polymer(cls.peo_head, s_head, s_tail, cls.peo_bulk, head, tail, cls.peo_tail, e_head, e_tail, cls.n_units, link_distance) # linear chain cls.peo_polymer_linear = Polymer(cls.peo_head, s_head, s_tail, cls.peo_bulk, head, tail, cls.peo_tail, e_head, e_tail, cls.n_units, link_distance, linear_chain=True)
def setUpClass(cls): ethanol_coords = [[0.00720, -0.56870, 0.00000], [-1.28540, 0.24990, 0.00000], [1.13040, 0.31470, 0.00000], [0.03920, -1.19720, 0.89000], [0.03920, -1.19720, -0.89000], [-1.31750, 0.87840, 0.89000], [-1.31750, 0.87840, -0.89000], [-2.14220, -0.42390, -0.00000], [1.98570, -0.13650, -0.00000]] water_coords = [[9.626, 6.787, 12.673], [9.626, 8.420, 12.673], [10.203, 7.604, 12.673]] cls.ethanol_atoms = ["C", "C", "O", "H", "H", "H", "H", "H", "H"] cls.water_atoms = ["H", "H", "O"] ethanol = Molecule(cls.ethanol_atoms, ethanol_coords) water = Molecule(cls.water_atoms, water_coords) cls.mols = [ethanol, water] cls.cocktail = Molecule.from_file( os.path.join(test_dir, "cocktail.xyz")) cls.packmol_config = [{"number": 1}, {"number": 15}]
def test_no_opt_Fragmentation(self): db_file = os.path.join(db_dir, "db.json") mmdb = QChemCalcDb.from_db_file(db_file, admin=True) with open(os.path.join(module_dir, "..", "..", "test_files","sb40.json")) as f: tmp = json.load(f) for entry in tmp: mmdb.insert(entry) with patch("atomate.qchem.firetasks.fragmenter.FWAction") as FWAction_patch: mock_FWAction = MagicMock() FWAction_patch.return_value = mock_FWAction mock_FWAction.as_dict.return_value = {'stored_data': {}, 'exit': False, 'update_spec': {}, 'mod_spec': [], 'additions': [], 'detours': [], 'defuse_children': False, 'defuse_workflow': False} # define starting molecule and workflow object initial_mol = Molecule.from_file(os.path.join(module_dir, "..", "..", "test_files", "top_11", "EC.xyz")) initial_mol.set_charge_and_spin(charge=-1) wf = get_fragmentation_wf(molecule=initial_mol, depth=1, pcm_dielectric=40.0, do_optimization=False, check_db=True) self.lp.add_wf(wf) rapidfire( self.lp, fworker=FWorker(env={"max_cores": 24, "db_file": db_file}), pdb_on_exception=True) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 0) mmdb.reset()
def from_dict(cls, d): return NwInput(Molecule.from_dict(d["mol"]), [NwTask.from_dict(dt) for dt in d["tasks"]], d["directives"])
def test_torsion_potential(self): # location of test files test_tor_files = os.path.join(module_dir, "..", "..", "test_files", "torsion_wf") # define starting molecule and torsion potential workflow object initial_qcin = QCInput.from_file( os.path.join(test_tor_files, "initial_opt", "mol.qin")) initial_mol = initial_qcin.molecule atom_indexes = [6, 8, 9, 10] angles = [0.0, 90.0, 180.0] rem = [] # add the first rem section rem.append({ "jobtype": "opt", "method": "wb97m-v", "basis": "def2-tzvppd", "gen_scfman": "true", "geom_opt_max_cycles": 75, "max_scf_cycles": 300, "scf_algorithm": "diis", "scf_guess": "sad", "sym_ignore": "true", "symmetry": "false", "thresh": 14 }) # the second rem section rem.append({ "jobtype": "opt", "method": "wb97m-v", "basis": "def2-tzvppd", "geom_opt_max_cycles": 75, "max_scf_cycles": 300, "scf_algorithm": "diis", "scf_guess": "sad", "sym_ignore": "true", "symmetry": "false", "thresh": 14 }) real_wf = get_wf_torsion_potential( molecule=initial_mol, atom_indexes=atom_indexes, angles=angles, rem=rem, db_file=">>db_file<<") # use powerup to replace run with fake run # def ref_dirs ref_dirs = { "initial_opt": os.path.join(test_tor_files, "initial_opt"), "opt_0": os.path.join(test_tor_files, "opt_0"), "opt_90": os.path.join(test_tor_files, "opt_90"), "opt_180": os.path.join(test_tor_files, "opt_180") } fake_wf = use_fake_qchem(real_wf, ref_dirs) self.lp.add_wf(fake_wf) rapidfire( self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) wf_test = self.lp.get_wf_by_fw_id(1) self.assertTrue( all([s == "COMPLETED" for s in wf_test.fw_states.values()])) # Checking of the inputs happens in fake_run_qchem so there is no point to retest the inputs # Check the output info that gets inserted in the DB init_opt = self.get_task_collection().find_one({ "task_label": "initial_opt" }) init_opt_final_mol = Molecule.from_dict( init_opt["output"]["optimized_molecule"]) init_opt_final_e = init_opt["output"]["final_energy"] # parse output file act_init_opt_out = QCOutput( os.path.join(test_tor_files, "initial_opt", "mol.qout")) act_init_opt_mol = act_init_opt_out.data[ "molecule_from_optimized_geometry"] act_init_opt_final_e = act_init_opt_out.data["final_energy"] np.testing.assert_equal(act_init_opt_mol.species, init_opt_final_mol.species) np.testing.assert_allclose( act_init_opt_mol.cart_coords, init_opt_final_mol.cart_coords, atol=0.0001) np.testing.assert_equal(act_init_opt_final_e, init_opt_final_e) # Optimization of 0 torsion opt_0 = self.get_task_collection().find_one({"task_label": "opt_0"}) opt_0_final_mol = Molecule.from_dict( opt_0["output"]["optimized_molecule"]) opt_0_final_e = opt_0["output"]["final_energy"] # parse output file act_opt_0_out = QCOutput( os.path.join(test_tor_files, "opt_0", "mol.qout")) act_opt_0_mol = act_opt_0_out.data["molecule_from_optimized_geometry"] act_opt_0_final_e = act_opt_0_out.data["final_energy"] np.testing.assert_equal(act_opt_0_mol.species, opt_0_final_mol.species) np.testing.assert_allclose( act_opt_0_mol.cart_coords, opt_0_final_mol.cart_coords, atol=0.0001) np.testing.assert_equal(act_opt_0_final_e, opt_0_final_e) # Optimization of 90 torsion opt_90 = self.get_task_collection().find_one({"task_label": "opt_90"}) opt_90_final_mol = Molecule.from_dict( opt_90["output"]["optimized_molecule"]) opt_90_final_e = opt_90["output"]["final_energy"] # parse output file act_opt_90_out = QCOutput( os.path.join(test_tor_files, "opt_90", "mol.qout")) act_opt_90_mol = act_opt_90_out.data[ "molecule_from_optimized_geometry"] act_opt_90_final_e = act_opt_90_out.data["final_energy"] np.testing.assert_equal(act_opt_90_mol.species, opt_90_final_mol.species) np.testing.assert_allclose( act_opt_90_mol.cart_coords, opt_90_final_mol.cart_coords, atol=0.0001) np.testing.assert_equal(act_opt_90_final_e, opt_90_final_e) # Optimization of 180 torsion opt_180 = self.get_task_collection().find_one({ "task_label": "opt_180" }) opt_180_final_mol = Molecule.from_dict( opt_180["output"]["optimized_molecule"]) opt_180_final_e = opt_180["output"]["final_energy"] # parse output file act_opt_180_out = QCOutput( os.path.join(test_tor_files, "opt_180", "mol.qout")) act_opt_180_mol = act_opt_180_out.data[ "molecule_from_optimized_geometry"] act_opt_180_final_e = act_opt_180_out.data["final_energy"] np.testing.assert_equal(act_opt_180_mol.species, opt_180_final_mol.species) np.testing.assert_allclose( act_opt_180_mol.cart_coords, opt_180_final_mol.cart_coords, atol=0.0001) np.testing.assert_equal(act_opt_180_final_e, opt_180_final_e)
""" remainder = {} count_dict = get_elements_count(structure) weights = get_weight(stoich) scaled_max = max([count_dict[ele]*weights[ele] for ele in stoich.keys() ]) #determine the scaled maximum neded while scaled_max % lcm_list(list(weights.values())): # increase scaled max until it can accomodate correct stoichiometry scaled_max = scaled_max + 1 for ele, count in count_dict.items(): remainder[ele] = int((scaled_max - count_dict[ele]*weights[ele]) / (weights[ele])) return remainder surf = Molecule.from_file('D:\\Users\\RyanTrottier\\Documents\\Scrap\\tmp.'+type) center_i = 787 center = surf[center_i] # pymatgen.core.sites.Site for radius in [3,4,5,6,8]: dr = 4 stoich = get_stoichiometry(surf) sites = [center] + [ x[0] for x in surf.get_neighbors(center, radius)] mol = Molecule.from_sites(sites) remainder = get_remainder(mol, stoich) i = 0 # going to iterate over all sites, starting with the closest add_sites = surf.get_neighbors_in_shell(center.coords, radius+dr, dr)
def get_subgraphs_as_molecules(self, use_weights=False): """ Retrieve subgraphs as molecules, useful for extracting molecules from periodic crystals. Will only return unique molecules, not any duplicates present in the crystal (a duplicate defined as an isomorphic subgraph). :param use_weights (bool): If True, only treat subgraphs as isomorphic if edges have the same weights. Typically, this means molecules will need to have the same bond lengths to be defined as duplicates, otherwise bond lengths can differ. This is a fairly robust approach, but will treat e.g. enantiomers as being duplicates. :return: list of unique Molecules in Structure """ # creating a supercell is an easy way to extract # molecules (and not, e.g., layers of a 2D crystal) # without adding extra logic if getattr(self, '_supercell_sg', None) is None: self._supercell_sg = supercell_sg = self*(3,3,3) # make undirected to find connected subgraphs supercell_sg.graph = nx.Graph(supercell_sg.graph) # find subgraphs all_subgraphs = list(nx.connected_component_subgraphs(supercell_sg.graph)) # discount subgraphs that lie across *supercell* boundaries # these will subgraphs representing crystals molecule_subgraphs = [] for subgraph in all_subgraphs: intersects_boundary = any([d['to_jimage'] != (0, 0, 0) for u, v, d in subgraph.edges(data=True)]) if not intersects_boundary: molecule_subgraphs.append(subgraph) # add specie names to graph to be able to test for isomorphism for subgraph in molecule_subgraphs: for n in subgraph: subgraph.add_node(n, specie=str(supercell_sg.structure[n].specie)) # now define how we test for isomorphism def node_match(n1, n2): return n1['specie'] == n2['specie'] def edge_match(e1, e2): if use_weights: return e1['weight'] == e2['weight'] else: return True # prune duplicate subgraphs unique_subgraphs = [] for subgraph in molecule_subgraphs: already_present = [nx.is_isomorphic(subgraph, g, node_match=node_match, edge_match=edge_match) for g in unique_subgraphs] if not any(already_present): unique_subgraphs.append(subgraph) # get Molecule objects for each subgraph molecules = [] for subgraph in unique_subgraphs: coords = [supercell_sg.structure[n].coords for n in subgraph.nodes()] species = [supercell_sg.structure[n].specie for n in subgraph.nodes()] molecule = Molecule(species, coords) # shift so origin is at center of mass molecule = molecule.get_centered_molecule() molecules.append(molecule) return molecules
# coding: utf-8 from __future__ import division, print_function, unicode_literals, absolute_import from atomate.qchem.workflows.base.FF_then_fragment import get_wf_FF_then_fragment from fireworks.core.launchpad import LaunchPad from pymatgen.core import Molecule mol = Molecule.from_file("BF4-.xyz") wf = get_wf_FF_then_fragment(molecule=mol, max_cores=32) lp = LaunchPad.auto_load() lp.add_wf(wf)