diff --git a/chemicals/reaction.py b/chemicals/reaction.py index a8806c4..d16e065 100644 --- a/chemicals/reaction.py +++ b/chemicals/reaction.py @@ -75,6 +75,7 @@ ------------------ .. autofunction:: chemicals.reaction.balance_stoichiometry .. autofunction:: chemicals.reaction.stoichiometric_matrix +.. autofunction:: chemicals.reaction.standard_formation_reaction """ __all__ = ['Hfg', 'Hfl', 'Hfs', 'S0g', 'S0l', 'S0s', @@ -83,12 +84,13 @@ 'Hfl_all_methods', 'Hfg_all_methods', 'Hfs_all_methods', 'S0l_all_methods', 'S0g_all_methods', 'S0s_all_methods', 'Gibbs_formation', 'entropy_formation', 'Hf_basis_converter', - 'balance_stoichiometry', 'stoichiometric_matrix'] + 'balance_stoichiometry', 'stoichiometric_matrix', 'standard_formation_reaction'] from math import ceil, log10 from chemicals import data_reader as dr from chemicals import heat_capacity, miscdata +from chemicals.elements import periodic_table, simple_formula_parser from chemicals.data_reader import ( data_source, database_constant_lookup, @@ -1074,3 +1076,63 @@ def balance_stoichiometry(matrix, rounding=9, allow_fractional=False): return d +def standard_formation_reaction(atoms): + r'''This function calculates the standard reaction to reduce a chemical + compound to its standard state elements. Any hydrogen in the compound + is transformed to H2; oxygen to O2; carbon to graphite (single C), calcium + to Ca, etc. + + Parameters + ---------- + atoms : dict[(str, float)] + A dictionary of (element, element_count) pairs for the reacting + compound, [-] + + Returns + ------- + reactant_coeff : float + The coefficient of the reactant; for compounds like CO that do not + divide evenly, this will be something other than 1 [-] + elemental_counts : list[float] + Balanced coefficients of each of the products, [-] + product_atomss : list[dict[(str, float)]] + A list of dictionaries of the elements produced, and how many atoms + of each element are in one unit of the element in its + standard form. Each dictionary contains a single key:value, with the key + being the element and the value being either 1 or 2 depending on the + standard state [-] + + Examples + -------- + Methane + + >>> standard_formation_reaction({'C': 1, 'H': 4}) + (1.0, [1.0, 2.0], [{'C': 1}, {'H': 2}]) + + Carbon monoxide + + >>> standard_formation_reaction({'C': 1, 'O': 1}) + (2.0, [2.0, 1.0], [{'C': 1}, {'O': 2}]) + + Methylamine + + >>> standard_formation_reaction({'C': 1, 'H': 5, 'N': 1}) + (2.0, [2.0, 5.0, 1.0], [{'C': 1}, {'H': 2}, {'N': 2}]) + + ''' + + product_atomss = [] + reactants = [] + for atom in atoms: + ele = periodic_table[atom] + ele_atoms = simple_formula_parser(ele.formula_standard) + product_atomss.append(ele_atoms) + reactants.append(True) + + atoms_to_process = product_atomss + [atoms] + reactants.append(False) + matrix = stoichiometric_matrix(atoms_to_process, reactants) + coeffs = balance_stoichiometry(matrix) + reactant_coeff = coeffs[-1] + elemental_counts = coeffs[:-1] + return reactant_coeff, elemental_counts, product_atomss diff --git a/tests/test_reaction.py b/tests/test_reaction.py index 6ccf690..5ba7d92 100644 --- a/tests/test_reaction.py +++ b/tests/test_reaction.py @@ -28,7 +28,8 @@ from chemicals.reaction import (Gibbs_formation, Hf_basis_converter, Hfg, Hfg_all_methods, Hfg_methods, Hfl, Hfl_methods, Hfs, Hfs_methods, S0g, S0g_all_methods, S0g_methods, S0l, S0l_methods, S0s, S0s_methods, - balance_stoichiometry, entropy_formation, stoichiometric_matrix) + balance_stoichiometry, entropy_formation, stoichiometric_matrix, + standard_formation_reaction) from chemicals.heat_capacity import TRC_gas_data, CRC_standard_data from chemicals.reaction import Hfg_API_TDB_data, Hfg_ATcT_data, Hfl_ATcT_data, Hfg_S0g_YAWS_data @@ -205,4 +206,30 @@ def test_balance_stoichiometry(): def test_stoichiometric_matrix(): res = stoichiometric_matrix([{'Mg': 1, 'O': 1}, {'Mg': 1}, {'O': 2}], [True, False, False]) - assert_close2d([[1, -1, 0], [1, 0, -2]], res) \ No newline at end of file + assert_close2d([[1, -1, 0], [1, 0, -2]], res) + + +def test_standard_formation_reaction(): + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 3, 'H': 8}) + assert coeff_test == [3.0, 4.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}] + + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 3, 'H': 7, 'N': 1, 'O': 2, 'S': 1}) + assert coeff_test == [6.0, 7.0, 1.0, 2.0, 2.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}, {'N': 2}, {'O': 2}, {'S': 1}] + + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 6, 'H': 7, 'B': 1, 'O': 2}) + assert coeff_test == [12.0, 7.0, 2.0, 2.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}, {'B': 1}, {'O': 2}] + + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 4, 'H': 12, 'Si': 1}) + assert coeff_test == [4.0, 6.0, 1.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}, {'Si': 1}] + + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 12, 'H': 10, 'Cl': 1, 'P': 1}) + assert coeff_test == [24.0, 10.0, 1.0, 2.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}, {'Cl': 2}, {'P': 1}] + + reactant_coeff, coeff_test, reactant_atomss_test = standard_formation_reaction({'C': 2, 'H': 4, 'Br': 1, 'F': 1}) + assert coeff_test == [4.0, 4.0, 1.0, 1.0] + assert reactant_atomss_test == [{'C': 1}, {'H': 2}, {'Br': 2}, {'F': 2}]