Пример #1
0
def save_flux_diagrams(solution,
                       times,
                       conditions=None,
                       condition_type='adiabatic-constant-volume',
                       path='.',
                       element='C',
                       filename='flux_diagram',
                       filetype='png'):
    """
    This method is similar to run_simulation but it saves reaction path
    diagrams instead of returning objects.
    """
    if conditions is not None:
        solution.TPX = conditions
    if condition_type == 'adiabatic-constant-volume':
        reactor = ct.IdealGasReactor(solution)
    elif condition_type == 'constant-temperature-and-pressure':
        reactor = ct.IdealGasConstPressureReactor(solution, energy='off')
    else:
        raise NotImplementedError(
            'only "adiabatic-constant-volume" or "constant-temperature-and-pressure" is supported. {} input'
            .format(condition_type))
    simulator = ct.ReactorNet([reactor])
    solution = reactor.kinetics

    for time in times:
        simulator.advance(time)

        save_flux_diagram(solution,
                          filename=filename +
                          '_{:.2e}s'.format(simulator.time),
                          path=path,
                          element=element,
                          filetype=filetype)
Пример #2
0
 def averageChemicalPower(gas, tMax):
     '''
     Function: averageChemicalPower
     ======================================================================
     This function returns the average chemical Power of a HP reaction with 
     respect to the temperature
     '''
     #find the equilibrium value
     (T0, p0, X0) = gas.TPX
     gas.equilibrate('HP')
     try:
         iH2O = gas.species_index('H2O')
         H2O = 'H2O'
     except:
         iH2O = gas.species_index('h2o')
         H2O = 'h2o'
     H2Oeq = gas.Y[iH2O]
     gas.TPX = (T0, p0, X0)
     alpha = 0.98
     #arbitrary percentage
     #initiate the reactor network
     r = ct.IdealGasConstPressureReactor(gas)
     sim = ct.ReactorNet([r])
     time = 0.0
     qDotMean = 0.0
     T = gas.T
     dt = tMax / 100.0
     #advance simulation with guessed timestep
     while r.thermo[H2O].Y < (alpha * H2Oeq):
         time += dt
         sim.advance(time)
         qDotMean += (gas.T - T) * chemicalPower(gas, 'hp')
         T = gas.T
     return qDotMean / (gas.T - T0)
Пример #3
0
def states_new_init(A):
    R_new = ct.Reaction.fromCti('''reaction('O2 + 2 H2 => 2 H2O',
            [%e, 0.0, 0.0])''' % (A))
    #print(type(R_new))
    #print(type(gas.reactions()))
    gas2 = ct.Solution(thermo='IdealGas',
                       kinetics='GasKinetics',
                       species=gas.species(),
                       reactions=[R_new])
    gas2.TPX = initial_state
    r_new = ct.IdealGasConstPressureReactor(gas2, energy='off')
    t_new = 0.0
    states_new = ct.SolutionArray(gas2, extra=['t'])
    sim_new = ct.ReactorNet([r_new])
    tt = []
    TT = []
    for n in range(100):
        '''t_new += 1.e-5
        sim_new.advance(t_new)
        #print(t_new)
        tt.append(1000 * t_new*1000)
        TT.append(r_new.T)'''
        t_new += 1.e-5
        sim_new.advance(t_new)
        states_new.append(r_new.thermo.state, t=t_new * 1e3)
    return states_new, gas2
Пример #4
0
    def run(self, reactor_choice, t_end, T_reac, P_reac, mix, **kwargs):
        def list2ct_mixture(
            mix
        ):  # list in the form of [[species, mol_frac], [species, mol_frac],...]
            return ', '.join("{!s}:{!r}".format(species, mol_frac)
                             for (species, mol_frac) in mix)

        details = {'success': False, 'message': []}

        if isinstance(mix, list):
            mix = list2ct_mixture(mix)

        mech_out = self.mech.set_TPX(T_reac, P_reac, mix)
        if not mech_out['success']:
            details['success'] = False
            details['message'] = mech_out['message']
            return None, mech_out

        #start = timer()
        if reactor_choice == 'Incident Shock Reactor':
            SIM, details = self.incident_shock_reactor(self.mech.gas, details,
                                                       t_end, **kwargs)
        elif '0d Reactor' in reactor_choice:
            if reactor_choice == '0d Reactor - Constant Volume':
                reactor = ct.IdealGasReactor(self.mech.gas)
            elif reactor_choice == '0d Reactor - Constant Pressure':
                reactor = ct.IdealGasConstPressureReactor(self.mech.gas)

            SIM, details = self.zero_d_ideal_gas_reactor(
                self.mech.gas, reactor, details, t_end, **kwargs)

        #print('{:0.1f} us'.format((timer() - start)*1E3))
        return SIM, details
Пример #5
0
def simulate_branching_various_conditions_3D(
    cantera_input_path,
    HO2_frac,
    conversion_species=['npropyloo', 'npropyl'],
    desired_conversion=0.95,
    starting_alkyl_radical='npropyl',
    expected_products=None,
    peroxy_frac=1e-17,
    temperatures=np.linspace(250, 1250, 25),
    pressures=np.logspace(3, 7, 15),
    NO_fracs=np.logspace(-12, -4, 15)):

    combs = [{
        'temp (K)': f1,
        'NO (fraction)': f2,
        'pres (Pa)': f3
    } for f1 in temperatures for f2 in NO_fracs for f3 in pressures]
    df = pd.DataFrame(combs)

    for index in df.index:
        initialMoleFractions = {
            "NO": df.loc[index, 'NO (fraction)'],
            "HO2": HO2_frac,
            starting_alkyl_radical: peroxy_frac,
            'O2': 0.21,
            "N2": 0.79,
        }
        solution = ctt.create_mechanism(cantera_input_path)

        conditions = df.loc[index, 'temp (K)'], df.loc[
            index, 'pres (Pa)'], initialMoleFractions
        solution.TPX = conditions
        reactor = ct.IdealGasConstPressureReactor(solution, energy='off')
        simulator = ct.ReactorNet([reactor])
        solution = reactor.kinetics

        peroxy_conc = sum([
            solution.concentrations[solution.species_index(s)]
            for s in conversion_species
        ])
        outputs = ctt.run_simulation_till_conversion(
            solution=solution,
            conditions=conditions,
            species=conversion_species,
            conversion=desired_conversion,
            condition_type='constant-temperature-and-pressure',
            output_reactions=False,
            atol=1e-25,
        )
        species = outputs['species']

        for name, conc in species.iteritems():
            if not expected_products or name in expected_products:
                df.loc[index, name] = (conc / peroxy_conc).values[-1]

    df.fillna(value=0, inplace=True)
    return df
def totaldelaydata1(ITemp, IPressure, Ifraction, IER):
    Temp = np.zeros(ITemp)
    a = np.zeros(Ifraction)
    pressure = np.zeros(IPressure)
    ER = np.zeros(IER)
    # write output CSV file for importing into Excel
    gas = ct.Solution('gri30.xml')
    #writer.writerow(gas.species_names)
    for i in range(ITemp):
        Temp[i] = 1000.0 + 50 * i
        for m in range(IPressure):
            pressure[m] = 1 * ct.one_atm + 5.0 * m * ct.one_atm
            for n in range(Ifraction):
                a[n] = 0.1 * n
                for e in range(IER):
                    gas.TP = Temp[i], pressure[m]
                    ER[e] = 0.5 + 0.1 * e
                    fO2 = ((1 - a[n]) * 2.0 + a[n] * 0.5) * (1 / ER[e])
                    CH4_P = 1 - a[n]
                    H2_P = a[n]
                    O2_P = fO2
                    N2_P = 3.76 * fO2
                    gas.X = {
                        'CH4': 1 - a[n],
                        'H2': a[n],
                        'O2': fO2,
                        'N2': 3.76 * fO2
                    }
                    r = ct.IdealGasConstPressureReactor(gas)
                    sim = ct.ReactorNet([r])
                    time = 0.0
                    states = ct.SolutionArray(gas, extra=['t'])

                    #print('%10s %10s %10s %14s' % ('t [s]','T [K]','P [Pa]','u [J/kg]'))
                    for number in range(10000):
                        time += 1.e-6
                        sim.advance(time)
                        states.append(r.thermo.state, t=time * 1e3)
                        #print('%10.3e %10.3f %10.3f %14.6e' % (sim.time, r.T,r.thermo.P, r.thermo.u))

                    X_OH = np.max(states.X[:, gas.species_index('OH')])
                    X_HO2 = np.max(states.X[:, gas.species_index('HO2')])

                    # We will use the 'OH' species to compute the ignition delay
                    max_index = np.argmax(states.X[:, gas.species_index('OH')])
                    Tau1 = states.t[max_index]

                    # We will use the 'HO2' species to compute the ignition delay
                    #max_index = np.argmax(states.X[:, gas.species_index('HO2')])
                    #Tau2[i] = states.t[max_index]

                    #    writer.writerow([pressure, Temp[i], CH4_P, H2_P,
                    #                   O2_P, N2_P, ER, X_OH[i], X_HO2[i], Tau1[i]])
                    yield pressure[m], Temp[
                        i], CH4_P, H2_P, O2_P, N2_P, X_OH, X_HO2, Tau1
                    gas = ct.Solution('gri30.xml')
Пример #7
0
def runsim(times):
    if (pressureflag == 0):
        if (energyflag == 1):
            r = ct.IdealGasReactor(gas, name='R1')
        else:
            r = ct.IdealGasReactor(gas, name='R1', energy='off')
    else:
        if (energyflag == 1):
            r = ct.IdealGasConstPressureReactor(gas, name='R1')
        else:
            r = ct.IdealGasConstPressureReactor(gas, name='R1', energy='off')
    sim = ct.ReactorNet([r])

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

    for t in times:
        sim.advance(t)
        norm = 0

        states.append(r.thermo.state, t=t)

    return states
Пример #8
0
 def set_case(self, problem):
     ''' function that set up the scenario'''
     if isinstance(problem[0], str) is False: problem[0] = '0D'
     if isinstance(problem[1], str) is False: problem[1] = 'volume'
     if problem[0].lower() == '0d':
         if problem[1].lower() == 'pressure':
             self.reactor = ct.IdealGasConstPressureReactor(self.gas)
             self.problemis = '0D, iso bar'
         if problem[1].lower() == 'volume':
             self.reactor = ct.IdealGasReactor(self.gas)
             self.reactor.volume = self.V
             self.problemis = '0D, iso volume'
         self.system = ct.ReactorNet((self.reactor, ))
Пример #9
0
def run(chemistry=None, initial=None, settings=None):
    """Function handling reactor simulation.

    The function uses the class 'ctwrap.Parser' in conjunction with 'pint.Quantity'
    for handling and conversion of units.

    Arguments:
        chemistry  (Parser): overloads 'defaults.chemistry'
        initial    (Parser): overloads 'defaults.initial'
        settings (Parser): overloads 'defaults.settings'

    Returns:
        Cantera SolutionArray
    """

    # initialize gas object
    gas = ct.Solution(chemistry.mechanism)

    # set temperature, pressure, and composition
    T = initial.T.m_as('kelvin')
    P = initial.P.m_as('pascal')
    gas.TP = T, P
    phi = initial['phi']
    gas.set_equivalence_ratio(phi, initial['fuel'], initial['oxidizer'])

    # define a reactor network
    reactor = ct.IdealGasConstPressureReactor(gas)
    sim = ct.ReactorNet([reactor])

    delta_T_max = 20.
    reactor.set_advance_limit('temperature', delta_T_max)

    # set simulation parameters
    sim.atol = settings['atol']
    sim.rtol = settings['rtol']
    sim.max_time_step = settings['max_time_step']
    delta_t = settings['delta_t']
    n_points = settings['n_points']

    # define SolutionArray and run simulation
    states = ct.SolutionArray(gas, extra=['t'])
    time = sim.time

    for _ in range(n_points):

        time += delta_t
        sim.advance(time)
        states.append(reactor.thermo.state, t=time)

    return states
Пример #10
0
    def reinitialize_simulation(
        self,
        T0=None,
        P0=None,
        X0=None,
        V0=None,
    ):
        """
        Re-initializes the cantera solution object (self.model) and cantera reactor object (self.cantera_reactor).
        This method is called at the start of other methods in this class.

        Args:
            T0 (float): Initial temperature in Kelvin.
            P0 (float): Initial pressure in Pascals.
            X0 (dict): Initial mole fractions.
            V0 (float): Initial volume in m3.
        """
        # assign initial conditions
        if V0 is None:
            self.model.TPX = T0, P0, X0
        elif P0 is None:
            self.model.TDX = T0, 1 / V0, X0

        self.cantera_reactor = ct.IdealGasConstPressureReactor(
            contents=self.model)
        # Run this individual condition as a simulation
        self.cantera_simulation = ct.ReactorNet([self.cantera_reactor])

        # set simulation tolerance
        self.cantera_simulation.atol = self.atol
        self.cantera_simulation.rtol = self.rtol

        if self.sensitive_species:
            if ct.__version__ == '2.2.1':
                self.logger.warning(
                    'Cantera version 2.2.1 may not support sensitivity analysis unless SUNDIALS '
                    'was used during compilation.')
                self.logger.warning(
                    'Upgrade to newer of Cantera in anaconda using the command '
                    '"conda update -c rmg cantera"')
            # Add all the reactions as part of SA
            for i in range(self.num_ct_reactions):
                self.cantera_reactor.add_sensitivity_reaction(i)
            # add all species enthalpies as part of SA
            for i in range(self.num_ct_species):
                self.cantera_reactor.add_sensitivity_species_enthalpy(i)
            # Set the tolerances for the sensitivity coefficients
            self.cantera_simulation.rtol_sensitivity = self.sa_atol
            self.cantera_simulation.atol_sensitivity = self.sa_rtol
Пример #11
0
    def setup_case(self):
        """Initialize simulation case.
        """
        self.gas = ct.Solution(self.model, self.phase_name)

        # Default maximum number of steps
        self.max_steps = 10000
        if self.properties.max_steps:
            self.max_steps = self.properties.max_steps

        # By default, simulations will run to steady state, with the maximum number of steps
        # given by ``self.max_steps``. Alternatively, an end time (in seconds) can be
        # given in cases where something specific is needed (e.g., longer than normal)
        self.time_end = 0.0
        if self.properties.end_time:
            self.time_end = self.properties.end_time

        self.gas.TP = (self.properties.temperature,
                       self.properties.pressure * ct.one_atm)
        # set initial composition using either equivalence ratio or general reactant composition
        if self.properties.equivalence_ratio:
            self.gas.set_equivalence_ratio(self.properties.equivalence_ratio,
                                           self.properties.fuel,
                                           self.properties.oxidizer)
        else:
            if self.properties.composition_type == 'mole':
                self.gas.TPX = (self.properties.temperature,
                                self.properties.pressure * ct.one_atm,
                                self.properties.reactants)
            else:
                self.gas.TPY = (self.properties.temperature,
                                self.properties.pressure * ct.one_atm,
                                self.properties.reactants)

        if self.properties.kind == 'constant pressure':
            self.reac = ct.IdealGasConstPressureReactor(self.gas)
        else:
            self.reac = ct.IdealGasReactor(self.gas)

        # Create ``ReactorNet`` newtork
        self.sim = ct.ReactorNet([self.reac])

        # Set file for later data file
        self.save_file = os.path.join(self.path, str(self.idx) + '.h5')
        self.sample_points = []

        self.ignition_delay = 0.0
Пример #12
0
    def __init__(self, gas):
        """Initialize particle object with thermochemical state.

        Parameters
        ----------
        gas : `cantera.Solution`
            Initial thermochemical state of particle

        Returns
        -------
        None

        """

        self.gas = gas
        self.reac = ct.IdealGasConstPressureReactor(self.gas)
        self.netw = ct.ReactorNet([self.reac])
Пример #13
0
def fitness(indv):
    tmp_parameters = indv.solution
    
    tmp_reactions = R.copy()
    for i in range(len(tmp_reactions)):
        if tmp_reactions[i].reaction_type !=4:
            tmp_reactions[i].rate = ct.Arrhenius(A = tmp_parameters[3*i], \
            b = tmp_parameters[3*i+1], E = tmp_parameters[3*i+2])
        else:
            tmp_reactions[i].low_rate = ct.Arrhenius(A = tmp_parameters[3*i], \
            b = tmp_parameters[3*i+1], E = tmp_parameters[3*i+2])
    gas2 = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',species=gas.species(),reactions=tmp_reactions)

    gas2.TPX = temp, pres, 'CH4:1, O2:2'
    r = ct.IdealGasConstPressureReactor(gas2)
    sim = ct.ReactorNet([r])
    states = ct.SolutionArray(gas2, extra=['t'])
    try:
        for t in np.arange(0, end_time, step_time):
            sim.advance(t)
            states.append(r.thermo.state, t=1000*t)
    except:
        return 1e8

    max_delta = 0
    index_temp = 0
    for i in range(len(states.T)-2):
        if(states.T[i+1] - states.T[i] > max_delta):
            max_delta = states.T[i+1] - states.T[i]
            index_temp = i

    ignite_time_optimised = float(states.t[index_temp])
    optimised_T   = float(states.T[-1]        )
    optimised_CH4 = float(states('CH4').X[-1] )
    optimised_O2  = float(states('O2').X[-1]  )
    optimised_CO2 = float(states('CO2').X[-1] )
    optimised_H2O = float(states('H2O').X[-1] )
    optimised_H   = float(states('H').X[-1]   )
    optimised_OH  = float(states('OH').X[-1]  )

    # return ((ignite_time_optimised - ignite_time_precise)/ignite_time_precise)**2\
    # + ((optimised_T - precise_T)/precise_T)**2\
    # + ((optimised_O2 - precise_O2)/precise_O2)**2\
    # + ((optimised_CO2 - precise_CO2)/precise_CO2)**2\
    # + ((optimised_H2O - precise_H2O)/precise_H2O)**2\
    return 1e8*abs(ignite_time_optimised - ignite_time_precise) + abs(optimised_T - precise_T)
Пример #14
0
    def react(self, dt):
        """Perform reaction timestep by advancing network.

        Parameters
        ----------
        dt : float
            Reaction timestep [seconds]

        Returns
        -------
        None

        """
        reac = ct.IdealGasConstPressureReactor(self.gas,
            volume=Particle.particle_mass/self.gas.density)
        netw = ct.ReactorNet([reac])
        netw.advance(netw.time + dt)
Пример #15
0
    def ODE_integrate(self, Y, T, p, steps):
        # do the ODE integration
        # Y is the species vector, T temperature, p pressure
        #self.gas = ct.Solution('utils/lu19.cti')
        self.gas.TPY = T, p, Y
        current_rho = self.gas.density
        r = ct.IdealGasConstPressureReactor(self.gas)
        sim = ct.ReactorNet([r])
        time = 0.0

        # do 10 small integration steps to get to dt! --> makes it less stiff
        for n in range(steps):
            time += self.dt / steps
            sim.advance(time)

        T_after = r.thermo.T
        Y_after = r.thermo.Y
        # mass fraction reaction rate dY/dt [1/s] same as in Cantera OF:
        RR_Y = (Y_after - Y) * current_rho / self.dt

        return T_after, Y_after, RR_Y, current_rho
Пример #16
0
    def test_equilibrium_HP(self):
        # Adiabatic, constant pressure combustion should proceed to equilibrum
        # at constant enthalpy and pressure.

        P0 = 10 * ct.one_atm
        T0 = 1100
        X0 = 'H2:1.0, O2:0.5, AR:8.0'

        gas1 = ct.Solution('h2o2.xml')
        gas1.TPX = T0, P0, X0
        r1 = ct.IdealGasConstPressureReactor(gas1)

        net = ct.ReactorNet()
        net.add_reactor(r1)
        net.advance(1.0)

        gas2 = ct.Solution('h2o2.xml')
        gas2.TPX = T0, P0, X0
        gas2.equilibrate('HP')

        self.assertNear(r1.T, gas2.T)
        self.assertNear(r1.thermo.P, P0)
        self.assertNear(r1.thermo.density, gas2.density)
        self.assertArrayNear(r1.thermo.X, gas2.X)
def ShockTube(ctiFile,
              speciesNames,
              pressure,
              temperature,
              conditions,
              initialTime,
              finalTime,
              thermalBoundary,
              observables=[],
              physical_params=[],
              kinetic_sens=0,
              physical_sens=0,
              reactorType='cv'):
    #gas = ct.Solution('AramcoMech2.0.cti')
    # 'GRI30-1999.cti'

    for s in ['Ar', 'AR', 'He', 'HE', 'n2', 'N2']:
        if s in speciesNames:
            addBackin = s
            speciesNames.remove(s)
            break

    gas = ct.Solution(ctiFile)
    gas.TPX = temperature, pressure * 101325, conditions
    physicalParamsSpecies = ['X' + species for species in speciesNames]

    physical_params = ['P', 'T', 'X']

    if thermalBoundary == 'adiabatic':
        if reactorType == 'cv':
            shockTube = ct.IdealGasReactor(gas, name='R1', energy='on')
        elif reactorType == 'cp':
            shockTube = ct.IdealGasConstPressureReactor(gas,
                                                        name='R1',
                                                        energy='on')
    elif thermalBoundary == 'isothermal':
        if reactorType == 'cv':
            shockTube = ct.IdealGasReactor(gas, name='R1', energy='off')
        elif reactorType == 'cp':
            shockTube = ct.IdealGasConstPressureReactor(gas,
                                                        name='R1',
                                                        energy='off')
    else:
        raise Exception(
            'Please enter adiabatic or isothermal for the thermal boundary layer'
        )

    sim = ct.ReactorNet([shockTube])

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

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

    if kinetic_sens == 1 and bool(observables):
        [shockTube.add_sensitivity_reaction(i) for i in range(gas.n_reactions)]
        dfs = [pd.DataFrame() for x in range(len(observables))]
        tempArray = [
            np.zeros(gas.n_reactions) for x in range(len(observables))
        ]

    if physical_sens == 1 and bool(observables):
        baseConditions = gas.TPX
        originalConditions = conditions

    columnNames = [
        shockTube.component_name(item) for item in range(shockTube.n_vars)
    ]
    columnNames = ['time'] + ['pressure'] + columnNames
    timeHistory = pd.DataFrame(columns=columnNames)
    timeHistorytest = pd.DataFrame(columns=columnNames)
    timeHistorytest2 = pd.DataFrame(columns=columnNames)
    timeHistorytest4 = [
        pd.DataFrame(columns=columnNames)
        for item in range(len(physicalParamsSpecies))
    ]

    t = initialTime
    counter = 0
    #commenting out volume
    while t < finalTime:
        t = sim.step()
        state = np.hstack([
            t, shockTube.thermo.P, shockTube.mass, shockTube.volume,
            shockTube.T, shockTube.thermo.X
        ])
        timeHistory.loc[counter] = state

        if kinetic_sens == 1 and bool(observables):

            newcounter = 0
            for observable, reaction in itertools.product(
                    observables, range(gas.n_reactions)):
                tempArray[observables.index(
                    observable)][reaction] = sim.sensitivity(
                        observable, reaction)
                newcounter += 1

                if (newcounter % gas.n_reactions == 0):
                    dfs[observables.index(observable)] = dfs[observables.index(
                        observable)].append(((pd.DataFrame(
                            tempArray[observables.index(observable)])
                                              ).transpose()),
                                            ignore_index=True)

        counter += 1
    if kinetic_sens == 1 and bool(observables):
        ksensIndex = [
            timeHistory['time'].as_matrix(),
            gas.reaction_equations(), observables
        ]

        numpyMatrixsksens = [
            dfs[dataframe].as_matrix() for dataframe in range(len(dfs))
        ]
        numpyMatrixsBsens = [
            numpyMatrixsksens[x] * (np.log(
                timeHistory['temperature'].as_matrix().flatten()))[:,
                                                                   np.newaxis]
            for x in range(len(numpyMatrixsksens))
        ]
        numpyMatrixsEsens = [
            numpyMatrixsksens[x] *
            (np.true_divide(-1, timeHistory['temperature'].as_matrix().flatten(
            )))[:, np.newaxis] for x in range(len(numpyMatrixsksens))
        ]
        S = np.dstack(numpyMatrixsksens)
        Sa = S
        Sb = np.dstack(numpyMatrixsBsens)
        Se = np.dstack(numpyMatrixsEsens)
        S = np.dstack(numpyMatrixsksens)

    if physical_sens == 1 and bool(observables):
        dk = .01
        originalPsens = (timeHistory[observables]).applymap(np.log)

        for numOfPhyParams in range(len(physical_params)):
            if physical_params[numOfPhyParams] == 'T':
                gas2 = ct.Solution(ctiFile)
                gas2.TPX = baseConditions[0] + dk, baseConditions[
                    1], baseConditions[2]
                if thermalBoundary == 'adiabatic':
                    if reactorType == 'cv':
                        shockTube2 = ct.IdealGasReactor(gas2,
                                                        name='R1',
                                                        energy='on')
                    elif reactorType == 'cp':
                        shockTube2 = ct.IdealGasConstPressureReactor(
                            gas2, name='R1', energy='on')
                    sim2 = ct.ReactorNet([shockTube2])
                if thermalBoundary == 'isothermal':
                    if reactorType == 'cv':
                        shockTube2 = ct.IdealGasReactor(gas2,
                                                        name='R1',
                                                        energy='off')
                    elif reactorType == 'cp':
                        shockTube2 = ct.IdealGasConstPressureReactor(
                            gas2, name='R1', energy='off')
                    sim2 = ct.ReactorNet([shockTube2])

                newTime = 0
                newCounter = 0
                while newTime < finalTime:
                    newTime = sim2.step()
                    state = np.hstack([
                        newTime, shockTube2.thermo.P, shockTube2.mass,
                        shockTube2.volume, shockTube2.T, shockTube2.thermo.X
                    ])
                    timeHistorytest.loc[newCounter] = state
                    newCounter += 1

                newTimeArray = timeHistorytest['time']
                temperatureForMappingPhysicalSensT = timeHistorytest[
                    'temperature'].values
                pressureForMappingPhysicalSensT = timeHistorytest[
                    'pressure'].values

                tempForInterp = timeHistorytest[observables]

                tempForInterplstT = [
                    tempForInterp.ix[:, x].values
                    for x in range(tempForInterp.shape[1])
                ]

                interpolatedData = [
                    np.interp(timeHistory['time'].values, newTimeArray.values,
                              tempForInterplstT[x])
                    for x in range(len(tempForInterplstT))
                ]
                interpolatedTemperatureForMappingPhysicalSensT = [
                    np.interp(timeHistory['time'].values, newTimeArray.values,
                              temperatureForMappingPhysicalSensT)
                ]
                interpolatedPressureForMappingPhysicalSensT = [
                    np.interp(timeHistory['time'].values, newTimeArray.values,
                              pressureForMappingPhysicalSensT)
                ]
                interpolatedData = [
                    pd.DataFrame(interpolatedData[x])
                    for x in range(len(interpolatedData))
                ]
                interpolatedData = pd.concat(interpolatedData,
                                             axis=1,
                                             ignore_index=True)

                concentrationOfAbsorbanceObservablesForSensT = interpolatedData
                concentrationOfAbsorbanceObservablesForSensT.columns = observables
                concentrationOfAbsorbanceObservablesForSensT = [
                    concentrationOfAbsorbanceObservablesForSensT
                ]

                tempT = interpolatedData.applymap(np.log)
                tempT.columns = observables
                tempT = (originalPsens.subtract(tempT)) / np.log(dk)
                tempTlst = [tempT.ix[:, idx] for idx in range(tempT.shape[1])]

            if physical_params[numOfPhyParams] == 'P':
                gas3 = ct.Solution(ctiFile)
                gas3.TPX = baseConditions[
                    0], baseConditions[1] + dk, baseConditions[2]
                if thermalBoundary == 'adiabatic':
                    if reactorType == 'cv':
                        shockTube3 = ct.IdealGasReactor(gas3,
                                                        name='R1',
                                                        energy='on')
                    elif reactorType == 'cp':
                        shockTube3 = ct.IdealGasConstPressureReactor(
                            gas3, name='R1', energy='on')
                    sim3 = ct.ReactorNet([shockTube3])
                if thermalBoundary == 'isothermal':
                    if reactorType == 'cv':
                        shockTube3 = ct.IdealGasReactor(gas3,
                                                        name='R1',
                                                        energy='off')
                    elif reactorType == 'cp':
                        shockTube3 = ct.IdealGasConstPressureReactor(
                            gas3, name='R1', energy='off')
                    sim3 = ct.ReactorNet([shockTube3])

                newTime2 = 0
                newCounter2 = 0
                while newTime2 < finalTime:
                    newTime2 = sim3.step()
                    state = np.hstack([
                        newTime2, shockTube3.thermo.P, shockTube3.mass,
                        shockTube3.volume, shockTube3.T, shockTube3.thermo.X
                    ])
                    timeHistorytest2.loc[newCounter2] = state
                    newCounter2 += 1

                newTimeArray2 = timeHistorytest2['time']
                temperatureForMappingPhysicalSensP = timeHistorytest2[
                    'temperature'].values
                pressureForMappingPhysicalSensP = timeHistorytest2[
                    'pressure'].values

                tempForInterp = timeHistorytest2[observables]
                tempForInterplstP = [
                    tempForInterp.ix[:, x].values
                    for x in range(tempForInterp.shape[1])
                ]

                interpolatedData2 = [
                    np.interp(timeHistory['time'].values, newTimeArray2.values,
                              tempForInterplstP[x])
                    for x in range(len(tempForInterplstP))
                ]
                interpolatedTemperatureForMappingPhysicalSensP = [
                    np.interp(timeHistory['time'].values, newTimeArray2.values,
                              temperatureForMappingPhysicalSensP)
                ]

                interpolatedPressureForMappingPhysicalSensP = [
                    np.interp(timeHistory['time'].values, newTimeArray2.values,
                              pressureForMappingPhysicalSensP)
                ]
                interpolatedData2 = [
                    pd.DataFrame(interpolatedData2[x])
                    for x in range(len(interpolatedData2))
                ]
                interpolatedData2 = pd.concat(interpolatedData2,
                                              axis=1,
                                              ignore_index=True)

                concentrationOfAbsorbanceObservablesForSensP = interpolatedData2
                concentrationOfAbsorbanceObservablesForSensP.columns = observables
                concentrationOfAbsorbanceObservablesForSensP = [
                    concentrationOfAbsorbanceObservablesForSensP
                ]

                tempP = interpolatedData2.applymap(np.log)
                tempP.columns = observables
                tempP = (originalPsens.subtract(tempP)) / np.log(dk)
                tempPlst = [tempP.ix[:, idx] for idx in range(tempP.shape[1])]

            if physical_params[numOfPhyParams] == 'X':
                for simulationNumber, speciesName in enumerate(speciesNames):

                    newConditions = originalConditions
                    gas4 = ct.Solution(ctiFile)
                    originalValue = conditions[speciesName]
                    newValue = originalValue + dk
                    newConditions.update({speciesName: newValue})
                    gas4.TPX = baseConditions[0], baseConditions[
                        1], newConditions

                    if thermalBoundary == 'adiabatic':
                        if reactorType == 'cv':
                            shockTube4 = ct.IdealGasReactor(gas4,
                                                            name='R1',
                                                            energy='on')
                        elif reactorType == 'cp':
                            shockTube4 = ct.IdealGasConstPressureReactor(
                                gas4, name='R1', energy='on')
                        sim4 = ct.ReactorNet([shockTube4])
                    if thermalBoundary == 'isothermal':
                        if reactorType == 'cv':
                            shockTube4 = ct.IdealGasReactor(gas4,
                                                            name='R1',
                                                            energy='off')
                        elif reactorType == 'cp':
                            shockTube4 = ct.IdealGasConstPressureReactor(
                                gas4, name='R1', energy='off')
                        sim4 = ct.ReactorNet([shockTube4])

                    newTime3 = 0
                    newCounter3 = 0
                    while newTime3 < finalTime:
                        newTime3 = sim4.step()
                        state = np.hstack([
                            newTime3, shockTube4.thermo.P, shockTube4.mass,
                            shockTube4.volume, shockTube4.T,
                            shockTube4.thermo.X
                        ])

                        timeHistorytest4[simulationNumber].loc[
                            newCounter3] = state
                        newCounter3 += 1

                    newConditions.update({speciesName: originalValue})

                newTimeArrays3 = [
                    timeHistorytest4[simulationNumber]['time']
                    for simulationNumber in range(len(timeHistorytest4))
                ]
                temperatureForMappingPhysicalSensX = [
                    timeHistorytest4[simulationNumber]['temperature']
                    for simulationNumber in range(len(timeHistorytest4))
                ]
                pressureForMappingPhysicalSensX = [
                    timeHistorytest4[simulationNumber]['pressure']
                    for simulationNumber in range(len(timeHistorytest4))
                ]
                tempForInterps = [
                    timeHistorytest4[simulationNumber][observables]
                    for simulationNumber in range(len(timeHistorytest4))
                ]

                tempForInterplstXs = [[] for x in range(len(timeHistorytest4))]
                for simulationNumber in range(len(timeHistorytest4)):
                    for x in range(tempForInterps[simulationNumber].shape[1]):
                        tempForInterplstXs[simulationNumber].append(
                            tempForInterps[simulationNumber].ix[:, x].values)

                interpolatedData3 = [[] for x in range(len(timeHistorytest4))]
                interpolatedTemperatureForMappingPhysicalSensX = []
                interpolatedPressureForMappingPhysicalSensX = []

                for simulationNumber in range(len(timeHistorytest4)):
                    for x in range(tempForInterps[simulationNumber].shape[1]):
                        interpolatedData3[simulationNumber].append(
                            np.interp(timeHistory['time'].values,
                                      newTimeArrays3[simulationNumber].values,
                                      tempForInterplstXs[simulationNumber][x]))
                for simulationNumber in range(len(timeHistorytest4)):
                    interpolatedTemperatureForMappingPhysicalSensX.append(
                        np.interp(
                            timeHistory['time'].values,
                            newTimeArrays3[simulationNumber].values,
                            temperatureForMappingPhysicalSensX[
                                simulationNumber]))

                for simulationNumber in range(len(timeHistorytest4)):
                    interpolatedPressureForMappingPhysicalSensX.append(
                        np.interp(
                            timeHistory['time'].values,
                            newTimeArrays3[simulationNumber].values,
                            pressureForMappingPhysicalSensX[simulationNumber]))

                interpolatedDataFrames = [[]
                                          for x in range(len(timeHistorytest4))
                                          ]

                #print(interpolatedData3)
                for simulationNumber in range(len(timeHistorytest4)):
                    for x in range(tempForInterps[simulationNumber].shape[1]):
                        interpolatedDataFrames[simulationNumber].append(
                            pd.DataFrame(
                                interpolatedData3[simulationNumber][x]))

                interpolatedDataFrames = [
                    pd.concat(interpolatedDataFrames[simulationNumber],
                              axis=1,
                              ignore_index=True)
                    for simulationNumber in range(len(timeHistorytest4))
                ]
                concentrationOfAbsorbanceObservablesForSensX = interpolatedDataFrames

                for simulationNumber in range(len(timeHistorytest4)):
                    concentrationOfAbsorbanceObservablesForSensX[
                        simulationNumber].columns = observables

                interpolatedDataFrames = [
                    interpolatedDataFrames[simulationNumber].applymap(np.log)
                    for simulationNumber in range(len(timeHistorytest4))
                ]
                for simulationNumber in range(len(timeHistorytest4)):
                    interpolatedDataFrames[
                        simulationNumber].columns = observables
                interpolatedDataFrames = [
                    (originalPsens.subtract(
                        interpolatedDataFrames[simulationNumber])) / np.log(dk)
                    for simulationNumber in range(len(timeHistorytest4))
                ]

                tempXlst = [[] for x in range(len(timeHistorytest4))]
                for simulationNumber in range(len(timeHistorytest4)):
                    for x in range(
                            interpolatedDataFrames[simulationNumber].shape[1]):
                        tempXlst[simulationNumber].append(
                            interpolatedDataFrames[simulationNumber].ix[:, x])

                tempXlsts = [[] for x in range(len(observables))]

                for lengthOfList in range(len(observables)):
                    for dfInList in range(len(timeHistorytest4)):
                        tempXlsts[lengthOfList].append(
                            tempXlst[dfInList][lengthOfList])

                tempXlsts = [
                    pd.concat(tempXlsts[simulationNumber],
                              axis=1,
                              ignore_index=True)
                    for simulationNumber in range(len(tempXlsts))
                ]

    if physical_sens == 1 and bool(observables):
        speciesNames.append(addBackin)
        if 'T' in physical_params and 'P' in physical_params and 'X' in physical_params:
            t = [tempTlst, tempPlst, tempXlsts]
            psensIndex = [
                timeHistory['time'].as_matrix(),
                ['T', 'P'] + physicalParamsSpecies, observables
            ]
            psensdfs = [
                pd.concat([t[0][x], t[1][x], t[2][x]],
                          ignore_index=True,
                          axis=1) for x in range(len(tempXlsts))
            ]
            numpyMatrixspsens = [
                psensdfs[dataframe].as_matrix()
                for dataframe in range(len(psensdfs))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensT +
                interpolatedTemperatureForMappingPhysicalSensP +
                interpolatedTemperatureForMappingPhysicalSensX
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensT +
                interpolatedPressureForMappingPhysicalSensP +
                interpolatedPressureForMappingPhysicalSensX
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensT +
                concentrationOfAbsorbanceObservablesForSensP +
                concentrationOfAbsorbanceObservablesForSensX
            ]

            pS = np.dstack(numpyMatrixspsens)
#
        elif 'T' in physical_params and 'P' in physical_params:
            t = [tempTlst, tempPlst]
            psensIndex = [
                timeHistory['time'].as_matrix(), ['T', 'P'], observables
            ]
            psensdfs = [
                pd.concat([t[0][x], t[1][x]], ignore_index=True, axis=1)
                for x in range(len(tempTlst))
            ]
            numpyMatrixspsens = [
                psensdfs[dataframe].as_matrix()
                for dataframe in range(len(psensdfs))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensT +
                interpolatedTemperatureForMappingPhysicalSensP
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensT +
                interpolatedPressureForMappingPhysicalSensP
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensT +
                concentrationOfAbsorbanceObservablesForSensP
            ]

            pS = np.dstack(numpyMatrixspsens)

        elif 'T' in physical_params and 'X' in physical_params:
            t = [tempTlst, tempXlsts]
            psensIndex = [
                timeHistory['time'].as_matrix(), ['T'] + physicalParamsSpecies,
                observables
            ]
            psensdfs = [
                pd.concat([t[0][x], t[1][x]], ignore_index=True, axis=1)
                for x in range(len(tempTlst))
            ]
            numpyMatrixspsens = [
                psensdfs[dataframe].as_matrix()
                for dataframe in range(len(psensdfs))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensT +
                interpolatedTemperatureForMappingPhysicalSensX
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensT +
                interpolatedPressureForMappingPhysicalSensX
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensT +
                concentrationOfAbsorbanceObservablesForSensX
            ]

            pS = np.dstack(numpyMatrixspsens)
#
        elif 'P' in physical_params and 'X' in physical_params:
            t = [tempPlst, tempXlsts]
            psensIndex = [
                timeHistory['time'].as_matrix(), ['P'] + physicalParamsSpecies,
                observables
            ]
            psensdfs = [
                pd.concat([t[0][x], t[1][x]], ignore_index=True, axis=1)
                for x in range(len(tempPlst))
            ]
            numpyMatrixspsens = [
                psensdfs[dataframe].as_matrix()
                for dataframe in range(len(psensdfs))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensP +
                interpolatedTemperatureForMappingPhysicalSensX
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensP +
                interpolatedPressureForMappingPhysicalSensX
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensP +
                concentrationOfAbsorbanceObservablesForSensX
            ]

            pS = np.dstack(numpyMatrixspsens)

        elif 'T' in physical_params:
            t = [tempTlst]
            psensIndex = [timeHistory['time'].as_matrix(), ['T'], observables]
            numpyMatrixspsens = [
                tempTlst[dataframe].as_matrix()
                for dataframe in range(len(tempTlst))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensT
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensT
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensT
            ]

            pS = np.dstack(numpyMatrixspsens)

        elif 'P' in physical_params:
            t = [tempPlst]
            psensIndex = [timeHistory['time'].as_matrix(), ['P'], observables]
            numpyMatrixspsens = [
                tempPlst[dataframe].as_matrix()
                for dataframe in range(len(tempPlst))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensP
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensP
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensP
            ]

            pS = np.dstack(numpyMatrixspsens)

        elif 'X' in physical_params:
            t = [tempXlsts]
            psensIndex = [
                timeHistory['time'].as_matrix(), [physicalParamsSpecies],
                observables
            ]
            numpyMatrixspsens = [
                tempXlsts[dataframe].as_matrix()
                for dataframe in range(len(tempXlsts))
            ]
            interpolatedTemperatureForMappingPhysicalSens = [
                interpolatedTemperatureForMappingPhysicalSensX
            ]
            interpolatedPressureForMappingPhysicalSens = [
                interpolatedPressureForMappingPhysicalSensX
            ]
            concentrationOfAbsorbanceObservablesForSens = [
                concentrationOfAbsorbanceObservablesForSensX
            ]

            pS = np.dstack(numpyMatrixspsens)

    if kinetic_sens == 1 and bool(observables) and physical_sens == 0:
        results = simulations.model_data('Shock-Tube',
                                         kinetic_sens=S,
                                         Solution=timeHistory,
                                         Index=ksensIndex)
        results.assign_ksens_mappings(Sa, Sb, Se)
        return results

    if kinetic_sens == 0 and bool(physical_params) and physical_sens == 1:
        results = simulations.model_data('Shock-Tube',
                                         physical_sens=pS,
                                         Solution=timeHistory,
                                         pIndex=psensIndex)
        results.add_interpolated_temps_for_physical_sens(
            interpolatedTemperatureForMappingPhysicalSens)
        results.add_interpolated_pressure_for_physical_sens(
            interpolatedPressureForMappingPhysicalSens)
        results.add_interpolated_concentration_for_physical_sens(
            concentrationOfAbsorbanceObservablesForSens)
        return results

    if physical_sens == 1 and bool(observables) and kinetic_sens == 1:
        results = simulations.model_data('Shock-Tube',
                                         kinetic_sens=S,
                                         physical_sens=pS,
                                         Solution=timeHistory,
                                         Index=ksensIndex,
                                         pIndex=psensIndex)
        results.assign_ksens_mappings(Sa, Sb, Se)
        results.add_interpolated_temps_for_physical_sens(
            interpolatedTemperatureForMappingPhysicalSens)
        results.add_interpolated_pressure_for_physical_sens(
            interpolatedPressureForMappingPhysicalSens)
        results.add_interpolated_concentration_for_physical_sens(
            concentrationOfAbsorbanceObservablesForSens)
        return results
#
    if physical_sens == 0 and kinetic_sens == 0:
        results = simulations.model_data('Shock-Tube', Solution=timeHistory)
        return results
Пример #18
0
    def simulate(self):
        """
        Run all the conditions as a cantera simulation.
        Returns the data as a list of tuples containing: (time, [list of temperature, pressure, and species data]) 
            for each reactor condition
        """
        # Get all the cantera names for the species
        speciesNamesList = [
            getSpeciesIdentifier(species) for species in self.speciesList
        ]
        inertIndexList = [
            self.speciesList.index(species) for species in self.speciesList
            if species.index == -1
        ]

        allData = []
        for condition in self.conditions:

            # First translate the molFrac from species objects to species names
            newMolFrac = {}
            for key, value in condition.molFrac.iteritems():
                newkey = getSpeciesIdentifier(key)
                newMolFrac[newkey] = value

            # Set Cantera simulation conditions
            if condition.V0 is None:
                self.model.TPX = condition.T0.value_si, condition.P0.value_si, newMolFrac
            elif condition.P0 is None:
                self.model.TDX = condition.T0.value_si, 1.0 / condition.V0.value_si, newMolFrac
            else:
                raise Exception(
                    "Cantera conditions in which T0 and P0 or T0 and V0 are not the specified state variables are not yet implemented."
                )

            # Choose reactor
            if condition.reactorType == 'IdealGasReactor':
                canteraReactor = ct.IdealGasReactor(self.model)
            elif condition.reactorType == 'IdealGasConstPressureReactor':
                canteraReactor = ct.IdealGasConstPressureReactor(
                    contents=self.model)
            elif condition.reactorType == 'IdealGasConstPressureTemperatureReactor':
                canteraReactor = ct.IdealGasConstPressureReactor(
                    contents=self.model, energy='off')
            else:
                raise Exception(
                    'Other types of reactor conditions are currently not supported'
                )

            # Run this individual condition as a simulation
            canteraSimulation = ct.ReactorNet([canteraReactor])

            numCtReactions = len(self.model.reactions())
            if self.sensitiveSpecies:
                if ct.__version__ == '2.2.1':
                    print 'Warning: Cantera version 2.2.1 may not support sensitivity analysis unless SUNDIALS was used during compilation.'
                    print 'Warning: Upgrade to newer of Cantera in anaconda using the command "conda update -c rmg cantera"'
                # Add all the reactions as part of the analysis
                for i in range(numCtReactions):
                    canteraReactor.add_sensitivity_reaction(i)
                # Set the tolerances for the sensitivity coefficients
                canteraSimulation.rtol_sensitivity = 1e-4
                canteraSimulation.atol_sensitivity = 1e-6

            # Initialize the variables to be saved
            times = []
            temperature = []
            pressure = []
            speciesData = []
            sensitivityData = []

            # Begin integration
            time = 0.0
            # Run the simulation over 100 time points
            while canteraSimulation.time < condition.reactionTime.value_si:

                # Advance the state of the reactor network in time from the current time to time t [s], taking as many integrator timesteps as necessary.
                canteraSimulation.step(condition.reactionTime.value_si)
                times.append(canteraSimulation.time)
                temperature.append(canteraReactor.T)
                pressure.append(canteraReactor.thermo.P)
                speciesData.append(canteraReactor.thermo[speciesNamesList].X)

                if self.sensitiveSpecies:
                    # Cantera returns mass-based sensitivities rather than molar concentration or mole fraction based sensitivities.
                    # The equation for converting between them is:
                    #
                    # d ln xi = d ln wi - sum_(species i) (dln wi) (xi)
                    #
                    # where xi is the mole fraction of species i and wi is the mass fraction of species i

                    massFracSensitivityArray = canteraSimulation.sensitivities(
                    )
                    if condition.reactorType == 'IdealGasReactor':
                        # Row 0: mass, Row 1: volume, Row 2: internal energy or temperature, Row 3+: mass fractions of species
                        massFracSensitivityArray = massFracSensitivityArray[
                            3:, :]
                    elif condition.reactorType == 'IdealGasConstPressureReactor' or condition.reactorType == 'IdealGasConstPressureTemperatureReactor':
                        # Row 0: mass, Row 1: enthalpy or temperature, Row 2+: mass fractions of the species
                        massFracSensitivityArray = massFracSensitivityArray[
                            2:, :]
                    else:
                        raise Exception(
                            'Other types of reactor conditions are currently not supported'
                        )

                    for i in range(len(massFracSensitivityArray)):
                        massFracSensitivityArray[i] *= speciesData[-1][i]

                    sensitivityArray = np.zeros(
                        len(self.sensitiveSpecies) *
                        len(self.model.reactions()))
                    for index, species in enumerate(self.sensitiveSpecies):
                        for j in range(numCtReactions):
                            sensitivityArray[
                                numCtReactions * index +
                                j] = canteraSimulation.sensitivity(
                                    species.toChemkin(), j)

                            for i in range(len(massFracSensitivityArray)):
                                if i not in inertIndexList:
                                    # massFracSensitivity for inerts are returned as nan in Cantera, so we must not include them here
                                    sensitivityArray[
                                        numCtReactions * index +
                                        j] -= massFracSensitivityArray[i][j]
                    sensitivityData.append(sensitivityArray)

            # Convert speciesData and sensitivityData to a numpy array
            speciesData = np.array(speciesData)
            sensitivityData = np.array(sensitivityData)

            # Resave data into generic data objects
            time = GenericData(label='Time', data=times, units='s')
            temperature = GenericData(label='Temperature',
                                      data=temperature,
                                      units='K')
            pressure = GenericData(label='Pressure', data=pressure, units='Pa')
            conditionData = []
            conditionData.append(temperature)
            conditionData.append(pressure)

            for index, species in enumerate(self.speciesList):
                # Create generic data object that saves the species object into the species object.  To allow easier manipulate later.
                speciesGenericData = GenericData(label=speciesNamesList[index],
                                                 species=species,
                                                 data=speciesData[:, index],
                                                 index=species.index)
                conditionData.append(speciesGenericData)

            reactionSensitivityData = []
            for index, species in enumerate(self.sensitiveSpecies):
                for j in range(numCtReactions):
                    reactionSensitivityGenericData = GenericData(
                        label='dln[{0}]/dln[k{1}]: {2}'.format(
                            species.toChemkin(), j + 1,
                            self.model.reactions()[j]),
                        species=species,
                        reaction=self.model.reactions()[j],
                        data=sensitivityData[:, numCtReactions * index + j],
                        index=j + 1,
                    )
                    reactionSensitivityData.append(
                        reactionSensitivityGenericData)

            allData.append((time, conditionData, reactionSensitivityData))

        return allData
Пример #19
0
# %%
import cantera as ct
# %%

gas = ct.Solution('h2_Burke_n2.cti')

r = ct.IdealGasConstPressureReactor(gas)
# %%

dt = 1e-5

t = 0.

# %%
r.T
t += dt
sim = ct.ReactorNet([r])
sim.advance(t)
r.T
# %%

gas.TPX = 300, 101325, {'H': 1.}
r.syncState()
r.T
# %%
sim.reinitialize()
# %%
t += dt
sim.advance(t)
r.T
# %%
Пример #20
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.IdealGasConstPressureReactor(gri3, name='R1')
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):
    r.add_sensitivity_reaction(i)

# set the tolerances for the solution and for the sensitivity coefficients
sim.rtol = 1.0e-6
sim.atol = 1.0e-15
sim.rtol_sensitivity = 1.0e-6
sim.atol_sensitivity = 1.0e-6

n_times = 400
tim = np.zeros(n_times)
data = np.zeros((n_times, 6))
Пример #21
0
import itertools
import cantera as ct
import pandas as pd
import numpy as np
gas = ct.Solution('MSI/data/test_data/FFCM1.cti')
gas.TPX = 1880, 1.74*101325, {'H2O':.013,'O2':.0099,'H':.0000007,'Ar':0.9770993}
observables = ['OH','H2O']
shockTube = ct.IdealGasConstPressureReactor(gas,name = 'R1',energy= 'on')
dfs = [pd.DataFrame() for x in range(len(observables))]
tempArray = [np.zeros(gas.n_reactions) for x in range(len(observables))]
kineticSens =1

sim=ct.ReactorNet([shockTube]) 
for i in range(gas.n_reactions):
    shockTube.add_sensitivity_reaction(i)           
t = 0
counter = 0
while t < .1:
    t = sim.step()
    if kineticSens == 1:
        counter_1 = 0
        for observable,reaction in itertools.product(observables, range(gas.n_reactions)):
            tempArray[observables.index(observable)][reaction] = sim.sensitivity(observable, reaction)                    
            counter_1 +=1
            if(counter_1 % gas.n_reactions == 0):
                dfs[observables.index(observable)] = dfs[observables.index(observable)].append(((pd.DataFrame(tempArray[observables.index(observable)])).transpose()),ignore_index=True)
                
    counter+=1
if kineticSens == 1:
    numpyMatrixsksens = [dfs[dataframe].as_matrix() for dataframe in range(len(dfs))]
    S = np.dstack(numpyMatrixsksens) 
Пример #22
0
    def setup_case(self):
        """
        Sets up the case to be run. Initializes the ``ThermoPhase``,
        ``Reactor``, and ``ReactorNet`` according to the values from
        the input file.
        """

        self.gas = ct.Solution(self.mech_filename)

        initial_temp = self.keywords['temperature']
        # The initial pressure in Cantera is expected in Pa; in SENKIN
        # it is expected in atm, so convert
        initial_pres = self.keywords['pressure'] * ct.one_atm
        # If the equivalence ratio has been specified, send the
        # keywords for conversion.
        if 'eqRatio' in self.keywords:
            reactants = utils.equivalence_ratio(
                self.gas,
                self.keywords['eqRatio'],
                self.keywords['fuel'],
                self.keywords['oxidizer'],
                self.keywords['completeProducts'],
                self.keywords['additionalSpecies'],
            )
        else:
            # The reactants are stored in the ``keywords`` dictionary
            # as a list of strings, so they need to be joined.
            reactants = ','.join(self.keywords['reactants'])

        self.gas.TPX = initial_temp, initial_pres, reactants

        # Create a non-interacting ``Reservoir`` to be on the other
        # side of the ``Wall``.
        env = ct.Reservoir(ct.Solution('air.xml'))
        # Set the ``temp_func`` to ``None`` as default; it will be set
        # later if needed.
        self.temp_func = None
        # All of the reactors are ``IdealGas`` Reactors. Set a ``Wall``
        # for every case so that later code can be more generic. If the
        # velocity is set to zero, the ``Wall`` won't affect anything.
        # We have to set the ``n_vars`` here because until the first
        # time step, ``ReactorNet.n_vars`` is zero, but we need the
        # ``n_vars`` before the first time step.
        if self.keywords['problemType'] == 1:
            self.reac = ct.IdealGasReactor(self.gas)
            # Number of solution variables is number of species + mass,
            # volume, temperature
            self.n_vars = self.reac.kinetics.n_species + 3
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
        elif self.keywords['problemType'] == 2:
            self.reac = ct.IdealGasConstPressureReactor(self.gas)
            # Number of solution variables is number of species + mass,
            # temperature
            self.n_vars = self.reac.kinetics.n_species + 2
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
        elif self.keywords['problemType'] == 3:
            self.reac = ct.IdealGasReactor(self.gas)
            # Number of solution variables is number of species + mass,
            # volume, temperature
            self.n_vars = self.reac.kinetics.n_species + 3
            self.wall = ct.Wall(self.reac,
                                env,
                                A=1.0,
                                velocity=VolumeProfile(self.keywords))
        elif self.keywords['problemType'] == 4:
            self.reac = ct.IdealGasConstPressureReactor(self.gas, energy='off')
            # Number of solution variables is number of species + mass,
            # temperature
            self.n_vars = self.reac.kinetics.n_species + 2
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
        elif self.keywords['problemType'] == 5:
            self.reac = ct.IdealGasReactor(self.gas, energy='off')
            # Number of solution variables is number of species + mass,
            # volume, temperature
            self.n_vars = self.reac.kinetics.n_species + 3
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
        elif self.keywords['problemType'] == 6:
            from user_routines import VolumeFunctionTime
            self.reac = ct.IdealGasReactor(self.gas)
            # Number of solution variables is number of species + mass,
            # volume, temperature
            self.n_vars = self.reac.kinetics.n_species + 3
            self.wall = ct.Wall(self.reac,
                                env,
                                A=1.0,
                                velocity=VolumeFunctionTime())
        elif self.keywords['problemType'] == 7:
            from user_routines import TemperatureFunctionTime
            self.reac = ct.IdealGasConstPressureReactor(self.gas, energy='off')
            # Number of solution variables is number of species + mass,
            # temperature
            self.n_vars = self.reac.kinetics.n_species + 2
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
            self.temp_func = ct.Func1(TemperatureFunctionTime())
        elif self.keywords['problemType'] == 8:
            self.reac = ct.IdealGasConstPressureReactor(self.gas, energy='off')
            # Number of solution variables is number of species + mass,
            # temperature
            self.n_vars = self.reac.kinetics.n_species + 2
            self.wall = ct.Wall(self.reac, env, A=1.0, velocity=0)
            self.temp_func = ct.Func1(TemperatureProfile(self.keywords))
        elif self.keywords['problemType'] == 9:
            self.reac = ct.IdealGasReactor(self.gas)
            # Number of solution variables is number of species + mass,
            # volume, temperature
            self.n_vars = self.reac.kinetics.n_species + 3
            self.wall = ct.Wall(env,
                                self.reac,
                                A=1.0,
                                velocity=ICEngineProfile(self.keywords))

        if 'reactorVolume' in self.keywords:
            self.reac.volume = self.keywords['reactorVolume']

        # Create the Reactor Network.
        self.netw = ct.ReactorNet([self.reac])

        if 'sensitivity' in self.keywords:
            self.sensitivity = True
            # There is no automatic way to calculate the sensitivity of
            # all of the reactions, so do it manually.
            for i in range(self.reac.kinetics.n_reactions):
                self.reac.add_sensitivity_reaction(i)
            # If no tolerances for the sensitivity are specified, set
            # to the SENKIN defaults.
            if 'sensAbsTol' in self.keywords:
                self.netw.atol_sensitivity = self.keywords['sensAbsTol']
            else:
                self.netw.atol_sensitivity = 1.0E-06
            if 'sensRelTol' in self.keywords:
                self.netw.rtol_sensitivity = self.keywords['sensRelTol']
            else:
                self.netw.rtol_sensitivity = 1.0E-04
        else:
            self.sensitivity = False

        # If no solution tolerances are specified, set to the default
        # SENKIN values.
        if 'abstol' in self.keywords:
            self.netw.atol = self.keywords['abstol']
        else:
            self.netw.atol = 1.0E-20

        if 'reltol' in self.keywords:
            self.netw.rtol = self.keywords['reltol']
        else:
            self.netw.rtol = 1.0E-08

        if 'tempLimit' in self.keywords:
            self.temp_limit = self.keywords['tempLimit']
        else:
            # tempThresh is set in the parser even if it is not present
            # in the input file
            self.temp_limit = (self.keywords['tempThresh'] +
                               self.keywords['temperature'])

        self.tend = self.keywords['endTime']

        # Set the maximum time step the solver can take. If a value is
        # not specified in the input file, default to 0.001*self.tend.
        # Set the time steps for saving to the binary file and writing
        # to the screen. If the time step for printing to the screen is
        # not set, default to printing 100 times.
        print_time_int = self.keywords.get('prntTimeInt')
        save_time_int = self.keywords.get('saveTimeInt')
        max_time_int = self.keywords.get('maxTimeStep')

        time_ints = [
            value for value in [print_time_int, save_time_int, max_time_int]
            if value is not None
        ]

        if time_ints:
            self.netw.set_max_time_step(min(time_ints))
        else:
            self.netw.set_max_time_step(self.tend / 100)

        if print_time_int is not None:
            self.print_time_step = print_time_int
        else:
            self.print_time_step = self.tend / 100

        self.print_time = self.print_time_step

        self.save_time_step = save_time_int

        if self.save_time_step is not None:
            self.save_time = self.save_time_step

        # Store the species names in a slightly shorter variable name
        self.species_names = self.reac.thermo.species_names

        # Initialize the ignition time, in case the end time is reached
        # before ignition occurs
        self.ignition_time = None
Пример #23
0
import sys
import numpy as np

import cantera as ct
import matplotlib.pyplot as plt
import re

gas = ct.Solution('gri30.cti')
temp = 1200.0
pres = ct.one_atm

gas.TPX = temp, pres, 'CH4:1, O2:2'
r = ct.IdealGasConstPressureReactor(gas, name='R1')
sim = ct.ReactorNet([r])

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

# set the tolerances for the solution and for the sensitivity coefficients
sim.rtol = 1.0e-6
sim.atol = 1.0e-15
sim.rtol_sensitivity = 1.0e-6
sim.atol_sensitivity = 1.0e-6

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

sCH4 = []
sO2 = []
sCO2 = []
Пример #24
0
def run_simulation(solution,  times, conditions=None,
                      condition_type = 'adiabatic-constant-volume',
                      output_species = True,
                      output_reactions = True,
                      output_directional_reactions = False,
                      output_rop_roc = False,
                      atol = 1e-15,
                      rtol = 1e-9,
                      temperature_values=None):
    """
    This method iterates through the cantera solution object and outputs information
    about the simulation as a pandas.DataFrame object.
    
    This method returns a dictionary with the reaction conditions data, species data,
    net reaction data, forward/reverse reaction data, and the rate of production 
    and consumption (or `None` if a variable not specified). 
    
    `solution` = Cantera.Solution object
    `conditions` = tuple of temperature, pressure, and mole fraction initial 
                species (will be deprecated. Set parameters before running)
    `times` = an iterable of times which you would like to store information in
    `condition_type` = string describing the run type
    `output_species` = output a DataFrame of species' concentrations
    `output_reactions` = output a DataFrame of net reaction rates
    `output_directional_reactions` = output a DataFrame of directional reaction rates
    `output_rop_roc` = output a DataFrame of species rates of consumption & production

    condition_types supported
    #########################
    'adiabatic-constant-volume' - assumes no heat transfer and no volume change
    'constant-temperature-and-pressure' - no solving energy equation or changing
                            rate constants
    'constant-temperature-and-volume' - no solving energy equation but allows
                            for pressure to change with reactions
    'specified-temperature-constant-volume' - the temperature profile specified
                            `temperature_values`, which corresponds to the
                            input `times`, alters the temperature right before
                            the next time step is taken. Constant volume is assumed.
    """
    if conditions is not None:
        solution.TPX = conditions
    if condition_type == 'adiabatic-constant-volume':
        reactor = ct.IdealGasReactor(solution)
    elif condition_type == 'constant-temperature-and-pressure':
        reactor = ct.IdealGasConstPressureReactor(solution, energy='off')
    elif condition_type == 'constant-temperature-and-volume':
        reactor = ct.IdealGasReactor(solution, energy='off')
    elif condition_type == 'specified-temperature-constant-volume':
        reactor = ct.IdealGasReactor(solution, energy='off')
        if temperature_values is None:
            raise AttributeError('Must specify temperature with `temperature_values` parameter')
        elif len(times) != len(temperature_values):
            raise AttributeError('`times` (len {0}) and `temperature_values` (len {1}) must have the same length.'.format(len(times),len(temperature_values)))
    else:
        supported_types = ['adiabatic-constant-volume','constant-temperature-and-pressure',
                           'constant-temperature-and-volume','specified-temperature-constant-volume']
        raise NotImplementedError('only {0} are supported. {1} input'.format(supported_types, condition_type))
    simulator = ct.ReactorNet([reactor])
    solution = reactor.kinetics
    simulator.atol = atol
    simulator.rtol = rtol
    # setup data storage
    outputs = {}
    outputs['conditions'] = pd.DataFrame()
    if output_species:
        outputs['species'] = pd.DataFrame()
    if output_reactions:
        outputs['net_reactions'] = pd.DataFrame()
    if output_directional_reactions:
        outputs['directional_reactions'] = pd.DataFrame()
    if output_rop_roc:
        outputs['rop'] = pd.DataFrame()

    for time_index, time in enumerate(times):
        if condition_type == 'specified-temperature-constant-volume':
            solution.TD = temperature_values[time_index], solution.density
            reactor = ct.IdealGasReactor(solution, energy='off')
            simulator = ct.ReactorNet([reactor])
            solution = reactor.kinetics
            simulator.atol = atol
            simulator.rtol = rtol
            if time_index > 0:
                simulator.set_initial_time(times[time_index-1])
        simulator.advance(time)
        # save data
        outputs['conditions'] = outputs['conditions'].append(
                                get_conditions_series(simulator,reactor,solution),
                                ignore_index = True)
        if output_species:
            outputs['species'] = outputs['species'].append(
                                get_species_series(solution),
                                ignore_index = True)
        if output_reactions:
            outputs['net_reactions'] = outputs['net_reactions'].append(
                                get_reaction_series(solution),
                                ignore_index = True)
        if output_directional_reactions:
            outputs['directional_reactions'] = outputs['directional_reactions'].append(
                                get_forward_and_reverse_reactions_series(solution),
                                ignore_index = True)
        if output_rop_roc:
            outputs['rop'] = outputs['rop'].append(
                                get_rop_and_roc_series(solution),
                                ignore_index = True)

    # set indexes as time
    time_vector = outputs['conditions']['time (s)']
    for output in outputs.values():
        output.set_index(time_vector,inplace=True)

    return outputs
Пример #25
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
Пример #26
0
def execute():
    #==============================================================================
#     set up the cantera gases and reactors
#==============================================================================
    drop = droplet(50e-6, 'A2', 300, 1) #drop is defined only to use the drop properties
    #environment air
    gas_env = ct.Solution('a2.cti')
    gas_env.TPX = 300, ct.one_atm, 'O2:29,N2:71'

    gas_fuel = ct.Solution('a2.cti')
    gas_fuel.TPX = drop.ABP, ct.one_atm, 'POSF10325:1' #gaseous fuel at average boiling temperature

    gas_kernel = ct.Solution('a2.cti')
    gas_kernel.TPX = 4000, ct.one_atm, 'O2:29,N2:71'
    gas_kernel.equilibrate('HP')
    
    res_air = ct.Reservoir(gas_env)
    res_fuel = ct.Reservoir(gas_fuel)
    kernel = ct.IdealGasConstPressureReactor(gas_kernel)
    kernel.volume = 2.4e-8 #m^3

    mfc1 = ct.MassFlowController(res_air, kernel) #connect air reservoir to kernel
    mfc2 = ct.MassFlowController(res_fuel, kernel) #connect fuel reservoir to kernel

    mfc1.set_mass_flow_rate(6e-5)
    mfc2.set_mass_flow_rate(0)

    w = ct.Wall(kernel, res_fuel)
    w.set_heat_flux(0)
    w.expansion_rate_coeff = 1e8

    net = ct.ReactorNet({kernel})
    net.atol = 1e-10 #absolute tolerance
    net.rtol = 1e-10 #relative tolerance
#==============================================================================
#   endtime, time steps, and data to be stored    
#==============================================================================
    dt = 1e-6 #change time step for advancing the reactor
    endtime = 1000e-6
    mdot_fuel = 1.98e-6 #this number should be calculated based on equivalence ratio, kg/s
    
    droplets = []
    T = []
    time = []
    m = []
    m_dot = []
    q_dot = []
    droplet_count = []
    X_fuel = []
    X_O = []
    X_CO2 = []
    num_d = []
    
#==============================================================================
#     advance reaction
#==============================================================================
    print("Running simulation")
    for i in range(1,int(endtime/dt)):
        print (int(endtime/dt) - i)
        #entrain droplets every 1 microsecond
        droplets.extend(entrainer(400, 5.*mdot_fuel))  
        mdot, qdot = vaporize(gas_kernel.T, droplets, dt)
        
#        print(gas_kernel.T, mdot, qdot, len(droplets))
#        print(str(mdot) + str(qdot) + str(gas_kernel.T)+'  '+str(len(droplets)))
        mfc2.set_mass_flow_rate(mdot)
        w.set_heat_flux(qdot) #heat required to heat up the droplets during that time step
        
        net.advance(i*dt)
        
        num_d.append(len(droplets))
        #storing variables
        T.append(gas_kernel.T)
        time.append(net.time)
        m.append(kernel.mass)
        m_dot.append(mdot)
        q_dot.append(qdot)
        droplet_count.append(len(droplets))
        if gas_kernel.X[0] < 0:
            gas_kernel.X[0] = 0
        X_fuel.append(gas_kernel.X[gas_kernel.species_index("POSF10325")])
        X_O.append(gas_kernel.X[gas_kernel.species_index("O")])
        X_CO2.append(gas_kernel.X[gas_kernel.species_index("CO2")])
        
#==============================================================================
#   plotting important information      
#==============================================================================
    plt.plot([t*1e3 for t in time],T, linewidth=3)
    plt.xlabel('time(ms)', FontSize=15)
    plt.ylabel('Temperature (K)', FontSize=15)
    plt.show()
    
    fig, ax1 = plt.subplots()
    ax2 = ax1.twinx()
    ax1.plot([t*1e3 for t in time], X_fuel, color = 'red', linewidth = 3)
    ax1.set_xlabel('time (ms)', FontSize=15)
    ax1.set_ylabel('X_fuel', color='red', FontSize=15)
#    ax2.plot([t*1e3 for t in time], X_O, color = 'green', linewidth = 3)
    ax2.set_ylabel('X_CO2', color='green', FontSize=15)
    ax2.plot([t*1e3 for t in time], X_CO2, color = 'blue', linewidth = 3)
    plt.show()
    
    fig, ax1 = plt.subplots()
    ax2 = ax1.twinx()
    ax1.plot([t*1e3 for t in time], m_dot, color = 'red', linewidth = 3)
    ax1.set_xlabel('time (ms)', FontSize=15)
    ax1.set_ylabel('m_dot', color='red', FontSize=15)
    ax2.plot([t*1e3 for t in time], q_dot, color = 'green', linewidth = 3)
    ax2.set_ylabel('q_dot', color='green', FontSize=15)
    plt.show()
    
    fig,ax1 = plt.subplots()
    ax1.plot([t*1e3 for t in time], num_d, linewidth=3)
    ax1.set_xlabel('time(ms)', FontSize=15)
    ax1.set_ylabel('#droplets', FontSize=15)
    plt.show()
Пример #27
0
                       fullOutput=False)

    # calculate postshock gas condition
    postshockgas = PostShock_fr(cj_speed, initpress * ct.one_atm, inittemp, q,
                                mech)
    # save and print initial shock temp and pressure
    shockedpress = postshockgas.P / 101325
    shockedtemp = postshockgas.T
    print(f'    PostShock Pressure: {postshockgas.P/101325} atm')
    print(f'    PostShock Temperature: {postshockgas.T} K')

    # Resolution: The PFR will be simulated by 'n_steps' time steps
    n_steps = 3000000

    # create a new reactor
    r1 = ct.IdealGasConstPressureReactor(postshockgas)
    # create a reactor network for performing time integration
    sim1 = ct.ReactorNet([r1])

    # approximate a time step to achieve a similar resolution as in the next method

    dt = 0.25 / n_steps
    det_time = 0
    # define timesteps
    timesteps = (np.arange(n_steps) + 1) * dt
    for t_i in timesteps:
        # perform time integration
        sim1.advance(t_i)
        # store current time
        det_time = t_i
        # compute velocity and transform into space
Пример #28
0
def run_simulation_till_conversion(solution, species, conversion,conditions=None,
                      condition_type = 'adiabatic-constant-volume',
                      output_species = True,
                      output_reactions = True,
                      output_directional_reactions = False,
                      output_rop_roc = False,
                      skip_data = 150,
                      atol = 1e-15,
                      rtol = 1e-9,):
    """
    This method iterates through the cantera solution object and outputs information
    about the simulation as a pandas.DataFrame object.

    This method returns a dictionary with the reaction conditions data, species data,
    net reaction data, forward/reverse reaction data, and the rate of production 
    and consumption (or `None` if a variable not specified) at the specified conversion value.

    `solution` = Cantera.Solution object
    `conditions` = tuple of temperature, pressure, and mole fraction initial 
                species
    `species` = a string of the species label (or list of strings) to be used in conversion calculations
    `conversion` = a float of the fraction conversion to stop the simulation at
    `condition_type` = string describing the run type, currently supports 
                'adiabatic-constant-volume' and 'constant-temperature-and-pressure'
    `output_species` = output a Series of species' concentrations
    `output_reactions` = output a Series of net reaction rates
    `output_directional_reactions` = output a Series of directional reaction rates
    `output_rop_roc` = output a DataFrame of species rates of consumption & production
    `skip_data` = an integer which reduces storing each point of data.
                    storage space scales as 1/`skip_data`
    """
    if conditions is not None:
        solution.TPX = conditions
    if condition_type == 'adiabatic-constant-volume':
        reactor = ct.IdealGasReactor(solution)
    if condition_type == 'constant-temperature-and-pressure':
        reactor = ct.IdealGasConstPressureReactor(solution, energy='off')
    else:
        raise NotImplementedError('only adiabatic constant volume is supported')
    simulator = ct.ReactorNet([reactor])
    solution = reactor.kinetics
    simulator.atol = atol
    simulator.rtol = rtol
    # setup data storage
    outputs = {}
    outputs['conditions'] = pd.DataFrame()
    if output_species:
        outputs['species'] = pd.DataFrame()
    if output_reactions:
        outputs['net_reactions'] = pd.DataFrame()
    if output_directional_reactions:
        outputs['directional_reactions'] = pd.DataFrame()
    if output_rop_roc:
        outputs['rop'] = pd.DataFrame()

    if isinstance(species,str):
        target_species_indexes = [solution.species_index(species)]
    else: # must be a list or tuple
        target_species_indexes = [solution.species_index(s) for s in species]
    starting_concentration = sum([solution.concentrations[target_species_index] for target_species_index in target_species_indexes])

    proper_conversion = False
    new_conversion = 0
    skip_count = 1e8
    while not proper_conversion:
        error_count = 0
        while error_count >= 0:
            try:
                simulator.step()
                error_count = -1
            except:
                error_count += 1
                if error_count > 10:
                    print('Might not be possible to achieve conversion at T={0}, P={1}, with concentrations of {2} obtaining a conversion of {3} at time {4} s.'.format(solution.T,solution.P,zip(solution.species_names,solution.X), new_conversion,simulator.time))
                    raise
        new_conversion = 1-sum([solution.concentrations[target_species_index] for target_species_index in target_species_indexes])/starting_concentration
        if new_conversion > conversion:
            proper_conversion = True
        
        # save data
        if skip_count > skip_data or proper_conversion:
            skip_count = 0
            outputs['conditions'] = outputs['conditions'].append(
                                    get_conditions_series(simulator,reactor,solution),
                                    ignore_index = True)
            if output_species:
                outputs['species'] = outputs['species'].append(
                                    get_species_series(solution),
                                    ignore_index = True)
            if output_reactions:
                outputs['net_reactions'] = outputs['net_reactions'].append(
                                    get_reaction_series(solution),
                                    ignore_index = True)
            if output_directional_reactions:
                outputs['directional_reactions'] = outputs['directional_reactions'].append(
                                    get_forward_and_reverse_reactions_series(solution),
                                    ignore_index = True)
            if output_rop_roc:
                outputs['rop'] = outputs['rop'].append(
                                    get_rop_and_roc_series(solution),
                                    ignore_index = True)
        skip_count += 1

    # set indexes as time
    time_vector = outputs['conditions']['time (s)']
    for output in outputs.values():
        output.set_index(time_vector,inplace=True)
    return outputs
def obj_func(A,states_ref):
    ret = 0.
    states_new,gas2 = states_new_init(A)
    for n in range(100):
        ret += (states_new.X[n,gas2.species_index('H2')] - states_ref.X[n,gas2.species_index('H2')])**2/100
    return ret
#return abs(a-b)




gas = ct.Solution('gri30.xml')
initial_state = 1500, ct.one_atm, 'H2:2,O2:1'
gas.TPX = 1500.0, ct.one_atm, 'H2:2,O2:1'
r = ct.IdealGasConstPressureReactor(gas,energy = 'off')
sim = ct.ReactorNet([r])
time = 0.0
states = ct.SolutionArray(gas, extra=['t'])

#
i = (j for j in range(0,10))
N = (j for j in range(1,11))
#
for n in range(100):
    time += 1.e-5
    sim.advance(time)
    states.append(r.thermo.state, t=time*1e3)
    #print('%10.3e %10.3f %10.3f %14.6e' % (sim.time, r.T,
    #                                       r.thermo.P, r.thermo.u))
Пример #30
0
    def run(self, initialTime: float = -1.0, finalTime: float = -1.0):
        '''
        Run the shock tube simulation
        '''
        if initialTime == -1.0:
            initialTime = self.initialTime
        if finalTime == -1.0:
            finalTime = self.finalTime
        self.timeHistory = None
        self.kineticSensitivities = None  #3D numpy array, columns are reactions with timehistories, depth gives the observable for those histories
        conditions = self.settingShockTubeConditions()
        mechanicalBoundary = conditions[1]
        #same solution for both cp and cv sims
        if mechanicalBoundary == 'constant pressure':
            shockTube = ct.IdealGasConstPressureReactor(
                self.processor.solution, name='R1', energy=conditions[0])
        else:
            shockTube = ct.IdealGasReactor(self.processor.solution,
                                           name='R1',
                                           energy=conditions[0])
        sim = ct.ReactorNet([shockTube])

        columnNames = [
            shockTube.component_name(item) for item in range(shockTube.n_vars)
        ]
        columnNames = ['time'] + ['pressure'] + columnNames
        self.timeHistory = pd.DataFrame(columns=columnNames)

        if self.kineticSens == 1:
            for i in range(self.processor.solution.n_reactions):
                shockTube.add_sensitivity_reaction(i)
            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))
            ]

        t = self.initialTime
        counter = 0
        while t < self.finalTime:
            t = sim.step()
            if mechanicalBoundary == 'constant volume':
                state = np.hstack([
                    t, shockTube.thermo.P, shockTube.mass, shockTube.volume,
                    shockTube.T, shockTube.thermo.X
                ])
            else:
                state = np.hstack([
                    t, shockTube.thermo.P, shockTube.mass, shockTube.T,
                    shockTube.thermo.X
                ])

            self.timeHistory.loc[counter] = state
            if self.kineticSens == 1:
                counter_1 = 0
                for observable, reaction in itertools.product(
                        self.observables,
                        range(self.processor.solution.n_reactions)):
                    tempArray[self.observables.index(
                        observable)][reaction] = sim.sensitivity(
                            observable, reaction)
                    counter_1 += 1
                    if counter_1 % self.processor.solution.n_reactions == 0:
                        dfs[self.observables.index(observable)] = dfs[
                            self.observables.index(observable)].append(
                                ((pd.DataFrame(
                                    tempArray[self.observables.index(
                                        observable)])).transpose()),
                                ignore_index=True)
            counter += 1
        if self.timeHistories != None:
            self.timeHistories.append(self.timeHistory)

        if self.kineticSens == 1:
            numpyMatrixsksens = [
                dfs[dataframe].values for dataframe in range(len(dfs))
            ]
            self.kineticSensitivities = np.dstack(numpyMatrixsksens)
            return self.timeHistory, self.kineticSensitivities
        else:
            return self.timeHistory