summaryrefslogtreecommitdiff
path: root/src/main/java/org/apache/commons/math3/ode/events/FilterType.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/apache/commons/math3/ode/events/FilterType.java')
-rw-r--r--src/main/java/org/apache/commons/math3/ode/events/FilterType.java400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math3/ode/events/FilterType.java b/src/main/java/org/apache/commons/math3/ode/events/FilterType.java
new file mode 100644
index 0000000..2ac0df8
--- /dev/null
+++ b/src/main/java/org/apache/commons/math3/ode/events/FilterType.java
@@ -0,0 +1,400 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math3.ode.events;
+
+import org.apache.commons.math3.exception.MathInternalError;
+
+/** Enumerate for {@link EventFilter filtering events}.
+ *
+ * @since 3.2
+ */
+
+public enum FilterType {
+
+ /** Constant for triggering only decreasing events.
+ * <p>When this filter is used, the wrapped {@link EventHandler
+ * event handler} {@link EventHandler#eventOccurred(double, double[],
+ * boolean) eventOccurred} method will be called <em>only</em> with
+ * its {@code increasing} argument set to false.</p>
+ */
+ TRIGGER_ONLY_DECREASING_EVENTS {
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean getTriggeredIncreasing() {
+ return false;
+ }
+
+ /** {@inheritDoc}
+ * <p>
+ * states scheduling for computing h(t,y) as an altered version of g(t, y)
+ * <ul>
+ * <li>0 are triggered events for which a zero is produced (here decreasing events)</li>
+ * <li>X are ignored events for which zero is masked (here increasing events)</li>
+ * </ul>
+ * </p>
+ * <pre>
+ * g(t)
+ * ___ ___ ___
+ * / \ / \ / \
+ * / \ / \ / \
+ * / g>0 \ / g>0 \ / g>0 \
+ * / \ / \ / \
+ * ----- X --------- 0 --------- X --------- 0 --------- X --------- 0 ---
+ * / \ / \ / \
+ * / \ g<0 / \ g<0 / \ g<0
+ * / \ / \ / \ /
+ * ___/ \___/ \___/ \___/
+ * </pre>
+ * <pre>
+ * h(t,y)) as an alteration of g(t,y)
+ * ___ ___ ___
+ * \ / \ / \ / \
+ * \ / \ h=+g / \ / \
+ * \ / \ h=min(-s,-g,+g) / \ / \
+ * \_/ \ / \_/ \
+ * ------ ---------- 0 ----------_---------- 0 --------------------- 0 ---
+ * \ / \ / \
+ * h=max(+s,-g,+g) \ / \ / h=max(+s,-g,+g) \
+ * \ / \ / h=-g \ /
+ * \___/ \___/ \___/
+ * </pre>
+ * <p>
+ * As shown by the figure above, several expressions are used to compute h,
+ * depending on the current state:
+ * <ul>
+ * <li>h = max(+s,-g,+g)</li>
+ * <li>h = +g</li>
+ * <li>h = min(-s,-g,+g)</li>
+ * <li>h = -g</li>
+ * </ul>
+ * where s is a tiny positive value: {@link org.apache.commons.math3.util.Precision#SAFE_MIN}.
+ * </p>
+ */
+ @Override
+ protected Transformer selectTransformer(final Transformer previous,
+ final double g, final boolean forward) {
+ if (forward) {
+ switch (previous) {
+ case UNINITIALIZED :
+ // we are initializing the first point
+ if (g > 0) {
+ // initialize as if previous root (i.e. backward one) was an ignored increasing event
+ return Transformer.MAX;
+ } else if (g < 0) {
+ // initialize as if previous root (i.e. backward one) was a triggered decreasing event
+ return Transformer.PLUS;
+ } else {
+ // we are exactly at a root, we don't know if it is an increasing
+ // or a decreasing event, we remain in uninitialized state
+ return Transformer.UNINITIALIZED;
+ }
+ case PLUS :
+ if (g >= 0) {
+ // we have crossed the zero line on an ignored increasing event,
+ // we must change the transformer
+ return Transformer.MIN;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MINUS :
+ if (g >= 0) {
+ // we have crossed the zero line on an ignored increasing event,
+ // we must change the transformer
+ return Transformer.MAX;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MIN :
+ if (g <= 0) {
+ // we have crossed the zero line on a triggered decreasing event,
+ // we must change the transformer
+ return Transformer.MINUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MAX :
+ if (g <= 0) {
+ // we have crossed the zero line on a triggered decreasing event,
+ // we must change the transformer
+ return Transformer.PLUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ default :
+ // this should never happen
+ throw new MathInternalError();
+ }
+ } else {
+ switch (previous) {
+ case UNINITIALIZED :
+ // we are initializing the first point
+ if (g > 0) {
+ // initialize as if previous root (i.e. forward one) was a triggered decreasing event
+ return Transformer.MINUS;
+ } else if (g < 0) {
+ // initialize as if previous root (i.e. forward one) was an ignored increasing event
+ return Transformer.MIN;
+ } else {
+ // we are exactly at a root, we don't know if it is an increasing
+ // or a decreasing event, we remain in uninitialized state
+ return Transformer.UNINITIALIZED;
+ }
+ case PLUS :
+ if (g <= 0) {
+ // we have crossed the zero line on an ignored increasing event,
+ // we must change the transformer
+ return Transformer.MAX;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MINUS :
+ if (g <= 0) {
+ // we have crossed the zero line on an ignored increasing event,
+ // we must change the transformer
+ return Transformer.MIN;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MIN :
+ if (g >= 0) {
+ // we have crossed the zero line on a triggered decreasing event,
+ // we must change the transformer
+ return Transformer.PLUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MAX :
+ if (g >= 0) {
+ // we have crossed the zero line on a triggered decreasing event,
+ // we must change the transformer
+ return Transformer.MINUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ default :
+ // this should never happen
+ throw new MathInternalError();
+ }
+ }
+ }
+
+ },
+
+ /** Constant for triggering only increasing events.
+ * <p>When this filter is used, the wrapped {@link EventHandler
+ * event handler} {@link EventHandler#eventOccurred(double, double[],
+ * boolean) eventOccurred} method will be called <em>only</em> with
+ * its {@code increasing} argument set to true.</p>
+ */
+ TRIGGER_ONLY_INCREASING_EVENTS {
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean getTriggeredIncreasing() {
+ return true;
+ }
+
+ /** {@inheritDoc}
+ * <p>
+ * states scheduling for computing h(t,y) as an altered version of g(t, y)
+ * <ul>
+ * <li>0 are triggered events for which a zero is produced (here increasing events)</li>
+ * <li>X are ignored events for which zero is masked (here decreasing events)</li>
+ * </ul>
+ * </p>
+ * <pre>
+ * g(t)
+ * ___ ___ ___
+ * / \ / \ / \
+ * / \ / \ / \
+ * / g>0 \ / g>0 \ / g>0 \
+ * / \ / \ / \
+ * ----- 0 --------- X --------- 0 --------- X --------- 0 --------- X ---
+ * / \ / \ / \
+ * / \ g<0 / \ g<0 / \ g<0
+ * / \ / \ / \ /
+ * ___/ \___/ \___/ \___/
+ * </pre>
+ * <pre>
+ * h(t,y)) as an alteration of g(t,y)
+ * ___ ___
+ * \ / \ / \
+ * \ h=-g / \ / \ h=-g
+ * \ h=min(-s,-g,+g) / \ / \ h=min(-s,-g,+g)
+ * \ / \_/ \
+ * ------0 ----------_---------- 0 --------------------- 0 --------- _ ---
+ * \ / \ / \ / \
+ * \ / \ / h=max(+s,-g,+g) \ / \
+ * \ / \ / h=+g \ / \ /
+ * \___/ \___/ \___/ \___/
+ * </pre>
+ * <p>
+ * As shown by the figure above, several expressions are used to compute h,
+ * depending on the current state:
+ * <ul>
+ * <li>h = max(+s,-g,+g)</li>
+ * <li>h = +g</li>
+ * <li>h = min(-s,-g,+g)</li>
+ * <li>h = -g</li>
+ * </ul>
+ * where s is a tiny positive value: {@link org.apache.commons.math3.util.Precision#SAFE_MIN}.
+ * </p>
+ */
+ @Override
+ protected Transformer selectTransformer(final Transformer previous,
+ final double g, final boolean forward) {
+ if (forward) {
+ switch (previous) {
+ case UNINITIALIZED :
+ // we are initializing the first point
+ if (g > 0) {
+ // initialize as if previous root (i.e. backward one) was a triggered increasing event
+ return Transformer.PLUS;
+ } else if (g < 0) {
+ // initialize as if previous root (i.e. backward one) was an ignored decreasing event
+ return Transformer.MIN;
+ } else {
+ // we are exactly at a root, we don't know if it is an increasing
+ // or a decreasing event, we remain in uninitialized state
+ return Transformer.UNINITIALIZED;
+ }
+ case PLUS :
+ if (g <= 0) {
+ // we have crossed the zero line on an ignored decreasing event,
+ // we must change the transformer
+ return Transformer.MAX;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MINUS :
+ if (g <= 0) {
+ // we have crossed the zero line on an ignored decreasing event,
+ // we must change the transformer
+ return Transformer.MIN;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MIN :
+ if (g >= 0) {
+ // we have crossed the zero line on a triggered increasing event,
+ // we must change the transformer
+ return Transformer.PLUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MAX :
+ if (g >= 0) {
+ // we have crossed the zero line on a triggered increasing event,
+ // we must change the transformer
+ return Transformer.MINUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ default :
+ // this should never happen
+ throw new MathInternalError();
+ }
+ } else {
+ switch (previous) {
+ case UNINITIALIZED :
+ // we are initializing the first point
+ if (g > 0) {
+ // initialize as if previous root (i.e. forward one) was an ignored decreasing event
+ return Transformer.MAX;
+ } else if (g < 0) {
+ // initialize as if previous root (i.e. forward one) was a triggered increasing event
+ return Transformer.MINUS;
+ } else {
+ // we are exactly at a root, we don't know if it is an increasing
+ // or a decreasing event, we remain in uninitialized state
+ return Transformer.UNINITIALIZED;
+ }
+ case PLUS :
+ if (g >= 0) {
+ // we have crossed the zero line on an ignored decreasing event,
+ // we must change the transformer
+ return Transformer.MIN;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MINUS :
+ if (g >= 0) {
+ // we have crossed the zero line on an ignored decreasing event,
+ // we must change the transformer
+ return Transformer.MAX;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MIN :
+ if (g <= 0) {
+ // we have crossed the zero line on a triggered increasing event,
+ // we must change the transformer
+ return Transformer.MINUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ case MAX :
+ if (g <= 0) {
+ // we have crossed the zero line on a triggered increasing event,
+ // we must change the transformer
+ return Transformer.PLUS;
+ } else {
+ // we are still in the same status
+ return previous;
+ }
+ default :
+ // this should never happen
+ throw new MathInternalError();
+ }
+ }
+ }
+
+ };
+
+ /** Get the increasing status of triggered events.
+ * @return true if triggered events are increasing events
+ */
+ protected abstract boolean getTriggeredIncreasing();
+
+ /** Get next function transformer in the specified direction.
+ * @param previous transformer active on the previous point with respect
+ * to integration direction (may be null if no previous point is known)
+ * @param g current value of the g function
+ * @param forward true if integration goes forward
+ * @return next transformer transformer
+ */
+ protected abstract Transformer selectTransformer(Transformer previous,
+ double g, boolean forward);
+
+}