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    *      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.math4.legacy.ode.events;
19  
20  import org.apache.commons.math4.legacy.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
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.numbers.core.Precision#SAFE_MIN}.
87           * </p>
88           */
89          @Override
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     /** Constant for triggering only increasing events.
207      * <p>When this filter is used, the wrapped {@link EventHandler
208      * event handler} {@link EventHandler#eventOccurred(double, double[],
209      * boolean) eventOccurred} method will be called <em>only</em> with
210      * its {@code increasing} argument set to true.</p>
211      */
212     TRIGGER_ONLY_INCREASING_EVENTS {
213 
214         /**  {@inheritDoc} */
215         @Override
216         protected boolean getTriggeredIncreasing() {
217             return true;
218         }
219 
220         /** {@inheritDoc}
221          * <p>
222          * states scheduling for computing h(t,y) as an altered version of g(t, y)
223          * <ul>
224          * <li>0 are triggered events for which a zero is produced (here increasing events)</li>
225          * <li>X are ignored events for which zero is masked (here decreasing events)</li>
226          * </ul>
227          * </p>
228          * <pre>
229          *  g(t)
230          *             ___                     ___                     ___
231          *            /   \                   /   \                   /   \
232          *           /     \                 /     \                 /     \
233          *          /  g>0  \               /  g>0  \               /  g>0  \
234          *         /         \             /         \             /         \
235          *  ----- 0 --------- X --------- 0 --------- X --------- 0 --------- X ---
236          *       /             \         /             \         /             \
237          *      /               \ g<0   /               \  g<0  /               \ g<0
238          *     /                 \     /                 \     /                 \     /
239          * ___/                   \___/                   \___/                   \___/
240          * </pre>
241          * <pre>
242          *  h(t,y)) as an alteration of g(t,y)
243          *                                     ___         ___
244          *    \                               /   \       /   \
245          *     \ h=-g                        /     \     /     \ h=-g
246          *      \      h=min(-s,-g,+g)      /       \   /       \      h=min(-s,-g,+g)
247          *       \                         /         \_/         \
248          *  ------0 ----------_---------- 0 --------------------- 0 --------- _ ---
249          *         \         / \         /                         \         / \
250          *          \       /   \       /       h=max(+s,-g,+g)     \       /   \
251          *           \     /     \     / h=+g                        \     /     \     /
252          *            \___/       \___/                               \___/       \___/
253          * </pre>
254          * <p>
255          * As shown by the figure above, several expressions are used to compute h,
256          * depending on the current state:
257          * <ul>
258          *   <li>h = max(+s,-g,+g)</li>
259          *   <li>h = +g</li>
260          *   <li>h = min(-s,-g,+g)</li>
261          *   <li>h = -g</li>
262          * </ul>
263          * where s is a tiny positive value: {@link org.apache.commons.numbers.core.Precision#SAFE_MIN}.
264          * </p>
265          */
266         @Override
267         protected  Transformer selectTransformer(final Transformer previous,
268                                                  final double g, final boolean forward) {
269             if (forward) {
270                 switch (previous) {
271                     case UNINITIALIZED :
272                         // we are initializing the first point
273                         if (g > 0) {
274                             // initialize as if previous root (i.e. backward one) was a triggered increasing event
275                             return Transformer.PLUS;
276                         } else if (g < 0) {
277                             // initialize as if previous root (i.e. backward one) was an ignored decreasing event
278                             return Transformer.MIN;
279                         } else {
280                             // we are exactly at a root, we don't know if it is an increasing
281                             // or a decreasing event, we remain in uninitialized state
282                             return Transformer.UNINITIALIZED;
283                         }
284                     case PLUS  :
285                         if (g <= 0) {
286                             // we have crossed the zero line on an ignored decreasing event,
287                             // we must change the transformer
288                             return Transformer.MAX;
289                         } else {
290                             // we are still in the same status
291                             return previous;
292                         }
293                     case MINUS :
294                         if (g <= 0) {
295                             // we have crossed the zero line on an ignored decreasing event,
296                             // we must change the transformer
297                             return Transformer.MIN;
298                         } else {
299                             // we are still in the same status
300                             return previous;
301                         }
302                     case MIN   :
303                         if (g >= 0) {
304                             // we have crossed the zero line on a triggered increasing event,
305                             // we must change the transformer
306                             return Transformer.PLUS;
307                         } else {
308                             // we are still in the same status
309                             return previous;
310                         }
311                     case MAX   :
312                         if (g >= 0) {
313                             // we have crossed the zero line on a triggered increasing event,
314                             // we must change the transformer
315                             return Transformer.MINUS;
316                         } else {
317                             // we are still in the same status
318                             return previous;
319                         }
320                     default    :
321                         // this should never happen
322                         throw new MathInternalError();
323                 }
324             } else {
325                 switch (previous) {
326                     case UNINITIALIZED :
327                         // we are initializing the first point
328                         if (g > 0) {
329                             // initialize as if previous root (i.e. forward one) was an ignored decreasing event
330                             return Transformer.MAX;
331                         } else if (g < 0) {
332                             // initialize as if previous root (i.e. forward one) was a triggered increasing event
333                             return Transformer.MINUS;
334                         } else {
335                             // we are exactly at a root, we don't know if it is an increasing
336                             // or a decreasing event, we remain in uninitialized state
337                             return Transformer.UNINITIALIZED;
338                         }
339                     case PLUS  :
340                         if (g >= 0) {
341                             // we have crossed the zero line on an ignored decreasing event,
342                             // we must change the transformer
343                             return Transformer.MIN;
344                         } else {
345                             // we are still in the same status
346                             return previous;
347                         }
348                     case MINUS :
349                         if (g >= 0) {
350                             // we have crossed the zero line on an ignored decreasing event,
351                             // we must change the transformer
352                             return Transformer.MAX;
353                         } else {
354                             // we are still in the same status
355                             return previous;
356                         }
357                     case MIN   :
358                         if (g <= 0) {
359                             // we have crossed the zero line on a triggered increasing event,
360                             // we must change the transformer
361                             return Transformer.MINUS;
362                         } else {
363                             // we are still in the same status
364                             return previous;
365                         }
366                     case MAX   :
367                         if (g <= 0) {
368                             // we have crossed the zero line on a triggered increasing event,
369                             // we must change the transformer
370                             return Transformer.PLUS;
371                         } else {
372                             // we are still in the same status
373                             return previous;
374                         }
375                     default    :
376                         // this should never happen
377                         throw new MathInternalError();
378                 }
379             }
380         }
381     };
382 
383     /** Get the increasing status of triggered events.
384      * @return true if triggered events are increasing events
385      */
386     protected abstract boolean getTriggeredIncreasing();
387 
388     /** Get next function transformer in the specified direction.
389      * @param previous transformer active on the previous point with respect
390      * to integration direction (may be null if no previous point is known)
391      * @param g current value of the g function
392      * @param forward true if integration goes forward
393      * @return next transformer transformer
394      */
395     protected abstract Transformer selectTransformer(Transformer previous,
396                                                      double g, boolean forward);
397 }