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