def test_failingSystemCommand(self): # now we test a Model that can not run in R since one crucial parameter is missing C_0, t = symbols("C_0, t") C_S, C_B, varepsilon, t_start, t_end, tn = symbols( "C_S,C_B,varepsilon,t_start,t_end,tn") V_S, mu_B, K_S = symbols("V_S mu_B K_S") F_npp = symbols("F_npp") alphas = {"1_to_2": 1, "2_to_1": varepsilon} F = Matrix(2, 1, [mu_B * C_B, V_S * C_B * C_S / (K_S + C_S)]) C = Matrix(2, 1, [C_B, C_S]) I = Matrix(2, 1, [0, F_npp]) M = RExample(C, alphas, F, I, who_am_i()) dic = { F_npp: 0.01, V_S: 0.000018, mu_B: 0.007, K_S: 1.0, varepsilon: 0.5, # the following always have to be present C_0: Matrix(2, 1, [972, 304]), t_start: 0, t_end: 2000, #tn:100 should cause an error } M.addParameterSet(dic) with self.assertRaises(RcodeException): M.writeSoilRModel()
def test_linearUnstableWithoutInertPool(self): C_0, t = symbols("C_0, t") C1, C2 = symbols("C1,C2", real=True, nonnegative=True) a, b = symbols("a,b", real=True, positive=True) i1, i2 = symbols("i1,i2", real=True, positive=True) t_start, t_end, tn = symbols("t_start,t_end,tn") C = Matrix(2, 1, [C1, C2]) #F=Matrix([C1*a,C2*a]) F = Matrix([C1 * a + b * C2, C2 * a - b * C1]) I = Matrix(2, 1, [i1, i2]) alphas = {} M = RExample(C, alphas, F, I, who_am_i()) dic = { a: 1, #this leads to permanent oscillation without decay b: 5, i1: 1, i2: 1, # the following always have to be present C_0: Matrix(2, 1, [1, 1]), t_start: 0, t_end: 10, tn: 100 } M.addParameterSet(dic) M.latexSummary() with self.assertRaises(RcodeException): M.writeSoilRModel()
def test_timeDependentNotConverging(self): # by creating a time dependent input we easily create a model that never converges # although it is very sensible and good natured C_0, t = symbols("C_0, t") C1, C2 = symbols("C1,C2", real=True, nonnegative=True) a, b = symbols("a,b", real=True, positive=True) i1, i2 = symbols("i1,i2", real=True, positive=True) t_start, t_end, tn = symbols("t_start,t_end,tn") C = Matrix(2, 1, [C1, C2]) F = Matrix([C1 * a, C2 * a]) I = Matrix(2, 1, [i1 * sin(t), i2 * sin(t)]) alphas = {} M = RExample(C, alphas, F, I, who_am_i()) dic = { a: 5, b: 1, i1: 1, i2: 1, # the following always have to be present C_0: Matrix(2, 1, [1, 1]), t_start: 0, t_end: 100, tn: 1000 } M.addParameterSet(dic) M.latexSummary() with self.assertRaises(RcodeException): M.writeSoilRModel()
def test_oscillatingLinearModel_2(self): # we provoke a pair of complex conjugate eigenvalues with real part a and imagenary part b,-b respectively # by constructing an appropriate matrix with a on the diagonal and b,-b as off diagonal terms C_0, t = symbols("C_0, t") C1, C2 = symbols("C1,C2", real=True, nonnegative=True) a, b = symbols("a,b", real=True, positive=True) i1, i2 = symbols("i1,i2", real=True, positive=True) t_start, t_end, tn = symbols("t_start,t_end,tn") C = Matrix(2, 1, [C1, C2]) F = Matrix([C1 * a, C2 * a]) #F=Matrix([C1*a+b*C2,C2*a-b*C1]) I = Matrix(2, 1, [i1, i2]) #alphas={} alphas = {"1_to_2": b / a, "2_to_1": -b / a} M = RExample(C, alphas, F, I, who_am_i()) dic = { a: 5, b: 1, i1: 1, i2: 1, # the following always have to be present C_0: Matrix(2, 1, [1, 1]), t_start: 0, t_end: 10, tn: 100 } M.addParameterSet(dic) with self.assertRaises(NegativeRespiration): M.latexSummary() M.writeSoilRModel()
def test_negativeRespirationDetection(self): # now we test a Model that can not run in R since one crucial parameter is missing C_0, t = symbols("C_0, t") C_S, C_B, varepsilon, t_start, t_end, tn = symbols( "C_S,C_B,varepsilon,t_start,t_end,tn") V_S, mu_B, K_S = symbols("V_S mu_B K_S") F_npp = symbols("F_npp") alphas = {"1_to_2": 1, "2_to_1": varepsilon} F = Matrix(2, 1, [mu_B * C_B, V_S * C_B * C_S / (K_S + C_S)]) C = Matrix(2, 1, [C_B, C_S]) I = Matrix(2, 1, [0, F_npp]) M = RExample(C, alphas, F, I, who_am_i()) dic = { F_npp: 0.01, V_S: 0.000018, mu_B: 0.007, K_S: 1.0, # negative transfer should lead to a varepsilon: -0.5, # the following always have to be present C_0: Matrix(2, 1, [972, 304]), t_start: 0, t_end: 2000, tn: 100 } M.addParameterSet(dic) with self.assertRaises(NegativeRespiration): M.latexSummary()
def test_SW_RMM_S(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") S, D, M, E = symbols("S, D, M, E") C = Matrix(4, 1, [S, D, M, E]) K_e = Symbol("K_e", real=True) # Fraction of DOC used for enzyme production. K_d = Symbol("K_d", real=True) # Decay constant. K_t = Symbol( "K_t", real=True ) # proportion of microbial biomass that dies in each time interval. K_r = Symbol( "K_r", real=True ) # proportion of dead microbial biomass that is available for microbial use. K_m = Symbol("K_m", real=True) # microbial maintenance rate. K_l = Symbol("K_l", real=True) # decay constant for exoenzymes. K_es = Symbol( "K_es", real=True) # half saturation constant for enzymes on substrate. alphas = { "1_to_2": 1, "2_to_3": 1 - K_e, "2_to_4": K_e, "3_to_2": (K_t * K_r) / K_m } I = Matrix(4, 1, [0, 0, 0, 0]) F = Matrix(4, 1, [K_d * S * E / (K_es + E), D, K_m * M, K_l * E]) Mod = RExample(C, alphas, F, I, who_am_i()) Cdot = I + Mod.getOperator() solutions = solve(Cdot, [D, M, E]) pprint(solutions) Mod.suggestFixedPoint({ S: simplify(solutions[S]), D: simplify(solutions[D]), M: simplify(solutions[M]), E: simplify(solutions[E]), }) Mod.addParameterSet({ K_e: 0.005, K_d: 0.001, K_t: 0.012, K_r: 0.85, K_m: 0.22, K_l: 0.005, K_es: 0.3, t_start: 0, t_end: 2e5, tn: 2e4, C_0: Matrix(4, 1, [.1, .1, .1, .1]) }) Mod.latexSummary() Mod.writeSoilRModel()
def test_VegVero(self): # This model is releates to TwopMMmodel # C pools and startvector Xleaf, Xwood, Xroot, C_0 = symbols("Xleaf, Xwood, Xroot, C_0") C = Matrix(3, 1, [Xleaf, Xwood, Xroot]) # a scalar representing the Activity factor; # i.e. a temperature and moisture modifier (unitless) a1, a2, a3 = symbols("a1,a2,a3") b1, b2, b3 = symbols("b1,b2,b3") c1, c2, c3 = symbols("c1,c2,c3") u1, u2, u3 = symbols("u1,u2,u3") # the alphas have to be a function of C and t (at most) alphas = {} # F=Matrix(2,1,[ # A_f*k_s*B*(S/(K_m+S)), # k_b*B # ]) F = Matrix(3, 1, [-a1 * c1 * Xleaf, -a2 * c2 * Xwood, -a3 * c3 * Xroot]) I = Matrix(3, 1, [b1 * u1, b2 * u2, b3 * u3]) tPM = RExample(C, alphas, F, I, who_am_i()) #times and time steps for the numeric modelling t_start, t_end, tn = symbols("t_start,t_end,tn") tPM.addParameterSet({ a1: -1, a2: -1, a3: -1, b1: 0.14, b2: 0.26, b3: 0.14, c1: 0.00258, c2: 0.0000586, c3: 0.00239, u1: 10, u2: 10, u3: 10, t_start: 0, t_end: 2000, tn: 2000, C_0: Matrix(3, 1, [100, 10, 10]) }) tPM.suggestFixedPoint({ Xleaf: -b1 * u1 / (a1 * c1), Xwood: -b2 * u2 / (a2 * c2), Xroot: -b3 * u3 / (a3 * c3) }) tPM.writeSoilRModel() tPM.latexSummary()
def test_vector2assignments(self): C_S, C_B, varepsilon = symbols("C_S,C_B,varepsilon") k_S, k_B, k_M = symbols("k_S k_B k_M") alphas = {"1_to_2": varepsilon, "2_to_1": 1} f1 = k_S * C_B * C_S / (k_M + C_S) f2 = k_B * C_B F = Matrix(2, 1, [f1, f2]) C = Matrix(2, 1, [C_S, C_B]) tPM = RExample(C, alphas, F, I, who_am_i()) res = tPM.cvecAssignments() ref = "C_S=C[1]\nC_B=C[2]" self.assertEqual(res, ref)
def test_Wang2pools(self): # This model is also releated to TwopMMmodel.R and Manzoni but slightly different and with other names C_0, t = symbols( "C_0, t" ) # these always have to be present because the translation relies on them C_S, C_B, varepsilon, t_start, t_end, tn = symbols( "C_S,C_B,varepsilon,t_start,t_end,tn") V_S, mu_B, K_S = symbols("V_S mu_B K_S") F_npp = symbols("F_npp") # the alphas have to be a function of C and t (at most) alphas = {"1_to_2": 1, "2_to_1": varepsilon} F = Matrix(2, 1, [mu_B * C_B, V_S * C_B * C_S / (K_S + C_S)]) C = Matrix(2, 1, [C_B, C_S]) I = Matrix(2, 1, [0, F_npp]) M = RExample(C, alphas, F, I, who_am_i()) #pprint(tPM.jacobian().eigenvals()) dic = { F_npp: 0.01, V_S: 0.000018, mu_B: 0.007, K_S: 1.0, varepsilon: 0.5, # the following always have to be present C_0: Matrix(2, 1, [972, 304]), t_start: 0, t_end: 2000, tn: 100 } M.addParameterSet(dic) M.suggestFixedPoint({ C_B: F_npp / (mu_B * (1.0 / varepsilon - 1)), C_S: K_S / (varepsilon * (V_S / mu_B) - 1) }) M.writeSoilRModel() M.latexSummary()
def test_bacwave(self): C_0, t = symbols( "C_0, t", real=True ) # these always have to be present because the translation relies on them #times and time steps for the numeric modelling t_start, t_end, tn = symbols("t_start,t_end,tn") S, X, C_0 = symbols("S, X, C_0") C = Matrix(2, 1, [S, X]) u_max = Symbol( "u_max", real=True ) # a scalar representing the maximum relative growth rate of bacteria (hr-1) k_s = Symbol( "k_s", real=True ) # a scalar representing the substrate constant for growth (ug C /ml soil solution) theta = Symbol( "theta", real=True, nonnegative=True ) # a scalar representing soil water content (ml solution/cm3 soil) D_max = Symbol( "D_max", real=True ) # a scalar representing the maximal relative death rate of bacteria (hr-1) k_d = Symbol( "k_d", real=True ) # a scalar representing the substrate constant for death of bacteria (ug C/ml soil solution) k_r = Symbol( "k_r", real=True ) # a scalar representing the fraction of death biomass recycling to substrate (unitless) Y = Symbol( "Y", real=True ) # a scalar representing the yield coefficient for bacteria (ug C/ugC) BGF = Symbol( "BGF", real=True ) # a scalar representing the constant background flux of substrate (ug C/cm3 soil/hr) Exu_max = Symbol( "Exu_max", real=True ) # a scalar representing the maximal exudation rate (ug C/(hr cm3 soil)) Exu_T = Symbol( "Exu_T", real=True, positive=True ) # a scalar representing the time constant for exudation, responsible for duration of exudation (1/hr). #respired carbon fraction # the alphas have to be a function of C and t (at most) alphas = {"1_to_2": Y, "2_to_1": k_r} F = Matrix(2, 1, [(X / Y) * (u_max * S) / ((k_s * theta) + S), (D_max * k_d * X) / (k_d + (S / theta))]) I = Matrix(2, 1, [BGF + (Exu_max * exp(-Exu_T * t)), 0]) tPM = RExample(C, alphas, F, I, who_am_i()) # we try to solve for the fixed points mat = I + tPM.getOperator() asymptotic_mat = Matrix(2, 1, [limit(l, t, oo) for l in mat]) ##solutions=solve(mat,X,S) # would lead a "time dependent fixed point" which seems a bit of a contradiction # the order of the unknowns seems to be important solve(mat,S,X) takes much longer asymptotic_solutions = solve( asymptotic_mat, X, S ) # the order of the unknowns seems to be important solve(mat,S,X) takes much longer #nontrivial=solutions[2] # in this case we choose manually the third solution nontrivial = asymptotic_solutions[2] pprint(nontrivial) tPM.suggestFixedPoint({ X: simplify(nontrivial[0]), S: simplify(nontrivial[1]) }) dic = { u_max: 0.063, k_s: 3.0, theta: 0.23, D_max: 0.26, k_d: 14.5, k_r: 0.4, Y: 0.44, BGF: 0.15, Exu_max: 8, Exu_T: 0.8, # the following are allways required for R t_start: 0, t_end: 800, tn: 8000, C_0: Matrix(2, 1, [0.5, 1.5]) } tPM.addParameterSet(dic) tPM.writeSoilRModel() tPM.latexSummary()
def test_Yasso(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") A, W, E, N, H = symbols("A, W, E, N, H") C = Matrix(5, 1, [A, W, E, N, H]) k_A = Symbol("k_A", real=True) # Decomposition rate of the A pool. k_W = Symbol("k_W", real=True) # Decomposition rate of the W pool. k_E = Symbol("k_E", real=True) # Decomposition rate of the E pool. k_N = Symbol("k_N", real=True) # Decomposition rate of the N pool. k_H = Symbol("k_H", real=True) # Decomposition rate of the H pool. p1 = Symbol("p1", real=True) # Transfer coefficient. p2 = Symbol("p2", real=True) # Transfer coefficient. p3 = Symbol("p3", real=True) # Transfer coefficient. p4 = Symbol("p4", real=True) # Transfer coefficient. p5 = Symbol("p5", real=True) # Transfer coefficient. p6 = Symbol("p6", real=True) # Transfer coefficient. p7 = Symbol("p7", real=True) # Transfer coefficient. p8 = Symbol("p8", real=True) # Transfer coefficient. p9 = Symbol("p9", real=True) # Transfer coefficient. p10 = Symbol("p10", real=True) # Transfer coefficient. p11 = Symbol("p11", real=True) # Transfer coefficient. p12 = Symbol("p12", real=True) # Transfer coefficient. pH = Symbol("pH", real=True) # Transfer coefficient. In = Symbol("In", real=True) # Litter inputs. alphas = { "2_to_1": p1, "3_to_1": p2, "4_to_1": p3, "1_to_2": p4, "3_to_2": p5, "4_to_2": p6, "1_to_3": p7, "2_to_3": p8, "4_to_3": p9, "1_to_4": p10, "2_to_4": p11, "3_to_4": p12, "1_to_5": pH, "2_to_5": pH, "3_to_5": pH, "4_to_5": pH } I = Matrix(5, 1, [In, 0, 0, 0, 0]) F = Matrix(5, 1, [k_A * A, k_W * W, k_E * E, k_N * N, k_H * H]) Mod = RExample(C, alphas, F, I, who_am_i()) Cdot = I + Mod.getOperator() #for unique solutions we can extract the information automatically solutions = solve(Cdot, [C[i] for i in range(0, len(C))]) Mod.suggestFixedPoint( {C[i]: solutions[C[i]] for i in range(0, len(C))}) Mod.addParameterSet({ k_A: 0.66, k_W: 4.3, k_E: 0.35, k_N: 0.22, k_H: 0.0033, p1: 0.32, p2: 0.01, p3: 0.93, p4: 0.34, p5: 0, p6: 0, p7: 0, p8: 0, p9: 0.01, p10: 0, p11: 0, p12: 0.92, pH: 0.04, In: 0, t_start: 0, t_end: 2e3, tn: 2e2, C_0: Matrix(5, 1, [.1, .1, .1, .1, .1]) }) Mod.latexSummary() Mod.writeSoilRModel()
def test_RothC(self): C_0, t = symbols( "C_0, t", real=True ) # these always have to be present because the translation relies on them #times and time steps for the numeric modelling t_start, t_end, tn = symbols("t_start,t_end,tn") C_1, C_2, C_3, C_4, C_5 = symbols("C_1, C_2, C_3, C_4, C_5") C = Matrix(5, 1, [C_1, C_2, C_3, C_4, C_5]) k_1 = Symbol("k_1", real=True) # Decomposition rate of the DPM pool. k_2 = Symbol("k_2", real=True) # Decomposition rate of the RPM pool. k_3 = Symbol("k_3", real=True) # Decomposition rate of the BIO pool. k_4 = Symbol("k_4", real=True) # Decomposition rate of the HUM pool. k_5 = Symbol("k_5", real=True) # Decomposition rate of the IOM pool. DR = Symbol( "DR", real=True ) # ratio of decomposable plant material to resistant plant material (DPM/RPM). clay = Symbol("clay", real=True) # percent clay in mineral soil. In = Symbol("In", real=True) # Carbon inputs. x = 1.67 * (1.85 + 1.6 * exp(-0.0786 * clay)) alphas = { "1_to_3": (0.46 / (x + 1)), "2_to_3": (0.46 / (x + 1)), "4_to_3": (0.46 / (x + 1)), "1_to_4": (0.54 / (x + 1)), "2_to_4": (0.54 / (x + 1)), "3_to_4": (0.54 / (x + 1)) } I = Matrix(5, 1, [In * DR / (DR + 1), In / (DR + 1), 0, 0, 0]) F = Matrix( 5, 1, [ k_1 * C_1, k_2 * C_2, (k_3 - k_3 * 0.46 / (x + 1)) * C_3, (k_4 - k_4 * 0.54 / (x + 1)) * C_4, #k_5*C_5]) 0 * C_5 ]) Mod = RExample(C, alphas, F, I, who_am_i()) Mod.addParameterSet({ k_1: 10, k_2: 0.3, k_3: 0.66, k_4: 0.02, #k_5:0, DR: 1.44, clay: 23.4, In: 1.7, C_0: Matrix(5, 1, [0.3, 0.3, 0.3, 0.3, 0.3]), t_start: 0, t_end: 200, tn: 400 }) J = Mod.jacobian() # in this case the system is linear and the # Jacobian represents a Matrix that is not C dependent # furthermore the RothC model has a stagnant pool (k5=0) which is # expressed mathematically by the fact that the Jacobian is # rank deficient and thus not invertable # The nullspace or kernel of J is of dimension 1 which translates # into a one dimensional vectorspace of fixed points in contrast # to the unique solution of a non singular Jacobian as usual. # We represent this degree of freedom by the free choice of C5 # and solve only the remaining system solutions = J[0:4, 0:4].LUsolve(-I[0:4, 0]) #ss=J[0:2,0:2].LUsolve(I[0:2,0]) pprint(solutions) Mod.suggestFixedPoint({ C_1: simplify(solutions[0]), C_2: simplify(solutions[1]), C_3: simplify(solutions[2]), C_4: simplify(solutions[3]), C_5: C_5 }) Mod.latexSummary() Mod.writeSoilRModel()
def test_MEND_NUM(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") P, M, Q, B, De, EP, EM = symbols("P, M, Q, B, De, EP, EM", nonnegative=True) C = Matrix(7, 1, [P, M, Q, B, De, EP, EM]) V_P = Symbol( "V_P", real=True) # maximum specific decomposition rate for P by EP. K_P = Symbol( "K_p", real=True) # half-saturation constant for decomposition of P. V_M = Symbol( "V_M", real=True) # maximum specific decomposition rate for M by EM. K_M = Symbol( "K_M", real=True) # half-saturation constant for decomposition of M. K_BA = Symbol("K_BA", real=True) V_D = Symbol( "V_De", real=True) # maximum specific uptake rate of D for growth of B K_D = Symbol( "K_D", real=True ) # half-saturation constant of uptake of D for growth of B m_R = Symbol("m_R", real=True) # specific maintenance factor or rate. E_C = Symbol("E_C", real=True) # carbon use efficiency. f_D = Symbol("f_D", real=True) # fraction of decomposed P allocated to D g_D = Symbol("g_D", real=True) # fraction of dead B allocated to D p_EP = Symbol("p_EP", real=True) # fraction of mR for production of EP. p_EM = Symbol("p_EM", real=True) # fraction of mR for production of EM. r_EP = Symbol("r_EP", real=True) # turnover rate of EP. r_EM = Symbol("r_EM", real=True) # turnover rate of EM. Q_max = Symbol("Q_max", real=True) # maximum DOC sorption capacity. K_des = Symbol("K_des", real=True) # desorption rate. K_ads = K_BA * K_des # specific adsorption rate. #K_ads=Symbol("K_ads", real=True) # specific adsorption rate. I_P = Symbol("I_P", real=True) # input rate of P. I_D = Symbol("I_D", real=True) # input rate of D. P_E = p_EP + p_EM F_R = B * ((1 / E_C) - 1) * (De * (V_D + m_R)) / (K_D + De) F_E = B * m_R O_B = F_R + F_E F_U = De * ((V_D + m_R) / E_C) * (B / (K_D + De)) F_A = De * (K_ads * (1 - Q) / Q_max) O_D = F_U + F_A f_E = (1 - (F_R / O_B)) f_U = (1 - (F_A / O_D)) f_A = (1 - (F_U / O_D)) alphas = { "1_to_2": 1 - f_D, "1_to_5": f_D, "2_to_5": 1, "3_to_5": 1, "4_to_1": (1 - g_D) * (1 - P_E) * f_E, "4_to_5": g_D * (1 - P_E) * f_E, "4_to_6": p_EP * f_E, "4_to_7": p_EM * f_E, "5_to_4": f_U, "5_to_3": f_A } I = Matrix(7, 1, [I_P, 0, 0, 0, I_D, 0, 0]) F = Matrix(7, 1, [(V_P * EP * P) / (K_P + P), (V_M * EM * M) / (K_M + M), (K_des * Q) / Q_max, O_B, O_D, r_EP * EP, r_EM * EM]) Mod = RExample(C, alphas, F, I, who_am_i()) Cdot = I + Mod.getOperator() #analytical fixed point solutions #for unique solutions we can extract the information automatically #solutions=solve(Cdot,[C[i] for i in range(0,len(C))]) #Mod.suggestFixedPoint( {C[i]:solutions[C[i]] for i in range(0,len(C))}) #s1={V_P:2.5, K_P:50, V_M:1, K_M:250, V_D:0.0005, K_D:0.26, m_R:0.00028, E_C:0.47, f_D:0.5, g_D:0.5, p_EP:0.01, p_EM:0.01, r_EP:0.001, r_EM:0.001, Q_max:1.7, K_ads:0.006, K_des:0.001, I_P:0.00008, I_D:0.00008} A = 1 - E_C + (1 - p_EP - p_EM) * E_C * (1 - g_D) * (I_D / I_P + 1) Beq = (I_D + I_P) / (1 / (E_C - 1) * m_R) f1 = { P: K_P / (V_P * p_EP / r_EP * E_C / A * (I_D / I_P + 1) - 1), M: K_M / (V_M * p_EM / r_EM * E_C / ((1 - f_D) * A) * (1 + I_D / I_P) - 1), Q: Q_max / (1 + V_D / (m_R * K_D * K_BA)), B: Beq, De: K_D / (V_D / m_R), EP: Beq * m_R * p_EP / r_EP, EM: Beq * m_R * p_EM / r_EM } p1 = { V_P: 2.5, K_P: 50, V_M: 1, K_M: 250, V_D: 0.0005, K_D: 0.26, m_R: 0.00028, E_C: 0.47, f_D: 0.5, g_D: 0.5, p_EP: 0.01, p_EM: 0.01, r_EP: 0.001, r_EM: 0.001, Q_max: 1.7, K_BA: 6, #K_ads:0.006, K_des: 0.001, I_P: 0.00008, I_D: 0.00008, C_0: Matrix(7, 1, [.3, .3, .3, .3, .3, .3, .3]), t_start: 0, t_end: 200, tn: 400 } f1_num = {key: val.subs(p1) for key, val in f1.items()} Mod.suggestFixedPoint(f1_num) Mod.addParameterSet(p1) # #numerical solutionss # CdotNum=Cdot.subs(p1) # JNum=Mod.jacobian().subs(p1) # from scipy.optimize import fsolve,root # from numpy import array # import math # def evalJ(intup): # # read from the input tuple # dic={C[i]:intup[i] for i in range(0,len(intup))} # M=JNum.subs(dic) # return(array(M.tolist(),dtype="float")) # #Jeval=lambdify(tuple(C),JNum,use_array=True) # def evalCdotNum(intup): # # read from the input tuple # dic={C[i]:intup[i] for i in range(0,len(intup))} # outtup=tuple(CdotNum.subs(dic)) # return(outtup) # #sol=fsolve( # # #full_output=True, # # func=evalCdotNum, # # fprime=evalJ, # # maxfev=10000, # # x0=tuple([20 for i in range(0,len(C))])) # #print(sol) # #print(evalCdotNum(sol)) # sol2=root( # evalCdotNum, # tuple([.1 for i in range(0,len(C))]), # method="hybr", # jac=evalJ) # print(sol2) # #test the result # print(evalCdotNum(sol2.x)) Mod.latexComponents()
def test_MEND(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") P, M, Q, B, De, EP, EM = symbols("P, M, Q, B, De, EP, EM") C = Matrix(7, 1, [P, M, Q, B, De, EP, EM]) V_P = Symbol( "V_P", real=True, positive=True) # maximum specific decomposition rate for P by EP. K_P = Symbol( "K_p", real=True, positive=True) # half-saturation constant for decomposition of P. V_M = Symbol( "V_M", real=True, positive=True) # maximum specific decomposition rate for M by EM. K_M = Symbol( "K_M", real=True, positive=True) # half-saturation constant for decomposition of M. K_BA = Symbol("K_BA", real=True, positive=True) V_D = Symbol( "V_D", real=True, positive=True) # maximum specific uptake rate of D for growth of B K_D = Symbol( "K_D", real=True, positive=True ) # half-saturation constant of uptake of D for growth of B m_R = Symbol("m_R", real=True, positive=True) # specific maintenance factor or rate. E_C = Symbol("E_C", real=True, positive=True) # carbon use efficiency. f_D = Symbol("f_D", real=True, positive=True) # fraction of decomposed P allocated to D g_D = Symbol("g_D", real=True, positive=True) # fraction of dead B allocated to D p_EP = Symbol("p_EP", real=True, positive=True) # fraction of mR for production of EP. p_EM = Symbol("p_EM", real=True, positive=True) # fraction of mR for production of EM. r_EP = Symbol("r_EP", real=True, positive=True) # turnover rate of EP. r_EM = Symbol("r_EM", real=True, positive=True) # turnover rate of EM. Q_max = Symbol("Q_max", real=True, positive=True) # maximum DOC sorption capacity. K_des = Symbol("K_des", real=True, positive=True) # desorption rate. #K_ads=Symbol("K_ads", real=True) # specific adsorption rate. K_ads = K_BA * K_des # specific adsorption rate. I_P = Symbol("I_P", real=True, positive=True) # input rate of P. I_D = Symbol("I_D", real=True, positive=True) # input rate of D. P_E = p_EP + p_EM F_R = B * ((1 / E_C) - 1) * (De * (V_D + m_R)) / (K_D + De) F_E = B * m_R O_B = F_R + F_E F_U = De * ((V_D + m_R) / E_C) * (B / (K_D + De)) F_A = De * (K_ads * (1 - Q) / Q_max) O_D = F_U + F_A f_E = (1 - (F_R / O_B)) f_U = (1 - (F_A / O_D)) f_A = (1 - (F_U / O_D)) alphas = { "1_to_2": 1 - f_D, "1_to_5": f_D, "2_to_5": 1, "3_to_5": 1, "4_to_1": (1 - g_D) * (1 - P_E) * f_E, "4_to_5": g_D * (1 - P_E) * f_E, "4_to_6": p_EP * f_E, "4_to_7": p_EM * f_E, "5_to_4": f_U, "5_to_3": f_A } I = Matrix(7, 1, [I_P, 0, 0, 0, I_D, 0, 0]) F = Matrix(7, 1, [(V_P * EP * P) / (K_P + P), (V_M * EM * M) / (K_M + M), (K_des * Q) / Q_max, O_B, O_D, r_EP * EP, r_EM * EM]) Mod = RExample(C, alphas, F, I, who_am_i()) Cdot = I + Mod.getOperator() # Unique solutions we can often compute automatically and # extract the information automatically # but for this example the computation is too expensive # Fortunately the fixed points are published in the original pater A = 1 - E_C + (1 - p_EP - p_EM) * E_C * (1 - g_D) * (I_D / I_P + 1) Beq = (I_D + I_P) / (1 / (E_C - 1) * m_R) f1 = { P: K_P / (V_P * p_EP / r_EP * E_C / A * (I_D / I_P + 1) - 1), M: K_M / (V_M * p_EM / r_EM * E_C / ((1 - f_D) * A) * (1 + I_D / I_P) - 1), Q: Q_max / (1 + V_D / (m_R * K_D * K_BA)), B: Beq, De: K_D / (V_D / m_R), EP: Beq * m_R * p_EP / r_EP, EM: Beq * m_R * p_EM / r_EM } p1 = { V_P: 2.5, K_P: 50, V_M: 1, K_M: 250, V_D: 0.0005, K_D: 0.26, m_R: 0.00028, E_C: 0.47, f_D: 0.5, g_D: 0.5, p_EP: 0.01, p_EM: 0.01, r_EP: 0.001, r_EM: 0.001, Q_max: 1.7, K_BA: 6, #K_ads:0.006, K_des: 0.001, I_P: 0.00008, I_D: 0.00008, C_0: Matrix(7, 1, [.3, .3, .3, .3, .3, .3, .3]), t_start: 0, t_end: 200, tn: 400 } f1_num = {key: val.subs(p1) for key, val in f1.items()} Mod.suggestFixedPoint(f1) #Mod.suggestFixedPoint(f1_num) #Mod.addParameterSet(p1) Mod.latexSummary() Mod.writeSoilRModel()
def test_twoPMacrobial(self): # This model is releates to TwopMMmodel # C pools and startvector S, B, C_0 = symbols("S, B, C_0") C = Matrix(2, 1, [S, B]) #respired carbon fraction r = symbols("r") # a scalar representing the Activity factor; # i.e. a temperature and moisture modifier (unitless) A_f = symbols("A_f") # the michaelis konstant K_m = symbols("K_m") #decay rates for (S)oil and (B)acteria k_s, k_b = symbols("k_s, k_b") #input flux to pool S ADD = symbols("ADD") # the alphas have to be a function of C and t (at most) alphas = {"1_to_2": 1 - r, "2_to_1": 1} F = Matrix(2, 1, [A_f * k_s * B * (S / (K_m + S)), k_b * B]) I = Matrix(2, 1, [ADD, 0]) tPM = RExample(C, alphas, F, I, who_am_i()) #times and time steps for the numeric modelling t_start, t_end, tn = symbols("t_start,t_end,tn") tPM.addParameterSet({ ADD: 3.3, A_f: 1, k_s: 0.000018, k_b: 0.007, K_m: 900, r: 0.6, t_start: 0, t_end: 2000, tn: 2000, C_0: Matrix(2, 1, [100, 10]) }) tPM.addParameterSet({ ADD: 3.3, A_f: 3, k_s: 0.000018, k_b: 0.0000001, K_m: 900, r: 0.6, t_start: 0, t_end: 200000, tn: 2000, C_0: Matrix(2, 1, [972, 304]) }) tPM.addParameterSet({ ADD: 3.3, A_f: 3, k_s: 0.000018, k_b: 0.0000001, K_m: 900, r: 0.6, t_start: 0, t_end: 20000, tn: 2000, C_0: Matrix(2, 1, [4.18604651162791, 22000000.0]) }) tPM.addParameterSet({ ADD: 345, A_f: 1, k_s: 42.82, k_b: 4.38, K_m: 269774.1, r: 0.2, t_start: 0, t_end: 20000, tn: 2000, C_0: Matrix(2, 1, [4.18604651162791, 22000000.0]) }) tPM.suggestFixedPoint({ S: k_b * K_m / (A_f * k_s * (1 - r) - k_b), B: ADD * (1 - r) / (k_b * r) }) tPM.writeSoilRModel() tPM.latexSummary()
def test_AWB(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") B, E, S, D = symbols("B, E, S, D") C = Matrix(4, 1, [B, E, S, D]) V_M = Symbol("V_M", real=True) # Maximum rate of uptake. V_m = Symbol("V_m", real=True) # maximum rate of SOM decomposition. r_B = Symbol("r_B", real=True) # Microbial death rate. r_E = Symbol("r_E", real=True) # Rate enzyme production. r_L = Symbol("r_L", real=True) # Rate enzyme loss. a_BS = Symbol("a_BS", real=True) # Fraction of dead microbial biomass to SOM. epsilon_0 = Symbol("epsilon_0", real=True) # intercenpt of CUE function. epsilon_s = Symbol("epsilon_s", real=True) # Slope of CUE function. Km_0 = Symbol("Km_0", real=True) # Intercept of half-sat. function. Km_s = Symbol("Km_s", real=True) # Slope of half-sat. function. Km_u0 = Symbol("Km_u0", real=True) # Intercept of half-sat. function of uptake. Km_us = Symbol("Km_us", real=True) # Slope of half-sat. function of uptake. Ea = Symbol("Ea", real=True) # Activation energy. R = Symbol("R", real=True) # Gas constant. T = Symbol("T", real=True) # Temperature. I_S = Symbol("I_S", real=True) # Inputs to SOC (S) pool. I_D = Symbol("I_D", real=True) # Inputs to DOC (D) pool. alphas = { "1_to_2": r_E / (r_B + r_E), "1_to_3": (a_BS * r_B) / (r_B + r_E), "1_to_4": r_B * (1 - a_BS) / (r_B + r_E), "4_to_1": epsilon_0 + epsilon_s * T } I = Matrix(4, 1, [0, 0, I_S, I_D]) F = Matrix(4, 1, [(r_B + r_E) * B, r_L * E, V_m * exp(-Ea / (R * (T + 273))) * (E * S) / ((Km_s * T + Km_0) + S), V_M * exp(-Ea / (R * (T + 273))) * (B * D) / ((Km_us * T + Km_u0) + D)]) Mod = RExample(C, alphas, F, I, who_am_i()) # computation does not finish after many hours # we should try to simplify the assumptions #Cdot=I+Mod.getOperator() #solutions=solve(Cdot,B, E, S, D) #Mod.suggestFixedPoint({ # B:simplify(solutions[B]), # E:simplify(solutions[E]), # S:simplify(solutions[S]), # D:simplify(solutions[D]), # }) Mod.addParameterSet({ V_M: 100000000, V_m: 100000000, r_B: 0.0002, r_E: 0.000005, r_L: 0.001, a_BS: 0.5, epsilon_0: 0.63, epsilon_s: 0.016, Km_0: 500, Km_u0: 0.1, Km_s: 0.5, Km_us: 0.1, Ea: 47, R: 0.008314, T: 20, I_S: 0.005, I_D: 0.005, t_start: 0, t_end: 2e5, tn: 2e4, C_0: Matrix(4, 1, [.1, .1, .1, .1]) }) Mod.latexSummary() Mod.writeSoilRModel()
def test_ICBM(self): C_0, t, t_start, t_end, tn = symbols( "C_0, t,t_start,t_end,tn", real=True ) # these always have to be present because the translation relies on them Y, O = symbols("Y,O") #Young and old carbon pools h = Symbol( "h" ) #Humification coefficient. Fraction of the decomposed young C transferred to old pool k1 = Symbol("k1") #Decomposition rate of the young pool (yr-1). k2 = Symbol("k2") #Decomposition rate of the old pool (yr-1). r = Symbol("r") #External (climatic) effect on decomposition. i = symbols("i") # Mean annual carbon input (kg C m-2 yr-1). # the alphas have to be a function of C and t (at most) alphas = {"1_to_2": h} F = Matrix(2, 1, [r * k1 * Y, r * k2 * O]) C = Matrix(2, 1, [Y, O]) I = Matrix(2, 1, [i, 0]) M = RExample(C, alphas, F, I, who_am_i()) Cdot = I + M.getOperator() print(Cdot.shape) solutions = solve(Cdot, Y, O) M.suggestFixedPoint({ Y: simplify(solutions[Y]), #Y:i/(r*k1), O: simplify(solutions[O]) #O:(h*i)/(r*k2) }) dic = { #+N +straw h: 0.125, k1: 0.8, k2: 0.00605, r: 1.0, i: 0.285, # the following always have to be present C_0: Matrix(2, 1, [0.3, 4.11]), t_start: 0, t_end: 200, tn: 400 } M.addParameterSet(dic) M.addParameterSet({ #Bare fallow h: 0.13, k1: 0.8, k2: 0.00605, r: 1.32, i: 0, C_0: Matrix(2, 1, [0.3, 3.96]), t_start: 0, t_end: 200, tn: 400 }) M.addParameterSet({ # -N +Straw h: 0.125, k1: 0.8, k2: 0.00605, r: 1.22, i: 0.248, C_0: Matrix(2, 1, [0.3, 4.05]), t_start: 0, t_end: 200, tn: 400 }) M.addParameterSet({ # -N -Straw h: 0.125, k1: 0.8, k2: 0.00605, r: 1.17, i: 0.057, C_0: Matrix(2, 1, [0.3, 3.99]), t_start: 0, t_end: 200, tn: 400 }) M.addParameterSet({ # +N -Straw h: 0.125, k1: 0.8, k2: 0.00605, r: 1.07, i: 0.091, C_0: Matrix(2, 1, [0.3, 4.02]), t_start: 0, t_end: 200, tn: 400 }) M.addParameterSet({ # Farmyard manure h: 0.25, k1: 0.8, k2: 0.00605, r: 1.1, i: 0.272, C_0: Matrix(2, 1, [0.3, 3.99]), t_start: 0, t_end: 200, tn: 400 }) M.addParameterSet({ # Sewage sludge h: 0.34, k1: 0.8, k2: 0.00605, r: 0.97, i: 0.296, C_0: Matrix(2, 1, [0.3, 4.14]), t_start: 0, t_end: 200, tn: 400 }) M.writeSoilRModel() M.latexSummary()
def test_Manzoni(self): # This model is releates to TwopMMmodel # and Manzoni # C pools and startvector C_S, C_B, C_0 = symbols("C_S, C_B, C_0", real=True) C = Matrix(2, 1, [C_S, C_B]) #respired carbon fraction r = symbols("r") # a scalar representing the Activity factor; # i.e. a temperature and moisture modifier (unitless) A_f = symbols("A_f") # the michaelis konstant K_m = symbols("K_m") #decay rates for (S)oil and (B)acteria k_S, k_B = symbols("k_S, k_B") #input flux to pool S ADD = symbols("ADD") # the alphas have to be a function of C and t (at most) alphas = {"1_to_2": 1 - r, "2_to_1": 1} F = Matrix(2, 1, [k_S * C_B * (C_S / (K_m + C_S)), k_B * C_B]) I = Matrix(2, 1, [ADD, 0]) tPM = RExample(C, alphas, F, I, who_am_i()) #times and time steps for the numeric modelling t, t_start, t_end, tn = symbols("t,t_start,t_end,tn", real=True) # the following parameter set should produce a negative fixed point # since C_S*=k_BK_M/(k_s(1-r)-kb) and k_s(1-r)<kb dic = { ADD: 3.3, k_S: 4e-3, k_B: 2.3e-3, K_m: 1000, K_m: 900, r: 0.6, t_start: 0, t_end: 1000, tn: 2000, "C_Ranges": [np.linspace(0, 20, num=50), np.linspace(0, 20, num=50)], C_0: Matrix(2, 1, [100, 10]) } tPM.addParameterSet(dic) dic = { ADD: 3.3, k_S: 8e-3, k_B: 2.3e-3, K_m: 1000, r: 0.6, t_start: 0, t_end: 1000, tn: 2000, "C_Ranges": [np.linspace(0, 20, num=50), np.linspace(0, 20, num=50)], C_0: Matrix(2, 1, [100, 10]) } tPM.addParameterSet(dic) tPM.suggestFixedPoint({ C_S: k_B * K_m / (k_S * (1 - r) - k_B), C_B: ADD * (1 - r) / (k_B * r) }) #tPM.latexAttractionLandscape() #tPM.writeSoilRModel() tPM.latexSummary()
def test_Century(self): C_0, t = symbols("C_0, t", real=True) t_start, t_end, tn = symbols("t_start,t_end,tn") C_1, C_2, C_3, C_4, C_5 = symbols("C_1, C_2, C_3, C_4, C_5") C = Matrix(5, 1, [C_1, C_2, C_3, C_4, C_5]) k_1 = Symbol("k_1", nonnegative=True, real=True) # Decomposition rate of the structural litter. k_2 = Symbol("k_2", nonnegative=True, real=True) # Decomposition rate of the metabolic littter. k_3 = Symbol("k_3", nonnegative=True, real=True) # Decomposition rate of the Active pool. k_4 = Symbol("k_4", nonnegative=True, real=True) # Decomposition rate of the Slow pool. k_5 = Symbol("k_5", nonnegative=True, real=True) # Decomosition rate of the Passive pool. In = Symbol("In", nonnegative=True, real=True) # Carbon inputs. LN = Symbol("LN", nonnegative=True, real=True) # Lignin to nitrogen ratio. Ls = Symbol( "Ls", nonnegative=True, real=True) # Fraction of structural material that is lignin. c = Symbol("c", nonnegative=True, real=True) # Proportion of clay in mineral soil. s = Symbol("s", nonnegative=True, real=True) # Proportion of silt in mineral soil. alpha31 = Symbol("alpha31", real=True) # Transfer coefficient. alpha32 = Symbol("alpha32", real=True) # Transfer coefficient. alpha34 = Symbol("alpha34", real=True) # Transfer coefficient. alpha35 = Symbol("alpha35", real=True) # Transfer coefficient. alpha41 = Symbol("alpha41", real=True) # Transfer coefficient. alpha53 = Symbol("alpha53", real=True) # Transfer coefficient. alpha54 = Symbol("alpha54", real=True) # Transfer coefficient. Fm = 0.85 - 0.18 * LN Fs = 1 - Fm Tx = c + s fTx = 1 - 0.75 * Tx Es = 0.85 - 0.68 * Tx alpha43 = 1 - Es - alpha53 alphas = { "1_to_3": alpha31, "2_to_3": alpha32, "4_to_3": alpha34, "5_to_3": alpha35, "1_to_4": alpha41, "3_to_5": alpha53, "3_to_4": alpha43, "4_to_5": alpha54 } I = Matrix(5, 1, [In * Fm, In * Fs, 0, 0, 0]) F = Matrix(5, 1, [ k_1 * C_1 * exp(-3.0 * Ls), k_2 * C_2, k_3 * C_3 * fTx, k_4 * C_4, k_5 * C_5 ]) Mod = RExample(C, alphas, F, I, who_am_i()) Cdot = I + Mod.getOperator() solutions = solve(Cdot, [C[i] for i in range(0, len(C))]) pprint(solutions) Mod.suggestFixedPoint( {C[i]: solutions[C[i]] for i in range(0, len(C))}) Mod.addParameterSet({ k_1: 0.094, k_2: 0.35, k_3: 0.14, k_4: 0.0038, k_5: 0.00013, c: 0.2, s: 0.45, LN: 0.5, Ls: 0.1, In: 0.1, alpha31: 0.45, alpha32: 0.55, alpha34: 0.42, alpha35: 0.45, alpha41: 0.3, alpha53: 0.004, alpha54: 0.03, t_start: 0, t_end: 2e5, tn: 2e4, C_0: Matrix(5, 1, [.1, .1, .1, .1, .1]) }) Mod.latexSummary() Mod.writeSoilRModel()