Пример #1
0
	def fit_shomate_species(cls, symbol, T, Cp, H0, S0, T_ref = c.T0('K'), elements = None):
		"""
		Derives the shomate species from fitting the heat capacity (J/mol/K) and temperature (K) data and including the formation of enthalpy (kJ/mol) and entropy (J/mol/K).

		Paramters
		---------
			symbol - str
				Name of shomate polynomial
			T - (N,) ndarray
				Temperatures (K)
			Cp - (N,) ndarray
				Heat capacities corresponding to T (J/mol/K)
			H0 - float
				Enthalpy at reference temperature (kJ/mol)
			S0 - float
				Entropy at reference temperature (J/mol/K)
			T_ref - float
				Reference temperature (K)
			elements - dict
				Stoichiometric make up of species. Keys should be elements.
				e.g. H2O = {'H': 2, 'O': 1}
		Returns
		-------
			shomate - Shomate object
		"""
		T_low = min(T)
		T_high = max(T)
		t = np.array(T)/1000.
		[a, pcov] = curve_fit(_shomate_Cp, t, np.array(Cp))
		a = np.append(a, [0., 0., 0.])
		a[5] = H0 - _get_HoRT(T = T_ref, a = a)*c.R('kJ/mol/K')*T_ref
		a[6] = S0 - _get_SoR(T = T_ref, a = a)*c.R('J/mol/K')
		a[7] = - _get_HoRT(T = c.T0('K'), a = a)*c.R('kJ/mol/K')*c.T0('K')
		return cls(symbol = symbol, T_low = T_low, T_high = T_high, a = np.array(a), elements = elements)
Пример #2
0
	def read_fund_csv(symbol, csv_path, print_graph = False):
		"""
		Reads a csv file for data that will be fed into function fit_shomate_species.

		Parameters
		----------
			symbol - str
				Name of the shomate polynomial
			csv_path - str
				Path to the csv file containing the values
			print_graph - bool
				Whether or not to show the thermodynamic quantities at the range of temperatures
		Returns
			shomate - Shomate object
		"""
		H0_S0_read = False
		T = []
		Cp = []
		
		print(("Reading from file: %s" % csv_path))
		with open(csv_path, 'r') as csv_file:
			for line in csv_file:
				if line[0] != '!':
					#Split data and remove unnecessary characters
					data = line.split(',')
					T.append(float(data[0]))
					Cp.append(float(data[1]))
					if len(data) > 2 and not H0_S0_read:
						H0 = float(data[2])
						S0 = float(data[3])
						H0_S0_read = True				

		shomate = Shomate.fit_shomate_species(symbol, T, Cp, H0, S0)
		if print_graph:
			T_range = np.linspace(shomate.T_low, shomate.T_high)
			Cp_fit = shomate.get_CpoR(T_range)*c.R('J/mol/K')
			H_fit = shomate.get_HoRT(T_range)*T_range*c.R('kJ/mol/K')
			S_fit = shomate.get_SoR(T_range)*c.R('J/mol/K')
			plt.figure()
			plt.subplot(311)
			plt.plot(T, Cp, 'ro', T_range, Cp_fit, 'b-')
			plt.legend(['NIST Data', 'Fit'])
			plt.xlabel('Temperature (K)')
			plt.ylabel('Cp (J/mol/K)')
			
			plt.subplot(312)
			plt.plot(T_range, H_fit)
			plt.xlabel('Temperature (K)')
			plt.ylabel('H (kJ/mol/K)')

			plt.subplot(313)
			plt.plot(T_range, S_fit)
			plt.xlabel('Temperature (K)')
			plt.ylabel('S (J/mol/K)')
		return shomate
Пример #3
0
    def plot_thermo(self, T_low=None, T_high=None, units=None):
        """
        Plots the heat capacity, enthalpy and entropy in the temperature range specified.
        Parameters
        ----------
            T_low - float
                Lower bound to plot temperature (K). If not specified then the T_low attribute for the species is used.
            T_high - float
                Higher bound to plot temperatures (K). If not specified then the T_high attribute for the species is used.
            units - string
                Controls the units used based on the molar gas constant (e.g. J/mol/K, kcal/mol/K, 'eV/K'). 
                If not specified then dimensionless units are used.
        """
        import matplotlib.pyplot as plt

        if T_low == None:
            T_low = self.T_low
        if T_high == None:
            T_high = self.T_high

        T = np.linspace(T_low, T_high)
        Cp = self.get_CpoR(T)
        H = self.get_HoRT(T)
        S = self.get_SoR(T)
        if units is not None:
            Cp = Cp * c.R(units)
            H = H * c.R(units) * T
            S = S * c.R(units)

        plt.figure()
        plt.subplot(311)
        plt.plot(T, Cp, 'r-')
        if units is None:
            plt.ylabel('Cp/R')
        else:
            plt.ylabel('Cp (%s)' % units)
        plt.xlabel('T (K)')
        plt.title('Plots for %s using NASA polynomials.' % self.symbol)

        plt.subplot(312)
        plt.plot(T, H, 'b-')
        if units is None:
            plt.ylabel('H/RT')
        else:
            plt.ylabel('H (%s)' % units.replace('/K', ''))
        plt.xlabel('T (K)')

        #Entropy graph
        plt.subplot(313)
        plt.plot(T, S, 'k-')
        if units is None:
            plt.ylabel('S/R')
        else:
            plt.ylabel('S (%s)' % units)
        plt.xlabel('T (K)')
Пример #4
0
	def get_HoRT(self, T, H_correction = False, verbose = True):
		"""
		Calculate the dimensionless enthalpy for a single temperature.
		
		Parameters
		----------
			T - float
				Temperature
			H_correction - bool
				If set to True, subtracts the enthalpy at T = 298 K. Equivalent to H parameter on NIST
			verbose - bool
				Whether or not more information should be provided
		Returns
		-------
			HoRT - float
				Dimensionless enthalpy at a single temperature (i.e. H/RT where R is the molar gas constant)
		"""		
		t = T/1000.
		if H_correction:
			T_arr = np.array([t, t ** 2 / 2, t ** 3 / 3, t ** 4 / 4, -1/t, 1., 0., 1.])
		else:			
			T_arr = np.array([t, t ** 2 / 2, t ** 3 / 3, t ** 4 / 4, -1/t, 1., 0., 0.])
		if verbose:
			if T < self.T_low:
				print(("Warning. Input temperature (%f) lower than T_low (%f) for species %s" % (T, self.T_low, self.symbol)))
			elif T > self.T_high:
				print(("Warning. Input temperature (%f) higher than T_high (%f) for species %s" % (T, self.T_high, self.symbol)))
		return np.dot(T_arr, self.a)/(c.R('kJ/mol/K')*T)
Пример #5
0
    def get_A_from_sticking_coefficient(T, thermos):

        #Find gas-phase reactant
        for species, coefficient in self.stoichiometry.items():
            if coefficient < 0 and thermos[species].is_gas:
                #Calculate molecular weight
                MW = c.get_molecular_weight(thermos[species].elements)
                A = self.s * np.sqrt(c.R('J/mol/K') * T / (2 * np.pi * MW))
                return A
Пример #6
0
def _get_SoR(T, a):
	"""
	Internal function to calculate dimensionless entropy.
	
	Parameters
	----------
		T - float or (N,) ndarray
			Temperature(s)
		a - (8,) ndarray
			Shomate parameters
	Returns
	-------
		HoRT - float or (N,) ndarray
			Dimensionless entropy corresponding to T (i.e. S/R where R is the molar gas constant)
	"""
	t = T/1000.		
	T_arr = np.array([np.log(t), t, t ** 2 / 2., t ** 3 / 3., -0.5 * ( 1 / t ) ** 2, 0., 1., 0.])
	return np.dot(T_arr, a)/c.R('J/mol/K')
Пример #7
0
def _get_HoRT(T, a, H_correction = False):
	"""
	Internal function to calculate dimensionless enthalpy.
	
	Parameters
	----------
		T - float or (N,) ndarray
			Temperature(s)
		a - (8,) ndarray
			Shomate parameters
		H_correction - bool
			If set to True, subtracts the enthalpy at T = 298 K. Equivalent to H parameter on NIST
	Returns
	-------
		HoRT - float or (N,) ndarray
			Dimensionless enthalpy corresponding to T (i.e. H/RT where R is the molar gas constant)
	"""
	t = T/1000.
	T_arr = np.array([t, t ** 2 / 2, t ** 3 / 3, t ** 4 / 4, -1/t, 1., 0., 1.])
	return np.dot(T_arr, a)/(c.R('kJ/mol/K')*T)
Пример #8
0
	def get_SoR(self, T, verbose = True):
		"""
		Calculates the dimensionless entropy for a single temperature.
		
		Parameters
		----------
			T - float or (N,) ndarray
				Temperature(s)
			verbose - bool
				Whether or not more information should be provided
		Returns
		-------
			SoR - float
				Dimensionless entropy corresponding to T (i.e. S/R where R is the molar gas constant)
		""" 
		t = T/1000.		
		T_arr = np.array([np.log(t), t, t ** 2 / 2., t ** 3 / 3., -0.5 * ( 1 / t ) ** 2, 0., 1., 0.])
		if verbose:
			if T < self.T_low:
				print(("Warning. Input temperature (%f) lower than T_low (%f) for species %s" % (T, self.T_low, self.symbol)))
			elif T > self.T_high:
				print(("Warning. Input temperature (%f) higher than T_high (%f) for species %s" % (T, self.T_high, self.symbol)))
		return np.dot(T_arr, self.a)/c.R('J/mol/K')
Пример #9
0
	def get_CpoR(self, T, verbose = True):
		"""
		Calculate the dimensionless heat capacity for a single temperature.
		
		Parameters
		----------
			T - float
				Temperature
			verbose - bool
				Whether or not more information should be provided
		Returns
		-------
			CpoR - float
				Dimensionless heat capacity at a single temperature (i.e. Cp/R where R is the molar gas constant)
		"""
		t = T/1000.		
		T_arr = np.array([1, t, t ** 2, t ** 3, (1/t) ** 2, 0, 0, 0])
		if verbose:
			if T < self.T_low:
				print(("Warning. Input temperature (%f) lower than T_low (%f) for species %s" % (T, self.T_low, self.symbol)))
			elif T > self.T_high:
				print(("Warning. Input temperature (%f) higher than T_high (%f) for species %s" % (T, self.T_high, self.symbol)))
		return np.dot(T_arr, self.a)/c.R('J/mol/K')
Пример #10
0
	def plot_thermo(self, T_low, T_high, Cp_units = None, S_units = None, H_units = None, G_units = None, phase = None):
		"""
		Plots the heat capacity, enthalpy and entropy in the temperature range specified.
		The units for the plots can be specified by using R

		Parameters
		----------
			T_low - float
				Lower temperature bound
			T_high - float
				Higher temperature bound
			Cp_units - string
				Heat capacity units. Supported units can be found in py_box3.constants.R
				e.g. Use 'kJ/mol/K' to display heat capacity in kiloJoules per mol per Kelvin 
			H_units - string
				Enthalpy units. Supported units can be found in py_box3.constants.R
			S_units - string
				Entropy units. Supported units can be found in py_box3.constants.R
				e.g. Use 'kJ/mol/K' to display entropy in kiloJoules per mol per Kelvin 
			G_units - string
				Gibbs free energy units. Supported units can be found in py_box3.constants.R
		Returns
		-------
			fig - matplotlib.figure.Figure object
			ax_Cp - meatplotlib.Axes.axes object
				Axes to heat capacity plot
			ax_H - meatplotlib.Axes.axes object
				Axes to enthalpy plot
			ax_S - meatplotlib.Axes.axes object
				Axes to entropy plot
			ax_G - meatplotlib.Axes.axes object
				Axes to Gibbs energy plot
		"""
		import matplotlib.pyplot as plt

		T = np.linspace(T_low, T_high)
		Cp = self.get_CpoR(T, phase = phase)
		H = self.get_HoRT(T, phase = phase)
		S = self.get_SoR(T, phase = phase)
		G = self.get_GoRT(T, phase = phase)

		#Apply units
		if Cp_units is not None:
			Cp = Cp * c.R(Cp_units)
		if S_units is not None:
			S = S * c.R(S_units)
		if H_units is not None:
			H = H * c.R('{}/K'.format(H_units)) * T
		if G_units is not None:
			G = G * c.R('{}/K'.format(G_units)) * T

		fig = plt.figure()
		ax_Cp = plt.subplot(411)
		plt.plot(T, Cp, 'r-')
		if Cp_units is None:
			plt.ylabel('Cp/R')
		else:
			plt.ylabel('Cp ({})'.format(Cp_units))
		plt.xlabel('T (K)')
		plt.title('Plots for {} using shomate polynomials.'.format(self.symbol))

		ax_H = plt.subplot(412)
		plt.plot(T, H, 'g-')
		if H_units is None:
			plt.ylabel('H/RT')
		else:
			plt.ylabel('H ({})'.format(H_units))
		plt.xlabel('T (K)')

		#Entropy graph
		ax_S = plt.subplot(413)
		plt.plot(T, S, 'b-')
		if S_units is None:
			plt.ylabel('S/R')
		else:
			plt.ylabel('S ({})'.format(S_units))
		plt.xlabel('T (K)')

		ax_G = plt.subplot(414)
		plt.plot(T, G, 'k-')
		if G_units is None:
			plt.ylabel('G/RT')
		else:
			plt.ylabel('G (%s)' % G_units)
		plt.xlabel('T (K)')
		return (fig, ax_Cp, ax_H, ax_S, ax_G)
Пример #11
0
 def test_R(self):
     self.assertEqual(c.R('J/mol/K'), 8.3144598)