Beispiel #1
0
    def get_internal_energy(self,
                            temperature,
                            electronic_energy=0,
                            verbose=False):
        """Returns the internal energy of an adsorbed molecule.

        Parameters
        ----------
        temperature : numeric
            temperature in K
        electronic_energy : numeric
            energy in eV
        verbose : boolean
            whether to print ASE thermochemistry output

        Returns
        -------
        internal_energy : numeric
            Internal energy in eV
        """
        thermo_object = HarmonicThermo(vib_energies=self.vib_energies,
                                       potentialenergy=electronic_energy)
        self.internal_energy = thermo_object.get_internal_energy(
            temperature=temperature, verbose=verbose)
        return (self.internal_energy)
Beispiel #2
0
def thermo(vib_path, temp):
    """Calculate vibrational contributions to U, ZPE, Cv, and S

    vib_path (str): path to vibrational frequency data file (cm^-1 units)
    """
    # Read in vibrational frequencies (assumes cm^-1 units)
    vib = np.loadtxt(vib_path)

    # convert from cm-1 to eV
    vib_energies = vib * ase.units.invcm

    # initialize Harmonic-oscillator-approximated thermochemistry object
    thermo = HarmonicThermo(vib_energies)

    # Calculate U, ZPE, Cv, S, and ST.
    # Note that when E_pot = 0, U = ZPE + Cv
    u = thermo.get_internal_energy(temp, verbose=False)
    zpe = thermo.get_ZPE_correction()
    cv = u - zpe
    s = thermo.get_entropy(temp, verbose=False)
    ts = s * temp

    # calculate the G correction term
    g_correction = zpe + cv - ts

    # convert the results into a dictionary
    results = {
        'E_ZPE': zpe,
        'Cv_harm (0->T)': cv,
        'U': u,
        'S_harm': s,
        'T*S': ts,
        f'G_correction @ {temp} K': g_correction
    }

    # print the results in a nice format
    center = 50
    line = '=' * center
    print(line)
    print(f'Harmonic Thermochem Results at T = {temp} K'.center(center))
    print(line)

    # iteratively print each result in table format
    for name in results:
        lbl = 'eV/K' if name == 'S_harm' else 'eV'
        space = center - len(name) - 5
        val = results[name]
        print(f'{name}{val:>{space}.9f} {lbl}')
    print(line)
Beispiel #3
0
    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)
Beispiel #4
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