def test_translate_rotate(): reactant = ReactantComplex( Reactant(name='F-', charge=-1, atoms=[Atom('F')]), Reactant(name='alkeneCl', atoms=xyz_file_to_atoms('alkene.xyz'))) assert len(reactant.molecules) == 2 # Initially the geometry is not sensible assert reactant.get_distance(0, 2) < 1.0 # SN2' bond rearrangement bond_rearr = BondRearrangement(forming_bonds=[(0, 1)], breaking_bonds=[(3, 4)]) translate_rotate_reactant(reactant, bond_rearr, shift_factor=1.5) assert len(reactant.atoms) == 10 os.remove('complex.xyz') # The geometry should now be sensible for i in range(1, 10): assert reactant.get_distance(0, i) > 2.0 # Should be closer to the end carbon than the middle assert reactant.get_distance(0, 1) < reactant.get_distance(0, 2)
def test_free_energy_profile(): # Use a spoofed Gaussian09 and XTB install Config.lcode = 'xtb' Config.hcode = 'g09' Config.G09.path = here Config.ts_template_folder_path = os.getcwd() method = get_hmethod() assert method.name == 'g09' rxn = reaction.Reaction(Reactant(name='F-', smiles='[F-]'), Reactant(name='CH3Cl', smiles='ClC'), Product(name='Cl-', smiles='[Cl-]'), Product(name='CH3F', smiles='CF'), name='sn2', solvent_name='water') # Don't run the calculation without a working XTB install if shutil.which('xtb') is None or not shutil.which('xtb').endswith('xtb'): return rxn.calculate_reaction_profile(free_energy=True) # Allow ~0.5 kcal mol-1 either side of the true value dg_ts = rxn.calc_delta_g_ddagger() assert 17 < dg_ts * Constants.ha2kcalmol < 18 dg_r = rxn.calc_delta_g() assert -13.2 < dg_r * Constants.ha2kcalmol < -12.3 dh_ts = rxn.calc_delta_h_ddagger() assert 9.2 < dh_ts * Constants.ha2kcalmol < 10.3 dh_r = rxn.calc_delta_h() assert -13.6 < dh_r * Constants.ha2kcalmol < -12.6 # Should be able to plot an enthalpy profile plot_reaction_profile([rxn], units=KcalMol, name='enthalpy', enthalpy=True) assert os.path.exists('enthalpy_reaction_profile.png') os.remove('enthalpy_reaction_profile.png') # Reset the configuration to the default values Config.hcode = None Config.G09.path = None Config.lcode = None Config.XTB.path = None
def test_detection(): # F- + H2CCHCH2Cl -> FCH2CHCH2 + Cl- reaction = Reaction(Reactant(name='F-', charge=-1, atoms=[Atom('F')]), Reactant(name='alkeneCl', smiles='C=CCCl'), Product(name='alkeneF', smiles='C=CCF'), Product(name='Cl-', charge=-1, atoms=[Atom('Cl')])) assert reaction.type == Substitution reactant, product = get_complexes(reaction) bond_rearrs = get_bond_rearrangs(reactant, product, name='SN2') # autodE should find both direct SN2 and SN2' pathways assert len(bond_rearrs) == 2 os.remove('SN2_bond_rearrangs.txt')
def test_check_solvent(): r = Reactant(name='r', solvent_name='water') p = Product(name='p') with pytest.raises(SolventsDontMatch): _ = reaction.Reaction(r, p) p = Product(name='p', solvent_name='water') reaction_check = reaction.Reaction(r, p) assert reaction_check.solvent.name == 'water'
def test_swap_reacs_prods(): reactant = Reactant(name='r') product = Product(name='p') swapped_reaction = reaction.Reaction(reactant, product) assert swapped_reaction.reacs[0].name == 'r' assert swapped_reaction.prods[0].name == 'p' swapped_reaction.switch_reactants_products() assert swapped_reaction.reacs[0].name == 'p' assert swapped_reaction.prods[0].name == 'r'
def test_single_points(): # Spoof ORCA install Config.ORCA.path = here rxn = reaction.Reaction(Reactant(smiles='O'), Product(smiles='O')) # calculate_single_points should be pretty tolerant.. not raising # exceptions if the energy is already None rxn.calculate_single_points() assert rxn.reacs[0].energy is None overlapping_h2 = Reactant(atoms=[Atom('H'), Atom('H')]) overlapping_h2.energy = -1 rxn.reacs = [overlapping_h2] # Shouldn't calculate a single point for a molecule that is not # 'reasonable' rxn.calculate_single_points() assert rxn.reacs[0].energy == -1 Config.ORCA.path = None
def test_subst(): reactant = Reactant(name='sn2_r', atoms=xyz_file_to_atoms('reactant.xyz')) # SN2' bond rearrangement bond_rearr = BondRearrangement(forming_bonds=[(0, 1)], breaking_bonds=[(3, 4)]) subst_centers = get_substitution_centres(reactant, bond_rearr, shift_factor=1.0) assert len(subst_centers) == 1 # get_substitution_centres should add a dummy atom so the ACX angle is # defined assert len(reactant.atoms) == 11
or minor release """ from autode.reactions import Reaction from autode.species import Reactant, Product from autode.input_output import xyz_file_to_atoms from autode.config import Config from time import time import os here = os.path.dirname(os.path.abspath(__file__)) data_path = os.path.join(here, 'data', 'benchmark') # Leave unchanged for comparable timings Config.n_cores = 8 sn2 = Reaction(Reactant(name='F-', smiles='[F-]'), Reactant(name='CH3Cl', smiles='ClC'), Product(name='Cl-', smiles='[Cl-]'), Product(name='CH3F', smiles='CF'), solvent_name='water', name='sn2') cope = Reaction(Reactant(name='diene1', smiles='C=C[C@H](C)[C@@H](C)C=C'), Product(name='diene2', smiles='C/C=C/CC/C=C/C'), name='cope_rearrangement') da = Reaction(Reactant(name='butadiene', smiles='C=CC=C'), Reactant(name='ethene', smiles='C=C'), Product(name='cyclohexene', smiles='C1C=CCCC1'), name='diels_alder')