1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.ode.nonstiff;
19
20 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
21 import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
22 import org.apache.commons.math4.legacy.exception.NoBracketingException;
23 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
24 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
25 import org.apache.commons.math4.legacy.ode.AbstractIntegrator;
26 import org.apache.commons.math4.legacy.ode.ExpandableStatefulODE;
27 import org.apache.commons.math4.core.jdkmath.JdkMath;
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
64
65 public abstract class AdaptiveStepsizeIntegrator
66 extends AbstractIntegrator {
67
68
69 protected double scalAbsoluteTolerance;
70
71
72 protected double scalRelativeTolerance;
73
74
75 protected double[] vecAbsoluteTolerance;
76
77
78 protected double[] vecRelativeTolerance;
79
80
81 protected int mainSetDimension;
82
83
84 private double initialStep;
85
86
87 private double minStep;
88
89
90 private double maxStep;
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public AdaptiveStepsizeIntegrator(final String name,
105 final double minStep, final double maxStep,
106 final double scalAbsoluteTolerance,
107 final double scalRelativeTolerance) {
108
109 super(name);
110 setStepSizeControl(minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
111 resetInternalState();
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public AdaptiveStepsizeIntegrator(final String name,
127 final double minStep, final double maxStep,
128 final double[] vecAbsoluteTolerance,
129 final double[] vecRelativeTolerance) {
130
131 super(name);
132 setStepSizeControl(minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
133 resetInternalState();
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 public void setStepSizeControl(final double minimalStep, final double maximalStep,
151 final double absoluteTolerance,
152 final double relativeTolerance) {
153
154 minStep = JdkMath.abs(minimalStep);
155 maxStep = JdkMath.abs(maximalStep);
156 initialStep = -1;
157
158 scalAbsoluteTolerance = absoluteTolerance;
159 scalRelativeTolerance = relativeTolerance;
160 vecAbsoluteTolerance = null;
161 vecRelativeTolerance = null;
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 public void setStepSizeControl(final double minimalStep, final double maximalStep,
179 final double[] absoluteTolerance,
180 final double[] relativeTolerance) {
181
182 minStep = JdkMath.abs(minimalStep);
183 maxStep = JdkMath.abs(maximalStep);
184 initialStep = -1;
185
186 scalAbsoluteTolerance = 0;
187 scalRelativeTolerance = 0;
188 vecAbsoluteTolerance = absoluteTolerance.clone();
189 vecRelativeTolerance = relativeTolerance.clone();
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 public void setInitialStepSize(final double initialStepSize) {
204 if (initialStepSize < minStep || initialStepSize > maxStep) {
205 initialStep = -1.0;
206 } else {
207 initialStep = initialStepSize;
208 }
209 }
210
211
212 @Override
213 protected void sanityChecks(final ExpandableStatefulODE equations, final double t)
214 throws DimensionMismatchException, NumberIsTooSmallException {
215
216 super.sanityChecks(equations, t);
217
218 mainSetDimension = equations.getPrimaryMapper().getDimension();
219
220 if (vecAbsoluteTolerance != null && vecAbsoluteTolerance.length != mainSetDimension) {
221 throw new DimensionMismatchException(mainSetDimension, vecAbsoluteTolerance.length);
222 }
223
224 if (vecRelativeTolerance != null && vecRelativeTolerance.length != mainSetDimension) {
225 throw new DimensionMismatchException(mainSetDimension, vecRelativeTolerance.length);
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 public double initializeStep(final boolean forward, final int order, final double[] scale,
243 final double t0, final double[] y0, final double[] yDot0,
244 final double[] y1, final double[] yDot1)
245 throws MaxCountExceededException, DimensionMismatchException {
246
247 if (initialStep > 0) {
248
249 return forward ? initialStep : -initialStep;
250 }
251
252
253
254 double ratio;
255 double yOnScale2 = 0;
256 double yDotOnScale2 = 0;
257 for (int j = 0; j < scale.length; ++j) {
258 ratio = y0[j] / scale[j];
259 yOnScale2 += ratio * ratio;
260 ratio = yDot0[j] / scale[j];
261 yDotOnScale2 += ratio * ratio;
262 }
263
264 double h = (yOnScale2 < 1.0e-10 || yDotOnScale2 < 1.0e-10) ?
265 1.0e-6 : (0.01 * JdkMath.sqrt(yOnScale2 / yDotOnScale2));
266 if (! forward) {
267 h = -h;
268 }
269
270
271 for (int j = 0; j < y0.length; ++j) {
272 y1[j] = y0[j] + h * yDot0[j];
273 }
274 computeDerivatives(t0 + h, y1, yDot1);
275
276
277 double yDDotOnScale = 0;
278 for (int j = 0; j < scale.length; ++j) {
279 ratio = (yDot1[j] - yDot0[j]) / scale[j];
280 yDDotOnScale += ratio * ratio;
281 }
282 yDDotOnScale = JdkMath.sqrt(yDDotOnScale) / h;
283
284
285
286 final double maxInv2 = JdkMath.max(JdkMath.sqrt(yDotOnScale2), yDDotOnScale);
287 final double h1 = (maxInv2 < 1.0e-15) ?
288 JdkMath.max(1.0e-6, 0.001 * JdkMath.abs(h)) :
289 JdkMath.pow(0.01 / maxInv2, 1.0 / order);
290 h = JdkMath.min(100.0 * JdkMath.abs(h), h1);
291 h = JdkMath.max(h, 1.0e-12 * JdkMath.abs(t0));
292 if (h < getMinStep()) {
293 h = getMinStep();
294 }
295 if (h > getMaxStep()) {
296 h = getMaxStep();
297 }
298 if (! forward) {
299 h = -h;
300 }
301
302 return h;
303 }
304
305
306
307
308
309
310
311
312
313
314 protected double filterStep(final double h, final boolean forward, final boolean acceptSmall)
315 throws NumberIsTooSmallException {
316
317 double filteredH = h;
318 if (JdkMath.abs(h) < minStep) {
319 if (acceptSmall) {
320 filteredH = forward ? minStep : -minStep;
321 } else {
322 throw new NumberIsTooSmallException(LocalizedFormats.MINIMAL_STEPSIZE_REACHED_DURING_INTEGRATION,
323 JdkMath.abs(h), minStep, true);
324 }
325 }
326
327 if (filteredH > maxStep) {
328 filteredH = maxStep;
329 } else if (filteredH < -maxStep) {
330 filteredH = -maxStep;
331 }
332
333 return filteredH;
334 }
335
336
337 @Override
338 public abstract void integrate (ExpandableStatefulODE equations, double t)
339 throws NumberIsTooSmallException, DimensionMismatchException,
340 MaxCountExceededException, NoBracketingException;
341
342
343 @Override
344 public double getCurrentStepStart() {
345 return stepStart;
346 }
347
348
349 protected void resetInternalState() {
350 stepStart = Double.NaN;
351 stepSize = JdkMath.sqrt(minStep * maxStep);
352 }
353
354
355
356
357 public double getMinStep() {
358 return minStep;
359 }
360
361
362
363
364 public double getMaxStep() {
365 return maxStep;
366 }
367 }