Пример #1
0
    def get_SoR(self, Ts, P=1., verbose=False):
        """Calculate the dimensionless entropy.

        Parameters:
            Ts : float or (N,) `numpy.ndarray`_
                Temperature(s) in K
            P : float, optional
                Pressure in atm. Default is 1 atm.
            verbose : bool
                Whether a table breaking down each contribution should be printed
        Returns:
            SoR : float or (N,) `numpy.ndarray`_
                Dimensionless entropy (S/R) at the specified temperature and pressure
        """
        try:
            iter(Ts)
        except TypeError:
            SoR = self.model.get_entropy(
                Ts,
                pressure=P * c.convert_unit(from_='atm', to='Pa'),
                verbose=verbose) / c.R('eV/K')
        else:
            SoR = np.zeros_like(Ts)
            for i, T in enumerate(Ts):
                SoR[i] = self.model.get_entropy(
                    T,
                    pressure=P * c.convert_unit(from_='atm', to='Pa'),
                    verbose=verbose) / c.R('eV/K')
        return SoR
Пример #2
0
    def get_Vm(self, T=c.T0('K'), P=c.P0('bar'), gas_phase=True):
        """Calculates the molar volume of a van der Waals gas

        Parameters
        ----------
            T : float, optional
                Temperature in K. Default is standard temperature
            P : float, optional
                Pressure in bar. Default is standard pressure
            gas_phase : bool, optional
                Relevant if system is in vapor-liquid equilibrium. If True, 
                return the larger volume (gas phase). If False, returns the 
                smaller volume (liquid phase).
        Returns
        -------
            Vm : float
                Volume in m3
        """
        P_SI = P * c.convert_unit(from_='bar', to='Pa')
        Vm = np.roots([
            P_SI, -(P_SI * self.b + c.R('J/mol/K') * T), self.a,
            -self.a * self.b
        ])
        real_Vm = np.real([Vm_i for Vm_i in Vm if np.isreal(Vm_i)])
        if gas_phase:
            return np.max(real_Vm)
        else:
            return np.min(real_Vm)
Пример #3
0
    def from_critical(cls, Tc, Pc):
        """Creates the van der Waals object from critical temperature and 
        pressure

        Parameters
        ----------
            Tc : float
                Critical temperature in K
            Pc : float
                Critical pressure in bar
        Returns
        -------
            vanDerWaalsEOS : vanDerWaalsEOS object
        """
        Pc_SI = Pc * c.convert_unit(from_='bar', to='Pa')
        a = 27. / 64. * (c.R('J/mol/K') * Tc)**2 / Pc_SI
        b = c.R('J/mol/K') * Tc / 8. / Pc_SI
        return cls(a=a, b=b)
Пример #4
0
    def get_SoR(self, Ts, verbose=False):
        """Calculate dimensionless entropy at a given temperature.

        Args:
            Ts (float or numpy array): Temperature(s) in K
            verbose (bool): Flag to print each contribution to entropy
        Returns:
            SoR (float or numpy array): Dimensionless entropy (S/R)
        """
        try:
            iter(Ts)
        except TypeError:
            SoR = self.model.get_entropy(Ts, verbose) / c.R('eV/K')
        else:
            SoR = np.zeros_like(Ts)
            for i, T in enumerate(Ts):
                SoR[i] = self.model.get_entropy(T, verbose) / c.R('eV/K')
        return SoR
Пример #5
0
    def get_Tc(self):
        """Calculates the critical temperature

        Returns
        -------
            Tc : float
                Critcial temperature in K
        """
        return 8. * self.a / 27. / self.b / c.R('J/mol/K')
Пример #6
0
    def get_SoR(self, Ts, P=1., verbose=False):
        """Calculate the dimensionless entropy.

        Parameters:
            Ts : float or (N,) `numpy.ndarray`_
                Temperature(s) in K
            P : float
                Pressure in atm. Default is 1 atm
            verbose : bool
                Whether a table breaking down each contribution should be printed
        Returns:
            SoR : float or (N,) `numpy.ndarray`_
                Dimensionless entropy (S/R)
        """
        try:
            iter(Ts)
        except TypeError:
            SoR = self.model.get_entropy(Ts, verbose)/c.R('eV/K')
        else:
            SoR = np.zeros_like(Ts)
            for i, T in enumerate(Ts):
                SoR[i] = self.model.get_entropy(T, verbose)/c.R('eV/K')
        return SoR
Пример #7
0
    def setUp(self):
        unittest.TestCase.setUp(self)
        H2_thermo = BaseThermo(name='H2',
                               phase='G',
                               elements={'H': 2},
                               thermo_model=IdealGasThermo,
                               T_ref=c.T0('K'),
                               HoRT_ref=0.,
                               vib_energies=np.array([4306.1793]) *
                               c.c('cm/s') * c.h('eV s'),
                               potentialenergy=-6.7598,
                               geometry='linear',
                               symmetrynumber=2,
                               spin=0,
                               atoms=molecule('H2'))

        H2O_thermo = BaseThermo(
            name='H2O',
            phase='G',
            elements={
                'H': 2,
                'O': 1
            },
            thermo_model=IdealGasThermo,
            T_ref=c.T0('K'),
            HoRT_ref=-241.826 / (c.R('kJ/mol/K') * c.T0('K')),
            vib_energies=np.array([3825.434, 3710.264, 1582.432]) *
            c.c('cm/s') * c.h('eV s'),
            potentialenergy=-14.2209,
            geometry='nonlinear',
            symmetrynumber=2,
            spin=0,
            atoms=molecule('H2O'))

        O2_thermo = BaseThermo(name='H2O',
                               phase='G',
                               elements={'O': 2},
                               thermo_model=IdealGasThermo,
                               T_ref=c.T0('K'),
                               HoRT_ref=0.,
                               vib_energies=np.array([2205.]) * c.c('cm/s') *
                               c.h('eV s'),
                               potentialenergy=-9.86,
                               geometry='linear',
                               symmetrynumber=2,
                               spin=1,
                               atoms=molecule('O2'))
        self.references = References(
            references=[H2_thermo, H2O_thermo, O2_thermo])
Пример #8
0
    def get_V(self, T=c.T0('K'), P=c.P0('bar'), n=1.):
        """Calculates the volume of an ideal gas

        Parameters
        ----------
            T : float, optional
                Temperature in K. Default is standard temperature
            P : float, optional
                Pressure in bar. Default is standard pressure
            n : float, optional
                Number of moles (in mol). Default is 1 mol
        Returns
        -------
            V : float
                Volume in m3
        """
        return n * c.R('m3 bar/mol/K') * T / P
Пример #9
0
    def get_T(self, V=c.V0('m3'), P=c.P0('bar'), n=1.):
        """Calculates the volume of an ideal gas

        Parameters
        ----------
            V : float, optional
                Volume in m3. Default is standard volume
            P : float, optional
                Pressure in bar. Default is standard pressure
            n : float, optional
                Number of moles (in mol). Default is 1 mol
        Returns
        -------
            T : float
                Temperature in K
        """
        return P * V / c.R('m3 bar/mol/K') / n
Пример #10
0
    def get_n(self, V=c.V0('m3'), P=c.P0('bar'), T=c.T0('K')):
        """Calculates the volume of an ideal gas

        Parameters
        ----------
            V : float, optional
                Volume in m3. Default is standard volume
            P : float, optional
                Pressure in bar. Default is standard pressure
            T : float, optional
                Temperature in K. Default is standard temperature
        Returns
        -------
            n : float
                Number of moles in mol
        """
        return P * V / c.R('m3 bar/mol/K') / T
Пример #11
0
    def get_V(self, T, P):
        """Calculates the molar volume of an ideal gas at T and P

        :math:`V_m=\\frac{RT}{P}`

        Parameters
        ----------
            T : float
                Temperature in K
            P : float
                Pressure in bar
        Returns
        -------
            V : float
                Molar volume in m3
        """
        return T * c.R('J/mol/K') / (P * c.convert_unit(from_='bar', to='Pa'))
Пример #12
0
    def get_SoR(self, temperature, pressure=1.0, verbose=False):
        """Calculate the dimensionless entropy.

        Parameters:
            temperature (float): Temperature(s) in K
            pressure (float, optional): Pressure in atm. Default is 1 atm.
            verbose (bool): Print a table breaking down each contribution
        """
        if self.specie_type == 'ideal gas':
            entropy = self.model.get_entropy(
                temperature,
                pressure=pressure * c.convert_unit(from_='atm', to='Pa'),
                verbose=verbose)
        else:
            entropy = self.model.get_entropy(temperature, verbose=verbose)

        return entropy / c.R('eV/K')
Пример #13
0
    def get_P(self, T=c.T0('K'), V=c.V0('m3'), n=1.):
        """Calculates the pressure of an ideal gas

        Parameters
        ----------
            T : float, optional
                Temperature in K. Default is standard temperature
            V : float, optional
                Volume in m3. Default is standard volume
            n : float, optional
                Number of moles (in mol). Default is 1 mol
        Returns
        -------
            P : float
                Pressure in bar
        """
        return n * c.R('m3 bar/mol/K') * T / V
Пример #14
0
    def get_P(self, T=c.T0('K'), V=c.V0('m3'), n=1.):
        """Calculates the pressure of a van der Waals gas

        Parameters
        ----------
            T : float, optional
                Temperature in K. Default is standard temperature
            V : float, optional
                Volume in m3. Default is standard volume
            n : float, optional
                Number of moles (in mol). Default is 1 mol
        Returns
        -------
            P : float
                Pressure in bar
        """
        Vm = V / n
        return (c.R('J/mol/K')*T/(Vm - self.b) - self.a*(1./Vm)**2) \
               *c.convert_unit(from_='Pa', to='bar')
Пример #15
0
    def get_T(self, V=c.V0('m3'), P=c.P0('bar'), n=1.):
        """Calculates the volume of a van der Waals gas

        Parameters
        ----------
            V : float, optional
                Volume in m3. Default is standard volume
            P : float, optional
                Pressure in bar. Default is standard pressure
            n : float, optional
                Number of moles (in mol). Default is 1 mol
        Returns
        -------
            T : float
                Temperature in K
        """
        Vm = V / n
        return (P*c.convert_unit(from_='bar', to='Pa') + self.a/Vm**2) \
               *(Vm - self.b)/c.R('J/mol/K')
Пример #16
0
    def plot_statmech_and_empirical(self,
                                    T_low=None,
                                    T_high=None,
                                    Cp_units=None,
                                    H_units=None,
                                    S_units=None,
                                    G_units=None):
        """Plots the thermodynamic profiles between ``T_low`` and ``T_high``
        using empirical relationship

        Parameters
        ----------
            T_low : float
                Lower temperature in K. If not specified, ``T_low``
                attribute used
            T_high : float
                Upper temperature in K. If not specified, ``T_high``
                attribute used
            Cp_units : str
                Units to plot heat capacity. See ``PyMuTT.constants.R`` for
                accepted units. If not specified, dimensionless units used.
            H_units : str
                Units to plot enthalpy. See ``PyMuTT.constants.R`` for accepted
                units but omit the '/K' (e.g. J/mol). If not specified,
                dimensionless units used.
            S_units : str
                Units to plot entropy. See ``PyMuTT.constants.R`` for accepted
                units. If not specified, dimensionless units used.
            G_units : str
                Units to plot Gibbs free energy. See ``PyMuTT.constants.R``
                for accepted units but omit the '/K' (e.g. J/mol). If not
                specified, dimensionless units used.
        Returns
        -------
            figure : `matplotlib.figure.Figure`_
                Figure
            axes : tuple of `matplotlib.axes.Axes.axis`_
                Axes of the plots.
                0. Cp
                1. H
                2. S
                3. G

        .. _`matplotlib.figure.Figure`: https://matplotlib.org/api/_as_gen/matplotlib.figure.Figure.html
        .. _`matplotlib.axes.Axes.axis`: https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.axis.html
        """
        if T_low is None:
            T_low = self.T_low
        if T_high is None:
            T_high = self.T_high
        T = np.linspace(T_low, T_high)

        f, ax = plt.subplots(4, sharex=True)
        '''
        Heat Capacity
        '''
        ax[0].set_title('Specie: {}'.format(self.name))
        T, Cp_plot_statmech, Cp_plot_empirical = self.compare_CpoR(T=T)
        if Cp_units is None:
            ax[0].set_ylabel('Cp/R')
        else:
            ax[0].set_ylabel('Cp ({})'.format(Cp_units))
            Cp_plot_statmech = Cp_plot_statmech * c.R(Cp_units)
            Cp_plot_empirical = Cp_plot_empirical * c.R(Cp_units)

        ax[0].plot(T, Cp_plot_statmech, 'r-', label='Stat Mech Model')
        ax[0].plot(T, Cp_plot_empirical, 'b-', label='Empirical Model')
        ax[0].legend()
        '''
        Enthalpy
        '''
        T, H_plot_statmech, H_plot_empirical = self.compare_HoRT(T=T)

        if H_units is None:
            ax[1].set_ylabel('H/RT')
        else:
            ax[1].set_ylabel('H ({})'.format(H_units))
            H_plot_statmech = H_plot_statmech *\
                c.R('{}/K'.format(H_units))*T
            H_plot_empirical = H_plot_empirical *\
                c.R('{}/K'.format(H_units))*T
        ax[1].plot(T, H_plot_statmech, 'r-')
        ax[1].plot(T, H_plot_empirical, 'b-')
        '''
        Entropy
        '''
        T, S_plot_statmech, S_plot_empirical = self.compare_SoR(T=T)
        if S_units is None:
            ax[2].set_ylabel('S/R')
        else:
            ax[2].set_ylabel('S ({})'.format(S_units))
            S_plot_statmech = S_plot_statmech * c.R(S_units)
            S_plot_empirical = S_plot_empirical * c.R(S_units)
        ax[2].plot(T, S_plot_statmech, 'r-')
        ax[2].plot(T, S_plot_empirical, 'b-')
        '''
        Gibbs energy
        '''
        ax[3].set_xlabel('Temperature (K)')
        T, G_plot_statmech, G_plot_empirical = self.compare_GoRT(T=T)
        if G_units is None:
            ax[3].set_ylabel('G/RT')
        else:
            ax[3].set_ylabel('G ({})'.format(G_units))
            G_plot_statmech = G_plot_statmech *\
                c.R('{}/K'.format(G_units))*T
            G_plot_empirical = G_plot_empirical *\
                c.R('{}/K'.format(G_units))*T
        ax[3].plot(T, G_plot_statmech, 'r-')
        ax[3].plot(T, G_plot_empirical, 'b-')

        return f, ax
Пример #17
0
    def plot_empirical(self,
                       T_low=None,
                       T_high=None,
                       Cp_units=None,
                       H_units=None,
                       S_units=None,
                       G_units=None):
        """Plot the thermodynamic profiles between ``T_low`` and ``T_high``
        using empirical relationship

        Parameters:
            T_low : float
                Lower temperature in K. If not specified, ``T_low`` attribute
                used.
            T_high : float
                Upper temperature in K. If not specified, ``T_high`` attribute
                used.
            Cp_units : str
                Units to plot heat capacity. See ``PyMuTT.constants.R`` for
                accepted units. If not specified, dimensionless units used.
            H_units : str
                Units to plot enthalpy. See ``PyMuTT.constants.R`` for accepted
                units but omit the '/K' (e.g. J/mol). If not specified,
                dimensionless units used.
            S_units : str
                Units to plot entropy. See ``PyMuTT.constants.R`` for accepted
                units. If not specified, dimensionless units used.
            G_units : str
                Units to plot Gibbs free energy. See ``PyMuTT.constants.R`` for
                accepted units but omit the '/K' (e.g. J/mol). If not specified,
                dimensionless units used.

        Returns:
            figure : `matplotlib.figure.Figure`_
                Figure
            axes : tuple of `matplotlib.axes.Axes.axis`_
                Axes of the plots.
                0. Cp
                1. H
                2. S
                3. G
        """
        if T_low is None:
            T_low = self.T_low
        if T_high is None:
            T_high = self.T_high
        Ts = np.linspace(T_low, T_high)

        f, ax = plt.subplots(4, sharex=True)
        '''
        Heat Capacity
        '''
        ax[0].set_title('Specie: {}'.format(self.name))
        Cp_plot = np.array(map(self.get_CpoR, Ts))
        if Cp_units is None:
            ax[0].set_ylabel('Cp/R')
        else:
            ax[0].set_ylabel('Cp ({})'.format(Cp_units))
            Cp_plot *= c.R(Cp_units)
        ax[0].plot(Ts, Cp_plot, 'r-')
        '''
        Enthalpy
        '''
        H_plot = np.array(map(self.get_HoRT, Ts))
        if H_units is None:
            ax[1].set_ylabel('H/RT')
        else:
            ax[1].set_ylabel('H ({})'.format(H_units))
            H_plot *= c.R('{}/K'.format(H_units)) * Ts
        ax[1].plot(Ts, H_plot, 'g-')
        '''
        Entropy
        '''
        S_plot = np.array(map(self.get_SoR, Ts))
        if S_units is None:
            ax[2].set_ylabel('S/R')
        else:
            ax[2].set_ylabel('S ({})'.format(S_units))
            S_plot *= c.R(S_units)
        ax[2].plot(Ts, S_plot, 'b-')
        '''
        Gibbs energy
        '''
        ax[3].set_xlabel('Temperature (K)')
        G_plot = np.array(map(self.get_GoRT, Ts))
        if G_units is None:
            ax[3].set_ylabel('G/RT')
        else:
            ax[3].set_ylabel('G ({})'.format(G_units))
            G_plot *= c.R('{}/K'.format(G_units)) * Ts
        ax[3].plot(Ts, G_plot, 'k-')

        return f, ax
Пример #18
0
 def test_R(self):
     self.assertEqual(c.R('J/mol/K'), 8.3144598)
     with self.assertRaises(KeyError):
         c.R('arbitrary unit')
Пример #19
0
 def test_get_GoRT(self):
     expected_GoRT_CO2 = \
         self.CO2_ASE.get_gibbs_energy(temperature=self.T0, pressure=self.P0,
            verbose=False)/c.R('eV/K')/self.T0
     calc_GoRT_CO2 = self.CO2_PyMuTT.get_GoRT(T=self.T0, V=self.V0)
     self.assertTrue(np.isclose(expected_GoRT_CO2, calc_GoRT_CO2))
Пример #20
0
 def test_get_SoR(self):
     expected_SoR_CO2 = \
         self.CO2_ASE.get_entropy(temperature=self.T0, pressure=self.P0,
             verbose=False)/c.R('eV/K')
     calc_SoR_CO2 = self.CO2_PyMuTT.get_SoR(T=self.T0, V=self.V0)
     self.assertTrue(np.isclose(expected_SoR_CO2, calc_SoR_CO2))
Пример #21
0
 def test_get_HoRT(self):
     expected_HoRT_CO2 = \
         self.CO2_ASE.get_enthalpy(temperature=self.T0, verbose=False) \
         /c.R('eV/K')/self.T0
     calc_HoRT_CO2 = self.CO2_PyMuTT.get_HoRT(T=self.T0)
     self.assertTrue(np.isclose(expected_HoRT_CO2, calc_HoRT_CO2))
Пример #22
0
import numpy as np
import matplotlib.pyplot as plt
from PyMuTT import constants as c
from PyMuTT.models.empirical.nasa import Nasa

# Gas phase heat capacity data (in J/mol/K) for CH3OH from NIST
# https://webbook.nist.gov/cgi/cbook.cgi?ID=C67561&Units=SI&Mask=1#Thermo-Gas
Ts = np.array([50, 100, 150, 200, 273.15, 298.15, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1750, 2000, 2250, 2500, 2750, 3000])
Cp = np.array([34.00, 36.95, 38.64, 39.71, 42.59, 44.06, 44.17, 51.63, 59.7, 67.19, 73.86, 79.76, 84.95, 89.54, 93.57, 97.12, 100.24, 102.98, 105.4, 110.2, 113.8, 116.5, 118.6, 120, 121])
CpoR = Cp/c.R('J/mol/K')

#Enthalpy of Formation for CH3OH (in kJ/mol) from NIST
T_ref = c.T0('K')
H_ref = -205.
HoRT_ref = H_ref/c.R('kJ/mol/K')/T_ref
#Standard molar entropy (in J/mol/K) from Wikipedia, https://en.wikipedia.org/wiki/Methanol_(data_page)
S_ref = 239.9
SoR_ref = S_ref/c.R('J/mol/K')

#Units to plot the figure
Cp_units = 'J/mol/K'
H_units = 'kJ/mol'
S_units = 'J/mol/K'
G_units = 'kJ/mol'

#Input the experimental data and fitting to a NASA polynomial
CH3OH_nasa = Nasa(name ='CH3OH', Ts=Ts, CpoR=CpoR, T_ref=T_ref, HoRT_ref=HoRT_ref, SoR_ref=SoR_ref)

#Compare the Nasa polynomial to the input data
fig, axes = CH3OH_nasa.plot_empirical(Cp_units=Cp_units, H_units=H_units, S_units=S_units, G_units=G_units)
axes[0].plot(Ts, Cp, 'ko')
    def setUp(self):
        unittest.TestCase.setUp(self)

        H2_thermo = Reference(name='H2',
                              phase='G',
                              elements={'H': 2},
                              T_ref=c.T0('K'),
                              HoRT_ref=0.,
                              statmech_model=StatMech,
                              trans_model=trans.IdealTrans,
                              n_degrees=3,
                              vib_model=vib.HarmonicVib,
                              elec_model=elec.IdealElec,
                              rot_model=rot.RigidRotor,
                              vib_wavenumbers=np.array([4306.1793]),
                              potentialenergy=-6.7598,
                              geometry='linear',
                              symmetrynumber=2,
                              spin=0,
                              atoms=molecule('H2'))

        H2O_thermo = Reference(
            name='H2O',
            phase='G',
            elements={
                'H': 2,
                'O': 1
            },
            T_ref=c.T0('K'),
            HoRT_ref=-241.826 / (c.R('kJ/mol/K') * c.T0('K')),
            statmech_model=StatMech,
            trans_model=trans.IdealTrans,
            n_degrees=3,
            vib_model=vib.HarmonicVib,
            elec_model=elec.IdealElec,
            rot_model=rot.RigidRotor,
            vib_wavenumbers=np.array([3825.434, 3710.264, 1582.432]),
            potentialenergy=-14.2209,
            geometry='nonlinear',
            symmetrynumber=2,
            spin=0,
            atoms=molecule('H2O'))

        O2_thermo = Reference(name='H2O',
                              phase='G',
                              elements={'O': 2},
                              T_ref=c.T0('K'),
                              HoRT_ref=0.,
                              statmech_model=StatMech,
                              trans_model=trans.IdealTrans,
                              n_degrees=3,
                              vib_model=vib.HarmonicVib,
                              elec_model=elec.IdealElec,
                              rot_model=rot.RigidRotor,
                              vib_wavenumbers=np.array([2205.]),
                              potentialenergy=-9.86,
                              geometry='linear',
                              symmetrynumber=2,
                              spin=1,
                              atoms=molecule('O2'))
        self.references = References(
            references=[H2_thermo, H2O_thermo, O2_thermo])