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