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
21 import org.hipparchus.exception.MathIllegalArgumentException;
22 import org.hipparchus.exception.MathIllegalStateException;
23 import org.hipparchus.ode.AbstractIntegrator;
24 import org.hipparchus.ode.EquationsMapper;
25 import org.hipparchus.ode.ExpandableODE;
26 import org.hipparchus.ode.LocalizedODEFormats;
27 import org.hipparchus.ode.ODEState;
28 import org.hipparchus.ode.ODEStateAndDerivative;
29 import org.hipparchus.util.FastMath;
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 implements ExplicitRungeKuttaIntegrator {
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 double step;
66
67
68
69
70
71
72
73 protected RungeKuttaIntegrator(final String name, final double step) {
74 super(name);
75 this.c = getC();
76 this.a = getA();
77 this.b = getB();
78 this.step = FastMath.abs(step);
79 }
80
81
82
83
84 public double getDefaultStep() {
85 return this.step;
86 }
87
88
89
90
91
92
93
94
95
96 protected abstract RungeKuttaStateInterpolator createInterpolator(boolean forward, double[][] yDotK,
97 ODEStateAndDerivative globalPreviousState,
98 ODEStateAndDerivative globalCurrentState,
99 EquationsMapper mapper);
100
101
102 @Override
103 public ODEStateAndDerivative integrate(final ExpandableODE equations,
104 final ODEState initialState, final double finalTime)
105 throws MathIllegalArgumentException, MathIllegalStateException {
106
107 sanityChecks(initialState, finalTime);
108 setStepStart(initIntegration(equations, initialState, finalTime));
109 final boolean forward = finalTime > initialState.getTime();
110
111
112 final int stages = c.length + 1;
113 double[] y = getStepStart().getCompleteState();
114 final double[][] yDotK = new double[stages][];
115 final double[] yTmp = new double[y.length];
116
117
118 if (forward) {
119 if (getStepStart().getTime() + step >= finalTime) {
120 setStepSize(finalTime - getStepStart().getTime());
121 } else {
122 setStepSize(step);
123 }
124 } else {
125 if (getStepStart().getTime() - step <= finalTime) {
126 setStepSize(finalTime - getStepStart().getTime());
127 } else {
128 setStepSize(-step);
129 }
130 }
131
132
133 setIsLastStep(false);
134 do {
135
136
137 y = getStepStart().getCompleteState();
138 yDotK[0] = getStepStart().getCompleteDerivative();
139
140
141 ExplicitRungeKuttaIntegrator.applyInternalButcherWeights(getEquations(), getStepStart().getTime(), y,
142 getStepSize(), a, c, yDotK);
143
144 incrementEvaluations(stages - 1);
145
146
147 for (int j = 0; j < y.length; ++j) {
148 double sum = b[0] * yDotK[0][j];
149 for (int l = 1; l < stages; ++l) {
150 sum += b[l] * yDotK[l][j];
151 }
152 yTmp[j] = y[j] + getStepSize() * sum;
153 if (Double.isNaN(yTmp[j])) {
154 throw new MathIllegalStateException(LocalizedODEFormats.NAN_APPEARING_DURING_INTEGRATION,
155 getStepStart().getTime() + getStepSize());
156 }
157
158 }
159 final double stepEnd = getStepStart().getTime() + getStepSize();
160 final double[] yDotTmp = computeDerivatives(stepEnd, yTmp);
161 final ODEStateAndDerivative stateTmp =
162 equations.getMapper().mapStateAndDerivative(stepEnd, yTmp, yDotTmp);
163
164
165 System.arraycopy(yTmp, 0, y, 0, y.length);
166 setStepStart(acceptStep(createInterpolator(forward, yDotK, getStepStart(), stateTmp,
167 equations.getMapper()),
168 finalTime));
169
170 if (!isLastStep()) {
171
172
173 final double nextT = getStepStart().getTime() + getStepSize();
174 final boolean nextIsLast = forward ? (nextT >= finalTime) : (nextT <= finalTime);
175 if (nextIsLast) {
176 setStepSize(finalTime - getStepStart().getTime());
177 }
178 }
179
180 } while (!isLastStep());
181
182 final ODEStateAndDerivative finalState = getStepStart();
183 setStepStart(null);
184 setStepSize(Double.NaN);
185 return finalState;
186
187 }
188
189 }