Systems of ODEs
The ODESystem class is what we use to represent our system of ordinary differential equations.
Creating ODESystems
There are a number of different ways of creating an ODESystem.
- class desr.ode_system.ODESystem(variables, derivatives, indep_var=None, initial_conditions=None, same_units=None, constraints=None, is_reduced=False)[source]
A system of differential equations.
The main attributes are
variablesandderivatives.variablesis an ordered tuple of variables, which includes the independent variable.derivativesis an ordered tuple of the same length that contains the derivatives with respect toindep_var.- Parameters:
variables (tuple of sympy.Symbol) – Ordered tuple of variables.
derivatives (tuple of sympy.Expression) – Ordered tuple of derivatives.
indep_var (sympy.Symbol, optional) – Independent variable we are differentiating with respect to.
initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
sympy.Symbol (same_units (dict of) – sympy.Expression): lists of things that must have the same units.
- classmethod ODESystem.from_equations(equations, indep_var=t, initial_conditions=None, is_reduced=False)[source]
Instantiate from multiple equations.
- Parameters:
equations (str, iter of str) – Equations of the form “dx/dt = expr”, optionally seperated by
n.indep_var (sympy.Symbol) – The independent variable, usually
t.initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
- Returns:
System of equations.
- Return type:
>>> eqns = ['dx/dt = c_0*x*y', 'dy/dt = c_1*(1-x)*(1-y)'] >>> ODESystem.from_equations(eqns) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(1 - x)*(1 - y) dc_0/dt = 0 dc_1/dt = 0 >>> eqns = '\n'.join(['dy/dx = c_0*x*y', 'dz/dx = c_1*(1-y)*z**2']) >>> ODESystem.from_equations(eqns, indep_var=sympy.Symbol('x')) dx/dx = 1 dy/dx = c_0*x*y dz/dx = c_1*z**2*(1 - y) dc_0/dx = 0 dc_1/dx = 0
- classmethod ODESystem.from_dict(deriv_dict, indep_var=t, initial_conditions=None, is_reduced=False)[source]
Instantiate from a text of equations.
- Parameters:
deriv_dict (dict) – {variable: derivative} mapping.
indep_var (sympy.Symbol) – Independent variable, that the derivatives are with respect to.
initial_conditions (tuple of sympy.Symbol) – The initial values of non-constant variables
- Returns:
System of ODEs.
- Return type:
>>> _input = {'x': 'c_0*x*y', 'y': 'c_1*(1-x)*(1-y)'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.items()} >>> ODESystem.from_dict(_input) dt/dt = 1 dx/dt = c_0*x*y dy/dt = c_1*(1 - x)*(1 - y) dc_0/dt = 0 dc_1/dt = 0
>>> _input = {'y': 'c_0*x*y', 'z': 'c_1*(1-y)*z**2'} >>> _input = {sympy.Symbol(k): sympy.sympify(v) for k, v in _input.items()} >>> ODESystem.from_dict(_input, indep_var=sympy.Symbol('x')) dx/dx = 1 dy/dx = c_0*x*y dz/dx = c_1*z**2*(1 - y) dc_0/dx = 0 dc_1/dx = 0
- classmethod ODESystem.from_tex(tex, is_reduced=False)[source]
Given the LaTeX of a system of differential equations, return a ODESystem of it.
- Parameters:
tex (str) – LaTeX
- Returns:
System of ODEs.
- Return type:
>>> eqns = ['\frac{dE}{dt} &= - k_1 E S + k_{-1} C + k_2 C \\', ... '\frac{dS}{dt} &= - k_1 E S + k_{-1} C \\', ... '\frac{dC}{dt} &= k_1 E S - k_{-1} C - k_2 C \\', ... '\frac{dP}{dt} &= k_2 C'] >>> ODESystem.from_tex('\n'.join(eqns)) dt/dt = 1 dC/dt = -C*k_2 - C*k_m1 + E*S*k_1 dE/dt = C*k_2 + C*k_m1 - E*S*k_1 dP/dt = C*k_2 dS/dt = C*k_m1 - E*S*k_1 dk_1/dt = 0 dk_2/dt = 0 dk_m1/dt = 0
Todo
Allow initial conditions to be set from tex.
Finding Scaling Actions
- ODESystem.exponent_matrix()[source]
Determine the ‘exponent’ or ‘power’ matrix of the system, denoted by \(K\) in the literature, by gluing together the power matrices of each derivative, initial condition, constraint, and require-same-variable.
In particular, it concatenates \(K_{\left(\frac{t}{x} \cdot \frac{dx}{dt}\right)}\) for \(x\) in
variables, where \(t\) is the independent variable.>>> eqns = '\n'.join(['ds/dt = -k_1*e_0*s + (k_1*s + k_m1)*c', ... 'dc/dt = k_1*e_0*s - (k_1*s + k_m1 + k_2)*c']) >>> system = ODESystem.from_equations(eqns) >>> system.variables (t, c, s, e_0, k_1, k_2, k_m1) >>> system.exponent_matrix() Matrix([ [1, 1, 1, 1, 1, 1, 1], [0, 0, 0, -1, 0, 1, 1], [1, 0, 0, 1, 0, 0, -1], [0, 0, 0, 1, 1, 0, 0], [1, 0, 0, 1, 1, 1, 0], [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1]])
While we get a different answer to the example in the paper, this is just due to choosing our reference exponent in a different way.
Todo
Change the code to agree with the paper.
>>> system.update_initial_conditions({'s': 's_0'}) >>> system.exponent_matrix() Matrix([ [1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, -1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, -1, 1], [0, 0, 0, 1, 1, 0, 0, 0], [1, 0, 0, 1, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, -1]])
- ODESystem.maximal_scaling_matrix()[source]
Determine the maximal scaling matrix leaving this system invariant.
- Returns:
Maximal scaling matrix.
- Return type:
sympy.Matrix
>>> eqns = '\n'.join(['ds/dt = -k_1*e_0*s + (k_1*s + k_m1)*c', ... 'dc/dt = k_1*e_0*s - (k_1*s + k_m1 + k_2)*c']) >>> system = ODESystem.from_equations(eqns) >>> system.maximal_scaling_matrix() Matrix([ [1, 0, 0, 0, -1, -1, -1], [0, 1, 1, 1, -1, 0, 0]])
Output Functions
There are a number of useful ways to output the system.
- ODESystem.derivative_dict
expr mapping, filtering out the
None’s in expr.- Returns:
Keys are non-constant variables, value is the derivative with respect to the independent variable.
- Return type:
dict
- Type:
Return a variable
- ODESystem.to_tex()[source]
- Returns:
TeX representation.
- Return type:
str
>>> eqns = ['dC/dt = -C*k_2 - C*k_m1 + E*S*k_1', ... 'dE/dt = C*k_2 + C*k_m1 - E*S*k_1', ... 'dP/dt = C*k_2', ... 'dS/dt = C*k_m1 - E*S*k_1'] >>> system = ODESystem.from_equations('\n'.join(eqns)) >>> print(system.to_tex()) \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0
>>> system.update_initial_conditions({'C': 'C_0'}) >>> print(system.to_tex()) \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0 \\ \frac{dC_{0}}{dt} &= 0 \\ C\left(0\right) &= C_{0}
>>> system.add_constraint('K_m', '(k_m1 + k_2) / k_1') >>> print(system.to_tex()) \frac{dt}{dt} &= 1 \\ \frac{dC}{dt} &= - C k_{2} - C k_{-1} + E S k_{1} \\ \frac{dE}{dt} &= C k_{2} + C k_{-1} - E S k_{1} \\ \frac{dP}{dt} &= C k_{2} \\ \frac{dS}{dt} &= C k_{-1} - E S k_{1} \\ \frac{dk_{1}}{dt} &= 0 \\ \frac{dk_{2}}{dt} &= 0 \\ \frac{dk_{-1}}{dt} &= 0 \\ \frac{dC_{0}}{dt} &= 0 \\ \frac{dK_{m}}{dt} &= 0 \\ C\left(0\right) &= C_{0} \\ K_{m} &= \frac{k_{2} + k_{-1}}{k_{1}}