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