def test_ShiftedTPoly_MassAction(): rate = MassAction(ShiftedTPoly([100, 2, 5, 7])) assert rate.args[0].args == [100, 2, 5, 7] r = Reaction({'A': 2, 'B': 1}, {'P': 1}, rate) res = r.rate_expr()({'A': 11, 'B': 13, 'temperature': 273.15}, reaction=r) x = 273.15-100 ref = 11*11*13*(2 + 5*x + 7*x**2) assert abs((res - ref)/ref) < 1e-14
def test_Expr__from_callback(): def rate_coeff(args, T, reaction, backend=math): return args[0]*backend.exp(args[1]/T) RateExpr = Expr.from_callback(rate_coeff, parameter_keys=('Tem',), nargs=2) k1 = RateExpr([2.1e10, -5132.2]) rxn = Reaction({'H2': 2, 'O2': 1}, {'H2O': 2}, MassAction(k1)) ma = rxn.rate_expr() res = ma({'Tem': 273.15, 'H2': 7, 'O2': 13}, reaction=rxn) ref = 7*7*13*2.1e10*math.exp(-5132.2/273.15) assert abs((res-ref)/ref) < 1e-14
def test_MassAction__subclass_from_callback(): def rate_coeff(variables, all_args, reaction, backend): return all_args[0]*backend.exp(all_args[1]/variables['temperature']) CustomMassAction = MassAction.subclass_from_callback( rate_coeff, cls_attrs=dict(parameter_keys=('temperature',), nargs=2)) k1 = CustomMassAction([2.1e10, -5132.2]) rxn = Reaction({'H2': 2, 'O2': 1}, {'H2O': 2}, k1) cma = rxn.rate_expr() res = cma({'temperature': 273.15, 'H2': 7, 'O2': 13}, reaction=rxn) ref = 7*7*13*2.1e10*math.exp(-5132.2/273.15) assert abs((res-ref)/ref) < 1e-14
def test_get_ode__ArrheniusParam(): rxn = Reaction({'A': 1}, {'B': 1}, None) rxn.param = ArrheniusParam(1e10, 40e3) rsys = ReactionSystem([rxn], 'A B') odesys = get_odesys(rsys, include_params=True)[0] conc = {'A': 3, 'B': 5} x, y, p = odesys.to_arrays(-37, conc, {'temperature': 200}) fout = odesys.f_cb(x, y, p) ref = 3*1e10*np.exp(-40e3/8.314472/200) assert np.all(abs((fout[:, 0] + ref)/ref) < 1e-14) assert np.all(abs((fout[:, 1] - ref)/ref) < 1e-14)
def test_MassAction__rate_coeff(): perMolar_perSecond = u.perMolar_perSecond p1 = MassAction(Constant(perMolar_perSecond) * 10**RTPoly([1, 2*u.kelvin, 3*u.kelvin**2])) rcoeff1 = p1.rate_coeff({'temperature': 283.15*u.K}) ref1 = 10**(1 + 2/283.15 + 3/283.15**2) * perMolar_perSecond assert allclose(rcoeff1, ref1) rxn1 = Reaction({'A', 'B'}, {'C'}, p1) rat1 = rxn1.rate({'A': 2, 'B': 3, 'temperature': 283.15*u.K}) assert allclose(rat1['A'], -2*3*ref1) assert allclose(rat1['B'], -2*3*ref1) assert allclose(rat1['C'], 2*3*ref1)
def test_RateExpr__subclass_from_callback(): SF = RateExpr.subclass_from_callback( lambda v, a, backend: a[0]*v['H2']*v['Br2']**(3/2) / (v['Br2'] + a[1]*v['HBr']) ) ratex = SF([11, 13], ['k_HBr', 'kprime_HBr']) r = Reaction({'H2': 1, 'Br2': 1}, {'HBr': 2}, ratex) res1 = r.rate_expr()({'H2': 5, 'Br2': 7, 'HBr': 15}) ref1 = 11*5*7**1.5/(7+13*15) assert abs((res1-ref1)/ref1) < 1e-14 res2 = r.rate_expr()({'H2': 5, 'Br2': 7, 'HBr': 15, 'k_HBr': 23, 'kprime_HBr': 42}) ref2 = 23*5*7**1.5/(7+42*15) assert abs((res2-ref2)/ref2) < 1e-14
def test_mk_Radiolytic(): R1 = mk_Radiolytic() R2 = mk_Radiolytic() assert R1 is R2 RABG = mk_Radiolytic('alpha', 'beta', 'gamma') rxn = Reaction({}, {'H': 2}, RABG([3, 5, 7], 'ya yb yg'.split())) rat = rxn.rate({'doserate_alpha': 11, 'doserate_beta': 13, 'doserate_gamma': 17, 'density': .7}) assert abs(rat['H'] - .7*2*(3*11 + 5*13 + 7*17)) < 1e-13 assert RABG.parameter_keys == ('density', 'doserate_alpha', 'doserate_beta', 'doserate_gamma') assert RABG.argument_names == tuple('radiolytic_yield_%s' % k for k in 'alpha beta gamma'.split()) assert rxn.param.unique_keys == ('ya', 'yb', 'yg') rat2 = rxn.rate({'doserate_alpha': 11, 'doserate_beta': 13, 'doserate_gamma': 17, 'density': .7, 'ya': 23, 'yb': 29, 'yg': 31}) assert abs(rat2['H'] - .7*2*(23*11 + 29*13 + 31*17)) < 1e-13
def test_MassAction__subclass_from_callback__units(): def rate_coeff(variables, all_args, backend, **kwargs): return all_args[0]*backend.exp(all_args[1]/variables['temperature']) CustomMassAction = MassAction.subclass_from_callback( rate_coeff, cls_attrs=dict(parameter_keys=('temperature',), nargs=2)) k1 = CustomMassAction([2.1e10/u.molar**2/u.second, -5132.2*u.kelvin]) rxn = Reaction({'H2': 2, 'O2': 1}, {'H2O': 2}, k1) variables = { 'temperature': 491.67*u.rankine, 'H2': 7000*u.mol/u.metre**3, 'O2': 13*u.molar } cma = rxn.rate_expr() res = cma(variables, backend=Backend(), reaction=rxn) ref = 7*7*13*2.1e10*math.exp(-5132.2/273.15) * u.molar/u.second assert allclose(res, ref)
def test_MassAction(): ma = MassAction([3.14], ['my_rate']) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, ma, {'B': 1}) arg1 = {'A': 11, 'B': 13, 'C': 17} arg2 = {'A': 11, 'B': 13, 'C': 17, 'my_rate': 2.72} res1 = r.rate_expr()(arg1, reaction=r) res2 = r.rate_expr()(arg2, reaction=r) ref1 = 3.14*13*11**2 ref2 = 2.72*13*11**2 assert abs(res1 - ref1) < 1e-14 assert abs(res2 - ref2) < 1e-12 rat1 = r.rate(arg1) rat2 = r.rate(arg2) for key, coeff in [('A', -2), ('B', -2), ('C', 1)]: assert abs(rat1[key] - ref1*coeff) < 2e-12 assert abs(rat2[key] - ref2*coeff) < 2e-12
def test_Radiolytic__parsing(): rxn = Reaction.from_string("-> H + OH; Radiolytic({'radiolytic_yield': 2.1e-7})", None) res = rxn.rate({'doserate': 0.15, 'density': 0.998}) ref = 0.15*0.998*2.1e-7 assert abs((res['H'] - ref)/ref) < 1e-15 assert abs((res['OH'] - ref)/ref) < 1e-15 gval, = rxn.rate_expr().g_values({}).values() assert abs(gval - 2.1e-7) < 1e-15
def test_Radiolytic__parsing__units(): rxn = Reaction.from_string("-> H + OH; Radiolytic({'radiolytic_yield': 2.1e-7*mol/J})", None) assert rxn.reac == {} assert rxn.prod == {'H': 1, 'OH': 1} res = rxn.rate({'doserate': 0.15*u.gray/u.s, 'density': 0.998*u.kg/u.dm3}) ref = 0.15*0.998*2.1e-7*u.molar/u.second assert abs((res['H'] - ref)/ref) < 1e-15 assert abs((res['OH'] - ref)/ref) < 1e-15
def test_ArrheniusMassAction__units(): A, Ea_over_R = 1.2e11 / u.molar**2 / u.second, 40e3 / 8.3145 * u.kelvin ama = MassAction(Arrhenius([A, Ea_over_R])) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, ama, {'B': 1}) T_ = 'temperature' def ref(v): return 1.2e11 / u.molar**2 / u.second * math.exp( -Ea_over_R / v[T_]) * v['B'] * v['A']**2 ma = r.rate_expr() for params in [(11. * u.molar, 13. * u.molar, 17. * u.molar, 311.2 * u.kelvin), (12 * u.molar, 8 * u.molar, 5 * u.molar, 270 * u.kelvin)]: var = dict(zip(['A', 'B', 'C', T_], params)) ref_val = ref(var) assert abs((ma(var, reaction=r) - ref_val) / ref_val) < 1e-14
def test_Radiolytic__parsing(): rxn = Reaction.from_string( "-> H + OH; Radiolytic({'radiolytic_yield': 2.1e-7})", None) res = rxn.rate({'doserate': 0.15, 'density': 0.998}) ref = 0.15 * 0.998 * 2.1e-7 assert abs((res['H'] - ref) / ref) < 1e-15 assert abs((res['OH'] - ref) / ref) < 1e-15 gval, = rxn.rate_expr().g_values({}).values() assert abs(gval - 2.1e-7) < 1e-15
def test_MassAction__subclass_from_callback__units(): def rate_coeff(variables, all_args, backend, **kwargs): return all_args[0] * backend.exp( all_args[1] / variables['temperature']) CustomMassAction = MassAction.subclass_from_callback( rate_coeff, cls_attrs=dict(parameter_keys=('temperature', ), nargs=2)) k1 = CustomMassAction([2.1e10 / u.molar**2 / u.second, -5132.2 * u.kelvin]) rxn = Reaction({'H2': 2, 'O2': 1}, {'H2O': 2}, k1) variables = { 'temperature': 491.67 * u.rankine, 'H2': 7000 * u.mol / u.metre**3, 'O2': 13 * u.molar } cma = rxn.rate_expr() res = cma(variables, backend=Backend(), reaction=rxn) ref = 7 * 7 * 13 * 2.1e10 * math.exp(-5132.2 / 273.15) * u.molar / u.second assert allclose(res, ref)
def test_ArrheniusMassAction(): A, Ea_over_R = 1.2e11, 40e3/8.3145 ama = MassAction(Arrhenius([A, Ea_over_R])) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, ama, {'B': 1}) T_ = 'temperature' def ref(v): return 1.2e11*math.exp(-Ea_over_R/v[T_])*v['B']*v['A']**2 ma = r.rate_expr() for params in [(11., 13., 17., 311.2), (12, 8, 5, 270)]: var = dict(zip(['A', 'B', 'C', T_], params)) ref_var = ref(var) assert abs((ma(var, reaction=r) - ref_var)/ref_var) < 1e-14 with pytest.raises(ValueError): Arrhenius([A, Ea_over_R, 1, A])
def test_MassAction__subclass_from_callback(): def rate_coeff(variables, all_args, backend): return all_args[0]*backend.exp(all_args[1]/variables['temperature']) CustomMassAction = MassAction.subclass_from_callback( rate_coeff, cls_attrs=dict(parameter_keys=('temperature',), nargs=2)) k1 = CustomMassAction([2.1e10, -5132.2], rxn=Reaction({'H2': 2, 'O2': 1}, {'H2O': 2})) res = k1({'temperature': 273.15, 'H2': 7, 'O2': 13}) ref = 7*7*13*2.1e10*math.exp(-5132.2/273.15) assert abs((res-ref)/ref) < 1e-14
def test_RateExpr__subclass_from_callback(): SF = RateExpr.subclass_from_callback(lambda v, a, backend: a[0] * v[ "H2"] * v["Br2"]**(3 / 2) / (v["Br2"] + a[1] * v["HBr"])) ratex = SF([11, 13], ["k_HBr", "kprime_HBr"]) r = Reaction({"H2": 1, "Br2": 1}, {"HBr": 2}, ratex) res1 = r.rate_expr()({"H2": 5, "Br2": 7, "HBr": 15}) ref1 = 11 * 5 * 7**1.5 / (7 + 13 * 15) assert abs((res1 - ref1) / ref1) < 1e-14 res2 = r.rate_expr()({ "H2": 5, "Br2": 7, "HBr": 15, "k_HBr": 23, "kprime_HBr": 42 }) ref2 = 23 * 5 * 7**1.5 / (7 + 42 * 15) assert abs((res2 - ref2) / ref2) < 1e-14
def test_RateExpr__subclass_from_callback(): SF = RateExpr.subclass_from_callback(lambda v, a, backend: a[0] * v[ 'H2'] * v['Br2']**(3 / 2) / (v['Br2'] + a[1] * v['HBr'])) ratex = SF([11, 13], ['k_HBr', 'kprime_HBr']) r = Reaction({'H2': 1, 'Br2': 1}, {'HBr': 2}, ratex) res1 = r.rate_expr()({'H2': 5, 'Br2': 7, 'HBr': 15}) ref1 = 11 * 5 * 7**1.5 / (7 + 13 * 15) assert abs((res1 - ref1) / ref1) < 1e-14 res2 = r.rate_expr()({ 'H2': 5, 'Br2': 7, 'HBr': 15, 'k_HBr': 23, 'kprime_HBr': 42 }) ref2 = 23 * 5 * 7**1.5 / (7 + 42 * 15) assert abs((res2 - ref2) / ref2) < 1e-14
def test_TPolyInLog10MassAction(): p = MassAction(ShiftedLog10TPoly([2, 0.3, .2, .03, .004])) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, p, {'B': 1}) lgT = Log10('temperature') lgTref = Log10('Tref') res = p({'A': 11, 'B': 13, 'temperature': 298.15, 'log10_temperature': lgT, 'log10_Tref': lgTref}, reaction=r) _T = math.log10(298.15) - 2 ref = .3 + .2*_T + 0.03 * _T**2 + 0.004 * _T**3 assert abs(res - ref*13*11**2) < 1e-15
def test_get_ode__Radiolytic(): rad = Radiolytic([2.4e-7]) rxn = Reaction({"A": 4, "B": 1}, {"C": 3, "D": 2}, rad) rsys = ReactionSystem([rxn], "A B C D") odesys = get_odesys(rsys, include_params=True)[0] c = {"A": 3, "B": 5, "C": 11, "D": 13} x, y, p = odesys.to_arrays(-37, c, {"doserate": 0.4, "density": 0.998}) fout = odesys.f_cb(x, y, p) r = 2.4e-7 * 0.4 * 0.998 ref = [-4 * r, -r, 3 * r, 2 * r] assert np.all(abs((fout - ref) / ref) < 1e-14)
def test_Log10PiecewiseRTPolyMassAction(): p1 = RTPoly([0, 12.281, -3.768e2, -6.673e4, -1.075e7]) p2 = RTPoly([0, -47.532, 4.92, -1.036, 0.0]) bounds = [(293.15, 423.15), (423.15, 623.15)] k_unit = 1 ratex = Log10PiecewiseRTPolyMassAction.from_polynomials( bounds, [p1, p2], [k_unit]) Reaction({'e-(aq)': 2}, {'H2': 1, 'OH-': 2}, ratex, {'H2O': 2}) res = ratex({'e-(aq)': 1e-13, 'temperature': 293.15}) ref = 6.20e9 * 1e-26 assert abs((res - ref) / ref) < 6e-3
def test_get_ode__TPoly(): rate = MassAction(ShiftedTPoly([273.15*u.K, 10/u.molar/u.s, 2/u.molar/u.s/u.K])) rxn = Reaction({'A': 1, 'B': 1}, {'C': 3, 'D': 2}, rate, {'A': 3}) rsys = ReactionSystem([rxn], 'A B C D') odesys = get_odesys(rsys, unit_registry=SI_base_registry)[0] conc = {'A': 3*u.molar, 'B': 5*u.molar, 'C': 11*u.molar, 'D': 13*u.molar} x, y, p = odesys.to_arrays(-37*u.second, conc, {'temperature': 298.15*u.kelvin}) fout = odesys.f_cb(x, y, p) r = 3*5*(10+2*25)*1000 # mol/m3/s ref = [-4*r, -r, 3*r, 2*r] assert np.all(abs((fout - ref)/ref) < 1e-14)
def test_TPolyInLog10MassAction__units(): Mps = u.molar/u.second kunit = 1/u.molar**2/u.second p = MassAction(Constant(kunit)*ShiftedLog10TPoly([2, 0.3, .2, .03, .004])) lgT = Log10('temperature'/Constant(u.K)) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, p, {'B': 1}) res = p({'A': 11*u.molar, 'B': 13*u.molar, 'temperature': 298.15*u.K, 'log10_temperature': lgT}, backend=Backend(), reaction=r) _T = math.log10(298.15) - 2 ref = (.3 + .2*_T + 0.03 * _T**2 + 0.004 * _T**3) * 13 * 11**2 * Mps assert abs(res - ref) < 1e-15*Mps
def test_get_ode__Radiolytic(): rad = Radiolytic([2.4e-7]) rxn = Reaction({'A': 4, 'B': 1}, {'C': 3, 'D': 2}, rad) rsys = ReactionSystem([rxn], 'A B C D') odesys = get_odesys(rsys, include_params=True)[0] c = {'A': 3, 'B': 5, 'C': 11, 'D': 13} x, y, p = odesys.to_arrays(-37, c, {'doserate': 0.4, 'density': 0.998}) fout = odesys.f_cb(x, y, p) r = 2.4e-7*0.4*0.998 ref = [-4*r, -r, 3*r, 2*r] assert np.all(abs((fout - ref)/ref) < 1e-14)
def test_ode_with_global_parameters(): ratex = MassAction(Arrhenius([1e10, 40e3/8.3145])) rxn = Reaction({'A': 1}, {'B': 1}, ratex) rsys = ReactionSystem([rxn], 'A B') odesys, extra = get_odesys(rsys, include_params=False) param_keys, unique_keys, p_units = map(extra.get, 'param_keys unique p_units'.split()) conc = {'A': 3, 'B': 5} x, y, p = odesys.to_arrays(-37, conc, {'temperature': 298.15}) fout = odesys.f_cb(x, y, p) ref = 3*1e10*np.exp(-40e3/8.3145/298.15) assert np.all(abs((fout[:, 0] + ref)/ref) < 1e-14) assert np.all(abs((fout[:, 1] - ref)/ref) < 1e-14)
def test_Radiolytic__parsing__units(): rxn = Reaction.from_string( "-> H + OH; Radiolytic({'radiolytic_yield': 2.1e-7*mol/J})", None) assert rxn.reac == {} assert rxn.prod == {"H": 1, "OH": 1} res = rxn.rate({ "doserate": 0.15 * u.gray / u.s, "density": 0.998 * u.kg / u.dm3 }) ref = 0.15 * 0.998 * 2.1e-7 * u.molar / u.second assert abs((res["H"] - ref) / ref) < 1e-15 assert abs((res["OH"] - ref) / ref) < 1e-15
def _r(r, p, substmap, parmap, *, unit_conc, unit_time, variables=None): pk, = r.param.unique_keys if isinstance(r.param, MassAction): ratcoeff = to_unitless(p[pk], unit_conc**(1 - r.order()) / unit_time) if not r.inact_reac: r_str = '{}, {}'.format( parmap[pk], r.string(substances=substmap, with_param=False, Reaction_arrow='-->', Reaction_coeff_space='')) else: all_keys = r.keys() reac_stoichs = r.all_reac_stoich(all_keys) act_stoichs = r.active_reac_stoich(all_keys) rate = '*'.join([parmap[pk]] + [('%s^%d' % (substmap[k], v)) if v > 1 else substmap[k] for k, v in zip(all_keys, act_stoichs) if v > 0]) r2 = Reaction( dict([(k, v) for k, v in zip(all_keys, reac_stoichs) if v]), r.prod) r_str = '{}, {}'.format( rate, r2.string(substances=substmap, with_param=False, Reaction_arrow='\u21D2', Reaction_coeff_space='')) elif isinstance(r.param, RadiolyticBase): ratcoeff = to_unitless( p[pk] * variables['doserate'] * variables['density'], unit_conc / unit_time) assert not r.reac and not r.inact_reac and not r.inact_prod (prod, n), = r.prod.items() assert n == 1 r_str = ('{}, 0 \u21D2 {}' if ratcoeff > 0 else '{}, {} \u21D2 0').format(parmap[pk], substmap[prod]) else: raise NotImplementedError("Whats that?") return r_str, pk, abs(ratcoeff)
def test_ArrheniusMassAction__units(R_from_constants): import numpy as np Ea = 40e3*u.J/u.mol R = default_constants.molar_gas_constant if R_from_constants else (8.3145*u.J/u.mol/u.K) A, Ea_over_R = 1.2e11/u.molar**2/u.second, Ea/R ref1 = A*np.exp(-to_unitless(Ea_over_R/(290*u.K))) arrh = Arrhenius([A, Ea_over_R]) assert allclose(arrh({'temperature': 290*u.K}), ref1) ama = MassAction(arrh) r = Reaction({'A': 2, 'B': 1}, {'C': 1}, ama, {'B': 1}) T_ = 'temperature' def ref(v): return 1.2e11/u.molar**2/u.second*math.exp( -Ea_over_R.simplified/v[T_])*v['B']*v['A']**2 ma = r.rate_expr() for params in [(11.*u.molar, 13.*u.molar, 17.*u.molar, 311.2*u.kelvin), (12*u.molar, 8*u.molar, 5*u.molar, 270*u.kelvin)]: var = dict(zip(['A', 'B', 'C', T_], params)) ref_val = ref(var) assert abs((ma(var, reaction=r) - ref_val)/ref_val) < 1e-14
def test_EyringMassAction(): args = kB_h_times_exp_dS_R, dH_over_R = 1.2e11/273.15, 40e3/8 ama = EyringMassAction(args, ('Sfreq', 'Hact')) rxn1 = Reaction({'A': 2, 'B': 1}, {'C': 1}, ama, {'B': 1}) T_ = 'temperature' def ref(v): return v.get('Sfreq', 1.2e11/273.15)*v[T_]*math.exp(-v.get('Hact', 40e3/8)/v[T_])*v['B']*v['A']**2 for params in [(11., 13., 17., 311.2), (12, 8, 5, 270)]: var = dict(zip(['A', 'B', 'C', T_], params)) r = ref(var) assert abs((ama(var) - r)/r) < 1e-14 with pytest.raises(ValueError): EyringMassAction([1, 1, 1, 1, 1]) assert ama.as_mass_action({T_: 273.15}).args[0] == 1.2e11*math.exp(-40e3/8/273.15) ama2 = EyringMassAction([1.2e11/273, 40e3/8, 1.2, 1e3], ('Sfreq', 'Hact', 'Sref', 'Href')) rxn2 = Reaction({'C': 1}, {'A': 2, 'B': 2}, ama2) var2 = {'C': 29, 'temperature': 273} def ref2(var): return var['C']*var.get('temperature', 273)*var.get('Sfreq', 1.2e11/273)/var.get('Sref', 1.2)*math.exp( (var.get('Href', 1e3) - var.get('Hact', 5e3))/var.get('temperature', 273)) r2 = ref2(var2) assert abs((ama2(var2) - r2)/r2) < 1e-14 rsys = ReactionSystem([rxn1, rxn2]) var3 = {'A': 11, 'B': 13, 'C': 17, 'temperature': 298, 'Sfreq': 1.2e11/298} rates = rsys.rates(var3) rf3 = ref(var3) rb3 = ref2(var3) ref_rates = {'A': 2*(rb3 - rf3), 'B': 2*(rb3 - rf3), 'C': rf3 - rb3} for k, v in ref_rates.items(): assert abs((rates[k] - v)/v) < 1e-14
def test_TPiecewisePolyMassAction(): tp1 = TPoly([10, 0.1]) tp2 = ShiftedTPoly([273.15, 37.315, -0.1]) pwp = MassAction(TPiecewise([0, tp1, 273.15, tp2, 373.15])) r = Reaction({"A": 2, "B": 1}, {"C": 1}, inact_reac={"B": 1}) res1 = pwp({"A": 11, "B": 13, "temperature": 198.15}, reaction=r) ref1 = 11 * 11 * 13 * 29.815 assert abs((res1 - ref1) / ref1) < 1e-14 res2 = pwp({"A": 11, "B": 13, "temperature": 298.15}, reaction=r) ref2 = 11 * 11 * 13 * (37.315 - 25 * 0.1) assert abs((res2 - ref2) / ref2) < 1e-14 with pytest.raises(ValueError): pwp({"A": 11, "B": 13, "temperature": 398.15}, reaction=r)
def test_Log10TPolyMassAction__units(): Mps = u.molar / u.second kunit = 1 / u.molar**2 / u.second r = Log10TPolyMassAction( [kunit, 273.15 * u.K, .7, .02 / u.K, .003 / u.K**2, .0004 / u.K**3]) Reaction({'A': 2, 'B': 1}, {'C': 1}, r, {'B': 1}) res = r({ 'A': 11 * u.molar, 'B': 13 * u.molar, 'temperature': 298.15 * u.K }) ref = 10**(.7 + .02 * 25 + 0.003 * 25**2 + 0.0004 * 25**3) assert abs(res - ref * 13 * 11**2 * Mps) < 1e-15
async def balance(self, ctx, *, equation: str): """Balances a chemical equation.""" try: reac, prod = equation.split('=') except ValueError: reac, prod = equation.split('->') reac = [r.strip().lstrip('0123456789') for r in reac.split('+')] prod = [p.strip().lstrip('0123456789') for p in prod.split('+')] balanced = await self.bot.loop.run_in_executor(None, balance_stoichiometry, reac, prod) answer = Reaction(*balanced) msg = await ctx.send('<a:loading:393852367751086090>') await msg.edit(content=f'```py\nNonbalanced Equation: {equation}```\n\n<a:loading:393852367751086090>') await msg.edit(content=f'```py\nNonbalanced Equation: {equation}\n\nBalanced Equation: {answer.string()}```')
def test_PiecewiseTPolyMassAction__sympy(): import sympy as sp tp1 = TPoly([0, 10, 0.1]) tp2 = TPoly([273.15, 37.315, -0.1]) pwp = PiecewiseTPolyMassAction.from_polynomials([(0, 273.15), (273.15, 373.15)], [tp1, tp2]) T = sp.Symbol('T') Reaction({'A': 2, 'B': 1}, {'C': 1}, pwp, {'B': 1}) res1 = pwp({'A': 11, 'B': 13, 'temperature': T}, backend=sp) ref1 = 11**2 * 13 * sp.Piecewise( (10 + 0.1 * T, sp.And(0 <= T, T <= 273.15)), (37.315 - 0.1 * (T - 273.15), sp.And(273.15 <= T, T <= 373.15))) assert res1 == ref1
def test_get_ode__Radiolytic__substitutions(): rad = Radiolytic([2.4e-7]) rxn = Reaction({'A': 4, 'B': 1}, {'C': 3, 'D': 2}, rad) rsys = ReactionSystem([rxn], 'A B C D') substance_rho = Density([1, -1e-3, 273.15]) odesys = get_odesys(rsys, include_params=True, substitutions={'density': substance_rho})[0] conc = {'A': 3, 'B': 5, 'C': 11, 'D': 13} state = {'doserate': 0.4, 'temperature': 298.15} x, y, p = odesys.to_arrays(-37, conc, state) fout = odesys.f_cb(x, y, p) r = 2.4e-7*0.4*substance_rho({'temperature': 298.15}) ref = [-4*r, -r, 3*r, 2*r] assert np.all(abs((fout - ref)/ref) < 1e-14)
def test_MassAction(): ma = MassAction([3.14], ['my_rate']) Reaction({'A': 2, 'B': 1}, {'C': 1}, ma, {'B': 1}) assert abs(ma({'A': 11, 'B': 13, 'C': 17}) - 3.14 * 13 * 11**2) < 1e-14 assert abs( ma({ 'A': 11, 'B': 13, 'C': 17, 'my_rate': 2.72 }) - 2.72 * 13 * 11**2) < 1e-12 ma2 = ma.as_mass_action({}) assert ma == ma2 assert abs(ma2({'A': 11, 'B': 13, 'C': 17}) - 3.14 * 13 * 11**2) < 1e-14
def test_PiecewiseTPolyMassAction__sympy(): import sympy as sp tp1 = TPoly([10, 0.1]) tp2 = ShiftedTPoly([273.15, 37.315, -0.1]) pwp = MassAction(TPiecewise([0, tp1, 273.15, tp2, 373.15])) T = sp.Symbol('T') r = Reaction({'A': 2, 'B': 1}, {'C': 1}, inact_reac={'B': 1}) res1 = pwp({'A': 11, 'B': 13, 'temperature': T}, backend=sp, reaction=r) ref1 = 11**2 * 13 * sp.Piecewise( (10+0.1*T, sp.And(0 <= T, T <= 273.15)), (37.315 - 0.1*(T-273.15), sp.And(273.15 <= T, T <= 373.15)), (sp.Symbol('NAN'), True) ) assert res1 == ref1
def test_TPiecewise(): expr0 = ShiftedTPoly([273.15*u.K, 10/u.molar/u.s, 0.1/u.molar/u.s/u.K]) expr1 = ShiftedTPoly([298.15*u.K, 12.5/u.molar/u.s, 0/u.molar/u.s/u.K, 2/u.molar/u.s/u.K**2]) pwma = MassAction(TPiecewise([273.15*u.K, expr0, 298.15*u.K, expr1, 373.15*u.K])) r = Reaction({'e-(aq)': 2}, {'H2': 1, 'OH-': 2}, inact_reac={'H2O': 2}) res0 = pwma({'temperature': 293.15*u.K, 'e-(aq)': 1e-13*u.molar}, reaction=r) ref0 = 12*1e-26 * u.molar/u.s assert allclose(res0, ref0) assert not allclose(res0, 2*ref0) res1 = pwma({'temperature': 300.15*u.K, 'e-(aq)': 2e-13*u.molar}, reaction=r) ref1 = 20.5*4e-26 * u.molar/u.s assert allclose(res1, ref1) assert not allclose(res1, ref1/2)
def test_get_ode__Radiolytic__substitutions(): rad = Radiolytic([2.4e-7]) rxn = Reaction({"A": 4, "B": 1}, {"C": 3, "D": 2}, rad) rsys = ReactionSystem([rxn], "A B C D") substance_rho = Density([1, -1e-3, 273.15]) odesys = get_odesys( rsys, include_params=True, substitutions={"density": substance_rho} )[0] conc = {"A": 3, "B": 5, "C": 11, "D": 13} state = {"doserate": 0.4, "temperature": 298.15} x, y, p = odesys.to_arrays(-37, conc, state) fout = odesys.f_cb(x, y, p) r = 2.4e-7 * 0.4 * substance_rho({"temperature": 298.15}) ref = [-4 * r, -r, 3 * r, 2 * r] assert np.all(abs((fout - ref) / ref) < 1e-14)
def test_PiecewiseTPolyMassAction__sympy(): import sympy as sp tp1 = TPoly([10, 0.1]) tp2 = ShiftedTPoly([273.15, 37.315, -0.1]) pwp = MassAction(TPiecewise([0, tp1, 273.15, tp2, 373.15])) T = sp.Symbol("T") r = Reaction({"A": 2, "B": 1}, {"C": 1}, inact_reac={"B": 1}) res1 = pwp({"A": 11, "B": 13, "temperature": T}, backend=sp, reaction=r) ref1 = (11**2 * 13 * sp.Piecewise( (10 + 0.1 * T, sp.And(0 <= T, T <= 273.15)), (37.315 - 0.1 * (T - 273.15), sp.And(273.15 <= T, T <= 373.15)), (sp.Symbol("NAN"), True), )) assert res1 == ref1
def test_Log10TPolyMassAction__units(): Mps = u.molar / u.second kunit = 1 / u.molar**2 / u.second p = MassAction( Constant(kunit) * 10**ShiftedTPoly( [273.15 * u.K, 0.7, 0.02 / u.K, 0.003 / u.K**2, 0.0004 / u.K**3])) r = Reaction({"A": 2, "B": 1}, {"C": 1}, p, {"B": 1}) res = p({ "A": 11 * u.molar, "B": 13 * u.molar, "temperature": 298.15 * u.K }, reaction=r) ref = 10**(0.7 + 0.02 * 25 + 0.003 * 25**2 + 0.0004 * 25**3) assert abs(res - ref * 13 * 11**2 * Mps) < 1e-15
def test_RTPolyMassAction__units(): Mps = u.molar / u.second kunit = 1 / u.molar**2 / u.second r = RTPolyMassAction([ 273.15 * u.K, 7 * kunit, .2 * kunit * u.K, .03 * kunit * u.K**2, .004 * kunit * u.K**3 ]) Reaction({'A': 2, 'B': 1}, {'C': 1}, r, {'B': 1}) res = r({ 'A': 11 * u.molar, 'B': 13 * u.molar, 'temperature': 298.15 * u.K }) ref = 7 + .2 / 25 + 0.03 / 25**2 + 0.004 / 25**3 assert abs(res - ref * 13 * 11**2 * Mps) < 1e-15
def test_get_ode__Radiolytic__substitutions__units(): rad = Radiolytic([2.4e-7*u.mol/u.joule]) rxn = Reaction({'A': 4, 'B': 1}, {'C': 3, 'D': 2}, rad) rsys = ReactionSystem([rxn], 'A B C D') g_dm3 = u.gram / u.decimetre**3 kg_dm3 = u.kg / u.decimetre**3 substance_rho = Density([1*kg_dm3, -1*g_dm3/u.kelvin, 273.15*u.kelvin]) odesys = get_odesys(rsys, include_params=True, unit_registry=SI_base_registry, substitutions={'density': substance_rho})[0] conc = {'A': 3*u.molar, 'B': 5*u.molar, 'C': 11*u.molar, 'D': 13*u.molar} x, y, p = odesys.to_arrays(-37*u.second, conc, {'doserate': 0.4*u.gray/u.second, 'temperature': 298.15*u.kelvin}) fout = odesys.f_cb(x, y, p) r = 2.4e-7*0.4*0.975 * 1e3 # mol/m3/s ref = [-4*r, -r, 3*r, 2*r] assert np.all(abs((fout - ref)/ref) < 1e-14)
def test_get_ode__Radiolytic__units(): rad = Radiolytic([2.4e-7*u.mol/u.joule]) rxn = Reaction({'A': 4, 'B': 1}, {'C': 3, 'D': 2}, rad) rsys = ReactionSystem([rxn], 'A B C D') odesys = get_odesys(rsys, include_params=True, unit_registry=SI_base_registry)[0] conc = {'A': 3*u.molar, 'B': 5*u.molar, 'C': 11*u.molar, 'D': 13*u.molar} x, y, p = odesys.to_arrays(-37*u.second, conc, { 'doserate': 0.4*u.gray/u.second, 'density': 0.998*u.kg/u.decimetre**3 }) fout = odesys.f_cb(x, y, p) # f_cb does not carry any units r = 2.4e-7*0.4*0.998*1e3 # mol/m3 ref = [-4*r, -r, 3*r, 2*r] assert np.all(abs((fout - ref)/ref) < 1e-14)
def test_Reaction_string(): from sympy import S r = Reaction({'A': 1, 'B': 2}, {'C': S(3)/2}, checks=[ chk for chk in Reaction.default_checks if chk != 'all_integral']) assert r.string() == 'A + 2 B -> 3/2 C'
def test_eval_template__Reaction(): rendered = eval_template("2 OH -> H2O2; ${6*pi*arg}/M/s", arg=1/math.pi) assert allclose(Reaction.from_string(rendered).param, Reaction.from_string("2 OH -> H2O2; 6.0/M/s").param)
def test_Radioyltic__Reaction_html(): rate = Radiolytic([2.1*u.per100eV]) rxn = Reaction({}, {'H': 1}, rate) H = Substance.from_formula('H') html = rxn.html({'H': H}, with_param=True) assert html == ' → H; %s' % str(rate)