Example #1
0
def hello_world():

    body = request.get_json()

    units = body['units']

    set_units(units)

    selected_species = pm.get(body['species'])

    chart_data = build_chart_data(selected_species)

    if 'pressure' in body:
        pressure_float = float(body['pressure'])
        return jsonify({
            "values":
            build_saturation_response_from_pressure(selected_species,
                                                    pressure_float),
            "chart_data":
            chart_data
        })

    if 'temp' in body:
        temp_float = float(body['temp'])
        return jsonify({
            "values":
            build_saturation_response_from_temp(selected_species, temp_float),
            "chart_data":
            chart_data
        })
def plot_cycle(cycle):

	id_df = cycle()[0]
	re_df = cycle()[2]
	index = id_df.columns.values
	T_id = id_df[index[0]]
	s_id = id_df[index[3]]
	T_re = re_df[index[0]]
	s_re = re_df[index[3]]
	p_id = id_df[index[1]]
	p_re = re_df[index[1]]

	H2O = pm.get('mp.H2O')

	T_id_last = np.linspace(T_id[-1], T_id[0],150)
	p_id_last = p_id[-1] * np.ones(len(T_id_last))
	S_id_last = H2O.s(T=T_id_last,p=p_id_last)

	T_re_last = np.linspace(T_re[-1], T_re[0],150)
	p_re_last = p_re[-1] * np.ones(len(T_re_last))
	S_re_last = H2O.s(T=T_re_last,p=p_re_last)

	water_curve()
	plt.plot(S_id_last,T_id_last,'-g')
	plt.plot(s_id, T_id, '-og', label='Ideal')
	plt.plot(S_re_last,T_re_last,'-k')
	plt.plot(s_re, T_re, '-ok', label='Real')
	plt.legend()
	plt.title(cycle()[-1])
	plt.xlabel('Entropy s [kJ/(kg K)]')
	plt.ylabel('Temperature T [K]')
	return plt.show()
 def __init__(self, T3t=k.T3t, T0=k.T0, Pa=k.Pa, delta=0.001):
     self.delta = delta
     self.data = self.create_data_array()
     self.T3t, self.T0, self.Pa = T3t, T0, Pa
     self.P3t = (np.asscalar(self.air.d(T=self.T3t)) / 1000)
     self.air = pm.get('ig.air')
     self.cp0 = np.asscalar(self.air.cp(T=self.T0, p=self.Pa))
Example #4
0
	def __init__(self, delta=0.01):
		self.M0_at_SF_max = 2.34
		self.SF_max = 817.5201699820385
		self.air = pm.get('ig.air')
		self.delta = 0.01
		# self.data = Problem1.empty_data_array(delta)
		self.Ts, self.gs = self.throat_convergence()
		# self.Te, self.ge, self.Me = self.exit_convergence()
		# self.A = self.area_ratio()
		self.check()
	def __init__(self, T3t=k.T3t, T0=k.T0, Pa=k.Pa, delta=0.01, gamma=k.GAMMA, verbose=True):
		self.delta = delta
		self.data = Problem1.empty_data_array(delta)
		self.P1 = Problem1(verbose=False)
		self.SF_P1, self.M0_P1 = self.P1.SF, self.P1.M0
		self.M0, self.SF = 0, 0
		self.air = pm.get('ig.air')
		self.T3t = T3t
		self.T0 = T0
		self.Pa = Pa
		self.M4 = 2
		self.gamma = gamma
		self.verbose = verbose
		self.ideal_nozzle()
 def __init__(self, delta=0.01):
     self.data = Problem2.empty_data_array(delta)
     self.SF_ideal, self.M0_ideal = Problem1.return_values()
     # self.M0_at_SF_max = 2.34
     # self.SF_max = 817.5201699820385
     self.air = pm.get('ig.air')
     self.delta = 0.01
     self.g = self.gamma(k.T0)
     self.Ts, self.gs = self.throat_convergence()
     self.Ps = self.pressure_from_temperature()
     self.Te = self.temperature_from_pressure()
     self.Me_id = self.Me_ideal()
     self.A = self.area_ratio()
     self.execute()
Example #7
0
 def __init__(self, fluid, unit_system="kSI_K", verbose=False):
     self.verbose = verbose
     self.unit_system = unit_system
     self.fluid = fluid
     if fluid.lower() == "air":
         fluid = "air"
     self._pm = pm.get(f"ig.{fluid}")
     self._pm.config = pm.config
     # legacy definitions/aliases
     self.Cp = self.c_p = self.cp
     self.Cv = self.c_v = self.cv
     self.mw = self.mm
     self.e = self.u
     self.gamma = self.k
def water_curve():
	#From the pyromat documentation we get the water curve:
	# Get the critical and triple point properties
	H2O = pm.get('mp.H2O')
	Tt,pt = H2O.triple()
	Tc,pc = H2O.critical()
	# Explore the temperatures between Tt and Tc in 5K increments
	T = np.linspace(Tt,Tc,1000)
	s0 = np.zeros(len(T))
	s1 = np.zeros(len(T))
	#fig = plt.figure()
	for i in range(len(T)):
	    s0[i]=H2O.s(T[i],x=0)
	    s1[i]=H2O.s(T[i],x=1)
	return plt.plot(s0,T,'cyan',s1,T,'red',ls='--')
Example #9
0
def plot_t_s():
    # initialize library
    air = pyro.get('ig.air')
    pyro.config['unit_pressure'] = 'bar'
    pyro.config['unit_temperature'] = 'K'
    pyro.config['unit_matter'] = 'kg'
    pyro.config['unit_energy'] = 'kJ'

    # isobaric
    p1 = P0
    t1 = T0
    s1 = air.s(t1, p1)
    p2 = p1 * MAX_PRESSURE_RATIO
    t2 = air.T_s(s=s1, p=p2)
    s2 = s1
    # wc = air.h(t2,p2) - air.h(T1,p1)
    t3 = T_MAX
    p4 = p1
    p3 = p2
    qh = air.h(t3, p3) - air.h(t2, p2)
    s3 = air.s(t3, p3)
    s4 = s3
    t4 = air.T_s(s=s4, p=p4)
    wt = air.h(t3, p3) - air.h(t4, p4)

    temperature_axis_array = np.linspace(t2, t3)
    plt.plot([s1, s2], [t1, t2], 'blue', linewidth=1.5)
    plt.plot(air.s(T=temperature_axis_array, p=p2),
             temperature_axis_array,
             'green',
             linewidth=1.5)
    plt.plot([s3, s3], [t3, t4], 'black', linewidth=1.5)
    temperature_axis_array = np.linspace(t1, t4)
    plt.plot(air.s(T=temperature_axis_array, p=p1),
             temperature_axis_array,
             'red',
             linewidth=1.5)

    plt.legend([
        'Adiabatic Compression', 'Isobaric Combustion',
        'Adiabatic Compression', 'Isobaric Cooling'
    ])

    plt.xlabel('Entropy, s (kJ/kg/K)')
    plt.ylabel('Temperature, T (K)')
    plt.grid('on')
    plt.title('Brayton Cycle T-S Graphic')
    plt.show()
Example #10
0
    def get_substance(self, idstr):
        """Wrapper function for pm.get() that registers appropriate error messages
    substance = get_substance(idstr)

The idstr is the ID string used by get().
"""
        substance = None
        try:
            substance = pm.get(idstr)
        except pm.utility.PMParamError:
            self.mh.error('Substance not found: ' + str(idstr))
        except:
            self.mh.error(
                'There was an unexpected error retrieving substance: ' +
                str(idstr))
            self.mh.message(repr(sys.exc_info()[1]))
        return substance
 def __init__(self,
              T3t=k.T3t,
              T0=k.T0,
              Pa=k.Pa,
              delta=0.01,
              gamma=k.GAMMA,
              verbose=True):
     self.delta = delta
     self.data = Problem1.empty_data_array(delta)
     self.T3t = T3t  # [K]
     self.T0 = T0  # [K]
     self.Pa = Pa  # [K]
     self.gamma = gamma
     self.air = pm.get('ig.air')
     self.verbose = verbose
     self.SF = 0
     self.M0 = 0
     self.execute()
Example #12
0
 def __init__(self,
              T3t=k.T3t,
              T0=k.T0,
              Pa=k.Pa,
              delta=0.01,
              gamma=k.GAMMA,
              verbose=True):
     self.delta = delta
     self.data = Problem1.empty_data_array(delta)
     self.P1 = Problem1(verbose=False)
     self.SF_P1, self.M0_P1 = self.P1.SF, self.P1.M0
     self.air = pm.get('ig.air')
     self.T3t = T3t
     self.T0 = T0
     self.Pa = Pa
     self.gamma = gamma
     self.verbose = verbose
     self.M0_star = self.equation_A()
     #self.optimize()
     self.M4 = 2.53
     self.A = self.equation_B(self.M4)
     #self.nozzle_area_ratio = self.equation_B()
     self.execute()
Example #13
0
def runargtest(outfile, species, args, reference, error_threshold=.001):
    """Test properties for a species object given flexible arguments
    runargtest(outfile, species, args, reference)

outfile
    An open writable file to which to stream the results summary text.

species
    The pyromat object to test or the string id of the object to get

args
    A dictionary containing keyword arguments to pass to the methods identified
by reference.

reference
    A dictionary with keys that must correspond to property methods belonging
to the species.  The corresponding value to each key are the expected results
from the Tp test.  Examples are in test.py.
"""
    if isinstance(species, str):
        test = pyro.get(species)
    elif issubclass(type(species), pyro.reg.__basedata__):
        test = species
    else:
        raise Exception(
            "Species needs to be a PYroMat ID string or a PYroMat object\n")
    sys.stdout.write("Testing " + str(test) + "..")
    outfile.write("Validation of {:s}\n".format(str(test)))
    outfile.write("  Error failure threshold {:%}\n".format(error_threshold))
    error = False

    for argname in args:
        N = np.array(args[argname]).size
        break

    if N > 1:
        linefmt = "{:>15s} = " + "{:<15.5e}" * N + "\n"
        errfmt = "{:>15s} = " + "{:<15.5%}" * N + "\n"
        for argname in args:
            outfile.write(linefmt.format(argname, *args[argname]))
        for thisparam in reference:
            # Evaluate the parameter under test
            val = getattr(test, thisparam)(**args)
            val_ref = reference[thisparam]
            val_error = np.abs((val - val_ref) / val_ref)
            outfile.write(linefmt.format(thisparam, *val))
            outfile.write(linefmt.format('ref', *val_ref))
            outfile.write(errfmt.format('error', *val_error))
            if np.any(val_error > error_threshold):
                error = True
                outfile.write("    [FAILED]\n")
            else:
                outfile.write("    [passed]\n")
    else:
        linefmt = "{:>15s} = {:<15.5e}\n"
        errfmt = "{:>15s} = {:<15.5%}\n"
        for argname in args:
            outfile.write(linefmt.format(argname, float(args[argname])))
        for thisparam in reference:
            # Evaluate the parameter under test
            val = getattr(test, thisparam)(**args)
            val_ref = reference[thisparam]
            val_error = np.abs((val - val_ref) / val_ref)
            outfile.write(linefmt.format(thisparam, float(val)))
            outfile.write(linefmt.format('ref', float(val_ref)))
            outfile.write(errfmt.format('error', float(val_error)))
            if np.any(val_error > error_threshold):
                error = True
                outfile.write("    [FAILED]\n")
            else:
                outfile.write("    [passed]\n")
    outfile.write("\n")

    if error:
        sys.stdout.write("[FAILED]\n")
    else:
        sys.stdout.write("[passed]\n")
    return error
Example #14
0
    if runargtest(writeto, 'ig.O2', args, reference):
        failures.append('ig.O2')

    # Test the mixture class
    T = [320., 1000., 1000.]
    p = [1., 1., 5.]
    h = [446.5, 1173., 1173.]
    s = [3.956, 5.158, 4.696]
    cp = [1.007, 1.141, 1.142]
    writeto.write(
        "Air properties were referenced against the CRC Handbook for" +
        " Chemistry and\nPhysics 97th Edition ``Thermophysical Properties of" +
        " Air''\nby Eric W. Lemon.\n" +
        "Enthalpy and Entropy values were adjusted to match a 1 bar and 300K.\n"
    )
    air = pyro.get('ig.air')
    h = air.h(T=T[0], p=1.) - h[0] + np.array(h)
    s = air.s(T=T[0], p=1.) - s[0] + np.array(s)
    reference = {'cp': cp, 's': s, 'h': h}
    args = {'T': T, 'p': p}
    error = runargtest(writeto, air, args, reference, error_threshold=.005)

    # Now the inverse
    args = {'h': h, 'p': p}
    reference = {'T_h': T}
    error = runargtest(writeto, air, args, reference) or error

    args = {'s': s, 'p': p}
    reference = {'T_s': T}
    error = runargtest(writeto, air, args, reference) or error
    if error:
Example #15
0
    # Reference values from IF-97
    reference = {
        'cp': np.array([.261609445e1, .272724317e1, .288569882e1]),
        'h': np.array([.521976855e4, .516723514e4, .657122604e4]),
        's': np.array([.965408875e1, .772970133e1, .853640623e1]),
        'e': np.array([.452749310e4, .447495124e4, .563707038e4]),
        'd': 1. / np.array([.138455090e1, .230761299e-1, .311385219e-1])
    }

    writeto.write("Steam validation values for region 5 found at \n" +
                  "http://www.iapws.org/relguide/IF97-Rev.pdf\n" +
                  "   Table 42 pg 40\n")
    runargtest(writeto, 'steam', args, reference)

    test = pyro.get('steam')
    T = np.array([300., 500., 600.])
    args = {'T': T}
    reference = {'ps': np.array([.353658941e-1, .263889776e2, .123443146e3])}

    writeto.write(
        "Steam validation values for saturation (region 4) found at \n" +
        "http://www.iapws.org/relguide/IF97-Rev.pdf\n" +
        "   Table 35 pg 34 and Table 36 pg 36\n")
    runargtest(writeto, 'steam', args, reference)

    p = np.array([1., 10., 100.])
    args = {'p': p}
    reference = {'Ts': np.array([.372755919e3, .453035632e3, .584149488e3])}
    runargtest(writeto, 'steam', args, reference)
Example #16
0
    def update(self):
        """Update the cycle states and processes
"""
        if self._test(require=('fluid', 'p1', 'p2', 'eta12', 'eta23',
                               'eta34')):
            raise PMCycleError(
                'There was a problem with the Rankine Cycle configuration')

        fluid = self.param['fluid']

        # Parse the subsance input
        if isinstance(fluid, str):
            fluid = pm.get(fluid)
        if not isinstance(fluid, pm.reg.registry['mp1']):
            raise PMCycleError('RankineCycle requires substances of class mp1')

        # Vectorize the parameters
        p1, p2, eta12, eta23, eta34 = self._prepparam('p1', 'p2', 'eta12',
                                                      'eta23', 'eta34')

        # Get the critical and triple points
        Tc, pc = fluid.critical()
        Tt, pt = fluid.triple()

        # Test the inputs
        # pt < p1 < pc
        if (p1 <= pt).any():
            raise PMCycleError(
                'RankineCycle requires p1 to be greater than the triple-point pressure'
            )
        elif (p1 >= pc).any():
            raise PMCycleError(
                'Rankine Cycle requires p1 to be less than the critical-point pressure'
            )

        # p1 < p2 < pc
        if (p2 <= p1).any():
            raise PMCycleError(
                'RankineCycle requires p2 to be greater than p1.')
        elif (p2 >= pc).any():
            raise PMCycleError(
                'RankineCycle requires p1 to be less than the critical-point pressure'
            )

        if (eta12<0).any() or (eta12>1).any() or (eta23<0).any() or \
                (eta23>1).any() or (eta34<0).any() or (eta34>1).any():
            raise PMCycleError(
                'RankineCycle efficiencies must be between 0 and 1.')

        # Update the lastparam values
        self._writelast()

        # Calculate state 1
        self.p[0] = p1
        self.T[0] = fluid.Ts(p=p1)
        self.s[0], _ = fluid.ss(T=self.T[0])
        self.h[0], _ = fluid.hs(T=self.T[0])
        self.d[0], _ = fluid.ds(T=self.T[0])
        self.x[0] = 0.

        # Calculate state 2
        self.p[1] = p2
        # Start with the isentropic performance
        T2s = fluid.T_s(s=self.s[0], p=p2)
        h2s = fluid.h(T=T2s, p=p2)
        # Adjust the enthalpy rise by the inverse of pump efficiency
        self.h[1] = self.h[0] + (h2s - self.h[0]) / eta12
        self.T[1], self.x[1] = fluid.T_h(h=self.h[1], p=p2, quality=True)
        self.d[1] = fluid.d(T=self.T[1], p=p2, x=self.x[1])
        # Now that we have density, we can use it directly to solve for entropy
        self.s[1] = fluid.s(T=self.T[1], d=self.d[1])

        # Calculate state 3
        self.p[2] = p2
        self.T[2] = fluid.Ts(p=p2)
        _, self.s[2] = fluid.ss(T=self.T[2])
        _, self.h[2] = fluid.hs(T=self.T[2])
        _, self.d[2] = fluid.ds(T=self.T[2])
        self.x[2] = 1.

        # Calculate state 4
        self.p[3] = p1
        T4s, x4s = fluid.T_s(self.s[2], p=p1, quality=True)
        h4s = fluid.h(T=T4s, x=x4s)
        # Adjust enthlpy fall by the turbine efficiency
        self.h[3] = self.h[2] + (h4s - self.h[2]) * eta34
        self.T[3], self.x[3] = fluid.T_h(h=self.h[3], p=p1, quality=True)
        self.d[3] = fluid.d(T=self.T[3], p=p1, x=self.x[3])
        # Now that we have density, we can use it directly to solve for entropy
        self.s[3] = fluid.s(T=self.T[3], d=self.d[3])

        self.w = [self.h[0] - self.h[1], 0., self.h[2] - self.h[3], 0.]

        # Adjust the required boiler heat by the efficiency
        self.q = [
            0., (self.h[2] - self.h[1]) / eta23, 0., self.h[0] - self.h[3]
        ]

        self.meta['qH'] = self.q[1]
        self.meta['qL'] = self.q[3]
        self.meta['wnet'] = self.w[2] + self.w[0]
        self.meta['eta'] = self.meta['wnet'] / self.meta['qH']
Example #17
0
    sys.stdout = save_stdout


species, type, plin, Tlin, vlin, hlin, slin, up, uT, uE, uM, uV = pmcgi.argparse(
    [('id'), ('type', str, 'Ts'), ('plin', str, 'false'),
     ('Tlin', str, 'false'), ('vlin', str, 'false'), ('hlin', str, 'false'),
     ('slin', str, 'false'), ('up'), ('uT'), ('uE'), ('uM'), ('uV')])

# Apply the units
pm.config['unit_temperature'] = uT
pm.config['unit_pressure'] = up
pm.config['unit_matter'] = uM
pm.config['unit_energy'] = uE
pm.config['unit_volume'] = uV

this = pm.get(species)

# Calculate the states
F = pm.get(species)

if plin == 'true':
    plines = None
else:
    plines = []

if Tlin == 'true':
    Tlines = None
else:
    Tlines = []

if vlin == 'true':
Example #18
0
#
#   Brayton cycle demo
#   C.R. Martin (c) 2016-2018
#   GPL v3.0
#   Enjoy!
#

import pyromat as pyro
import numpy as np
import matplotlib.pyplot as plt

air = pyro.get('ig.air')
# Force the unit system into kJ,kg,bar,K
pyro.config['unit_energy'] = 'kJ'
pyro.config['unit_matter'] = 'kg'
pyro.config['unit_pressure'] = 'bar'
pyro.config['unit_temperature'] = 'K'

# Let's design a gas turbine with a 100kW power output
Wnet = 100.
# There are three processes separating four states in a brayton cycle.
#
# (1) ---|Compressor|---> (2) ---|Combustor|---> (3) ---|Turbine|---> (4)
#
#(1) The inlet is ambient temperature and pressure.  In our example, we will
#   use 1.013bar and 300K for p1 and T1
p1 = 1.013
T1 = 300.

#|Compressor| is ideally an isentropic process designed to compress the
# incoming air to a certain pressure ratio, pr.  Let's use pr=12.
Example #19
0
from fluid_properties import *
import matplotlib.pyplot as plt
import numpy as np
import math
import pyromat as pm
from pyXSteam.XSteam import XSteam
from CoolProp.HumidAirProp import HAPropsSI


def wall_element_calc(case, y_plus, V_inf, L_characteristic, epsilon,
                      fluid_name, T1, p1):
    # get working_fluid properties
    pm.config['unit_pressure'] = 'Pa'
    pm.config['unit_temperature'] = 'C'
    working_fluid = pm.get('ig.' + fluid_name)
    rho = working_fluid.d(T=T1, p=p1)
    mu = working_fluid.mu = thermophysical_properties('mu', fluid_name, T1)
    Re = (rho * V_inf * L_characteristic) / mu

    if case == "pipe_flow":
        cf = colebrook_calc(epsilon, L_characteristic, Re) / 4
        tau_w = cf * 0.5 * rho * V_inf**2
        u_star = math.sqrt(tau_w / rho)
        y = (y_plus * mu) / (rho * u_star)
    return y


y = wall_element_calc('pipe_flow', 30, 30, 0.001, 0, 'air', 15, 101325)
print(y)
Example #20
0
    def tsplot(self,
               ax=None,
               fig=None,
               slabels=True,
               satstyle=None,
               procstyle=None,
               statestyle=None):
        """
"""
        # If the properties are empty, abort
        if not self.T:
            raise PMCycleError(
                'The plot cannot be generated for a cycle that has not yet been updated.  Run update().'
            )
        if isinstance(self.T, np.ndarray) and self.T.size > 1:
            raise PMCycleError(
                'Plotting arrays of cycle data is not supported.')

        uE = self.lastparam['unit_energy']
        uM = self.lastparam['unit_matter']
        uT = self.lastparam['unit_temperature']

        ax = self._initplot('s (%s/%s%s)' % (uE, uM, uT),
                            'T (%s)' % (uT),
                            ax=ax,
                            fig=fig)

        if satstyle is None:
            satstyle = {'lw': 2, 'c': 'k', 'ls': 'solid', 'marker': 'None'}
        if procstyle is None:
            procstyle = {'lw': 2, 'c': 'r', 'ls': 'solid', 'marker': 'None'}
        if statestyle is None:
            statestyle = {
                'ls': 'None',
                'marker': 'o',
                'mec': 'k',
                'mew': 1,
                'mfc': 'r',
                'ms': 6
            }
        boxstyle = {'fc': 'w', 'ec': 'k', 'boxstyle': 'square,pad=.25'}

        # Get the working fluid object
        if isinstance(self.lastparam['fluid'], str):
            fluid = pm.get(self.lastparam['fluid'])
        else:
            fluid = self.lastparam['fluid']

        # Plot the dome
        Tc, pc = fluid.critical()
        Tt, pt = fluid.triple()
        T = np.linspace(Tt, 0.99999 * Tc, 100)
        sL, sV = fluid.ss(T=T)
        ax.plot(sL, T, **satstyle)
        ax.plot(sV, T, **satstyle)

        # Isentropic pump is a straight vertical line
        ax.plot([self.s[0], self.s[1]], [self.T[0], self.T[1]], **procstyle)

        # Isobaric boiler
        s = np.linspace(self.s[1], self.s[2], 51)
        T = fluid.T_s(s, p=self.p[1])
        ax.plot(s, T, **procstyle)

        # Isobaric super-heater
        s = np.linspace(self.s[2], self.s[3], 21)
        T = fluid.T_s(s, p=self.p[1])
        ax.plot(s, T, **procstyle)

        # Isentropic turbine is a straight vertical line
        ax.plot([self.s[3], self.s[4]], [self.T[3], self.T[4]], **procstyle)

        # Isobaric condensation
        s = np.linspace(self.s[4], self.s[0], 51)
        T = fluid.T_s(s, p=self.p[0])
        ax.plot(s, T, **procstyle)

        # deterine offsets in T and s space
        ds = ax.get_xlim()
        ds = .02 * (ds[1] - ds[0])
        dT = ax.get_ylim()
        dT = .02 * (dT[1] - dT[0])

        # Deal with the state labels
        ax.plot(self.s[0], self.T[0], **statestyle)
        tt = ax.text(self.s[0] - ds, self.T[0] - dT, '1', ha='right', va='top')
        tt.set_bbox(boxstyle)
        ax.plot(self.s[1], self.T[1], **statestyle)
        tt = ax.text(self.s[1] - ds,
                     self.T[1] + dT,
                     '2',
                     ha='right',
                     va='bottom')
        tt.set_bbox(boxstyle)
        ax.plot(self.s[2], self.T[2], **statestyle)
        tt = ax.text(self.s[2] - ds,
                     self.T[2] + dT,
                     '3',
                     ha='right',
                     va='bottom')
        tt.set_bbox(boxstyle)
        ax.plot(self.s[3], self.T[3], **statestyle)
        tt = ax.text(self.s[3] + ds,
                     self.T[3] + dT,
                     '4',
                     ha='left',
                     va='bottom')
        tt.set_bbox(boxstyle)
        ax.plot(self.s[4], self.T[4], **statestyle)
        tt = ax.text(self.s[4] + ds, self.T[4] - dT, '5', ha='left', va='top')
        tt.set_bbox(boxstyle)

        return ax
Example #21
0
    def update(self):
        """Update the cycle states and processes
"""
        if self._test(require=('fluid', 'p1', 'p2', 'T4', 'q34', 'eta12',
                               'eta23', 'eta34', 'eta45')):
            raise PMCycleError(
                'There was a problem with the Rankine Cycle configuration')

        # Determine the super-heat solution mode
        mode = 0
        if self.param['q34'] is not None:
            mode = 2
        elif self.param['T4'] is not None:
            mode = 1

        fluid = self.param['fluid']
        # Parse the subsance input
        if isinstance(fluid, str):
            fluid = pm.get(fluid)
        if not isinstance(fluid, pm.reg.registry['mp1']):
            raise PMCycleError('RankineCycle requires substances of class mp1')

        p1, p2, T4, q34, eta12, eta23, eta34, eta45 = self._prepparam(
            'p1', 'p2', 'T4', 'q34', 'eta12', 'eta23', 'eta34', 'eta45')

        # Get the critical and triple points
        Tc, pc = fluid.critical()
        Tt, pt = fluid.triple()

        # Test the inputs
        # pt < p1 < pc
        if (p1 <= pt).any():
            raise PMCycleError(
                'RankineSHCycle requires p1 to be greater than the triple-point pressure'
            )
        elif (p1 >= pc).any():
            raise PMCycleError(
                'RankineSHCycle requires p1 to be less than the critical-point pressure'
            )

        # p1 < p2 < pc
        if (p2 <= p1).any():
            raise PMCycleError(
                'RankineSHCycle requires p2 to be greater than p1.')
        elif (p2 >= pc).any():
            raise PMCycleError(
                'RankineSHCycle requires p1 to be less than the critical-point pressure'
            )

        if (eta12<0).any() or (eta12>1).any() or (eta23<0).any() or \
                (eta23>1).any() or (eta34<0).any() or (eta34>1).any() or\
                (eta45<0).any() or (eta45>1).any():
            raise PMCycleError(
                'RankineSHCycle efficiencies must be between 0 and 1.')

        # Update the lastparam values
        self._writelast()

        # Calculate state 1
        self.p[0] = p1
        self.T[0] = fluid.Ts(p=p1)
        self.s[0], _ = fluid.ss(T=self.T[0])
        self.h[0], _ = fluid.hs(T=self.T[0])
        self.d[0], _ = fluid.ds(T=self.T[0])
        self.x[0] = 0.

        # Calculate state 2
        self.p[1] = p2
        # Start with the isentropic performance
        T2s = fluid.T_s(s=self.s[0], p=p2)
        h2s = fluid.h(T=T2s, p=p2)
        # Adjust the enthalpy rise by the inverse of pump efficiency
        self.h[1] = self.h[0] + (h2s - self.h[0]) / eta12
        self.T[1], self.x[1] = fluid.T_h(h=self.h[1], p=p2, quality=True)
        self.d[1] = fluid.d(T=self.T[1], p=p2, x=self.x[1])
        # Now that we have density, we can use it directly to solve for entropy
        self.s[1] = fluid.s(T=self.T[1], d=self.d[1])

        # Calculate state 3
        self.p[2] = p2
        self.T[2] = fluid.Ts(p=p2)
        _, self.s[2] = fluid.ss(T=self.T[2])
        _, self.h[2] = fluid.hs(T=self.T[2])
        _, self.d[2] = fluid.ds(T=self.T[2])
        self.x[2] = 1.

        # Calculate states 4 by case
        # If the target for state5 is a saturated vapor
        if mode == 0:
            # force s4 to be equal to the sV at p1
            self.p[3] = p2
            _, self.s[3] = fluid.ss(p=p1)
            self.T[3], self.x[3] = fluid.T_s(s=self.s[3], p=p2, quality=True)
            self.d[3] = fluid.d(T=self.T[3], p=p2, x=self.x[3])
            self.h[3] = fluid.h(T=self.T[3], d=self.d[3])

        # If state 4 is temperature limited
        elif mode == 1:
            # Test the temperature
            if (T4 < self.T[2]).any():
                raise PMCycleError(
                    'RankineSHCycle requires T4 to be greater than T3.')

            self.p[3] = p2
            self.T[3] = T4
            self.h[3], self.s[3], self.d[3] = fluid.hsd(T=T4, p=p2)
            self.x[3] = -1.

        # If state 4 is determined by heat addition
        else:
            self.p[3] = p2
            self.h[3] = self.h[2] + q34
            self.T[3], self.x[3] = fluid.T_h(h=self.h[3], p=p2, quality=True)
            self.d[3] = fluid.d(T=self.T[3], p=p2, x=self.x[3])
            self.s[3] = fluid.s(T=self.T[3], d=self.d[3])

        # Calculate state 5
        self.p[4] = p1
        T5s, x5s = fluid.T_s(self.s[3], p=p1, quality=True)
        h5s = fluid.h(T=T5s, p=p1, x=x5s)
        # Adjust enthlpy fall by the turbine efficiency
        self.h[4] = self.h[3] + (h5s - self.h[3]) * eta45
        self.T[4], self.x[4] = fluid.T_h(h=self.h[4], p=p1, quality=True)
        self.d[4] = fluid.d(T=self.T[4], p=p1, x=self.x[4])
        # Now that we have density, we can use it directly to solve for entropy
        self.s[4] = fluid.s(T=self.T[4], d=self.d[4])

        self.w = [self.h[0] - self.h[1], 0., 0., self.h[3] - self.h[4], 0.]

        self.q = [
            0., self.h[2] - self.h[1], self.h[3] - self.h[2], 0.,
            self.h[0] - self.h[4]
        ]

        self.meta['qH'] = self.q[1] + self.q[2]
        self.meta['qL'] = self.q[3]
        self.meta['wnet'] = self.w[3] + self.w[0]
        self.meta['eta'] = self.meta['wnet'] / self.meta['qH']
Example #22
0
import pyromat as pm
import numpy as np
import matplotlib.pylab as pylab

#Tester for MP1. Not exhaustive, as other bugs have also been identified.

#get steam
mp1obj = pm.get('mp.H2O')

#Public methods
#Tlim
mp1obj.Tlim()
mp1obj.Tlim(p=1)

#Plim
mp1obj.plim()
mp1obj.plim(T=1000)

#critical
mp1obj.critical()
mp1obj.critical(density=True)

#triple
mp1obj.triple()

#ps
mp1obj.ps(T=373)  #should be around 1 bar
mp1obj.ps(T=[373, 373])
mp1obj.ps(T=np.asarray(373))
mp1obj.ps(T=np.asarray([373, 373]))
#print(mp1obj.ps(T=373))
Example #23
0
#color = 'b'   # Blue
# This is a True/False flag to deactivate the plot text
show_text = True
# This is a True/False flag to allow over-plotting of previous results
clear_plots = False
# Liquid water reservoir is at ambient pressure
p1 = 1.013
# Operating pressure of the boiler
p2 = 18.3  # 18.3 bar is roughly 250 psig
#p2 = 11.4  # 11.4 bar is roughly 150 psig

# How much work do we need?
Wnet = 100.  # Let's make a 100kW engine

# Get the steam data
steam = pyro.get('mp.H2O')

# Assume the reservoir is a saturated liquid, as it would likely
# be coming out of the condenser.  In reality some supercooling
# is likely, but we will neglect it here.
# States (5) and (1) will straddle the dome
T1 = steam.Ts(p1)
p5 = p1  # Since it is spanning the done, (5) and (1) share T and p
T5 = T1
h1, h5 = steam.hs(p=p1, T=T1)  # these are faster with T and p
s1, s5 = steam.ss(p=p1, T=T1)
d1, d5 = steam.ds(p=p1, T=T1)

# Isentropic compression of liquid water
# It is common to assume that T1=T2 since liquid is very close
# to incompressible.  To compare results, remove the comment
Example #24
0
# In this code, we generate a surface plot that spans the saturation
# curve from triple point to critical point.  We'll add two red lines
# to show where the liquid- and gas-phase saturation properties are in 
# each plot.  

import pyromat as pyro
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np


# Start with a blank slate
plt.close('all')

# Get the steam object
S = pyro.get('mp.H2O')

# Get the critical and triple point properties
Tt,pt = S.triple()
Tc,pc = S.critical()

# Explore the temperatures between Tt and Tc in 5K increments
Ts = np.arange(Tt,Tc,5.)

# Now, obtain the saturation properties
# Note that when a saturation property is called with the "tp" flag True
# it also returns the saturation temperature and pressure.
# This is more efficient than separate calls to Ts and ps.
Ts,ps,dL,dV = S.ds(T=Ts,tp=True)
# It is faster to explicitly pass both Ts and ps to the saturation methods.
# This saves them a redundant call to Ts or ps since both are required anyway.
Example #25
0
from fluid_properties import *
import matplotlib.pyplot as plt
import numpy as np
import math
import pyromat as pm
from pyXSteam.XSteam import XSteam
from CoolProp.HumidAirProp import HAPropsSI

## Configure Pyromat
pm.config['unit_pressure'] = 'Pa'
pm.config['unit_temperature'] = 'C'
# Live example
working_fluid = pm.get('ig.air')
cp = working_fluid.cp(25, 101325)

steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS)  # m/kg/sec/°C/bar/W
'''
cp=steamTable.Cp_pt(25,1)
'''
Example #26
0
    def update(self):
        """Update the cycle states and processes
"""
        if self._test(require=('fluid', 'p1', 'p2', 'T1', 'T3', 'q23', 'eta12',
                               'eta23', 'eta34')):
            raise PMCycleError(
                'There was a problem with the Brayton Cycle configuration')

        # Detect the solution mode
        if self.param['T3'] is not None:
            mode = 0
        elif self.param['q23'] is not None:
            mode = 1
        else:
            raise PMCycleError(
                'BraytonCycle requires T3 or q23 to be specified.')

        fluid = self.param['fluid']
        # Parse the subsance input
        if isinstance(fluid, str):
            fluid = pm.get(fluid)

        p1, p2, T1, T3, q23, eta12, eta23, eta34 = self._prepparam(
            'p1', 'p2', 'T1', 'T3', 'q23', 'eta12', 'eta23', 'eta34')

        # p1 < p2 < pc
        if (p2 <= p1).any():
            raise PMCycleError(
                'BraytonCycle requires p2 to be greater than p1.')

        if (T3 <= T1).any():
            raise PMCycleError('BraytonCycle requires T3 to be less than T1.')

        self._writelast()

        # Calculate state 1
        self.p[0] = p1
        self.T[0] = T1
        self.s[0] = fluid.s(T=T1, p=p1)
        self.h[0] = fluid.h(T=T1, p=p1)
        self.d[0] = fluid.d(T=T1, p=p1)
        self.x[0] = -1

        # Calculate state 2
        self.p[1] = p2
        Ts2 = fluid.T_s(s=self.s[0], p=p2)
        hs2 = fluid.h(T=Ts2, p=p2)
        # Modify the work by the compressor efficiency
        self.h[1] = self.h[0] + (hs2 - self.h[0]) / eta12
        self.T[1] = fluid.T_h(h=self.h[1], p=p2)
        self.s[1] = fluid.s(T=self.T[1], p=p2)
        self.d[1] = fluid.d(T=self.T[1], p=p2)
        self.x[1] = -1

        if mode == 0:
            # Calculate state 3
            self.p[2] = p2
            self.T[2] = T3
            self.s[2] = fluid.s(T=T3, p=p2)
            self.h[2] = fluid.h(T=T3, p=p2)
            self.d[2] = fluid.d(T=T3, p=p2)
            self.x[2] = -1
        else:
            self.p[2] = p2
            self.h[2] = self.h[1] + q23 * eta23
            self.T[2] = fluid.T_h(h=self.h[2], p=p2)
            self.s[2] = fluid.s(T=self.T[2], p=p2)
            self.d[2] = fluid.d(T=self.d[2], p=p2)
            self.x[2] = -1

        # Calculate state 4
        self.p[3] = p1
        T4s = fluid.T_s(s=self.s[2], p=p1)
        h4s = fluid.h(T=T4s, p=p1)
        self.h[3] = self.h[2] + (h4s - self.h[2]) * eta34
        self.T[3] = fluid.T_h(h=self.h[3], p=p1)
        self.s[3] = fluid.s(T=self.T[3], p=p1)
        self.d[3] = fluid.d(T=self.T[3], p=p1)
        self.x[3] = -1

        self.w = [self.h[0] - self.h[1], 0., self.h[2] - self.h[3], 0.]

        self.q = [0., self.h[2] - self.h[1], 0., self.h[0] - self.h[3]]

        self.meta['qH'] = self.q[1]
        self.meta['qL'] = self.q[3]
        self.meta['wnet'] = self.w[2] + self.w[0]
        self.meta['eta'] = self.meta['wnet'] / self.meta['qH']
Example #27
0
import matplotlib.pyplot as plt
import numpy as np

uT = 'K'
up = 'kPa'
uM = 'kg'
uE = 'kJ'
uV = 'm3'

pm.config['unit_temperature'] = uT
pm.config['unit_pressure'] = up
pm.config['unit_matter'] = uM
pm.config['unit_energy'] = uE
pm.config['unit_volume'] = uV

F = pm.get('mp.H2O')
f = plt.figure()
ax = f.add_subplot(111)


def P_h(T, h):
    P_h = pmsolve.solve1n('p', f=F.T_h, param_init=100)
    return P_h(T, h=h)


def P_d(T, d):
    P_d = pmsolve.solve1n('p', f=F.ds, param_init=1)
    return P_d(d, T=T)


def Psat_d(d):
Example #28
0
import pyromat as pm
import numpy as np

pm.config["unit_pressure"] = "kPa"
pm.config["def_p"] = 100

mp_water = pm.get("mp.H2O") # <-- for multi-phase water properties

p1 = 10 # <-- given
p2 = 400 # <-- given

v1 = 1/mp_water.ds(p=p1)[0]

w_pump1 = v1*(p2-p1)
h2 = h1+w_pump1
print(f"Work required by pump 1: {round(float(w_pump1),1)} kJ/kg")
Work required by pump 1: 0.4 kJ/kg

p5 = 4000 # <-- given
T5 = 400+273.15 # K <-- given
h5 = mp_water.h(p=p5, T=T5)
s5 = mp_water.s(p=p5, T=T5)

s6 =s5
p6 = 400 # <-- given
T6, x6 = mp_water.T_s(s=s6, p=p6, quality=True)
h6 = mp_water.h(x=x6, p=p6)

print(f"Quality of bled steam: {round(float(x6),4)}")
Quality of bled steam: 0.9757
Example #29
0
#Set up the species spinner
lu.setspeciesselect(P, species, speciesline, 56)

# Apply the units within pyromat
pm.config['unit_temperature'] = uT
pm.config['unit_pressure'] = up
pm.config['unit_matter'] = uM
pm.config['unit_energy'] = uE
pm.config['unit_volume'] = uV

# # # # # # # # # # # # #
# Calculate the states  #
# # # # # # # # # # # # #
#Get the substance object
F = pm.get(species)

#Set blank labels for each of the properties.
#These will be reset by each of the methods for re-entry into the input boxes.
Tval = pval = ''

#check for cases where too few or too many properties are specified (zero specified results in defaults)
ins = np.array([p1, T1
                ])  #test array for counting how many properties were specified
if (sum(ins >= 0) == 0):
    p1 = 101.325
elif (sum(ins >= 0) != 1):
    lu.perror(P, 'Must specify pressure or temperature, but not both.',
              errline)

#Determine which two properties were chosen, calculate the state
Example #30
0
import pyromat as pm

pm.config["unit_pressure"] = "kPa"
pm.config["def_p"] = 100

mp_water = pm.get("mp.H2O")

#saturated liquid, thus x = 0
p1 = 10 # <--given
T1 = mp_water.Ts(p=p1)[0]
s1 = mp_water.ss(p=p1)[0]
p2 = 2000 # <--given and converted to kPa
s2= s1
v = 1/mp_water.ds(p=p1)[0]

w_p = v*(p2-p1)
print(f"Work required by pump: {round(float(w_p),1)} kJ/kg")

h1 = mp_water.hs(p=p1)[0]
h2 = h1+w_p
T2 = mp_water.T_h(p=p2,h=h2)

print(f"h2 = {round(float(h2),1)} kJ/kg")
h2 = 193.8 kJ/kg

# steam leaves the boiler as saturated vapor, thus x = 1
p3 = p2
T3 = mp_water.Ts(p=p3)

h3 = mp_water.hs(p=p3)[1]
s3dash = mp_water.ss(p=p3)[0]