Esempio n. 1
0
    def setUp(self):
        self.referenceFile = pjoin(os.path.dirname(__file__), 'data', 'WallTest-integrateWithAdvance.csv')
        # reservoir to represent the environment
        self.gas0 = ct.Solution('air.xml')
        self.gas0.TP = 300, ct.one_atm
        self.env = ct.Reservoir(self.gas0)

        # reactor to represent the side filled with Argon
        self.gas1 = ct.Solution('air.xml')
        self.gas1.TPX = 1000.0, 30*ct.one_atm, 'AR:1.0'
        self.r1 = ct.Reactor(self.gas1)

        # reactor to represent the combustible mixture
        self.gas2 = ct.Solution('h2o2.xml')
        self.gas2.TPX = 500.0, 1.5*ct.one_atm, 'H2:0.5, O2:1.0, AR:10.0'
        self.r2 = ct.Reactor(self.gas2)

        # Wall between the two reactors
        self.w1 = ct.Wall(self.r2, self.r1, A=1.0, K=2e-4, U=400.0)

        # Wall to represent heat loss to the environment
        self.w2 = ct.Wall(self.r2, self.env, A=1.0, U=2000.0)

        # Create the reactor network
        self.sim = ct.ReactorNet([self.r1, self.r2])
Esempio n. 2
0
    def test_Reactor(self):
        phase = ct.PureFluid('liquidvapor.xml', 'oxygen')
        air = ct.Solution('air.xml')

        phase.TP = 93, 4e5
        r1 = ct.Reactor(phase)
        r1.volume = 0.1

        air.TP = 300, 4e5
        r2 = ct.Reactor(air)
        r2.volume = 10.0

        air.TP = 500, 4e5
        env = ct.Reservoir(air)

        w1 = ct.Wall(r1,r2)
        w1.expansion_rate_coeff = 1e-3
        w2 = ct.Wall(env,r1, Q=500000, A=1)
        net = ct.ReactorNet([r1,r2])
        net.atol = 1e-10
        net.rtol = 1e-6

        states = ct.SolutionArray(phase, extra='t')
        for t in np.arange(0.0, 60.0, 1):
            net.advance(t)
            states.append(TD=r1.thermo.TD, t=net.time)

        self.assertEqual(states.X[0], 0)
        self.assertEqual(states.X[-1], 1)
        self.assertNear(states.X[30], 0.54806, 1e-4)
Esempio n. 3
0
File: engines.py Progetto: NREL/MPRL
    def setup_reactor(self):
        self.gas = ct.Solution(self.rxnmech)
        self.xinit = {"O2": 0.21, "N2": 0.79}
        self.gas.TPX = self.T0, self.p0, self.xinit

        self.injection_gas, _ = setup_injection_gas(self.rxnmech,
                                                    self.fuel,
                                                    pure_fuel=True)
        self.injection_gas.TP = self.T0, self.p0
        fuel_res = ct.Reservoir(self.injection_gas)

        # Create the reactor object
        self.reactor = ct.Reactor(self.gas)
        self.rempty = ct.Reactor(self.gas)

        # Set the initial states of the reactor
        self.reactor.chemistry_enabled = True
        self.reactor.volume = self.history["V"][0]

        # Add in a fuel injector
        self.injector = ct.MassFlowController(fuel_res, self.reactor)

        # Add in a wall that moves according to piston velocity
        self.piston = ct.Wall(
            left=self.reactor,
            right=self.rempty,
            A=np.pi / 4.0 * self.bore**2,
            U=0.0,
            velocity=self.history["piston_velocity"][0],
        )

        # Create the network object
        self.sim = ct.ReactorNet([self.reactor])
Esempio n. 4
0
    def make_reactors(self,
                      independent=True,
                      n_reactors=2,
                      T1=300,
                      P1=101325,
                      X1='O2:1.0',
                      T2=300,
                      P2=101325,
                      X2='O2:1.0'):

        self.net = ct.ReactorNet()

        self.gas1 = ct.Solution('h2o2.xml')
        self.gas1.TPX = T1, P1, X1
        self.r1 = ct.Reactor(self.gas1)
        self.net.add_reactor(self.r1)

        if independent:
            self.gas2 = ct.Solution('h2o2.xml')
        else:
            self.gas2 = self.gas1

        if n_reactors >= 2:
            self.gas2.TPX = T2, P2, X2
            self.r2 = ct.Reactor(self.gas2)
            self.net.add_reactor(self.r2)
Esempio n. 5
0
    def makeReactors(self):
        self.net = ct.ReactorNet()

        self.gas = ct.Solution('diamond.xml', 'gas')
        self.solid = ct.Solution('diamond.xml', 'diamond')
        self.interface = ct.Interface('diamond.xml', 'diamond_100',
                                      (self.gas, self.solid))
        self.r1 = ct.Reactor(self.gas)
        self.net.addReactor(self.r1)

        self.r2 = ct.Reactor(self.gas)
        self.net.addReactor(self.r2)

        self.w = ct.Wall(self.r1, self.r2)
Esempio n. 6
0
        def setup():
            net = ct.ReactorNet()
            gas.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5'

            r = ct.Reactor(gas)
            net.addReactor(r)
            return r, net
Esempio n. 7
0
def eval_idt(args):
    mech, options, x = args
    gas = global_var.gases[mech]
    t_fin = options.t_fin

    time_vec = []
    temp_vec = []

    # DCN Conditions
    p = options.pres  # Pa
    t = options.temp  # K
    phi = options.phi

    # Add air to the mixture
    stoich_o2 = 0.0
    for idx, species in enumerate(options.palette):
        stoich_o2 += x[idx] * (gas.n_atoms(species, 'C') +
                               0.25 * gas.n_atoms(species, 'H'))

    # Set gas composition with air
    x_mod = (options.phi / stoich_o2) * x
    comp_string = set_gas_using_palette(gas, options, t, p, x_mod)
    comp_string += ',O2:1,N2:3.76'
    gas.TPX = t, p, comp_string

    # Create reactor network
    r = ct.Reactor(gas)
    sim = ct.ReactorNet([r])

    # Advance the reactor
    time = 0.0
    time_vec.append(time)

    while time < t_fin:
        time = sim.step()
        time_vec.append(time)
        temp_vec.append(r.T)

    # Find maximum slope of temperature
    max_der = 0.0
    der = 0.0
    index = 0

    for idx, val in enumerate(temp_vec):
        der = (temp_vec[idx] - temp_vec[idx-1]) / \
              (time_vec[idx] - time_vec[idx-1])

        if abs(der) > max_der:
            max_der = der
            index = idx

    if temp_vec[index] < t:
        return -1
    else:
        print str(["{:0.3f}".format(y)
                   for y in x]) + ", " + str("{:0.7e}".format(time_vec[index]))
        #print str(options.pres) + ", " + str(options.temp) + ", " + str(options.phi) + ", " + str("{:0.7e}".format(time_vec[index]))
        sys.stdout.flush()
        return time_vec[index]
Esempio n. 8
0
        def setup(reverse=False):
            net = ct.ReactorNet()
            gas1 = ct.Solution('h2o2.xml')
            gas1.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5'
            rA = ct.Reactor(gas1)

            gas2 = ct.Solution('h2o2.xml')
            gas2.TPX = 920, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:0.5'
            rB = ct.Reactor(gas2)
            if reverse:
                net.addReactor(rB)
                net.addReactor(rA)
            else:
                net.addReactor(rA)
                net.addReactor(rB)

            return rA, rB, net
Esempio n. 9
0
def test_cantera_reactornet():
    """
    Testing basic Cantera ReactorNet functionality
    """
    g = get_gas()
    ctreactor = ct.Reactor(g)
    ctnet = ct.ReactorNet([ctreactor])
    ctnet.advance(0.01)
Esempio n. 10
0
    def test_sensitivities2(self):
        net = ct.ReactorNet()

        gas1 = ct.Solution('diamond.xml', 'gas')
        solid = ct.Solution('diamond.xml', 'diamond')
        interface = ct.Interface('diamond.xml', 'diamond_100',
                                 (gas1, solid))
        r1 = ct.Reactor(gas1)
        net.addReactor(r1)

        gas2 = ct.Solution('h2o2.xml')
        gas2.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5'
        r2 = ct.Reactor(gas2)
        net.addReactor(r2)

        w = ct.Wall(r1, r2)
        w.left.kinetics = interface

        C = np.zeros(interface.nSpecies)
        C[0] = 0.3
        C[4] = 0.7

        w.left.coverages = C
        w.left.addSensitivityReaction(2)
        r2.addSensitivityReaction(18)

        for T in (901, 905, 910, 950, 1500):
            while r2.T < T:
                net.step(1.0)

            S = net.sensitivities()
            K1 = gas1.nSpecies + interface.nSpecies

            # Constant internal energy and volume should generate zero
            # sensitivity coefficients
            self.assertArrayNear(S[0:2,:], np.zeros((2,2)))
            self.assertArrayNear(S[K1+2:K1+4,:], np.zeros((2,2)))

            S11 = np.linalg.norm(S[2:K1+2,0])
            S21 = np.linalg.norm(S[2:K1+2,1])
            S12 = np.linalg.norm(S[K1+4:,0])
            S22 = np.linalg.norm(S[K1+4:,1])

            self.assertTrue(S11 > 1e5 * S12)
            self.assertTrue(S22 > 1e5 * S21)
Esempio n. 11
0
    def getAI(self):

        gas = Global.gas
        ifuel = gas.species_index(self.fuel)
        io2 = gas.species_index('O2')
        in2 = gas.species_index('N2')

        self.putMultiplier(gas)

        x = np.zeros(gas.n_species)
        x[ifuel] = self.phi
        x[io2] = gas.n_atoms(self.fuel, 'C') + 0.25 * \
            gas.n_atoms(self.fuel, 'H')
        x[in2] = x[io2] * self.n2_o2_ratio

        gas.TPX = self.Tin, self.P, x

        # Create reactor network
        r = ct.Reactor(gas)
        sim = ct.ReactorNet([r])

        # Advance the reactor
        time = 0.0
        time0 = 0.0
        time1 = 0.0
        curT0 = r.T
        curT1 = r.T
        iteration = 0

        #sim.atol = 1e-7
        #sim.rtol = 1e-4

        try:
            while curT1 < self.Ttarget:
                time = sim.step()
                curT0 = curT1
                curT1 = r.T
                time0 = time1
                time1 = time
                iteration += 1
                if (time > 4.e2):
                    print('Current time too large, continuing')
                    return 4.e2
                if (iteration > 100000):
                    print('Max Iteration reached, continuing')
                    return 0.
        except:
            print('Failed! Continuing...')
            return 4.e2

        weight = (self.Ttarget - curT0) / (curT1 - curT0)

        AItime = (1. - weight) * time0 + weight * time1

        return AItime
Esempio n. 12
0
    def test_insert(self):
        R = ct.Reactor()
        f1 = lambda r: r.T
        f2 = lambda r: r.kinetics.netProductionRates
        self.assertRaises(Exception, f1, R)
        self.assertRaises(Exception, f2, R)

        g = ct.Solution('h2o2.xml')
        g.TP = 300, 101325
        R.insert(g)

        self.assertNear(R.T, 300)
        self.assertEqual(len(R.kinetics.netProductionRates), g.nSpecies)
Esempio n. 13
0
        def setup(order):
            gas1.TPX = 1200, 1e3, 'H:0.002, H2:1, CH4:0.01, CH3:0.0002'
            gas2.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5'
            net = ct.ReactorNet()
            rA = ct.Reactor(gas1)
            rB = ct.Reactor(gas2)

            if order % 2 == 0:
                wA = ct.Wall(rA, rB)
                wB = ct.Wall(rB, rA)
            else:
                wB = ct.Wall(rB, rA)
                wA = ct.Wall(rA, rB)

            wA.left.kinetics = interface
            wB.right.kinetics = interface

            wA.area = 0.1
            wB.area = 10

            C1 = np.zeros(interface.nSpecies)
            C2 = np.zeros(interface.nSpecies)
            C1[0] = 0.3
            C1[4] = 0.7

            C2[0] = 0.9
            C2[4] = 0.1
            wA.left.coverages = C1
            wB.right.coverages = C2

            if order // 2 == 0:
                net.addReactor(rA)
                net.addReactor(rB)
            else:
                net.addReactor(rB)
                net.addReactor(rA)

            return rA,rB,wA,wB,net
Esempio n. 14
0
    def setUp(self):
        # reservoir to represent the environment
        self.gas0 = ct.Solution('air.xml')
        self.gas0.TP = 300, ct.one_atm
        self.env = ct.Reservoir(self.gas0)

        # reactor to represent the side filled with Argon
        self.gas1 = ct.Solution('air.xml')
        self.gas1.TPX = 1000.0, 30 * ct.one_atm, 'AR:1.0'
        self.r1 = ct.Reactor(self.gas1)

        # reactor to represent the combustible mixture
        self.gas2 = ct.Solution('h2o2.xml')
        self.gas2.TPX = 500.0, 1.5 * ct.one_atm, 'H2:0.5, O2:1.0, AR:10.0'
        self.r2 = ct.Reactor(self.gas2)

        # Wall between the two reactors
        self.w1 = ct.Wall(self.r2, self.r1, A=1.0, K=2e-4, U=400.0)

        # Wall to represent heat loss to the environment
        self.w2 = ct.Wall(self.r2, self.env, A=1.0, U=2000.0)

        # Create the reactor network
        self.sim = ct.ReactorNet([self.r1, self.r2])
Esempio n. 15
0
    def test_sensitivities1(self):
        net = ct.ReactorNet()
        gas = ct.Solution('gri30.xml')
        gas.TPX = 1300, 20*101325, 'CO:1.0, H2:0.1, CH4:0.1, H2O:0.5'
        r1 = ct.Reactor(gas)
        net.addReactor(r1)

        self.assertEqual(net.nSensitivityParams, 0)
        r1.addSensitivityReaction(40)
        r1.addSensitivityReaction(41)

        net.advance(0.1)

        self.assertEqual(net.nSensitivityParams, 2)
        self.assertEqual(net.nVars, gas.nSpecies + 2)
        S = net.sensitivities()
        self.assertEqual(S.shape, (net.nVars, net.nSensitivityParams))
Esempio n. 16
0
 def advance(solution_object):
     reactor = ct.Reactor(solution_object)
     sim = ct.ReactorNet([reactor])
     current_time = 0.0
     end_time = 5.0e-3
     time_array = []
     temperature_array = []
     data_index = 0
     while current_time < end_time:
         data_index += 1
         current_time = sim.step(end_time)
         time_array.append(current_time)
         temperature_array.append(reactor.T)
     time_array = np.array(time_array)
     temperature_array = np.array(temperature_array)
     temperature_profile = np.vstack((time_array, temperature_array)).T
     return [temperature_profile, time_array, temperature_array]
Esempio n. 17
0
    def getAI(self):

        gas = Global.gas
        ifuel = gas.species_index(self.fuel)
        io2 = gas.species_index('O2')
        in2 = gas.species_index('N2')

        self.putMultiplier(gas)

        x = np.zeros(gas.n_species)
        x[ifuel] = self.phi
        x[io2] = gas.n_atoms(self.fuel, 'C') + 0.25 * \
            gas.n_atoms(self.fuel, 'H')
        x[in2] = x[io2] * self.n2_o2_ratio

        gas.TPX = self.Tin, self.P, x

        # Create reactor network
        r = ct.Reactor(gas)
        sim = ct.ReactorNet([r])

        # Advance the reactor
        time = 0.0
        time0 = 0.0
        time1 = 0.0
        curT0 = r.T
        curT1 = r.T

        #sim.atol = 1e-7
        #sim.rtol = 1e-4

        while curT1 < self.Ttarget:
            time = sim.step()
            curT0 = curT1
            curT1 = r.T
            time0 = time1
            time1 = time

        weight = (self.Ttarget - curT0) / (curT1 - curT0)

        AItime = (1. - weight) * time0 + weight * time1

        logging.debug('Done Ignition time computation')

        return AItime
    def forward(self):

        estimatedIgnitionDelayTimes = 0.005
        igni = []
        for i, tem in enumerate(self.tem):

            ideal_gas = ct.Solution(self.file)  # 要不要加呢

            reactorTemperature10 = tem  # 这里temperature改成每一个温度
            ideal_gas.TP = reactorTemperature10, self.p1
            ideal_gas.X = self.conditions
            r = ct.Reactor(contents=ideal_gas)
            reactorNetwork = ct.ReactorNet([r])
            timeHistory = ct.SolutionArray(ideal_gas, extra=['t'])
            t = 0
            counter = 0
            while t < estimatedIgnitionDelayTimes:
                t = reactorNetwork.step()
                if not counter % 20:
                    timeHistory.append(r.thermo.state, t=t)
                counter += 1
            tau = self.ignitionDelay(timeHistory, 'OH')
            igni.append(tau)  # 工况1的第一个温度的着火延迟
        return igni
Esempio n. 19
0
def run_sim(solution_object, condition, sys_args='none', **usr_args ):
    """
    Function to run Cantera reactor simulation for autoigntion conditions

    Parameters
    ----------
    solution_object : obj
        Cantera solution object
    condition
        An object contining initial conditions (temperature, pressure, mole fractions)

    Returns
    ----------
    Output
        Plot of Temp vs Time
        Points of interest
        CSV file
        Hdf5 file
        mass_fractions.hdf5 : [initial_condition]
                                [index]
                                    [Pressure]
                                    [Reaction Rates of Progress]
                                    [Species Mass Fractions]
                                    [Species Net Production Rates Original]
                                    [Temp]
                                    [Time]

        return_obj : obj
            sim result
                .time
                .temp
                .initial_temperature_array
                .sp_data
                .test (h5py object)
                .tau
                .Temp
                .frac

    Example
    -------
        run_sim(gas_solution, points='y', plot='y', initial_sim='y')

    """
    func_start_time = tm.time()
    solution = solution_object
    initial_temperature = float(condition.temperature)
    pressure = float(condition.pressure)*float(ct.one_atm)
    #check if species in solution
    frac = ''
    for reactant in condition.species.iteritems():
        if reactant[0] in solution.species_names:
            frac += str(reactant[0]) + ':' + str(reactant[1]) + ','
    frac = frac[:-1]
    solution.TPX = initial_temperature, pressure, frac #101.325 kPa
    species = solution.species()
    reactions = solution.reactions()

    #run sim to find ignition delay from dT/dt max
    reactor = ct.Reactor(solution)
    simulation = ct.ReactorNet([reactor])
    current_time = 0.0
    stop_time = 5.0e-3
    group_index = 0
    times1 = []
    temps = [] #first column is time, second is temperature
    mass = reactor.mass
    sdata = np.zeros([0, len(reactor.Y)])
    production_data = np.zeros([0, len(solution.net_production_rates)])
    state_list = list()

    f1 = h5py.File('mass_fractions.hdf5', 'a')
    try:
        group_name = str(initial_temperature) + '_' + str(pressure) + '_' + str(frac)
    except ValueError:
        print "Duplicate initial conditions, or check to make sure mass fractions file isn't in directory. If it is, delete it"""
    individual = f1.create_group(group_name)
    timer_start =tm.time()
    while current_time < stop_time:
        group_index += 1
        try:
            current_time = simulation.step()
        except Exception:
            error_string = 'Cantera autoignition_error @ %sK initial temperature' %initial_temperature
            print error_string
            return
        times1.append(current_time)
        temps.append(reactor.T)
        species_data = reactor.Y
        grp = individual.create_group(str(group_index))
        grp['Temp'] = reactor.T
        grp['Time'] = current_time
        grp['Pressure'] = reactor.thermo.P
        species_production_rates = reactor.kinetics.net_production_rates
        net_rates_of_progress = reactor.kinetics.net_rates_of_progress
        grp.create_dataset('Species Mass Fractions', data=species_data)
        grp.create_dataset('Reaction Rates of Progress', data=net_rates_of_progress)
        grp.create_dataset('Species Net Production Rates Original', data=species_production_rates)

        species_data = species_data[:, np.newaxis].T #translate from [n, 1] to [1,n]
        sdata = np.vstack((sdata, species_data))

        production_rates = np.array(solution.net_production_rates)
        production_rates = production_rates[:, np.newaxis].T
        production_data = np.vstack((production_data, production_rates))

    sample = get_range(times1, temps, sdata, production_data)
    timer_stop = tm.time()


    #strips all data except that within a 40 point sample range around ignition
    for grp in f1[group_name].keys():
        if int(grp) not in range((sample.index-20), (sample.index+20)):
            f1[group_name].__delitem__(str(grp))

    #f1.close()

    #utility functions
    def plot():
        import matplotlib.pyplot as plt
        plt.clf()
        #plot combustion point
        plt.plot(sample.derivative_max[0], sample.derivative_max[1], 'ro', ms=7, label='ignition point')
        #plot initial and final sample points
        plt.plot(sample.initial_point[0], sample.initial_point[1], 'rx', ms=5, mew=2)
        plt.plot(sample.final_point[0], sample.final_point[1], 'rx', ms=5, mew=2)
        #plot temp vs time
        plt.plot(sample.times_total, sample.temps_total)
        plt.xlabel('Time (s)')
        plt.title('Mixture Temperature vs Time')
        plt.legend()
        plt.ylabel('Temperature (C)')
        #plt.axis([0, 1.2, 900, 2800])
        plt.show()

    def writecsv(sdata):


        names = str(solution.species_names)
        tt = ['Time (s)', 'Temp (K)']
        names = solution.species_names
        name_array = np.append(tt, names)
        sdata = sdata.astype('|S10')
        file_data = np.vstack((name_array, sdata))
        #open and write to file
        input_file_name_stripped = os.path.splitext(data_file)[0]
        output_file_name = os.path.join(input_file_name_stripped + '_species_data.csv')
        print output_file_name
        with open(output_file_name, 'wb') as f:
            np.savetxt(f, file_data, fmt=('%+12s'), delimiter=',')
        #os.system('atom '+ output_file_name)

    def writehdf5(sdata):
        #format matrix for hdf5
        names = str(solution.species_names)
        tt = ['Time (s)', 'Temp (K)']
        names = solution.species_names
        name_array = np.append(tt, names)
        sdata = sdata.astype('|S10')
        file_data = np.vstack((name_array, sdata))
        #open and write to file
        input_file_name_stripped = os.path.splitext(data_file)[0]
        output_file_name = os.path.join(input_file_name_stripped + '_species_data.hdf5')
        with h5py.File(output_file_name, 'w') as f:
            Times = f.create_dataset("Times", data=sample.times)
            Temps = f.create_dataset("Temps", data=sample.temps)
            sgroup = f.create_group('Species_Data')
            for i, sp in enumerate(solution.species_names):
                sgroup.create_dataset(sp, data=sdata[:, i+2])

    def points():
        print("\nTime[s]            Temp[K]        Index        Point")
        print(str(sample.initial_point[0]) +  "       " + str("{0:.2f}".format(sample.initial_point[1]))\
         + "       " + str(sample.initial_point[2]) + "     " + "Initial sample point")
        print(str(sample.tau) + "        " + str("{0:.2f}".format(sample.derivative_max[1])) + "       " + str(sample.derivative_max[2])\
                + "     " + "Ignition point")
        print(str(sample.final_point[0]) +  "       " + str("{0:.2f}".format(sample.final_point[1]))\
         + "       " + str(sample.final_point[2]) + "     " + "Final sample point")

    #terminal use case
    if sys_args is not 'none':
        if sys_args.plot:
            plot()
        if sys_args.writecsv:
            writecsv(sample.species_data)
        if sys_args.writehdf5:
            writehdf5(sample.species_data)
        if sys_args.points:
            points()


    class return_obj:
        def __init__(self, time, temp, sp_data, f1, tau, Temp, frac):
            self.time = time
            self.temp = temp
            self.initial_temperature_array = []
            self.sp_data = sp_data
            self.test = f1
            self.tau = tau
            self.Temp = initial_temperature
            self.frac = frac
            self.tau_array = []
    #print 'autoignition time: %0.5f'    %(tm.time()-func_start_time)
    return return_obj(sample.times, sample.temps, sample.species_data, f1, sample.tau, initial_temperature, frac)

    "sdata is an array of 40 timesteps, with each instance containing an array of species"
    "mass fractions at that instant"
Esempio n. 20
0
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 = 300.0, ct.one_atm, 'H:1.0'
igniter = ct.Reservoir(gas)

# create the combustor, and fill it in initially with N2
gas.TPX = 300.0, ct.one_atm, 'N2:1.0'
combustor = ct.Reactor(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
Esempio n. 21
0
length = 2.0  # reactor length [m]
area = 7.85398e-5  # cross section area [m2]
n_reactor = 200  # number of divided reactor

Tout = 100.0 + 273.15  # outer temperature [K]
area_wall = 0.0628329  # heat transfer wall area [m2]
ht = 700.0  # heat transfer coef. [W/m2/K]

# define object
gas = ct.Solution('water.cti', 'liquid_water')
gas.TPX = Tin, p, comp
mdot = vin * area * gas.density
dx = length / n_reactor

#r = ct.IdealGasReactor(gas)
r = ct.Reactor(gas)  # since water is not ideal gas
r.volume = area * dx

upstream = ct.Reservoir(gas, name='upstream')
downstream = ct.Reservoir(gas, name='downstream')
m = ct.MassFlowController(upstream, r, mdot=mdot)
v = ct.PressureController(r, downstream, master=m, K=1.0e-5)

gas.TPX = Tout, p, comp
outer = ct.Reservoir(gas)
wall = ct.Wall(outer, r, U=ht)
wall.area = area_wall / n_reactor

sim = ct.ReactorNet([r])

# solve
Esempio n. 22
0
import os
import csv
import numpy as np

import cantera as ct

#-----------------------------------------------------------------------
# First create each gas needed, and a reactor or reservoir for each one.
#-----------------------------------------------------------------------

# create an argon gas object and set its state
ar = ct.Solution('argon.xml')
ar.TP = 1000.0, 20.0 * ct.one_atm

# create a reactor to represent the side of the cylinder filled with argon
r1 = ct.Reactor(ar)

# create a reservoir for the environment, and fill it with air.
env = ct.Reservoir(ct.Solution('air.xml'))

# use GRI-Mech 3.0 for the methane/air mixture, and set its initial state
gri3 = ct.Solution('gri30.xml')
gri3.TPX = 500.0, 0.2 * ct.one_atm, 'CH4:1.1, O2:2, N2:7.52'

# create a reactor for the methane/air side
r2 = ct.Reactor(gri3)

#-----------------------------------------------------------------------------
# Now couple the reactors by defining common walls that may move (a piston) or
# conduct heat
#-----------------------------------------------------------------------------
import numpy as np
import cantera as ct
import math
import csv
import matplotlib.pyplot as plt

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

#mieszanka
T = 1000.0
P = 200000
X = 'C2H4:0.5 O2:3 N2:11.28'
gas.TPX = T, P, X

r = ct.Reactor(gas)
sim = ct.ReactorNet([r])

times = np.zeros(2000)
data = np.zeros([2000, 4])

tk = 0.5

dt = tk / 2000
time = 0
n = 0

while n < 2000:
    time += dt
    sim.advance(time)
    times[n] = time
Esempio n. 24
0
def run_reactor(
    cti_file,
    t_array=[528],
    p_array=[75],
    v_array=[0.00424],
    h2_array=[0.75],
    co2_array=[0.5],
    rtol=1.0e-11,
    atol=1.0e-22,
    reactor_type=0,
    energy="off",
    sensitivity=False,
    sensatol=1e-6,
    sensrtol=1e-6,
    reactime=1e5,
):

    import pandas as pd
    import numpy as np
    import time
    import cantera as ct
    from matplotlib import pyplot as plt
    import csv
    import math
    import os
    import sys
    import re
    import itertools
    import logging
    from collections import defaultdict
    import git

    try:
        array_i = int(os.getenv("SLURM_ARRAY_TASK_ID"))
    except TypeError:
        array_i = 0

    # get git commit hash and message

    repo = git.Repo("/work/westgroup/lee.ting/cantera/ammonia/")
    git_sha = str(repo.head.commit)[0:6]
    git_msg = str(repo.head.commit.message)[0:20].replace(" ", "_").replace(
        "'", "_")

    # this should probably be outside of function
    settings = list(
        itertools.product(t_array, p_array, v_array, h2_array, co2_array))

    # constants
    pi = math.pi

    # set initial temps, pressures, concentrations
    temp = settings[array_i][0]  # kelvin
    temp_str = str(temp)[0:3]
    pressure = settings[array_i][1] * ct.one_atm  # Pascals

    X_h2 = settings[array_i][3]
    x_h2_str = str(X_h2)[0:3].replace(".", "_")
    x_CO_CO2_str = str(settings[array_i][4])[0:3].replace(".", "_")

    if X_h2 == 0.75:
        X_h2o = 0.05
    else:
        X_h2o = 0

    X_co = (1 - (X_h2 + X_h2o)) * (settings[array_i][4])
    X_co2 = (1 - (X_h2 + X_h2o)) * (1 - settings[array_i][4])

    # normalize mole fractions just in case
    # X_co = X_co/(X_co+X_co2+X_h2)
    # X_co2= X_co2/(X_co+X_co2+X_h2)
    # X_h2 = X_h2/(X_co+X_co2+X_h2)

    mw_co = 28.01e-3  # [kg/mol]
    mw_co2 = 44.01e-3  # [kg/mol]
    mw_h2 = 2.016e-3  # [kg/mol]
    mw_h2o = 18.01528e-3  # [kg/mol]

    co2_ratio = X_co2 / (X_co + X_co2)
    h2_ratio = (X_co2 + X_co) / X_h2

    # CO/CO2/H2/H2: typical is
    concentrations_rmg = {"O2(2)": X_co, "NH3(6)": X_co2, "He": X_h2}

    # initialize cantera gas and surface
    gas = ct.Solution(cti_file, "gas")

    # surf_grab = ct.Interface(cti_file,'surface1_grab', [gas_grab])
    surf = ct.Interface(cti_file, "surface1", [gas])

    # gas_grab.TPX =
    gas.TPX = temp, pressure, concentrations_rmg
    surf.TP = temp, pressure

    # create gas inlet
    inlet = ct.Reservoir(gas)

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

    # Reactor volume
    rradius = 35e-3
    rlength = 70e-3
    rvol = (rradius**2) * pi * rlength

    # Catalyst Surface Area
    site_density = (surf.site_density * 1000
                    )  # [mol/m^2]cantera uses kmol/m^2, convert to mol/m^2
    cat_weight = 4.24e-3  # [kg]
    cat_site_per_wt = (300 *
                       1e-6) * 1000  # [mol/kg] 1e-6mol/micromole, 1000g/kg
    cat_area = site_density / (cat_weight * cat_site_per_wt)  # [m^3]

    # reactor initialization
    if reactor_type == 0:
        r = ct.Reactor(gas, energy=energy)
        reactor_type_str = "Reactor"
    elif reactor_type == 1:
        r = ct.IdealGasReactor(gas, energy=energy)
        reactor_type_str = "IdealGasReactor"
    elif reactor_type == 2:
        r = ct.ConstPressureReactor(gas, energy=energy)
        reactor_type_str = "ConstPressureReactor"
    elif reactor_type == 3:
        r = ct.IdealGasConstPressureReactor(gas, energy=energy)
        reactor_type_str = "IdealGasConstPressureReactor"

    rsurf = ct.ReactorSurface(surf, r, A=cat_area)
    r.volume = rvol
    surf.coverages = "X(1):1.0"

    # flow controllers (Graaf measured flow at 293.15 and 1 atm)
    one_atm = ct.one_atm
    FC_temp = 293.15
    volume_flow = settings[array_i][2]  # [m^3/s]
    molar_flow = volume_flow * one_atm / (8.3145 * FC_temp)  # [mol/s]
    mass_flow = molar_flow * (X_co * mw_co + X_co2 * mw_co2 + X_h2 * mw_h2 +
                              X_h2o * mw_h2o)  # [kg/s]
    mfc = ct.MassFlowController(inlet, r, mdot=mass_flow)

    # A PressureController has a baseline mass flow rate matching the 'master'
    # MassFlowController, with an additional pressure-dependent term. By explicitly
    # including the upstream mass flow rate, the pressure is kept constant without
    # needing to use a large value for 'K', which can introduce undesired stiffness.
    outlet_mfc = ct.PressureController(r, exhaust, master=mfc, K=0.01)

    # initialize reactor network
    sim = ct.ReactorNet([r])

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

    #################################################
    # Run single reactor
    #################################################

    # round numbers so they're easier to read
    # temp_str = '%s' % '%.3g' % tempn

    cat_area_str = "%s" % "%.3g" % cat_area
    results_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_sha}_{git_msg}/{reactor_type_str}/transient/{temp_str}/results"
    )
    # results_path_csp = (
    #     os.path.dirname(os.path.abspath(__file__))
    #     + f"/{git_sha}_{git_msg}/{reactor_type_str}/transient/{temp_str}/results/csp"
    # )
    flux_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_sha}_{git_msg}/{reactor_type_str}/transient/{temp_str}/flux_diagrams/{x_h2_str}/{x_CO_CO2_str}"
    )
    try:
        os.makedirs(results_path, exist_ok=True)
    except OSError as error:
        print(error)

    # try:
    #     os.makedirs(results_path_csp, exist_ok=True)
    # except OSError as error:
    #     print(error)

    try:
        os.makedirs(flux_path, exist_ok=True)
    except OSError as error:
        print(error)

    gas_ROP_str = [i + " ROP [kmol/m^3 s]" for i in gas.species_names]

    # surface ROP reports gas and surface ROP. these values might be redundant, not sure.

    gas_surf_ROP_str = [
        i + " surface ROP [kmol/m^2 s]" for i in gas.species_names
    ]
    surf_ROP_str = [i + " ROP [kmol/m^2 s]" for i in surf.species_names]

    gasrxn_ROP_str = [
        i + " ROP [kmol/m^3 s]" for i in gas.reaction_equations()
    ]
    surfrxn_ROP_str = [
        i + " ROP [kmol/m^2 s]" for i in surf.reaction_equations()
    ]

    output_filename = (
        results_path +
        f"/Spinning_basket_area_{cat_area_str}_energy_{energy}" +
        f"_temp_{temp}_h2_{x_h2_str}_COCO2_{x_CO_CO2_str}.csv")
    # output_filename_csp = (
    #     results_path_csp
    #     + f"/Spinning_basket_area_{cat_area_str}_energy_{energy}"
    #     + f"_temp_{temp}_h2_{x_h2_str}_COCO2_{x_CO_CO2_str}.csv"
    # )
    outfile = open(output_filename, "w")
    # outfile_csp = open(output_filename_csp, "w")
    writer = csv.writer(outfile)
    # writer_csp = csv.writer(outfile_csp)

    # Sensitivity atol, rtol, and strings for gas and surface reactions if selected
    # slows down script by a lot
    if sensitivity:
        sim.rtol_sensitivity = sensrtol
        sim.atol_sensitivity = sensatol
        sens_species = [
            "NH3(6)"
        ]  #change THIS to your species, can add "," and other species

        # turn on sensitive reactions/species
        for i in range(gas.n_reactions):
            r.add_sensitivity_reaction(i)

        for i in range(surf.n_reactions):
            rsurf.add_sensitivity_reaction(i)

        # for i in range(gas.n_species):
        #     r.add_sensitivity_species_enthalpy(i)

        # for i in range(surf.n_species):
        #     rsurf.add_sensitivity_species_enthalpy(i)

        for j in sens_species:
            gasrxn_sens_str = [
                j + " sensitivity to " + i for i in gas.reaction_equations()
            ]
            surfrxn_sens_str = [
                j + " sensitivity to " + i for i in surf.reaction_equations()
            ]
            # gastherm_sens_str = [j + " thermo sensitivity to " + i for i in gas.species_names]
            # surftherm_sens_str = [j + " thermo sensitivity to " + i for i in surf.species_names]
            sens_list = gasrxn_sens_str + surfrxn_sens_str  # + gastherm_sens_str

        writer.writerow([
            "T (C)",
            "P (atm)",
            "V (M^3/s)",
            "X_co initial",
            "X_co2initial",
            "X_h2 initial",
            "X_h2o initial",
            "CO2/(CO2+CO)",
            "(CO+CO2/H2)",
            "T (C) final",
            "Rtol",
            "Atol",
            "reactor type",
        ] + gas.species_names + surf.species_names + gas_ROP_str +
                        gas_surf_ROP_str + surf_ROP_str + gasrxn_ROP_str +
                        surfrxn_ROP_str + sens_list)

    else:
        writer.writerow([
            "T (C)",
            "P (atm)",
            "V (M^3/s)",
            "X_co initial",
            "X_co2 initial",
            "X_h2 initial",
            "X_h2o initial",
            "CO2/(CO2+CO)",
            "(CO+CO2/H2)",
            "T (C) final",
            "Rtol",
            "Atol",
            "reactor type",
        ] + gas.species_names + surf.species_names + gas_ROP_str +
                        gas_surf_ROP_str + surf_ROP_str + gasrxn_ROP_str +
                        surfrxn_ROP_str)

    # writer_csp.writerow(
    #     ["iter", "t", "dt", "Density[kg/m3]", "Pressure[Pascal]", "Temperature[K]",]
    #     + gas.species_names
    #     + surf.species_names
    # )

    t = 0.0
    dt = 0.1
    iter_ct = 0
    # run the simulation
    first_run = True

    while t < reactime:
        # save flux diagrams at beginning of run
        if first_run == True:
            save_flux_diagrams(gas, suffix=flux_path, timepoint="beginning")
            save_flux_diagrams(surf, suffix=flux_path, timepoint="beginning")
            first_run = False
        t += dt
        sim.advance(t)
        #         if t % 10 < 0.01:

        if sensitivity:
            # get sensitivity for sensitive species i (e.g. methanol) in reaction j
            for i in sens_species:
                g_nrxn = gas.n_reactions
                s_nrxn = surf.n_reactions
                # g_nspec = gas.n_species
                # s_nspec = surf.n_species

                gas_sensitivities = [
                    sim.sensitivity(i, j) for j in range(g_nrxn)
                ]
                surf_sensitivities = [
                    sim.sensitivity(i, j)
                    for j in range(g_nrxn, g_nrxn + s_nrxn)
                ]
                # gas_therm_sensitivities = [sim.sensitivity(i,j)
                # for j in range(g_nrxn+s_nrxn,g_nrxn+s_nrxn+g_nspec)]
                # surf_therm_sensitivities = [sim.sensitivity(i,j)
                # for j in range(g_nrxn+s_nrxn+g_nspec,g_nrxn+s_nrxn+g_nspec+s_nspec)]

                sensitivities_all = (
                    gas_sensitivities + surf_sensitivities
                    # + gas_therm_sensitivities
                )

            writer.writerow([
                temp,
                pressure,
                volume_flow,
                X_co,
                X_co2,
                X_h2,
                X_h2o,
                co2_ratio,
                h2_ratio,
                gas.T,
                sim.rtol,
                sim.atol,
                reactor_type_str,
            ] + list(gas.X) + list(surf.X) + list(gas.net_production_rates) +
                            list(surf.net_production_rates) +
                            list(gas.net_rates_of_progress) +
                            list(surf.net_rates_of_progress) +
                            sensitivities_all)

        else:
            writer.writerow([
                temp,
                pressure,
                volume_flow,
                X_co,
                X_co2,
                X_h2,
                X_h2o,
                co2_ratio,
                h2_ratio,
                gas.T,
                sim.rtol,
                sim.atol,
                reactor_type_str,
            ] + list(gas.X) + list(surf.X) + list(gas.net_production_rates) +
                            list(surf.net_production_rates) +
                            list(gas.net_rates_of_progress) +
                            list(surf.net_rates_of_progress))

        # writer_csp.writerow(
        #     [
        #         iter_ct,
        #         sim.time,
        #         dt,
        #         gas.density,
        #         gas.P,
        #         gas.T,
        #     ]
        #     + list(gas.X)
        #     + list(surf.X)
        # )

        iter_ct += 1

    outfile.close()
    # outfile_csp.close()

    # save flux diagrams at the end of the run
    save_flux_diagrams(gas, suffix=flux_path, timepoint="end")
    save_flux_diagrams(surf, suffix=flux_path, timepoint="end")
    return
Esempio n. 25
0
def run_reactor(
    cti_file,
    t_array=[548],
    surf_t_array=[
        548
    ],  # not used, but will be for different starting temperatures
    p_array=[1],
    v_array=[2.771e-10
             ],  # 14*7*(140e-4)^2*π/2*0.9=0.0002771(cm^3)=2.771e-10(m^3)
    o2_array=[0.88],
    nh3_array=[0.066],
    rtol=1.0e-11,
    atol=1.0e-22,
    reactor_type=0,
    energy="off",
    sensitivity=False,
    sensatol=1e-6,
    sensrtol=1e-6,
    reactime=1e5,
):

    # 14 aluminum plates, each of them containing seven semi-cylindrical microchannels of 280 µm width
    # and 140 µm depth, 9 mm long, arranged at equal distances of 280 µm

    try:
        array_i = int(os.getenv("SLURM_ARRAY_TASK_ID"))
    except TypeError:
        array_i = 0

    # get git commit hash and message
    rmg_model_path = "../ammonia"
    repo = git.Repo(rmg_model_path)
    date = time.localtime(repo.head.commit.committed_date)
    git_date = f"{date[0]}_{date[1]}_{date[2]}_{date[3]}{date[4]}"
    git_sha = str(repo.head.commit)[0:6]
    git_msg = str(repo.head.commit.message)[0:50].replace(" ", "_").replace(
        "'", "_").replace("\n", "")
    git_file_string = f"{git_date}_{git_sha}_{git_msg}"

    # set sensitivity string for file path name
    if sensitivity:
        sensitivity_str = "on"
    else:
        sensitivity_str = "off"

    # this should probably be outside of function
    settings = list(
        itertools.product(t_array, surf_t_array, p_array, v_array, o2_array,
                          nh3_array))

    # constants
    pi = math.pi

    # set initial temps, pressures, concentrations
    temp = settings[array_i][1]  # kelvin
    temp_str = str(temp)[0:3]
    pressure = settings[array_i][2] * ct.one_atm  # Pascals

    surf_temp = temp

    X_o2 = settings[array_i][4]
    x_O2_str = str(X_o2)[0].replace(".", "_")

    X_nh3 = (settings[array_i][5])
    x_NH3_str = str(X_nh3)[0:11].replace(".", "_")

    X_he = 1 - X_o2 - X_nh3

    mw_nh3 = 17.0306e-3  # [kg/mol]
    mw_o2 = 31.999e-3  # [kg/mol]
    mw_he = 4.002602e-3  # [kg/mol]

    o2_ratio = X_nh3 / X_o2

    # O2/NH3/He: typical is
    concentrations_rmg = {"O2(2)": X_o2, "NH3(6)": X_nh3, "He": X_he}

    # initialize cantera gas and surface
    gas = ct.Solution(cti_file, "gas")
    surf = ct.Interface(cti_file, "surface1", [gas])

    # initialize temperatures
    gas.TPX = temp, pressure, concentrations_rmg
    surf.TP = temp, pressure  # change this to surf_temp when we want a different starting temperature for the surface

    # if a mistake is made with the input,
    # cantera will normalize the mole fractions.
    # make sure that we are reporting/using
    # the normalized values
    X_o2 = float(gas["O2(2)"].X)
    X_nh3 = float(gas["NH3(6)"].X)
    X_he = float(gas["He"].X)

    # create gas inlet
    inlet = ct.Reservoir(gas)

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

    # Reactor volume
    number_of_reactors = 1001
    rradius = 1.4e-4  #140µm to 0.00014m
    rtotal_length = 9e-3  #9mm to 0.009m
    rtotal_vol = (rradius**2) * pi * rtotal_length / 2

    rlength = rtotal_length / 1001

    # divide totareactor total volume
    rvol = (rtotal_vol) / number_of_reactors

    # Catalyst Surface Area
    site_density = (surf.site_density * 1000
                    )  # [mol/m^2] cantera uses kmol/m^2, convert to mol/m^2
    cat_area_total = rradius * 2 / 2 * pi * rtotal_length  # [m^3]
    cat_area = cat_area_total / number_of_reactors

    # reactor initialization
    if reactor_type == 0:
        r = ct.Reactor(gas, energy=energy)
        reactor_type_str = "Reactor"
    elif reactor_type == 1:
        r = ct.IdealGasReactor(gas, energy=energy)
        reactor_type_str = "IdealGasReactor"
    elif reactor_type == 2:
        r = ct.ConstPressureReactor(gas, energy=energy)
        reactor_type_str = "ConstPressureReactor"
    elif reactor_type == 3:
        r = ct.IdealGasConstPressureReactor(gas, energy=energy)
        reactor_type_str = "IdealGasConstPressureReactor"

    # calculate the available catalyst area in a differential reactor
    rsurf = ct.ReactorSurface(surf, r, A=cat_area)
    r.volume = rvol
    surf.coverages = "X(1):1.0"

    # flow controllers
    one_atm = ct.one_atm
    FC_temp = 293.15
    volume_flow = settings[array_i][3]  # [m^3/s]
    molar_flow = volume_flow * one_atm / (8.3145 * FC_temp)  # [mol/s]
    mass_flow = molar_flow * (X_nh3 * mw_nh3 + X_o2 * mw_o2 + X_he * mw_he
                              )  # [kg/s]
    mfc = ct.MassFlowController(inlet, r, mdot=mass_flow)

    # A PressureController has a baseline mass flow rate matching the 'master'
    # MassFlowController, with an additional pressure-dependent term. By explicitly
    # including the upstream mass flow rate, the pressure is kept constant without
    # needing to use a large value for 'K', which can introduce undesired stiffness.
    outlet_mfc = ct.PressureController(r, exhaust, master=mfc, K=0.01)

    # initialize reactor network
    sim = ct.ReactorNet([r])

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

    #################################################
    # Run single reactor
    #################################################

    # round numbers for filepath strings so they're easier to read
    # temp_str = '%s' % '%.3g' % tempn
    cat_area_str = "%s" % "%.3g" % cat_area

    # if it doesn't already exist, g
    species_path = (os.path.dirname(os.path.abspath(__file__)) +
                    f"/{git_file_string}/species_pictures")

    results_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_file_string}/{reactor_type_str}/energy_{energy}/sensitivity_{sensitivity_str}/{temp_str}/results"
    )

    flux_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_file_string}/{reactor_type_str}/energy_{energy}/sensitivity_{sensitivity_str}/{temp_str}/flux_diagrams/{x_O2_str}/{x_NH3_str}"
    )
    # create species folder for species pictures if it does not already exist
    try:
        os.makedirs(species_path, exist_ok=True)
        save_pictures(git_path=rmg_model_path, species_path=species_path)
    except OSError as error:
        print(error)

    try:
        os.makedirs(results_path, exist_ok=True)
    except OSError as error:
        print(error)

    try:
        os.makedirs(flux_path, exist_ok=True)
    except OSError as error:
        print(error)

    gas_ROP_str = [i + " ROP [kmol/m^3 s]" for i in gas.species_names]

    # surface ROP reports gas and surface ROP. these values are not redundant
    gas_surf_ROP_str = [
        i + " surface ROP [kmol/m^2 s]" for i in gas.species_names
    ]
    surf_ROP_str = [i + " ROP [kmol/m^2 s]" for i in surf.species_names]

    gasrxn_ROP_str = [
        i + " ROP [kmol/m^3 s]" for i in gas.reaction_equations()
    ]
    surfrxn_ROP_str = [
        i + " ROP [kmol/m^2 s]" for i in surf.reaction_equations()
    ]

    output_filename = (
        results_path +
        f"/Spinning_basket_area_{cat_area_str}_energy_{energy}" +
        f"_temp_{temp}_O2_{x_O2_str}_NH3_{x_NH3_str}.csv")

    outfile = open(output_filename, "w")
    writer = csv.writer(outfile)

    # Sensitivity atol, rtol, and strings for gas and surface reactions if selected
    # slows down script by a lot
    if sensitivity:
        sim.rtol_sensitivity = sensrtol
        sim.atol_sensitivity = sensatol
        sens_species = [
            "NH3(6)", "O2(2)", "N2(4)", "NO(5)", "N2O(7)"
        ]  #change THIS to your species, can add "," and other species

        # turn on sensitive reactions
        for i in range(gas.n_reactions):
            r.add_sensitivity_reaction(i)

        for i in range(surf.n_reactions):
            rsurf.add_sensitivity_reaction(i)

        # thermo sensitivities. leave off for now as they can cause solver crashes
        # for i in range(gas.n_species):
        #     r.add_sensitivity_species_enthalpy(i)

        # for i in range(surf.n_species):
        #     rsurf.add_sensitivity_species_enthalpy(i)

        for j in sens_species:
            gasrxn_sens_str = [
                j + " sensitivity to " + i for i in gas.reaction_equations()
            ]
            surfrxn_sens_str = [
                j + " sensitivity to " + i for i in surf.reaction_equations()
            ]
            # gastherm_sens_str = [j + " thermo sensitivity to " + i for i in gas.species_names]
            # surftherm_sens_str = [j + " thermo sensitivity to " + i for i in surf.species_names]
            sens_list = gasrxn_sens_str + surfrxn_sens_str  # + gastherm_sens_str

        writer.writerow([
            "Distance (mm)", "T (C)", "P (Pa)", "V (M^3/s)", "X_nh3 initial",
            "X_o2 initial", "X_he initial", "(NH3/O2)", "T (C) final", "Rtol",
            "Atol", "reactor type", "energy on?"
        ] + gas.species_names + surf.species_names + gas_ROP_str +
                        gas_surf_ROP_str + surf_ROP_str + gasrxn_ROP_str +
                        surfrxn_ROP_str + sens_list)

    else:

        writer.writerow([
            "Distance (mm)", "T (C)", "P (Pa)", "V (M^3/s)", "X_nh3 initial",
            "X_o2 initial", "X_he initial", "(NH3/O2)", "T (C) final", "Rtol",
            "Atol", "reactor type", "energy on?"
        ] + gas.species_names + surf.species_names + gas_ROP_str +
                        gas_surf_ROP_str + surf_ROP_str + gasrxn_ROP_str +
                        surfrxn_ROP_str)

    t = 0.0
    dt = 0.1
    iter_ct = 0
    # run the simulation
    first_run = True
    distance_mm = 0

    for n in range(number_of_reactors):

        # Set the state of the reservoir to match that of the previous reactor
        gas.TDY = TDY = r.thermo.TDY
        inlet.syncState()
        sim.reinitialize()
        previous_coverages = surf.coverages  # in case we want to retry

        if n > 0:  # Add a first row in the CSV with just the feed
            try:
                sim.advance_to_steady_state()
            except ct.CanteraError:
                t = sim.time
                sim.set_initial_time(0)
                gas.TDY = TDY
                surf.coverages = previous_coverages
                r.syncState()
                sim.reinitialize()
                new_target_time = 0.01 * t
                logging.warning(
                    f"Couldn't reach {t:.1g} s so going to try {new_target_time:.1g} s"
                )
                try:
                    sim.advance(new_target_time)
                except ct.CanteraError:
                    outfile.close()
                    raise

        # save flux diagrams at beginning of run
        if first_run == True:
            save_flux_diagrams(gas,
                               suffix=flux_path,
                               timepoint="beginning",
                               species_path=species_path)
            save_flux_diagrams(surf,
                               suffix=flux_path,
                               timepoint="beginning",
                               species_path=species_path)

            first_run = False

        if sensitivity:
            # get sensitivity for sensitive species i (e.g. methanol) in reaction j
            for i in sens_species:
                g_nrxn = gas.n_reactions
                s_nrxn = surf.n_reactions
                # g_nspec = gas.n_species
                # s_nspec = surf.n_species

                gas_sensitivities = [
                    sim.sensitivity(i, j) for j in range(g_nrxn)
                ]
                surf_sensitivities = [
                    sim.sensitivity(i, j)
                    for j in range(g_nrxn, g_nrxn + s_nrxn)
                ]
                # gas_therm_sensitivities = [sim.sensitivity(i,j)
                # for j in range(g_nrxn+s_nrxn,g_nrxn+s_nrxn+g_nspec)]
                # surf_therm_sensitivities = [sim.sensitivity(i,j)
                # for j in range(g_nrxn+s_nrxn+g_nspec,g_nrxn+s_nrxn+g_nspec+s_nspec)]

                sensitivities_all = (
                    gas_sensitivities + surf_sensitivities
                    # + gas_therm_sensitivities
                )

            writer.writerow([
                distance_mm,
                temp,
                gas.P,
                volume_flow,
                X_nh3,
                X_o2,
                X_he,
                o2_ratio,
                gas.T,
                sim.rtol,
                sim.atol,
                reactor_type_str,
                energy,
            ] + list(gas.X) + list(surf.X) + list(gas.net_production_rates) +
                            list(surf.net_production_rates) +
                            list(gas.net_rates_of_progress) +
                            list(surf.net_rates_of_progress) +
                            sensitivities_all, )

        else:
            writer.writerow([
                distance_mm,
                temp,
                gas.P,
                volume_flow,
                X_nh3,
                X_o2,
                X_he,
                o2_ratio,
                gas.T,
                sim.rtol,
                sim.atol,
                reactor_type_str,
                energy,
            ] + list(gas.X) + list(surf.X) + list(gas.net_production_rates) +
                            list(surf.net_production_rates) +
                            list(gas.net_rates_of_progress) +
                            list(surf.net_rates_of_progress))

        iter_ct += 1
        distance_mm = n * rlength * 1.0e3  # distance in mm

    outfile.close()

    # save flux diagrams at the end of the run
    save_flux_diagrams(gas,
                       suffix=flux_path,
                       timepoint="end",
                       species_path=species_path)
    save_flux_diagrams(surf,
                       suffix=flux_path,
                       timepoint="end",
                       species_path=species_path)
    return
Esempio n. 26
0
import sys

import cantera as ct

fmt = '%10.3f  %10.1f  %10.4f  %10.4g  %10.4g  %10.4g  %10.4g'
print('%10s  %10s  %10s  %10s  %10s  %10s %10s' %
      ('time [s]', 'T1 [K]', 'T2 [K]', 'V1 [m^3]', 'V2 [m^3]', 'V1+V2 [m^3]',
       'X(CO)'))

gas1 = ct.Solution('h2o2.cti')
gas1.TPX = 900.0, ct.one_atm, 'H2:2, O2:1, AR:20'

gas2 = ct.Solution('gri30.xml')
gas2.TPX = 900.0, ct.one_atm, 'CO:2, H2O:0.01, O2:5'

r1 = ct.Reactor(gas1)
r1.volume = 0.5
r2 = ct.Reactor(gas2)
r2.volume = 0.1
w = ct.Wall(r1, r2, K=1.0e3)

net = ct.ReactorNet([r1, r2])

tim = []
t1 = []
t2 = []
v1 = []
v2 = []
v = []
xco = []
xh2 = []
Esempio n. 27
0
real_gas = ct.Solution('nDodecane_Reitz.cti', 'nDodecane_RK')

# Set the state of the gas object:
real_gas.TP = reactorTemperature, reactorPressure

# Define the fuel, oxidizer and set the stoichiometry:
real_gas.set_equivalence_ratio(phi=1.0,
                               fuel='c12h26',
                               oxidizer={
                                   'o2': 1.0,
                                   'n2': 3.76
                               })

# Create a reactor object and add it to a reactor network
# In this example, this will be the only reactor in the network
r = ct.Reactor(contents=real_gas)
reactorNetwork = ct.ReactorNet([r])
timeHistory_RG = ct.SolutionArray(real_gas, extra=['t'])
# Tic
t0 = time.time()

# This is a starting estimate. If you do not get an ignition within this time,
# increase it
estimatedIgnitionDelayTime = 0.005
t = 0

counter = 1
while (t < estimatedIgnitionDelayTime):
    t = reactorNetwork.step()
    if (counter % 20 == 0):
        # We will save only every 20th value. Otherwise, this takes too long
Esempio n. 28
0
def run_reactor_ss(
    cti_file,
    t_array=[528],
    p_array=[75],
    v_array=[0.00424],
    h2_array=[0.75],
    co2_array=[0.5],
    rtol=1.0e-11,
    atol=1.0e-22,
    reactor_type=0,
    energy="off",
    sensitivity=False,
    sensatol=1e-6,
    sensrtol=1e-6,
    reactime=1e5,
):
    ''' 
    run the reactor to steady state. saves a single CSV output file with one row of data. 
    results saved in new folder marked "steady state" under reactor type
    
    '''

    import pandas as pd
    import numpy as np
    import time
    import cantera as ct
    from matplotlib import pyplot as plt
    import csv
    import math
    import os
    import sys
    import re
    import itertools
    import logging
    from collections import defaultdict
    import git

    try:
        array_i = int(os.getenv("SLURM_ARRAY_TASK_ID"))
    except TypeError:
        array_i = 0

    # get git commit hash and message

    repo = git.Repo("/work/westgroup/lee.ting/cantera/ammonia")
    git_sha = str(repo.head.commit)[0:6]
    git_msg = str(repo.head.commit.message)[0:20].replace(" ", "_").replace(
        "'", "_")

    # this should probably be outside of function
    settings = list(
        itertools.product(t_array, p_array, v_array, h2_array, co2_array))

    # constants
    pi = math.pi

    # set initial temps, pressures, concentrations
    temp = settings[array_i][0]  # kelvin
    temp_str = str(temp)[0:3]
    pressure = settings[array_i][1] * ct.one_atm  # Pascals

    X_h2 = settings[array_i][3]
    x_h2_str = str(X_h2)[0:3].replace(".", "_")
    x_CO_CO2_str = str(settings[array_i][4])[0:3].replace(".", "_")

    if X_h2 == 0.75:
        X_h2o = 0.05
    else:
        X_h2o = 0

    X_co = (1 - (X_h2 + X_h2o)) * (settings[array_i][4])
    X_co2 = (1 - (X_h2 + X_h2o)) * (1 - settings[array_i][4])

    # normalize mole fractions just in case
    # X_co = X_co/(X_co+X_co2+X_h2)
    # X_co2= X_co2/(X_co+X_co2+X_h2)
    # X_h2 = X_h2/(X_co+X_co2+X_h2)

    mw_co = 28.01e-3  # [kg/mol]
    mw_co2 = 44.01e-3  # [kg/mol]
    mw_h2 = 2.016e-3  # [kg/mol]
    mw_h2o = 18.01528e-3  # [kg/mol]

    co2_ratio = X_co2 / (X_co + X_co2)
    h2_ratio = (X_co2 + X_co) / X_h2

    # CO/CO2/H2/H2: typical is
    concentrations_rmg = {"O2(2)": X_co, "NH3(6)": X_co2, "He": X_h2}

    # initialize cantera gas and surface
    gas = ct.Solution(cti_file, "gas")

    # surf_grab = ct.Interface(cti_file,'surface1_grab', [gas_grab])
    surf = ct.Interface(cti_file, "surface1", [gas])

    # gas_grab.TPX =
    gas.TPX = temp, pressure, concentrations_rmg
    surf.TP = temp, pressure

    # create gas inlet
    inlet = ct.Reservoir(gas)

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

    # Reactor volume
    rradius = 35e-3
    rlength = 70e-3
    rvol = (rradius**2) * pi * rlength

    # Catalyst Surface Area
    site_density = (surf.site_density * 1000
                    )  # [mol/m^2]cantera uses kmol/m^2, convert to mol/m^2
    cat_weight = 4.24e-3  # [kg]
    cat_site_per_wt = (300 *
                       1e-6) * 1000  # [mol/kg] 1e-6mol/micromole, 1000g/kg
    cat_area = site_density / (cat_weight * cat_site_per_wt)  # [m^3]

    # reactor initialization
    if reactor_type == 0:
        r = ct.Reactor(gas, energy=energy)
        reactor_type_str = "Reactor"
    elif reactor_type == 1:
        r = ct.IdealGasReactor(gas, energy=energy)
        reactor_type_str = "IdealGasReactor"
    elif reactor_type == 2:
        r = ct.ConstPressureReactor(gas, energy=energy)
        reactor_type_str = "ConstPressureReactor"
    elif reactor_type == 3:
        r = ct.IdealGasConstPressureReactor(gas, energy=energy)
        reactor_type_str = "IdealGasConstPressureReactor"

    rsurf = ct.ReactorSurface(surf, r, A=cat_area)
    r.volume = rvol
    surf.coverages = "X(1):1.0"

    # flow controllers (Graaf measured flow at 293.15 and 1 atm)
    one_atm = ct.one_atm
    FC_temp = 293.15
    volume_flow = settings[array_i][2]  # [m^3/s]
    molar_flow = volume_flow * one_atm / (8.3145 * FC_temp)  # [mol/s]
    mass_flow = molar_flow * (X_co * mw_co + X_co2 * mw_co2 + X_h2 * mw_h2 +
                              X_h2o * mw_h2o)  # [kg/s]
    mfc = ct.MassFlowController(inlet, r, mdot=mass_flow)

    # A PressureController has a baseline mass flow rate matching the 'master'
    # MassFlowController, with an additional pressure-dependent term. By explicitly
    # including the upstream mass flow rate, the pressure is kept constant without
    # needing to use a large value for 'K', which can introduce undesired stiffness.
    outlet_mfc = ct.PressureController(r, exhaust, master=mfc, K=0.01)

    # initialize reactor network
    sim = ct.ReactorNet([r])

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

    #################################################
    # Run single reactor
    #################################################

    # round numbers so they're easier to read
    # temp_str = '%s' % '%.3g' % tempn

    cat_area_str = "%s" % "%.3g" % cat_area
    results_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_sha}_{git_msg}/{reactor_type_str}/steady_state/{temp_str}/results"
    )

    flux_path = (
        os.path.dirname(os.path.abspath(__file__)) +
        f"/{git_sha}_{git_msg}/{reactor_type_str}/steady_state/{temp_str}/flux_diagrams/{x_h2_str}/{x_CO_CO2_str}"
    )
    try:
        os.makedirs(results_path, exist_ok=True)
    except OSError as error:
        print(error)

    try:
        os.makedirs(flux_path, exist_ok=True)
    except OSError as error:
        print(error)

    gas_ROP_str = [i + " ROP [kmol/m^3 s]" for i in gas.species_names]

    # surface ROP reports gas and surface ROP. these values are not redundant.
    gas_surf_ROP_str = [
        i + " surface ROP [kmol/m^2 s]" for i in gas.species_names
    ]
    surf_ROP_str = [i + " ROP [kmol/m^2 s]" for i in surf.species_names]

    gasrxn_ROP_str = [
        i + " ROP [kmol/m^3 s]" for i in gas.reaction_equations()
    ]
    surfrxn_ROP_str = [
        i + " ROP [kmol/m^2 s]" for i in surf.reaction_equations()
    ]

    output_filename = (
        results_path +
        f"/Spinning_basket_area_{cat_area_str}_energy_{energy}" +
        f"_temp_{temp}_h2_{x_h2_str}_COCO2_{x_CO_CO2_str}.csv")

    outfile = open(output_filename, "w")
    writer = csv.writer(outfile)

    writer.writerow([
        "T (C)",
        "P (atm)",
        "V (M^3/s)",
        "X_co initial",
        "X_co2 initial",
        "X_h2 initial",
        "X_h2o initial",
        "CO2/(CO2+CO)",
        "(CO+CO2/H2)",
        "T (C) final",
        "Rtol",
        "Atol",
        "reactor type",
    ] + gas.species_names + surf.species_names + gas_ROP_str +
                    gas_surf_ROP_str + surf_ROP_str + gasrxn_ROP_str +
                    surfrxn_ROP_str)

    # Run Simulation to steady state
    sim.advance_to_steady_state()

    # Record steady state data to CSV
    writer.writerow([
        temp,
        pressure,
        volume_flow,
        X_co,
        X_co2,
        X_h2,
        X_h2o,
        co2_ratio,
        h2_ratio,
        gas.T,
        sim.rtol,
        sim.atol,
        reactor_type_str,
    ] + list(gas.X) + list(surf.X) + list(gas.net_production_rates) +
                    list(surf.net_production_rates) +
                    list(gas.net_rates_of_progress) +
                    list(surf.net_rates_of_progress))

    outfile.close()

    # save flux diagrams at the end of the run
    save_flux_diagrams(gas, suffix=flux_path, timepoint="end")
    save_flux_diagrams(surf, suffix=flux_path, timepoint="end")
    return
Esempio n. 29
0
# Create reservoirs for the two inlet streams and for the outlet stream.  The
# upsteam reservoirs could be replaced by reactors, which might themselves be
# connected to reactors further upstream. The outlet reservoir could be
# replaced with a reactor with no outlet, if it is desired to integrate the
# composition leaving the mixer in time, or by an arbitrary network of
# downstream reactors.
res_a = ct.Reservoir(gas_a)
res_b = ct.Reservoir(gas_b)
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(
Esempio n. 30
0
"""
Constant-pressure, adiabatic kinetics simulation with sensitivity analysis
"""

import sys
import numpy as np

import cantera as ct

gri3 = ct.Solution('gri30.xml')
temp = 1500.0
pres = ct.one_atm

gri3.TPX = temp, pres, 'CH4:0.1, O2:2, N2:7.52'
r = ct.Reactor(gri3)

air = ct.Solution('air.xml')
air.TP = temp, pres
env = ct.Reservoir(air)

# Define a wall between the reactor and the environment, and make it flexible,
# so that the pressure in the reactor is held at the environment pressure.
w = ct.Wall(r, env)
w.expansion_rate_coeff = 1.0e6  # set expansion parameter. dV/dt = KA(P_1 - P_2)
w.area = 1.0

sim = ct.ReactorNet([r])

# enable sensitivity with respect to the rates of the first 10
# reactions (reactions 0 through 9)
for i in range(10):