Exemple #1
0
    def test_setInitialTime(self):
        self.makeReactors(P1=10*ct.OneAtm, X1='AR:1.0', X2='O2:1.0')
        self.net.rtol = 1e-12
        valve = ct.Valve(self.r1, self.r2)
        mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
        valve.setValveCoeff(mdot)

        t0 = 0.0
        tf = t0 + 0.5
        self.net.advance(tf)
        self.assertNear(self.net.time, tf)
        p1a = self.r1.thermo.P
        p2a = self.r2.thermo.P

        self.makeReactors(P1=10*ct.OneAtm, X1='AR:1.0', X2='O2:1.0')
        self.net.rtol = 1e-12
        valve = ct.Valve(self.r1, self.r2)
        mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
        valve.setValveCoeff(mdot)

        t0 = 0.2
        self.net.setInitialTime(t0)
        tf = t0 + 0.5
        self.net.advance(tf)
        self.assertNear(self.net.time, tf)
        p1b = self.r1.thermo.P
        p2b = self.r2.thermo.P

        self.assertNear(p1a, p1b)
        self.assertNear(p2a, p2b)
Exemple #2
0
    def test_valve_errors(self):
        self.make_reactors()
        res = ct.Reservoir()

        with self.assertRaises(ct.CanteraError):
            # Must assign contents of both reactors before creating Valve
            v = ct.Valve(self.r1, res)

        v = ct.Valve(self.r1, self.r2)
        with self.assertRaises(ct.CanteraError):
            # inlet and outlet cannot be reassigned
            v._install(self.r2, self.r1)
def runSinglePSR(T, P, moleFraction, factor, reactionIndex, targetSpc):

    start = time.time()

    # create the gas mixture
    gas = ct.Solution('HXD15_Battin_mech.xml')
    gas.TPX = T, P, moleFraction

    # create an upstream reservoir that will supply the reactor. The temperature,
    # pressure, and composition of the upstream reservoir are set to those of the
    # 'gas' object at the time the reservoir is created.
    upstream = ct.Reservoir(gas)

    # Now create the reactor object with the same initial state
    cstr = ct.IdealGasReactor(gas)

    # Set its volume to 80 cm^3. In this problem, the reactor volume is fixed, so
    # the initial volume is the volume at all later times.
    cstr.volume = 80.0*1.0e-6

    # Connect the upstream reservoir to the reactor with a mass flow controller
    # (constant mdot). Set the mass flow rate.
    vdot = 40* 1.0e-6 # m^3/s
    mdot = gas.density * vdot # kg/s
    mfc = ct.MassFlowController(upstream, cstr, mdot=mdot)

    # now create a downstream reservoir to exhaust into.
    downstream = ct.Reservoir(gas)

    # connect the reactor to the downstream reservoir with a valve, and set the
    # coefficient sufficiently large to keep the reactor pressure close to the
    # downstream pressure.
    v = ct.Valve(cstr, downstream, K=1.0e-9)

    # create the network
    network = ct.ReactorNet([cstr])

    # modify the A factor of the given reaction
    gas.set_multiplier(factor,reactionIndex-1)

    # now integrate in time
    t = 0.0
    dt   = 0.1

    print "\n\n\n**************************\n***** Solving case %d *****\n"%(reactionIndex)

    while t < 30.0:
        print t
        t += dt
        network.advance(t)

    results = []
    for spc in targetSpc:
        results.append(cstr.thermo[spc].X[0]*1.0e6)

    end = time.time()
    print 'Execution time is:'
    print end - start

    return [gas.reaction_equation(reactionIndex-1)] + results
Exemple #4
0
    def setup(self, T0, P0, mdot_fuel, mdot_ox):

        self.gas = ct.Solution('gri30.xml')

        # fuel inlet
        self.gas.TPX = T0, P0, "CH4:1.0"
        self.fuel_in = ct.Reservoir(self.gas)

        # oxidizer inlet
        self.gas.TPX = T0, P0, "N2:3.76, O2:1.0"
        self.oxidizer_in = ct.Reservoir(self.gas)

        # reactor, initially filled with N2
        self.gas.TPX = T0, P0, "N2:1.0"
        self.combustor = ct.IdealGasReactor(self.gas)
        self.combustor.volume = 1.0

        # outlet
        self.exhaust = ct.Reservoir(self.gas)

        # connect the reactor to the reservoirs
        self.fuel_mfc = ct.MassFlowController(self.fuel_in, self.combustor)
        self.fuel_mfc.set_mass_flow_rate(mdot_fuel)
        self.oxidizer_mfc = ct.MassFlowController(self.oxidizer_in, self.combustor)
        self.oxidizer_mfc.set_mass_flow_rate(mdot_ox)
        self.valve = ct.Valve(self.combustor, self.exhaust)
        self.valve.set_valve_coeff(1.0)

        self.net = ct.ReactorNet()
        self.net.add_reactor(self.combustor)
        self.net.max_err_test_fails = 10
Exemple #5
0
    def test_valve2(self):
        # Similar to test_valve1, but by disabling the energy equation
        # (constant T) we can compare with an analytical solution for
        # the mass of each reactor as a function of time
        self.makeReactors(P1=10*ct.OneAtm)
        self.r1.energyEnabled = False
        self.r2.energyEnabled = False
        valve = ct.Valve(self.r1, self.r2)
        k = 2e-5
        valve.setValveCoeff(k)

        self.assertFalse(self.r1.energyEnabled)
        self.assertFalse(self.r2.energyEnabled)

        m1a = self.r1.thermo.density * self.r1.volume
        m2a = self.r2.thermo.density * self.r2.volume
        P1a = self.r1.thermo.P
        P2a = self.r2.thermo.P

        A = k * P1a * (1 + m2a/m1a)
        B = k * (P1a/m1a + P2a/m2a)

        for t in np.linspace(1e-5, 0.5):
            self.net.advance(t)
            m1 = self.r1.thermo.density * self.r1.volume
            m2 = self.r2.thermo.density * self.r2.volume
            self.assertNear(m2, (m2a - A/B) * np.exp(-B * t) + A/B)
            self.assertNear(m1a+m2a, m1+m2)
Exemple #6
0
    def test_valve3(self):
        # This case specifies a non-linear relationship between pressure drop
        # and flow rate.
        self.make_reactors(P1=10*ct.one_atm, X1='AR:0.5, O2:0.5',
                           X2='O2:1.0')
        self.net.rtol = 1e-12
        self.net.atol = 1e-20
        valve = ct.Valve(self.r1, self.r2)
        mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
        valve.set_valve_coeff(mdot)
        Y1 = self.r1.Y
        kO2 = self.gas1.species_index('O2')
        kAr = self.gas1.species_index('AR')

        def speciesMass(k):
            return self.r1.Y[k] * self.r1.mass + self.r2.Y[k] * self.r2.mass
        mO2 = speciesMass(kO2)
        mAr = speciesMass(kAr)

        t = 0
        while t < 1.0:
            t = self.net.step()
            p1 = self.r1.thermo.P
            p2 = self.r2.thermo.P
            self.assertNear(mdot(p1-p2), valve.mdot(t))
            self.assertArrayNear(Y1, self.r1.Y)
            self.assertNear(speciesMass(kAr), mAr)
            self.assertNear(speciesMass(kO2), mO2)
Exemple #7
0
    def test_valve1(self):
        self.makeReactors(P1=10*ct.OneAtm, X1='AR:1.0', X2='O2:1.0')
        valve = ct.Valve(self.r1, self.r2)
        k = 2e-5
        valve.setValveCoeff(k)

        self.assertEqual(self.r1.outlets, self.r2.inlets)
        self.assertTrue(self.r1.energyEnabled)
        self.assertTrue(self.r2.energyEnabled)
        self.assertTrue((self.r1.thermo.P - self.r2.thermo.P) * k,
                        valve.mdot(0))

        m1a = self.r1.thermo.density * self.r1.volume
        m2a = self.r2.thermo.density * self.r2.volume
        Y1a = self.r1.thermo.Y
        Y2a = self.r2.thermo.Y

        self.net.advance(0.1)

        m1b = self.r1.thermo.density * self.r1.volume
        m2b = self.r2.thermo.density * self.r2.volume

        self.assertTrue((self.r1.thermo.P - self.r2.thermo.P) * k,
                        valve.mdot(0.1))
        self.assertNear(m1a+m2a, m1b+m2b)
        Y1b = self.r1.thermo.Y
        Y2b = self.r2.thermo.Y
        self.assertArrayNear(m1a*Y1a + m2a*Y2a, m1b*Y1b + m2b*Y2b)
 def run_single(self):
     
     gas=self.processor.solution
     reactorPressure=gas.P
     self.reactorPressure=self.processor.solution.P
     pressureValveCoefficient=self.pvalveCoefficient
     maxPressureRiseAllowed=self.maxPrise
     
     print(maxPressureRiseAllowed,self.reactorPressure,pressureValveCoefficient)
     #Build the system components for JSR
     fuelAirMixtureTank=ct.Reservoir(self.processor.solution)
     exhaust=ct.Reservoir(self.processor.solution)
     
     stirredReactor=ct.IdealGasReactor(self.processor.solution,energy=self.energycon,volume=self.reactor_volume)
     massFlowController=ct.MassFlowController(upstream=fuelAirMixtureTank,
                                              downstream=stirredReactor,mdot=stirredReactor.mass/self.residence_time)
     pressureRegulator=ct.Valve(upstream=stirredReactor,downstream=exhaust,K=pressureValveCoefficient)
     reactorNetwork=ct.ReactorNet([stirredReactor])
     
     if bool(self.observables) and self.kineticSens==1:
         for i in range(gas.n_reactions):
             stirredReactor.add_sensitivity_reaction(i)
         
     if self.kineticSens and bool(self.observables)==False:
         #except:
             print('Please supply a non-empty list of observables for sensitivity analysis or set kinetic_sens=0')
     if self.physicalSens==1 and bool(self.observables)==False:
Exemple #9
0
    def setUp(self):
        self.gas = ct.Solution('h2o2.xml')

        # create a reservoir for the fuel inlet, and set to pure methane.
        self.gas.TPX = 300.0, ct.one_atm, 'H2:1.0'
        fuel_in = ct.Reservoir(self.gas)
        fuel_mw = self.gas.mean_molecular_weight

        # Oxidizer inlet
        self.gas.TPX = 300.0, ct.one_atm, 'O2:1.0, AR:3.0'
        oxidizer_in = ct.Reservoir(self.gas)
        oxidizer_mw = self.gas.mean_molecular_weight

        # to ignite the fuel/air mixture, we'll introduce a pulse of radicals.
        # The steady-state behavior is independent of how we do this, so we'll
        # just use a stream of pure atomic hydrogen.
        self.gas.TPX = 300.0, ct.one_atm, 'H:1.0'
        self.igniter = ct.Reservoir(self.gas)

        # create the combustor, and fill it in initially with a diluent
        self.gas.TPX = 300.0, ct.one_atm, 'AR:1.0'
        self.combustor = ct.IdealGasReactor(self.gas)

        # create a reservoir for the exhaust
        self.exhaust = ct.Reservoir(self.gas)

        # compute fuel and air mass flow rates
        factor = 0.1
        oxidizer_mdot = 4 * factor * oxidizer_mw
        fuel_mdot = factor * fuel_mw

        # The igniter will use a time-dependent igniter mass flow rate.
        def igniter_mdot(t, t0=0.1, fwhm=0.05, amplitude=0.1):
            return amplitude * math.exp(
                -(t - t0)**2 * 4 * math.log(2) / fwhm**2)

        # create and install the mass flow controllers. Controllers
        # m1 and m2 provide constant mass flow rates, and m3 provides
        # a short Gaussian pulse only to ignite the mixture
        m1 = ct.MassFlowController(fuel_in, self.combustor, mdot=fuel_mdot)
        m2 = ct.MassFlowController(oxidizer_in,
                                   self.combustor,
                                   mdot=oxidizer_mdot)
        m3 = ct.MassFlowController(self.igniter,
                                   self.combustor,
                                   mdot=igniter_mdot)

        # put a valve on the exhaust line to regulate the pressure
        self.v = ct.Valve(self.combustor, self.exhaust, K=1.0)

        # the simulation only contains one reactor
        self.sim = ct.ReactorNet([self.combustor])
Exemple #10
0
    def test_valve3(self):
        # This case specifies a non-linear relationship between pressure drop
        # and flow rate.
        self.makeReactors(P1=10*ct.OneAtm, X1='AR:1.0', X2='O2:1.0')
        valve = ct.Valve(self.r1, self.r2)
        mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
        valve.setValveCoeff(mdot)

        t = 0
        while t < 1.0:
            t = self.net.step(1.0)
            p1 = self.r1.thermo.P
            p2 = self.r2.thermo.P
            self.assertNear(mdot(p1-p2), valve.mdot(t))
Exemple #11
0
def psr_ss(soln_in, soln_out, p, T0, T, X0, X, tau):

    #sys.stdout.flush()

    """
    find the steady state of a PSR

    :param mech:    mechanism
    :param p:       pressure (Pa)
    :param T0:      temperature (K) of the inlet flow
    :param T:       initial temperature (K) of the reactor
    :param tau:     residence time (s) of the reactor

    :return reactor:

    """

    vol = 1.0     # unit: m3
    K = 1.0
    t_end = tau * 100.0

    #print 't_end = '+str(t_end)

    soln_out.TPX = T, p, X
    soln_in.TPX = T0, p, X0

    inlet = ct.Reservoir(soln_in)
    reactor = ct.IdealGasReactor(soln_out)
    reactor.volume = vol

    vdot = vol/tau
    mdot = soln_out.density * vdot
    mfc = ct.MassFlowController(inlet, reactor, mdot=mdot)

    exhaust = ct.Reservoir(soln_out)
    valve = ct.Valve(reactor, exhaust, K=K)

    network = ct.ReactorNet([reactor])
    try:
        network.advance(t_end)
    except RuntimeError as e:

        print '@'*10+'\nct.exceptions = \n'+str(e)
        #sys.exit()
        return None

    return soln_out
 def run(self,):
     
     gas=processor.solution.P
     reactorPressure=gas
     pressureValveCoefficient=pvalveCoefficient
     maxPressureRiseAllowed=maxPrise
     
     
     #Build the system components for JSR
     fuelAirMixtureTank=ct.Reservoir(gas)
     exhaust=ct.Reservoir(gas)
     
     stirredReactor=ct.IdealGasReactor(gas,energy=energycon,volume=volume)
     massFlowController=ct.MassFlowController(upstream=fuelAirMixtureTank,
                                              downstream=stirredReactor,mdot=stirredReactor.mass/restime)
     pressureRegulator=ct.Valve(upstream=stirredReactor,downstream=exhaust,K=pressureValveCoefficient)
     reactorNetwork=ct.ReactorNet([stirredReactor])
     
     if bool(self.moleFractionObservables) and self.kineticSens==1:
         for i in range(gas.n_reactions):
             stirredReactor.add_sensitivity_reaction(i)
         
     if self.kineticSens and bool(self.moleFractionObservables)==False:
         except:
# Connect the upstream reservoir to the reactor with a mass flow controller
# (constant mdot). Set the mass flow rate to 1.25 sccm.
sccm = 1.25
vdot = sccm * 1.0e-6 / 60.0 * (
    (ct.one_atm / gas.P) * (gas.T / 273.15))  # m^3/s
mdot = gas.density * vdot  # kg/s
mfc = ct.MassFlowController(upstream, cstr, mdot=mdot)

# now create a downstream reservoir to exhaust into.
downstream = ct.Reservoir(gas)

# connect the reactor to the downstream reservoir with a valve, and set the
# coefficient sufficiently large to keep the reactor pressure close to the
# downstream pressure of 60 Torr.
v = ct.Valve(cstr, downstream, K=1.0e-9)

# create the network
network = ct.ReactorNet([cstr])

# In[3]:

# now integrate in time
t = 0.0
dt = 0.1

states = ct.SolutionArray(gas, extra=['t'])
while t < 300.0:
    t += dt
    network.advance(t)
    states.append(cstr.thermo.state, t=t)
r = ct.IdealGasReactor(gas)
# define inlet state
gas.TPX = T_inlet, p_inlet, comp_inlet
inlet = ct.Reservoir(gas)
# define injector state (gaseous!)
gas.TPX = T_injector, p_injector, comp_injector
injector = ct.Reservoir(gas)
# define outlet pressure (temperature and composition don't matter)
gas.TPX = T_ambient, p_outlet, comp_ambient
outlet = ct.Reservoir(gas)
# define ambient pressure (temperature and composition don't matter)
gas.TPX = T_ambient, p_ambient, comp_ambient
ambient_air = ct.Reservoir(gas)

# set up connecting devices
inlet_valve = ct.Valve(inlet, r)
injector_mfc = ct.MassFlowController(injector, r)
outlet_valve = ct.Valve(r, outlet)
piston = ct.Wall(ambient_air, r)

# convert time to crank angle
def crank_angle(t):
    return np.remainder(2 * np.pi * f * t, 4 * np.pi)

# set up IC engine parameters
V_oT = V_H / (epsilon - 1.)
A_piston = .25 * np.pi * d_piston ** 2
stroke = V_H / A_piston
r.volume = V_oT
piston.area = A_piston
def piston_speed(t):
Exemple #15
0
#####################################################################

# load reaction mechanism
gas = ct.Solution(reaction_mechanism, phase_name)

# define initial state and set up reactor
gas.TPX = T_inlet, p_inlet, comp_inlet
cyl = ct.IdealGasReactor(gas)
cyl.volume = V_oT

# define inlet state
gas.TPX = T_inlet, p_inlet, comp_inlet
inlet = ct.Reservoir(gas)

# inlet valve
inlet_valve = ct.Valve(inlet, cyl)
inlet_delta = np.mod(inlet_close - inlet_open, 4 * np.pi)
inlet_valve.valve_coeff = inlet_valve_coeff
inlet_valve.set_time_function(
    lambda t: np.mod(crank_angle(t) - inlet_open, 4 * np.pi) < inlet_delta)

# define injector state (gaseous!)
gas.TPX = T_injector, p_injector, comp_injector
injector = ct.Reservoir(gas)

# injector is modeled as a mass flow controller
injector_mfc = ct.MassFlowController(injector, cyl)
injector_delta = np.mod(injector_close - injector_open, 4 * np.pi)
injector_t_open = (injector_close - injector_open) / 2. / np.pi / f
injector_mfc.mass_flow_coeff = injector_mass / injector_t_open
injector_mfc.set_time_function(lambda t: np.mod(
Exemple #16
0

# Igniter modeled as pulsed radicals of Hydrogen
fwhm=0.2
amp=0.1
t0=1
igniter_mdot= lambda t:amp*math.exp(-(t-t0)**2*4*math.log(2)/fwhm**2)
ignite_pipe=ct.MassFlowController(igniter,combustor,mdot=igniter_mdot)

# The premixed reactants have to enter the combustor

mixer2combustor=ct.MassFlowController(mixer2,combustor)

#exhaust valve

v2=ct.Valve(combustor, exhaust2, K=100)

#reactor Network

sim=ct.ReactorNet([mixer2, combustor])


#time stepping

t_init2=0
temp=numpy.zeros(100)
comp=numpy.zeros(100)

tfinal = 6.0
tnow = 0.0
Tprev = combustor.T
Exemple #17
0
def JSR_isothermal_stdst(Temps,
                         gas,
                         Pressure,
                         concentrations,
                         residenceTime,
                         reactorVolume,
                         pressureValveCoefficient=0.01,
                         maxsimulationTime=1000):
    stirredReactor_list = []
    gas_List = []
    for i in np.arange(len(Temps)):
        # Inlet gas conditions
        reactorTemperature = Temps[i]  #Kelvin
        reactorPressure = Pressure  #in atm.
        gas.TPX = reactorTemperature, reactorPressure, concentrations
        # Reactor parameters
        # Instrument parameters

        # This is the "conductance" of the pressure valve and will determine its efficiency in
        # holding the reactor pressure to the desired conditions.
        pressureValveCoefficient = pressureValveCoefficient

        # This parameter will allow you to decide if the valve's conductance is acceptable. If there
        # is a pressure rise in the reactor beyond this tolerance, you will get a warning
        maxPressureRiseAllowed = 0.001

        # Simulation termination criterion
        maxSimulationTime = maxsimulationTime  # seconds
        fuelAirMixtureTank = ct.Reservoir(gas)
        exhaust = ct.Reservoir(gas)

        stirredReactor = ct.IdealGasReactor(gas,
                                            energy='off',
                                            volume=reactorVolume)

        massFlowController = ct.MassFlowController(upstream=fuelAirMixtureTank,
                                                   downstream=stirredReactor,
                                                   mdot=stirredReactor.mass /
                                                   residenceTime)

        pressureRegulator = ct.Valve(upstream=stirredReactor,
                                     downstream=exhaust,
                                     K=pressureValveCoefficient)

        reactorNetwork = ct.ReactorNet([stirredReactor])

        # now compile a list of all variables for which we will store data
        columnNames = [
            stirredReactor.component_name(item)
            for item in range(stirredReactor.n_vars)
        ]
        columnNames = ['pressure'] + columnNames

        # use the above list to create a DataFrame
        timeHistory = pd.DataFrame(columns=columnNames)

        # Start the stopwatch
        tic = time.time()

        # Set simulation start time to zero
        t = 0
        counter = 1
        while t < maxSimulationTime:
            t = reactorNetwork.step()

            # We will store only every 10th value. Remember, we have 1200+ species, so there will be
            # 1200 columns for us to work with
            if (counter % 10 == 0):
                #Extract the state of the reactor
                state = np.hstack([
                    stirredReactor.thermo.P, stirredReactor.mass,
                    stirredReactor.volume, stirredReactor.T,
                    stirredReactor.thermo.X
                ])

                #Update the dataframe
                timeHistory.loc[t] = state

            counter += 1

        # Stop the stopwatch
        toc = time.time()

        print('Simulation Took {:3.2f}s to compute, with {} steps'.format(
            toc - tic, counter))
        #state = np.hstack([stirredReactor.thermo.P, stirredReactor.mass,
        #stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X])
        #for j in np.arange(len(speciesName)):
        #component_final_X[i,j] = stirredReactor.get_state()[stirredReactor.component_index(speciesName[j])]
        #component_final_X[i,j] = state[stirredReactor.component_index(speciesName[j])+1]
        # We now check to see if the pressure rise during the simulation, a.k.a the pressure valve
        # was okay
        pressureDifferential = timeHistory['pressure'].max(
        ) - timeHistory['pressure'].min()
        if (abs(pressureDifferential / reactorPressure) >
                maxPressureRiseAllowed):
            print(
                "WARNING: Non-trivial pressure rise in the reactor. Adjust K value in valve"
            )

        stirredReactor_list.append(stirredReactor)

    #%matplotlib notebook

    #plt.style.use('ggplot')
    #plt.style.use('seaborn-pastel')

    #plt.rcParams['axes.labelsize'] = 18
    #plt.rcParams['xtick.labelsize'] = 14
    #plt.rcParams['ytick.labelsize'] = 14
    #plt.rcParams['figure.autolayout'] = True

    #plt.figure()
    #plt.semilogx(timeHistory.index, timeHistory['B2CO'],'-o')
    #plt.xlabel('Time (s)')
    #plt.ylabel(r'Mole Fraction : $X_{CO}$');
    return stirredReactor_list, gas
Exemple #18
0
def Engine(fname):
    import sys
    import numpy as np
    import cantera as ct
    import matplotlib.pyplot as plt
    import csv
    import time
    # from scipy.interpolate import interp1d
    import math
    from openpyxl import load_workbook

    def volume(t):
        theta = t * omega + IVC * np.pi / 180  #theta in radian; TDC corresponds to theta=0
        v = V_min * (1 + ((r_c - 1) / 2) *
                     (L / a + 1 - np.cos(theta) -
                      np.sqrt(pow(L / a, 2) - pow(np.sin(theta), 2))))
        return v

    def surfA(t):
        area = np.pi * math.pow(D, 2) / 4
        SA = 2 * area + np.pi * D * volume(t) / area
        return SA

    def vel(t):  #Note - the only input to the passed through function is time
        theta = t * omega + IVC * np.pi / 180  #TDC corresponds to theta=0
        z = np.sqrt(pow(L / a, 2) - pow(np.sin(theta), 2))
        v = omega * (V_min / A_p) * (
            (r_c - 1) / 2) * np.sin(theta) * (1 + np.cos(theta) / z)
        return v

    def qfluxB(
            t):  #Note - the only input to the passed through function is time
        rho = m_t / volume(t)
        T = (unb.mass * unb.thermo.T + bur.mass * bur.thermo.T) / (unb.mass +
                                                                   bur.mass)
        k = k_0 * pow(T, n_k)  #W/m-K, for air
        mu = mu_0 * pow(T, n_mu)  #kg/m-s, for air
        Re = rho * MPS * D / mu
        Nu = Nu_0 * pow(Re, n_Nu)
        h = Nu * k / D
        area = surfA(t) * bur.volume / volume(t)
        q = h * area * (bur.thermo.T - T_w) * HeatOn
        return q

    def qfluxU(
            t):  #Note - the only input to the passed through function is time
        rho = m_t / volume(t)
        T = (unb.mass * unb.thermo.T + bur.mass * bur.thermo.T) / (unb.mass +
                                                                   bur.mass)
        k = k_0 * pow(T, n_k)  #W/m-K, for air
        mu = mu_0 * pow(T, n_mu)  #kg/m-s, for air
        Re = rho * MPS * D / mu
        Nu = Nu_0 * pow(Re, n_Nu)
        h = Nu * k / D
        area = surfA(t) * unb.volume / volume(t)
        q = h * area * (unb.thermo.T - T_w) / A_p * HeatOn
        return q

    def mflow(
            t):  #Note - the only input to the passed through function is time
        theta = t * omega + IVC * np.pi / 180  #TDC corresponds to theta=0
        if (theta >= theta_0r) and (theta <= theta_99r):
            # dxb=1/Deltathetar
            dxb = b * (m + 1) / Deltathetar * pow(
                ((theta - theta_0r) / Deltathetar), m) * math.exp(-b * pow(
                    ((theta - theta_0r) / Deltathetar), m + 1))
        else:
            dxb = 0
        mf = burnflag * m_t * omega * dxb  #mass flow unb to bur

        return mf

    ##  MAIN  - read inputs
    wb = load_workbook(fname)
    ws = wb.active
    r_c = ws['A1'].value  # compression ratio
    L = ws['A2'].value  # con rod length [m]
    D = ws['A3'].value  # bore [m]
    stroke = ws['A4'].value  # stroke [m]
    IVC = ws['A5'].value  # IVC crank angle where TDC = 0
    EVO = ws['A6'].value  # EVO crank angle where TDC = 0
    CrevOn = ws['A7'].value  # Flag to determine whether to use crevice model
    HeatOn = ws[
        'A8'].value  # Flag to determine whether to use heat transfer model
    crevfrac = ws['A9'].value  # crevice volume fraction of minimum volume
    RPM = ws['A10'].value  # engine speed
    b = ws['A11'].value  # Wiebe b parameter
    m = ws['A12'].value  # Wiebe m parameter
    theta_0 = ws['A13'].value  # Wiebe combustion start parameter
    Deltatheta = ws['A14'].value  # Wiebe combustion duration parameter
    eta_c = ws['A15'].value  # combustion efficiency
    T_IVC = ws['A16'].value  # IVC temperature [K]
    P_IVC = ws['A17'].value  # IVC pressure [bar]
    T_w = ws['A18'].value  # wall temperature [K]
    RON = ws['A19'].value  # fuel RON
    MON = ws['A20'].value  # fuel MON
    Phi = ws['A21'].value  # equivalence ratio
    burnflag = ws[
        'A22'].value  # fraction of mass transferred out of unburned zone
    k_0 = ws['A23'].value  # thermal conductivity [W/m-K]
    n_k = ws['A24'].value  # thermal conductivity temperature exponent
    mu_0 = ws['A25'].value  # dynamic viscosity [kg/m-s]
    n_mu = ws['A26'].value  # viscosity temperature exponent
    Nu_0 = ws['A27'].value  # Nusselt number correlation scaling constant
    n_Nu = ws[
        'A28'].value  # Nusselt number correlation Reynolds number exponent
    Chemflag = ws['A29'].value  # End gas chemistry flag; 1=on
    Y_EGR = ws['A30'].value  # EGR mass fraction
    Y_f_ref = ws['A31'].value  # mass fraction of FUEL to the reformer
    Phi_ref = ws['A32'].value  # reformer equivalence ratio
    Ref_comp = ws[
        'A33'].value  # reformer composition: 0=PCI; 1=equilibriu; 2=ideal
    mechanism = ws['A34'].value  # kinetic mechanism

    ## Engine geometry calculations
    a = stroke / 2  # crank radius
    A_p = np.pi * D * D / 4  # piston area [m^2]
    V_disp = A_p * stroke  # displacement volume [m^3]
    V_min = V_disp / (r_c - 1)  # TDC volume [m^3]
    V_max = V_min + V_disp  # BDC volume [m^3]
    MPS = 2 * stroke * RPM / 60  #mean piston speed [m/s]

    ## Engine operating conditions
    theta_0r = theta_0 * np.pi / 180  #start of combustion in radians
    Deltathetar = Deltatheta * np.pi / 180  #combustion duration in radians
    theta_99r = theta_0r + Deltathetar * math.pow(
        -math.log(0.01) / b, 1 / m)  #99% of mass burn for Wiebe
    omega = RPM * 2 * np.pi / 60  #rotation rate in radian per second based on RPM

    T_0 = T_IVC  # K
    P_0 = 1e5 * P_IVC  # Pa
    ct.suppress_thermo_warnings()
    env = ct.Solution('air.xml')
    env.TP = T_w, P_0
    gas = ct.Solution(mechanism)
    x_init = np.zeros(gas.X.shape)

    c4 = ws['C41'].value  #0.01      #n-butane
    c5 = ws['C42'].value  #0.0      #iso-pentane
    c5_2 = ws['C43'].value  #0.04   #n-pentane
    ic8 = ws['C44'].value  #0.93    #Iso-octane
    c6 = ws['C45'].value  #0.0      #added for 1-hexene
    nc7 = ws['C46'].value  #0.0    #n-heptane
    c7_2 = ws['C47'].value  #0.0    #tolune
    tmb = ws['C48'].value  #0.02     #1,2,4 Trimethyl benzene
    eth = ws['C49'].value  #0       #Ethanol

    x_init[gas.species_index('C4H10')] = c4
    x_init[gas.species_index('IC5H12')] = c5
    x_init[gas.species_index('NC5H12')] = c5_2
    x_init[gas.species_index('C6H12-1')] = c6
    x_init[gas.species_index('NC7H16')] = nc7
    x_init[gas.species_index('C6H5CH3')] = c7_2
    x_init[gas.species_index('IC8')] = ic8
    x_init[gas.species_index('T124MBZ')] = tmb
    x_init[gas.species_index('C2H5OH')] = eth
    #    x_init[gas.species_index('NO')]=150e-6  #150 ppm NO

    ## Determine global composition
    nC = (4 * c4) + (5 * c5) + (5 * c5_2) + (6 * c6) + (7 * nc7) + (
        8 * ic8) + (9 * tmb) + (2 * eth) + (7 * c7_2)
    nH = (10 * c4) + (12 * c5) + (12 * c5_2) + (12 * c6) + (16 * nc7) + (
        18 * ic8) + (12 * tmb) + (6 * eth) + (8 * c7_2)
    nO = 1 * eth

    x_init[gas.species_index('O2')] = (nC + nH / 4 - nO / 2) / Phi
    x_init[gas.species_index('N2')] = 3.76 * (nC + nH / 4 - nO / 2) / Phi
    gas.TPX = 300, 1e5, x_init
    y_global = gas.Y

    ## Determine EGR composition
    keep = np.zeros(gas.X.shape)
    keep[gas.species_index('N2')] = 1
    keep[gas.species_index('O2')] = 1
    keep[gas.species_index('CO2')] = 1
    keep[gas.species_index('CO')] = 1
    keep[gas.species_index('H2O')] = 1
    keep[gas.species_index('H2')] = 1
    gas.TPY = 300, 1e5, y_global
    gas.equilibrate('HP')  #find equilibrium concentration
    y_EGR = gas.Y * keep
    # y_EGR[7:86]=0;  #set minor species to zero; based on MECHANISM
    gas.Y = y_EGR  #use Cantera to renormalize mass fraction
    y_EGR = gas.Y

    y_eng = 1 / (1 + Y_EGR) * y_global + +Y_EGR / (1 + Y_EGR) * y_EGR

    gas.TPX = 298, 1e5, x_init
    delta_uf = gas.standard_int_energies_RT * (ct.gas_constant *
                                               298) / gas.molecular_weights

    tmax = (EVO - IVC) / 6 / RPM  # time for one revolution
    step = 8 * (EVO - IVC)
    tim = np.linspace(tmax / step, tmax, step)
    theta = IVC + omega * tim * 180 / np.pi

    ## Cantera reactor setup
    gas.TPY = T_0, P_0, y_eng  #reactants
    # gas.set_multiplier(1)   #option to make reactants inert
    unb = ct.IdealGasReactor(gas)
    if Chemflag == 0:
        unb.chemistry_enabled = False

    gas.TPY = T_0, P_0, y_eng  #products
    gas.equilibrate(
        'HP'
    )  #make the products hot so that mass will burn when it moves into products
    bur = ct.IdealGasReactor(gas)

    r3 = ct.Reservoir(env)  #outside world

    gas.TPY = T_w, P_0, y_eng
    crev = ct.IdealGasReactor(gas)  #crevices
    crev.chemistry_enabled = False  #no reaction in crevices

    piston = ct.Wall(unb, r3, velocity=vel, A=A_p, Q=qfluxU)
    flame = ct.Wall(
        unb, bur, K=0.01,
        A=A_p)  #expansion rate K set to lowest value possible to have const P
    topland = ct.Wall(
        crev, r3, U=1e3)  #heat xfer rate set to keep close to wall temperature
    head = ct.Wall(bur, r3, A=1, Q=qfluxB)

    mfc = ct.MassFlowController(unb, bur, mdot=mflow)
    V1 = ct.Valve(unb, crev)
    V1.set_valve_coeff(1e-6 * CrevOn)
    V2 = ct.Valve(crev, bur)
    V2.set_valve_coeff(1e-6 * CrevOn)

    sim = ct.ReactorNet([unb, bur, crev])
    sim.atol = 1e-12
    sim.rtol = 1e-6
    initvol = 1e-3
    unb.volume = (1 - initvol) * volume(0)
    bur.volume = initvol * volume(0)
    crev.volume = crevfrac * V_min

    m_t = unb.mass + bur.mass + crev.mass

    vol = np.zeros(step)
    T = np.zeros(step)
    vol2 = np.zeros(step)
    P = np.zeros(step)
    outdat = np.zeros((step, 13))
    SpecMatrix = np.zeros((step, gas.X.shape[0]))
    #burnflag=0.82  #flag to stop combustion if unburned mass gets too low
    #    y_old=unb.thermo.Y

    for i in range(step):  #step):
        if math.fmod(i, 32) == 0:
            print(i / step)
        sim.advance(tim[i])
        # burnflag=unb.mass/m_t
        # if unb.mass/m_t < 1-eta_c:
        #     burnflag=0
        outdat[i, 0] = IVC + tim[i] * RPM / 60 * 360
        outdat[i, 1] = bur.thermo.P / 1e5
        outdat[i, 2] = bur.thermo.T
        outdat[i, 3] = bur.mass / m_t
        outdat[i, 4] = qfluxB(tim[i])
        outdat[i, 5] = unb.thermo.T
        outdat[i, 6] = qfluxU(tim[i]) * A_p
        outdat[i, 7] = unb.mass / m_t
        outdat[i, 8] = crev.mass / m_t
        outdat[i, 9] = volume(sim.time)
        outdat[i, 10] = -(unb.kinetics.net_production_rates *
                          unb.thermo.molecular_weights
                          ).dot(delta_uf) * unb.volume * 60 / (RPM * 360)
        outdat[i, 11] = m_t
        outdat[i, 12] = ct.gas_constant / gas.mean_molecular_weight
        outdat[i, 13] = volume(tim[i])

        SpecMatrix[i] = gas.X
#        outdat[i,10]=-(unb.thermo.Y-y_old).dot(delta_uf)/(tim[2]-tim[1])*unb.mass
#        y_old=unb.thermo.Y

    return outdat, SpecMatrix
Exemple #19
0
maxPressureRiseAllowed = 0.01

maxSimulationTime = 100  # seconds

fuelAirMixtureTank = ct.Reservoir(gas)
exhaust = ct.Reservoir(gas)

stirredReactor = ct.IdealGasReactor(gas, energy='on', volume=reactorVolume)

massFlowController = ct.MassFlowController(upstream=fuelAirMixtureTank,
                                           downstream=stirredReactor,
                                           mdot=stirredReactor.mass /
                                           residenceTime)

pressureRegulator = ct.Valve(upstream=stirredReactor,
                             downstream=exhaust,
                             K=pressureValveCoefficient)

reactorNetwork = ct.ReactorNet([stirredReactor])
# now compile a list of all variables for which we will store data
columnNames = [
    stirredReactor.component_name(item)
    for item in range(stirredReactor.n_vars)
]
columnNames = ['pressure'] + columnNames

# use the above list to create a DataFrame
timeHistory = pd.DataFrame(columns=columnNames)

# Start the stopwatch
tic = time.time()
Exemple #20
0
def JSR_steadystate2(gas,resTime,volume,kinetic_sens=0,physical_sens=0,observables=[],physical_params=['T','P'],energycon='off',pressureValveCoefficient=0.01,maxsimulationTime=1000,initial_conditions_gas=0,tempsens=0):
    # Inlet gas conditions are passed into function in the "gas" object, which is a cantera object
    # Reactor parameters passed into function as resTime and volume.  Residence time and volume of JSR
    #kinetic sens and physical sens are optional parameters which are set to zero by default.  Set them to 1 to
    #calculate sensitivity based on kinetic or physical parameters.  If these are set to 1 you must pass
    #an array of all observables to calculate sensitivities for
    
    simtype='jsr'
    reactorPressure=gas.P
    # This is the "conductance" of the pressure valve and will determine its efficiency in 
    # holding the reactor pressure to the desired conditions. It is an optional parameter
    pressureValveCoefficient=pressureValveCoefficient

    # This parameter will allow you to decide if the valve's conductance is acceptable. If there
    # is a pressure rise in the reactor beyond this tolerance, you will get a warning
    maxPressureRiseAllowed = 0.001

    # Simulation termination criterion
    #maxSimulationTime = maxsimulationTime # seconds.  An optional parameter
    fuelAirMixtureTank = ct.Reservoir(gas)
    exhaust = ct.Reservoir(gas)
    if initial_conditions_gas==0:
        stirredReactor = ct.IdealGasReactor(gas, energy=energycon, volume=volume)
        mdot=stirredReactor.mass/resTime
    else:
        stirredReactor = ct.IdealGasReactor(initial_conditions_gas,energy=energycon,volume=volume)
        dummyReactor = ct.IdealGasReactor(gas,energy=energycon,volume=volume)
        mdot=dummyReactor.mass/resTime
    
    
        
    massFlowController = ct.MassFlowController(upstream=fuelAirMixtureTank,downstream=stirredReactor,mdot=mdot)

    pressureRegulator = ct.Valve(upstream=stirredReactor,downstream=exhaust,K=pressureValveCoefficient)

    reactorNetwork = ct.ReactorNet([stirredReactor])
    
    #This block adds kinetic sensitivity parameters for all reactions if desired.  
    if kinetic_sens==1 and bool(observables):
        for i in range(gas.n_reactions):
            stirredReactor.add_sensitivity_reaction(i)
            
    if kinetic_sens==1 and bool(observables)==False:
        print('Please supply a non-empty list of observables for sensitivity analysis or set kinetic_sens=0')
        
    #if physical_sens==1 and bool(observables):
        #print('Placeholder')
    if physical_sens==1 and bool(observables)==False:
        print('Please supply a non-empty list of observables for sensitivity analysis or set physical_sens=0')

    # now compile a list of all variables for which we will store data
    columnNames = [stirredReactor.component_name(item) for item in range(stirredReactor.n_vars)]
    columnNames = ['pressure'] + columnNames

    # use the above list to create a DataFrame
    timeHistory = pd.DataFrame(columns=columnNames)

    # Start the stopwatch
    tic = time.time()
    
    
    #Names=[]
    #for l in np.arange(stirredReactor.n_vars):
        #Names.append(stirredReactor.component_name(l))
    #global b
    
    #Names = [stirredReactor.component_name(item) for item in range(stirredReactor.n_vars)]
    #state = np.hstack([stirredReactor.mass, 
                   #stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X])
    #print(state)
    #b=pd.DataFrame(data=state).transpose()
    #b.columns=Names
    
    #Establish a matrix to hold sensitivities for kinetic parameters, along with tolerances
    if kinetic_sens==1 and bool(observables):
        #senscolumnNames = ['Reaction']+observables     
        senscolumnNames = observables
        #sensArray = pd.DataFrame(columns=senscolumnNames)
        senstempArray = np.zeros((gas.n_reactions,len(observables)))
        reactorNetwork.rtol_sensitivity = 1.0e-6
        reactorNetwork.atol_sensitivity = 1.0e-6
        
    dk=0.01    
        
    if physical_sens==1 and bool(observables):
        #psenscolumnNames = ['Parameter'] + observables
        #psensArray = pd.DataFrame(columns=senscolumnNames)
        pIndex=[[gas.T],physical_params,observables]
        psenstempArray = np.zeros((len(observables),len(physical_params)))
        tempSol=[]
        conditions=gas.TPX
        for i in np.arange(len(physical_params)):
            if physical_params[i]=='T':
                gas.TPX=conditions[0]+dk,conditions[1],conditions[2]
            if physical_params[i]=='P':
                gas.TPX=conditions[0],conditions[1]+dk,conditions[2]
            
            tempMixTank=ct.Reservoir(gas)
            tempExhaust = ct.Reservoir(gas)
            tempReactor=ct.IdealGasReactor(gas,energy=energycon,volume=volume)
            tempMassFlowCt=ct.MassFlowController(upstream=tempMixTank,downstream=tempReactor,mdot=tempReactor.mass/resTime)
            tempPresReg=ct.Valve(upstream=tempReactor,downstream=tempExhaust,K=pressureValveCoefficient)
            tempNetwork=ct.ReactorNet([tempReactor])
            tempNetwork.advance_to_steady_state()
            tempSol.append(tempReactor.get_state())
            gas.TPX=conditions
    reactorNetwork.rtol=1e-10
    resid=reactorNetwork.advance_to_steady_state(return_residuals=True)
    #print(resid)
    #print(reactorNetwork.rtol)
    final_pressure=stirredReactor.thermo.P
    global b
    b=reactorNetwork.sensitivities()
    if kinetic_sens==1 and bool(observables):
        for k in np.arange(len(observables)):
            for j in np.arange(gas.n_reactions):
                try:
                    senstempArray[j,k]=reactorNetwork.sensitivity(observables[k],j)
                except:
                    senstempArray[j,k]=-1
                
        #sensArray['Reaction']=gas.reaction_equations()        
        #sensArray[observables]=senstempArray.T   
        #temp = sensArray.as_matrix()
        kIndex = [[gas.T],gas.reaction_equations(),senscolumnNames]
        
        
        
    if physical_sens==1 and bool(observables):
        for k in np.arange(len(observables)):
            for j in np.arange(len(['T','P'])):
                psenstempArray[j,k]=np.log10(stirredReactor.get_state()[stirredReactor.component_index(observables[k])])-np.log10(tempSol[j][stirredReactor.component_index(observables[k])])
                psenstempArray[j,k]=np.divide(psenstempArray[j,k],np.log10(dk))
    
    #state = np.hstack([stirredReactor.thermo.P, stirredReactor.mass, 
                   #stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X]) 
        
        # Stop the stopwatch
    toc = time.time()

    print('Simulation Took {:3.2f}s to compute'.format(toc-tic))
    columnNames = []
    #Store solution to a solution array
    #for l in np.arange(stirredReactor.n_vars):
        #columnNames.append(stirredReactor.component_name(l))
    columnNames=[stirredReactor.component_name(item) for item in range(stirredReactor.n_vars)]
    #state=stirredReactor.get_state()
    state=np.hstack([stirredReactor.mass, 
                   stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X])
    data=pd.DataFrame(state).transpose()
    data.columns=columnNames
       
    # We now check to see if the pressure rise during the simulation, a.k.a the pressure valve
    # was okay
    pressureDifferential = timeHistory['pressure'].max()-timeHistory['pressure'].min()
    if(abs(pressureDifferential/reactorPressure) > maxPressureRiseAllowed):
        print("WARNING: Non-trivial pressure rise in the reactor. Adjust K value in valve")
        
    if kinetic_sens==1 and bool(observables) and physical_sens!=1:
        modelData=model_data(simtype,kinetic_sens=np.expand_dims(senstempArray,axis=0),Solution=data,Index=kIndex)
        modelData.add_final_pressure(final_pressure)
        modelData.add_solver_time(toc-tic)
        return modelData
    if physical_sens==1 and bool(observables) and kinetic_sens!=1:
        
        modelData=model_data(simtype,physical_sens=np.expand_dims(psenstempArray,axis=0),Solution=data,pIndex=pIndex)
        modelData.add_final_pressure(final_pressure)
        modelData.add_solver_time(toc-tic)
        return modelData
    if physical_sens==1 and bool(observables) and kinetic_sens==1:
        
        modelData=model_data(simtype,physical_sens=np.expand_dims(psenstempArray,axis=0),kinetic_sens=np.expand_dims(senstempArray,axis=0),Solution=data,Index=kIndex,pIndex=pIndex)
        modelData.add_final_pressure(final_pressure)
        modelData.add_solver_time(toc-tic)
        return modelData
    else:
        modelData=model_data(simtype,Solution=data)
        modelData.add_final_pressure(final_pressure)
        modelData.add_solver_time(toc-tic)
        return modelData
Exemple #21
0
exhaust = ct.Reservoir(gas)
exaustP = ct.one_atm


#defining of necessary funciotns
def kappa(gas):
    return gas.cp / gas.cv


def critical_flow(gasin, gasinP, gasinT, gasinmw, k, gasoutP, area):
    R = ct.gas_constant / gasinmw
    return (area * gasinP * math.sqrt(k / (R * gasinT)) *
            (2 / (k + 1))**((k + 1) / (2 * (k - 1)))) / (gasinP - gasoutP)


v1 = ct.Valve(fuel, combustion_chamber)
v2 = ct.Valve(oxidizer, combustion_chamber)
v3 = ct.Valve(combustion_chamber, exhaust)

#igniter setup
fwhm = 0.008
amplitude = 0.01
t0 = 0.05
igniter_mdot = lambda t: amplitude * math.exp(-(t - t0)**2 * 4 * math.log(2) /
                                              fwhm**2)
m3 = ct.MassFlowController(igniter, combustion_chamber, mdot=igniter_mdot)

states = ct.SolutionArray(gas, extra=['t', 'mass', 'v'])

# the simulation only contains one reactor
sim = ct.ReactorNet([combustion_chamber])
Exemple #22
0
    def run_single(self):
        
        gas=self.processor.solution
        reactorPressure=gas.P
        self.reactorPressure=self.processor.solution.P
        pressureValveCoefficient=self.pvalveCoefficient
        maxPressureRiseAllowed=self.maxPrise
        
        print(maxPressureRiseAllowed,self.reactorPressure,pressureValveCoefficient)
        #Build the system components for JSR
        pretic=time.time()
        
        if bool(self.observables) and self.kineticSens==1:
            ###################################################################
            #Block to create temp reactor network to pre-solve JSR without kinetic sens
            ct.suppress_thermo_warnings()
            tempgas=ct.Solution(self.processor.cti_path)
            tempgas.TPX=self.processor.solution.TPX
            tempfuelAirMixtureTank=ct.Reservoir(tempgas)
            tempexhaust=ct.Reservoir(tempgas)
            tempstirredReactor=ct.IdealGasReactor(tempgas,energy=self.energycon,
                                                  volume=self.reactor_volume)
            tempmassFlowController=ct.MassFlowController(upstream=tempfuelAirMixtureTank,
                                                         downstream=tempstirredReactor,
                                                         mdot=tempstirredReactor.mass/self.residence_time)
            tempPressureRegulator=ct.Valve(upstream=tempstirredReactor,downstream=tempexhaust,
                                           K=pressureValveCoefficient)
            
            tempreactorNetwork=ct.ReactorNet([tempstirredReactor])
            tempreactorNetwork.rtol = self.rtol
            tempreactorNetwork.atol = self.atol
            print(self.rtol,self.atol)
            tempreactorNetwork.advance_to_steady_state()
            ###################################################################
            #reactorNetwork.advance_to_steady_state()
            #reactorNetwork.reinitialize()
        
        elif self.kineticSens and bool(self.observables)==False:
            #except:
                print('Please supply a non-empty list of observables for sensitivity analysis or set kinetic_sens=0')        
        pretoc=time.time()
        
        print('Presolving Took {:3.2f}s to compute'.format(pretoc-pretic))        
        fuelAirMixtureTank=ct.Reservoir(self.processor.solution)
        exhaust=ct.Reservoir(self.processor.solution)
        if bool(self.observables) and self.kineticSens==1:
            stirredReactor=ct.IdealGasReactor(tempgas,energy=self.energycon,
                                          volume=self.reactor_volume)
        else:
            stirredReactor=ct.IdealGasReactor(self.processor.solution,energy=self.energycon,
                                          volume=self.reactor_volume)
        #stirredReactor=ct.IdealGasReactor(self.processor.solution,energy=self.energycon,
        #                                  volume=self.reactor_volume)    
        massFlowController=ct.MassFlowController(upstream=fuelAirMixtureTank,
                                                 downstream=stirredReactor,
                                                 mdot=stirredReactor.mass/self.residence_time)
        pressureRegulator=ct.Valve(upstream=stirredReactor,downstream=exhaust,K=pressureValveCoefficient)
        reactorNetwork=ct.ReactorNet([stirredReactor])
        if bool(self.observables) and self.kineticSens==1:
            for i in range(gas.n_reactions):
                stirredReactor.add_sensitivity_reaction(i)
        reactorNetwork.rtol_sensitivity=0.0000001
        reactorNetwork.atol_sensitivity=0.00000001
        print('Sens tols:'+str(reactorNetwork.atol_sensitivity)+', '+str(reactorNetwork.rtol_sensitivity))
        # now compile a list of all variables for which we will store data
        columnNames = [stirredReactor.component_name(item) for item in range(stirredReactor.n_vars)]
        columnNames = ['pressure'] + columnNames

        # use the above list to create a DataFrame
        timeHistory = pd.DataFrame(columns=columnNames)

        # Start the stopwatch
        tic = time.time()
        reactorNetwork.rtol = self.rtol
        reactorNetwork.atol = self.atol    
        #reactorNetwork.max_err_test_fails= 10000
        #print(reactorNetwork.max_err_test_fails)
        if self.physicalSens==1 and bool(self.observables)==False:
            #except:
                print('Please supply a non-empty list of observables for sensitivity analysis or set physical_sens=0')
        
        #Establish a matrix to hold sensitivities for kinetic parameters, along with tolerances
        if self.kineticSens==1 and bool(self.observables):
            #senscolumnNames = ['Reaction']+observables     
            senscolumnNames = self.observables
            #sensArray = pd.DataFrame(columns=senscolumnNames)
            #senstempArray = np.zeros((gas.n_reactions,len(observables)))
            dfs = [pd.DataFrame() for x in range(len(self.observables))]
            #tempArray = [np.zeros(self.processor.solution.n_reactions) for x in range(len(self.observables))]
            #stirredReactor.thermo.X=tempstirredReactor.thermo.X
                
        
        posttic=time.time()
#        for steps in range(10):
#            reactorNetwork.step()
        reactorNetwork.advance_to_steady_state()
        posttoc=time.time()
        print('Main Solver Took {:3.2f}s to compute'.format(posttoc-posttic))
        final_pressure=stirredReactor.thermo.P
        sens=reactorNetwork.sensitivities()
        #print(sens[:,787])
        #print(gas.species_names)
        #print(self.observables)
        #print(sens)
        if self.kineticSens==1 and bool(self.observables):
            #print((pd.DataFrame(sens[0,:])).transpose())
            #test=pd.concat([pd.DataFrame(),pd.DataFrame(sens[0,:]).transpose()])
            #print(test)
            for k in range(len(self.observables)):
                index=gas.species_names.index(self.observables[k])
                dfs[k] = dfs[k].append(((pd.DataFrame(sens[index+3,:])).transpose()),ignore_index=True)
                #dfs[k]=pd.concat([dfs[k],pd.DataFrame(sens[k,:]).transpose()])
                #dfs[k]=pd.DataFrame(sens[k,:]).transpose()
            #print(dfs)  
        toc = time.time()
        print('Simulation Took {:3.2f}s to compute'.format(toc-tic)+' at T = '+str(stirredReactor.T))
        #print(dfs[0])
        columnNames = []
        #Store solution to a solution array
        #for l in np.arange(stirredReactor.n_vars):
            #columnNames.append(stirredReactor.component_name(l))
        columnNames=[stirredReactor.component_name(item) for item in range(stirredReactor.n_vars)]
        #state=stirredReactor.get_state()
        state=np.hstack([stirredReactor.mass, 
                   stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X])
        data=pd.DataFrame(state).transpose()
        data.columns=columnNames
        pressureDifferential = timeHistory['pressure'].max()-timeHistory['pressure'].min()
        if(abs(pressureDifferential/self.reactorPressure) > maxPressureRiseAllowed):
            #except:
                print("WARNING: Non-trivial pressure rise in the reactor. Adjust K value in valve")
        
        if self.kineticSens==1:
            numpyMatrixsksens = [dfs[dataframe].values for dataframe in range(len(dfs))]
            self.kineticSensitivities = np.dstack(numpyMatrixsksens)
            #print(np.shape(self.kineticSensitivities))
            self.solution=data
            return (self.solution,self.kineticSensitivities)
        else:
            self.solution=data
            return (self.solution,[])
Exemple #23
0
def combustor():

    # use reaction mechanism GRI-Mech 3.0

    gas = ct.Solution('gri30.xml')

    # create a reservoir for the fuel inlet, and set to pure methane.
    fuelX = 'CH4:' + eCH4.get() + ',C2H6:' + eC2H6.get() + ',N2:' + eN2.get()
    gas.TPX = float(eFuelT.get()), ct.one_atm, fuelX
    fuel_in = ct.Reservoir(gas)
    fuel_mw = gas.mean_molecular_weight

    # use predefined function Air() for the air inlet
    air = ct.Solution('air.xml')
    air_in = ct.Reservoir(air)
    air_mw = air.mean_molecular_weight

    # to ignite the fuel/air mixture, we'll introduce a pulse of radicals. The
    # steady-state behavior is independent of how we do this, so we'll just use a
    # stream of pure atomic hydrogen.
    gas.TPX = float(eCombustorT.get()), ct.one_atm, 'H:1.0'
    igniter = ct.Reservoir(gas)

    # create the combustor, and fill it in initially with N2
    gas.TPX = float(eCombustorT.get()), ct.one_atm, 'N2:1.0'
    combustor = ct.IdealGasReactor(gas)
    combustor.volume = 1.0

    # create a reservoir for the exhaust
    exhaust = ct.Reservoir(gas)

    # lean combustion, phi = 0.5
    equiv_ratio = 0.5

    # compute fuel and air mass flow rates
    factor = 0.1
    air_mdot = factor * 9.52 * air_mw
    fuel_mdot = factor * equiv_ratio * fuel_mw

    # create and install the mass flow controllers. Controllers m1 and m2 provide
    # constant mass flow rates, and m3 provides a short Gaussian pulse only to
    # ignite the mixture
    m1 = ct.MassFlowController(fuel_in, combustor, mdot=fuel_mdot)

    # note that this connects two reactors with different reaction mechanisms and
    # different numbers of species. Downstream and upstream species are matched by
    # name.
    m2 = ct.MassFlowController(air_in, combustor, mdot=air_mdot)

    # The igniter will use a Gaussian time-dependent mass flow rate.
    fwhm = 0.2
    amplitude = 0.1
    t0 = 1.0
    igniter_mdot = lambda t: amplitude * math.exp(-(t - t0)**2 * 4 * math.log(
        2) / fwhm**2)
    m3 = ct.MassFlowController(igniter, combustor, mdot=igniter_mdot)

    # put a valve on the exhaust line to regulate the pressure
    v = ct.Valve(combustor, exhaust, K=1.0)

    # the simulation only contains one reactor
    sim = ct.ReactorNet([combustor])

    # take single steps to 6 s, writing the results to a CSV file for later
    # plotting.
    tfinal = 4.0
    tnow = 0.0
    Tprev = combustor.T
    tprev = tnow
    states = ct.SolutionArray(gas, extra=['t', 'tres'])

    while tnow < tfinal:
        tnow = sim.step()
        tres = combustor.mass / v.mdot(tnow)
        Tnow = combustor.T
        if abs(Tnow - Tprev) > 1.0 or tnow - tprev > 2e-2:
            tprev = tnow
            Tprev = Tnow
            states.append(gas.state, t=tnow, tres=tres)

    states.write_csv('combustor.csv', cols=('t', 'T', 'tres', 'X'))

    #matplotlib
    plt.figure()
    plt.plot(states.t, states.T)
    plt.xlabel('Time [s]')
    plt.ylabel('Temperature [K]')
    plt.title('Temperature')
    plt.plot()
    plt.savefig('Temperature.png')

    plt.figure()
    plt.plot(states.t, states.P)
    plt.xlabel('Time [s]')
    plt.ylabel('Pressure [Pa]')
    plt.title('Pressure')
    plt.plot()
    plt.savefig('Pressure.png')

    plt.figure()
    plt.plot(states.t, states.X)
    plt.xlabel('Time [s]')
    plt.ylabel('Concentration H20')
    plt.title('H20')
    plt.plot()
    plt.savefig('X.png')

    print('OK!')
Exemple #24
0
T = 299.05 # temperature unit: K
mix_comp = 'IC8H18:1, O2:12.5, AR:75' # mixture composition. Molar ratio.

# Input the ic8 model
mixture = ct.Solution('ic8mech.xml')	# Set the state of the reactive mixture
mixture.TPX = T, P, mix_comp
air = ct.Solution('air.xml')

mixture_unr = ct.Solution('ic8mech_unr.xml')	# Set the state of the unreactive mixture
mixture_unr.TPX = T, P, mix_comp

r1 = ct.IdealGasReactor(mixture)	# Set core zone
r2 = ct.IdealGasReactor(mixture_unr)	# Set boundary layer zone
r3 = ct.IdealGasReactor(mixture_unr)	# Set crevice zone

v1 = ct.Valve(r1,r2)			# Add a valve between the main combustion chamber and the boundary layer
v2 = ct.Valve(r2,r3)			# Add a valve between the boundary layer and the crevice

Env = ct.Reservoir(air)			# Set the environment
w1 = ct.Wall(Env, r1)
w2 = ct.Wall(Env, r2)
w3 = ct.Wall(Env, r3)

######################################################################################################################
#

v1.set_valve_coeff(5E-6)  		# Set mass flow rate for valve1
v2.set_valve_coeff(5E-6)  		# Set mass flow rate for valve2

# Set the geometry of the RCM
dia_2 = 50.8E-3 # Diameter of the combustion chamber.
Exemple #25
0
# note that this connects two reactors with different reaction mechanisms and
# different numbers of species. Downstream and upstream species are matched by
# name.
m2 = ct.MassFlowController(air_in, combustor, mdot=air_mdot)

# The igniter will use a Gaussian time-dependent mass flow rate.
fwhm = 0.2
amplitude = 0.1
t0 = 1.0
igniter_mdot = lambda t: amplitude * math.exp(-(t - t0)**2 * 4 * math.log(2) /
                                              fwhm**2)
m3 = ct.MassFlowController(igniter, combustor, mdot=igniter_mdot)

# put a valve on the exhaust line to regulate the pressure
v = ct.Valve(combustor, exhaust, K=1.0)

# the simulation only contains one reactor
sim = ct.ReactorNet([combustor])

# take single steps to 6 s, writing the results to a CSV file for later
# plotting.
tfinal = 6.0
tnow = 0.0
Tprev = combustor.T
tprev = tnow
states = ct.SolutionArray(gas, extra=['t', 'tres'])

while tnow < tfinal:
    tnow = sim.step()
    tres = combustor.mass / v.mdot(tnow)
Exemple #26
0
downstream = ct.Reservoir(gas_b)

# Create a reactor for the mixer. A reactor is required instead of a
# reservoir, since the state will change with time if the inlet mass flow
# rates change or if there is chemistry occurring.
gas_b.TPX = 300.0, ct.one_atm, 'O2:0.21, N2:0.78, AR:0.01'
mixer = ct.Reactor(gas_b)

# create two mass flow controllers connecting the upstream reservoirs to the
# mixer, and set their mass flow rates to values corresponding to
# stoichiometric combustion.
mfc1 = ct.MassFlowController(res_a, mixer, mdot=rho_a * 2.5 / 0.21)
mfc2 = ct.MassFlowController(res_b, mixer, mdot=rho_b * 1.0)

# connect the mixer to the downstream reservoir with a valve.
outlet = ct.Valve(mixer, downstream, K=10.0)

sim = ct.ReactorNet([mixer])

# Since the mixer is a reactor, we need to integrate in time to reach steady
# state. A few residence times should be enough.
print('{:>14s} {:>14s} {:>14s}  {:>14s}  {:>14s}'.format(
    't [s]', 'T [K]', 'h [J/kg]', 'P [Pa]', 'X_CH4'))

t = 0.0
for n in range(30):
    tres = mixer.mass / (mfc1.mdot(t) + mfc2.mdot(t))
    t += 0.5 * tres
    sim.advance(t)
    print('{:14.5g} {:14.5g} {:14.5g}  {:14.5g}  {:14.5g}'.format(
        t, mixer.T, mixer.thermo.h, mixer.thermo.P, mixer.thermo['CH4'].X[0]))
Exemple #27
0
    # create a reservoir for the reactor to exhaust into. The composition of
    # this reservoir is irrelevant.
    downstream = ct.Reservoir(gas, name='downstream')

    # use a 'Wall' object to implement the reacting surface in the reactor.
    # Since walls have to be installed between two reactors/reserviors, we'll
    # install it between the upstream reservoir and the reactor.  The area is
    # set to the desired catalyst area in the reactor, and surface reactions
    # are included only on the side facing the reactor.
    w = ct.Wall(upstream, r, A=cat_area, kinetics=[None, surf])

    # We need a valve between the reactor and the downstream reservoir. This
    # will determine the pressure in the reactor. Set K large enough that the
    # pressure difference is very small.
    v = ct.Valve(r, downstream, K=1e-4)

    # The mass flow rate into the reactor will be fixed by using a
    # MassFlowController object.
    m = ct.MassFlowController(upstream, r, mdot=mass_flow_rate)

    sim = ct.ReactorNet([r])
    sim.max_err_test_fails = 12

    # set relative and absolute tolerances on the simulation
    sim.rtol = 1.0e-9
    sim.atol = 1.0e-21

    T_start, rho_start, Y_start = r.thermo.TDY
    cov_start = surf.coverages
    V_start = r.volume
Exemple #28
0
#energy='off' apaga la ecuación de energía al crear el reactor
r1 = ct.IdealGasReactor(contents=gas, energy='off')

#Miro el contenido del reactor en fracciones másicas
r1.Y

residence_time = 0.8e-4


def mdot_out(t):
    return r1.mass / residence_time


#Poner una válvula a la entrada del reactor r1 para mantener P=cte y evitar que se #devuelva el flujo. Véase  help(ct.Valve)
#Nótese el uso del objeto upstream que es un tipo Reservoir devinido arriba
inlet = ct.Valve(upstream, r1, K=100)
#Pone un objeto MassFlowController a la salidad de r1 que mantiene el flujo másico
#constante, véase help(ct.MassFlowController)
#Nótese el uso del objeto downstream que es un tipo Reservoir devinido arriba
outlet = ct.MassFlowController(r1, downstream)
#fija el flujo másico a la salida del reactor
outlet.set_mass_flow_rate(mdot_out)

net = ct.ReactorNet([r1])

#Creo los "pasos de tiempo" en los que quiero ver el progreso de la solución
#El solver de cantera resuelve de forma automática y escoge su paso de tiempo de #forma automática así t sea 2, 20 o 2000 puntos
t = np.linspace(0, residence_time, 2)
#
#¿Por qué el código original de Ray multiplica por 5 el tiempo de residencia?
#t = np.linspace(0, 5*residence_time, 2)
Exemple #29
0
        m2 = ct.MassFlowController(air_in,
                                   przestrzen_obliczeniowa,
                                   mdot=air_mdot)

        # ignition modelled by Gaussian pulse
        fwhm = 0.2
        amplitude = 0.1
        t0 = 1.0
        igniter_mdot = lambda t: amplitude * math.exp(-(t - t0)**2 * 4 * math.
                                                      log(2) / fwhm**2)
        m3 = ct.MassFlowController(igniter,
                                   przestrzen_obliczeniowa,
                                   mdot=igniter_mdot)

        # pressure constraint on exhaust, applied by using a valve
        v = ct.Valve(przestrzen_obliczeniowa, exhaust, K=1.0)

        # creating simulation of reactor network
        sim = ct.ReactorNet([przestrzen_obliczeniowa])

        # setting time limits of simulation
        tfinal = 8.0
        tnow = 0.0

        # Let's assume OH radicals' mass fraction reaches constant value when reactor approaches state of steady burning. If so,
        # lifespan of radicals become virtually dependant only on time limits of simulation
        # That would be critical mistake, so in order to avoid it, a counter is added to check if dy/dt (where y is OH mass fraction)
        # becomes equal to 0, if so, and OH mass fraction (current) is lower than its maximum value, loop becomes broken instantly
        # and lifespan counter freezes at current value.

        # delcaring variable for previous OH mass fraction value to check, if reactor has reached it's steady state
Exemple #30
0
def JSR_steadystate(gas,
                    resTime,
                    volume,
                    kinetic_sens=0,
                    physical_sens=0,
                    observables=[],
                    physical_params=[],
                    energycon='off',
                    pressureValveCoefficient=0.01,
                    maxsimulationTime=1000):
    # Inlet gas conditions are passed into function in the "gas" object, which is a cantera object
    # Reactor parameters passed into function as resTime and volume.  Residence time and volume of JSR
    #kinetic sens and physical sens are optional parameters which are set to zero by default.  Set them to 1 to
    #calculate sensitivity based on kinetic or physical parameters.  If these are set to 1 you must pass
    #an array of all observables to calculate sensitivities for
    reactorPressure = gas.P
    # This is the "conductance" of the pressure valve and will determine its efficiency in
    # holding the reactor pressure to the desired conditions. It is an optional parameter
    pressureValveCoefficient = pressureValveCoefficient

    # This parameter will allow you to decide if the valve's conductance is acceptable. If there
    # is a pressure rise in the reactor beyond this tolerance, you will get a warning
    maxPressureRiseAllowed = 0.001

    # Simulation termination criterion
    maxSimulationTime = maxsimulationTime  # seconds.  An optional parameter
    fuelAirMixtureTank = ct.Reservoir(gas)
    exhaust = ct.Reservoir(gas)

    stirredReactor = ct.IdealGasReactor(gas, energy=energycon, volume=volume)

    massFlowController = ct.MassFlowController(upstream=fuelAirMixtureTank,
                                               downstream=stirredReactor,
                                               mdot=stirredReactor.mass /
                                               resTime)

    pressureRegulator = ct.Valve(upstream=stirredReactor,
                                 downstream=exhaust,
                                 K=pressureValveCoefficient)

    reactorNetwork = ct.ReactorNet([stirredReactor])

    #This block adds kinetic sensitivity parameters for all reactions if desired.
    if kinetic_sens == 1 and bool(observables):
        for i in range(gas.n_reactions):
            stirredReactor.add_sensitivity_reaction(i)
    if kinetic_sens == 1 and bool(observables) == False:
        print(
            'Please supply a non-empty list of observables for sensitivity analysis or set kinetic_sens=0'
        )

    if physical_sens == 1 and bool(observables):
        print('Placeholder')
    if physical_sens == 1 and bool(observables) == False:
        print(
            'Please supply a non-empty list of observables for sensitivity analysis or set physical_sens=0'
        )

    # now compile a list of all variables for which we will store data
    columnNames = [
        stirredReactor.component_name(item)
        for item in range(stirredReactor.n_vars)
    ]
    columnNames = ['pressure'] + columnNames

    # use the above list to create a DataFrame
    timeHistory = pd.DataFrame(columns=columnNames)

    # Start the stopwatch
    tic = time.time()

    #Establish a matrix to hold sensitivities for kinetic parameters, along with tolerances
    if kinetic_sens == 1 and bool(observables):
        senscolumnNames = ['Reaction'] + observables
        sensArray = pd.DataFrame(columns=senscolumnNames)
        senstempArray = np.zeros((len(observables), gas.n_reactions))
        reactorNetwork.rtol_sensitivity = 1.0e-6
        reactorNetwork.atol_sensitivity = 1.0e-6
    if physical_sens == 1 and bool(observables):
        senscolumnNames = ['Parameter'] + observables
        psensArray = pd.DataFrame(columns=senscolumnNames)
        senstempArray = np.zeros((len(observables), len(physical_params)))

    reactorNetwork.advance_to_steady_state()

    if kinetic_sens == 1 and bool(observables):
        for k in np.arange(len(observables)):
            for j in np.arange(gas.n_reactions):
                #print( k,j)
                senstempArray[k, j] = reactorNetwork.sensitivity(
                    observables[k], j)
        sensArray['Reaction'] = gas.reaction_equations()
        sensArray[observables] = senstempArray.T

    #state = np.hstack([stirredReactor.thermo.P, stirredReactor.mass,
    #stirredReactor.volume, stirredReactor.T, stirredReactor.thermo.X])

    # Stop the stopwatch
    toc = time.time()

    print('Simulation Took {:3.2f}s to compute'.format(toc - tic))

    # We now check to see if the pressure rise during the simulation, a.k.a the pressure valve
    # was okay
    pressureDifferential = timeHistory['pressure'].max(
    ) - timeHistory['pressure'].min()
    if (abs(pressureDifferential / reactorPressure) > maxPressureRiseAllowed):
        print(
            "WARNING: Non-trivial pressure rise in the reactor. Adjust K value in valve"
        )

    if kinetic_sens == 1 and bool(observables) and physical_sens == 0:
        modelData = jsr_model_data(kinetic_sens=sensArray,
                                   reactorSolution=stirredReactor)
        return modelData
    if physical_sens == 1 and bool(observables) and kinetic_sens == 0:
        modelData = jsr_model_data(physical_sens=psensArray,
                                   reactorSolution=stirredReactor)
    if physical_sens == 1 and bool(observables) and kinetic_sens == 1:
        modelData = jsr_model_data(physical_sens=psensArray,
                                   kinetic_sens=sensArray,
                                   reactorSolution=stirredReactor)
    else:
        modelData = jsr_model_data(reactorSolution=stirredReactor)
        return modelData