Beispiel #1
0
def GibbsAds(energy, frequencies, T):
    #Expecting T in Kelvin
    #note that frequencies should have a lower bound, e.g. 56 cm-1, in order to bound entropic contributions.
    cm_to_eV = 1.23981e-4
    vib_energies = list(frequencies)
    for i in range(len(vib_energies)):
        vib_energies[i] = vib_energies[i] * cm_to_eV
    thermo_ads = HarmonicThermo(vib_energies=vib_energies,
                                electronicenergy=energy)
    val = thermo_ads.get_gibbs_energy(temperature=T, verbose=False)
    return val
Beispiel #2
0
    def _calculate_Gcorr(self, adsorbate, verbose=False):
        """Re-calculates the G_correction for the specified adsorbate. Note
        since only harmonic degrees of freedom are considered and the clean
        slab is considered to be static (i.e., its vibrations are
        unaffected by the presence of the adsorbate), then its G correction
        is 0.

        Args:
            adsorbate (string)
            verbose (bool, optional)
        """
        if adsorbate == '':
            self.data[adsorbate]['EtoG'] = 0.
        if adsorbate == '':
            self.data[adsorbate]['EtoG'] = 0.
        else:
            vibs = self.data[adsorbate]['vibs']
            thermo = HarmonicThermo(vib_energies=vibs, electronicenergy=None)
            self.data[adsorbate]['EtoG'] = thermo.get_gibbs_energy(
                temperature=self.temperature, verbose=verbose)
Beispiel #3
0
    def _calculate_Gcorr(self, adsorbate, verbose=False):
        """Re-calculates the G_correction for the specified adsorbate. Note
        since only harmonic degrees of freedom are considered and the clean
        slab is considered to be static (i.e., its vibrations are
        unaffected by the presence of the adsorbate), then its G correction
        is 0.

        Args:
            adsorbate (string)
            verbose (bool, optional)
        """
        if adsorbate == '':
            self.data[adsorbate]['EtoG'] = 0.
        if adsorbate == '':
            self.data[adsorbate]['EtoG'] = 0.
        else:
            vibs = self.data[adsorbate]['vibs']
            thermo = HarmonicThermo(vib_energies=vibs,
                                    electronicenergy=None)
            self.data[adsorbate]['EtoG'] = thermo.get_gibbs_energy(
                temperature=self.temperature, verbose=verbose)
# 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
Beispiel #5
0
                 isif=2,
                 prec="Normal",
                 ediff=1E-4,
                 ediffg=-0.02,
                 xc="pbe",
                 ispin=2,
                 lcharg=True,
                 encut=470,
                 lorbit=11,
                 nelmin=6,
                 nelm=60,
                 ivdw=11,
                 isym=0,
                 lreal="Auto",
                 gamma=True,
                 potim=0.015,
                 nfree=2)
freq_cluster.calc = freq_calc
vib = Vibrations(freq_cluster)
vib.run()
vib_energies = vib.get_energies()

thermo = HarmonicThermo(
    vib_energies=vib_energies,
    potentialenergy=potentialenergy,
    atoms=freq_cluster
)  #harmonic approximation for the adsorbate species vibration
G = thermo.get_gibbs_energy(temperature=298.15, pressure=101325.)
S = thermo.get_entropy(temperature=298.15)
H = thermo.get_helmholtz_energy(temperature=298.15)
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
Beispiel #7
0
## more information here: https://wiki.fysik.dtu.dk/ase/ase/thermochemistry/thermochemistry.html

name = 'example_ads'

#electronic energy in eV
energy = -21861.531796

#vibrational energies in meV
vibenergies = [60.5, 77.1, 314.2]

#convert from meV to eV for each mode
vibenergies[:] = [ve / 1000. for ve in vibenergies]

#list of temperatures
temperatures = [300]

#operating pressure
pressures = [101325]

f = open(name + '_free.energy', 'w')
for temperature in temperatures:
    for pressure in pressures:
        gibbs = HarmonicThermo(vib_energies=vibenergies,
                               electronicenergy=energy)
        freeenergy = gibbs.get_gibbs_energy(temperature, pressure)
        f.write('Temperature: ' + str(temperature) + '\t' + 'Pressure: ' +
                str(pressure) + '\t' + 'Free energy: ' + str(freeenergy) +
                '\n')

f.close
Beispiel #8
0
class Reactant:
    """
    """
    def __init__(
        self,
        surf_name=None,
        surf_class=None,  #type
        species_name=None,
        species_type=None,
        traj_loc=None,
        vib_loc=None,
        symmetrynumber=None,
        geometry=None,
        spin=None,
        calc_params=None,
        tag='',
    ):

        self.surf_name = surf_name
        self.surf_class = surf_class
        self.species_name = species_name
        self.species_type = species_type
        self.traj_loc = traj_loc
        self.symmetrynumber = symmetrynumber
        self.geometry = geometry
        self.spin = spin
        self.tag = tag

        if calc_params != None:
            self.calc_params = calc_params

        if traj_loc != None:
            self.atoms = read(traj_loc)
            self.calc_params = self.get_calc_params()
            if self.calc_params['xc'] == 'BEEF':
                self.beef = self.beef_reader()
        else:
            self.atoms = []
            self.calc_params = {}

        if vib_loc != None:
            self.vibs = self.vibs_reader(vib_loc)
            if self.species_type == 'slab':
                self.gibbs = None
            elif self.species_type == 'gas':
                self.gibbs = IdealGasThermo(
                    vib_energies=self.vibs,
                    potentialenergy=0,
                    atoms=self.atoms,
                    geometry=self.geometry,
                    symmetrynumber=self.symmetrynumber,
                    spin=self.spin,
                )
            elif self.species_type == 'adsorbate':
                self.gibbs = HarmonicThermo(vib_energies=self.vibs,
                                            potentialenergy=0)
            else:
                print "Warning: unrecognized species_type: ", self.species_type
                self.gibbs = None

    def get_calc_params(self):
        directory = '/'.join(self.traj_loc.split('/')[0:-1])
        if len(directory) < 1:
            directory = '.'

        #Look for all log/input files in all folders in main directory, choose first for calc params
        calcdirs = glob(directory + '/*/log')
        if len(calcdirs) == 0:
            print "WARNING: No log file found for: %s" % (self.species_name)
            calc_params = {'pw': None, 'xc': None, 'kpts': None, 'psp': None}
            return calc_params
        #Get parameters from longest log file
        #size = 0
        #for i, cd in enumerate(calcdirs):
        #    if  os.stat(cd).st_size  > size:
        #        j = i
        #        size = os.stat(cd).st_size
        j = 0
        log_file = open(calcdirs[j], 'r').readlines()
        inpdirs = glob(directory + '/*/pw.inp')
        inp_file = open(inpdirs[j], 'r')

        calc_params = {}
        calc_params['psp'] = {}
        for i, line in enumerate(log_file):
            line = line.strip()
            #XC
            if line.startswith('Exchange-correlation'):
                if 'BEEF' in line:
                    xc = 'BEEF'
                elif 'RPBE' in line:
                    xc = 'RPBE'
                elif 'PBE' in line:
                    xc = 'PBE'
            #PSP
            if line.startswith('PseudoPot.'):
                elem = line.split()[4]
                md5 = log_file[i + 2].split()[-1]
                calc_params['psp'][elem] = md5
            #PW
            if line.startswith('kinetic-energy cutoff'):
                pw = float(re.findall("\d+\.\d+", line)[0])
                pw *= 13.61  #ryd to ev
                pw = str(int(pw))  #round pw and turn to str
        calc_params['xc'] = xc
        calc_params['pw'] = pw
        #K-PTS
        inplines = inp_file.readlines()
        kpts = inplines[-1].split()
        calc_params['kpts'] = ''.join(kpts[0:3])

        if len(calc_params) < 3:
            print "ERROR: Unable to extract calculator parameters automatically, user can supply manually."
            exit()

        inp_file.close()
        return calc_params

    def beef_reader(self):
        directory = '/'.join(self.traj_loc.split('/')[0:-1])
        if os.path.exists(directory + '/ensemble.pkl') == False or os.stat(
                directory + '/ensemble.pkl').st_size == 0:
            print "Warning: No beef ensemble for %s" % (directory)
            return
        beef_array = pickle.load(open(directory + '/ensemble.pkl', 'r'))
        #Check if BEEF normalized around zero or not
        #Correct????
        if abs(np.mean(beef_array)) < 100:
            beef_array += read(self.traj_loc).get_potential_energy()
        return beef_array

    def vibs_reader(self, vib_loc):
        f = open(vib_loc + '/myjob.out', 'r')
        vibenergies = []
        for line in f:
            try:
                temp = line.replace('.', '')
                temp = temp.replace(' ', '')
                temp = temp.replace('i', '')
                float(temp)
            except ValueError:
                continue
            num, meV, inv_cm, = line.split()
            if 'i' in meV:
                meV = 7
            vibenergies.append(float(meV))
        #convert from meV to eV for each mode
        vibenergies[:] = [round(ve / 1000., 4) for ve in vibenergies]
        if vibenergies == []:
            print "Warning: No vibrational energies for %s" % (self.traj_loc)
        return vibenergies

    def get_Gcorr(self, T, P=101325, verbose=False):
        if self.species_type == 'slab' or self.species_type == 'bulk':
            Gcorr = 0
        elif self.species_type == 'gas':
            if len(self.vibs) == 0:
                print "ERROR: No vibrations for %s" % (self.traj_loc)
                exit()
            Gcorr = self.gibbs.get_gibbs_energy(T, P, verbose=verbose)
        elif self.species_type == 'adsorbate':
            if len(self.vibs) == 0:
                print "ERROR: No vibrations for %s" % (self.traj_loc)
                exit()
            Gcorr = self.gibbs.get_helmholtz_energy(T, verbose=verbose)
        else:
            print "Error: ambiguous species type for function get_dGcorr.  Should be 'gas' or 'adsorbate'."
            exit()

        return Gcorr

    def get_Hcorr(self, T, verbose=False):
        if self.species_type == 'slab' or self.species_type == 'bulk':
            Hcorr = 0
        elif self.species_type == 'gas':
            Hcorr = self.gibbs.get_enthalpy(T, verbose=verbose)
        elif self.species_type == 'adsorbate':
            Hcorr = self.gibbs.get_internal_energy(T, verbose=verbose)
        return Hcorr
######################################################

## more information here: https://wiki.fysik.dtu.dk/ase/ase/thermochemistry/thermochemistry.html

name = 'example_ads'

#electronic energy in eV
energy = -21861.531796 

#vibrational energies in meV
vibenergies = [60.5, 77.1, 314.2]

#convert from meV to eV for each mode
vibenergies[:] = [ve/1000. for ve in vibenergies]

#list of temperatures
temperatures = [300]

#operating pressure
pressures = [101325]

f=open(name+'_free.energy','w')
for temperature in temperatures:
    for pressure in pressures:
        gibbs = HarmonicThermo(vib_energies = vibenergies, electronicenergy = energy)
        freeenergy = gibbs.get_gibbs_energy(temperature,pressure)
        f.write('Temperature: '+str(temperature)+'\t'+'Pressure: '+str(pressure)+'\t'+'Free energy: '+str(freeenergy)+'\n')
        

f.close