We explain here how to use some additional features of
However, the discussion below does not cover all of its capabilities.
For a complete list of command-line options, see ode Invocation.
It is easy to use
ode to create plots of great beauty. An
example would be a plot of a strange attractor, namely the Lorenz
attractor. Suppose that a file named lorenz contains the
# The Lorenz model, a system of three coupled ODE's with parameter r. x' = -3*(x-y) y' = -x*z+r*x-y z' = x*y-z r = 26 x = 0; y = 1; z = 0 print x, y step 0, 200
Then executing the command
ode < lorenz | graph -T X -C -x -10 10 -y -10 10
would produce a plot of the Lorenz attractor (strictly speaking, a plot of one of its two-dimensional projections). You may produce a Postscript plot of the Lorenz attractor, and print it, by doing something like
ode < lorenz | graph -T ps -x -10 10 -y -10 10 -W 0 | lpr
The ‘-W 0’ (“zero width”) option requests that
graph -T ps
use the thinnest line possible, to improve the visual appearance of the
plot on a printer or other Postscript device.
Besides plotting a visually striking object in real time, the Lorenz
attractor example shows how statements may be separated by semicolons,
rather than appearing on different lines. It also shows how to use
symbolic constants. In the description read by
parameter r is a variable like x, y, and z. But unlike them it is not updated during stepping, since no
formula for its derivative r' is given.
Our second example deals with the interactive construction of a `phase portrait': a set of solution curves with different initial conditions. Phase portraits are of paramount interest in the qualitative theory of differential equations, and also possess æsthetic appeal.
Since a description read by
ode may contain any number of
‘step’ statements, multiple solution curves may be plotted in a
single run. The most recent ‘print’ statement will be used with
each ‘step’ statement. In practice, a phase portrait would be
drawn from a few well-chosen solution curves. Choosing a good set of
solution curves may require experimentation, which makes interactivity
and real-time plotting all-important.
As an example, consider a so-called Lotka–Volterra predator–prey model. Suppose that in a lake there are two species of fish: A (the prey) who live by eating a plentiful supply of plants, and B (the predator) who eat A. Let x(t) be the population of A and y(t) the population of B at time t. A crude model for the interaction of A and B is given by the equations
x' = x(a-by) y' = y(cx-d)
where a, b, c, d are positive constants. To draw a phase portrait for this system interactively, you could type
ode | graph -T X -C -x 0 5 -y 0 5 x' = (a - b*y) * x y' = (c*x - d) * y a = 1; b = 1; c = 1; d = 1; print x, y x = 1; y = 2 step 0, 10 x = 1; y = 3 step 0, 10 x = 1; y = 4 step 0, 10 x = 1; y = 5 step 0, 10 .
Four curves will be drawn in succession, one per ‘step’ line. They
will be periodic; this periodicity is similar to the fluctuations
between predator and prey populations that occur in real-world
ecosystems. On a color display the curves will appear in different
colors, since by default,
graph changes the linemode between
datasets. That feature may be turned off by using
graph -T X
-B rather than
graph -T X.
It is sometimes useful to use
graph to plot
discrete points, which are not joined by line segments to form a curve.
Our third example illustrates this. Suppose the file atwoods
contains the lines
m = 1 M = 1.0625 a = 0.5; adot = 0 l = 10; ldot = 0 ldot' = ( m * l * adot * adot - M * 9.8 + m * 9.8 * cos(a) ) / (m + M) l' = ldot adot' = (-1/l) * (9.8 * sin(a) + 2 * adot * ldot) a' = adot print l, ldot step 0, 400
The first few lines describe the functioning of a so-called swinging Atwood's machine. An ordinary Atwood's machine consists of a taut cord draped over a pulley, with a mass attached to the cord at each end. Normally, the heavier mass (M) would win against the lighter mass (m), and draw it upward. A swinging Atwood's machine allows the lighter mass to swing back and forth as well as move vertically.
The ‘print l, ldot’ statement requests that the vertical position and vertical velocity of the lighter mass be printed out at each step. If you run the command
ode < atwoods | graph -T X -x 9 11 -y -1 1 -m 0 -S 1 -X l -Y ldot
you will obtain a real-time plot. The ‘-m 0’ option requests that successive data points not be joined by line segments, and the ‘-S 1’ option requests that plotting symbol #1 (a dot) be plotted at the location of each point. As you will see if you run this command, the heavy mass does not win against the lighter mass. Instead the machine oscillates non-periodically. Since the motion is non-periodic, the plot benefits from being drawn as a sequence of unconnected points.
We conclude by mentioning a few features of
ode that may be
useful when things are not going quite right. One of them is the
‘examine’ statement. It may be used to discover pertinent
information about any variable in a system. For details, see Input Language.
Another useful feature is that the ‘print’ statement may be used to print out more than just the value of a variable. As we have seen, if the name of the variable is followed by ‘'’, the derivative of the variable will be printed instead. In a similar way, following the variable name with ‘?’, ‘!’, or ‘~’ prints respectively the relative single-step error, the absolute single-step error, or the accumulated error (not currently implemented). These quantities are discussed in Numerical Error.
The ‘print’ statement may be more complicated than was shown in the preceding examples. Its general structure is
print <pr-list> [every <const>] [from <const>]
The bracket notation ‘[...]’ means that the enclosed statements are optional. Until now we have not mentioned the ‘every’ clause or the ‘from’ clause. The <pr-list> is familiar, however; it is simply a comma-separated list of variables. For example, in the statement
print t, y, y' every 5 from 1
the <pr-list> is <t, y, y'>. The clauses ‘every 5’ and ‘from 1’ specify that printing should take place after every fifth step, and that the printing should begin when the independent variable t reaches 1. An ‘every’ clause is useful if you wish to `thin out' the output generated by a ‘step’ statement, and a ‘from’ clause is useful if you wish to view only the final portion of a solution curve.