def test_edges_given_PC(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, edges=self.pc_edges, depth=0, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) self.assertEqual(ft.charges,[-1,0,1]) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 295 * 3)
def test_babel_TFSI(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.tfsi, depth=0, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) self.assertEqual(ft.charges,[-1,0,1]) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 468)
def test_babel_TFSI(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.tfsi, depth=0, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) self.assertEqual(ft.charges,[-1,0,1]) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 468)
def test_edges_given_PC(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, edges=self.pc_edges, depth=0, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) self.assertEqual(ft.charges,[-1,0,1]) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 295 * 3)
def test_EC_neg(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.neg_ec, depth=1, check_db=False) ft.run_task({}) self.assertEqual(ft.check_db,False) frags = ft.unique_fragments self.assertEqual(len(frags), 7) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 15)
def test_EC_neg(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.neg_ec, depth=1, check_db=False) ft.run_task({}) self.assertEqual(ft.check_db,False) frags = ft.unique_fragments self.assertEqual(len(frags), 7) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 14)
def test_neg_TFSI_with_additional_charges(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule( molecule=self.neg_tfsi, depth=0, additional_charges=[-2, 1], do_triplets=False, ) ft.run_task({}) self.assertEqual(ft.check_db, False) self.assertEqual(ft.charges, [-1, 0, -2, 1]) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 624) with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule( molecule=self.neg_tfsi, depth=0, additional_charges=[0, 1], do_triplets=False, ) ft.run_task({}) self.assertEqual(ft.check_db, False) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 468)
def test_babel_PC_depth_0_vs_depth_10(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, depth=0, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db, False) depth0frags = ft.unique_fragments self.assertEqual(len(depth0frags), 295) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 295 * 3) with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, depth=10, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db, False) depth10frags = ft.unique_fragments self.assertEqual(len(depth10frags), 63) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 63 * 3) for fragment10 in depth10frags: found = False for fragment0 in depth0frags: if fragment0.isomorphic_to(fragment10): found = True self.assertEqual(found, True)
def test_FragmentFW_not_defaults(self): firework = FragmentFW(molecule=self.act_mol, depth=0, open_rings=False, additional_charges=[2], do_triplets=False, name="fragmenting a thing", qchem_cmd="qchem -slurm", multimode="mpi", max_cores=12, qchem_input_params={"pcm_dielectric": 10.0}, db_file=os.path.join(db_dir, "db.json"), check_db=False) self.assertEqual( firework.tasks[0].as_dict(), FragmentMolecule(molecule=self.act_mol, depth=0, open_rings=False, additional_charges=[2], do_triplets=False, max_cores=12, qchem_input_params={ "pcm_dielectric": 10.0 }, db_file=os.path.join(db_dir, "db.json"), check_db=False).as_dict()) self.assertEqual(firework.parents, []) self.assertEqual(firework.name, "fragmenting a thing")
def test_in_database_with_actual_database(self): db_file=os.path.join(db_dir, "db.json") dir2620=os.path.join(module_dir, "..", "..", "test_files", "2620_complete") mol2620=QCOutput(os.path.join(dir2620,"mol.qout.opt_0")).data["initial_molecule"] parse_firetask = QChemToDb(calc_dir=dir2620, db_file=db_file) parse_firetask.run_task({}) with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.neg_tfsi, db_file=db_file, depth=0, additional_charges=[-2,1], do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,True) self.assertEqual(ft.charges,[-1,0,-2,1]) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 623) self.assertEqual(ft._in_database(mol2620),True) mol2620.set_charge_and_spin(charge=0) self.assertEqual(ft._in_database(mol2620),False)
def test_in_database_and_EC_neg_frag(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: ft = FragmentMolecule(molecule=self.neg_ec, depth=1, qchem_input_params={"pcm_dielectric": 40.0}, check_db=True, db_file=db_file) ft.run_task({}) self.assertEqual(ft.check_db,True) frags = ft.unique_fragments self.assertEqual(len(frags), 7) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 0) mmdb.reset()
def test_in_database_and_EC_neg_frag(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: ft = FragmentMolecule(molecule=self.neg_ec, depth=1, qchem_input_params={"pcm_dielectric": 40.0}, check_db=True, db_file=db_file) ft.run_task({}) self.assertEqual(ft.check_db,True) frags = ft.unique_fragments self.assertEqual(len(frags), 7) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 0) mmdb.reset()
def test_in_database_with_actual_database(self): db_file = os.path.join(db_dir, "db.json") dir2620 = os.path.join(module_dir, "..", "..", "test_files", "2620_complete") mol2620 = QCOutput(os.path.join( dir2620, "mol.qout.opt_0")).data["initial_molecule"] parse_firetask = QChemToDb(calc_dir=dir2620, db_file=db_file) parse_firetask.run_task({}) with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule( molecule=self.neg_tfsi, db_file=db_file, depth=0, additional_charges=[-2, 1], do_triplets=False, ) ft.run_task({}) self.assertEqual(ft.check_db, True) self.assertEqual(ft.charges, [-1, 0, -2, 1]) self.assertEqual(len(FWAction_patch.call_args[1]["additions"]), 623) self.assertEqual(ft._in_database(mol2620), True) mol2620.set_charge_and_spin(charge=0) self.assertEqual(ft._in_database(mol2620), False)
def test_babel_PC_depth_0_vs_depth_10(self): with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, depth=0, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) depth0frags = ft.unique_fragments self.assertEqual(len(depth0frags), 295) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 295*3) with patch("atomate.qchem.firetasks.fragmenter.FWAction" ) as FWAction_patch: ft = FragmentMolecule(molecule=self.pc, depth=10, open_rings=False, do_triplets=False) ft.run_task({}) self.assertEqual(ft.check_db,False) depth10frags = ft.unique_fragments self.assertEqual(len(depth10frags), 63) self.assertEqual( len(FWAction_patch.call_args[1]["additions"]), 63*3) for fragment10 in depth10frags: found = False for fragment0 in depth0frags: if fragment0.isomorphic_to(fragment10): found = True self.assertEqual(found, True)
def test_FragmentFW_defaults(self): firework = FragmentFW(molecule=self.act_mol) self.assertEqual( firework.tasks[0].as_dict(), FragmentMolecule(molecule=self.act_mol, depth=1, open_rings=True, additional_charges=[], do_triplets=True, max_cores=">>max_cores<<", qchem_input_params={}, db_file=None, check_db=True).as_dict()) self.assertEqual(firework.parents, []) self.assertEqual(firework.name, "fragment and optimize")
def test_build_unique_relevant_molecules(self): ft = FragmentMolecule(molecule=self.pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False edges = {(e[0], e[1]): None for e in self.pc_edges} mol_graph = MoleculeGraph.with_edges(self.pc, edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 295 * 3) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_mols.json")) ref_mols = loadfn(os.path.join(module_dir, "pc_mols.json")) self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pos_pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1, 2] ft.do_triplets = False mol_graph = MoleculeGraph.with_edges(self.pos_pc, edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 295 * 4) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pos_pc_mols.json")) ref_mols = loadfn(os.path.join(module_dir, "pos_pc_mols.json")) self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 12 * 3) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_frag1_mols.json")) ref_mols = loadfn(os.path.join(module_dir, "pc_frag1_mols.json")) self.assertEqual(ft.unique_molecules, ref_mols)
def test_build_new_FWs(self): ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False ft.linked = False ft.qchem_input_params = {} pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) unique_frag_dict = mol_graph.build_unique_fragments() unique_frag_list = [] for key in unique_frag_dict: for frag in unique_frag_dict[key]: unique_frag_list.append(frag) ft.unique_fragments = unique_frag_list ft._build_unique_relevant_molecules() ft.all_relevant_docs = list() new_FWs = ft._build_new_FWs() self.assertEqual(len(new_FWs), 36)
def test_in_database_through_build_new_FWs(self): ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False ft.linked = False ft.qchem_input_params = {} pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) unique_frag_dict = mol_graph.build_unique_fragments() unique_frag_list = [] for key in unique_frag_dict: for frag in unique_frag_dict[key]: unique_frag_list.append(frag) ft.unique_fragments = unique_frag_list ft._build_unique_relevant_molecules() docs = loadfn(os.path.join(module_dir, "doc.json")) for doc in docs: doc["input"]["initial_molecule"] = doc["input"][ "initial_molecule"].as_dict() ft.all_relevant_docs = docs new_FWs = ft._build_new_FWs() self.assertEqual(len(new_FWs), 29)
def test_build_unique_relevant_molecules_with_triplets(self): ft = FragmentMolecule(molecule=self.pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = True edges = {(e[0], e[1]): None for e in self.pc_edges} mol_graph = MoleculeGraph.with_edges(self.pc, edges) unique_frag_dict = mol_graph.build_unique_fragments() unique_frag_list = [] for key in unique_frag_dict: for frag in unique_frag_dict[key]: unique_frag_list.append(frag) ft.unique_fragments = unique_frag_list ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 1323) # dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_mols_with_trips.json")) loadfn(os.path.join(module_dir, "pc_mols_with_trips.json")) # self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pos_pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1, 2] ft.do_triplets = True mol_graph = MoleculeGraph.with_edges(self.pos_pc, edges) unique_frag_dict = mol_graph.build_unique_fragments() unique_frag_list = [] for key in unique_frag_dict: for frag in unique_frag_dict[key]: unique_frag_list.append(frag) ft.unique_fragments = unique_frag_list ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 1770) # dumpfn(ft.unique_molecules, os.path.join(module_dir,"pos_pc_mols_with_trips.json")) loadfn(os.path.join(module_dir, "pos_pc_mols_with_trips.json")) # self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = True pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) unique_frag_dict = mol_graph.build_unique_fragments() unique_frag_list = [] for key in unique_frag_dict: for frag in unique_frag_dict[key]: unique_frag_list.append(frag) ft.unique_fragments = unique_frag_list ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 54) # dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_frag1_mols_with_trips.json")) loadfn(os.path.join(module_dir, "pc_frag1_mols_with_trips.json"))
def __init__(self, molecule=None, depth=1, open_rings=True, additional_charges=None, do_triplets=True, name="fragment and optimize", qchem_cmd=">>qchem_cmd<<", multimode=">>multimode<<", max_cores=">>max_cores<<", qchem_input_params=None, db_file=None, check_db=True, parents=None, **kwargs): """ Fragment the given structure and optimize all unique fragments Args: molecule (Molecule): Input molecule. depth (int): Fragmentation depth. Defaults to 1. See fragmenter firetask for more details. open_rings (bool): Whether or not to open any rings encountered during fragmentation. Defaults to True. See fragmenter firetask for more details. additional_charges (list): List of additional charges besides the defaults. See fragmenter firetask for more details. do_triplets (bool): Whether to simulate triplets as well as singlets for molecules with an even number of electrons. Defaults to True. name (str): Name for the Firework. qchem_cmd (str): Command to run QChem. Supports env_chk. multimode (str): Parallelization scheme, either openmp or mpi. Supports env_chk. max_cores (int): Maximum number of cores to parallelize over. Supports env_chk. qchem_input_params (dict): Specify kwargs for instantiating the input set parameters. Basic uses would be to modify the default inputs of the set, such as dft_rung, basis_set, pcm_dielectric, scf_algorithm, or max_scf_cycles. See pymatgen/io/qchem/sets.py for default values of all input parameters. For instance, if a user wanted to use a more advanced DFT functional, include a pcm with a dielectric of 30, and use a larger basis, the user would set qchem_input_params = {"dft_rung": 5, "pcm_dielectric": 30, "basis_set": "6-311++g**"}. However, more advanced customization of the input is also possible through the overwrite_inputs key which allows the user to directly modify the rem, pcm, smd, and solvent dictionaries that QChemDictSet passes to inputs.py to print an actual input file. For instance, if a user wanted to set the sym_ignore flag in the rem section of the input file to true, then they would set qchem_input_params = {"overwrite_inputs": "rem": {"sym_ignore": "true"}}. Of course, overwrite_inputs could be used in conjuction with more typical modifications, as seen in the test_double_FF_opt workflow test. db_file (str): Path to file specifying db credentials to place output parsing. check_db (bool): Whether or not to check the database for equivalent structures before adding new fragment fireworks. Defaults to True. parents ([Firework]): Parents of this particular Firework. **kwargs: Other kwargs that are passed to Firework.__init__. """ qchem_input_params = qchem_input_params or {} additional_charges = additional_charges or [] t = [] t.append( FragmentMolecule(molecule=molecule, depth=depth, open_rings=open_rings, additional_charges=additional_charges, do_triplets=do_triplets, max_cores=max_cores, qchem_input_params=qchem_input_params, db_file=db_file, check_db=check_db)) super(FragmentFW, self).__init__(t, parents=parents, name=name, **kwargs)
def test_build_unique_relevant_molecules_with_triplets(self): ft = FragmentMolecule(molecule=self.pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = True edges = {(e[0], e[1]): None for e in self.pc_edges} mol_graph = MoleculeGraph.with_edges(self.pc, edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 1323) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_mols_with_trips.json")) ref_mols = loadfn(os.path.join(module_dir, "pc_mols_with_trips.json")) self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pos_pc, edges=self.pc_edges, depth=0, opt_steps=1000) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1, 2] ft.do_triplets = True mol_graph = MoleculeGraph.with_edges(self.pos_pc, edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 1770) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pos_pc_mols_with_trips.json")) ref_mols = loadfn(os.path.join(module_dir, "pos_pc_mols_with_trips.json")) self.assertEqual(ft.unique_molecules, ref_mols) ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = True pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() self.assertEqual(len(ft.unique_molecules), 54) #dumpfn(ft.unique_molecules, os.path.join(module_dir,"pc_frag1_mols_with_trips.json")) ref_mols = loadfn(os.path.join(module_dir, "pc_frag1_mols_with_trips.json")) self.assertEqual(ft.unique_molecules, ref_mols)
def test_build_new_FWs(self): ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False ft.qchem_input_params = {} pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() ft.all_relevant_docs = list() new_FWs = ft._build_new_FWs() self.assertEqual(len(new_FWs), 36)
def test_in_database_through_build_new_FWs(self): ft = FragmentMolecule(molecule=self.pc_frag1, edges=self.pc_frag1_edges, depth=0) ft.mol = ft.get("molecule") ft.depth = ft.get("depth") ft.charges = [-1, 0, 1] ft.do_triplets = False ft.qchem_input_params = {} pc_frag1_edges = {(e[0], e[1]): None for e in self.pc_frag1_edges} mol_graph = MoleculeGraph.with_edges(self.pc_frag1, pc_frag1_edges) ft.unique_fragments = mol_graph.build_unique_fragments() ft._build_unique_relevant_molecules() docs = loadfn(os.path.join(module_dir, "doc.json")) for doc in docs: doc["input"]["initial_molecule"] = doc["input"]["initial_molecule"].as_dict() ft.all_relevant_docs = docs new_FWs = ft._build_new_FWs() self.assertEqual(len(new_FWs), 29)