1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.ode.nonstiff;
19
20
21 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
22 import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
23 import org.apache.commons.math4.legacy.exception.NoBracketingException;
24 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
25 import org.apache.commons.math4.legacy.ode.AbstractIntegrator;
26 import org.apache.commons.math4.legacy.ode.ExpandableStatefulODE;
27 import org.apache.commons.math4.legacy.ode.FirstOrderDifferentialEquations;
28 import org.apache.commons.math4.core.jdkmath.JdkMath;
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 public abstract class RungeKuttaIntegrator extends AbstractIntegrator {
54
55
56 private final double[] c;
57
58
59 private final double[][] a;
60
61
62 private final double[] b;
63
64
65 private final RungeKuttaStepInterpolator prototype;
66
67
68 private final double step;
69
70
71
72
73
74
75
76
77
78
79
80 protected RungeKuttaIntegrator(final String name,
81 final double[] c, final double[][] a, final double[] b,
82 final RungeKuttaStepInterpolator prototype,
83 final double step) {
84 super(name);
85 this.c = c;
86 this.a = a;
87 this.b = b;
88 this.prototype = prototype;
89 this.step = JdkMath.abs(step);
90 }
91
92
93 @Override
94 public void integrate(final ExpandableStatefulODE equations, final double t)
95 throws NumberIsTooSmallException, DimensionMismatchException,
96 MaxCountExceededException, NoBracketingException {
97
98 sanityChecks(equations, t);
99 setEquations(equations);
100 final boolean forward = t > equations.getTime();
101
102
103 final double[] y0 = equations.getCompleteState();
104 final double[] y = y0.clone();
105 final int stages = c.length + 1;
106 final double[][] yDotK = new double[stages][];
107 for (int i = 0; i < stages; ++i) {
108 yDotK [i] = new double[y0.length];
109 }
110 final double[] yTmp = y0.clone();
111 final double[] yDotTmp = new double[y0.length];
112
113
114 final RungeKuttaStepInterpolator interpolator = (RungeKuttaStepInterpolator) prototype.copy();
115 interpolator.reinitialize(this, yTmp, yDotK, forward,
116 equations.getPrimaryMapper(), equations.getSecondaryMappers());
117 interpolator.storeTime(equations.getTime());
118
119
120 stepStart = equations.getTime();
121 if (forward) {
122 if (stepStart + step >= t) {
123 stepSize = t - stepStart;
124 } else {
125 stepSize = step;
126 }
127 } else {
128 if (stepStart - step <= t) {
129 stepSize = t - stepStart;
130 } else {
131 stepSize = -step;
132 }
133 }
134 initIntegration(equations.getTime(), y0, t);
135
136
137 isLastStep = false;
138 do {
139
140 interpolator.shift();
141
142
143 computeDerivatives(stepStart, y, yDotK[0]);
144
145
146 for (int k = 1; k < stages; ++k) {
147
148 for (int j = 0; j < y0.length; ++j) {
149 double sum = a[k-1][0] * yDotK[0][j];
150 for (int l = 1; l < k; ++l) {
151 sum += a[k-1][l] * yDotK[l][j];
152 }
153 yTmp[j] = y[j] + stepSize * sum;
154 }
155
156 computeDerivatives(stepStart + c[k-1] * stepSize, yTmp, yDotK[k]);
157 }
158
159
160 for (int j = 0; j < y0.length; ++j) {
161 double sum = b[0] * yDotK[0][j];
162 for (int l = 1; l < stages; ++l) {
163 sum += b[l] * yDotK[l][j];
164 }
165 yTmp[j] = y[j] + stepSize * sum;
166 }
167
168
169 interpolator.storeTime(stepStart + stepSize);
170 System.arraycopy(yTmp, 0, y, 0, y0.length);
171 System.arraycopy(yDotK[stages - 1], 0, yDotTmp, 0, y0.length);
172 stepStart = acceptStep(interpolator, y, yDotTmp, t);
173
174 if (!isLastStep) {
175
176
177 interpolator.storeTime(stepStart);
178
179
180 final double nextT = stepStart + stepSize;
181 final boolean nextIsLast = forward ? (nextT >= t) : (nextT <= t);
182 if (nextIsLast) {
183 stepSize = t - stepStart;
184 }
185 }
186 } while (!isLastStep);
187
188
189 equations.setTime(stepStart);
190 equations.setCompleteState(y);
191
192 stepStart = Double.NaN;
193 stepSize = Double.NaN;
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 public double[] singleStep(final FirstOrderDifferentialEquations equations,
222 final double t0, final double[] y0, final double t) {
223
224
225 final double[] y = y0.clone();
226 final int stages = c.length + 1;
227 final double[][] yDotK = new double[stages][];
228 for (int i = 0; i < stages; ++i) {
229 yDotK [i] = new double[y0.length];
230 }
231 final double[] yTmp = y0.clone();
232
233
234 final double h = t - t0;
235 equations.computeDerivatives(t0, y, yDotK[0]);
236
237
238 for (int k = 1; k < stages; ++k) {
239
240 for (int j = 0; j < y0.length; ++j) {
241 double sum = a[k-1][0] * yDotK[0][j];
242 for (int l = 1; l < k; ++l) {
243 sum += a[k-1][l] * yDotK[l][j];
244 }
245 yTmp[j] = y[j] + h * sum;
246 }
247
248 equations.computeDerivatives(t0 + c[k-1] * h, yTmp, yDotK[k]);
249 }
250
251
252 for (int j = 0; j < y0.length; ++j) {
253 double sum = b[0] * yDotK[0][j];
254 for (int l = 1; l < stages; ++l) {
255 sum += b[l] * yDotK[l][j];
256 }
257 y[j] += h * sum;
258 }
259
260 return y;
261 }
262 }