1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.ode.nonstiff;
24
25 import org.hipparchus.Field;
26 import org.hipparchus.CalculusFieldElement;
27 import org.hipparchus.exception.MathIllegalArgumentException;
28 import org.hipparchus.exception.MathIllegalStateException;
29 import org.hipparchus.linear.Array2DRowFieldMatrix;
30 import org.hipparchus.linear.FieldMatrix;
31 import org.hipparchus.ode.FieldEquationsMapper;
32 import org.hipparchus.ode.FieldExpandableODE;
33 import org.hipparchus.ode.FieldODEState;
34 import org.hipparchus.ode.FieldODEStateAndDerivative;
35 import org.hipparchus.ode.LocalizedODEFormats;
36 import org.hipparchus.ode.MultistepFieldIntegrator;
37 import org.hipparchus.ode.nonstiff.interpolators.AdamsFieldStateInterpolator;
38 import org.hipparchus.util.MathArrays;
39
40
41
42
43
44
45 public abstract class AdamsFieldIntegrator<T extends CalculusFieldElement<T>> extends MultistepFieldIntegrator<T> {
46
47
48 private final AdamsNordsieckFieldTransformer<T> transformer;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 protected AdamsFieldIntegrator(final Field<T> field, final String name, final int nSteps, final int order,
67 final double minStep, final double maxStep, final double scalAbsoluteTolerance,
68 final double scalRelativeTolerance)
69 throws MathIllegalArgumentException {
70 super(field, name, nSteps, order, minStep, maxStep,
71 scalAbsoluteTolerance, scalRelativeTolerance);
72 transformer = AdamsNordsieckFieldTransformer.getInstance(field, nSteps);
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 protected AdamsFieldIntegrator(final Field<T> field, final String name, final int nSteps, final int order,
92 final double minStep, final double maxStep, final double[] vecAbsoluteTolerance,
93 final double[] vecRelativeTolerance)
94 throws IllegalArgumentException {
95 super(field, name, nSteps, order, minStep, maxStep,
96 vecAbsoluteTolerance, vecRelativeTolerance);
97 transformer = AdamsNordsieckFieldTransformer.getInstance(field, nSteps);
98 }
99
100
101 @Override
102 public FieldODEStateAndDerivative<T> integrate(final FieldExpandableODE<T> equations,
103 final FieldODEState<T> initialState,
104 final T finalTime)
105 throws MathIllegalArgumentException, MathIllegalStateException {
106
107 sanityChecks(initialState, finalTime);
108 setStepStart(initIntegration(equations, initialState, finalTime));
109 final boolean forward = finalTime.subtract(initialState.getTime()).getReal() > 0;
110
111
112 start(equations, getStepStart(), finalTime);
113
114
115 FieldODEStateAndDerivative<T> stepStart = getStepStart();
116 FieldODEStateAndDerivative<T> stepEnd =
117 AdamsFieldStateInterpolator.taylor(equations.getMapper(), stepStart,
118 stepStart.getTime().add(getStepSize()),
119 getStepSize(), scaled, nordsieck);
120
121
122 setIsLastStep(false);
123 final T[] y = stepStart.getCompleteState();
124 do {
125
126 T[] predictedY = null;
127 final T[] predictedScaled = MathArrays.buildArray(getField(), y.length);
128 Array2DRowFieldMatrix<T> predictedNordsieck = null;
129 double error = 10;
130 while (error >= 1.0) {
131
132
133 predictedY = stepEnd.getCompleteState();
134
135
136 final T[] yDot = computeDerivatives(stepEnd.getTime(), predictedY);
137
138
139 for (int j = 0; j < predictedScaled.length; ++j) {
140 predictedScaled[j] = getStepSize().multiply(yDot[j]);
141 }
142 predictedNordsieck = updateHighOrderDerivativesPhase1(nordsieck);
143 updateHighOrderDerivativesPhase2(scaled, predictedScaled, predictedNordsieck);
144
145
146 error = errorEstimation(y, stepEnd.getTime(), predictedY, predictedScaled, predictedNordsieck);
147 if (Double.isNaN(error)) {
148 throw new MathIllegalStateException(LocalizedODEFormats.NAN_APPEARING_DURING_INTEGRATION,
149 stepEnd.getTime().getReal());
150 }
151
152 if (error >= 1.0) {
153
154 final double factor = computeStepGrowShrinkFactor(error);
155 rescale(getStepSizeHelper().filterStep(getStepSize().multiply(factor), forward, false));
156 stepEnd = AdamsFieldStateInterpolator.taylor(equations.getMapper(), getStepStart(),
157 getStepStart().getTime().add(getStepSize()),
158 getStepSize(),
159 scaled,
160 nordsieck);
161
162 }
163 }
164
165 final AdamsFieldStateInterpolator<T> interpolator =
166 finalizeStep(getStepSize(), predictedY, predictedScaled, predictedNordsieck,
167 forward, getStepStart(), stepEnd, equations.getMapper());
168
169
170 setStepStart(acceptStep(interpolator, finalTime));
171 scaled = interpolator.getScaled();
172 nordsieck = interpolator.getNordsieck();
173
174 if (!isLastStep()) {
175
176 if (resetOccurred()) {
177
178
179
180 start(equations, getStepStart(), finalTime);
181
182 final T nextT = getStepStart().getTime().add(getStepSize());
183 final boolean nextIsLast = forward ?
184 nextT.subtract(finalTime).getReal() >= 0 :
185 nextT.subtract(finalTime).getReal() <= 0;
186 final T hNew = nextIsLast ? finalTime.subtract(getStepStart().getTime()) : getStepSize();
187
188 rescale(hNew);
189 System.arraycopy(getStepStart().getCompleteState(), 0, y, 0, y.length);
190
191 } else {
192
193
194 final double factor = computeStepGrowShrinkFactor(error);
195 final T scaledH = getStepSize().multiply(factor);
196 final T nextT = getStepStart().getTime().add(scaledH);
197 final boolean nextIsLast = forward ?
198 nextT.subtract(finalTime).getReal() >= 0 :
199 nextT.subtract(finalTime).getReal() <= 0;
200 T hNew = getStepSizeHelper().filterStep(scaledH, forward, nextIsLast);
201
202 final T filteredNextT = getStepStart().getTime().add(hNew);
203 final boolean filteredNextIsLast = forward ?
204 filteredNextT.subtract(finalTime).getReal() >= 0 :
205 filteredNextT.subtract(finalTime).getReal() <= 0;
206 if (filteredNextIsLast) {
207 hNew = finalTime.subtract(getStepStart().getTime());
208 }
209
210 rescale(hNew);
211 System.arraycopy(predictedY, 0, y, 0, y.length);
212
213 }
214
215 stepEnd = AdamsFieldStateInterpolator.taylor(equations.getMapper(), getStepStart(),
216 getStepStart().getTime().add(getStepSize()),
217 getStepSize(), scaled, nordsieck);
218
219 }
220
221 } while (!isLastStep());
222
223 final FieldODEStateAndDerivative<T> finalState = getStepStart();
224 setStepStart(null);
225 setStepSize(null);
226 return finalState;
227
228 }
229
230
231 @Override
232 protected Array2DRowFieldMatrix<T> initializeHighOrderDerivatives(final T h, final T[] t,
233 final T[][] y,
234 final T[][] yDot) {
235 return transformer.initializeHighOrderDerivatives(h, t, y, yDot);
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249 public Array2DRowFieldMatrix<T> updateHighOrderDerivativesPhase1(final Array2DRowFieldMatrix<T> highOrder) {
250 return transformer.updateHighOrderDerivativesPhase1(highOrder);
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 public void updateHighOrderDerivativesPhase2(final T[] start, final T[] end,
267 final Array2DRowFieldMatrix<T> highOrder) {
268 transformer.updateHighOrderDerivativesPhase2(start, end, highOrder);
269 }
270
271
272
273
274
275
276
277
278
279
280 protected abstract double errorEstimation(T[] previousState, T predictedTime,
281 T[] predictedState, T[] predictedScaled,
282 FieldMatrix<T> predictedNordsieck);
283
284
285
286
287
288
289
290
291
292
293
294
295
296 protected abstract AdamsFieldStateInterpolator<T> finalizeStep(T stepSize, T[] predictedState,
297 T[] predictedScaled, Array2DRowFieldMatrix<T> predictedNordsieck,
298 boolean isForward,
299 FieldODEStateAndDerivative<T> globalPreviousState,
300 FieldODEStateAndDerivative<T> globalCurrentState,
301 FieldEquationsMapper<T> equationsMapper);
302
303 }