예제 #1
0
    def test_elementary(self):
        r = ct.ElementaryReaction({'O':1, 'H2':1}, {'H':1, 'OH':1})
        r.rate = ct.Arrhenius(3.87e1, 2.7, 6260*1000*4.184)

        gas2 = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                           species=self.species, reactions=[r])
        gas2.TPX = self.gas.TPX

        self.assertNear(gas2.forward_rate_constants[0],
                        self.gas.forward_rate_constants[2])
        self.assertNear(gas2.net_rates_of_progress[0],
                        self.gas.net_rates_of_progress[2])
예제 #2
0
    def test_negative_A(self):
        species = ct.Species.listFromFile('gri30.cti')
        r = ct.ElementaryReaction('NH:1, NO:1', 'N2O:1, H:1')
        r.rate = ct.Arrhenius(-2.16e13, -0.23, 0)

        self.assertFalse(r.allow_negative_pre_exponential_factor)

        with self.assertRaises(Exception):
            gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                              species=species, reactions=[r])

        r.allow_negative_pre_exponential_factor = True
        gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                          species=species, reactions=[r])
예제 #3
0
    def test_modify_invalid(self):
        # different reaction type
        tbr = self.gas.reaction(0)
        R2 = ct.ElementaryReaction(tbr.reactants, tbr.products)
        R2.rate = tbr.rate
        with self.assertRaises(ct.CanteraError):
            self.gas.modify_reaction(0, R2)

        # different reactants
        R = self.gas.reaction(7)
        with self.assertRaises(ct.CanteraError):
            self.gas.modify_reaction(23, R)

        # different products
        R = self.gas.reaction(14)
        with self.assertRaises(ct.CanteraError):
            self.gas.modify_reaction(15, R)
예제 #4
0
def remove(seed, num, exclude):
    np.random.seed(seed)
    reactions = gas.reactions()
    removed = []
    rcandidates = range(0, len(reactions))
    rcandidates = [item for item in rcandidates if item not in exclude]
    removed = np.random.choice(rcandidates, size=num, replace=False)
    for ind in removed:
        if (gas.reaction_type(ind) == 1):
            newreac = ct.ElementaryReaction(reactants=reactions[ind].reactants,
                                            products=reactions[ind].products)
            gas.modify_reaction(ind, newreac)
        if (gas.reaction_type(ind) == 2):
            newreac = ct.ThreeBodyReaction(reactants=reactions[ind].reactants,
                                           products=reactions[ind].products)
            gas.modify_reaction(ind, newreac)
        if (gas.reaction_type(ind) == 4):
            newreac = ct.FalloffReaction(reactants=reactions[ind].reactants,
                                         products=reactions[ind].products)
            gas.modify_reaction(ind, newreac)

    return removed
예제 #5
0
constants for reaction 2 and reaction 3 to show that even two reactions that have the
same Blowers-Masel parameters can have different forward rate constants.

The first plot generated shows how the rate constant changes with respect to temperature
for elementary and Blower-Masel reactions. The second plot shows the activation energy
change of a Blowers-Masel reaction with respect to the delta enthalpy of the reaction.

Requires: cantera >= 2.6.0, matplotlib >= 2.0
"""

import cantera as ct
import numpy as np
import matplotlib.pyplot as plt

#Create an elementary reaction O+H2<=>H+OH
r1 = ct.ElementaryReaction({'O': 1, 'H2': 1}, {'H': 1, 'OH': 1})
r1.rate = ct.Arrhenius(3.87e1, 2.7, 6260 * 1000 * 4.184)

#Create a Blowers-Masel reaction O+H2<=>H+OH
r2 = ct.BlowersMaselReaction({'O': 1, 'H2': 1}, {'H': 1, 'OH': 1})
r2.rate = ct.BlowersMasel(3.87e1, 2.7, 6260 * 1000 * 4.184, 1e9)

#Create a Blowers-Masel reaction with same parameters with r2
#reaction equation is H+CH4<=>CH3+H2
r3 = ct.BlowersMaselReaction({'H': 1, 'CH4': 1}, {'CH3': 1, 'H2': 1})
r3.rate = ct.BlowersMasel(3.87e1, 2.7, 6260 * 1000 * 4.184, 1e9)

gas = ct.Solution(thermo='IdealGas',
                  kinetics='GasKinetics',
                  species=ct.Solution('gri30.yaml').species(),
                  reactions=[r1, r2, r3])
예제 #6
0
    def perturb_parameter_thisisthecomplicatedonethatdoesntwork(
            self, parameter, new_value):
        param_info = self.model_parameter_info[parameter]
        reaction_number = param_info['reaction_number']
        parameter_type = param_info['parameter_type']

        print(parameter)
        print(param_info)

        reaction = self.gas.reaction(reaction_number)
        print(reaction.rate)
        rate = None
        efficiencies = None
        reactants = reaction.reactant_string
        products = reaction.product_string

        rtype = reaction.reaction_type

        pressurestring = 'pressure'
        HasFalloff = False

        if pressurestring in parameter_type:
            HasFalloff = True
        if HasFalloff:
            highrate = reaction.high_rate
            lowrate = reaction.low_rate
            if rtype == 4:
                newreaction = ct.FalloffReaction(reactants=reactants,
                                                 products=products)
            if rtype == 8:
                newreaction = ct.ChemicallyActivatedReaction(
                    reactants=reactants, products=products)
        else:
            rate = reaction.rate
            if rtype == 2:
                newreaction = ct.ThreeBodyReaction(reactants=reactants,
                                                   products=products)
            else:
                newreaction = ct.ElementaryReaction(reactants=reactants,
                                                    products=products)

        if parameter_type == 'A_factor':
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_A = new_value
            newreaction.rate = ct.Arrhenius(A=new_A, b=old_b, E=old_E)
        if parameter_type == 'Energy':
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_E = new_value
            newreaction.rate = ct.Arrhenius(A=old_A, b=old_b, E=new_E)
        if parameter_type == 'High_pressure_A':
            rate = highrate
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_A = new_value
            newreaction.high_rate = ct.Arrhenius(A=new_A, b=old_b, E=old_E)
        if parameter_type == 'High_pressure_E':
            rate = highrate
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_E = new_value
            newreaction.high_rate = ct.Arrhenius(A=old_A, b=old_b, E=new_E)
        if parameter_type == 'Low_pressure_A':
            rate = lowrate
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_A = new_value
            newreaction.low_rate = ct.Arrhenius(A=new_A, b=old_b, E=old_E)
        if parameter_type == 'Low_pressure_E':
            rate = lowrate
            old_A = rate.pre_exponential_factor
            old_b = rate.temperature_exponent
            old_E = rate.activation_energy
            new_E = new_value
            newreaction.low_rate = ct.Arrhenius(A=old_A, b=old_b, E=new_E)

        self.gas.modify_reaction(reaction_number, newreaction)

        if parameter_type == 'Efficiency':
            efficiencies = copy.deepcopy(reaction.efficiencies)
            species = param_info['species']
            efficiencies[species] = new_value
            reaction.efficiencies = efficiencies
        return
예제 #7
0
def residual(eta, k0, observations, measure_ind, tmaxes, temperatures,
             pressures, initials, maxes, yields):
    rstart = timeit.default_timer()

    ret = 0
    reactions = gas.reaction_equations()
    k = k0 * 10**eta
    if (gas.reaction_type(measure_ind) == 1):
        newrate = ct.ElementaryReaction(gas.reactions()[measure_ind].reactants,
                                        gas.reactions()[measure_ind].products)
        newrate.rate = ct.Arrhenius(
            k,
            gas.reactions()[measure_ind].rate.temperature_exponent,
            gas.reactions()[measure_ind].rate.activation_energy)
        gas.modify_reaction(measure_ind, newrate)
    if (gas.reaction_type(measure_ind) == 2):
        newrate = ct.ThreeBodyReaction(
            reactants=gas.reactions()[measure_ind].reactants,
            products=gas.reactions()[measure_ind].products)
        newrate.efficiencies = gas.reactions()[measure_ind].efficiencies
        newrate.rate = ct.Arrhenius(
            k,
            gas.reactions()[measure_ind].rate.temperature_exponent,
            gas.reactions()[measure_ind].rate.activation_energy)
        gas.modify_reaction(measure_ind, newrate)
    if (gas.reaction_type(measure_ind) == 4):
        newrate = ct.FalloffReaction(
            reactants=gas.reactions()[measure_ind].reactants,
            products=gas.reactions()[measure_ind].products)
        newrate.efficiencies = gas.reactions()[measure_ind].efficiencies
        newrate.falloff = gas.reactions()[measure_ind].falloff
        newrate.low_rate = ct.Arrhenius(
            k,
            gas.reactions()[measure_ind].low_rate.temperature_exponent,
            gas.reactions()[measure_ind].low_rate.temperature_exponent,
            gas.reactions()[measure_ind].low_rate.activation_energy)
        newrate.high_rate = gas.reactions()[measure_ind].high_rate
        gas.modify_reaction(measure_ind, newrate)

    sys.stdout.flush()
    for i in range(0, nmeasure):
        states = runsim_nosense(tmaxes[i], temperatures[i], pressures[i],
                                initials[i])

        for n in maxes:
            lst1 = observations[i].X[:, n]
            lst2 = states.X[:, n]
            ind1 = np.array(np.where(np.sign(np.diff(lst1)) == -1))[0, 0]

            if np.any(np.sign(np.diff(lst2)) == -1):
                ind2 = np.array(np.where(np.sign(np.diff(lst2)) == -1))[0, 0]
            else:
                ind2 = len(lst2) - 1
            ret += ((1.0 * ind2 / ind1 - 1)**2 +
                    (lst2[ind2] / lst1[ind1] - 1)**2) / nmeasure

            if (outflag == 1):
                print(temperatures[i], tmaxes[i], pressures[i] / ct.one_atm,
                      (1.0 * ind2 / ind1 - 1), (lst2[ind2] / lst1[ind1] - 1))
                sys.stdout.flush()
        for n in yields:
            lst1 = observations[i].X[:, n]
            lst2 = states.X[:, n]
            ret += ((lst2[-1] / lst1[-1] - 1)**2) / nmeasure

            if (outflag == 1):
                print(temperatures[i], tmaxes[i], pressures[i] / ct.one_atm,
                      (lst2[-1] / lst1[-1] - 1))
                sys.stdout.flush()

    if (outflag == 1):
        rstop = timeit.default_timer()
        print('iter time: %f' % (rstop - rstart))
        print('residual: ', ret)
        print('x: ', eta)
        sys.stdout.flush()

    return np.sqrt(ret)
예제 #8
0
          sensnorm,
          k / k0,
          result.fun,
          *removed,
          sep=' ',
          file=f)

    f.close()

    if (outflag == 1):
        print(result)
        sys.stdout.flush()
        reactions = gas.reaction_equations()
        if (gas.reaction_type(measure_ind) == 1):
            newrate = ct.ElementaryReaction(
                gas.reactions()[measure_ind].reactants,
                gas.reactions()[measure_ind].products)
            newrate.rate = ct.Arrhenius(
                k,
                gas.reactions()[measure_ind].rate.temperature_exponent,
                gas.reactions()[measure_ind].rate.activation_energy)
            gas.modify_reaction(measure_ind, newrate)
        if (gas.reaction_type(measure_ind) == 2):
            newrate = ct.ThreeBodyReaction(
                reactants=gas.reactions()[measure_ind].reactants,
                products=gas.reactions()[measure_ind].products)
            newrate.efficiencies = gas.reactions()[measure_ind].efficiencies
            newrate.rate = ct.Arrhenius(
                k,
                gas.reactions()[measure_ind].rate.temperature_exponent,
                gas.reactions()[measure_ind].rate.activation_energy)
예제 #9
0
            [300.00, 1000.00],
            [2.08692170E+00,  1.33149650E-01, -8.11574520E-05,
             2.94092860E-08, -6.51952130E-12, -3.59128140E+04,
             2.73552890E+01]
        ),
        NASA(
            [1000.00, 5000.00],
            [2.48802010E+01,  7.82500480E-02, -3.15509730E-05,
             5.78789000E-09, -3.98279680E-13, -4.31106840E+04,
             -9.36552550E+01]
        )
    ),
)

reaction(
    equation='A => B',
    kf=Arrhenius(A=52499925000.0, b=1.5, E=40900.0),
)
"""
gas = ct.Solution(source=cti_str)
gas.TP = 1000, 101325
print(gas.reactions()[0].rate(1000))
print(gas.forward_rate_constants)

r = ct.ElementaryReaction({'A': 1}, {'B': 1})
r.rate = ct.Arrhenius(3.87e1, 2.7, 6260 * 1000 * 4.184)

gas.modify_reaction(0, r)
print(gas.reactions()[0].rate(1000))
print(gas.forward_rate_constants)
예제 #10
0
    def _build_cantera_solution(cls, gdata):
        p_ref = gdata['ref_pressure']
        species_list = list()
        for s in gdata['species']:
            spec = gdata['species'][s]
            ctspec = ct.Species(
                s, ','.join(
                    [f'{k}:{spec["atom_map"][k]}' for k in spec['atom_map']]))
            if spec['cp'][0] == 'constant':
                Tmin, Tmax, T0, h0, s0, cp = spec['cp'][1:]
                ctspec.thermo = ct.ConstantCp(Tmin, Tmax, p_ref,
                                              list([T0, h0, s0, cp]))
            elif spec['cp'][0] == 'NASA7':
                Tmin, Tmid, Tmax, low_coeffs, high_coeffs = spec['cp'][1:]
                coeffs = [Tmid] + high_coeffs + low_coeffs
                ctspec.thermo = ct.NasaPoly2(Tmin, Tmax, p_ref, coeffs)
            species_list.append(ctspec)

        reaction_list = list()
        for rxn in gdata['reactions']:
            type, reactants_stoich, products_stoich, reversible = rxn[:4]

            fwd_pre_exp_value, fwd_temp_exponent, fwd_act_energy = rxn[4:7]
            fwd_rate = ct.Arrhenius(fwd_pre_exp_value, fwd_temp_exponent,
                                    fwd_act_energy)

            if type == 'simple' or type == 'simple-special':
                ctrxn = ct.ElementaryReaction(reactants_stoich,
                                              products_stoich)
                ctrxn.rate = fwd_rate
            elif type == 'three-body' or type == 'three-body-special':
                ctrxn = ct.ThreeBodyReaction(reactants_stoich, products_stoich)
                ctrxn.rate = fwd_rate
                ctrxn.efficiencies = rxn[7]
                ctrxn.default_efficiency = rxn[8]
            elif type == 'Lindemann' or type == 'Lindemann-special':
                ctrxn = ct.FalloffReaction(reactants_stoich, products_stoich)
                ctrxn.efficiencies = rxn[7]
                ctrxn.default_efficiency = rxn[8]
                flf_pre_exp_value, flf_temp_exponent, flf_act_energy = rxn[
                    9:12]
                ctrxn.high_rate = fwd_rate
                ctrxn.low_rate = ct.Arrhenius(flf_pre_exp_value,
                                              flf_temp_exponent,
                                              flf_act_energy)
                ctrxn.falloff = ct.Falloff()
            elif type == 'Troe' or type == 'Troe-special':
                ctrxn = ct.FalloffReaction(reactants_stoich, products_stoich)
                ctrxn.efficiencies = rxn[7]
                ctrxn.default_efficiency = rxn[8]
                flf_pre_exp_value, flf_temp_exponent, flf_act_energy = rxn[
                    9:12]
                troe_params = rxn[12]
                ctrxn.high_rate = fwd_rate
                ctrxn.low_rate = ct.Arrhenius(flf_pre_exp_value,
                                              flf_temp_exponent,
                                              flf_act_energy)
                if len(troe_params) == 4 and abs(troe_params[3]) < 1e-300:
                    ctrxn.falloff = ct.TroeFalloff(troe_params[:3])
                else:
                    ctrxn.falloff = ct.TroeFalloff(troe_params)

            if 'special' in type:
                ctrxn.orders = rxn[-1]

            ctrxn.reversible = reversible
            reaction_list.append(ctrxn)

        return ct.Solution(thermo='IdealGas',
                           kinetics='GasKinetics',
                           species=species_list,
                           reactions=reaction_list)
예제 #11
0
    def set_mechanism(self, mech_dict, species_dict={}, bnds=[]):
        def get_Arrhenius_parameters(entry):
            A = entry['pre_exponential_factor']
            b = entry['temperature_exponent']
            Ea = entry['activation_energy']

            return A, b, Ea

        if len(species_dict) == 0:
            species = self.gas.species()
        else:
            species = []
            for n in range(len(species_dict)):
                s_dict = species_dict[n]
                s = ct.Species(name=s_dict['name'],
                               composition=s_dict['composition'],
                               charge=s_dict['charge'],
                               size=s_dict['size'])
                thermo = s_dict['type'](s_dict['T_low'], s_dict['T_high'],
                                        s_dict['P_ref'], s_dict['coeffs'])
                s.thermo = thermo

                species.append(s)

        # Set kinetics data
        rxns = []
        for rxnIdx in range(len(mech_dict)):
            if 'ElementaryReaction' == mech_dict[rxnIdx]['rxnType']:
                rxn = ct.ElementaryReaction(mech_dict[rxnIdx]['reactants'],
                                            mech_dict[rxnIdx]['products'])
                rxn.allow_negative_pre_exponential_factor = True

                A, b, Ea = get_Arrhenius_parameters(
                    mech_dict[rxnIdx]['rxnCoeffs'][0])
                rxn.rate = ct.Arrhenius(A, b, Ea)

            elif 'ThreeBodyReaction' == mech_dict[rxnIdx]['rxnType']:
                rxn = ct.ThreeBodyReaction(mech_dict[rxnIdx]['reactants'],
                                           mech_dict[rxnIdx]['products'])

                A, b, Ea = get_Arrhenius_parameters(
                    mech_dict[rxnIdx]['rxnCoeffs'][0])
                rxn.rate = ct.Arrhenius(A, b, Ea)
                rxn.efficiencies = mech_dict[rxnIdx]['rxnCoeffs'][0][
                    'efficiencies']

            elif 'PlogReaction' == mech_dict[rxnIdx]['rxnType']:
                rxn = ct.PlogReaction(mech_dict[rxnIdx]['reactants'],
                                      mech_dict[rxnIdx]['products'])

                rates = []
                for plog in mech_dict[rxnIdx]['rxnCoeffs']:
                    pressure = plog['Pressure']
                    A, b, Ea = get_Arrhenius_parameters(plog)
                    rates.append((pressure, ct.Arrhenius(A, b, Ea)))

                rxn.rates = rates

            elif 'FalloffReaction' == mech_dict[rxnIdx]['rxnType']:
                rxn = ct.FalloffReaction(mech_dict[rxnIdx]['reactants'],
                                         mech_dict[rxnIdx]['products'])

                # high pressure limit
                A, b, Ea = get_Arrhenius_parameters(
                    mech_dict[rxnIdx]['rxnCoeffs']['high_rate'])
                rxn.high_rate = ct.Arrhenius(A, b, Ea)

                # low pressure limit
                A, b, Ea = get_Arrhenius_parameters(
                    mech_dict[rxnIdx]['rxnCoeffs']['low_rate'])
                rxn.low_rate = ct.Arrhenius(A, b, Ea)

                # falloff parameters
                if mech_dict[rxnIdx]['rxnCoeffs']['falloff_type'] == 'Troe':
                    falloff_param = mech_dict[rxnIdx]['rxnCoeffs'][
                        'falloff_parameters']
                    if falloff_param[-1] == 0.0:
                        falloff_param = falloff_param[0:-1]

                    rxn.falloff = ct.TroeFalloff(falloff_param)
                else:
                    rxn.falloff = ct.SriFalloff(
                        mech_dict[rxnIdx]['rxnCoeffs']['falloff_parameters'])

                rxn.efficiencies = mech_dict[rxnIdx]['rxnCoeffs'][
                    'efficiencies']

            elif 'ChebyshevReaction' == mech_dict[rxnIdx]['rxnType']:
                rxn = ct.ChebyshevReaction(mech_dict[rxnIdx]['reactants'],
                                           mech_dict[rxnIdx]['products'])
                rxn.set_parameters(Tmin=mech_dict['Tmin'],
                                   Tmax=mech_dict['Tmax'],
                                   Pmin=mech_dict['Pmin'],
                                   Pmax=mech_dict['Pmax'],
                                   coeffs=mech_dict['coeffs'])

            rxn.duplicate = mech_dict[rxnIdx]['duplicate']
            rxn.reversible = mech_dict[rxnIdx]['reversible']
            rxn.allow_negative_orders = True
            rxn.allow_nonreactant_orders = True

            rxns.append(rxn)

        self.gas = ct.Solution(thermo='IdealGas',
                               kinetics='GasKinetics',
                               species=species,
                               reactions=rxns)

        self.set_rate_expression_coeffs(bnds)  # set copy of coeffs
        self.set_thermo_expression_coeffs()  # set copy of thermo coeffs
예제 #12
0
def run(gas, interval, num_states, work_dir, repeats=10):
    def arrhenius(T, A, b, Ea, print_stats=False):
        vals = A * np.power(T, b) * np.exp(-Ea / (ct.gas_constant * T))
        if print_stats:
            print(A, b, Ea, np.max(np.abs(vals - kf) / kf))
        return vals

    # first, convert all reactions to a single rate form
    reacs = gas.reactions()[:]
    for i, reac in enumerate(reacs):
        if isinstance(reac, ct.ChemicallyActivatedReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.high_rate
        elif isinstance(reac, ct.FalloffReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.high_rate
        elif isinstance(reac, ct.ThreeBodyReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.rate
        elif isinstance(reac, ct.PlogReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.rates[-1][1]
        elif isinstance(reac, ct.ChebyshevReaction):
            # fit _something_ to it at a 10 bar, for 600-2200K
            T = np.linspace(600, 2200, num=1000)
            kf = np.zeros_like(T)
            for j in range(T.size):
                kf[j] = reac(T[j], 10 * 10*1e5)
            A = 1e10
            b = 1
            Ea = 1200 * ct.gas_constant
            (A, b, Ea), _ = curve_fit(
                arrhenius, T, kf,
                p0=[A, b, Ea],
                bounds=[(0, -2, 0), (np.inf, 5, np.inf)],
                maxfev=1e6,
                xtol=1e-15)
            if False:
                plt.plot(T, kf, color='b', linestyle='-', label='cheb')
                plt.plot(T, arrhenius(T, A, b, Ea), color='r', linestyle='--',
                         label='fit')
                plt.legend(loc=0)
                plt.show()
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = ct.Arrhenius(A, b, Ea)
        # set all to reversible
        reacs[i].reversible = True

    # and convert gas
    gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                      reactions=reacs,
                      species=gas.species())

    # next, order the reactions by the number of distinct species
    def get_reac_and_spec_maps(mygas):
        # first, create rxn->species maps
        reac_nu = mygas.reactant_stoich_coeffs()
        prod_nu = mygas.product_stoich_coeffs()
        # species -> rxn mappings
        spec_masks = np.zeros((mygas.n_species, mygas.n_reactions),
                              dtype=np.bool)
        # the reaction -> species mappings
        reac_masks = []
        for i, reac in enumerate(mygas.reactions()):
            for spec in set(list(reac.reactants.keys()) + list(
                                 reac.products.keys())):
                j = mygas.species_index(spec)
                if prod_nu[j, i] - reac_nu[j, i]:
                    # non-zero species
                    spec_masks[j, i] = True
            reac_masks.append(np.where(spec_masks[:, i])[0])

        # convert to flat, fixed size array
        copy = np.array(reac_masks, copy=True)
        max_size = np.max([x.size for x in reac_masks])
        reac_masks = np.full((len(reac_masks), max_size), -1)
        for i, mask in enumerate(copy):
            reac_masks[i, :mask.size] = mask[:]

        return spec_masks, reac_masks

    # ensure we didn't remove any species
    spec_masks, reac_masks = get_reac_and_spec_maps(gas)
    converted_spec_count = np.where(~np.sum(spec_masks, axis=1))[0].size
    assert converted_spec_count == gas.n_species

    def species_to_rxn_count(reac_list=slice(None)):
        """
        The number of reactions each species is in
        """
        return np.sum(spec_masks[:, reac_list], axis=1)

    def simple(specs, spec_counts):
        """
        Returns 0 if any species in the reaction is unique to that reaction
        otherwise mean of the number of reactions per species in the reaction
        """
        specs = specs[np.where(specs >= 0)]
        if np.any(spec_counts[specs] == 1):
            return 0
        return np.mean(spec_counts[specs])

    def minh(specs, spec_counts):
        """
        The minimum number of reactions any species in the reaction is in
        """

        specs = specs[np.where(specs >= 0)]
        minh = np.min(spec_counts[specs])
        return 0 if minh == 1 else minh

    def rxn_scores(heuristic, reac_list=slice(None)):
        """
        Returns a score from 0--1, where 1 indicates that the reactions is a
        good removal candidate and 0 a bad candidate

        Heuristics correspond to local methods
        """

        reac_list = np.arange(gas.n_reactions)[reac_list]
        s2r = species_to_rxn_count(reac_list)
        scores = np.apply_along_axis(heuristic, 1, reac_masks[reac_list], s2r)
        return scores

    def get_next_removed(heuristic, reac_list=slice(None)):
        """
        Get the index of the next reaction to remove from the current reac_list
        using the given heuristic
        """
        scores = rxn_scores(heuristic, reac_list)
        amax = np.argmax(scores)
        if scores[amax] == 0:
            return -1
        return reac_list[amax]

    def active_reactions(reac_list, return_active=False):
        """
        Returns the number of active reactions in the reac_list
        If return_active is True, return the list of active reactions
        """
        alist = np.where(reac_list >= 0)[0]
        if return_active:
            return alist
        return alist.size

    saved_reaction_lists = []
    reac_list = np.arange(gas.n_reactions)
    saved_reaction_lists.append(active_reactions(reac_list, True))
    while True:
        remove_at = get_next_removed(minh, reac_list=np.where(
            reac_list >= 0)[0])
        if remove_at == -1:
            break
        reac_list[remove_at] = -1
        if (active_reactions(reac_list) <= active_reactions(
                saved_reaction_lists[-1]) - interval):
            # save list
            saved_reaction_lists.append(active_reactions(reac_list, True))

    # get final reaction list and save
    reac_list = active_reactions(reac_list, True)
    saved_reaction_lists.append(reac_list)

    def gas_from_reac_list(reac_list):
        reacs = gas.reactions()[:]
        reacs = [reacs[i] for i in reac_list]
        return ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                           reactions=reacs,
                           species=gas.species())

    # remap, and ensure the number of removed species is not less than
    # previously
    newgas = gas_from_reac_list(reac_list)
    smap_final, _ = get_reac_and_spec_maps(newgas)
    scount_final = np.where(~np.sum(smap_final, axis=1))[0].size
    assert scount_final == converted_spec_count

    print('Final mechanism size: {} reactions, {} species'.format(
        newgas.n_reactions, scount_final))

    vecsize = 8
    platform = 'intel'
    split_rate_kernels = False
    lang = 'opencl'
    rate_spec = 'hybrid'
    num_cores = 1
    order = 'C'

    def get_filename(wide=False):
        """
        emulate pyjac's naming scheme
        """
        desc = 'spec'
        vsize = vecsize if wide else '1'
        vectype = 'w' if wide else 'par'
        platform = 'intel'
        split = 'split' if split_rate_kernels else 'single'
        conp = 'conp'

        return '{}_{}_{}_{}_{}_{}_{}_{}_{}_{}'.format(
                desc, lang, vsize, order,
                vectype, platform, rate_spec,
                split, num_cores, conp) + '.txt'

    def check_file(file):
        if not os.path.exists(file):
            return repeats
        with open(file, 'r') as f:
            lines = f.readlines()
        import re
        todo = repeats
        for line in lines:
            line = line.split(',')
            if len(line) > 1 and sum(
                    1 if re.search(r'(?:\d+(?:\.\d+e[+-]\d+))', l) else 0
                    for l in line) == 4:
                # four doubles -> good line
                todo -= 1
        return todo

    build = os.path.join(path, 'out')
    obj = os.path.join(path, 'obj')
    lib = os.path.join(path, 'lib')

    for wide in [True, False]:
        vsize = vecsize if wide else None
        # now, go through the various generated reactions lists and run
        # the test on each
        for reac_list in saved_reaction_lists:
            outname = get_filename(wide)
            todo = check_file(outname)
            # clean
            clean_dir(build, remove_dir=False)
            clean_dir(obj, remove_dir=False)
            clean_dir(lib, remove_dir=False)

            subdir = os.path.join(work_dir, str(active_reactions(reac_list)))
            create_dir(subdir)
            # generate the source rate evaluation
            rgas = gas_from_reac_list(reac_list)
            create_jacobian('opencl', gas=rgas, vector_size=vsize,
                            wide=wide, build_path=build,
                            rate_specialization=rate_spec,
                            split_rate_kernels=split_rate_kernels,
                            data_filename=os.path.abspath(
                                os.path.join(work_dir, 'data.bin')),
                            data_order=order,
                            platform=platform,
                            skip_jac=True)

            # first create the executable (via libgen)
            tester = generate_library(lang, build, obj_dir=obj, out_dir=lib,
                                      shared=True,
                                      btype=build_type.species_rates,
                                      as_executable=True)

            # and do runs
            with open(os.path.join(subdir, outname), 'a+') as file:
                for i in range(todo):
                    print(i, "/", todo)
                    subprocess.check_call([os.path.join(lib, tester),
                                           str(num_states), str(1)],
                                          stdout=file)
예제 #13
0
    def toCantera(self, speciesList=None, useChemkinIdentifier = False):
        """
        Converts the RMG Reaction object to a Cantera Reaction object
        with the appropriate reaction class.

        If useChemkinIdentifier is set to False, the species label is used
        instead. Be sure that species' labels are unique when setting it False.
        """
        from rmgpy.kinetics import Arrhenius, ArrheniusEP, MultiArrhenius, PDepArrhenius, MultiPDepArrhenius, Chebyshev, ThirdBody, Lindemann, Troe
                    
        import cantera as ct
        
        if speciesList is None:
            speciesList = []
        
        # Create the dictionaries containing species strings and their stoichiometries
        # for initializing the cantera reaction object
        ctReactants = {}
        for reactant in self.reactants:
            if useChemkinIdentifier:
                reactantName = reactant.toChemkin()
            else:
                reactantName = reactant.label
            if reactantName in ctReactants:
                ctReactants[reactantName] += 1
            else:
                ctReactants[reactantName] = 1
        ctProducts = {}
        for product in self.products:
            if useChemkinIdentifier:
                productName = product.toChemkin()
            else:
                productName = product.label
            if productName in ctProducts:
                ctProducts[productName] += 1
            else:
                ctProducts[productName] = 1
                
        if self.kinetics:
            if isinstance(self.kinetics, Arrhenius):
                # Create an Elementary Reaction
                ctReaction = ct.ElementaryReaction(reactants=ctReactants, products=ctProducts)
            elif isinstance(self.kinetics, MultiArrhenius):
                # Return a list of elementary reactions which are duplicates
                ctReaction = [ct.ElementaryReaction(reactants=ctReactants, products=ctProducts) for arr in self.kinetics.arrhenius]
                
            elif isinstance(self.kinetics, PDepArrhenius):
                ctReaction = ct.PlogReaction(reactants=ctReactants, products=ctProducts)
                
            elif isinstance(self.kinetics, MultiPDepArrhenius):
                ctReaction = [ct.PlogReaction(reactants=ctReactants, products=ctProducts) for arr in self.kinetics.arrhenius]
                
            
            elif isinstance(self.kinetics, Chebyshev):
                ctReaction = ct.ChebyshevReaction(reactants=ctReactants, products=ctProducts)
            
            elif isinstance(self.kinetics, ThirdBody):
                ctReaction = ct.ThreeBodyReaction(reactants=ctReactants, products=ctProducts)
                
            elif isinstance(self.kinetics, Lindemann) or isinstance(self.kinetics, Troe):
                ctReaction = ct.FalloffReaction(reactants=ctReactants, products=ctProducts)
            else:
                raise NotImplementedError('Not able to set cantera kinetics for {0}'.format(self.kinetics))
            
            
            # Set reversibility, duplicate, and ID attributes
            if isinstance(ctReaction,list):
                for rxn in ctReaction:
                    rxn.reversible = self.reversible
                    # Set the duplicate flag to true since this reaction comes from multiarrhenius or multipdeparrhenius 
                    rxn.duplicate = True
                    # Set the ID flag to the original rmg index 
                    rxn.ID = str(self.index) 
            else:
                ctReaction.reversible = self.reversible
                ctReaction.duplicate = self.duplicate
                ctReaction.ID = str(self.index)
                
            
            self.kinetics.setCanteraKinetics(ctReaction, speciesList)
            
            return ctReaction
                
        else:
            raise Exception('Cantera reaction cannot be created because there was no kinetics.')