40 Finding a “solution”
As you saw in the previous chapter, each differential equation in a dynamical system relates the derivative of a function to the function itself. For instance, in
In high-school mathematics, many algebraic problems were of the form, “Solve for
Having been exposed to this style in high school, you may have come to think of “finding a solution” as the only task to perform in working on a problem.
In working with dynamical systems, “finding a solution” is one of the several tasks, among others, that you might need to perform to serve the purpose of your modeling effort. But not every modeling purpose requires “finding a solution,” that is, finding the function
Given what you learned in studying Block 3 of this book, you likely will be tempted to approach the task of “finding a solution” by applying symbolic anti-differentiation techniques to the problem. After all, each differential equation in a dynamical system involves a function
Admittedly, in mathematics it is common to refer to integrating a differential equation, but this should be broadly understood as accumulating the increments
In this chapter we will introduce three different techniques to accumulating a solution to a differential equation or a pair of such equations. First, we will look again at the graphical method of “following the flow” in a plot of the flow field. This technique is mainly of use for developing intuition about the dynamics.
Second, we will develop a simple Euler method for accumulating a solution. Third, we will explore how to take a guess about the solution and, when the guess is good enough, refine that into an actual solution. This is called the method of ansätze.
Third, and briefly, we will look at some of the situations where symbolic anti-differentiation can be used. This includes a very brief introduction to substitution methods.
A differential equation like
In many texts and research papers, differential equations are written using Leibniz’s notation, like this:
This is exactly equivalent to our notation
An even more concise notation, originated by Isaac Newton, is to replace the
This dot notation is even more expressive when working with second-order differential equations involving second derivative. In the dot notation,
40.1 The flow field
With a pair of differential equations, as with the pendulum or the rabbit-fox model, each equation gives one component of the change in state. To draw the flow at single point in state space, evaluate the dynamical functions at that point. Each dynamical function contributes, as its output, one of the components of the state velocity vector. If the parameters in the model have been assigned numerical values, the result of evaluating the right-hand sides will be two numbers.
A case in point is the rabbit-fox system. The axes in the rabbit-fox state space are denominated in units of rabbit density
To to find the state velocity at, say,
Once you know the numerical vector value of the state velocity, you need to convert it to a form suitable for plotting in the state space. The conversion is needed because the state space is denominated in rabbit density and fox density, not in rabbit density per month or fox density per month. The conversion is accomplished by multiplying the state velocity vector by a small
The conversion produces a vector whose components are denominated in the same way as the state space and thus can be plotted meaningfully in the state space.
To illustrate, let’s draw a flow vector for the state space coordinate
To draw the entire flow field, repeat this process at many other points in the state space as in Figure 40.2.
Some people prefer a visualization of short segments of actual trajectories, as in the right panel in Figure 40.2, rather than the state velocity vector. This is a matter of personal preference.
With the flow field depicted in sufficient detail, you can now trace out trajectory.
To trace out a trajectory, select a initial condition for the system. Then follow the flow, taking only a small step in state space. The next step should be in the direction of the flow arrow at the end of the previous step.
The trajectory you draw will be only a sketch, but it can be effective for developing intuition. Figure 40.3 shows a semi-automated version of the go-with-the-flow method. The computer has been used to draw the arrows. When you click in the plot, the computer also undertakes calculation of the trajectory.
Regrettably, from such a sketch of the trajectory, you cannot easily construct
The next section will show you how the computer constructed the trajectory and how we can get information on the speed of the flow.
40.2 Euler method
Recall from Block 2 the limit definition of the derivative:
The differential equations specify the values of
Our starting point for solving each differential equation is to re-write it as a finite difference. To illustrate, we will solve the equation
Applying the finite difference definition, we get
Multiplying both sides of the above by
To use this, we start at the initial condition, say
time | state |
---|---|
0 | 0.2 |
Next, pick a value for
To fill in the next row, we apply the Euler formula. Sine
time | state |
---|---|
0.0 | |
0.1 |
The next step will bring us to time
time | state |
---|---|
0.0 | |
0.1 | |
0.2 |
Add as many rows to the table as you like; the process will be the same.
You will recognize this as an iterative process, as discussed in Chapter 32.
As is so often the case, it is wise to think about carrying out processes in terms of fundamental tasks accomplished by calculus operations—evaluate, differentiate, anti-differentiate, solve, find argmax, iterate. The obvious choice for integrating differential equations is “anti-differentiate,” but as described previously, the techniques we covered in Block 3 are not sufficient for the task. Instead, we use iteration to solve differential equations.
This example uses the software you have already seen, Iterate()
, to carry out the task. In practice, however, you will use a special form of Iterate()
called integrateODE()
that makes use of interpolation techniques to give a more precise answer.
To implement the iteration to solve
<- function(t, x, dt=0.1) {
next_step <- t + dt
t <- x + x*(1-x)*dt
x
c(t=t, x=x) # return value
}
Notice that we wrote next_step()
with an input slot for
Use Iterate()
to carry out the iteration of next_step()
. Note that we use the fargs
argument to Iterate()
to pass our selected value for dt
to the function next_step()
. We will run the iteration for 100 steps. With
<- Iterate(next_step, x0=c(t=0, x=0.2), n=100,
Soln fargs=list(dt=0.1))
n | t | x |
---|---|---|
0 | 0.0 | 0.2000000 |
1 | 0.1 | 0.2160000 |
2 | 0.2 | 0.2329344 |
... 101 rows in total ... | ||
99 | 9.9 | 0.9998595 |
100 | 10.0 | 0.9998736 |
We can now plot the time series
:::
In the previous example using Iterate()
to solve a differential equation, the output of the iteration was a data frame containing values for the solution at discrete times: 0, 0.1, 0.2, and so on. A data table is a perfectly good way to represent a function, but it is handier to have a function in a form that operations like slice_plot()
and D()
can be applied to. Another way to look at things is that, mathematically, the solution to a differential equation should be a continuous-time function. Fortunately, we have at hand the interpolation techniques covered in Chapter 33 to carry out the construction of a continuous-time function from a tabular representation. The R/mosaic function integrateODE()
connects together the iteration and interpolation to provide a solution that is in the form of continuous-time function(s).
Use the R/mosaic function integrateODE()
to solve differential equations numerically. It is a specialized function that handles sets of first-order differential equations, but any high-order differential equation can be separated into a set of first-order equations.
To illustrate, this command will solve the differential equation Iterate()
. ::: {.cell layout-align=“center” fig.showtext=‘false’}
<- integrateODE(dx ~ x*(1-x), x = 0.2,
Soln2 bounds(t=0:10), dt=0.01)
## Solution containing functions x(t).
The first argument is a tilde expression, but in a form that is different from from that used in functions such as D()
or contour_plot()
, etc. To the left of the tilde is a single name composed of the state variable—x
here—prefixed by a d
. The d
is just a reminder that we are describing not x
itself, but
The next argument is the initial condition. We are starting the integration at bounds()
sets the time interval for the integration and dt
sets the time step..
The output of integrateODE()
is an R structure of a type called a “list” that is new to us. The list contains the function(s) created by integrateODE()
which you refer to by name (x
) using a special form of R punctuation $
suited to lists.. In other words, Soln2$x
will be a function, which you can plot like any other function, for instance:
slice_plot(Soln2$x(t) ~ t, bounds(t=0:10))
This use of the R symbol $
is new to us. We won’t emphasize it here. Instead, we’ll use the traj_plot()
graphics function (introduced in Chapter 48) which already knows how to access the functions created by integrateODE()
.
traj_plot(x(t) ~ t, Soln2, bounds(t=0:10))
An important feature of integrateODE()
is its ability to handle sets of first-order differential equations. For instance, the rabbit/fox system
<- integrateODE(
Eco_soln ~ 0.66*r - 1.33*r*f,
dr ~ -f + r*f,
df r = 2, f = 0.5, #initial conditions
bounds(t=0:5), dt=0.1)
## Solution containing functions r(t), f(t).
::: You can plot the time series using slice_plot()
<- traj_plot(r(t) ~ t, Eco_soln, bounds(t=0:5)) %>% gf_labs(title="Rabbits")
pA <- traj_plot(f(t) ~ t, Eco_soln, bounds(t=0:5)) %>% gf_labs(title="Foxes")
pB ::grid.arrange(pA, pB, ncol=2) gridExtra
To plot the trajectory, simply change the tilde expression used in traj_plot()
. which creates a time series plot, traj_plot()
shows the trajectory.
traj_plot(f(t) ~ r(t), Eco_soln, nt=10)
:::
40.3 Symbolic solutions
Occasionally it is possible to integrate a differential equation using symbolic techniques. This is particularly true for differential equations that are linear. The example we will handle here is the first-order linear differential equation
A method we will use repeatedly in this block is called the “method of ansätze.” An ansatz (singular of the German “ansätze”) is, in this context, a guess for the solution. Since differential equations have been a central part of science for more than 200 years, you can imagine that a large library of equations and their solutions has been assembled. For the equations that are most frequently used and that can be solved symbolically, the solutions are already known. Thus, the “guess” for the solution can be a very well informed guess.
Let’s see how this works for
Plugging in the ansatz, translates the differential equation to a new form:
The ansatz substitution didn’t give any result at all for
A slightly more complex differential equation is
For nonlinear dynamical function, there is no perfectly general way to find symbolic solutions. But for some dynamical functions, it can be done. we will demonstrate by integrating
The idea of separating the differential equation is to algebraically move all the
The integral on the right side,
The integral on the left side may not be as familiar, but the person solving this problem for the second time will remember that
At this point, move all the constants of integration over to the right side and consolate them into a single constant of integration
Now we have
= makeFun(A*exp(t)/(1 + A*exp(t)) ~ t)
Symb_soln slice_plot(Symb_soln(t, A=0.2) ~ t, bounds(t=-5:10))
Not all differential equations can be separated in this way, and even for those that can, the integrals may not be tractable. So this route to a solution is not a general-purpose one, unlike the Euler method. Still, the Euler method gives only an approximate solution, so with Euler we need to take care that the approximation is close enough for the purpose at hand. In this case, we have both an Euler solution (with
40.4 Exercises
Exercise 40.01
Some of these are first-order differential equations, others are not. For each, say whether it is indeed a first-order differential equation and, if so, what is the name of the state variable.
Exercise 40.03
For the following, you can use whatever you like for function names, e.g.
Write down the framework for a system of differential equations with state variables
.Write down the framework for a system of differential equations with state
.Write down the framework for a system of differential equations with state variables
.
Exercise 40.05
Figure 40.5 shows time series for the rabbit and fox population density starting at the initial condition
Using the R/mosaic commands given in the text to make Figure 40.5, integrate the equations from
A. Using the time-series plots, estimate the period of the cyclic oscillations. - What is the period of the fox population cycle? - How large in amplitude (peak to trough) is the fox population cycle? - How do the cycle period and amplitude for the rabbits compare to those for the foxes?
B. Change the initial condition from
Exercise 40.06
We will explore some common pitfalls for using the integrateODE()
and traj_plot()
functions.
Part A What is the purpose of the integrateODE()
function?
- To translate a dynamical system into a set of numerical solutions, one for each state variable.
- To draw a flow field of the dynamical system.
- To anti-differentiate a differential equation, giving a symbolic solution.
- To plot the trajectory of a dynamical system.
Part B What is the proper format to use in specifying the dynamical system to integrateODE()
?
- A set of tilde expressions, each one an individual argument.
- A set of named arguments, with the formula on the right-hand side.
- A set of equations separated by semi-colons.
- A set of tilde expressions separated by semi-colons.
Part C What should the left-hand side of the tilde expression look like for a state variable z
?
dz
z
zdot
dt_z
Part D For the dynamical system integrateODE()
command look like? (Note: we are using ...
as a placeholder for other inputs that will be needed by integrateODE()
.)
integrateODE(dx ~ y, dy ~ -x, ...)
integrateODE(dx = y, dy = -x, ...)
integrateODE(dx ~ y, dy = -x, ...)
Part E Aside from the tilde-expressions encoding the dynamical system, what other information is absolutely essential to specify when constructing a numerical solution?
- The initial condition for each and every state variable.
- The trajectory.
- The time series.
- The initial condition for at least one of the state variables.
Part F How should you specify how long you want integrateODE()
to carry forward the solution in time, say for 10 time units?
bounds(t=0:10)
duration=10
t=10
for=10
Exercise 40.07
This system of differential equations, called the Lorenz equations is famous as the first widely recognized example of a type of motion called chaos.
What are the state variables and what are the parameters?
What is the dimension of the state space?
For initial conditions
and , , and , useintegrateODE()
to integrate the equations over with a stepsize of . (This means you should set use the argumentsbounds(t=0:50), dt=0.01
. Call your trajectoryT1
.
## Solution containing functions x(t), y(t), z(t).
## Solution containing functions x(t), y(t), z(t).
Based on your results in (3), what are the values of
, , and at time .Make a time series plot of
. Note that jumps between a oscillation with negative and the same kind of oscillation with positive .Plot out the
component of the trajectory versus the component of the trajectory. To get a smooth plot, you will have to use thenpts=10000
argument totraj_plot()
. The trajectory will appear to cross itself, but this is because you are only plotting two of the state variables.Create another trajectory
T2
in the same way you madeT1
. But change each of the initial conditions in the third decimal point. Then plot out the time series forT1
(withcolor="blue"
) and the time series forT2
(with color=“red”`) on the same axes. The two time series will track one another very closely, but then come out of sync with one another.The characteristic feature of chaos is that a small change in initial conditions can lead to a very large change in the time series. How long does it take for the two time series in (7) to become utterly out of sync with one another?
The function
traj_plot_3D()
provides a simple way to look at the trajectory in 3 dimensions. Such a plot shows that the trajectory does not in fact cross itself. Use this command:
traj_plot_3D(x, y, z, T1, npts=5000)
Exercise 40.09
The differential equation
Exponential growth is considered fast, but there are far faster forms of growth. To illustrate, consider the differential equation
This can be interpreted in terms of a model of the size of the flame as one lights a match. Think of the flame as a ball of hot gas of radius
Within the ball of flame, O_2_ reacts with the cumbustible material to produce the products of combustion and heat. Needless to say, this reaction eliminates the O_2_ in the ball. But O_2_ can diffuse into the ball from outside. The O_2_ infusion rate available in this way is proportional to the surface area of the ball, that is,
The match-flame equation is one that can be separated into parts: all the
Integrating both sides of the separated equation will produce
A. Integrate the left side of the separated equation and use that to find a relationship between
B. The constant of integration,
C. Replace
D.
E. Use integrateODE()
to integrate the original differential equation. You will have to pick some numerical value for
F. Describe in everyday words what the solution says and how big the ball of flame becomes.
The model
Exercise 40.11
This activity makes use of the following app:
Click on the picture of the app and it will open in a new browser tab. Arrange that new tab side-by-side with the one where you are reading this.
To solve a differential equation with the Euler method, you need two things:
- The differential equation itself. Several choices are available in the selector on the left side of the app. On the right side of the equation is the dynamics(x) function.
- An initial condition
. You can select this with the slider.
You will also need
- A stepsize
. So long as this is “small enough,” the specifics don’t really matter.
How Euler works The first row of the table shows the situation at
In the following, whenever we write
- Knowing the value of
the instantaneous value of can be found by plugging into the dynamics() function. - Now that we know
, we know how fast is changing. Multiply this rate of change by to get the total change of for the next step. - Add a new row to the table at
with the -value from the previous row added to the total change of from that previous row. Loop back to (a) each time the “step” button is pressed.
Select
Part A For
- linear decay to zero
- linear growth from zero
- exponential decay to zero
- exponential growth from zero
- exponential decay to
- exponential growth from
Part B For the differential equation
- linear decay to zero
- linear growth from zero
- exponential decay to zero
- exponential growth from zero
- exponential decay to
- exponential growth from
Part C For the differential equation
- linear decay to zero
- linear growth from zero
- exponential decay to zero
- exponential growth from zero
- exponential decay to
- exponential growth from
Part D For the differential equation
- linear decay to zero
- linear growth from zero
- exponential decay to zero
- exponential growth from zero
- exponential decay to
- exponential growth from
Part E For the differential equation
- linear decay to
- exponential decay to
- exponential growth from zero followed by exponential decay to
- exponential decay to zero followed by exponential growth to
Exercise 40.13
Figure 40.6 shows the difference between the symbolic solution to
<- integrateODE(dx ~ x*(1-x), x=0.01,
Euler bounds(t=0:20), dt=0.1)
## Solution containing functions x(t).
= makeFun(A*exp(t)/(1 + A*exp(t)) ~ t, A=1/99)
Symb_soln Symb_soln(3)
## [1] 0.1686648
$x(3)
Euler## [1] 0.1686648
The approximation error occurs after the seventh decimal place.
A. How large can
B. How large can