diff --git a/src/java/org/apache/commons/math/FunctionEvaluationException.java b/src/java/org/apache/commons/math/FunctionEvaluationException.java index fcda39488..ae37ca7a6 100644 --- a/src/java/org/apache/commons/math/FunctionEvaluationException.java +++ b/src/java/org/apache/commons/math/FunctionEvaluationException.java @@ -17,7 +17,7 @@ package org.apache.commons.math; /** - * Exeption thrown when an error occurs evaluating a function. + * Exception thrown when an error occurs evaluating a function. *
* Maintains an argument
property holding the input value that
* caused the function evaluation to fail.
diff --git a/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java b/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java
index 3eb9ddd5d..c5819bbee 100644
--- a/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java
+++ b/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java
@@ -151,11 +151,14 @@ public abstract class AdaptiveStepsizeIntegrator
* function checks (this interval prevents missing sign changes in
* case the integration steps becomes very large)
* @param convergence convergence threshold in the event time search
+ * @param maxIterationCount upper limit of the iteration count in
+ * the event time search
*/
public void addSwitchingFunction(SwitchingFunction function,
double maxCheckInterval,
- double convergence) {
- switchesHandler.add(function, maxCheckInterval, convergence);
+ double convergence,
+ int maxIterationCount) {
+ switchesHandler.add(function, maxCheckInterval, convergence, maxIterationCount);
}
/** Perform some sanity checks on the integration parameters.
diff --git a/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java b/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java
index 91c47d43d..0861dbe95 100644
--- a/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java
+++ b/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java
@@ -58,10 +58,13 @@ public interface FirstOrderIntegrator {
* function checks (this interval prevents missing sign changes in
* case the integration steps becomes very large)
* @param convergence convergence threshold in the event time search
+ * @param maxIterationCount upper limit of the iteration count in
+ * the event time search
*/
public void addSwitchingFunction(SwitchingFunction function,
double maxCheckInterval,
- double convergence);
+ double convergence,
+ int maxIterationCount);
/** Integrate the differential equations up to the given time.
*
This method solves an Initial Value Problem (IVP).
diff --git a/src/java/org/apache/commons/math/ode/GraggBulirschStoerIntegrator.java b/src/java/org/apache/commons/math/ode/GraggBulirschStoerIntegrator.java index 3970202ca..e8d96c801 100644 --- a/src/java/org/apache/commons/math/ode/GraggBulirschStoerIntegrator.java +++ b/src/java/org/apache/commons/math/ode/GraggBulirschStoerIntegrator.java @@ -291,11 +291,14 @@ public class GraggBulirschStoerIntegrator * function checks (this interval prevents missing sign changes in * case the integration steps becomes very large) * @param convergence convergence threshold in the event time search + * @param maxIterationCount upper limit of the iteration count in + * the event time search */ public void addSwitchingFunction(SwitchingFunction function, double maxCheckInterval, - double convergence) { - super.addSwitchingFunction(function, maxCheckInterval, convergence); + double convergence, + int maxIterationCount) { + super.addSwitchingFunction(function, maxCheckInterval, convergence, maxIterationCount); denseOutput = (handler.requiresDenseOutput() || (! switchesHandler.isEmpty())); diff --git a/src/java/org/apache/commons/math/ode/IntegratorException.java b/src/java/org/apache/commons/math/ode/IntegratorException.java index 2296e6679..93805eccb 100644 --- a/src/java/org/apache/commons/math/ode/IntegratorException.java +++ b/src/java/org/apache/commons/math/ode/IntegratorException.java @@ -36,6 +36,14 @@ public class IntegratorException super(specifier, parts); } - private static final long serialVersionUID = -1390328069787882608L; + /** + * Create an exception with a given root cause. + * @param cause the exception or error that caused this exception to be thrown + */ + public IntegratorException(Throwable cause) { + super(cause); + } + + private static final long serialVersionUID = -1215318282266670558L; } diff --git a/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java b/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java index d6206c8e2..891ab310f 100644 --- a/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java +++ b/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java @@ -95,11 +95,14 @@ public abstract class RungeKuttaIntegrator * function checks (this interval prevents missing sign changes in * case the integration steps becomes very large) * @param convergence convergence threshold in the event time search + * @param maxIterationCount upper limit of the iteration count in + * the event time search */ public void addSwitchingFunction(SwitchingFunction function, double maxCheckInterval, - double convergence) { - switchesHandler.add(function, maxCheckInterval, convergence); + double convergence, + int maxIterationCount) { + switchesHandler.add(function, maxCheckInterval, convergence, maxIterationCount); } /** Perform some sanity checks on the integration parameters. diff --git a/src/java/org/apache/commons/math/ode/SwitchState.java b/src/java/org/apache/commons/math/ode/SwitchState.java index 51a512c10..62f1ecea7 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 = 3256541562455482289L; + private static final long serialVersionUID = -7307007422156119622L; /** Switching function. */ private SwitchingFunction function; @@ -53,6 +53,9 @@ class SwitchState implements Serializable { /** Convergence threshold for event localisation. */ private double convergence; + /** Upper limit in the iteration count for event localisation. */ + private int maxIterationCount; + /** Time at the beginning of the step. */ private double t0; @@ -85,12 +88,15 @@ class SwitchState implements Serializable { * function checks (this interval prevents missing sign changes in * case the integration steps becomes very large) * @param convergence convergence threshold in the event time search + * @param maxIterationCount upper limit of the iteration count in + * the event time search */ - public SwitchState(SwitchingFunction function, - double maxCheckInterval, double convergence) { - this.function = function; - this.maxCheckInterval = maxCheckInterval; - this.convergence = Math.abs(convergence); + public SwitchState(SwitchingFunction function, double maxCheckInterval, + double convergence, int maxIterationCount) { + this.function = function; + this.maxCheckInterval = maxCheckInterval; + this.convergence = Math.abs(convergence); + this.maxIterationCount = maxIterationCount; // some dummy values ... t0 = Double.NaN; @@ -109,8 +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 + * value cannot be evaluated at the beginning of the step */ - public void reinitializeBegin(double t0, double[] y0) { + public void reinitializeBegin(double t0, double[] y0) + throws FunctionEvaluationException { this.t0 = t0; g0 = function.g(t0, y0); g0Positive = (g0 >= 0); @@ -121,8 +130,14 @@ class SwitchState implements Serializable { * @return true if the switching function triggers an event before * the end of the proposed step (this implies the step should be * rejected) + * @exception DerivativeException if the interpolator fails to + * compute the function somewhere within the step + * @exception FunctionEvaluationException if the switching function + * cannot be evaluated + * @exception ConvergenceException if an event cannot be located */ - public boolean evaluateStep(final StepInterpolator interpolator) { + public boolean evaluateStep(final StepInterpolator interpolator) + throws DerivativeException, FunctionEvaluationException, ConvergenceException { try { @@ -147,36 +162,32 @@ class SwitchState implements Serializable { // variation direction, with respect to the integration direction increasing = (gb >= ga); - try { - UnivariateRealSolver solver = new BrentSolver(new UnivariateRealFunction() { - public double value(double t) throws FunctionEvaluationException { - try { - interpolator.setInterpolatedTime(t); - return function.g(t, interpolator.getInterpolatedState()); - } catch (DerivativeException e) { - throw new FunctionEvaluationException(t, e); - } + UnivariateRealSolver solver = new BrentSolver(new UnivariateRealFunction() { + public double value(double t) throws FunctionEvaluationException { + try { + interpolator.setInterpolatedTime(t); + return function.g(t, interpolator.getInterpolatedState()); + } catch (DerivativeException e) { + throw new FunctionEvaluationException(t, e); } - }); - solver.setAbsoluteAccuracy(convergence); - solver.setMaximalIterationCount(1000); - double root = solver.solve(ta, tb); - if (Double.isNaN(previousEventTime) || (Math.abs(previousEventTime - root) > convergence)) { - pendingEventTime = root; - if (pendingEvent && (Math.abs(t1 - pendingEventTime) <= convergence)) { - // we were already waiting for this event which was - // found during a previous call for a step that was - // rejected, this step must now be accepted since it - // properly ends exactly at the event occurrence - return false; - } - // either we were not waiting for the event or it has - // moved in such a way the step cannot be accepted - pendingEvent = true; - return true; } - } catch (ConvergenceException ce) { - throw new RuntimeException("internal error"); + }); + solver.setAbsoluteAccuracy(convergence); + solver.setMaximalIterationCount(maxIterationCount); + double root = solver.solve(ta, tb); + if (Double.isNaN(previousEventTime) || (Math.abs(previousEventTime - root) > convergence)) { + pendingEventTime = root; + if (pendingEvent && (Math.abs(t1 - pendingEventTime) <= convergence)) { + // we were already waiting for this event which was + // found during a previous call for a step that was + // rejected, this step must now be accepted since it + // properly ends exactly at the event occurrence + return false; + } + // either we were not waiting for the event or it has + // moved in such a way the step cannot be accepted + pendingEvent = true; + return true; } } else { @@ -192,10 +203,12 @@ class SwitchState implements Serializable { pendingEventTime = Double.NaN; return false; - } catch (DerivativeException e) { - throw new RuntimeException("unexpected exception: " + e.getMessage()); } catch (FunctionEvaluationException e) { - throw new RuntimeException("unexpected exception: " + e.getMessage()); + Throwable cause = e.getCause(); + if ((cause != null) && (cause instanceof DerivativeException)) { + throw (DerivativeException) cause; + } + throw e; } } @@ -214,8 +227,11 @@ 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 + * function cannot be evaluated */ - public void stepAccepted(double t, double[] y) { + public void stepAccepted(double t, double[] y) + throws FunctionEvaluationException { t0 = t; g0 = function.g(t, y); diff --git a/src/java/org/apache/commons/math/ode/SwitchingFunction.java b/src/java/org/apache/commons/math/ode/SwitchingFunction.java index 634f95330..ad6a0a40b 100644 --- a/src/java/org/apache/commons/math/ode/SwitchingFunction.java +++ b/src/java/org/apache/commons/math/ode/SwitchingFunction.java @@ -19,6 +19,8 @@ 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 @@ -91,8 +93,10 @@ 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 */ - public double g(double t, double[] y); + public double g(double t, double[] y) throws FunctionEvaluationException; /** Handle an event and choose what to do next. diff --git a/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java b/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java index fe558470a..9cc6ce796 100644 --- a/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java +++ b/src/java/org/apache/commons/math/ode/SwitchingFunctionsHandler.java @@ -17,6 +17,8 @@ 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 java.util.ArrayList; @@ -48,10 +50,13 @@ public class SwitchingFunctionsHandler { * function checks (this interval prevents missing sign changes in * case the integration steps becomes very large) * @param convergence convergence threshold in the event time search + * @param maxIterationCount upper limit of the iteration count in + * the event time search */ - public void add(SwitchingFunction function, - double maxCheckInterval, double convergence) { - functions.add(new SwitchState(function, maxCheckInterval, convergence)); + public void add(SwitchingFunction function, double maxCheckInterval, + double convergence, int maxIterationCount) { + functions.add(new SwitchState(function, maxCheckInterval, + convergence, maxIterationCount)); } /** Check if the handler does not have any condition. @@ -67,8 +72,12 @@ public class SwitchingFunctionsHandler { * @return true if at least one switching function triggers an event * before the end of the proposed step (this implies the step should * be rejected) + * @exception DerivativeException if the interpolator fails to + * compute the function somewhere within the step + * @exception IntegratorException if an event cannot be located */ - public boolean evaluateStep(StepInterpolator interpolator) { + public boolean evaluateStep(StepInterpolator interpolator) + throws DerivativeException, IntegratorException { try { @@ -118,8 +127,10 @@ public class SwitchingFunctionsHandler { return first != null; - } catch (DerivativeException e) { - throw new RuntimeException("unexpected exception: " + e.getMessage()); + } catch (FunctionEvaluationException fee) { + throw new IntegratorException(fee); + } catch (ConvergenceException ce) { + throw new IntegratorException(ce); } } @@ -140,10 +151,17 @@ public class SwitchingFunctionsHandler { * end of the step * @param y array containing the current value of the state vector * at the end of the step + * @exception IntegratorException if the value of one of the + * switching functions cannot be evaluated */ - public void stepAccepted(double t, double[] y) { - for (Iterator iter = functions.iterator(); iter.hasNext();) { - ((SwitchState) iter.next()).stepAccepted(t, y); + public void stepAccepted(double t, double[] y) + throws IntegratorException { + try { + for (Iterator iter = functions.iterator(); iter.hasNext();) { + ((SwitchState) iter.next()).stepAccepted(t, y); + } + } catch (FunctionEvaluationException fee) { + throw new IntegratorException(fee); } } diff --git a/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java b/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java index 1660fc803..27e7e57de 100644 --- a/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/ClassicalRungeKuttaIntegratorTest.java @@ -86,7 +86,7 @@ public class ClassicalRungeKuttaIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-6 * step); + Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); diff --git a/src/test/org/apache/commons/math/ode/DormandPrince54IntegratorTest.java b/src/test/org/apache/commons/math/ode/DormandPrince54IntegratorTest.java index 1ea693b52..5c3ad294a 100644 --- a/src/test/org/apache/commons/math/ode/DormandPrince54IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/DormandPrince54IntegratorTest.java @@ -189,7 +189,7 @@ public class DormandPrince54IntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-8 * maxStep); + Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), diff --git a/src/test/org/apache/commons/math/ode/DormandPrince853IntegratorTest.java b/src/test/org/apache/commons/math/ode/DormandPrince853IntegratorTest.java index ba41992bc..b5aaa297a 100644 --- a/src/test/org/apache/commons/math/ode/DormandPrince853IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/DormandPrince853IntegratorTest.java @@ -142,7 +142,7 @@ public class DormandPrince853IntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-8 * maxStep); + Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), @@ -227,7 +227,7 @@ public class DormandPrince853IntegratorTest final StepProblem stepProblem = new StepProblem(0.0, 1.0, 2.0); FirstOrderIntegrator integ = new DormandPrince853Integrator(0.1, 10, 1.0e-12, 0.0); - integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12); + integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12, 1000); double[] y = { Double.NaN }; integ.integrate(stepProblem, 0.0, new double[] { 0.0 }, 10.0, y); assertEquals(8.0, y[0], 1.0e-12); diff --git a/src/test/org/apache/commons/math/ode/EulerIntegratorTest.java b/src/test/org/apache/commons/math/ode/EulerIntegratorTest.java index 66404d9e0..55fb11337 100644 --- a/src/test/org/apache/commons/math/ode/EulerIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/EulerIntegratorTest.java @@ -64,7 +64,7 @@ public class EulerIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-6 * step); + Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), diff --git a/src/test/org/apache/commons/math/ode/GillIntegratorTest.java b/src/test/org/apache/commons/math/ode/GillIntegratorTest.java index 58815624f..bc9f1c3ef 100644 --- a/src/test/org/apache/commons/math/ode/GillIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/GillIntegratorTest.java @@ -66,7 +66,7 @@ public class GillIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-6 * step); + Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); @@ -138,7 +138,7 @@ public class GillIntegratorTest throws DerivativeException, IntegratorException { final StepProblem stepProblem = new StepProblem(0.0, 1.0, 2.0); FirstOrderIntegrator integ = new GillIntegrator(0.3); - integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12); + integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12, 1000); double[] y = { Double.NaN }; integ.integrate(stepProblem, 0.0, new double[] { 0.0 }, 10.0, y); assertEquals(8.0, y[0], 1.0e-12); diff --git a/src/test/org/apache/commons/math/ode/GraggBulirschStoerIntegratorTest.java b/src/test/org/apache/commons/math/ode/GraggBulirschStoerIntegratorTest.java index 71f94f0dc..7d6a089ba 100644 --- a/src/test/org/apache/commons/math/ode/GraggBulirschStoerIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/GraggBulirschStoerIntegratorTest.java @@ -182,7 +182,7 @@ public class GraggBulirschStoerIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-8 * maxStep); + Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), @@ -238,7 +238,7 @@ public class GraggBulirschStoerIntegratorTest final StepProblem stepProblem = new StepProblem(0.0, 1.0, 2.0); FirstOrderIntegrator integ = new GraggBulirschStoerIntegrator(0.1, 10, 1.0e-12, 0.0); - integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12); + integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12, 1000); double[] y = { Double.NaN }; integ.integrate(stepProblem, 0.0, new double[] { 0.0 }, 10.0, y); assertEquals(8.0, y[0], 1.0e-12); diff --git a/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java b/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java index fc043169e..d36310033 100644 --- a/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/HighamHall54IntegratorTest.java @@ -17,6 +17,8 @@ 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; @@ -149,7 +151,7 @@ public class HighamHall54IntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-8 * maxStep); + Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), @@ -161,6 +163,94 @@ public class HighamHall54IntegratorTest } + public void testSwitchingFunctionsError() + throws DerivativeException, IntegratorException { + + final TestProblem1 pb = new TestProblem1(); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance; + + FirstOrderIntegrator integ = + new HighamHall54Integrator(minStep, maxStep, + scalAbsoluteTolerance, scalRelativeTolerance); + TestProblemHandler handler = new TestProblemHandler(pb, integ); + integ.setStepHandler(handler); + + integ.addSwitchingFunction(new SwitchingFunction() { + public int eventOccurred(double t, double[] y) { + return SwitchingFunction.CONTINUE; + } + public double g(double t, double[] y) throws FunctionEvaluationException { + double middle = (pb.getInitialTime() + pb.getFinalTime()) / 2; + double offset = t - middle; + if (offset > 0) { + throw new FunctionEvaluationException(t); + } + return offset; + } + public void resetState(double t, double[] y) { + } + private static final long serialVersionUID = 935652725339916361L; + }, Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000); + + try { + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + fail("an exception should have been thrown"); + } catch (IntegratorException ie) { + // expected behavior + } catch (Exception e) { + fail("wrong exception type caught"); + } + + } + + public void testSwitchingFunctionsNoConvergence() + throws DerivativeException, IntegratorException { + + final TestProblem1 pb = new TestProblem1(); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance; + + FirstOrderIntegrator integ = + new HighamHall54Integrator(minStep, maxStep, + scalAbsoluteTolerance, scalRelativeTolerance); + TestProblemHandler handler = new TestProblemHandler(pb, integ); + integ.setStepHandler(handler); + + integ.addSwitchingFunction(new SwitchingFunction() { + public int eventOccurred(double t, double[] y) { + return SwitchingFunction.CONTINUE; + } + public double g(double t, double[] y) { + double middle = (pb.getInitialTime() + pb.getFinalTime()) / 2; + double offset = t - middle; + return (offset > 0) ? (offset + 0.5) : (offset - 0.5); + } + public void resetState(double t, double[] y) { + } + private static final long serialVersionUID = 935652725339916361L; + }, Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 3); + + try { + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + fail("an exception should have been thrown"); + } catch (IntegratorException ie) { + assertTrue(ie.getCause() != null); + assertTrue(ie.getCause() instanceof ConvergenceException); + } catch (Exception e) { + fail("wrong exception type caught"); + } + +} + public void testSanityChecks() { try { final TestProblem3 pb = new TestProblem3(0.9); diff --git a/src/test/org/apache/commons/math/ode/MidpointIntegratorTest.java b/src/test/org/apache/commons/math/ode/MidpointIntegratorTest.java index 45f36d39e..f0c025dca 100644 --- a/src/test/org/apache/commons/math/ode/MidpointIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/MidpointIntegratorTest.java @@ -63,7 +63,7 @@ public class MidpointIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-6 * step); + Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), diff --git a/src/test/org/apache/commons/math/ode/ThreeEighthesIntegratorTest.java b/src/test/org/apache/commons/math/ode/ThreeEighthesIntegratorTest.java index 4b65cab68..1796da360 100644 --- a/src/test/org/apache/commons/math/ode/ThreeEighthesIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/ThreeEighthesIntegratorTest.java @@ -66,7 +66,7 @@ public class ThreeEighthesIntegratorTest SwitchingFunction[] functions = pb.getSwitchingFunctions(); for (int l = 0; l < functions.length; ++l) { integ.addSwitchingFunction(functions[l], - Double.POSITIVE_INFINITY, 1.0e-6 * step); + Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]);