View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) 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 ASF 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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.ode.events;
24  
25  import org.hipparchus.exception.MathRuntimeException;
26  
27  /** Enumerate for {@link EventSlopeFilter filtering events}.
28   *
29   */
30  
31  public enum FilterType {
32  
33      /** Constant for triggering only decreasing events.
34       * <p>When this filter is used, the wrapped {@link ODEEventHandler
35       * event handler} {@link ODEEventHandler#eventOccurred(org.hipparchus.ode.ODEStateAndDerivative,
36       * ODEEventDetector, boolean) eventOccurred} method will be called <em>only</em> with
37       * its {@code increasing} argument set to false.</p>
38       */
39      TRIGGER_ONLY_DECREASING_EVENTS {
40  
41          /**  {@inheritDoc} */
42          @Override
43          protected boolean isTriggeredOnIncreasing() {
44              return false;
45          }
46  
47          /** {@inheritDoc}
48           * <p>
49           * states scheduling for computing h(t,y) as an altered version of g(t, y)
50           * <ul>
51           * <li>0 are triggered events for which a zero is produced (here decreasing events)</li>
52           * <li>X are ignored events for which zero is masked (here increasing events)</li>
53           * </ul>
54           * </p>
55           * <pre>
56           *  g(t)
57           *             ___                     ___                     ___
58           *            /   \                   /   \                   /   \
59           *           /     \                 /     \                 /     \
60           *          /  g>0  \               /  g>0  \               /  g>0  \
61           *         /         \             /         \             /         \
62           *  ----- X --------- 0 --------- X --------- 0 --------- X --------- 0 ---
63           *       /             \         /             \         /             \
64           *      /               \ g<0   /               \  g<0  /               \ g<0
65           *     /                 \     /                 \     /                 \     /
66           * ___/                   \___/                   \___/                   \___/
67           * </pre>
68           * <pre>
69           *  h(t,y)) as an alteration of g(t,y)
70           *             ___                                 ___         ___
71           *    \       /   \                               /   \       /   \
72           *     \     /     \ h=+g                        /     \     /     \
73           *      \   /       \      h=min(-s,-g,+g)      /       \   /       \
74           *       \_/         \                         /         \_/         \
75           *  ------ ---------- 0 ----------_---------- 0 --------------------- 0 ---
76           *                     \         / \         /                         \
77           *   h=max(+s,-g,+g)    \       /   \       /       h=max(+s,-g,+g)     \
78           *                       \     /     \     / h=-g                        \     /
79           *                        \___/       \___/                               \___/
80           * </pre>
81           * <p>
82           * As shown by the figure above, several expressions are used to compute h,
83           * depending on the current state:
84           * <ul>
85           *   <li>h = max(+s,-g,+g)</li>
86           *   <li>h = +g</li>
87           *   <li>h = min(-s,-g,+g)</li>
88           *   <li>h = -g</li>
89           * </ul>
90           * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}.
91           * </p>
92           */
93          @Override
94          protected  Transformer selectTransformer(final Transformer previous,
95                                                   final double g, final boolean forward) {
96              if (forward) {
97                  switch (previous) {
98                      case UNINITIALIZED :
99                          // we are initializing the first point
100                         if (g > 0) {
101                             // initialize as if previous root (i.e. backward one) was an ignored increasing event
102                             return Transformer.MAX;
103                         } else if (g < 0) {
104                             // initialize as if previous root (i.e. backward one) was a triggered decreasing event
105                             return Transformer.PLUS;
106                         } else {
107                             // we are exactly at a root, we don't know if it is an increasing
108                             // or a decreasing event, we remain in uninitialized state
109                             return Transformer.UNINITIALIZED;
110                         }
111                     case PLUS  :
112                         if (g >= 0) {
113                             // we have crossed the zero line on an ignored increasing event,
114                             // we must change the transformer
115                             return Transformer.MIN;
116                         } else {
117                             // we are still in the same status
118                             return previous;
119                         }
120                     case MINUS :
121                         if (g >= 0) {
122                             // we have crossed the zero line on an ignored increasing event,
123                             // we must change the transformer
124                             return Transformer.MAX;
125                         } else {
126                             // we are still in the same status
127                             return previous;
128                         }
129                     case MIN   :
130                         if (g <= 0) {
131                             // we have crossed the zero line on a triggered decreasing event,
132                             // we must change the transformer
133                             return Transformer.MINUS;
134                         } else {
135                             // we are still in the same status
136                             return previous;
137                         }
138                     case MAX   :
139                         if (g <= 0) {
140                             // we have crossed the zero line on a triggered decreasing event,
141                             // we must change the transformer
142                             return Transformer.PLUS;
143                         } else {
144                             // we are still in the same status
145                             return previous;
146                         }
147                     default    :
148                         // this should never happen
149                         throw MathRuntimeException.createInternalError();
150                 }
151             } else {
152                 switch (previous) {
153                     case UNINITIALIZED :
154                         // we are initializing the first point
155                         if (g > 0) {
156                             // initialize as if previous root (i.e. forward one) was a triggered decreasing event
157                             return Transformer.MINUS;
158                         } else if (g < 0) {
159                             // initialize as if previous root (i.e. forward one) was an ignored increasing event
160                             return Transformer.MIN;
161                         } else {
162                             // we are exactly at a root, we don't know if it is an increasing
163                             // or a decreasing event, we remain in uninitialized state
164                             return Transformer.UNINITIALIZED;
165                         }
166                     case PLUS  :
167                         if (g <= 0) {
168                             // we have crossed the zero line on an ignored increasing event,
169                             // we must change the transformer
170                             return Transformer.MAX;
171                         } else {
172                             // we are still in the same status
173                             return previous;
174                         }
175                     case MINUS :
176                         if (g <= 0) {
177                             // we have crossed the zero line on an ignored increasing event,
178                             // we must change the transformer
179                             return Transformer.MIN;
180                         } else {
181                             // we are still in the same status
182                             return previous;
183                         }
184                     case MIN   :
185                         if (g >= 0) {
186                             // we have crossed the zero line on a triggered decreasing event,
187                             // we must change the transformer
188                             return Transformer.PLUS;
189                         } else {
190                             // we are still in the same status
191                             return previous;
192                         }
193                     case MAX   :
194                         if (g >= 0) {
195                             // we have crossed the zero line on a triggered decreasing event,
196                             // we must change the transformer
197                             return Transformer.MINUS;
198                         } else {
199                             // we are still in the same status
200                             return previous;
201                         }
202                     default    :
203                         // this should never happen
204                         throw MathRuntimeException.createInternalError();
205                 }
206             }
207         }
208 
209     },
210 
211     /** Constant for triggering only increasing events.
212      * <p>When this filter is used, the wrapped {@link ODEEventHandler
213      * event handler} {@link ODEEventHandler#eventOccurred(org.hipparchus.ode.ODEStateAndDerivative,
214      * ODEEventDetector, boolean) eventOccurred} method will be called <em>only</em> with
215      * its {@code increasing} argument set to true.</p>
216      */
217     TRIGGER_ONLY_INCREASING_EVENTS {
218 
219         /**  {@inheritDoc} */
220         @Override
221         protected boolean isTriggeredOnIncreasing() {
222             return true;
223         }
224 
225         /** {@inheritDoc}
226          * <p>
227          * states scheduling for computing h(t,y) as an altered version of g(t, y)
228          * <ul>
229          * <li>0 are triggered events for which a zero is produced (here increasing events)</li>
230          * <li>X are ignored events for which zero is masked (here decreasing events)</li>
231          * </ul>
232          * </p>
233          * <pre>
234          *  g(t)
235          *             ___                     ___                     ___
236          *            /   \                   /   \                   /   \
237          *           /     \                 /     \                 /     \
238          *          /  g>0  \               /  g>0  \               /  g>0  \
239          *         /         \             /         \             /         \
240          *  ----- 0 --------- X --------- 0 --------- X --------- 0 --------- X ---
241          *       /             \         /             \         /             \
242          *      /               \ g<0   /               \  g<0  /               \ g<0
243          *     /                 \     /                 \     /                 \     /
244          * ___/                   \___/                   \___/                   \___/
245          * </pre>
246          * <pre>
247          *  h(t,y)) as an alteration of g(t,y)
248          *                                     ___         ___
249          *    \                               /   \       /   \
250          *     \ h=-g                        /     \     /     \ h=-g
251          *      \      h=min(-s,-g,+g)      /       \   /       \      h=min(-s,-g,+g)
252          *       \                         /         \_/         \
253          *  ------0 ----------_---------- 0 --------------------- 0 --------- _ ---
254          *         \         / \         /                         \         / \
255          *          \       /   \       /       h=max(+s,-g,+g)     \       /   \
256          *           \     /     \     / h=+g                        \     /     \     /
257          *            \___/       \___/                               \___/       \___/
258          * </pre>
259          * <p>
260          * As shown by the figure above, several expressions are used to compute h,
261          * depending on the current state:
262          * <ul>
263          *   <li>h = max(+s,-g,+g)</li>
264          *   <li>h = +g</li>
265          *   <li>h = min(-s,-g,+g)</li>
266          *   <li>h = -g</li>
267          * </ul>
268          * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}.
269          * </p>
270          */
271         @Override
272         protected  Transformer selectTransformer(final Transformer previous,
273                                                  final double g, final boolean forward) {
274             if (forward) {
275                 switch (previous) {
276                     case UNINITIALIZED :
277                         // we are initializing the first point
278                         if (g > 0) {
279                             // initialize as if previous root (i.e. backward one) was a triggered increasing event
280                             return Transformer.PLUS;
281                         } else if (g < 0) {
282                             // initialize as if previous root (i.e. backward one) was an ignored decreasing event
283                             return Transformer.MIN;
284                         } else {
285                             // we are exactly at a root, we don't know if it is an increasing
286                             // or a decreasing event, we remain in uninitialized state
287                             return Transformer.UNINITIALIZED;
288                         }
289                     case PLUS  :
290                         if (g <= 0) {
291                             // we have crossed the zero line on an ignored decreasing event,
292                             // we must change the transformer
293                             return Transformer.MAX;
294                         } else {
295                             // we are still in the same status
296                             return previous;
297                         }
298                     case MINUS :
299                         if (g <= 0) {
300                             // we have crossed the zero line on an ignored decreasing event,
301                             // we must change the transformer
302                             return Transformer.MIN;
303                         } else {
304                             // we are still in the same status
305                             return previous;
306                         }
307                     case MIN   :
308                         if (g >= 0) {
309                             // we have crossed the zero line on a triggered increasing event,
310                             // we must change the transformer
311                             return Transformer.PLUS;
312                         } else {
313                             // we are still in the same status
314                             return previous;
315                         }
316                     case MAX   :
317                         if (g >= 0) {
318                             // we have crossed the zero line on a triggered increasing event,
319                             // we must change the transformer
320                             return Transformer.MINUS;
321                         } else {
322                             // we are still in the same status
323                             return previous;
324                         }
325                     default    :
326                         // this should never happen
327                         throw MathRuntimeException.createInternalError();
328                 }
329             } else {
330                 switch (previous) {
331                     case UNINITIALIZED :
332                         // we are initializing the first point
333                         if (g > 0) {
334                             // initialize as if previous root (i.e. forward one) was an ignored decreasing event
335                             return Transformer.MAX;
336                         } else if (g < 0) {
337                             // initialize as if previous root (i.e. forward one) was a triggered increasing event
338                             return Transformer.MINUS;
339                         } else {
340                             // we are exactly at a root, we don't know if it is an increasing
341                             // or a decreasing event, we remain in uninitialized state
342                             return Transformer.UNINITIALIZED;
343                         }
344                     case PLUS  :
345                         if (g >= 0) {
346                             // we have crossed the zero line on an ignored decreasing event,
347                             // we must change the transformer
348                             return Transformer.MIN;
349                         } else {
350                             // we are still in the same status
351                             return previous;
352                         }
353                     case MINUS :
354                         if (g >= 0) {
355                             // we have crossed the zero line on an ignored decreasing event,
356                             // we must change the transformer
357                             return Transformer.MAX;
358                         } else {
359                             // we are still in the same status
360                             return previous;
361                         }
362                     case MIN   :
363                         if (g <= 0) {
364                             // we have crossed the zero line on a triggered increasing event,
365                             // we must change the transformer
366                             return Transformer.MINUS;
367                         } else {
368                             // we are still in the same status
369                             return previous;
370                         }
371                     case MAX   :
372                         if (g <= 0) {
373                             // we have crossed the zero line on a triggered increasing event,
374                             // we must change the transformer
375                             return Transformer.PLUS;
376                         } else {
377                             // we are still in the same status
378                             return previous;
379                         }
380                     default    :
381                         // this should never happen
382                         throw MathRuntimeException.createInternalError();
383                 }
384             }
385         }
386 
387     };
388 
389     /** Check if triggered events are increasing events.
390      * @return true if triggered events are increasing events
391      */
392     protected abstract boolean isTriggeredOnIncreasing();
393 
394     /** Get next function transformer in the specified direction.
395      * @param previous transformer active on the previous point with respect
396      * to integration direction (may be null if no previous point is known)
397      * @param g current value of the g function
398      * @param forward true if integration goes forward
399      * @return next transformer transformer
400      */
401     protected abstract Transformer selectTransformer(Transformer previous,
402                                                      double g, boolean forward);
403 
404 }