def test_get_ts_guess_1dscan(): os.chdir(os.path.join(here, 'data')) fbond = FormingBond(atom_indexes=(1, 2), species=reac) fbond.final_dist = 0.7 ts_guess = get_ts_guess_1d(name='H+H2_H2+H', reactant=reac, product=prod, bond=fbond, method=orca, keywords=opt_keywords, dr=0.06) assert ts_guess.n_atoms == 3 # Peak in the PES is at r = 0.85 Å assert 0.84 < ts_guess.get_distance(1, 2) < 0.86 assert os.path.exists('H+H2_H2+H.png') for filename in os.listdir(os.getcwd()): if filename.endswith(('.inp', '.png')): os.remove(filename) os.chdir(here)
def test_get_ts_guess_1dscan(): fbond = FormingBond(atom_indexes=(1, 2), species=reac) fbond.final_dist = 0.7 ts_guess = get_ts_guess_1d(name='H+H2_H2+H', reactant=reac, product=prod, bond=fbond, method=orca, keywords=opt_keywords, dr=0.06) assert ts_guess.n_atoms == 3 # Peak in the PES is at r = 0.85 Å assert 0.84 < ts_guess.get_distance(1, 2) < 0.86 assert os.path.exists('H+H2_H2+H.png') os.remove('H+H2_H2+H.png')
def test_removing_active_bonds(): filepath = os.path.join(here, 'data', 'neb', 'co_complex.xyz') mol = Molecule(name='co_complex', atoms=xyz_file_to_atoms(filepath)) bbond = BreakingBond(atom_indexes=(1, 2), species=mol) fbond = FormingBond(atom_indexes=(3, 1), species=mol) bonds = neb.active_bonds_no_rings(mol, fbonds=[fbond], bbonds=[bbond]) # Should remove the breaking bond as it forms a ring with an already # present atom pair assert len(bonds) == 1 assert isinstance(bonds[0], FormingBond) # Also check that the number of images to generate are somewhat reasonable n_images = neb.calc_n_images(fbonds=[fbond], bbonds=[bbond], average_spacing=0.1) assert 0 < n_images < 20
def test_bonds(): h1 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=0.0) h2 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=0.7) h3 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=1.7) hydrogen = Reactant(name='H2', atoms=[h1, h2], charge=0, mult=1) h = Reactant(name='H', atoms=[h3], charge=0, mult=2) reac = ReactantComplex(hydrogen, h) prod_h2 = Product(name='H2', atoms=[h1, h2], charge=0, mult=1) prod_h = Product(name='H', atoms=[h3], charge=0, mult=2) fbond = FormingBond(atom_indexes=(1, 2), species=reac) bbond = BreakingBond(atom_indexes=(0, 1), species=reac, reaction=Reaction(hydrogen, h, prod_h2, prod_h)) assert fbond.curr_dist == 1.0 assert 0.6 < fbond.final_dist < 0.8 assert 2.0 < bbond.final_dist < 2.5 assert bbond.curr_dist == 0.7
def test_get_ts_guess_2dscan(): ch3cl_f = Reactant(name='CH3Cl_F-', charge=-1, mult=1, atoms=[ Atom('F', -4.14292, -0.24015, 0.07872), Atom('Cl', 1.63463, 0.09787, -0.02490), Atom('C', -0.14523, -0.00817, 0.00208), Atom('H', -0.47498, -0.59594, -0.86199), Atom('H', -0.45432, -0.49900, 0.93234), Atom('H', -0.56010, 1.00533, -0.04754) ]) ch3f_cl = Product(name='CH3Cl_F-', charge=-1, mult=1, atoms=[ Atom('F', 1.63463, 0.09787, -0.02490), Atom('Cl', -4.14292, -0.24015, 0.07872), Atom('C', -0.14523, -0.00817, 0.00208), Atom('H', -0.47498, -0.59594, -0.86199), Atom('H', -0.45432, -0.49900, 0.93234), Atom('H', -0.56010, 1.00533, -0.04754) ]) # H H # F- C--Cl -> F--C Cl- # H H H H pes = pes_2d.PES2d(reactant=ReactantComplex(ch3cl_f), product=ProductComplex(ch3f_cl), r1s=np.linspace(4.0, 1.5, 9), r1_idxs=(0, 2), r2s=np.linspace(1.78, 4.0, 8), r2_idxs=(1, 2)) pes.calculate(name='SN2_PES', method=xtb, keywords=xtb.keywords.low_opt) assert pes.species[0, 1] is not None assert -13.13 < pes.species[0, 1].energy < -13.11 assert pes.species.shape == (9, 8) assert pes.rs.shape == (9, 8) assert type(pes.rs[0, 1]) == tuple assert pes.rs[1, 1] == (np.linspace(4.0, 1.5, 9)[1], np.linspace(1.78, 4.0, 8)[1]) # Fitting the surface with a 2D polynomial up to order 3 in r1 and r2 i.e. # r1^3r2^3 pes.fit(polynomial_order=3) assert pes.coeff_mat is not None assert pes.coeff_mat.shape == (4, 4) # Includes r1^0 etc. pes.print_plot(name='pes_plot') assert os.path.exists('pes_plot.png') os.remove('pes_plot.png') # Products should be made on this surface assert pes.products_made() # Get the TS guess from this surface calling all the above functions reactant = ReactantComplex(ch3cl_f) fbond = FormingBond(atom_indexes=(0, 2), species=reactant) fbond.final_dist = 1.5 bbond = BreakingBond(atom_indexes=(1, 2), species=reactant, reaction=Reaction(ch3cl_f, ch3f_cl)) bbond.final_dist = 4.0 ts_guess = pes_2d.get_ts_guess_2d(reactant=reactant, product=ProductComplex(ch3f_cl), bond1=fbond, bond2=bbond, polynomial_order=3, name='SN2_PES', method=xtb, keywords=xtb.keywords.low_opt, dr=0.3) assert ts_guess is not None assert ts_guess.n_atoms == 6 assert ts_guess.energy is None assert 1.9 < ts_guess.get_distance(0, 2) < 2.1 assert 1.9 < ts_guess.get_distance(1, 2) < 2.0
def get_ts_guess_function_and_params(reaction, bond_rearr): """Get the functions (1dscan or 2dscan) and parameters required for the function for a TS scan Arguments: reaction (autode.reaction.Reaction): bond_rearr (autode.bond_rearrangement.BondRearrangement): Returns: (list): updated funcs and params list """ name = str(reaction) scan_name = name r, p = reaction.reactant, reaction.product lmethod, hmethod = get_lmethod(), get_hmethod() # Bonds with initial and final distances bbonds = [BreakingBond(pair, r, reaction) for pair in bond_rearr.bbonds] scan_name += "_".join(str(bb) for bb in bbonds) fbonds = [FormingBond(pair, r) for pair in bond_rearr.fbonds] scan_name += "_".join(str(fb) for fb in fbonds) # Ideally use a transition state template, then only a single constrained # optimisation needs to be run... yield get_template_ts_guess, (r, p, bond_rearr, f'{name}_template_{bond_rearr}', hmethod) # Otherwise try a nudged elastic band calculation, don't use the low level # method if there are any metals.. if not any(atom.label in metals for atom in r.atoms): yield get_ts_guess_neb, (r, p, lmethod, fbonds, bbonds, f'{name}_ll_neb_{bond_rearr}') # Always attempt a high-level NEB yield get_ts_guess_neb, (r, p, hmethod, fbonds, bbonds, f'{name}_hl_neb_{bond_rearr}') # Otherwise run 1D or 2D potential energy surface scans to generate a # transition state guess cheap -> most expensive if len(bbonds) == 1 and len(fbonds) == 1 and reaction.type in (Substitution, Elimination): yield get_ts_guess_2d, (r, p, fbonds[0], bbonds[0], f'{scan_name}_ll2d', lmethod, lmethod.keywords.low_opt) yield get_ts_guess_1d, (r, p, bbonds[0], f'{scan_name}_hl1d_bbond', hmethod, hmethod.keywords.low_opt) yield get_ts_guess_1d, (r, p, bbonds[0], f'{scan_name}_hl1d_alt_bbond', hmethod, hmethod.keywords.opt) if len(bbonds) > 0 and len(fbonds) == 1: yield get_ts_guess_1d, (r, p, fbonds[0], f'{scan_name}_hl1d_fbond', hmethod, hmethod.keywords.low_opt) yield get_ts_guess_1d, (r, p, fbonds[0], f'{scan_name}_hl1d_alt_fbond', hmethod, hmethod.keywords.opt) if len(bbonds) >= 1 and len(fbonds) >= 1: for fbond in fbonds: for bbond in bbonds: yield get_ts_guess_2d, (r, p, fbond, bbond, f'{scan_name}_ll2d', lmethod, lmethod.keywords.low_opt) yield get_ts_guess_2d, (r, p, fbond, bbond, f'{scan_name}_hl2d', hmethod, hmethod.keywords.low_opt) if len(bbonds) == 1 and len(fbonds) == 0: yield get_ts_guess_1d, (r, p, bbonds[0], f'{scan_name}_hl1d', hmethod, hmethod.keywords.low_opt) yield get_ts_guess_1d, (r, p, bbonds[0], f'{scan_name}_hl1d_alt', hmethod, hmethod.keywords.opt) if len(fbonds) == 2: yield get_ts_guess_2d, (r, p, fbonds[0], fbonds[1], f'{scan_name}_ll2d_fbonds', lmethod, lmethod.keywords.low_opt) yield get_ts_guess_2d, (r, p, fbonds[0], fbonds[1], f'{scan_name}_hl2d_fbonds', hmethod, hmethod.keywords.low_opt) if len(bbonds) == 2: yield get_ts_guess_2d, (r, p, bbonds[0], bbonds[1], f'{scan_name}_ll2d_bbonds', lmethod, lmethod.keywords.low_opt) yield get_ts_guess_2d, (r, p, bbonds[0], bbonds[1], f'{scan_name}_hl2d_bbonds', hmethod, hmethod.keywords.low_opt) return None