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