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