Example #1
0
    def test_mechanism_simple_api_methods(self):
        try:
            xml = abspath(join('tests', 'test_mechanisms', 'h2-burke.xml'))
            sol = Solution(xml)
            m = ChemicalMechanismSpec.from_solution(sol)
            self.assertEqual(m.n_species, sol.n_species, 'ChemicalMechanismSpec.n_species vs ct.Solution.n_species')
            self.assertEqual(m.n_reactions, sol.n_reactions,
                             'ChemicalMechanismSpec.n_reactions vs ct.Solution.n_reactions')
            for i in range(m.n_species):
                self.assertEqual(m.species_names[i], sol.species_names[i],
                                 'ChemicalMechanismSpec.species_name[i] vs ct.Solution.species_name[i]')
            for n in m.species_names:
                self.assertEqual(m.species_index(n), sol.species_index(n),
                                 'ChemicalMechanismSpec.species_index(name) vs ct.Solution.species_index(name)')

            for i, n in enumerate(m.species_names):
                self.assertEqual(m.species_index(n), i, 'species names and indices are consistent, index vs i')
                self.assertEqual(n, m.species_names[i], 'species names and indices are consistent, name vs n')
                self.assertEqual(m.molecular_weight(i), m.molecular_weight(n),
                                 'ChemicalMechanismSpec molecular_weight(name) vs molecular_weight(idx)')
        except:
            self.assertTrue(False)

        try:
            xml = abspath(join('tests', 'test_mechanisms', 'h2-burke.xml'))
            m = ChemicalMechanismSpec.from_solution(Solution(xml))
            m.molecular_weight(list())
            self.assertTrue(False)
        except:
            self.assertTrue(True)
Example #2
0
def validate_on_mechanism(mech, temperature, pressure, tau, do_rhs, do_jac):
    xml = join(test_mech_directory, mech + '.xml')
    T = temperature
    Tin = T + 1000.
    p = pressure

    r = ChemicalMechanismSpec(xml, 'gas').griffon

    gas = Solution(xml)
    ns = gas.n_species

    y = np.ones(ns)  # equal masses in the reactor
    gas.TPY = T, p, y
    y = np.copy(gas.Y)

    xin = np.ones(ns)  # equal moles in the feed
    gas.TPX = Tin, p, xin
    yin = np.copy(gas.Y)

    state = hstack((T, y[:-1]))

    rhsCN = rhs_cantera(p, T, y, Tin, yin, tau, gas)
    rhsGR = np.empty(ns)
    r.reactor_rhs_isobaric(state, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, rhsGR)

    if do_rhs:
        return max(abs(rhsGR - rhsCN) / (abs(rhsCN) + 1.)) < 1.e-4

    if do_jac:
        jacGR = np.empty(ns * ns)
        r.reactor_jac_isobaric(state, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, 0, 0, rhsGR, jacGR)
        jacGR = jacGR.reshape((ns, ns), order='F')

        dT = 1.e-6
        dY = 1.e-6
        jacFD = np.empty((ns, ns))
        rhsGR1, rhsGR2 = np.empty(ns), np.empty(ns)
        state_m = hstack((T - dT, y[:-1]))
        state_p = hstack((T + dT, y[:-1]))
        r.reactor_rhs_isobaric(state_m, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, rhsGR1)
        r.reactor_rhs_isobaric(state_p, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, rhsGR2)
        jacFD[:, 0] = (- rhsGR1 + rhsGR2) / (2. * dT)

        for i in range(ns - 1):
            y_m1, y_p1 = np.copy(y), np.copy(y)
            y_m1[i] += - dY
            y_m1[-1] -= - dY
            y_p1[i] += dY
            y_p1[-1] -= dY
            state_m = hstack((T, y_m1[:-1]))
            state_p = hstack((T, y_p1[:-1]))
            r.reactor_rhs_isobaric(state_m, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, rhsGR1)
            r.reactor_rhs_isobaric(state_p, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, True, rhsGR2)
            jacFD[:, 1 + i] = (- rhsGR1 + rhsGR2) / (2. * dY)

        pass_jac = max(abs(jacGR - jacFD) / (abs(jacGR) + 1.)) < 1.e-2

        return pass_jac
Example #3
0
def new_result_dict(sln: ct.Solution, species_list=None):
    """
    Returns an empty result dictionary used for storing state variables during kinetic simulations
    :param sln: ct.Solution object to be used in the simulation
    :param species_list: list of species for which to record mole fractions; default None to record all species in
     mechansim
    :return dict: result dictionary with empty lists in fields for time, T, P, and all species, along with a list of
     all included species and another of the species indices within the sln.X array
    """
    # if the species list is None, make entries for all the species in the Solution object
    if species_list is None:
        species_list = sln.species_names
    else:  # remove any species in the list not in the Solution to prevent errors
        species_list_2, species_list = list(species_list), [
        ]  # store provided species_list as species_list_2, make a
        #   new species list for storing valid species
        for sp in species_list_2:
            if sp in sln.species_names and sp not in species_list:
                species_list += [sp]
            elif sp not in sln.species_names:
                print(f"{sp} not in mechanism; removed from tracked species.")

    # start initializing the dictionary with basic properties - time, temperature (T), pressure (P)
    result_dict = {'time': [], 'T': [], 'P': []}
    # now add entries for the species
    for sp in species_list:
        result_dict[sp] = []
    # finally, add entries with a list of the species and their indices
    result_dict['species'] = species_list
    result_dict['indices'] = [sln.species_index(sp) for sp in species_list]

    return result_dict
Example #4
0
def pymars(model_file,
           conditions,
           error,
           method,
           target_species,
           retained_species=None,
           run_sensitivity_analysis=False,
           epsilon_star=0.1):
    """Driver function for pyMARS to reduce a model.

    Parameters
    ----------
    model_file : str
        Cantera-format model to be reduced (e.g., 'mech.cti').
    conditions : str
        File with list of autoignition initial conditions.
    error : float
        Maximum error % for the reduced model.
    method : {'DRG', 'DRGEP', 'PFA'}
        Skeletal reduction method to use.
    target_species: list of str
        List of target species for reduction.
    retained_species : list of str, optional
        List of non-target species to always retain.
    run_sensitivity_analysis : bool, optional
        Flag to run sensitivity analysis after completing another method.
    epsilon_star : float, optional
        Epsilon^* value used to determine species for sensitivity analysis.

    Returns
    -------
        Converted mechanism file
        Trimmed Solution Object
        Trimmed Mechanism file

    Examples
    --------
    >>> pymars('gri30.cti', conditions_file, 10.0, 'DRGEP', ['CH4', 'O2'], retained_species=['N2'])

    """

    solution_object = Solution(model_file)

    if method == 'DRG':
        results = run_drg(solution_object, conditions, error, target_species,
                          retained_species)
    elif method == 'PFA':
        results = run_pfa(solution_object, conditions, error, target_species,
                          retained_species)
    elif method == 'DRGEP':
        results = run_drgep(solution_object, conditions, error, target_species,
                            retained_species)
    reduced_model, reduced_error = results

    if run_sensitivity_analysis:
        results = run_sa(solution_object, reduced_model, epsilon_star,
                         conditions, error, retained_species)
        reduced_model, reduced_error = results
        sa_file = soln2cti.write(reduced_model)
Example #5
0
    def test_mechanism_serialization(self):
        xml = abspath(join('tests', 'test_mechanisms', 'h2-burke.xml'))
        sol = Solution(xml)
        m1 = ChemicalMechanismSpec.from_solution(sol)

        m1_pickle = pickle.dumps(m1)
        m2 = pickle.loads(m1_pickle)

        self.assertTrue(m1.mech_data['species'] == m2.mech_data['species'])
        self.assertTrue(m1.mech_data['reactions'] == m2.mech_data['reactions'])
Example #6
0
 def test_create_valid_mechanism_spec_from_solution(self):
     try:
         xml = abspath(join('tests', 'test_mechanisms', 'h2-burke.xml'))
         sol = Solution(xml)
         m = ChemicalMechanismSpec.from_solution(sol)
         g = m.griffon
         x = m.mech_xml_path
         n = m.group_name
         s = m.gas
         self.assertTrue(True)
     except:
         self.assertTrue(False)
Example #7
0
def test_reflected_shock_frozen():
    mechanism = 'gri30.cti'

    # define states
    initial_gas = Solution(mechanism)
    initial_gas.TPX = 300, 101325, {'H2': 1}

    working_gas = Solution(mechanism)
    working_gas.TPX = 300, 101325 * 2, {'H2': 1}

    velocity_guess = 7

    # errors from hand calculations
    good_errors = [
        -73.5,  # enthalpy
        101316.97487230592  # pressure
    ]

    test_errors = calculate_error.reflected_shock_frozen(
        working_gas=working_gas,
        post_shock_gas=initial_gas,
        shock_speed=velocity_guess)

    for test, good in zip(test_errors, good_errors):
        assert abs(test - good) / good < 1e-7
Example #8
0
def test_equilibrium():
    mechanism = 'gri30.cti'

    # define states
    initial_gas = Solution(mechanism)
    initial_gas.TPX = 300, 101325, {'H2': 1}

    working_gas = Solution(mechanism)
    working_gas.TPX = 300, 101325 * 2, {'H2': 1}

    velocity_guess = 7

    # errors from hand calculations
    good_errors = [
        -18.375000000,  # enthalpy
        101322.993718076,  # pressure
    ]

    test_errors = calculate_error.equilibrium(
        working_gas=working_gas,
        initial_state_gas=initial_gas,
        initial_velocity_guess=velocity_guess)

    for test, good in zip(test_errors, good_errors):
        assert abs(test - good) / good < 1e-7
    def test_no_convergence():
        # ensure the proper warning is generated when solution doesn't converge
        mechanism = 'gri30.cti'

        initial_gas = Solution(mechanism)
        initial_gas.TPX = 300, 101325, {'H2': 1}

        working_gas = Solution(mechanism)
        working_gas.TPX = 300, 101325 * 2, {'H2': 1}

        with pytest.warns(Warning, match='No convergence within 1 iterations'):
            sd.Detonation.cj_state(working_gas, initial_gas, 1e-50, 1e-50, 1.5,
                                   1)
Example #10
0
def equilibrium_constants_expr(sol: ct.Solution, react: ct.Reaction, gibbs_rt):
    indices_reac = [sol.species_index(sp) for sp in react.reactants]
    indices_prod = [sol.species_index(sp) for sp in react.products]

    # Stoichiometric coefficients
    nu_reac = [react.reactants[sp] for sp in react.reactants]
    nu_prod = [react.products[sp] for sp in react.products]

    sum_r = sum(nu_reac_i * gibbs_rt[indices_reac_i]
                for indices_reac_i, nu_reac_i in zip(indices_reac, nu_reac))
    sum_p = sum(nu_prod_i * gibbs_rt[indices_prod_i]
                for indices_prod_i, nu_prod_i in zip(indices_prod, nu_prod))

    # Check if reaction is termolecular
    sum_nu_net = sum(nu_prod) - sum(nu_reac)
    if sum_nu_net < 0:
        # Three species on reactants side
        return sum_p + p.Variable("C0") - sum_r
    elif sum_nu_net > 0:
        # Three species on products side
        return sum_p - (sum_r + p.Variable("C0"))
    else:
        return sum_p - sum_r
Example #11
0
    def test_good_input():
        # compare against SDToolbox results
        mechanism = 'gri30.cti'

        initial_gas = Solution(mechanism)
        initial_gas.TPX = 300, 101325, {'H2': 1}

        working_gas = Solution(mechanism)
        working_gas.TPX = 300, 101325 * 2, {'H2': 1}

        cj_calcs = sd.Detonation.cj_state(
            working_gas,
            initial_gas,
            1e-5,
            1e-5,
            1.5
        )

        good_temp = 355.77590742266216
        good_press = 180244.9690980063
        good_species = {'H': 2.8407416566652653e-30, 'H2': 1.0}

        test_temp = cj_calcs[0].T
        check_temp = abs(test_temp - good_temp) / good_temp < 1e-7

        test_press = cj_calcs[0].P
        check_press = abs(test_press - good_press) / good_press < 1e-7

        good_velocity = 1700.3611387277992
        test_velocity = cj_calcs[1]
        check_velocity = abs(test_velocity - good_velocity) / good_velocity \
            < 1e-7

        checks = [check_temp, check_press, check_velocity]

        # make sure the species in each solution are the same
        test_species = cj_calcs[0].mole_fraction_dict()
        for species in good_species:
            checks.append(
                good_species[species] - test_species[species] < 1e-7
            )

        assert all(checks)
Example #12
0
def validate_on_mechanism(mech, temperature, pressure, full_Jacobian,
                          isochoric):
    xml = join(test_mech_directory, mech + '.xml')

    r = ChemicalMechanismSpec(xml, 'gas').griffon

    gas = Solution(xml)
    ns = gas.n_species

    T = temperature
    p = pressure

    gas.TPX = T, p, ones(ns)
    y = gas.Y
    rho = gas.density_mass

    if full_Jacobian and isochoric:
        state = hstack((rho, T, y[:-1]))
        rhsGRTemporary = np.empty(ns + 1)
        jac_dense = np.empty((ns + 1) * (ns + 1))
        jac_sparse = np.empty((ns + 1) * (ns + 1))
        r.reactor_jac_isochoric(state, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, 0, rhsGRTemporary, jac_dense)
        r.reactor_jac_isochoric(state, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, 2, rhsGRTemporary, jac_sparse)
        jac_dense = jac_dense.reshape((ns + 1, ns + 1), order='F')
        jac_sparse = jac_sparse.reshape((ns + 1, ns + 1), order='F')

    elif full_Jacobian and not isochoric:
        state = hstack((T, y[:-1]))
        k = np.empty(ns)
        jac_dense = np.empty(ns * ns)
        jac_sparse = np.empty(ns * ns)
        r.reactor_jac_isobaric(state, p, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0, 0,
                               False, 0, 0, k, jac_dense)
        r.reactor_jac_isobaric(state, p, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0, 0,
                               False, 2, 0, k, jac_sparse)

        jac_dense = jac_dense.reshape((ns, ns), order='F')
        jac_sparse = jac_sparse.reshape((ns, ns), order='F')

    else:
        jac_dense = np.zeros((ns + 1) * (ns + 1))
        jac_sparse = np.zeros((ns + 1) * (ns + 1))
        r.prod_rates_primitive_sensitivities(rho, T, y, 0, jac_dense)
        r.prod_rates_primitive_sensitivities(rho, T, y, 2, jac_sparse)
        jac_dense = jac_dense.reshape((ns + 1, ns + 1), order='F')[:-1, :]
        jac_sparse = jac_sparse.reshape((ns + 1, ns + 1), order='F')[:-1, :]

        jac_fd = np.zeros_like(jac_dense)
        rhsGR1 = np.zeros(ns)
        rhsGR2 = np.zeros(ns)
        dT = 1.e-4
        dr = 1.e-4
        dY = 1.e-4
        r.production_rates(T, rho + dr, y, rhsGR1)
        r.production_rates(T, rho - dr, y, rhsGR2)
        jac_fd[:, 0] = (rhsGR1 - rhsGR2) / dr * 0.5
        r.production_rates(T + dT, rho, y, rhsGR1)
        r.production_rates(T - dT, rho, y, rhsGR2)
        jac_fd[:, 1] = (rhsGR1 - rhsGR2) / dT * 0.5

        for spec_idx in range(ns - 1):
            Yp = np.copy(y)
            Yp[spec_idx] += dY
            Yp[-1] -= dY
            Ym = np.copy(y)
            Ym[spec_idx] -= dY
            Ym[-1] += dY
            r.production_rates(T, rho, Yp, rhsGR1)
            r.production_rates(T, rho, Ym, rhsGR2)
            jac_fd[:, 2 + spec_idx] = (rhsGR1 - rhsGR2) / dY * 0.5

    pass_sparse_vs_dense_jac = np.linalg.norm(
        jac_dense.ravel() - jac_sparse.ravel(), ord=np.Inf) < 1.e-10

    # if not pass_sparse_vs_dense_jac:
    #     print(mech)
    #     diff = abs(jac_dense - jac_sparse) / (abs(jac_dense) + 1.)
    #     nr, nc = jac_dense.shape
    #     print('dense')
    #     for ir in range(nr):
    #         for ic in range(nc):
    #             print(f'{jac_dense[ir, ic]:8.0e}', end=', ')
    #         print('')
    #     print('sparse')
    #     for ir in range(nr):
    #         for ic in range(nc):
    #             print(f'{jac_sparse[ir, ic]:8.0e}', end=', ')
    #         print('')
    #     print('finite difference')
    #     for ir in range(nr):
    #         for ic in range(nc):
    #             print(f'{jac_fd[ir, ic]:8.0e}', end=', ')
    #         print('')
    #     print('diff')
    #     for ir in range(nr):
    #         for ic in range(nc):
    #             print(f'{diff[ir, ic]:8.0e}' if diff[ir, ic] > 1.e-12 else f'{"":8}', end=', ')
    #         print('')
    return pass_sparse_vs_dense_jac
def validate_on_mechanism(mech, temperature, pressure, test_rhs=True, test_jac=True):
    xml = join(test_mech_directory, mech + '.xml')

    T = temperature
    p = pressure

    r = ChemicalMechanismSpec(xml, 'gas').griffon

    gas = Solution(xml)
    ns = gas.n_species

    gas.TPX = T, p, ones(ns)
    y = gas.Y

    state = hstack((T, y[:-1]))

    rhsGR = np.empty(ns)
    r.reactor_rhs_isobaric(state, p, 0., np.ndarray(1), 0, 0, 0, 0, 0, 0, 0, False, rhsGR)

    if test_jac:
        Tin, yin, tau = 0, np.ndarray(1), 0
        rhsTmp = np.empty(ns)
        jacGR = np.empty(ns * ns)
        r.reactor_jac_isobaric(state, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, False, 0, 0, rhsTmp, jacGR)
        jacGR = jacGR.reshape((ns, ns), order='F')

        dT = 1.e-6
        dY = 1.e-6
        jacFD = np.empty((ns, ns))
        rhsGR1, rhsGR2 = np.empty(ns), np.empty(ns)
        state_m = hstack((T - dT, y[:-1]))
        state_p = hstack((T + dT, y[:-1]))
        r.reactor_rhs_isobaric(state_m, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, False, rhsGR1)
        r.reactor_rhs_isobaric(state_p, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, False, rhsGR2)
        jacFD[:, 0] = (- rhsGR1 + rhsGR2) / (2. * dT)

        for i in range(ns - 1):
            y_m1, y_p1 = np.copy(y), np.copy(y)
            y_m1[i] += - dY
            y_m1[-1] -= - dY
            y_p1[i] += dY
            y_p1[-1] -= dY
            state_m = hstack((T, y_m1[:-1]))
            state_p = hstack((T, y_p1[:-1]))
            r.reactor_rhs_isobaric(state_m, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, False, rhsGR1)
            r.reactor_rhs_isobaric(state_p, p, Tin, yin, tau, 0, 0, 0, 0, 0, 0, False, rhsGR2)
            jacFD[:, 1 + i] = (- rhsGR1 + rhsGR2) / (2. * dY)

        pass_jac = max(abs(jacGR - jacFD) / (abs(jacGR) + 1.)) < 1.e-2

    w = gas.net_production_rates * gas.molecular_weights
    h = gas.standard_enthalpies_RT * gas.T * gas_constant / gas.molecular_weights
    rhsCN = zeros(ns)
    rhsCN[1:] = w[:-1] / gas.density
    rhsCN[0] = - sum(w * h) / gas.density / gas.cp_mass
    pass_rhs = max(abs(rhsGR - rhsCN) / (abs(rhsCN) + 1.)) < 100. * sqrt(np.finfo(float).eps)

    if test_rhs and test_jac:
        return pass_rhs and pass_jac
    if test_rhs:
        return pass_rhs
    if test_jac:
        return pass_jac
Example #14
0
def get_kinetic_parameters_from_yaml(
        loaded_yaml: dict,
        gas: ct.Solution) -> Tuple[KineticsCoeffs, KineticsData]:
    """
    Extract Arrhenius, Troe parameters, reaction type indices from loaded YAML file
    returns: tuple containing namedtuples of KineticCoeffs and KineticsData
    Adapted from https://github.com/DENG-MIT/reactorch/blob/master/reactorch/Solution.py 
    """
    reactions = defaultdict(list)
    efficiencies_coeffs = onp.ones((gas.n_species, gas.n_reactions))
    reactant_stoich_coeffs = reactant_orders = gas.reactant_stoich_coeffs()
    arrhenius_coeffs = onp.zeros((gas.n_reactions, 3), dtype=onp.float64)
    arrhenius0_coeffs = onp.zeros((gas.n_reactions, 3), dtype=onp.float64)
    troe_coeffs = onp.zeros((gas.n_reactions, 4), dtype=onp.float64)
    is_reversible = onp.zeros(gas.n_reactions)
    three_body_indices, falloff_indices, troe_falloff_indices = list(), list(
    ), list()
    for i in range(gas.n_reactions):
        reactions[i] = {"equation": gas.reaction_equation(i)}
        reactions[i]["reactants"] = gas.reactants(i)
        reactions[i]["products"] = gas.products(i)
        reactions[i]["reaction_type"] = gas.reaction_type(i)
        if gas.is_reversible(i):
            is_reversible[i] = 1.0
        if gas.reaction_type(i) in [1, 2]:

            reactions[i]["A"] = loaded_yaml["reactions"][i]["rate-constant"][
                "A"]

            reactions[i]["b"] = loaded_yaml["reactions"][i]["rate-constant"][
                "b"]

            if type(loaded_yaml["reactions"][i]["rate-constant"]["Ea"]) is str:
                Ea = onp.float64([
                    loaded_yaml["reactions"][i]["rate-constant"]["Ea"].split(
                        " ")[0]
                ])
            else:
                Ea = loaded_yaml["reactions"][i]["rate-constant"]["Ea"]

            reactions[i]["Ea"] = Ea

        if gas.reaction_type(i) in [2]:
            three_body_indices.append(i)
            if "efficiencies" in loaded_yaml["reactions"][i]:
                reactions[i]["efficiencies"] = loaded_yaml["reactions"][i][
                    "efficiencies"]
                for key, value in reactions[i]["efficiencies"].items():
                    efficiencies_coeffs[gas.species_index(key), i] = value

        if gas.reaction_type(i) in [4]:

            if "efficiencies" in loaded_yaml["reactions"][i]:
                reactions[i]["efficiencies"] = loaded_yaml["reactions"][i][
                    "efficiencies"]
                for key, value in reactions[i]["efficiencies"].items():
                    efficiencies_coeffs[gas.species_index(key), i] = value

            high_p = loaded_yaml["reactions"][i]["high-P-rate-constant"]

            low_p = loaded_yaml["reactions"][i]["low-P-rate-constant"]

            reactions[i]["A"] = high_p["A"]

            reactions[i]["b"] = high_p["b"]

            if type(high_p["Ea"]) is str:
                high_Ea = onp.float64([high_p["Ea"].split(" ")[0]])
            else:
                high_Ea = high_p["Ea"]

            reactions[i]["Ea"] = high_Ea

            reactions[i]["A_0"] = low_p["A"]

            reactions[i]["b_0"] = low_p["b"]

            if type(low_p["Ea"]) is str:
                low_Ea = onp.float64([low_p["Ea"].split(" ")[0]])
            else:
                low_Ea = low_p["Ea"]

            reactions[i]["Ea_0"] = low_Ea

            if "Troe" in loaded_yaml["reactions"][i]:
                troe_falloff_indices.append(i)
                Troe = loaded_yaml["reactions"][i]["Troe"]
                if "T2" in loaded_yaml["reactions"][i]["Troe"]:
                    reactions[i]["Troe"] = {
                        "A": Troe["A"],
                        "T1": Troe["T1"],
                        "T2": Troe["T2"],
                        "T3": Troe["T3"],
                    }
                    troe_coeffs[i, 0] = Troe["A"]
                    troe_coeffs[i, 1] = Troe["T1"]
                    troe_coeffs[i, 2] = Troe["T2"]
                    troe_coeffs[i, 3] = Troe["T3"]
                else:
                    reactions[i]["Troe"] = {
                        "A": Troe["A"],
                        "T1": Troe["T1"],
                        "T3": Troe["T3"],
                    }
                    troe_coeffs[i, 0] = Troe["A"]
                    troe_coeffs[i, 1] = Troe["T1"]
                    troe_coeffs[i, 2] = 0.0
                    troe_coeffs[i, 3] = Troe["T3"]
            else:
                falloff_indices.append(i)

        if "orders" in loaded_yaml["reactions"][i]:
            for key, value in loaded_yaml["reactions"][i]["orders"].items():
                reactant_orders[gas.species_index(key), i] = value

        if "units" in loaded_yaml:
            if (loaded_yaml["units"]["length"] == "cm"
                    and loaded_yaml["units"]["quantity"] == "mol"):
                reactions[i]["A"] *= (1e-3)**(
                    reactant_stoich_coeffs[:, i].sum() - 1)

                if gas.reaction_type(i) in [2]:
                    reactions[i]["A"] *= 1e-3

                if gas.reaction_type(i) in [4]:
                    reactions[i]["A_0"] *= 1e-3
                    reactions[i]["A_0"] *= (1e-3)**(
                        reactant_stoich_coeffs[:, i].sum() - 1)
                    arrhenius0_coeffs[i, 0] = reactions[i]["A_0"]
                    arrhenius0_coeffs[i, 1] = reactions[i]["b_0"]
                    arrhenius0_coeffs[i, 2] = reactions[i]["Ea_0"]

        arrhenius_coeffs[i, 0] = reactions[i]["A"]
        arrhenius_coeffs[i, 1] = reactions[i]["b"]
        arrhenius_coeffs[i, 2] = reactions[i]["Ea"]
        kinetics_coeffs = KineticsCoeffs(
            arrhenius_coeffs=np.array(arrhenius_coeffs, dtype=np.float64),
            arrhenius0_coeffs=np.array(arrhenius0_coeffs, dtype=np.float64),
            troe_coeffs=np.array(troe_coeffs, dtype=np.float64),
            efficiency_coeffs=np.array(efficiencies_coeffs, dtype=np.float64),
        )
        kinetics_data = KineticsData(
            three_body_indices=np.array(three_body_indices, dtype=np.int64),
            falloff_indices=np.array(falloff_indices, dtype=np.int64),
            troe_falloff_indices=np.array(troe_falloff_indices,
                                          dtype=np.int64),
            is_reversible=np.array(is_reversible, dtype=np.int64),
        )
    return kinetics_coeffs, kinetics_data
Example #15
0
    def _extract_cantera_mechanism_data(cls, ctsol: ct.Solution):
        ct_element_mw_map = cls._get_cantera_element_mw_map(ctsol)
        elem_list = ctsol.element_names
        ref_temperature = 298.15
        ref_pressure = ctsol.reference_pressure
        spec_name_list = list()
        spec_dict = dict()
        reac_temporary_list = list()
        # todo: add error checking
        for i in range(ctsol.n_species):
            sp = ctsol.species(i)

            spec_name_list.append(sp.name)

            if isinstance(sp.thermo, ct.ConstantCp):
                spec_dict[sp.name] = dict({
                    'atoms':
                    sp.composition,
                    'heat-capacity':
                    dict({
                        'type': 'constant',
                        'Tmin': sp.thermo.min_temp,
                        'Tmax': sp.thermo.max_temp,
                        'T0': sp.thermo.coeffs[0],
                        'h0': sp.thermo.coeffs[1],
                        's0': sp.thermo.coeffs[2],
                        'cp': sp.thermo.coeffs[3]
                    })
                })
            elif isinstance(sp.thermo, ct.NasaPoly2):
                spec_dict[sp.name] = dict({
                    'atoms':
                    sp.composition,
                    'heat-capacity':
                    dict({
                        'type': 'NASA7',
                        'Tmin': sp.thermo.min_temp,
                        'Tmid': sp.thermo.coeffs[0],
                        'Tmax': sp.thermo.max_temp,
                        'low-coeffs': sp.thermo.coeffs[8:],
                        'high-coeffs': sp.thermo.coeffs[1:8]
                    })
                })

        for i in range(ctsol.n_reactions):
            rx = ctsol.reaction(i)
            if isinstance(rx, ct.FalloffReaction):
                f = rx.falloff
                if isinstance(f, ct.TroeFalloff):
                    reac_temporary_list.append(
                        (3,
                         dict({
                             'type': 'Troe',
                             'reversible': rx.reversible,
                             'reactants': rx.reactants,
                             'products': rx.products,
                             'default-eff': rx.default_efficiency,
                             'efficiencies': rx.efficiencies,
                             'fwd-A': rx.high_rate.pre_exponential_factor,
                             'fwd-b': rx.high_rate.temperature_exponent,
                             'fwd-Ea': rx.high_rate.activation_energy,
                             'flf-A': rx.low_rate.pre_exponential_factor,
                             'flf-b': rx.low_rate.temperature_exponent,
                             'flf-Ea': rx.low_rate.activation_energy,
                             'Troe-params': rx.falloff.parameters
                         })))
                    if rx.orders:
                        reac_temporary_list[-1][1]['orders'] = rx.orders
                else:
                    reac_temporary_list.append(
                        (2,
                         dict({
                             'type': 'Lindemann',
                             'reversible': rx.reversible,
                             'reactants': rx.reactants,
                             'products': rx.products,
                             'default-eff': rx.default_efficiency,
                             'efficiencies': rx.efficiencies,
                             'fwd-A': rx.high_rate.pre_exponential_factor,
                             'fwd-b': rx.high_rate.temperature_exponent,
                             'fwd-Ea': rx.high_rate.activation_energy,
                             'flf-A': rx.low_rate.pre_exponential_factor,
                             'flf-b': rx.low_rate.temperature_exponent,
                             'flf-Ea': rx.low_rate.activation_energy
                         })))
                    if rx.orders:
                        reac_temporary_list[-1][1]['orders'] = rx.orders
            elif isinstance(rx, ct.ThreeBodyReaction):
                reac_temporary_list.append((1,
                                            dict({
                                                'type':
                                                'three-body',
                                                'reversible':
                                                rx.reversible,
                                                'reactants':
                                                rx.reactants,
                                                'products':
                                                rx.products,
                                                'default-eff':
                                                rx.default_efficiency,
                                                'efficiencies':
                                                rx.efficiencies,
                                                'A':
                                                rx.rate.pre_exponential_factor,
                                                'b':
                                                rx.rate.temperature_exponent,
                                                'Ea':
                                                rx.rate.activation_energy
                                            })))
                if rx.orders:
                    reac_temporary_list[-1][1]['orders'] = rx.orders
            elif isinstance(rx, ct.ElementaryReaction):
                reac_temporary_list.append((0,
                                            dict({
                                                'type':
                                                'simple',
                                                'reversible':
                                                rx.reversible,
                                                'reactants':
                                                rx.reactants,
                                                'products':
                                                rx.products,
                                                'A':
                                                rx.rate.pre_exponential_factor,
                                                'b':
                                                rx.rate.temperature_exponent,
                                                'Ea':
                                                rx.rate.activation_energy
                                            })))
                if rx.orders:
                    reac_temporary_list[-1][1]['orders'] = rx.orders
        reac_list = [
            y[1] for y in sorted(reac_temporary_list, key=lambda x: x[0])
        ]
        return ct_element_mw_map, elem_list, ref_temperature, ref_pressure, spec_name_list, spec_dict, reac_list
Example #16
0
def validate_on_mechanism(mech, temperature, pressure, tau, do_rhs, do_jac):
    xml = join(test_mech_directory, mech + '.xml')
    T = temperature
    Tin = T + 1000.
    p = pressure

    r = ChemicalMechanismSpec(xml, 'gas').griffon

    gas = Solution(xml)
    ns = gas.n_species

    y = np.ones(ns)  # equal masses in the reactor
    gas.TPY = T, p, y
    y = np.copy(gas.Y)
    rho = gas.density_mass

    xin = np.ones(ns)  # equal moles in the feed
    gas.TPX = Tin, p, xin
    yin = np.copy(gas.Y)
    rhoin = gas.density_mass

    state = hstack((rho, T, y[:-1]))

    rhsGRChemOnly = np.zeros(ns + 1)
    r.reactor_rhs_isochoric(state, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0, 0,
                            False, rhsGRChemOnly)
    rhsCN = rhs_cantera(p, T, y, rhoin, Tin, yin, tau, gas, rhsGRChemOnly)
    rhsGR = np.empty(ns + 1)
    r.reactor_rhs_isochoric(state, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0, 0,
                            True, rhsGR)

    if do_rhs:
        return max(abs(rhsGR - rhsCN) /
                   (abs(rhsCN) + 1.)) < 100. * sqrt(np.finfo(float).eps)

    if do_jac:
        jacGR = np.empty((ns + 1) * (ns + 1))
        r.reactor_jac_isochoric(state, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0, 0,
                                True, 0, rhsGR, jacGR)
        jacGR = jacGR.reshape((ns + 1, ns + 1), order='F')

        drho = 1.e-6
        dT = 1.e-6
        dY = 1.e-6
        jacFD = np.empty((ns + 1, ns + 1))
        rhsGR1, rhsGR2 = np.empty(ns + 1), np.empty(ns + 1)

        state_m = hstack((rho - drho, T, y[:-1]))
        state_p = hstack((rho + drho, T, y[:-1]))
        r.reactor_rhs_isochoric(state_m, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0,
                                0, True, rhsGR1)
        r.reactor_rhs_isochoric(state_p, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0,
                                0, True, rhsGR2)
        jacFD[:, 0] = (-rhsGR1 + rhsGR2) / (2. * drho)

        state_m = hstack((rho, T - dT, y[:-1]))
        state_p = hstack((rho, T + dT, y[:-1]))
        r.reactor_rhs_isochoric(state_m, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0,
                                0, True, rhsGR1)
        r.reactor_rhs_isochoric(state_p, rhoin, Tin, yin, tau, 0, 0, 0, 0, 0,
                                0, True, rhsGR2)
        jacFD[:, 1] = (-rhsGR1 + rhsGR2) / (2. * dT)

        for i in range(ns - 1):
            y_m1, y_p1 = np.copy(y), np.copy(y)
            y_m1[i] += -dY
            y_m1[-1] -= -dY
            y_p1[i] += dY
            y_p1[-1] -= dY
            state_m = hstack((rho, T, y_m1[:-1]))
            state_p = hstack((rho, T, y_p1[:-1]))
            r.reactor_rhs_isochoric(state_m, rhoin, Tin, yin, tau, 0, 0, 0, 0,
                                    0, 0, True, rhsGR1)
            r.reactor_rhs_isochoric(state_p, rhoin, Tin, yin, tau, 0, 0, 0, 0,
                                    0, 0, True, rhsGR2)
            jacFD[:, 2 + i] = (-rhsGR1 + rhsGR2) / (2. * dY)

        return max(abs(jacGR - jacFD) / (abs(jacGR) + 1.)) < 1.e-4
Example #17
0
def validate_on_mechanism(mech,
                          temperature,
                          pressure,
                          test_rhs=True,
                          test_jac=True):
    xml = join(test_mech_directory, mech + '.xml')

    r = ChemicalMechanismSpec(xml, 'gas').griffon

    gas = Solution(xml)
    ns = gas.n_species

    T = temperature
    p = pressure

    gas.TPX = T, p, ones(ns)
    y = gas.Y
    rho = gas.density_mass

    state = hstack((rho, T, y[:-1]))

    rhsGR = np.empty(ns + 1)
    rhsGRTemporary = np.empty(ns + 1)
    jacGR = np.empty((ns + 1) * (ns + 1))
    r.reactor_rhs_isochoric(state, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0, 0,
                            False, rhsGR)
    r.reactor_jac_isochoric(state, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0, 0,
                            False, 0, rhsGRTemporary, jacGR)
    jacGR = jacGR.reshape((ns + 1, ns + 1), order='F')

    def cantera_rhs(rho_arg, T_arg, Y_arg):
        gas.TDY = T_arg, rho_arg, Y_arg
        w = gas.net_production_rates * gas.molecular_weights
        e = gas.standard_int_energies_RT * gas.T * gas_constant / gas.molecular_weights
        cv = gas.cv_mass
        rhs = zeros(ns + 1)
        rhs[0] = 0.
        rhs[1] = -sum(w * e) / (rho_arg * cv)
        rhs[2:] = w[:-1] / rho
        return rhs

    rhsCN = cantera_rhs(rho, T, y)

    if test_rhs:
        pass_rhs = max(abs(rhsGR - rhsCN) /
                       (abs(rhsCN) + 1.)) < 100. * sqrt(np.finfo(float).eps)

    if test_jac:
        jacFD = zeros((ns + 1, ns + 1))
        wm1 = zeros(ns + 1)
        wp1 = zeros(ns + 1)
        drho = 1.e-4
        dT = 1.e-2
        dY = 1.e-6

        state_m = hstack((rho - drho, T, y[:-1]))
        state_p = hstack((rho + drho, T, y[:-1]))
        r.reactor_rhs_isochoric(state_m, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, wm1)
        r.reactor_rhs_isochoric(state_p, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, wp1)
        jacFD[:, 0] = (-wm1 + wp1) / (2. * drho)

        state_m = hstack((rho, T - dT, y[:-1]))
        state_p = hstack((rho, T + dT, y[:-1]))
        r.reactor_rhs_isochoric(state_m, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, wm1)
        r.reactor_rhs_isochoric(state_p, 0, 0, np.ndarray(1), 0, 0, 0, 0, 0, 0,
                                0, False, wp1)
        jacFD[:, 1] = (-wm1 + wp1) / (2. * dT)

        for i in range(ns - 1):
            y_m1, y_p1 = copy(y), copy(y)
            y_m1[i] += -dY
            y_m1[-1] -= -dY
            y_p1[i] += dY
            y_p1[-1] -= dY
            state_m = hstack((rho, T, y_m1[:-1]))
            state_p = hstack((rho, T, y_p1[:-1]))
            r.reactor_rhs_isochoric(state_m, 0, 0, np.ndarray(1), 0, 0, 0, 0,
                                    0, 0, 0, False, wm1)
            r.reactor_rhs_isochoric(state_p, 0, 0, np.ndarray(1), 0, 0, 0, 0,
                                    0, 0, 0, False, wp1)
            jacFD[:, 2 + i] = (-wm1 + wp1) / (2. * dY)

        gas.TDY = T, rho, y
        cv = gas.cv_mass
        cvi = gas.standard_cp_R * gas_constant / gas.molecular_weights
        w = gas.net_production_rates * gas.molecular_weights
        e = gas.standard_int_energies_RT * gas.T * gas_constant / gas.molecular_weights

        gas.TDY = T + dT, rho, y
        wp = gas.net_production_rates * gas.molecular_weights
        cvp = gas.cv_mass

        gas.TDY = T - dT, rho, y
        wm = gas.net_production_rates * gas.molecular_weights
        cvm = gas.cv_mass

        wsensT = (wp - wm) / (2. * dT)
        cvsensT = (cvp - cvm) / (2. * dT)

        jacFD11 = np.copy(jacFD[1, 1])
        jacSemiFD11 = -1. / cv * (1. / rho * (sum(wsensT * e) + sum(cvi * w)) +
                                  cvsensT * rhsGR[1])
        pass_jac = max(abs(jacGR - jacFD) / (abs(jacGR) + 1.)) < 1.e-4

    if test_rhs:
        return pass_rhs
    if test_jac:
        if not pass_jac:
            print(jacGR[1, 1])
            print(jacSemiFD11)
            print(jacFD11)
            print(abs(jacGR - jacFD) / (abs(jacGR) + 1.))
        return pass_jac