1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.apache.commons.math4.legacy.ode.events;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.apache.commons.math4.legacy.analysis.solvers.BaseSecantSolver;
23  import org.apache.commons.math4.legacy.analysis.solvers.PegasusSolver;
24  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
25  import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
26  import org.apache.commons.math4.legacy.exception.NoBracketingException;
27  import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
28  import org.apache.commons.math4.legacy.ode.FirstOrderDifferentialEquations;
29  import org.apache.commons.math4.legacy.ode.FirstOrderIntegrator;
30  import org.apache.commons.math4.legacy.ode.nonstiff.DormandPrince853Integrator;
31  import org.junit.Assert;
32  import org.junit.Test;
33  
34  
35  
36  
37  public class OverlappingEventsTest implements FirstOrderDifferentialEquations {
38  
39      
40      private static final double[] EVENT_TIMES1 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
41                                                    7.0, 8.0, 9.0};
42  
43      
44      private static final double[] EVENT_TIMES2 = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0,
45                                                    3.5, 4.0, 4.5, 5.0, 5.5, 6.0,
46                                                    6.5, 7.0, 7.5, 8.0, 8.5, 9.0,
47                                                    9.5};
48  
49      
50  
51  
52  
53  
54      @Test
55      public void testOverlappingEvents0()
56          throws DimensionMismatchException, NumberIsTooSmallException,
57                 MaxCountExceededException, NoBracketingException {
58          test(0);
59      }
60  
61      
62  
63  
64  
65  
66      @Test
67      public void testOverlappingEvents1()
68          throws DimensionMismatchException, NumberIsTooSmallException,
69                 MaxCountExceededException, NoBracketingException {
70          test(1);
71      }
72  
73      
74  
75  
76  
77  
78  
79      public void test(int eventType)
80          throws DimensionMismatchException, NumberIsTooSmallException,
81                 MaxCountExceededException, NoBracketingException {
82          double e = 1e-15;
83          FirstOrderIntegrator integrator = new DormandPrince853Integrator(e, 100.0, 1e-7, 1e-7);
84          BaseSecantSolver rootSolver = new PegasusSolver(e, e);
85          EventHandler evt1 = new Event(0, eventType);
86          EventHandler evt2 = new Event(1, eventType);
87          integrator.addEventHandler(evt1, 0.1, e, 999, rootSolver);
88          integrator.addEventHandler(evt2, 0.1, e, 999, rootSolver);
89          double t = 0.0;
90          double tEnd = 10.0;
91          double[] y = {0.0, 0.0};
92          List<Double> events1 = new ArrayList<>();
93          List<Double> events2 = new ArrayList<>();
94          while (t < tEnd) {
95              t = integrator.integrate(this, t, y, tEnd, y);
96              
97  
98              if (y[0] >= 1.0) {
99                  y[0] = 0.0;
100                 events1.add(t);
101                 
102             }
103             if (y[1] >= 1.0) {
104                 y[1] = 0.0;
105                 events2.add(t);
106                 
107             }
108         }
109         Assert.assertEquals(EVENT_TIMES1.length, events1.size());
110         Assert.assertEquals(EVENT_TIMES2.length, events2.size());
111         for(int i = 0; i < EVENT_TIMES1.length; i++) {
112             Assert.assertEquals(EVENT_TIMES1[i], events1.get(i), 1e-7);
113         }
114         for(int i = 0; i < EVENT_TIMES2.length; i++) {
115             Assert.assertEquals(EVENT_TIMES2[i], events2.get(i), 1e-7);
116         }
117         
118     }
119 
120     
121     @Override
122     public int getDimension() {
123         return 2;
124     }
125 
126     
127     @Override
128     public void computeDerivatives(double t, double[] y, double[] yDot) {
129         yDot[0] = 1.0;
130         yDot[1] = 2.0;
131     }
132 
133     
134     private static final class Event implements EventHandler {
135         
136         private final int idx;
137 
138         
139         private final int eventType;
140 
141         
142 
143 
144 
145         Event(int idx, int eventType) {
146             this.idx = idx;
147             this.eventType = eventType;
148         }
149 
150         
151         @Override
152         public void init(double t0, double[] y0, double t) {
153         }
154 
155         
156         @Override
157         public double g(double t, double[] y) {
158             return (eventType == 0) ? y[idx] >= 1.0 ? 1.0 : -1.0
159                                     : y[idx] - 1.0;
160         }
161 
162         
163         @Override
164         public Action eventOccurred(double t, double[] y, boolean increasing) {
165             return Action.STOP;
166         }
167 
168         
169         @Override
170         public void resetState(double t, double[] y) {
171             
172         }
173     }
174 }