def vibname(relaxed): atoms = relaxed.copy() atoms.calc = relaxed.calc name = 'vib' vib = Vibrations(atoms, name=name) vib.run() return name
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
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 vibname(tmp_path, relaxed): atoms = relaxed.copy() atoms.calc = relaxed.calc name = str(tmp_path / 'vib') vib = Vibrations(atoms, name=name) vib.run() return name
def ase_vib(embedder, coords, atomnos, logfunction=None, title='temp'): ''' ''' atoms = Atoms(atomnos, positions=coords) atoms.calc = get_ase_calc(embedder) vib = Vibrations(atoms, name=title) if os.path.isdir(title): os.chdir(title) for f in os.listdir(): os.remove(f) os.chdir(os.path.dirname(os.getcwd())) else: os.mkdir(title) os.chdir(title) t_start = time.perf_counter() with HiddenPrints(): vib.run() # freqs = vib.get_frequencies() freqs = vib.get_energies() * 8065.544 # from eV to cm-1 if logfunction is not None: elapsed = time.perf_counter() - t_start logfunction( f'{title} - frequency calculation completed ({time_to_string(elapsed)})' ) os.chdir(os.path.dirname(os.getcwd())) return freqs, np.count_nonzero(freqs.imag > 1e-3)
def test_harmonic_vibrations(self, testdir): """Check the numerics with a trivial case: one atom in harmonic well""" rng = np.random.RandomState(42) k = rng.rand() ref_atoms = Atoms('H', positions=np.zeros([1, 3])) atoms = ref_atoms.copy() mass = atoms.get_masses()[0] atoms.calc = ForceConstantCalculator(D=np.eye(3) * k, ref=ref_atoms, f0=np.zeros((1, 3))) vib = Vibrations(atoms, name='harmonic') vib.run() vib.read() expected_energy = ( units._hbar # In J/s * np.sqrt(k # In eV/A^2 * units._e # eV -> J * units.m**2 # A^-2 -> m^-2 / mass # in amu / units._amu # amu^-1 -> kg^-1 )) / units._e # J/s -> eV/s assert np.allclose(vib.get_energies(), expected_energy)
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 test_gs_minimum(): """Test ground state minimum distance, energy and vibrational frequency""" atoms = H2Morse() assert atoms.get_distance(0, 1) == pytest.approx(Re[0], 1.e-12) assert atoms.get_potential_energy() == -De[0] # check ground state vibrations vib = Vibrations(atoms) vib.run() assert (vib.get_frequencies().real[-1] == pytest.approx(ome[0], 1e-2))
def run(self): if self.overlap: # XXXX stupid way to make a copy self.atoms.get_potential_energy() self.eq_calculator = self.atoms.get_calculator() fname = self.exname + '.eq.gpw' self.eq_calculator.write(fname, 'all') self.eq_calculator = self.eq_calculator.__class__(fname) self.eq_calculator.converge_wave_functions() Vibrations.run(self)
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
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() vib_data = vibs.get_vibrations() assert_array_almost_equal(freqs, vib_data.get_frequencies())
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 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)
def test_consistency_with_vibrationsdata(self, testdir, n2_emt): atoms = n2_emt vib = Vibrations(atoms) vib.run() vib_data = vib.get_vibrations() assert_array_almost_equal(vib.get_energies(), vib_data.get_energies()) # Compare the last mode as the others may be re-ordered by negligible # energy changes assert_array_almost_equal(vib.get_mode(5), vib_data.get_modes()[5])
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 run(self): if self.overlap: # XXXX stupid way to make a copy self.atoms.get_potential_energy() calc = self.atoms.calc fname = self.exname + '.eq.gpw' calc.write(fname, 'all') self.eq_calculator = calc.__class__.read(fname) if hasattr(self.eq_calculator, 'converge_wave_functions'): self.eq_calculator.converge_wave_functions() Vibrations.run(self)
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
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
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_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()
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_ideal_gas_thermo(): atoms = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)]) atoms.calc = 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.)
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 run(self): if self.overlap: # XXXX stupid way to make a copy self.atoms.get_potential_energy() self.eq_calculator = self.atoms.calc fname = 'tmp.gpw' self.eq_calculator.write(fname, 'all') self.eq_calculator = self.eq_calculator.__class__(restart=fname) try: # XXX GPAW specific self.eq_calculator.converge_wave_functions() except AttributeError: pass Vibrations.run(self)
def test_consistency_with_vibrationsdata(self, testdir, random_dimer): vib = Vibrations(random_dimer, delta=1e-6, nfree=4) vib.run() vib_data = vib.get_vibrations() assert_array_almost_equal(vib.get_energies(), vib_data.get_energies()) for mode_index in range(3 * len(vib.atoms)): assert_array_almost_equal(vib.get_mode(mode_index), vib_data.get_modes()[mode_index]) # Hessian should be close to the ForceConstantCalculator input assert_array_almost_equal(random_dimer.calc.D, vib_data.get_hessian_2d(), decimal=6)
def vib_zpe(self, job, atoms): from ase.vibrations import Vibrations self.log('-' * 60) self.log('Run ZEP calculation: {0}'.format(job)) label = os.path.join(self.label, job) label = os.path.join(label, 'vib') # copy file calculator = deepcopy(self.calculator) dip = dipole_correction(atoms, edir=3) calculator.update(dip) calculator.update({ 'calculation': 'scf', 'tstress': True, 'tprnfor': True, 'outdir': '../', 'prefix': '%s' % job, 'startingpot': 'file', 'startingwfc': 'file', 'etot_conv_thr': 1e-6, 'disk_io': 'none', }) # better to restart from previous geo_relax calculation calc = Espresso( label=label, **calculator, ) atoms.calc = calc if job[-1] == 'O': indices = [-1] elif job[-2:] == 'OH' and job[-3:] != 'OOH': indices = [-1, -2] elif job[-3:] == 'OOH': indices = [-1, -2, -3] elif job[-2:] == 'O2': indices = [-1, -2] else: indices = [] # print('%!!!') return job, 0 vib = Vibrations(atoms, name=os.path.join(label, job), indices=indices) vib.run() vib_energies = np.real(vib.get_energies()) zpe = 0. for energy in vib_energies: zpe += 0.5 * energy self.zpes[job] = zpe return job, zpe
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_json_manipulation(self, testdir, random_dimer): vib = Vibrations(random_dimer, name='interrupt') vib.run() disp_file = Path('interrupt/cache.1x-.json') comb_file = Path('interrupt/combined.json') assert disp_file.is_file() assert not comb_file.is_file() # Should do nothing harmful as files are already split # (It used to raise an error but this is no longer implemented.) vib.split() # Build a combined file assert vib.combine() == 13 # Individual displacements should be gone, combination should exist assert not disp_file.is_file() assert comb_file.is_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 fd: fd.write("hello") with pytest.raises(AssertionError): vib.split() os.remove(disp_file) # Now split() for real: replace .all.json file with displacements vib.split() assert disp_file.is_file() assert not comb_file.is_file()
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}}])
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()
def calculate(element, ref_data, p): values_dict = {} values_dict[p['xc']] = {} for XY, data in ref_data[p['xc']].items(): X = XY.split('-')[0] Y = XY.split('-')[1] if (X == Y and X == element) or (X != Y and (X == element or Y == element)): # compound contains the requested element re_ref = data['re'] we_ref = data['we'] m0_ref = data.get('m0', 0.0) # compound = Atoms(X+Y, [ (0, 0, 0.5 ), (0, 0, 0.5+re_ref/a), ], pbc=0) compound.set_cell([a, b, c], scale_atoms=1) compound.center() # calculation on the reference geometry calc = Calculator(**p) compound.set_calculator(calc) e_compound = compound.get_potential_energy() finegd = calc.density.finegd dip = finegd.calculate_dipole_moment(calc.density.rhot_g)*calc.a0 vib = Vibrations(compound) vib.run() vib_compound = vib.get_frequencies(method='frederiksen').real[-1] world.barrier() vib_pckl = glob('vib.*.pckl') if rank == 0: for file in vib_pckl: remove(file) # calculation on the relaxed geometry qn = QuasiNewton(compound) #qn.attach(PickleTrajectory('compound.traj', 'w', compound).write) qn.run(fmax=0.05) e_compound_r = compound.get_potential_energy() dist_compound_r = compound.get_distance(0,1) dip_r = finegd.calculate_dipole_moment(calc.density.rhot_g)*calc.a0 vib = Vibrations(compound) vib.run() vib_compound_r = vib.get_frequencies(method='frederiksen').real[-1] world.barrier() vib_pckl = glob('vib.*.pckl') if rank == 0: for file in vib_pckl: remove(file) del compound e = e_compound we = vib_compound m0 = dip e_r = e_compound_r we_r = vib_compound_r re_r = dist_compound_r m0_r = dip_r # values_dict[p['xc']][XY] = {'re': re_r, 'we': (we_r, we), 'm0': (m0_r, m0)} # return values_dict
# 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