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.events;
19
20
21 import org.apache.commons.math4.legacy.analysis.solvers.BrentSolver;
22 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
23 import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
24 import org.apache.commons.math4.legacy.exception.NoBracketingException;
25 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
26 import org.apache.commons.math4.legacy.ode.ExpandableStatefulODE;
27 import org.apache.commons.math4.legacy.ode.FirstOrderDifferentialEquations;
28 import org.apache.commons.math4.legacy.ode.SecondaryEquations;
29 import org.apache.commons.math4.legacy.ode.nonstiff.DormandPrince853Integrator;
30 import org.apache.commons.math4.legacy.ode.nonstiff.LutherIntegrator;
31 import org.apache.commons.math4.legacy.ode.sampling.AbstractStepInterpolator;
32 import org.apache.commons.math4.legacy.ode.sampling.DummyStepInterpolator;
33 import org.junit.Assert;
34 import org.junit.Test;
35
36 public class EventStateTest {
37
38
39 @Test
40 public void closeEvents() throws MaxCountExceededException, NoBracketingException {
41
42 final double r1 = 90.0;
43 final double r2 = 135.0;
44 final double gap = r2 - r1;
45
46 final double tolerance = 0.1;
47 EventState es = new EventState(new CloseEventsGenerator(r1, r2), 1.5 * gap,
48 tolerance, 100,
49 new BrentSolver(tolerance));
50 es.setExpandable(new ExpandableStatefulODE(new FirstOrderDifferentialEquations() {
51 @Override
52 public int getDimension() {
53 return 0;
54 }
55 @Override
56 public void computeDerivatives(double t, double[] y, double[] yDot) {
57 }
58 }));
59
60 AbstractStepInterpolator interpolator =
61 new DummyStepInterpolator(new double[0], new double[0], true);
62 interpolator.storeTime(r1 - 2.5 * gap);
63 interpolator.shift();
64 interpolator.storeTime(r1 - 1.5 * gap);
65 es.reinitializeBegin(interpolator);
66
67 interpolator.shift();
68 interpolator.storeTime(r1 - 0.5 * gap);
69 Assert.assertFalse(es.evaluateStep(interpolator));
70
71 interpolator.shift();
72 interpolator.storeTime(0.5 * (r1 + r2));
73 Assert.assertTrue(es.evaluateStep(interpolator));
74 Assert.assertEquals(r1, es.getEventTime(), tolerance);
75 es.stepAccepted(es.getEventTime(), new double[0]);
76
77 interpolator.shift();
78 interpolator.storeTime(r2 + 0.4 * gap);
79 Assert.assertTrue(es.evaluateStep(interpolator));
80 Assert.assertEquals(r2, es.getEventTime(), tolerance);
81 }
82
83
84 @Test
85 public void testIssue695()
86 throws DimensionMismatchException, NumberIsTooSmallException,
87 MaxCountExceededException, NoBracketingException {
88
89 FirstOrderDifferentialEquations equation = new FirstOrderDifferentialEquations() {
90
91 @Override
92 public int getDimension() {
93 return 1;
94 }
95
96 @Override
97 public void computeDerivatives(double t, double[] y, double[] yDot) {
98 yDot[0] = 1.0;
99 }
100 };
101
102 DormandPrince853Integrator integrator = new DormandPrince853Integrator(0.001, 1000, 1.0e-14, 1.0e-14);
103 integrator.addEventHandler(new ResettingEvent(10.99), 0.1, 1.0e-9, 1000);
104 integrator.addEventHandler(new ResettingEvent(11.01), 0.1, 1.0e-9, 1000);
105 integrator.setInitialStepSize(3.0);
106
107 double target = 30.0;
108 double[] y = new double[1];
109 double tEnd = integrator.integrate(equation, 0.0, y, target, y);
110 Assert.assertEquals(target, tEnd, 1.0e-10);
111 Assert.assertEquals(32.0, y[0], 1.0e-10);
112 }
113
114 private static final class ResettingEvent implements EventHandler {
115
116 private static double lastTriggerTime = Double.NEGATIVE_INFINITY;
117 private final double tEvent;
118
119 ResettingEvent(final double tEvent) {
120 this.tEvent = tEvent;
121 }
122
123 @Override
124 public void init(double t0, double[] y0, double t) {
125 }
126
127 @Override
128 public double g(double t, double[] y) {
129
130
131
132
133 Assert.assertTrue("going backward in time! (" + t + " < " + lastTriggerTime + ")",
134 t >= lastTriggerTime);
135 return t - tEvent;
136 }
137
138 @Override
139 public Action eventOccurred(double t, double[] y, boolean increasing) {
140
141 lastTriggerTime = t;
142 return Action.RESET_STATE;
143 }
144
145 @Override
146 public void resetState(double t, double[] y) {
147 y[0] += 1.0;
148 }
149 }
150
151
152 @Test
153 public void testIssue965()
154 throws DimensionMismatchException, NumberIsTooSmallException,
155 MaxCountExceededException, NoBracketingException {
156
157 ExpandableStatefulODE equation =
158 new ExpandableStatefulODE(new FirstOrderDifferentialEquations() {
159
160 @Override
161 public int getDimension() {
162 return 1;
163 }
164
165 @Override
166 public void computeDerivatives(double t, double[] y, double[] yDot) {
167 yDot[0] = 2.0;
168 }
169 });
170 equation.setTime(0.0);
171 equation.setPrimaryState(new double[1]);
172 equation.addSecondaryEquations(new SecondaryEquations() {
173
174 @Override
175 public int getDimension() {
176 return 1;
177 }
178
179 @Override
180 public void computeDerivatives(double t, double[] primary,
181 double[] primaryDot, double[] secondary,
182 double[] secondaryDot) {
183 secondaryDot[0] = -3.0;
184 }
185 });
186 int index = equation.getSecondaryMappers()[0].getFirstIndex();
187
188 DormandPrince853Integrator integrator = new DormandPrince853Integrator(0.001, 1000, 1.0e-14, 1.0e-14);
189 integrator.addEventHandler(new SecondaryStateEvent(index, -3.0), 0.1, 1.0e-9, 1000);
190 integrator.setInitialStepSize(3.0);
191
192 integrator.integrate(equation, 30.0);
193 Assert.assertEquals( 1.0, equation.getTime(), 1.0e-10);
194 Assert.assertEquals( 2.0, equation.getPrimaryState()[0], 1.0e-10);
195 Assert.assertEquals(-3.0, equation.getSecondaryState(0)[0], 1.0e-10);
196 }
197
198 private static final class SecondaryStateEvent implements EventHandler {
199
200 private int index;
201 private final double target;
202
203 SecondaryStateEvent(final int index, final double target) {
204 this.index = index;
205 this.target = target;
206 }
207
208 @Override
209 public void init(double t0, double[] y0, double t) {
210 }
211
212 @Override
213 public double g(double t, double[] y) {
214 return y[index] - target;
215 }
216
217 @Override
218 public Action eventOccurred(double t, double[] y, boolean increasing) {
219 return Action.STOP;
220 }
221
222 @Override
223 public void resetState(double t, double[] y) {
224 }
225 }
226
227 @Test
228 public void testEventsCloserThanThreshold()
229 throws DimensionMismatchException, NumberIsTooSmallException,
230 MaxCountExceededException, NoBracketingException {
231
232 FirstOrderDifferentialEquations equation = new FirstOrderDifferentialEquations() {
233
234 @Override
235 public int getDimension() {
236 return 1;
237 }
238
239 @Override
240 public void computeDerivatives(double t, double[] y, double[] yDot) {
241 yDot[0] = 1.0;
242 }
243 };
244
245 LutherIntegrator integrator = new LutherIntegrator(20.0);
246 CloseEventsGenerator eventsGenerator =
247 new CloseEventsGenerator(9.0 - 1.0 / 128, 9.0 + 1.0 / 128);
248 integrator.addEventHandler(eventsGenerator, 1.0, 0.02, 1000);
249 double[] y = new double[1];
250 double tEnd = integrator.integrate(equation, 0.0, y, 100.0, y);
251 Assert.assertEquals( 2, eventsGenerator.getCount());
252 Assert.assertEquals( 9.0 + 1.0 / 128, tEnd, 1.0 / 32.0);
253 }
254
255 private static final class CloseEventsGenerator implements EventHandler {
256
257 private final double r1;
258 private final double r2;
259 private int count;
260
261 CloseEventsGenerator(final double r1, final double r2) {
262 this.r1 = r1;
263 this.r2 = r2;
264 this.count = 0;
265 }
266
267 @Override
268 public void init(double t0, double[] y0, double t) {
269 }
270
271 @Override
272 public void resetState(double t, double[] y) {
273 }
274
275 @Override
276 public double g(double t, double[] y) {
277 return (t - r1) * (r2 - t);
278 }
279
280 @Override
281 public Action eventOccurred(double t, double[] y, boolean increasing) {
282 return ++count < 2 ? Action.CONTINUE : Action.STOP;
283 }
284
285 public int getCount() {
286 return count;
287 }
288 }
289 }