def test_equation_writer_linebreaks(tmpdir): """EquationWriter breaks long import lines.""" from essm.variables.physics.thermodynamics import alpha_a, D_va, P_wa, \ R_mol, T_a, M_O2, P_O2, P_N2, M_N2, M_w, Le, C_wa, rho_a, P_a, \ x_N2, x_O2 writer_td = EquationWriter(docstring='Test of Equation_writer.') writer_td.neweq('eq_Le', Eq(Le, alpha_a / D_va), doc='Le as function of alpha_a and D_va.') writer_td.neweq('eq_Cwa', Eq(C_wa, P_wa / (R_mol * T_a)), doc='C_wa as a function of P_wa and T_a.') writer_td.neweq('eq_rhoa_Pwa_Ta', Eq(rho_a, (M_w * P_wa + M_N2 * P_N2 + M_O2 * P_O2) / (R_mol * T_a)), doc='rho_a as a function of P_wa and T_a.') writer_td.neweq('eq_Pa', Eq(P_a, P_N2 + P_O2 + P_wa), doc='Calculate air pressure from partial pressures.') writer_td.neweq('eq_PN2_PO2', Eq(P_N2, x_N2 / x_O2 * P_O2), doc='Calculate P_N2 as a function of P_O2') eq_file = tmpdir.mkdir('test').join('test_equations.py') writer_td.write(eq_file.strpath) with open(eq_file.strpath) as outfile: maxlinelength = max([len(line) for line in outfile.readlines()]) assert maxlinelength < 80
class demo_fall(Equation): """Test equation.""" class t(Variable): unit = second expr = Eq(demo_d, S(1) / S(2) * demo_g * t ** 2)
def test_variable_replacement(): """Test replace variables by values and symbols in expression.""" expr = demo_fall vdict = Variable.__defaults__.copy() vdict[Symbol('x')] = 1 assert replace_variables(expr, vdict) == \ Eq(demo_d, 4.9 * demo_fall.definition.t ** 2)
class eq_alphaa(Equation): """alpha_a as a function of air temperature. (Table A.3 in :cite:`monteith_principles_2007`) """ class p_alpha1(Variable): """Internal parameter of eq_alphaa.""" name = 'p_alpha1' unit = meter ** 2 / (kelvin * second) domain = 'real' latex_name = 'p_1' default = 1.32e-07 class p_alpha2(Variable): """Internal parameter of eq_alphaa.""" name = 'p_alpha2' unit = meter ** 2 / second domain = 'real' latex_name = 'p_2' default = 1.73e-05 expr = Eq(alpha_a, T_a * p_alpha1 - p_alpha2)
class eq_gbw_hc(Equation): """g_bw as function of h_c. (Eq. B2 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(g_bw, a_s * h_c / (Le**(2 / 3) * c_pa * rho_a))
class eq_ka(Equation): """k_a as a function of air temperature. (Table A.3 in :cite:`monteith_principles_2007`) """ class p_ka1(Variable): """Internal parameter of eq_ka.""" name = 'p_ka1' unit = joule / (kelvin ** 2 * meter * second) domain = 'real' latex_name = 'p_1' default = 6.84e-05 class p_ka2(Variable): """Internal parameter of eq_ka.""" name = 'p_ka2' unit = joule / (kelvin * meter * second) domain = 'real' latex_name = 'p_2' default = 5.63e-03 expr = Eq(k_a, T_a * p_ka1 + p_ka2)
class eq_gtw(Equation): """g_tw from g_sw and g_bw. (Eq. 6 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(g_tw, (1 / (1 / g_bw + 1 / g_sw)))
class eq_Cwl(Equation): """C_wl as function of P_wl and T_l. (Eq. B4 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(C_wl, P_wl / (R_mol * T_l))
class eq_El(Equation): """E_l as function of E_lmol. (Eq. 4 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(E_l, E_lmol * M_w * lambda_E)
def test_equation_writer(tmpdir): """EquationWriter creates importable file with internal variables.""" from sympy import var from essm.equations.leaf.energy_water import eq_Pwl, eq_Cwl from essm.variables.physics.thermodynamics import lambda_E, M_w, R_mol from essm.variables.leaf.energy_water import P_wl, T_l g = {} d = var('d') t = var('t') writer_td = EquationWriter(docstring='Test of Equation_writer.') writer_td.neweq('demo_fall', Eq(demo_g, d / t**2), doc='Test equation.\n\n (Some reference)\n ', variables=[{ "name": "d", "default": '0.9', "units": meter, "latex_name": 'p_1' }, { "name": "t", "units": second, "latex_name": 'p_2' }]) writer_td.eq(eq_Cwl) writer_td.eq(eq_Pwl) eq_file = tmpdir.mkdir('test').join('test_equations.py') writer_td.write(eq_file.strpath) with open(eq_file, "rb") as source_file: code = compile(eq_file.read(), eq_file, "exec") exec(code, g) assert g['demo_fall'].definition.d.definition.default == 0.9 assert g['eq_Cwl'].definition.expr == eq_Cwl.definition.expr assert g['eq_Pwl'].definition.expr == eq_Pwl.definition.expr
class eq_Elmol_conv(Equation): """E_lmol as function of g_twmol and P_wl. (Eq. B6 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(E_lmol, -(P_wa - P_wl) * g_twmol / P_a)
class eq_Rll(Equation): """R_ll as function of T_l and T_w. (Eq. 2 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(R_ll, (T_l**4 - T_w**4) * a_sh * epsilon_l * sigm)
class eq_Hl(Equation): """H_l as function of T_l. (Eq. 3 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(H_l, -(T_a - T_l) * a_sh * h_c)
class eq_Gr(Equation): """Gr as function of air density within and outside of leaf. (Eq. B12 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(Gr, L_l**3 * g * (rho_a - rho_al) / (nu_a**2 * rho_al))
class eq_Rs_enbal(Equation): """Calculate R_s from energy balance. (Eq. 1 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(R_s, E_l + H_l + R_ll)
class eq_hc(Equation): """h_c as a function of Nu and L_l. (Eq. B10 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(h_c, Nu * k_a / L_l)
class eq_Re(Equation): """Re as a function of v_w and L_l. (Eq. B11 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(Re, L_l * v_w / nu_a)
class eq_rhoa_Pwa_Ta(Equation): """rho_a as a function of P_wa and T_a. (Eq. B20 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(rho_a, (M_N2 * P_N2 + M_O2 * P_O2 + M_w * P_wa) / (R_mol * T_a))
class eq_Elmol(Equation): """E_lmol as functino of g_tw and C_wl. (Eq. 5 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(E_lmol, -(C_wa - C_wl) * g_tw)
class eq_Pwl(Equation): """Clausius-Clapeyron P_wl as function of T_l. (Eq. B3 in :cite:`hartmann_global_1994`) """ class p_CC1(Variable): """Internal parameter of eq_Pwl.""" name = 'p_CC1' unit = pascal domain = 'real' latex_name = 'p_1' default = 611. class p_CC2(Variable): """Internal parameter of eq_Pwl.""" name = 'p_CC2' unit = kelvin domain = 'real' latex_name = 'p_2' default = 273. expr = Eq(P_wl, p_CC1 * e**(-M_w * lambda_E * (1 / T_l - 1 / p_CC2) / R_mol))
class eq_Cwa(Equation): """C_wa as a function of P_wa and T_a. (Eq. B9 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(C_wa, P_wa / (R_mol * T_a))
class eq_Le(Equation): """Le as function of alpha_a and D_va. (Eq. B3 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq(Le, alpha_a / D_va)
class eq_PN2_PO2(Equation): """Calculate P_N2 as a function of P_O2. It follows Dalton's law of partial pressures. """ expr = Eq(P_N2, P_O2 * x_N2 / x_O2)
class eq_Qi(Equation): """Calculate .... :cite:`schymanski_leaf-scale_2017` """ expr = Eq(Q_i, dT_i * lambda_i * A_i / L_i) """Describe how you got the equation."""
class eq_rhoa(eq_rhoa_Pwa_Ta.definition, eq_PN2.definition, eq_PO2.definition): """Calculate rho_a from T_a, P_a and P_wa.""" expr = Eq( rho_a, ((M_N2 * P_a - (M_N2 - M_w) * P_wa) * x_N2 + (M_O2 * P_a - (M_O2 - M_w) * P_wa) * x_O2) / (R_mol * T_a * x_N2 + R_mol * T_a * x_O2) )
class eq_Pa(Equation): """Calculate air pressure. From partial pressures of N2, O2 and H2O, following Dalton's law of partial pressures. """ expr = Eq(P_a, P_N2 + P_O2 + P_wa)
class eq_gtwmol_gtw(eq_Elmol.definition, eq_Cwl.definition, eq_Elmol_conv.definition): """g_twmol as a function of g_tw. It uses eq_Elmol, eq_Cwl and eq_Elmol_conv. """ expr = Eq( g_twmol, -(P_a * P_wl * T_a - P_a * P_wa * T_l) * g_tw / ((P_wa - P_wl) * R_mol * T_a * T_l))
class eq_Nu_forced_all(Equation): """Nu as function of Re and Re_c under forced conditions. (Eqs. B13--B15 in :cite:`schymanski_leaf-scale_2017`) """ expr = Eq( Nu, -1 / 1000 * Pr**(1 / 3) * (37 * (Re + Re_c - 1 / 2 * abs(Re - Re_c))**(4 / 5) - 37 * Re**(4 / 5) - 664 * sqrt(Re + Re_c - 1 / 2 * abs(Re - Re_c))))
class combined_units(Equation): class x_mol(Variable): unit = joule / mole / kelvin class x_J(Variable): unit = joule class x_K(Variable): unit = kelvin class x_M(Variable): unit = mole expr = Eq(x_mol, x_J / x_M / x_K)
def test_equation_writer(tmpdir): """EquationWriter creates importable file with internal variables.""" from sympy import var g = {} d = var('d') t = var('t') writer_td = EquationWriter(docstring='Test of Equation_writer.') writer_td.eq( 'demo_fall', Eq(demo_g, d / t ** 2), doc='Test equation.\n\n (Some reference)\n ', variables=[{ "name": "d", "value": '0.9', "units": meter, "latexname": 'p_1'}, { "name": "t", "units": second, "latexname": 'p_2'}]) eq_file = tmpdir.mkdir('test').join('test_equations.py') writer_td.write(eq_file.strpath) execfile(eq_file.strpath, g) assert g['demo_fall'].definition.d.definition.default == 0.9