Пример #1
0
 def characteriseTSinternal(self, mol):
     os.chdir((self.workingDir + '/Raw/' + self.procNum))
     if (self.lowMeth == 'nwchem'):
         mol = tl.setCalc(mol, self.lowString, 'nwchem2', self.lowLev)
         self.Reac.get_forces()
     else:
         mol = tl.setCalc(mol, self.lowString, self.lowMeth, self.lowLev)
     vib = Vibrations(mol)
     vib.clean()
     vib.run()
     viblist = vib.get_frequencies()
     print("getting vibs")
     TSFreqs, zpe = tl.getVibString(viblist, False, True)
     print("vibs done " + str(zpe))
     imaginaryFreq = tl.getImageFreq(viblist)
     vib.clean()
     os.chdir((self.workingDir))
     # Finally get single point energy
     mol = tl.setCalc(mol, self.singleString, self.singleMeth,
                      self.singleLev)
     print("Getting single point energy for TS = " +
           str(mol.get_potential_energy()) + "zpe = " + str(zpe) +
           "reactant energy = " + str(self.reactantEnergy))
     energy = mol.get_potential_energy() + zpe
     return TSFreqs, imaginaryFreq, zpe, energy
Пример #2
0
def neural_hessian_ase(ase_atoms):
    print("Calculating Numerical Hessian using ASE")
    vib = Vibrations(ase_atoms, delta=0.05)
    vib.run()
    vib.summary()
    hessian = np.array(vib.H) * (kcal/mol) * Bohr**2
    vib.clean()
    
    return hessian
Пример #3
0
 def characteriseFreqInternal(self, mol):
     os.chdir((self.workingDir + '/' + '/Raw/' + self.procNum))
     vib = Vibrations(mol)
     vib.clean()
     vib.run()
     viblist = vib.get_frequencies()
     freqs, zpe = tl.getVibString(viblist, False, False)
     vib.clean()
     os.chdir((self.workingDir))
     return freqs, zpe
Пример #4
0
    def get_thermo_correction(
            self,
            coords: simtk.unit.quantity.Quantity) -> unit.quantity.Quantity:
        """
        Returns the thermochemistry correction. This calls: https://wiki.fysik.dtu.dk/ase/ase/thermochemistry/thermochemistry.html
        and uses the Ideal gas rigid rotor harmonic oscillator approximation to calculate the Gibbs free energy correction that
        needs to be added to the single point energy to obtain the Gibb's free energy
        coords: [K][3]

        Raises:
            verror: if imaginary frequencies are detected a ValueError is raised

        Returns:
            float -- temperature correct [kT]
        """
        if not (len(coords.shape) == 3 and coords.shape[2] == 3
                and coords.shape[0] == 1):
            raise RuntimeError(
                f"Something is wrong with the shape of the provided coordinates: {coords.shape}. Only x.shape[0] == 1 is possible."
            )

        ase_mol = copy.deepcopy(self.ase_mol)
        for atom, c in zip(ase_mol, coords[0]):
            atom.x = c[0].value_in_unit(unit.angstrom)
            atom.y = c[1].value_in_unit(unit.angstrom)
            atom.z = c[2].value_in_unit(unit.angstrom)

        calculator = self.model.ase()
        ase_mol.set_calculator(calculator)

        vib = Vibrations(ase_mol, name=f"/tmp/vib{random.randint(1,10000000)}")
        vib.run()
        vib_energies = vib.get_energies()
        thermo = IdealGasThermo(
            vib_energies=vib_energies,
            atoms=ase_mol,
            geometry="nonlinear",
            symmetrynumber=1,
            spin=0,
        )

        try:
            G = thermo.get_gibbs_energy(
                temperature=temperature.value_in_unit(unit.kelvin),
                pressure=pressure.value_in_unit(unit.pascal),
            )
        except ValueError as verror:
            logger.critical(verror)
            vib.clean()
            raise verror
        # removes the vib tmp files
        vib.clean()
        return (
            G * eV_to_kJ_mol
        ) * unit.kilojoule_per_mole  # eV * conversion_factor(eV to kJ/mol)
Пример #5
0
def test_vib():
    import os
    from ase import Atoms
    from ase.calculators.emt import EMT
    from ase.optimize import QuasiNewton
    from ase.vibrations import Vibrations
    from ase.thermochemistry import IdealGasThermo

    n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT())
    QuasiNewton(n2).run(fmax=0.01)
    vib = Vibrations(n2)
    vib.run()
    freqs = vib.get_frequencies()
    print(freqs)
    vib.summary()
    print(vib.get_mode(-1))
    vib.write_mode(n=None, nimages=20)
    vib_energies = vib.get_energies()

    for image in vib.iterimages():
        assert len(image) == 2

    thermo = IdealGasThermo(vib_energies=vib_energies,
                            geometry='linear',
                            atoms=n2,
                            symmetrynumber=2,
                            spin=0)
    thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.)

    assert vib.clean(empty_files=True) == 0
    assert vib.clean() == 13
    assert len(list(vib.iterimages())) == 13

    d = dict(vib.iterdisplace(inplace=False))

    for name, atoms in vib.iterdisplace(inplace=True):
        assert d[name] == atoms

    vib = Vibrations(n2)
    vib.run()
    assert vib.combine() == 13
    assert (freqs == vib.get_frequencies()).all()

    vib = Vibrations(n2)
    assert vib.split() == 1
    assert (freqs == vib.get_frequencies()).all()

    assert vib.combine() == 13
    # Read the data from other working directory
    dirname = os.path.basename(os.getcwd())
    os.chdir('..')  # Change working directory
    vib = Vibrations(n2, name=os.path.join(dirname, 'vib'))
    assert (freqs == vib.get_frequencies()).all()
    assert vib.clean() == 1
Пример #6
0
 def get_modes(self,atm,freqname="vib."):
     for f in [f for f in os.listdir(".") if freqname in f and  '.pckl' in f]:
         os.remove(f)
     new_target = open(os.devnull, "w")
     old_target, sys.stdout = sys.stdout, new_target
     atm.set_calculator(ANIENS(self.ens))
     vib = Vibrations(atm, nfree=2, name=freqname)
     vib.run()
     freq = vib.get_frequencies()
     modes = np.stack(vib.get_mode(i) for i in range(freq.size))
     vib.clean()
     sys.stdout = old_target
     return modes
Пример #7
0
    def test_pickle_manipulation(self, n2_emt):
        atoms = n2_emt
        vib = Vibrations(atoms, name='interrupt')
        vib.run()

        disp_file = 'interrupt.1x-.pckl'
        comb_file = 'interrupt.all.pckl'
        assert os.path.isfile(disp_file)
        assert not os.path.isfile(comb_file)

        with pytest.raises(RuntimeError):
            vib.split()

        # Build a combined file
        assert vib.combine() == 13

        # Individual displacements should be gone, combination should exist
        assert not os.path.isfile(disp_file)
        assert os.path.isfile(comb_file)

        # Not allowed to run after data has been combined
        with pytest.raises(RuntimeError):
            vib.run()
            # But reading is allowed
            vib.read()

        # Splitting should fail if any split file already exists
        with open(disp_file, 'w') as f:
            f.write("hello")
        with pytest.raises(RuntimeError):
            vib.split()
        os.remove(disp_file)

        # Now split() for real: replace .all.pckl file with displacements
        vib.split()
        assert os.path.isfile(disp_file)
        assert not os.path.isfile(comb_file)

        # Not allowed to clobber existing combined file
        with open(comb_file, 'w') as f:
            f.write("Hello")
        with pytest.raises(RuntimeError):
            vib.combine()
        os.remove(comb_file)

        # Combining data also fails if some data is missing
        os.remove('interrupt.1x-.pckl')
        with pytest.raises(RuntimeError):
            vib.combine()

        vib.clean()
Пример #8
0
    def test_vibrations_methods(self, testdir, random_dimer):
        vib = Vibrations(random_dimer)
        vib.run()
        vib_energies = vib.get_energies()

        for image in vib.iterimages():
            assert len(image) == 2

        thermo = IdealGasThermo(vib_energies=vib_energies,
                                geometry='linear',
                                atoms=vib.atoms,
                                symmetrynumber=2,
                                spin=0)
        thermo.get_gibbs_energy(temperature=298.15,
                                pressure=2 * 101325.,
                                verbose=False)

        with open(self.logfile, 'w') as fd:
            vib.summary(log=fd)

        with open(self.logfile, 'rt') as fd:
            log_txt = fd.read()
            assert log_txt == '\n'.join(
                VibrationsData._tabulate_from_energies(vib_energies)) + '\n'

        last_mode = vib.get_mode(-1)
        scale = 0.5
        assert_array_almost_equal(
            vib.show_as_force(-1, scale=scale, show=False).get_forces(),
            last_mode * 3 * len(vib.atoms) * scale)

        vib.write_mode(n=3, nimages=5)
        for i in range(3):
            assert not Path('vib.{}.traj'.format(i)).is_file()
        mode_traj = ase.io.read('vib.3.traj', index=':')
        assert len(mode_traj) == 5

        assert_array_almost_equal(mode_traj[0].get_all_distances(),
                                  random_dimer.get_all_distances())
        with pytest.raises(AssertionError):
            assert_array_almost_equal(mode_traj[4].get_all_distances(),
                                      random_dimer.get_all_distances())

        assert vib.clean(empty_files=True) == 0
        assert vib.clean() == 13
        assert len(list(vib.iterimages())) == 13

        d = dict(vib.iterdisplace(inplace=False))

        for name, image in vib.iterdisplace(inplace=True):
            assert d[name] == random_dimer
Пример #9
0
    def test_vibrations_restart_dir(self, testdir, random_dimer):
        vib = Vibrations(random_dimer)
        vib.run()
        freqs = vib.get_frequencies()
        assert freqs is not None

        # write/read the data from another working directory
        atoms = random_dimer.copy()  # This copy() removes the Calculator

        with ase.utils.workdir('run_from_here', mkdir=True):
            vib = Vibrations(atoms, name=str(Path.cwd().parent / 'vib'))
            assert_array_almost_equal(freqs, vib.get_frequencies())
            assert vib.clean() == 13
Пример #10
0
 def characteriseMinInternal(self, mol):
     os.chdir((self.workingDir + '/' + '/Raw/' + self.procNum))
     if (self.lowMeth == 'nwchem'):
         mol = tl.setCalc(mol, self.lowString, 'nwchem2', self.lowLev)
         self.Reac.get_forces()
     else:
         mol = tl.setCalc(mol, self.lowString, self.lowMeth, self.lowLev)
     min = BFGS(mol)
     min.run(fmax=0.05, steps=50)
     vib = Vibrations(mol)
     vib.clean()
     vib.run()
     viblist = vib.get_frequencies()
     Freqs, zpe = tl.getVibString(viblist, False, False)
     vib.clean()
     os.chdir((self.workingDir))
     # Finally get single point energy
     mol = tl.setCalc(mol, self.singleString, self.singleMeth,
                      self.singleLev)
     print("Getting single point energy for TS = " +
           str(mol.get_potential_energy()) + "zpe = " + str(zpe) +
           "reactant energy = " + str(self.reactantEnergy))
     energy = mol.get_potential_energy() + zpe
     return Freqs, energy, mol
Пример #11
0
slab = fcc111('Al', size=(2, 2, 2), vacuum=3.0)
CH3 = molecule('CH3')
add_adsorbate(slab, CH3, 2.5, 'ontop')

constraint = FixAtoms(mask=[a.symbol == 'Al' for a in slab])
slab.set_constraint(constraint)
slab.set_calculator(EMT())

dyn = QuasiNewton(slab, logfile='/dev/null')
dyn.run(fmax=0.05)

vib = Vibrations(slab, indices=[8, 9, 10, 11])
vib.run()
vib.summary(log='/dev/null')
vib.clean()

AM = AnharmonicModes(vibrations_object=vib)
rot_mode = AM.define_rotation(
    basepos=[0., 0., -1.],
    branch=[9, 10, 11],
    symnumber=3)

AM.run()
AM.summary(log='/dev/null')
AM.clean()

# print(AM.get_ZPE(), AM.get_entropic_energy())
assert abs(AM.get_ZPE() - 0.388) < 1e-3, AM.get_ZPE()
assert abs(AM.get_entropic_energy() - (0.091)) < 1e-3, (
    AM.get_entropic_energy())
Пример #12
0
slab = fcc111('Au', size=(2, 2, 2), vacuum=4.0)
H = molecule('H')
add_adsorbate(slab, H, 3.0, 'ontop')

constraint = FixAtoms(mask=[a.symbol == 'Au' for a in slab])
slab.set_constraint(constraint)

slab.set_calculator(EMT())

QuasiNewton(slab).run(fmax=0.001)

vib = Vibrations(slab, indices=[8])
vib.run()
vib.summary()
vib.clean()

AM = AnharmonicModes(vibrations_object=vib, settings={
    'plot_mode': True,
})

for i in range(len(vib.hnu)):
    AM.define_vibration(mode_number=-1)

AM.inspect_anmodes()
AM.run()
AM.summary()
AM.clean()

print(AM.get_ZPE(), AM.get_entropic_energy())
# assert abs(AM.get_ZPE() - 0.243) < 1e-3, AM.get_ZPE()
Пример #13
0
from ase.vibrations import Vibrations
from ase.thermochemistry import IdealGasThermo

n2 = Atoms('N2',
           positions=[(0, 0, 0), (0, 0, 1.1)],
           calculator=EMT())
QuasiNewton(n2).run(fmax=0.01)
vib = Vibrations(n2)
vib.run()
print(vib.get_frequencies())
vib.summary()
print(vib.get_mode(-1))
vib.write_mode(n=None, nimages=20)
vib_energies = vib.get_energies()

for image in vib.iterimages():
    assert len(image) == 2

thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear',
                        atoms=n2, symmetrynumber=2, spin=0)
thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.)

assert vib.clean(empty_files=True) == 0
assert vib.clean() == 13
assert len(list(vib.iterimages())) == 13

d = dict(vib.iterdisplace(inplace=False))

for name, atoms in vib.iterdisplace(inplace=True):
    assert d[name] == atoms
Пример #14
0
    def test_vibrations(self, testdir, n2_emt, n2_optimized):
        atoms = n2_emt
        vib = Vibrations(atoms)
        vib.run()
        freqs = vib.get_frequencies()
        vib.write_mode(n=None, nimages=5)
        vib.write_jmol()
        vib_energies = vib.get_energies()

        for image in vib.iterimages():
            assert len(image) == 2

        thermo = IdealGasThermo(vib_energies=vib_energies,
                                geometry='linear',
                                atoms=atoms,
                                symmetrynumber=2,
                                spin=0)
        thermo.get_gibbs_energy(temperature=298.15,
                                pressure=2 * 101325.,
                                verbose=False)

        vib.summary(log=self.logfile)
        with open(self.logfile, 'rt') as f:
            log_txt = f.read()
            assert log_txt == vibrations_n2_log

        mode1 = vib.get_mode(-1)
        assert_array_almost_equal(mode1,
                                  [[0., 0., -0.188935], [0., 0., 0.188935]])

        assert_array_almost_equal(
            vib.show_as_force(-1, show=False).get_forces(),
            [[0., 0., -2.26722e-1], [0., 0., 2.26722e-1]])

        for i in range(3):
            assert not os.path.isfile('vib.{}.traj'.format(i))
        mode_traj = ase.io.read('vib.3.traj', index=':')
        assert len(mode_traj) == 5
        assert_array_almost_equal(mode_traj[0].get_all_distances(),
                                  atoms.get_all_distances())
        with pytest.raises(AssertionError):
            assert_array_almost_equal(mode_traj[4].get_all_distances(),
                                      atoms.get_all_distances())

        with open('vib.xyz', 'rt') as f:
            jmol_txt = f.read()
            assert jmol_txt == jmol_txt_ref

        assert vib.clean(empty_files=True) == 0
        assert vib.clean() == 13
        assert len(list(vib.iterimages())) == 13

        d = dict(vib.iterdisplace(inplace=False))

        for name, image in vib.iterdisplace(inplace=True):
            assert d[name] == atoms

        atoms2 = n2_emt
        vib2 = Vibrations(atoms2)
        vib2.run()

        assert_array_almost_equal(freqs, vib.get_frequencies())

        # write/read the data from another working directory
        atoms3 = n2_optimized.copy()  # No calculator needed!

        workdir = os.path.abspath(os.path.curdir)
        try:
            os.mkdir('run_from_here')
            os.chdir('run_from_here')
            vib = Vibrations(atoms3, name=os.path.join(os.pardir, 'vib'))
            assert_array_almost_equal(freqs, vib.get_frequencies())
            assert vib.clean() == 13
        finally:
            os.chdir(workdir)
            if os.path.isdir('run_from_here'):
                os.rmdir('run_from_here')
Пример #15
0
    def vibrate(self, atoms: Atoms, indices: list, read_only=False):
        '''

        This method uses ase.vibrations module, see more for info.
        User provides the FHI-aims parameters, the Atoms object and list
        of indices of atoms to be vibrated. Variables related to FHI-aims are governed by the React object.
        Calculation folders are generated automatically and a sockets calculator is used for efficiency.

        Work in progress

        Args:
            atoms: Atoms object
            indices: list
                List of indices of atoms that require vibrations
            read_only: bool
                Flag for postprocessing - if True, the method only extracts information from existing files,
                no calculations are performed

        Returns:
            Zero-Point Energy: float
        '''
        '''Retrieve common properties'''
        basis_set = self.basis_set
        hpc = self.hpc
        params = self.params
        parent_dir = os.getcwd()
        dimensions = sum(atoms.pbc)

        if not self.filename:
            '''develop a naming scheme based on chemical formula'''
            self.filename = atoms.get_chemical_formula()

        vib_dir = parent_dir + "/VibData_" + self.filename + "/Vibs"
        print(vib_dir)

        vib = Vibrations(atoms, indices=indices, name=vib_dir)
        '''If a calculation was terminated prematurely (e.g. time limit) empty .json files remain and the calculation
        of the corresponding stretch modes would be skipped on restart. The line below prevents this'''
        vib.clean(empty_files=True)
        '''Extract vibration data from existing files'''
        if read_only:
            vib.read()

        else:
            '''Calculate required vibration modes'''
            required_cache = [
                os.path.join(vib_dir, "cache." + str(x) + y + ".json")
                for x in indices
                for y in ["x+", "x-", "y+", "y-", "y-", "z+", "z-"]
            ]
            check_required_modes_files = np.array(
                [os.path.exists(file) for file in required_cache])

            if np.all(check_required_modes_files == True):
                vib.read()
            else:
                '''Set the environment variables for geometry optimisation'''
                set_aims_command(hpc=hpc,
                                 basis_set=basis_set,
                                 defaults=2020,
                                 nodes_per_instance=self.nodes_per_instance)
                '''Generate a unique folder for aims calculation'''
                counter, subdirectory_name = self._restart_setup(
                    "Vib",
                    filename=self.filename,
                    restart=False,
                    verbose=False)

                os.makedirs(subdirectory_name, exist_ok=True)
                os.chdir(subdirectory_name)
                '''Name the aims output file'''
                out = str(counter) + "_" + str(self.filename) + ".out"
                '''Calculate vibrations and write the in a separate directory'''
                with _calc_generator(params, out_fn=out,
                                     dimensions=dimensions)[0] as calculator:
                    if not self.dry_run:
                        atoms.calc = calculator
                    else:
                        atoms.calc = EMT()

                    vib = Vibrations(atoms, indices=indices, name=vib_dir)
                    vib.run()

            vib.summary()
        '''Generate a unique folder for aims calculation'''
        if not read_only:
            os.chdir(vib_dir)
            vib.write_mode()
        os.chdir(parent_dir)

        return vib.get_zero_point_energy()
Пример #16
0
from __future__ import print_function
from ase import Atoms
from ase.calculators.emt import EMT
from ase.optimize import QuasiNewton
from ase.vibrations import Vibrations
from ase.thermochemistry import IdealGasThermo

n2 = Atoms('N2',
           positions=[(0, 0, 0), (0, 0, 1.1)],
           calculator=EMT())
QuasiNewton(n2).run(fmax=0.01)
vib = Vibrations(n2)
vib.run()
print(vib.get_frequencies())
vib.summary()
print(vib.get_mode(-1))
vib.write_mode(n=None, nimages=20)
vib_energies = vib.get_energies()

thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear',
                        atoms=n2, symmetrynumber=2, spin=0)
thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.)

assert vib.clean(empty_files=True) == 0
assert vib.clean() == 13