Exemplo n.º 1
0
def test_xtb_calculation():

    test_mol = Molecule(name='test_mol',
                        smiles='O=C(C=C1)[C@@](C2NC3C=C2)([H])[C@@]3([H])C1=O')
    calc = Calculation(name='opt', molecule=test_mol, method=method,
                       keywords=Config.XTB.keywords.opt)
    calc.run()

    assert os.path.exists('opt_xtb.xyz') is True
    assert os.path.exists('opt_xtb.out') is True
    assert len(calc.get_final_atoms()) == 22
    assert calc.get_energy() == -36.990267613593
    assert calc.output.exists()
    assert calc.output.file_lines is not None
    assert calc.input.filename == 'opt_xtb.xyz'
    assert calc.output.filename == 'opt_xtb.out'

    with pytest.raises(NotImplementedError):
        calc.optimisation_nearly_converged()
    with pytest.raises(NotImplementedError):
        calc.get_imaginary_freqs()
    with pytest.raises(NotImplementedError):
        calc.get_normal_mode_displacements(4)

    charges = calc.get_atomic_charges()
    assert len(charges) == 22
    assert all(-1.0 < c < 1.0 for c in charges)

    const_opt = Calculation(name='const_opt', molecule=test_mol,
                            method=method,
                            distance_constraints={(0, 1): 1.2539792},
                            cartesian_constraints=[0],
                            keywords=Config.XTB.keywords.opt)

    const_opt.generate_input()
    assert os.path.exists('const_opt_xtb.xyz')
    assert os.path.exists('xcontrol_const_opt_xtb')

    const_opt.clean_up(force=True)
    assert not os.path.exists('xcontrol_const_opt_xtb')

    # Write an empty output file
    open('tmp.out', 'w').close()
    const_opt.output.filename = 'tmp.out'
    const_opt.output.set_lines()

    # cannot get atoms from an empty file
    with pytest.raises(AtomsNotFound):
        _ = const_opt.get_final_atoms()
Exemplo n.º 2
0
def test_gauss_optts_calc():

    os.chdir(os.path.join(here, 'data'))

    calc = Calculation(name='test_ts_reopt_optts',
                       molecule=test_mol,
                       method=method,
                       keywords=optts_keywords,
                       bond_ids_to_add=[(0, 1)])
    calc.run()
    print(calc.input.added_internals)
    assert os.path.exists('test_ts_reopt_optts_g09.com')

    bond_added = False
    for line in open('test_ts_reopt_optts_g09.com', 'r'):
        if 'B' in line and len(line.split()) == 3:
            bond_added = True
            assert line.split()[0] == 'B'
            assert line.split()[1] == '1'
            assert line.split()[2] == '2'

    assert bond_added

    assert calc.get_normal_mode_displacements(mode_number=6) is not None
    assert calc.terminated_normally()
    assert calc.optimisation_converged()
    assert calc.optimisation_nearly_converged() is False
    assert len(calc.get_imaginary_freqs()) == 1

    assert -40.324 < calc.get_free_energy() < -40.322
    assert -40.301 < calc.get_enthalpy() < -40.299

    os.remove('test_ts_reopt_optts_g09.com')
    os.chdir(here)
Exemplo n.º 3
0
def test_orca_optts_calculation():

    methane = SolvatedMolecule(name='methane', smiles='C')
    methane.qm_solvent_atoms = []

    calc = Calculation(name='test_ts_reopt_optts',
                       molecule=methane,
                       method=method,
                       bond_ids_to_add=[(0, 1)],
                       keywords=opt_keywords,
                       other_input_block='%geom\n'
                       'Calc_Hess true\n'
                       'Recalc_Hess 40\n'
                       'Trust 0.2\n'
                       'MaxIter 100\nend')
    calc.run()

    assert os.path.exists('test_ts_reopt_optts_orca.inp')

    assert calc.get_normal_mode_displacements(mode_number=6) is not None
    assert calc.terminated_normally()
    assert calc.optimisation_converged()
    assert calc.optimisation_nearly_converged() is False
    assert len(calc.get_imaginary_freqs()) == 1

    # Gradients should be an n_atom x 3 array
    gradients = calc.get_gradients()
    assert len(gradients) == 5
    assert len(gradients[0]) == 3

    assert -599.437 < calc.get_enthalpy() < -599.436
    assert -599.469 < calc.get_free_energy() < -599.468
Exemplo n.º 4
0
def test_mopac_opt_calculation():

    calc = Calculation(name='opt',
                       molecule=methylchloride,
                       method=method,
                       keywords=Config.MOPAC.keywords.opt)
    calc.run()

    assert os.path.exists('opt_mopac.mop') is True
    assert os.path.exists('opt_mopac.out') is True
    assert len(calc.get_final_atoms()) == 5

    # Actual energy in Hartrees
    energy = Constants.eV2ha * -430.43191
    assert energy - 0.0001 < calc.get_energy() < energy + 0.0001

    assert calc.output.exists()
    assert calc.output.file_lines is not None
    assert calc.input.filename == 'opt_mopac.mop'
    assert calc.output.filename == 'opt_mopac.out'
    assert calc.terminated_normally()
    assert calc.optimisation_converged() is True

    with pytest.raises(CouldNotGetProperty):
        _ = calc.get_gradients()

    with pytest.raises(NotImplementedError):
        _ = calc.optimisation_nearly_converged()
    with pytest.raises(NotImplementedError):
        _ = calc.get_imaginary_freqs()
    with pytest.raises(NotImplementedError):
        _ = calc.get_normal_mode_displacements(4)
Exemplo n.º 5
0
def test_gauss_opt_calc():

    os.chdir(os.path.join(here, 'data'))

    methylchloride = Molecule(name='CH3Cl',
                              smiles='[H]C([H])(Cl)[H]',
                              solvent_name='water')
    calc = Calculation(name='opt',
                       molecule=methylchloride,
                       method=method,
                       keywords=opt_keywords)
    calc.run()

    assert os.path.exists('opt_g09.com')
    assert os.path.exists('opt_g09.log')
    assert len(calc.get_final_atoms()) == 5
    assert os.path.exists('opt_g09.xyz')
    assert calc.get_energy() == -499.729222331
    assert calc.output.exists()
    assert calc.output.file_lines is not None
    assert calc.get_imaginary_freqs() == []

    with pytest.raises(NoNormalModesFound):
        calc.get_normal_mode_displacements(mode_number=1)

    assert calc.input.filename == 'opt_g09.com'
    assert calc.output.filename == 'opt_g09.log'
    assert calc.terminated_normally()
    assert calc.optimisation_converged()
    assert calc.optimisation_nearly_converged() is False

    charges = calc.get_atomic_charges()
    assert len(charges) == methylchloride.n_atoms

    # Should be no very large atomic charges in this molecule
    assert all(-1.0 < c < 1.0 for c in charges)

    gradients = calc.get_gradients()
    assert len(gradients) == methylchloride.n_atoms
    assert len(gradients[0]) == 3

    # Should be no large forces for an optimised molecule
    assert sum(gradients[0]) < 0.1

    os.remove('opt_g09.com')
    os.chdir(here)
Exemplo n.º 6
0
def test_orca_opt_calculation():

    os.chdir(os.path.join(here, 'data'))

    methylchloride = Molecule(name='CH3Cl',
                              smiles='[H]C([H])(Cl)[H]',
                              solvent_name='water')

    calc = Calculation(name='opt', molecule=methylchloride, method=method,
                       keywords=opt_keywords)
    calc.run()

    assert os.path.exists('opt_orca.inp') is True
    assert os.path.exists('opt_orca.out') is True
    assert len(calc.get_final_atoms()) == 5
    assert -499.735 < calc.get_energy() < -499.730
    assert calc.output.exists()
    assert calc.output.file_lines is not None
    assert calc.get_imaginary_freqs() == []
    assert calc.input.filename == 'opt_orca.inp'
    assert calc.output.filename == 'opt_orca.out'
    assert calc.terminated_normally()

    assert calc.optimisation_converged()

    assert calc.optimisation_nearly_converged() is False

    with pytest.raises(NoNormalModesFound):
        calc.get_normal_mode_displacements(mode_number=0)

    # Should have a partial atomic charge for every atom
    charges = calc.get_atomic_charges()
    assert len(charges) == 5
    assert type(charges[0]) == float
    assert -1.0 < charges[0] < 1.0

    calc = Calculation(name='opt', molecule=methylchloride, method=method,
                       keywords=opt_keywords)

    # If the calculation is not run with calc.run() then there should be no
    # input and the calc should raise that there is no input
    with pytest.raises(NoInputError):
        execute_calc(calc)

    os.remove('opt_orca.inp')
    os.chdir(here)
Exemplo n.º 7
0
def test_xtb_calculation():

    os.chdir(os.path.join(here, 'data'))
    XTB.available = True

    test_mol = Molecule(name='test_mol',
                        smiles='O=C(C=C1)[C@@](C2NC3C=C2)([H])[C@@]3([H])C1=O')
    calc = Calculation(name='opt', molecule=test_mol, method=method,
                       keywords=Config.XTB.keywords.opt)
    calc.run()

    assert os.path.exists('opt_xtb.xyz') is True
    assert os.path.exists('opt_xtb.out') is True
    assert len(calc.get_final_atoms()) == 22
    assert calc.get_energy() == -36.990267613593
    assert calc.output.exists()
    assert calc.output.file_lines is not None
    assert calc.input.filename == 'opt_xtb.xyz'
    assert calc.output.filename == 'opt_xtb.out'

    with pytest.raises(NotImplementedError):
        calc.optimisation_nearly_converged()
    with pytest.raises(NotImplementedError):
        calc.get_imaginary_freqs()
    with pytest.raises(NotImplementedError):
        calc.get_normal_mode_displacements(4)

    charges = calc.get_atomic_charges()
    assert len(charges) == 22
    assert all(-1.0 < c < 1.0 for c in charges)

    const_opt = Calculation(name='const_opt', molecule=test_mol,
                            method=method,
                            distance_constraints={(0, 1): 1.2539792},
                            cartesian_constraints=[0],
                            keywords=Config.XTB.keywords.opt)

    const_opt.generate_input()
    assert os.path.exists('xcontrol_const_opt_xtb')

    os.remove('const_opt_xtb.xyz')
    os.remove('xcontrol_const_opt_xtb')
    os.remove('opt_xtb.xyz')
    os.chdir(here)
Exemplo n.º 8
0
class TSbase(Species):
    def _init_graph(self):
        """Set the molecular graph for this TS object from the reactant"""
        logger.warning(f'Setting the graph of {self.name} from reactants')

        self.graph = self.reactant.graph.copy()
        return None

    def could_have_correct_imag_mode(self, method=None, threshold=-45):
        """
        Determine if a point on the PES could have the correct imaginary mode. This must have

        (0) An imaginary frequency      (quoted as negative in most EST codes)
        (1) The most negative(/imaginary) is more negative that a threshold

        Keywords Arguments:
            method (autode.wrappers.base.ElectronicStructureMethod):
            threshold (float):

        Returns:
            (bool):
        """
        # By default the high level method is used to check imaginary modes
        if method is None:
            method = get_hmethod()

        if self.calc is None:
            logger.info('Calculating the hessian..')
            self.calc = Calculation(name=self.name + '_hess',
                                    molecule=self,
                                    method=method,
                                    keywords=method.keywords.hess,
                                    n_cores=Config.n_cores)
            self.calc.run()

        imag_freqs = self.calc.get_imaginary_freqs()

        if len(imag_freqs) == 0:
            logger.warning('Hessian had no imaginary modes')
            return False

        if len(imag_freqs) > 1:
            logger.warning(f'Hessian had {len(imag_freqs)} imaginary modes')

        if imag_freqs[0] > threshold:
            logger.warning('Imaginary modes were too small to be significant')
            return False

        try:
            _ = self.calc.get_normal_mode_displacements(mode_number=6)

        except NoNormalModesFound:
            logger.warning('No normal modes could be found cannot determine if'
                           'this the correct imaginary mode is found')
            return None

        # Check very conservatively for the correct displacement
        if not imag_mode_has_correct_displacement(self.calc,
                                                  self.bond_rearrangement,
                                                  delta_threshold=0.05,
                                                  req_all=False):
            logger.warning('Species does not have the correct imaginary mode')
            return False

        logger.info('Species could have the correct imaginary mode')
        return True

    def has_correct_imag_mode(self, calc=None, method=None):
        """Check that the imaginary mode is 'correct' set the calculation
        (hessian or optts)"""
        self.calc = calc if calc is not None else self.calc

        # By default the high level method is used to check imaginary modes
        if method is None:
            method = get_hmethod()

        # Run a fast check on  whether it's likely the mode is correct
        if not self.could_have_correct_imag_mode(method=method):
            return False

        if imag_mode_has_correct_displacement(self.calc,
                                              self.bond_rearrangement):
            logger.info('Displacement of the active atoms in the imaginary '
                        'mode bond forms and breaks the correct bonds')
            return True

        # Perform displacements over the imaginary mode to ensure the mode
        # connects reactants and products
        if imag_mode_links_reactant_products(self.calc,
                                             self.reactant,
                                             self.product,
                                             method=method):
            logger.info('Imaginary mode does link reactants and products')
            return True

        logger.warning('Species does *not* have the correct imaginary mode')
        return False

    def __init__(self, atoms, reactant, product, name='ts_guess'):

        super().__init__(name=name,
                         atoms=atoms,
                         charge=reactant.charge,
                         mult=reactant.mult)
        self.solvent = reactant.solvent
        self.atoms = atoms

        self.reactant = reactant
        self.product = product

        self.calc = None
        self.bond_rearrangement = None

        self._init_graph()