def run(job, atoms): kwargs = {'mode': 0, 'label': 'vib-{0}'.format(job, job), 'xc': 'PBE', 'scf_guess': 'atomic', 'max_scf': 500, 'EPS_SCF': 5.0E-7, 'added_mos': 500, 'sme/method': 'fermi_dirac', 'ELECTRONIC_TEMPERATURE': 300, 'DIA/ALGORITHM': 'STANDARD', 'mix/METHOD': 'BROYDEN_MIXING', 'ALPHA': 0.1, 'BETA': 1.5, 'NBUFFER': 8, 'cpu': 36, 'cutoff': 300, 'run_type': 'ENERGY_FORCE', # ENERGY_FORCE, GEO_OPT, CELL_OPT, MD 'atoms': atoms, } calc = CP2K(**kwargs) atoms.set_calculator(calc) vib = Vibrations(atoms, indices = [65, 69]) vib.run() vib.summary()
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 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
def VibScript(): from ase.vibrations import Vibrations import glob, json, cPickle, ase, os ####################### print "Initializing..." #---------------------- params, atoms = initialize( ) # Remove old .out/.err files, load from fw_spec, and write 'init.traj' prev = glob.glob( '*.pckl') #delete incomplete pckls - facilitating restarted jobs if rank() == 0: for p in prev: if os.stat(p).st_size < 100: os.remove(p) atoms.set_calculator(makeCalc(params)) vib = Vibrations(atoms, delta=params['delta'], indices=json.loads(params['vibids_json'])) vib.run() vib.write_jmol() ########################## print "Storing Results..." #------------------------- vib.summary(log='vibrations.txt') with open('vibrations.txt', 'r') as f: vibsummary = f.read() ase.io.write('final.traj', atoms) optAtoms = ase.io.read('final.traj') vib_energies, vib_frequencies = vib.get_energies(), vib.get_frequencies() resultDict = mergeDicts([ params, trajDetails(optAtoms), { 'vibfreqs_pckl': cPickle.dumps(vib_frequencies), 'vibsummary': vibsummary, 'vibengs_pckl': cPickle.dumps(vib_energies) } ]) with open('result.json', 'w') as outfile: outfile.write(json.dumps(resultDict)) with open('result.json', 'r') as outfile: json.loads(outfile.read()) #test that dictionary isn't 'corrupted' if rank() == 0: log(params, optAtoms) return 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
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
def test_vibrations_example(testdir): """Test the example from the Vibrations.__init__() docstring""" n2 = Atoms('N2', [(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) BFGS(n2).run(fmax=0.01) vib = Vibrations(n2) vib.run() with io.StringIO() as f: vib.summary(log=f) f.seek(0) summary = f.read() assert len(summary.split()) == len(expected_summary.split())
def freq(atoms=None): if atoms is None: atoms = read('md.traj',index=0) atoms.calc = IRFF(atoms=atoms,libfile='ffield.json',rcut=None,nn=True,massage=2) # Compute frequencies frequencies = Vibrations(atoms, name='freq') frequencies.run() # Print a summary frequencies.summary() frequencies.write_dos() # Write jmol file if requested # if write_jmol: frequencies.write_jmol()
def test_harmonic_thermo(): atoms = fcc100('Cu', (2, 2, 2), vacuum=10.) atoms.calc = EMT() add_adsorbate(atoms, 'Pt', 1.5, 'hollow') atoms.set_constraint(FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Cu'])) QuasiNewton(atoms).run(fmax=0.01) vib = Vibrations(atoms, name='harmonicthermo-vib', indices=[atom.index for atom in atoms if atom.symbol != 'Cu']) vib.run() vib.summary() vib_energies = vib.get_energies() thermo = HarmonicThermo(vib_energies=vib_energies, potentialenergy=atoms.get_potential_energy()) thermo.get_helmholtz_energy(temperature=298.15)
def compute_normal_modes(self, write_jmol=True): """ Use ase calculator to compute numerical frequencies for the molecule Args: write_jmol (bool): Write frequencies to input file for visualization in jmol (default=True) """ freq_file = os.path.join(self.working_dir, "normal_modes") # Compute frequencies frequencies = Vibrations(self.molecule, name=freq_file) frequencies.run() # Print a summary frequencies.summary() # Write jmol file if requested if write_jmol: frequencies.write_jmol()
def run(label, atoms): #calc.mode = 1 calc.directory = 'vib/pt/{0}'.format(label) calc.prefix = 'al2o3-pt-{0}'.format(label) calc.results = {} calc.CP2K_INPUT.FORCE_EVAL_list[0].DFT.Wfn_restart_file_name = 'al2o3-pt-{0}-RESTART.wfn'.format(label) calc.CP2K_INPUT.MOTION.CONSTRAINT.FIXED_ATOMS_list = [] #=============================================================================== atoms.set_calculator(calc) ###calc.write_input_file() #e = atoms.get_potential_energy() #t = calc.get_time() print(' {0} '.format(label)) vib = Vibrations(atoms, indices = [120]) vib.run() vib.summary() import os, shutil for file in os.listdir('.'): if "pckl" in file: shutil.move(file,calc.directory)
def test_vibration_on_surface(self, testdir): from ase.build import fcc111, add_adsorbate ag_slab = fcc111('Ag', (4, 4, 2), a=2) n2 = Atoms('N2', positions=[[0., 0., 0.], [0., np.sqrt(2), np.sqrt(2)]]) add_adsorbate(ag_slab, n2, height=1, position='fcc') # Add an interaction between the N atoms hessian_bottom_corner = np.zeros((2, 3, 2, 3)) hessian_bottom_corner[-1, :, -2] = [1, 1, 1] hessian_bottom_corner[-2, :, -1] = [1, 1, 1] hessian = np.zeros((34, 3, 34, 3)) hessian[32:, :, 32:, :] = hessian_bottom_corner ag_slab.calc = ForceConstantCalculator(hessian.reshape( (34 * 3, 34 * 3)), ref=ag_slab.copy(), f0=np.zeros((34, 3))) # Check that Vibrations with restricted indices returns correct Hessian vibs = Vibrations(ag_slab, indices=[-2, -1]) vibs.run() vibs.read() assert_array_almost_equal(vibs.get_vibrations().get_hessian(), hessian_bottom_corner) # These should blow up if the vectors don't match number of atoms vibs.summary() vibs.write_jmol() for i in range(6): # Frozen atoms should have zero displacement assert_array_almost_equal(vibs.get_mode(i)[0], [0., 0., 0.]) # The N atoms should have finite displacement assert np.all(vibs.get_mode(i)[-2:, :])
def run_task(self,fw_spec): """ONLY WORKS FOR QUANTUM ESPRESSO""" from ase.vibrations import Vibrations jobID = fw_spec['jobID'] job = db2object(jobID) t0 = time.time() atoms = job.atoms() atoms.set_calculator(job.vibCalc()) vib = Vibrations(atoms,delta=job.delta(),indicies=job.vibids) vib.run() vib.summary(log='vibrations.txt') vib.write_jmol() vibs = vib.get_frequencies() t = (time.time()-t0)/60.0 #min return FWAction(stored_data= {'vibs':vibs,'avgtime':t},mod_spec=[{'_push': {'vibs':vibs,'time':t}}])
def test_vibrations_on_surface(self, testdir): atoms = self.n2_on_ag.copy() atoms.calc = EMT() vibs = Vibrations(atoms, indices=[-2, -1]) vibs.run() freqs = vibs.get_frequencies() assert len(freqs) == 6 vib_data = vibs.get_vibrations() assert_array_almost_equal(freqs, vib_data.get_frequencies()) # These should blow up if the vectors don't match number of atoms vibs.summary() vibs.write_jmol() for i in range(6): # Frozen atoms should have zero displacement assert_array_almost_equal(vibs.get_mode(i)[0], [0., 0., 0.]) # At least one of the N atoms should have finite displacement # (It's a strange test system, the N aren't interacting.) assert np.any(vibs.get_mode(i)[-2:, :])
def run_task(self,fw_spec): """ONLY WORKS FOR QUANTUM ESPRESSO""" from ase.vibrations import Vibrations job,params,atoms = initialize(fw_spec) prev = g.glob('*.pckl') #delete incomplete pckls - facilitating restarted jobs for p in prev: if os.stat(p).st_size < 100: os.remove(p) atoms.set_calculator(job.vibCalc()) vib = Vibrations(atoms,delta=job.delta(),indices=job.vibids()) vib.run(); vib.write_jmol() vib.summary(log='vibrations.txt') with open('vibrations.txt','r') as f: vibsummary = f.read() vib_energies,vib_frequencies = vib.get_energies(),vib.get_frequencies() resultDict = misc.mergeDicts([params, {'vibfreqs_pckl': pickle.dumps(vib_frequencies) ,'vibsummary':vibsummary ,'vibengs_pckl':pickle.dumps(vib_energies)}]) with open('result.json', 'w') as outfile: json.dumps(resultDict, outfile) return fireworks.core.firework.FWAction(stored_data=resultDict)
def test_thermochemistry(): """Tests of the major methods (HarmonicThermo, IdealGasThermo, CrystalThermo) from the thermochemistry module.""" # Ideal gas thermo. atoms = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(atoms).run(fmax=0.01) energy = atoms.get_potential_energy() vib = Vibrations(atoms, name='idealgasthermo-vib') vib.run() vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear', atoms=atoms, symmetrynumber=2, spin=0, potentialenergy=energy) thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.) # Harmonic thermo. atoms = fcc100('Cu', (2, 2, 2), vacuum=10.) atoms.set_calculator(EMT()) add_adsorbate(atoms, 'Pt', 1.5, 'hollow') atoms.set_constraint( FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Cu'])) QuasiNewton(atoms).run(fmax=0.01) vib = Vibrations( atoms, name='harmonicthermo-vib', indices=[atom.index for atom in atoms if atom.symbol != 'Cu']) vib.run() vib.summary() vib_energies = vib.get_energies() thermo = HarmonicThermo(vib_energies=vib_energies, potentialenergy=atoms.get_potential_energy()) thermo.get_helmholtz_energy(temperature=298.15) # Crystal thermo. atoms = bulk('Al', 'fcc', a=4.05) calc = EMT() atoms.set_calculator(calc) energy = atoms.get_potential_energy() # Phonon calculator N = 7 ph = Phonons(atoms, calc, supercell=(N, N, N), delta=0.05) ph.run() ph.read(acoustic=True) phonon_energies, phonon_DOS = ph.dos(kpts=(4, 4, 4), npts=30, delta=5e-4) thermo = CrystalThermo(phonon_energies=phonon_energies, phonon_DOS=phonon_DOS, potentialenergy=energy, formula_units=4) thermo.get_helmholtz_energy(temperature=298.15) # Hindered translator / rotor. # (Taken directly from the example given in the documentation.) vibs = np.array([ 3049.060670, 3040.796863, 3001.661338, 2997.961647, 2866.153162, 2750.855460, 1436.792655, 1431.413595, 1415.952186, 1395.726300, 1358.412432, 1335.922737, 1167.009954, 1142.126116, 1013.918680, 803.400098, 783.026031, 310.448278, 136.112935, 112.939853, 103.926392, 77.262869, 60.278004, 25.825447 ]) vib_energies = vibs / 8065.54429 # Convert to eV from cm^-1. trans_barrier_energy = 0.049313 # eV rot_barrier_energy = 0.017675 # eV sitedensity = 1.5e15 # cm^-2 rotationalminima = 6 symmetrynumber = 1 mass = 30.07 # amu inertia = 73.149 # amu Ang^-2 thermo = HinderedThermo(vib_energies=vib_energies, trans_barrier_energy=trans_barrier_energy, rot_barrier_energy=rot_barrier_energy, sitedensity=sitedensity, rotationalminima=rotationalminima, symmetrynumber=symmetrynumber, mass=mass, inertia=inertia) helmholtz = thermo.get_helmholtz_energy(temperature=298.15) target = 1.593 # Taken from documentation example. assert (helmholtz - target) < 0.001
from __init__ import AnharmonicModes 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, (
from __init__ import AnharmonicModes 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())
#!/usr/bin/env python from ase.db import connect from ase.calculators.aims import Aims from ase.lattice.surface import fcc111, add_adsorbate from ase.constraints import FixAtoms from ase import Atoms, Atom from ase.io.aims import read_aims from ase.optimize import BFGS from ase.vibrations import Vibrations mydb = connect("mydb.db") atoms = mydb.get_atoms(name='pt-co-relax') calc = Aims(label='cluster/pt-co-vib-cons', xc='pbe', spin='none', relativistic = 'atomic_zora scalar', sc_accuracy_etot=1e-7, sc_accuracy_eev=1e-3, sc_accuracy_rho=1e-4, sc_accuracy_forces=1e-3) atoms.set_calculator(calc) vib = Vibrations(atoms, indices=[1, 2], name='cluster/pt-co-vib-cons/vib') vib.run() vib.summary()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Mon Jun 15 00:45:20 2020 @author: macenrola """ from ase import Atoms, io, calculators import ase.calculators.cp2k from gpaw import GPAW, PW from ase.optimize import BFGS from ase.vibrations import Vibrations mol = io.read( "/home/macenrola/Documents/cb8_MV_electrochemistry_JIA/apbs_ref/benzene.pdb" ) mol.center(vacuum=3.5) print(mol.cell) print(mol.positions) c = ase.calculators.cp2k.CP2K() CP2K.command = "env OMP_NUM_THREADS=2 mpirun -np 4 cp2k" print(mol.set_calculator(c)) BFGS(mol).run(fmax=0.01) vib = Vibrations(mol) vib.run() print(vib.summary())
from ase.build import molecule from ase.optimize import QuasiNewton from ase.calculators.emt import EMT from ase.vibrations import Vibrations from __init__ import AnharmonicModes H2 = molecule('H2') H2.set_calculator(EMT()) dyn = QuasiNewton(H2, logfile='/dev/null') dyn.run(fmax=0.05) vib = Vibrations(H2, indices=[0, 1]) vib.run() vib.summary(log='/dev/null') vib.clean() AM = AnharmonicModes(vib, settings={ 'temperature': 1000, }) vib_mode = AM.define_vibration(mode_number=-1) AM.run() AM.summary(log='/dev/null') AM.clean() assert abs(AM.get_ZPE() - 0.497) < 1e-3, AM.get_ZPE() assert abs(AM.get_entropic_energy()) < 1e-3, AM.get_entropic_energy() AM = AnharmonicModes(vib, settings={
calc = espresso(outdir = 'calcdir', **params) # regular espresso calculator calcvib = vibespresso(outdirprefix = 'vibdir', **params) # special calculator for the vibration calculations atoms.set_calculator(calc) # attach calculator to the atoms energy = atoms.get_potential_energy() # caclulate the energy, to be used to determine G # vibrate N and H atoms vibrateatoms = [atom.index for atom in atoms if atom.symbol in ['H','N']] # calculate the vibrational modes for all N and H atoms atoms.set_calculator(calcvib) # attach vibrations calculator to the 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) ### UNCOMMENT TO CALCULATE FREE get_energies ### YOU CAN ALSO USER get_ads_free_energy.py and get_gas_free_energy.py ### Calculate free energy # 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) ### At 300K and 101325 Pa
from ase.constraints import FixAtoms from ase.units import * from ase.vibrations import Vibrations from flare import kernels from flare.modules import gp_calculator from mc_kernels import mc_simple import pickle # load TS TS = read('dimer.traj') # fix bottommost layer fix = [atom.index for atom in TS if atom.position[2] < 9] move = [atom.index for atom in TS if atom.position[2] > 9] constraint = FixAtoms(mask=fix) TS.set_constraint(constraint) # set gp calculator gp_file = open('PdAg.gp', 'rb') gp_model = pickle.load(gp_file) gp_model.energy_force_kernel = mc_simple.two_plus_three_mc_force_en TS.set_calculator(gp_calculator.GPCalculator(gp_model)) # calculate Hessian vib = Vibrations(TS, indices=move) vib.run() # clean up vib.summary(log='gp_freq.txt') vib.combine()
dw=8000, # density cutoff nbands=-10, # number of bands kpts=(8, 8, 8), # k points xc='rpbe', # exchange correlation method sigma=0.2, # Fermi temperature dipole={'status': False}, spinpol=False, convergence={ 'energy': 0.0005, 'mixing': 0.1, 'nmix': 10, 'maxsteps': 500, 'diag': 'david' }, outdirprefix='vibdir') atoms.set_calculator(calc) vib = Vibrations(atoms, delta=0.04, indices=vib_atoms) vib.run() vib.summary(log='vibrations.txt') vib.write_jmol() realFreq = [ x * 0.00012 for x in vib.get_frequencies() if not isinstance(x, complex) ] #eV S = HarmonicThermo(realFreq).get_entropy(300) with open('vibrations.txt', 'a') as f: f.write('\nTS at 300K: ' + str(S))
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()
"""Calculate the vibrational modes of a H2O molecule.""" from ase.vibrations import Vibrations from gpaw import GPAW h2o = GPAW('h2o.gpw', txt=None).get_atoms() # Create vibration calculator vib = Vibrations(h2o) vib.run() vib.summary(method='frederiksen') # Make trajectory files to visualize normal modes: for mode in range(9): vib.write_mode(mode)
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')
vibDB = connect('./vib.db', append=False) # DB for vibration spectrum phonDB = connect('./ph.db', append=False) # DB for phonon structure and DOS # Using optimal lattice parameter from task 2 a = 4.043 # A atoms = bulk('Al', 'fcc', a) # view(atoms) # DEBUG #### Calculate vibrational spectrum # Attach EAM calculator to atoms mishin = EAM(potential='../CourseGitRepo/HA5_al_potential.alloy') # Set up EAM atoms.set_calculator(mishin) # Get vibrational spectrum v = Vibrations(atoms, name='./vibs/vib_bulk') v.run() v.summary() # Get frequencies and DOS - i.e # of states per frequency (freq, counts) = np.unique(v.get_frequencies(), return_counts=True) freq = np.array(freq) dos = np.array(counts) # Save to db vibDB.write(atoms, data={'frequency': freq, 'DOS': dos}) #### Calculate band structure N = 7 # Use a supercell of size 7x7x7 ph = Phonons(atoms, mishin, name='./phonons/ph_bulk', supercell=(N, N, N), delta=0.05) ph.run()
# | - TEMP ********************************************************************* from ase.vibrations import Vibrations from ase_modules.ase_methods import thermochem_IG_corr vib = Vibrations( atoms, indices=None, ) vib.run() # print("an_ads_vib | Getting vibrational energies") vib_e_list = vib.get_energies() vib.summary(log="vib_summ.out") thermochem_IG_corr( vib_e_list, Temperature=300.0, Pressure=100000.0, potentialenergy=0., symmetrynumber=2, spin=1, atoms=atoms, linear=True, ) # # H2O, H2, O2: 2, # symmetrynumber=symmetrynumber, # symmetry numbers from point group # spin=spin, # 1 for O2, 0 for H2O and H2
psppath='/home/vossj/suncat/psp/gbrv1.5pbe', # pseudopotential convergence={ 'energy': 1e-5, 'mixing': 0.1, '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
psppath='/home/vossj/suncat/psp/gbrv1.5pbe', # pseudopotential convergence={'energy': 1e-5, 'mixing': 0.1, '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
def calc(primitive, cachedir=None, supercell=(1, 1, 1), delta=0.01, quick=True): """Calculates the Hessian for a given atoms object (which *must* have an attached calculator). .. note:: We choose to use the Hessian as the fundamental quantity in vibrational analysis in `matdb`. .. note:: `atoms` will be relaxed before calculating the Hessian. Args: primitive (matdb.atoms.Atoms): atomic structure of the *primitive*. cachedir (str): path to the directory where phonon calculations are cached. If not specified, a temporary directory will be used. supercell (tuple): number of times to duplicate the cell when forming the supercell. delta (float): displacement in Angstroms of each atom when computing the phonons. quick (bool): when True, use symmetry to speed up the Hessian calculation. See :func:`_calc_quick`. Returns: numpy.ndarray: Hessian matrix that has dimension `(natoms*3, natoms*3)`, where `natoms` is the number of atoms in the *supercell*. """ if quick: return _calc_quick(primitive, supercell, delta) else: atoms = primitive.make_supercell(supercell) atoms.set_calculator(primitive.get_calculator()) from ase.vibrations import Vibrations #The phonon calculator caches the displacements and force sets for each #atomic displacement using pickle. This generates three files for each #atomic degree of freedom (one for each cartesian direction). We want to #save these in a special directory. tempcache = False if cachedir is None: cachedir = mkdtemp() tempcache = True else: cachedir = path.abspath(path.expanduser(cachedir)) if not path.isdir(cachedir): mkdir(cachedir) result = None precon = Exp(A=3) aphash = None #Calculate a hash of the calculator and atoms object that we are calculating #for. If the potential doesn't have a `to_dict` method, then we ignore the #hashing. if not tempcache and hasattr(atoms, "to_dict") and hasattr( atoms._calc, "to_dict"): atoms_pot = {"atoms": atoms.to_dict(), "pot": atoms._calc.to_dict()} #This UUID will probably be different, even if the positions and species #are identical. del atoms_pot["atoms"]["uuid"] hash_str = convert_dict_to_str(atoms_pot) aphash = str(sha1(hash_str).hexdigest()) if not tempcache: #Check whether we should clobber the cache or not. extras = ["vibsummary.log", "vib.log", "phonons.log"] with chdir(cachedir): hash_match = False if path.isfile("atomspot.hash"): with open("atomspot.hash") as f: xhash = f.read() hash_match = xhash == aphash hascache = False if not hash_match: for vibfile in glob("vib.*.pckl"): remove(vibfile) hascache = True for xfile in extras: if path.isfile(xfile): remove(xfile) hascache = True if hascache: msg.warn( "Using hard-coded cache directory. We were unable to " "verify that the atoms-potential combination matches " "the one for which existing cache files exist. So, we " "clobbered the existing files to get the science " "right. You can fix this by using `matdb.atoms.Atoms` " "and `matdb.calculators.*Calculator` objects.") with chdir(cachedir): #Relax the cell before we calculate the Hessian; this gets the forces #close to zero before we make harmonic approximation. try: with open("phonons.log") as f: with redirect_stdout(f): minim = PreconLBFGS(atoms, precon=precon, use_armijo=True) minim.run(fmax=1e-5) except: #The potential is unstable probably. Issue a warning. msg.warn( "Couldn't optimize the atoms object. Potential may be unstable." ) vib = Vibrations(atoms, delta=delta) with open("vib.log", 'a') as f: with redirect_stdout(f): vib.run() vib.summary(log="vibsummary.log") result = vib.H #Cache the hash of the atoms object and potential that we were using so #that we can check next time whether we should clobber the cache or not. if aphash is not None and not tempcache: with open(path.join(cachedir, "atomspot.hash"), 'w') as f: f.write(aphash) return result
from ase.optimize import QuasiNewton from ase.vibrations import Vibrations from gpaw import GPAW # Water molecule: d = 0.9575 t = pi / 180 * 104.51 H2O = Atoms("H2O", positions=[(0, 0, 0), (d, 0, 0), (d * cos(t), d * sin(t), 0)]) H2O.center(vacuum=3.5) calc = GPAW(h=0.2, txt="h2o.txt", mode="lcao", basis="dzp") H2O.set_calculator(calc) QuasiNewton(H2O).run(fmax=0.05) """Calculate the vibrational modes of a H2O molecule.""" # Create vibration calculator vib = Vibrations(H2O) vib.run() vib.summary(method="frederiksen") # Make trajectory files to visualize normal modes: for mode in range(9): vib.write_mode(mode)
# 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