def test_graph_no_other_bonds(): reac = Reactant(name='r', atoms=xyz_file_to_atoms('h_shift_correct_ts_mode.xyz')) br = BondRearrangement(breaking_bonds=[(1, 10)], forming_bonds=[(5, 10)]) calc = Calculation(name='h_shift', molecule=reac, method=orca, keywords=orca.keywords.opt_ts, n_cores=1) calc.output.filename = 'h_shift_correct_ts_mode.out' calc.output.file_lines = open('h_shift_correct_ts_mode.out', 'r').readlines() f_ts = Species(name='f_displaced', charge=0, mult=1, atoms=get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=1.0)) b_ts = Species(name='b_displaced', charge=0, mult=1, atoms=get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=-1.0)) assert not imag_mode_generates_other_bonds(ts=reac, f_species=f_ts, b_species=b_ts, bond_rearrangement=br)
def print_imag_vector(self, mode_number=6, name=None): """Print a .xyz file with multiple structures visualising the largest magnitude imaginary mode Keyword Arguments: mode_number (int): Number of the normal mode to visualise, 6 (default) is the lowest frequency vibration i.e. largest magnitude imaginary, if present name (str): """ assert self.optts_calc is not None name = self.name if name is None else name disp = -0.5 for i in range(40): atoms = get_displaced_atoms_along_mode( calc=self.optts_calc, mode_number=int(mode_number), disp_magnitude=disp, atoms=self.atoms) atoms_to_xyz_file(atoms=atoms, filename=f'{name}.xyz', append=True) # Add displacement so the final set of atoms are +0.5 Å displaced # along the mode, then displaced back again sign = 1 if i < 20 else -1 disp += sign * 1.0 / 20.0 return None
def test_correct_imag_mode(): os.chdir(os.path.join(here, 'data')) bond_rearrangement = BondRearrangement(breaking_bonds=[(4, 1), (4, 18)], forming_bonds=[(1, 18)]) g09 = G09() g09.available = True calc = Calculation(name='tmp', molecule=ReactantComplex( Reactant(smiles='CC(C)(C)C1C=CC=C1')), method=g09, keywords=Config.G09.keywords.opt_ts) calc.output.filename = 'correct_ts_mode_g09.log' calc.output.set_lines() f_displaced_atoms = get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=1.0) f_species = Species(name='f_displaced', atoms=f_displaced_atoms, charge=0, mult=1) # Charge & mult are placeholders b_displaced_atoms = get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=-1.0) b_species = Species(name='b_displaced', atoms=b_displaced_atoms, charge=0, mult=1) # With the correct mode no other bonds are made assert not imag_mode_generates_other_bonds( ts=calc.molecule, f_species=f_species, b_species=b_species, bond_rearrangement=bond_rearrangement) calc.output.filename = 'incorrect_ts_mode_g09.log' calc.output.set_lines() assert not imag_mode_has_correct_displacement(calc, bond_rearrangement) os.chdir(here)
def optimise(self, name_ext='optts'): """Optimise this TS to a true TS """ logger.info(f'Optimising {self.name} to a transition state') self._run_opt_ts_calc(method=get_hmethod(), name_ext=name_ext) # A transition state is a first order saddle point i.e. has a single # imaginary frequency if len(self.imaginary_frequencies) == 1: logger.info('Found a TS with a single imaginary frequency') return if len(self.imaginary_frequencies) == 0: logger.error('Transition state optimisation did not return any ' 'imaginary frequencies') return if all([freq > -50 for freq in self.imaginary_frequencies[1:]]): logger.warning('Had small imaginary modes - not displacing along') return # There is more than one imaginary frequency. Will assume that the most # negative is the correct mode.. for disp_magnitude in [1, -1]: logger.info('Displacing along second imaginary mode to try and ' 'remove') dis_name_ext = name_ext + '_dis' if disp_magnitude == 1 else name_ext + '_dis2' atoms, energy, calc = deepcopy(self.atoms), deepcopy( self.energy), deepcopy(self.optts_calc) self.atoms = get_displaced_atoms_along_mode( self.optts_calc, mode_number=7, disp_magnitude=disp_magnitude) self._run_opt_ts_calc(method=get_hmethod(), name_ext=dis_name_ext) if len(self.imaginary_frequencies) == 1: logger.info('Displacement along second imaginary mode ' 'successful. Now have 1 imaginary mode') break self.optts_calc = calc self.atoms = atoms self.energy = energy self.imaginary_frequencies = self.optts_calc.get_imaginary_freqs() return None