1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math.ode.nonstiff;
19
20
21 import org.apache.commons.math.ode.AbstractIntegrator;
22 import org.apache.commons.math.ode.DerivativeException;
23 import org.apache.commons.math.ode.FirstOrderDifferentialEquations;
24 import org.apache.commons.math.ode.IntegratorException;
25 import org.apache.commons.math.ode.events.CombinedEventsManager;
26 import org.apache.commons.math.ode.sampling.AbstractStepInterpolator;
27 import org.apache.commons.math.ode.sampling.DummyStepInterpolator;
28 import org.apache.commons.math.ode.sampling.StepHandler;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public abstract class RungeKuttaIntegrator extends AbstractIntegrator {
56
57
58 private final double[] c;
59
60
61 private final double[][] a;
62
63
64 private final double[] b;
65
66
67 private final RungeKuttaStepInterpolator prototype;
68
69
70 private final double step;
71
72
73
74
75
76
77
78
79
80
81
82 protected RungeKuttaIntegrator(final String name,
83 final double[] c, final double[][] a, final double[] b,
84 final RungeKuttaStepInterpolator prototype,
85 final double step) {
86 super(name);
87 this.c = c;
88 this.a = a;
89 this.b = b;
90 this.prototype = prototype;
91 this.step = Math.abs(step);
92 }
93
94
95 public double integrate(final FirstOrderDifferentialEquations equations,
96 final double t0, final double[] y0,
97 final double t, final double[] y)
98 throws DerivativeException, IntegratorException {
99
100 sanityChecks(equations, t0, y0, t, y);
101 setEquations(equations);
102 resetEvaluations();
103 final boolean forward = t > t0;
104
105
106 final int stages = c.length + 1;
107 if (y != y0) {
108 System.arraycopy(y0, 0, y, 0, y0.length);
109 }
110 final double[][] yDotK = new double[stages][];
111 for (int i = 0; i < stages; ++i) {
112 yDotK [i] = new double[y0.length];
113 }
114 final double[] yTmp = new double[y0.length];
115
116
117 AbstractStepInterpolator interpolator;
118 if (requiresDenseOutput() || (! eventsHandlersManager.isEmpty())) {
119 final RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.copy();
120 rki.reinitialize(this, yTmp, yDotK, forward);
121 interpolator = rki;
122 } else {
123 interpolator = new DummyStepInterpolator(yTmp, forward);
124 }
125 interpolator.storeTime(t0);
126
127
128 stepStart = t0;
129 stepSize = forward ? step : -step;
130 for (StepHandler handler : stepHandlers) {
131 handler.reset();
132 }
133 CombinedEventsManager manager = addEndTimeChecker(t0, t, eventsHandlersManager);
134 boolean lastStep = false;
135
136
137 while (!lastStep) {
138
139 interpolator.shift();
140
141 for (boolean loop = true; loop;) {
142
143
144 computeDerivatives(stepStart, y, yDotK[0]);
145
146
147 for (int k = 1; k < stages; ++k) {
148
149 for (int j = 0; j < y0.length; ++j) {
150 double sum = a[k-1][0] * yDotK[0][j];
151 for (int l = 1; l < k; ++l) {
152 sum += a[k-1][l] * yDotK[l][j];
153 }
154 yTmp[j] = y[j] + stepSize * sum;
155 }
156
157 computeDerivatives(stepStart + c[k-1] * stepSize, yTmp, yDotK[k]);
158
159 }
160
161
162 for (int j = 0; j < y0.length; ++j) {
163 double sum = b[0] * yDotK[0][j];
164 for (int l = 1; l < stages; ++l) {
165 sum += b[l] * yDotK[l][j];
166 }
167 yTmp[j] = y[j] + stepSize * sum;
168 }
169
170
171 interpolator.storeTime(stepStart + stepSize);
172 if (manager.evaluateStep(interpolator)) {
173 final double dt = manager.getEventTime() - stepStart;
174 if (Math.abs(dt) <= Math.ulp(stepStart)) {
175
176 loop = false;
177 } else {
178
179 stepSize = dt;
180 }
181 } else {
182 loop = false;
183 }
184
185 }
186
187
188 final double nextStep = stepStart + stepSize;
189 System.arraycopy(yTmp, 0, y, 0, y0.length);
190 manager.stepAccepted(nextStep, y);
191 lastStep = manager.stop();
192
193
194 interpolator.storeTime(nextStep);
195 for (StepHandler handler : stepHandlers) {
196 handler.handleStep(interpolator, lastStep);
197 }
198 stepStart = nextStep;
199
200 if (manager.reset(stepStart, y) && ! lastStep) {
201
202
203 computeDerivatives(stepStart, y, yDotK[0]);
204 }
205
206
207 stepSize = forward ? step : -step;
208
209 }
210
211 final double stopTime = stepStart;
212 stepStart = Double.NaN;
213 stepSize = Double.NaN;
214 return stopTime;
215
216 }
217
218 }