def test_Ag_Cu100(): from math import sqrt from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.vibrations import Vibrations from ase.calculators.emt import EMT from ase.optimize import QuasiNewton, BFGS # Distance between Cu atoms on a (100) surface: d = 3.6 / sqrt(2) initial = Atoms('Cu', positions=[(0, 0, 0)], cell=(d, d, 1.0), pbc=(True, True, False)) initial *= (2, 2, 1) # 2x2 (100) surface-cell # Approximate height of Ag atom on Cu(100) surfece: h0 = 2.0 initial += Atom('Ag', (d / 2, d / 2, h0)) # Make band: images = [initial.copy() for i in range(6)] neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(range(len(initial) - 1)) for image in images: image.calc = EMT() image.set_constraint(constraint) # Displace last image: images[-1].positions[-1] += (d, 0, 0) # Relax height of Ag atom for initial and final states: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.01) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.01) # Interpolate positions between initial and final states: neb.interpolate() for image in images: print(image.positions[-1], image.get_potential_energy()) dyn = BFGS(neb, trajectory='mep.traj') dyn.run(fmax=0.05) for image in images: print(image.positions[-1], image.get_potential_energy()) a = images[0] vib = Vibrations(a, [4]) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(-1, nimages=20)
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
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
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() 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))
'nmix': 10, 'mix': 4, 'maxsteps': 500, 'diag': 'david' }, # convergence parameters outdirprefix='calcdirv') # output directory for Quantum Espresso files atoms.set_calculator(calcvib) vib = Vibrations(atoms, indices=vibrateatoms, delta=0.03) vib.run() vib.summary(method='standard') # Make trajectory files to visualize the modes. for mode in range(len(vibrateatoms) * 3): vib.write_mode(mode) # Calculate free energy vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, electronicenergy=energy, atoms=atoms, geometry='linear', symmetrynumber=2, spin=0) # At 300K and 101325 Pa # change for your operating conditions freeenergy = thermo.get_gibbs_energy(temperature=300, pressure=101325) f = open(name + '.energy', 'w')
ediff=1e-8, ediffg=-0.01, algo="Fast", gga="RP", xc="PBE", kpts=(4, 4, 1), # isif = 0, # ibrion = 5, # nsw = 0, # nfree = 2 ) adsorbedH.set_calculator(calc) electronicenergy = adsorbedH.get_potential_energy() print("electronic energy is %.5f" % electronicenergy) vib = Vibrations(adsorbedH, indices=[23], delta=0.01, nfree=2) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(-1) vib_energies = vib.get_energies() thermo = HarmonicThermo(vib_energies=vib_energies, electronicenergy=electronicenergy) thermo.get_entropy(temperature=298.15) thermo.get_internal_energy(temperature=298.15) thermo.get_free_energy(temperature=298.15)
# name of output file for free energies output_name = 'out.energy' ### At 300K and 101325 Pa ### change for your operating conditions T = 300 # K P = 101325 # Pa ######################################################################################################### ##### END ##### ######################################################################################################### energy = atoms.get_potential_energy() # caclulate the energy, to be used to determine G vibrateatoms = [atom.index for atom in atoms if atom.symbol in ['H','N']] # calculate the vibrational modes for all N and H atoms # Calculate vibrations vib = Vibrations(atoms,indices=vibrateatoms,delta=0.03) # define a vibration calculation vib.run() # run the vibration calculation vib.summary(method='standard') # summarize the calculated results for mode in range(len(vibrateatoms)*3): # Make trajectory files to visualize the modes. vib.write_mode(mode) vibenergies=vib.get_energies() vibenergies=[vib for vib in vibenergies if not isinstance(vib,complex)] # only take the real modes gibbs = HarmonicThermo(vib_energies = vibenergies, electronicenergy = energy) freeenergy = gibbs.get_gibbs_energy(T,P) f=open(output_name,'w') f.write('Potential energy: '+str(energy)+'\n'+'Free energy: '+str(freeenergy)+'\n') f.close
from ase import * from ase.vibrations import Vibrations 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(-1, nimages=20)
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(-1, nimages=20) vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear', atoms=n2, symmetrynumber=2, spin=0) thermo.get_free_energy(temperature=298.15, pressure=2*101325.)
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.)
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')
from ase.vibrations import Vibrations Au = read('CONTCAR') indices = [8, 9, 10, 12, 13] # Au.pbc = True calc4 = Vasp( xc='PBE', #Level of theory (density functional) encut= 400, #plane-wave kinetic energy cutoff (convergence test; I usually use about 520) kpts=[ 4, 4, 1 ], #number of k-points, e.g. [3,3,3] (convergence test; fewer kpoints are needed if lattice dimension is large) # isif=2, #relaxation method (2 = positions, 3 = positions+volume) prec='Accurate', #accuracy (don't change this) sigma=0.01, #don't need to change (smearing width) ismear=0, #don't need to change (smearing method) isym=0, #disables symmetry # ediffg=-0.03, #force tolerance, |ediffg| (eV/A) (I generally use 0.01 --> 0.03; lower is better but will take longer) # nsw=1000, #maximum number of steps ivdw=12, #enable van der Waals interactions setups='recommended') # ibrion=2) #geom opt algorithm (dont need change; default is conjugate gradient -- works fine) Au.set_calculator(calc4) vib = Vibrations(Au, indices=indices) vib.run() vib.summary() vib.write_mode() # Au.get_potential_energy()
# kpts={repeats}, # jobs_args='-nk {n_kpts}', balsamcalc_module = __import__('pynta.balsamcalc', fromlist=[socket_calculator]) sock_calc = getattr(balsamcalc_module, socket_calculator) atoms.calc = sock_calc(workflow='QE_Socket', job_kwargs=balsam_exe_settings, **calc_keywords) atoms.calc.set(**extra_calc_keywords) # start vibrations calculations vib = Vibrations(atoms, indices=indices, name=vib_files_loc) vib.run() vib.summary() # vib.clean() # write the first vibration mode to vib.0.traj file (default) - imaginary freq vib.write_mode(n=n, nimages=nimages) end = datetime.datetime.now() with open(os.path.join(prefix, geom[:-10] + '_time.log'), 'a+') as f: f.write(str(end)) f.write("\n") f.write(str(end - start)) f.write("\n") f.close()
#!/usr/bin/env python from ase import Atom, Atoms from ase.structure import molecule from ase.calculators.cp2k import CP2K from ase.optimize import BFGS from ase.vibrations import Vibrations from multiprocessing import Pool import os atoms = molecule('CO') atoms.center(vacuum=2.0) calc = CP2K(label = 'molecules/co/vib', xc='PBE') atoms.set_calculator(calc) gopt = BFGS(atoms, logfile=None) gopt.run(fmax=1e-2) e = atoms.get_potential_energy() pos = atoms.get_positions() d = ((pos[0] - pos[1])**2).sum()**0.5 print('{0:1.4f} {1:1.4f} '.format( e, d)) vib = Vibrations(n2) vib.run() vib.summary() vib.write_mode(-1)
CH3 = molecule('CH3') add_adsorbate(slab, CH3, 3.0, 'ontop') constraint = FixAtoms(mask=[a.symbol == 'Al' for a in slab]) slab.set_constraint(constraint) slab.set_calculator(EMT()) dyn = QuasiNewton(slab, trajectory='relax.traj') dyn.run(fmax=0.01) vib = Vibrations(slab, indices=[8, 9, 10, 11]) vib.run() vib.summary() vib.write_mode() print('\n >> Anharmonics <<\n') AM = AnharmonicModes( vibrations_object=vib, pre_names='an_mode_', settings={ 'use_forces': True, # 'plot_mode': True, 'temperature': 298.15, # 'rot_nsamples': 15, # 'max_step_iterations': 1, # 'min_step_iterations': 1, 'plot_mode_each_iteration': True, # 'rot_nsamples': 9,
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()