1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.hipparchus.ode.nonstiff;
19
20 import org.hipparchus.exception.MathIllegalArgumentException;
21 import org.hipparchus.exception.MathIllegalStateException;
22 import org.hipparchus.ode.EquationsMapper;
23 import org.hipparchus.ode.ExpandableODE;
24 import org.hipparchus.ode.LocalizedODEFormats;
25 import org.hipparchus.ode.ODEState;
26 import org.hipparchus.ode.ODEStateAndDerivative;
27 import org.hipparchus.util.FastMath;
28
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
56
57
58
59
60
61
62
63 public abstract class EmbeddedRungeKuttaIntegrator
64 extends AdaptiveStepsizeIntegrator
65 implements ExplicitRungeKuttaIntegrator {
66
67
68 private final int fsal;
69
70
71 private final double[] c;
72
73
74 private final double[][] a;
75
76
77 private final double[] b;
78
79
80 private final double exp;
81
82
83 private double safety;
84
85
86 private double minReduction;
87
88
89 private double maxGrowth;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 protected EmbeddedRungeKuttaIntegrator(final String name, final int fsal,
105 final double minStep, final double maxStep,
106 final double scalAbsoluteTolerance,
107 final double scalRelativeTolerance) {
108
109 super(name, minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
110
111 this.fsal = fsal;
112 this.c = getC();
113 this.a = getA();
114 this.b = getB();
115
116 exp = -1.0 / getOrder();
117
118
119 setSafety(0.9);
120 setMinReduction(0.2);
121 setMaxGrowth(10.0);
122
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136 protected EmbeddedRungeKuttaIntegrator(final String name, final int fsal,
137 final double minStep, final double maxStep,
138 final double[] vecAbsoluteTolerance,
139 final double[] vecRelativeTolerance) {
140
141 super(name, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
142
143 this.fsal = fsal;
144 this.c = getC();
145 this.a = getA();
146 this.b = getB();
147
148 exp = -1.0 / getOrder();
149
150
151 setSafety(0.9);
152 setMinReduction(0.2);
153 setMaxGrowth(10.0);
154
155 }
156
157
158
159
160
161
162
163
164
165 protected abstract RungeKuttaStateInterpolator createInterpolator(boolean forward, double[][] yDotK,
166 ODEStateAndDerivative globalPreviousState,
167 ODEStateAndDerivative globalCurrentState,
168 EquationsMapper mapper);
169
170
171
172 public abstract int getOrder();
173
174
175
176
177 public double getSafety() {
178 return safety;
179 }
180
181
182
183
184 public void setSafety(final double safety) {
185 this.safety = safety;
186 }
187
188
189 @Override
190 public ODEStateAndDerivative integrate(final ExpandableODE equations,
191 final ODEState initialState, final double finalTime)
192 throws MathIllegalArgumentException, MathIllegalStateException {
193
194 sanityChecks(initialState, finalTime);
195 setStepStart(initIntegration(equations, initialState, finalTime));
196 final boolean forward = finalTime > initialState.getTime();
197
198
199 final int stages = c.length + 1;
200 final double[][] yDotK = new double[stages][];
201 double[] yTmp = new double[equations.getMapper().getTotalDimension()];
202
203
204 double hNew = 0;
205 boolean firstTime = true;
206
207
208 setIsLastStep(false);
209 do {
210
211
212 double error = 10;
213 while (error >= 1.0) {
214
215
216 final double[] y = getStepStart().getCompleteState();
217 yDotK[0] = getStepStart().getCompleteDerivative();
218
219 if (firstTime) {
220 final StepsizeHelper helper = getStepSizeHelper();
221 final double[] scale = new double[helper.getMainSetDimension()];
222 for (int i = 0; i < scale.length; ++i) {
223 scale[i] = helper.getTolerance(i, FastMath.abs(y[i]));
224 }
225 hNew = initializeStep(forward, getOrder(), scale, getStepStart());
226 firstTime = false;
227 }
228
229 setStepSize(hNew);
230 if (forward) {
231 if (getStepStart().getTime() + getStepSize() >= finalTime) {
232 setStepSize(finalTime - getStepStart().getTime());
233 }
234 } else {
235 if (getStepStart().getTime() + getStepSize() <= finalTime) {
236 setStepSize(finalTime - getStepStart().getTime());
237 }
238 }
239
240
241 ExplicitRungeKuttaIntegrator.applyInternalButcherWeights(getEquations(), getStepStart().getTime(), y,
242 getStepSize(), a, c, yDotK);
243 yTmp = ExplicitRungeKuttaIntegrator.applyExternalButcherWeights(y, yDotK, getStepSize(), b);
244
245 incrementEvaluations(stages - 1);
246
247
248 error = estimateError(yDotK, y, yTmp, getStepSize());
249 if (Double.isNaN(error)) {
250 throw new MathIllegalStateException(LocalizedODEFormats.NAN_APPEARING_DURING_INTEGRATION,
251 getStepStart().getTime() + getStepSize());
252 }
253 if (error >= 1.0) {
254
255 final double factor =
256 FastMath.min(maxGrowth,
257 FastMath.max(minReduction, safety * FastMath.pow(error, exp)));
258 hNew = getStepSizeHelper().filterStep(getStepSize() * factor, forward, false);
259 }
260
261 }
262 final double stepEnd = getStepStart().getTime() + getStepSize();
263 final double[] yDotTmp = (fsal >= 0) ? yDotK[fsal] : computeDerivatives(stepEnd, yTmp);
264 final ODEStateAndDerivative stateTmp = equations.getMapper().mapStateAndDerivative(stepEnd, yTmp, yDotTmp);
265
266
267 setStepStart(acceptStep(createInterpolator(forward, yDotK, getStepStart(), stateTmp, equations.getMapper()), finalTime));
268
269 if (!isLastStep()) {
270
271
272 final double factor =
273 FastMath.min(maxGrowth, FastMath.max(minReduction, safety * FastMath.pow(error, exp)));
274 final double scaledH = getStepSize() * factor;
275 final double nextT = getStepStart().getTime() + scaledH;
276 final boolean nextIsLast = forward ? (nextT >= finalTime) : (nextT <= finalTime);
277 hNew = getStepSizeHelper().filterStep(scaledH, forward, nextIsLast);
278
279 final double filteredNextT = getStepStart().getTime() + hNew;
280 final boolean filteredNextIsLast = forward ? (filteredNextT >= finalTime) : (filteredNextT <= finalTime);
281 if (filteredNextIsLast) {
282 hNew = finalTime - getStepStart().getTime();
283 }
284
285 }
286
287 } while (!isLastStep());
288
289 final ODEStateAndDerivative finalState = getStepStart();
290 resetInternalState();
291 return finalState;
292
293 }
294
295
296
297
298 public double getMinReduction() {
299 return minReduction;
300 }
301
302
303
304
305 public void setMinReduction(final double minReduction) {
306 this.minReduction = minReduction;
307 }
308
309
310
311
312 public double getMaxGrowth() {
313 return maxGrowth;
314 }
315
316
317
318
319 public void setMaxGrowth(final double maxGrowth) {
320 this.maxGrowth = maxGrowth;
321 }
322
323
324
325
326
327
328
329
330 protected abstract double estimateError(double[][] yDotK,
331 double[] y0, double[] y1,
332 double h);
333
334 }