Chapter 5. Initial Value Problems for Ordinary Differential Equations

Initial value problems for ordinary differential equations (or systems) hardly need any motivation. They arise naturally in almost all sciences. In this chapter, we will focus on mastering numerical methods to solve these equations.

Throughout the chapter, we will explore all the techniques implemented in the SciPy stack through three common examples:

  • The trivial differential equation of the first order y'(t) = y(t) with the initial condition as y(0) = 1. The actual solution is y(t) = et.
  • A more complex differential equation of first order: a Bernoulli equation ty'(t) + 6y(t) = 3ty(t)3/4, with the initial condition y(1) = 1. The actual solution is y(t) = (3t5/2 + 7)4/(10000t6).
  • To illustrate the behavior with autonomous systems (where the derivatives do not depend on the time variable), we use a Lotka-Volterra model for one predator and one prey, y0'(t) = y0(t) – 0.1 y0(t) y1(t) and y1'(t) = –1.5 y1(t) + 0.075 y0(t) y1(t) with the initial condition y0(0) = 10 and y1(0) = 5 (representing 10 prey and 5 predators at the initial time).

    Note

    Higher-order differential equations can always be transformed into (non-necessarily autonomous) systems of differential equations. In turn, nonautonomous systems of differential equations can always be turned into autonomous by including a new variable in a smart way. The techniques to accomplish these transformations are straightforward, and explained in any textbook on differential equations.

We have the possibility of solving some differential equations analytically via SymPy. Although this is hardly the best way to solve initial value problems computationally—even when analytical solutions are available—we will illustrate some examples for completion. Reliable solvers are numerical in nature, and in this setting, there are mainly two ways to approach this problem—through analytic approximation methods, or with discrete-variable methods.

Symbolic solution of differential equations

Symbolic treatment of a few types of differential equations is coded in the SciPy stack through the module sympy.solvers.ode. At this point, only the following equations are accessible with this method:

  • First order separable
  • First order homogeneous
  • First order exact
  • First order linear
  • First order Bernoulli
  • Second order Liouville
  • Any order linear equations with constant coefficients

In addition to these, other equations might be solvable with the following techniques:

  • A power series solution for the first or second order equations (the latter only at ordinary and regular singular points)
  • The lie group method for the first order equations

Let's see these techniques in action with our one-dimensional examples, y' = y and the Bernoulli equation. Note the method of inputting a differential equation. We write it in the form F(t,y,y') = 0, and we feed the expression F(t,y,y') to the solver (see line 3 that follows). Also, notice how we code derivatives of a function using SymPy; the expression f(t).diff(t) represents the first derivative of f(t), for instance:

In [1]: from sympy.solvers import ode
In [2]: t = symbols('t'); 
   ...: f = Function('f')
In [3]: equation1 = f(t).diff(t) - f(t)
In [4]: ode.classify_ode(equation1)
Out[4]:
('separable',
 '1st_exact',
 '1st_linear',
 'almost_linear',
 '1st_power_series',
 'lie_group',
 'nth_linear_constant_coeff_homogeneous',
 'separable_Integral',
 '1st_exact_Integral',
 '1st_linear_Integral',
 'almost_linear_Integral')

Note

Note that some of the methods have a variant labeled with the suffix _Integral. This is a clever mechanism that allows us to complete the solution without actually computing the needed integrals. This is useful when facing expensive or impossible integrals.

The equation has been classified as a member of several types. We can now solve it according to the proper techniques of the corresponding type. For instance, we choose to solve this equation by first assuming that it is separable, and then by computing an approximation of degree four (n=4) to the solution with a power series representation (hint='1st_power_series') around x0=0:

In [5]: ode.dsolve(equation1, hint='separable')
Out[5]: f(t) == C1*exp(t)
In [6]: ode.dsolve(equation1, hint='1st_power_series', n=4, x0=0.0)
Out[6]: f(t) == C0 + C0*t + C0*t**2/2 + C0*t**3/6 + O(t**4)

Solving initial value problems is also possible, but only for solutions computed as a power series of first order differential equations:

In [7]: ode.dsolve(equation1, hint='1st_power_series', n=3, x0=0,
   ...:            ics={f(0.0): 1.0})
Out[7]: f(t) == 1.0 + 1.0*t + 0.5*t**2 + O(t**3)

Let's explore the second example with these techniques:

In [8]: equation2 = t*f(t).diff(t) + 6*f(t) - 3*t*f(t)**(0.75)
In [9]: ode.classify_ode(equation2)
Out[9]: ('Bernoulli', 'lie_group', 'Bernoulli_Integral')
In [10]: dsolve(equation2, hint='Bernoulli')
Out[10]: f(t) == (t**(-1.5)*(C1 + 0.3*t**2.5))**4.0
In [11]: dsolve(equation2, hint=lie_group')
Out[11]: f(t) == -5/(3*t*(C1*t**5 - 1))
[f(t) == 6.25e-6*(t**6*(625.0*C1**4 + 5400.0*C1*t**5 + 1296.0*t**10)
 - 120.0*sqrt(C1*t**17*(25.0*C1 + 36.0*t**5)**2))/t**12,
 f(t) == 6.25e-6*(t**6*(625.0*C1**4 + 5400.0*C1*t**5 + 1296.0*t**10)
 + 120.0*sqrt(C1*t**17*(25.0*C1 + 36.0*t**5)**2))/t**12]

Of course, although the functional expressions of both solutions in lines 10 and 11 are different, they represent the same function.

Note

For more information on how to use these techniques and code your own symbolic solvers, refer to the excellent documentation from the official SymPy pages at http://docs.sympy.org/dev/modules/solvers/ode.html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.134.17