1 /*
2 * Licensed to the Hipparchus project under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.hipparchus.ode.events;
19
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.solvers.BracketedRealFieldUnivariateSolver;
22 import org.hipparchus.analysis.solvers.FieldBracketingNthOrderBrentSolver;
23 import org.hipparchus.ode.FieldODEStateAndDerivative;
24
25 /** Base class for #@link {@link FieldODEEventDetector}.
26 * @param <T> type of the detector
27 * @param <E> type of the field elements
28 * @since 3.0
29 */
30 public abstract class AbstractFieldODEDetector<T extends AbstractFieldODEDetector<T, E>, E extends CalculusFieldElement<E>>
31 implements FieldODEEventDetector<E> {
32
33 /** Default maximum checking interval (s). */
34 public static final double DEFAULT_MAX_CHECK = AbstractODEDetector.DEFAULT_MAX_CHECK;
35
36 /** Default convergence threshold (s). */
37 public static final double DEFAULT_THRESHOLD = AbstractODEDetector.DEFAULT_THRESHOLD;
38
39 /** Default maximum number of iterations in the event time search. */
40 public static final int DEFAULT_MAX_ITER = AbstractODEDetector.DEFAULT_MAX_ITER;
41
42 /** Max check interval. */
43 private final FieldAdaptableInterval<E> maxCheck;
44
45 /** Maximum number of iterations in the event time search. */
46 private final int maxIter;
47
48 /** Root-finding algorithm to use to detect state events. */
49 private final BracketedRealFieldUnivariateSolver<E> solver;
50
51 /** Default handler for event overrides. */
52 private final FieldODEEventHandler<E> handler;
53
54 /** Propagation direction. */
55 private boolean forward;
56
57 /** Build a new instance.
58 * @param maxCheck maximum checking interval, must be strictly positive (s)
59 * @param maxIter maximum number of iterations in the event time search
60 * @param solver root-finding algorithm to use to detect state events
61 * @param handler event handler to call at event occurrences
62 */
63 protected AbstractFieldODEDetector(final FieldAdaptableInterval<E> maxCheck, final int maxIter,
64 final BracketedRealFieldUnivariateSolver<E> solver,
65 final FieldODEEventHandler<E> handler) {
66 this.maxCheck = maxCheck;
67 this.maxIter = maxIter;
68 this.solver = solver;
69 this.handler = handler;
70 this.forward = true;
71 }
72
73 /**
74 * {@inheritDoc}
75 *
76 * <p> This implementation sets the direction of integration and initializes the event
77 * handler. If a subclass overrides this method it should call {@code
78 * super.init(s0, t)}.
79 */
80 @Override
81 public void init(final FieldODEStateAndDerivative<E> s0, final E t) {
82 FieldODEEventDetector.super.init(s0, t);
83 forward = t.subtract(s0.getTime()).getReal() >= 0;
84 }
85
86 /** {@inheritDoc} */
87 @Override
88 public FieldAdaptableInterval<E> getMaxCheckInterval() {
89 return maxCheck;
90 }
91
92 /** {@inheritDoc} */
93 @Override
94 public int getMaxIterationCount() {
95 return maxIter;
96 }
97
98 /** {@inheritDoc} */
99 @Override
100 public BracketedRealFieldUnivariateSolver<E> getSolver() {
101 return solver;
102 }
103
104 /**
105 * Setup the maximum checking interval.
106 * <p>
107 * This will override a maximum checking interval if it has been configured previously.
108 * </p>
109 * @param newMaxCheck maximum checking interval (s)
110 * @return a new detector with updated configuration (the instance is not changed)
111 */
112 public T withMaxCheck(final E newMaxCheck) {
113 return withMaxCheck(FieldAdaptableInterval.of(newMaxCheck.getReal()));
114 }
115
116 /**
117 * Setup the maximum checking interval.
118 * <p>
119 * This will override a maximum checking interval if it has been configured previously.
120 * </p>
121 * @param newMaxCheck maximum checking interval (s)
122 * @return a new detector with updated configuration (the instance is not changed)
123 * @since 3.0
124 */
125 public T withMaxCheck(final FieldAdaptableInterval<E> newMaxCheck) {
126 return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler());
127 }
128
129 /**
130 * Setup the maximum number of iterations in the event time search.
131 * <p>
132 * This will override a number of iterations if it has been configured previously.
133 * </p>
134 * @param newMaxIter maximum number of iterations in the event time search
135 * @return a new detector with updated configuration (the instance is not changed)
136 */
137 public T withMaxIter(final int newMaxIter) {
138 return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler());
139 }
140
141 /**
142 * Setup the convergence threshold.
143 * <p>
144 * This is equivalent to call {@code withSolver(new FieldBracketingNthOrderBrentSolver<>(zero,
145 * newThreshold, zero, 5)}, so it will override a solver if one has been configured previously.
146 * </p>
147 * @param newThreshold convergence threshold
148 * @return a new detector with updated configuration (the instance is not changed)
149 * @see #withSolver(BracketedRealFieldUnivariateSolver)
150 */
151 public T withThreshold(final E newThreshold) {
152 final E zero = newThreshold.getField().getZero();
153 return withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, newThreshold, zero, 5));
154 }
155
156 /**
157 * Setup the root-finding algorithm to use to detect state events.
158 * <p>
159 * This will override a solver if it has been configured previously.
160 * </p>
161 * @param newSolver root-finding algorithm to use to detect state events
162 * @return a new detector with updated configuration (the instance is not changed)
163 * @see #withThreshold(CalculusFieldElement)
164 */
165 public T withSolver(final BracketedRealFieldUnivariateSolver<E> newSolver) {
166 return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler());
167 }
168
169 /**
170 * Setup the event handler to call at event occurrences.
171 * <p>
172 * This will override a handler if it has been configured previously.
173 * </p>
174 * @param newHandler event handler to call at event occurrences
175 * @return a new detector with updated configuration (the instance is not changed)
176 */
177 public T withHandler(final FieldODEEventHandler<E> newHandler) {
178 return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler);
179 }
180
181 /** {@inheritDoc} */
182 @Override
183 public FieldODEEventHandler<E> getHandler() {
184 return handler;
185 }
186
187 /** Build a new instance.
188 * @param newMaxCheck maximum checking interval
189 * @param newMaxIter maximum number of iterations in the event time search
190 * @param newSolver root-finding algorithm to use to detect state events
191 * @param newHandler event handler to call at event occurrences
192 * @return a new instance of the appropriate sub-type
193 */
194 protected abstract T create(FieldAdaptableInterval<E> newMaxCheck, int newMaxIter,
195 BracketedRealFieldUnivariateSolver<E> newSolver,
196 FieldODEEventHandler<E> newHandler);
197
198 /** Check if the current propagation is forward or backward.
199 * @return true if the current propagation is forward
200 */
201 public boolean isForward() {
202 return forward;
203 }
204
205 }