1
2
3
4
5
6
7
8
9
10
11 package nl.tudelft.simulation.jstats.ode.integrators;
12
13 import nl.tudelft.simulation.jstats.ode.DifferentialEquationInterface;
14
15 /***
16 * The CachingNumericalIntegrator is the basis for an integrator that needs
17 * access to previously calculated values of y', e.g. y'_(k-1), y'_(k-2), etc.
18 * <br>
19 * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
20 * University of Technology </a>, the Netherlands. <br>
21 * See for project information <a href="http://www.simulation.tudelft.nl">
22 * www.simulation.tudelft.nl </a> <br>
23 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
24 * License (GPL) </a>, no warranty <br>
25 *
26 * @version May 2, 2004 <br>
27 * @author <a
28 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
29 * Verbraeck </a>
30 */
31 public abstract class CachingNumericalIntegrator extends NumericalIntegrator
32 {
33 /*** the number of cachePlaces to store, e.g for k-1, k-2 set it to 2 */
34 private int cachePlaces = 0;
35
36 /*** the cache for y(k-1), y(k-2), etc. */
37 private double[][] cacheY;
38
39 /*** the cache for y'(k-1), y'(k-2), etc. */
40 private double[][] cacheDY;
41
42 /*** the number of cache places filled = the last cache place used */
43 private int lastCachePlace = -1;
44
45 /*** the primer integrator */
46 protected NumericalIntegrator startingIntegrator = null;
47
48 /*** the substeps to use when starting the integrator */
49 protected int startingSubSteps = 10;
50
51 /***
52 * constructs a new CachingNumericalIntegrator with a fixed number of cache
53 * places.
54 *
55 * @param timeStep the timeStep
56 * @param equation the differentialEquation
57 * @param cachePlaces the number of cache places to store
58 * @param integrationMethod the primer integrator to use
59 * @param startingSubSteps the number of substeps per timestep during
60 * starting of the integrator
61 */
62 public CachingNumericalIntegrator(final double timeStep,
63 final DifferentialEquationInterface equation,
64 final int cachePlaces, final short integrationMethod,
65 final int startingSubSteps)
66 {
67 super(timeStep, equation);
68 this.cachePlaces = cachePlaces;
69 this.cacheY = new double[cachePlaces][];
70 this.cacheDY = new double[cachePlaces][];
71 this.startingIntegrator = NumericalIntegrator.resolve(
72 integrationMethod, timeStep / (1.0d * startingSubSteps),
73 equation);
74 this.startingSubSteps = startingSubSteps;
75 }
76
77 /***
78 * @see nl.tudelft.simulation.jstats.ode.integrators.NumericalIntegrator#setTimeStep(double)
79 */
80 public void setTimeStep(final double timeStep)
81 {
82 super.setTimeStep(timeStep);
83 this.lastCachePlace = -1;
84 }
85
86 /***
87 * @see nl.tudelft.simulation.jstats.ode.integrators.NumericalIntegrator#next(double,
88 * double[])
89 */
90 public double[] next(final double x, final double[] y)
91 {
92 double[] ynext = null;
93
94 if (this.lastCachePlace < this.cachePlaces)
95 {
96
97
98 ynext = (double[]) y.clone();
99 double xstep = x;
100 for (int i = 0; i < this.startingSubSteps; i++)
101 {
102 ynext = this.startingIntegrator.next(xstep, ynext);
103 xstep += this.timeStep / (1.0d * this.startingSubSteps);
104 }
105 } else
106 {
107
108 ynext = next(x);
109 }
110 this.lastCachePlace++;
111 this.cacheY[this.lastCachePlace % this.cachePlaces] = ynext;
112 this.cacheDY[this.lastCachePlace % this.cachePlaces] = this.equation
113 .dy(x + this.timeStep, ynext);
114 return ynext;
115 }
116
117 /***
118 * get a cached Y-value,
119 *
120 * @param numberDown the number of the previous value we want
121 * @return the corresponding Y-value
122 */
123 public double[] getY(final int numberDown)
124 {
125 if (this.lastCachePlace < this.cachePlaces)
126 {
127 throw new RuntimeException(
128 "Tried to retrieve y-value that was not yet primed");
129 }
130 if (numberDown >= this.cachePlaces)
131 {
132 throw new RuntimeException(
133 "Tried to retrieve y-value beyond cache limits");
134 }
135 return (double[]) this.cacheY[(this.lastCachePlace - numberDown)
136 % this.cachePlaces].clone();
137 }
138
139 /***
140 * get a cached dY-value,
141 *
142 * @param numberDown the number of the previous value we want
143 * @return the corresponding dY-value
144 */
145 public double[] getDY(final int numberDown)
146 {
147 if (this.lastCachePlace < this.cachePlaces)
148 {
149 throw new RuntimeException(
150 "Tried to retrieve dy-value that was not yet primed");
151 }
152 if (numberDown >= this.cachePlaces)
153 {
154 throw new RuntimeException(
155 "Tried to retrieve dy-value beyond cache limits");
156 }
157 return (double[]) this.cacheDY[(this.lastCachePlace - numberDown)
158 % this.cachePlaces].clone();
159 }
160
161 /***
162 * The integrators that extend the CachingNumericalIntegrator calculate the
163 * value of y(x+timeStep) just based on the x-value. They retrieve y(x),
164 * y(x-timeStep), etc. or y(k), y(k-1) all from the cache.
165 *
166 * @param x the x-value to use in the calculation
167 * @return the value of y(x+timeStep)
168 */
169 public abstract double[] next(final double x);
170 }