Ordinary differential equations: Separable differential equations
Exact solutions of an ODE with Python
Python has the package Symbolic Python
on board to do exact calculations. A few examples give an idea of how it works.
General solution We consider the differential equation \[\frac{\dd y}{\dd t} = t\,y\] Using the method of separation of variables, you can find a general solution \[y(t)=c\cdot e^{\frac{1}{2}t^2}\] for some constant \(c\). Python can also determine this solution through the dsolve
function in the sympy
package:
>>> import sympy as sy # load the sympy package and use an acronym
>>> t = sy.symbols('t') # make a symbol t
>>> y = sy.Function('y') # make a symbolic function y
>>> ODE = sy.Eq(sy.Derivative(y(t),t), t*y(t)) # the ODE
>>> ysol = sy.dsolve(ODE, y(t)); ysol # determine the solution of the ODE
y(t) = C1*exp(t**2/2))
Initial Value Problem In the dsolve
command you also specify the initial value as an equation. We take as an example the initial value problem \[\frac{\dd y}{\dd t} = y^2,\quad y(0)=1\] Using the method of separation of variables, you can find a general solution \[y(t)=\frac{1}{c-t}\] for some constant \(c\). From \(y(0)=1\) follows that \(c=1\). Python can also determine this solution via the dsolve
function:
>>> import sympy as sy # load the sympy package and use an acronym
>>> sy.init_printing() # just for nicer display
>>> t = sy.symbols('t') # make a symbol t
>>> y = sy.Function('y') # make a symbolic function y >>> ODE = sy.Eq(sy.Derivative(y(t),t), y(t)**2) # the differential equation
>>> ysol= sy.dsolve(ODE, y(t), ics = {y(0):1}) # solve the initial value problem
>>> ysol
-1
y(t) = -----
t - 1
>>> gensol = sy.dsolve(ODE, y(t)) # determine general solution >>> constant = sy.solve([gensol.rhs.subs(t,0)-1]) # determine the constant
>>> ysol = gensol.subs(constant); ysol
-1
y(t) = -----
t - 1
ODE of order 2 The example is the initial value problem \[\frac{\dd^2y}{\dd t^2} -3\frac{\dd y}{\dd t}+ 2y = 0, \quad y(0)=-1,\quad \frac{dy}{dt}(0) = -3\] In the next section we will learn how to solve this problem, but the solution is \[y(t)=e^t - 2e^{2t}\] In the program below, we have use an alternative to specify derivatives in the differential equation and the initial conditions
>>> import sympy as sy # load the sympy package and use an acronym
>>> sy.init_printing() # just for nicer display
>>> t = sy.symbols('t') # make a symbol t
>>> y = sy.Function('y') # make a symbolic function y
>>> ODE = sy.Eq(y(t).diff(t,2)-3*y(t).diff(t) + 2*y(t), 0); ODE
2
d d
2*y(t) - 3*--(y(t)) + ---(y(t)) = 0
dt 2
dt
>>> ysol = sy.dsolve(ODE, y(t), ics = {y(0):-1, sy.diff(y(t),t).subs(t,0):-3}); ysol
2*t t
y(t) = - 2*e + e
>>> gensol = sy.dsolve(ODE, y(t)); genopl # the general solution
/ t\ t
y(t) = \C1 + C2*e /*e
>>> # define equations for initial values and solve them.
>>> constants = sy.solve([gensol.rhs.subs(t,0)+1, gensol.rhs.diff(t).subs(t,0)+3])
>>> ysol = gensol.subs(constants); ysol # substitution of the values found
/ t \ t
y(t) = \- 2*e + 1/*e
>>> sy.expand(ysol) # expand brackets and simplify
2*t t
y(t) = - 2*e + e
We continue this example to show how you can compute further with the symbolic solution in numerical sense. Substituting values of \(t\) does not work straightforwardly because ysol
is a symbolic expression. Use lambdify
to construct a function from the symbolic expression for \(y(t)\).
>>> yfun = sy.lambdify(t, yopl.rhs, "math")
>>> list(map(yfun, [0,1,2]))
[-1.0, -12.059830369402254, -101.80724396735783]