diff --git a/src/java/org/apache/commons/math/ode/SwitchException.java b/src/java/org/apache/commons/math/ode/SwitchException.java new file mode 100644 index 000000000..9a8fa1c87 --- /dev/null +++ b/src/java/org/apache/commons/math/ode/SwitchException.java @@ -0,0 +1,50 @@ +/* + * 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.math.ode; + +import org.apache.commons.math.MathException; + +/** + * This exception is made available to users to report + * the error conditions that are triggered by {@link SwitchingFunction} + * @version $Revision: 620312 $ $Date: 2008-02-10 20:28:59 +0100 (dim., 10 févr. 2008) $ + * @since 2.0 + */ +public class SwitchException extends MathException { + + /** Serialization UID. */ + private static final long serialVersionUID = -3662133702316614545L; + + /** Simple constructor. + * Build an exception by translating and formating a message + * @param specifier format specifier (to be translated) + * @param parts to insert in the format (no translation) + */ + public SwitchException(String specifier, Object[] parts) { + super(specifier, parts); + } + + /** + * Create an exception with a given root cause. + * @param cause the exception or error that caused this exception to be thrown + */ + public SwitchException(Throwable cause) { + super(cause); + } + +} diff --git a/src/java/org/apache/commons/math/ode/SwitchState.java b/src/java/org/apache/commons/math/ode/SwitchState.java index d729d365d..19197c2e4 100644 --- a/src/java/org/apache/commons/math/ode/SwitchState.java +++ b/src/java/org/apache/commons/math/ode/SwitchState.java @@ -42,7 +42,7 @@ import org.apache.commons.math.analysis.UnivariateRealSolver; class SwitchState implements Serializable { /** Serializable version identifier. */ - private static final long serialVersionUID = -7307007422156119622L; + private static final long serialVersionUID = -7307007422156119622L; /** Switching function. */ private SwitchingFunction function; @@ -50,10 +50,10 @@ class SwitchState implements Serializable { /** Maximal time interval between switching function checks. */ private double maxCheckInterval; - /** Convergence threshold for event localisation. */ + /** Convergence threshold for event localization. */ private double convergence; - /** Upper limit in the iteration count for event localisation. */ + /** Upper limit in the iteration count for event localization. */ private int maxIterationCount; /** Time at the beginning of the step. */ @@ -115,11 +115,11 @@ class SwitchState implements Serializable { * beginning of the step * @param y0 array containing the current value of the state vector * at the beginning of the step - * @exception FunctionEvaluationException if the switching function + * @exception SwitchException if the switching function * value cannot be evaluated at the beginning of the step */ public void reinitializeBegin(double t0, double[] y0) - throws FunctionEvaluationException { + throws SwitchException { this.t0 = t0; g0 = function.g(t0, y0); g0Positive = (g0 >= 0); @@ -132,12 +132,12 @@ class SwitchState implements Serializable { * rejected) * @exception DerivativeException if the interpolator fails to * compute the function somewhere within the step - * @exception FunctionEvaluationException if the switching function + * @exception SwitchException if the switching function * cannot be evaluated * @exception ConvergenceException if an event cannot be located */ public boolean evaluateStep(final StepInterpolator interpolator) - throws DerivativeException, FunctionEvaluationException, ConvergenceException { + throws DerivativeException, SwitchException, ConvergenceException { try { @@ -169,6 +169,8 @@ class SwitchState implements Serializable { return function.g(t, interpolator.getInterpolatedState()); } catch (DerivativeException e) { throw new FunctionEvaluationException(t, e); + } catch (SwitchException e) { + throw new FunctionEvaluationException(t, e); } } }); @@ -205,10 +207,12 @@ class SwitchState implements Serializable { } catch (FunctionEvaluationException e) { Throwable cause = e.getCause(); - if ((cause != null) && (cause instanceof DerivativeException)) { - throw (DerivativeException) cause; - } - throw e; + if ((cause != null) && (cause instanceof DerivativeException)) { + throw (DerivativeException) cause; + } else if ((cause != null) && (cause instanceof SwitchException)) { + throw (SwitchException) cause; + } + throw new SwitchException(e); } } @@ -227,11 +231,10 @@ class SwitchState implements Serializable { * end of the step * @param y array containing the current value of the state vector * at the end of the step - * @exception FunctionEvaluationException if the value of the switching + * @exception SwitchException if the value of the switching * function cannot be evaluated */ - public void stepAccepted(double t, double[] y) - throws FunctionEvaluationException { + public void stepAccepted(double t, double[] y) throws SwitchException { t0 = t; g0 = function.g(t, y); @@ -261,8 +264,10 @@ class SwitchState implements Serializable { * @param y array were to put the desired state vector at the beginning * of the next step * @return true if the integrator should reset the derivatives too + * @exception SwitchException if the state cannot be reseted by the switching + * function */ - public boolean reset(double t, double[] y) { + public boolean reset(double t, double[] y) throws SwitchException { if (! pendingEvent) { return false; diff --git a/src/java/org/apache/commons/math/ode/SwitchingFunction.java b/src/java/org/apache/commons/math/ode/SwitchingFunction.java index 06ef10b9b..8718ba0c1 100644 --- a/src/java/org/apache/commons/math/ode/SwitchingFunction.java +++ b/src/java/org/apache/commons/math/ode/SwitchingFunction.java @@ -19,8 +19,6 @@ package org.apache.commons.math.ode; import java.io.Serializable; -import org.apache.commons.math.FunctionEvaluationException; - /** This interface represents a switching function. * *

A switching function allows to handle discrete events in @@ -93,10 +91,9 @@ public interface SwitchingFunction extends Serializable { * @param t current value of the independent time variable * @param y array containing the current value of the state vector * @return value of the g function - * @exception FunctionEvaluationException if the value of the function - * cannot be evaluated + * @exception SwitchException if the switching function cannot be evaluated */ - public double g(double t, double[] y) throws FunctionEvaluationException; + public double g(double t, double[] y) throws SwitchException; /** Handle an event and choose what to do next. @@ -131,8 +128,9 @@ public interface SwitchingFunction extends Serializable { * @return indication of what the integrator should do next, this * value must be one of {@link #STOP}, {@link #RESET_STATE}, * {@link #RESET_DERIVATIVES} or {@link #CONTINUE} + * @exception SwitchException if the event occurrence triggers an error */ - public int eventOccurred(double t, double[] y); + public int eventOccurred(double t, double[] y) throws SwitchException; /** Reset the state prior to continue the integration. @@ -148,7 +146,8 @@ public interface SwitchingFunction extends Serializable { * @param t current value of the independent time variable * @param y array containing the current value of the state vector * the new state should be put in the same array + * @exception SwitchException if the state cannot be reseted */ - public void resetState(double t, double[] y); + public void resetState(double t, double[] y) throws SwitchException; } diff --git a/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java b/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java index 9a89788b1..fc37f680a 100644 --- a/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java +++ b/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java @@ -17,15 +17,14 @@ package org.apache.commons.math.ode; -import org.apache.commons.math.ConvergenceException; -import org.apache.commons.math.FunctionEvaluationException; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.apache.commons.math.ConvergenceException; + /** This class handles several {@link SwitchingFunction switching * functions} during integration. * @@ -147,8 +146,8 @@ public class SwitchingFunctionsHandler { return first != null; - } catch (FunctionEvaluationException fee) { - throw new IntegratorException(fee); + } catch (SwitchException se) { + throw new IntegratorException(se); } catch (ConvergenceException ce) { throw new IntegratorException(ce); } @@ -180,8 +179,8 @@ public class SwitchingFunctionsHandler { for (Iterator iter = functions.iterator(); iter.hasNext();) { ((SwitchState) iter.next()).stepAccepted(t, y); } - } catch (FunctionEvaluationException fee) { - throw new IntegratorException(fee); + } catch (SwitchException se) { + throw new IntegratorException(se); } } @@ -204,15 +203,21 @@ public class SwitchingFunctionsHandler { * @param y array were to put the desired state vector at the beginning * of the next step * @return true if the integrator should reset the derivatives too + * @exception IntegratorException if one of the switching functions + * that should reset the state fails to do it */ - public boolean reset(double t, double[] y) { - boolean resetDerivatives = false; - for (Iterator iter = functions.iterator(); iter.hasNext();) { - if (((SwitchState) iter.next()).reset(t, y)) { - resetDerivatives = true; + public boolean reset(double t, double[] y) throws IntegratorException { + try { + boolean resetDerivatives = false; + for (Iterator iter = functions.iterator(); iter.hasNext();) { + if (((SwitchState) iter.next()).reset(t, y)) { + resetDerivatives = true; + } + } + return resetDerivatives; + } catch (SwitchException se) { + throw new IntegratorException(se); } - } - return resetDerivatives; } /** Switching functions. */ diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index 6b6af8674..efb4aa012 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -35,11 +35,16 @@ The type attribute can be add,update,fix,remove. - -Commons Math Release Notes + Commons Math Release Notes + + Switching functions can now throw dedicated SwitchException from all their + method. At upper call level, the various ODE integrators handle these new + exceptions and wrap them into IntegratorException instances, hence the + integrators methods signature did not change. + Added the getSwitchingFunctions and clearSwitchingFunctions to the FirstOrderIntegrator interface and all its implementations diff --git a/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java b/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java index e48eeda20..be201b967 100644 --- a/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java @@ -17,17 +17,11 @@ package org.apache.commons.math.ode; -import org.apache.commons.math.ConvergenceException; -import org.apache.commons.math.FunctionEvaluationException; -import org.apache.commons.math.ode.DerivativeException; -import org.apache.commons.math.ode.FirstOrderIntegrator; -import org.apache.commons.math.ode.HighamHall54Integrator; -import org.apache.commons.math.ode.IntegratorException; -import org.apache.commons.math.ode.StepHandler; -import org.apache.commons.math.ode.StepInterpolator; -import org.apache.commons.math.ode.SwitchingFunction; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; -import junit.framework.*; +import org.apache.commons.math.ConvergenceException; public class HighamHall54IntegratorTest extends TestCase { @@ -185,11 +179,12 @@ public class HighamHall54IntegratorTest public int eventOccurred(double t, double[] y) { return SwitchingFunction.CONTINUE; } - public double g(double t, double[] y) throws FunctionEvaluationException { + public double g(double t, double[] y) throws SwitchException { double middle = (pb.getInitialTime() + pb.getFinalTime()) / 2; double offset = t - middle; if (offset > 0) { - throw new FunctionEvaluationException(t); + throw new SwitchException("Evaluation failed for argument = {0}", + new Object[] { new Double(t) }); } return offset; }