added a way to handle errors in user-defined switching functions

previously, only the function evaluation could trigger errors,
not the other functions of the interface

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@651514 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2008-04-25 07:25:58 +00:00
parent de621a4151
commit 03b9e6771e
6 changed files with 109 additions and 50 deletions

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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.
*
* <p>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 <i>time</i> 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 <i>time</i> 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;
}

View File

@ -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. */

View File

@ -35,11 +35,16 @@ The <action> type attribute can be add,update,fix,remove.
<document>
<properties>
<title>
Commons Math Release Notes</title>
<title>Commons Math Release Notes</title>
</properties>
<body>
<release version="2.0" date="TBD" description="TBD">
<action dev="luc" type="add" >
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.
</action>
<action dev="luc" type="add" issue="MATH-202">
Added the getSwitchingFunctions and clearSwitchingFunctions to the
FirstOrderIntegrator interface and all its implementations

View File

@ -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;
}