View Javadoc
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_MAXCHECK = 600;
35  
36      /** Default convergence threshold (s). */
37      public static final double DEFAULT_THRESHOLD = 1.e-6;
38  
39      /** Default maximum number of iterations in the event time search. */
40      public static final int DEFAULT_MAX_ITER = 100;
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          forward = t.subtract(s0.getTime()).getReal() >= 0;
83          getHandler().init(s0, t, this);
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      public abstract E g(FieldODEStateAndDerivative<E> s);
89  
90      /** {@inheritDoc} */
91      @Override
92      public FieldAdaptableInterval<E> getMaxCheckInterval() {
93          return maxCheck;
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      public int getMaxIterationCount() {
99          return maxIter;
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public BracketedRealFieldUnivariateSolver<E> getSolver() {
105         return solver;
106     }
107 
108     /**
109      * Setup the maximum checking interval.
110      * <p>
111      * This will override a maximum checking interval if it has been configured previously.
112      * </p>
113      * @param newMaxCheck maximum checking interval (s)
114      * @return a new detector with updated configuration (the instance is not changed)
115      */
116     public T withMaxCheck(final E newMaxCheck) {
117         return withMaxCheck(s -> newMaxCheck.getReal());
118     }
119 
120     /**
121      * Setup the maximum checking interval.
122      * <p>
123      * This will override a maximum checking interval if it has been configured previously.
124      * </p>
125      * @param newMaxCheck maximum checking interval (s)
126      * @return a new detector with updated configuration (the instance is not changed)
127      * @since 3.0
128      */
129     public T withMaxCheck(final FieldAdaptableInterval<E> newMaxCheck) {
130         return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler());
131     }
132 
133     /**
134      * Setup the maximum number of iterations in the event time search.
135      * <p>
136      * This will override a number of iterations if it has been configured previously.
137      * </p>
138      * @param newMaxIter maximum number of iterations in the event time search
139      * @return a new detector with updated configuration (the instance is not changed)
140      */
141     public T withMaxIter(final int newMaxIter) {
142         return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler());
143     }
144 
145     /**
146      * Setup the convergence threshold.
147      * <p>
148      * This is equivalent to call {@code withSolver(new FieldBracketingNthOrderBrentSolver<>(zero,
149      * newThreshold, zero, 5)}, so it will override a solver if one has been configured previously.
150      * </p>
151      * @param newThreshold convergence threshold
152      * @return a new detector with updated configuration (the instance is not changed)
153      * @see #withSolver(BracketedRealFieldUnivariateSolver)
154      */
155     public T withThreshold(final E newThreshold) {
156         final E zero = newThreshold.getField().getZero();
157         return withSolver(new FieldBracketingNthOrderBrentSolver<>(zero, newThreshold, zero, 5));
158     }
159 
160     /**
161      * Setup the root-finding algorithm to use to detect state events.
162      * <p>
163      * This will override a solver if it has been configured previously.
164      * </p>
165      * @param newSolver root-finding algorithm to use to detect state events
166      * @return a new detector with updated configuration (the instance is not changed)
167      * @see #withThreshold(CalculusFieldElement)
168      */
169     public T withSolver(final BracketedRealFieldUnivariateSolver<E> newSolver) {
170         return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler());
171     }
172 
173     /**
174      * Setup the event handler to call at event occurrences.
175      * <p>
176      * This will override a handler if it has been configured previously.
177      * </p>
178      * @param newHandler event handler to call at event occurrences
179      * @return a new detector with updated configuration (the instance is not changed)
180      */
181     public T withHandler(final FieldODEEventHandler<E> newHandler) {
182         return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler);
183     }
184 
185     /** {@inheritDoc} */
186     @Override
187     public FieldODEEventHandler<E> getHandler() {
188         return handler;
189     }
190 
191     /** Build a new instance.
192      * @param newMaxCheck maximum checking interval
193      * @param newMaxIter maximum number of iterations in the event time search
194      * @param newSolver root-finding algorithm to use to detect state events
195      * @param newHandler event handler to call at event occurrences
196      * @return a new instance of the appropriate sub-type
197      */
198     protected abstract T create(FieldAdaptableInterval<E> newMaxCheck, int newMaxIter,
199                                 BracketedRealFieldUnivariateSolver<E> newSolver,
200                                 FieldODEEventHandler<E> newHandler);
201 
202     /** Check if the current propagation is forward or backward.
203      * @return true if the current propagation is forward
204      */
205     public boolean isForward() {
206         return forward;
207     }
208 
209 }