The Leap project provides continuous and discrete simulations of population dynamics using a simple Lotka-Volterra model. The project builds upon the Bounce project by adding Swing-based and third-party graphical interface components including a 2D graphing component (JChart2D). The numerics module also makes use of the Matrix class in the Jama library.
The following UML diagram shows the LeapView class and its main components:
JChart2D is a free open-source 2D plotting library, available at http://jchart2d.sourceforge.net
It provides an easy-to-use and flexible set of classes for dynamically plotting 2D graphs. A large number of classes are listed in the javadocs, but only a small subset were used in this project:
| Class | Description |
|---|---|
| Chart2D | Panel where plots are drawn |
| ITrace2D | Represents a single line in plot |
| TracePoint2D | Defines a single point in a trace |
| IAxis | Interface for setting properties of x and y axis of plot |
| ATracePainter | Base class to override for custom painting of traces |
The following UML diagram shows the use of the Chart2D component from JChart2D:
The PlotPanel class contains a CustomChart2D component, which is derived from the Chart2D class. This class displays a set of plot lines called 'traces' (Trace2DSimple). Each trace draws a set of points (TracePoint2D) and the connections between them. A PlotPanel panel creates a single CustomChart2D component on construction. For each new data set to be plotted, a set of traces is created, with associated names and colors. Points are then added to each trace during each view update(), and the graph dynamically updates itself to show the new points, automatically rescaling the axes as needed.
The reason for using the derived class CustomChart2D is to handle mouse clicks on the chart, allowing clicked points on the PhasePlot to be sent to the view to rerun the simulation with the new initial conditions. The notification is done through the CustomChart2DListener interface, implemented by the view.
A second derived class, CustomTracePainter, is used to override the ATracePainter paintPoint() method, which allows a specified point to be highlighted. This is used to draw a circle around the most-recently-added point on the phase plot, which shows the progression of the simulation state through phase space.
A UML diagram shows the main class, LeapModel, and related classes in the model package:
Classes in the model package are shown in orange, classes from the numerics package are shown in blue. At top left is the main class, LeapModel. This defines the behavior of the simple Lotka-Volterra predator-prey model. The state of the model is changed over time through calls to the update() method, and the integrated state is returned in an instance of the LeapState class, which wraps a SystemState object that contains the actual state variables.
The model can perform both continuous and discrete integration of the system state, as determined by the value set through a call to setIntegrationMethod(). The single continuous method is "RK4" (Runge-Kutta order 4). Discrete integration is implemented through vector and matrix operations provided in the numerics module.
To allow for generalized integration of a discrete model state, a set of transform functions are used. For a linear system of equations, the discrete change of a state variable Ni over time can be defined as:
where ΔNi can be defined as a function of all state variables:
In the case of the simple LV model, we have:
This can be calculated by multiplying the current state as a row vector (N1 N2) by the 2x2 matrix M, defined as:
| a | c * N2 |
| -c * N1 | -b |
Note that these matrix values are not constant, but depend on the value of other state variables. To allow the numerics module to create the matrix, a set of function classes, MatrixXXFunction, are defined and passed to the numerics.Numerics.discreteIntegration() method, described below.
The numerics classes and related classes are shown in the following UML diagram:
The SystemState and Function classes have already been seen in the model class diagram above. The additional class is Numerics, which defines two static methods, rk4() and discreteIntegration(), along with some helper methods().
The rk4() method works the same way as in the previous Bounce demo project. The discreteIntegration() method performs a number of matrix operations using the Jama Matrix class. The helper methods are used to marshal the system state to and from a matrix representation. Jama is available at http://math.nist.gov/javanumerics/jama/