1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.ode.events;
18
19 import org.hipparchus.analysis.UnivariateFunction;
20 import org.hipparchus.analysis.solvers.BracketedUnivariateSolver;
21 import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
22 import org.hipparchus.ode.ODEIntegrator;
23 import org.hipparchus.ode.ODEState;
24 import org.hipparchus.ode.ODEStateAndDerivative;
25 import org.hipparchus.ode.OrdinaryDifferentialEquation;
26 import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
27 import org.hipparchus.util.FastMath;
28 import org.junit.jupiter.api.Test;
29
30 import static org.junit.jupiter.api.Assertions.assertEquals;
31
32
33
34 public class VariableCheckInterval implements OrdinaryDifferentialEquation {
35
36 @Test
37 void testFixedInterval() {
38 double tZero = 7.0;
39 double width = 0.25;
40 doTest(tZero, width, (s, isForward) -> width / 25, 710);
41 }
42
43 @Test
44 void testWidthAwareInterval() {
45 double tZero = 7.0;
46 double width = 0.25;
47 doTest(tZero, width,
48 (s, isForward) -> {
49 if (s.getTime() < tZero - 0.5 * width) {
50 return tZero - 0.25 * width - s.getTime();
51 } else if (s.getTime() > tZero + 0.5 * width) {
52 return s.getTime() - (tZero + 0.25 * width);
53 } else {
54 return width / 25;
55 }
56 },
57 21);
58 }
59
60 private void doTest(final double tZero, final double width, final AdaptableInterval checkInterval,
61 final int expectedCalls) {
62 double e = 1e-15;
63 ODEIntegrator integrator = new DormandPrince853Integrator(e, 100.0, 1e-7, 1e-7);
64 Event evt = new Event(checkInterval, e, 999, tZero, width);
65 integrator.addEventDetector(evt);
66 double t = 0.0;
67 double tEnd = 9.75;
68 double[] y = {0.0, 0.0};
69 final ODEStateAndDerivative finalState =
70 integrator.integrate(this, new ODEState(t, y), tEnd);
71 t = finalState.getTime();
72 assertEquals(tZero, finalState.getTime(), e);
73 assertEquals(expectedCalls, evt.count);
74 }
75
76
77 public int getDimension() {
78 return 2;
79 }
80
81
82 public double[] computeDerivatives(double t, double[] y) {
83 return new double[] { 1.0, 2.0 };
84 }
85
86
87 private class Event implements ODEEventDetector {
88
89 private final AdaptableInterval maxCheck;
90 private final int maxIter;
91 private final BracketingNthOrderBrentSolver solver;
92 private final double tZero;
93 private final double width;
94 private int count;
95
96
97
98
99
100
101
102
103 public Event(final AdaptableInterval maxCheck, final double threshold, final int maxIter,
104 final double tZero, final double width) {
105 this.maxCheck = maxCheck;
106 this.maxIter = maxIter;
107 this.solver = new BracketingNthOrderBrentSolver(0, threshold, 0, 5);
108 this.tZero = tZero;
109 this.width = width;
110 }
111
112 public AdaptableInterval getMaxCheckInterval() {
113 return maxCheck;
114 }
115
116 public int getMaxIterationCount() {
117 return maxIter;
118 }
119
120 public BracketedUnivariateSolver<UnivariateFunction> getSolver() {
121 return solver;
122 }
123
124 public ODEEventHandler getHandler() {
125 return (state, detector, increasing) -> Action.STOP;
126 }
127
128
129 public double g(final ODEStateAndDerivative s) {
130 ++count;
131 final double t = s.getTime();
132 return FastMath.max(-0.5 * width, FastMath.min(0.5 * width, t - tZero));
133 }
134
135
136 public void init(final ODEStateAndDerivative initialState, final double finalTime) {
137 count = 0;
138 }
139
140 }
141
142 }