diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/AdaptiveStepsizeIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/AdaptiveStepsizeIntegrator.java index 45f4f02e4..54eb12476 100644 --- a/src/main/java/org/apache/commons/math/ode/nonstiff/AdaptiveStepsizeIntegrator.java +++ b/src/main/java/org/apache/commons/math/ode/nonstiff/AdaptiveStepsizeIntegrator.java @@ -66,16 +66,16 @@ public abstract class AdaptiveStepsizeIntegrator extends AbstractIntegrator { /** Allowed absolute scalar error. */ - protected final double scalAbsoluteTolerance; + protected double scalAbsoluteTolerance; /** Allowed relative scalar error. */ - protected final double scalRelativeTolerance; + protected double scalRelativeTolerance; /** Allowed absolute vectorial error. */ - protected final double[] vecAbsoluteTolerance; + protected double[] vecAbsoluteTolerance; /** Allowed relative vectorial error. */ - protected final double[] vecRelativeTolerance; + protected double[] vecRelativeTolerance; /** Main set dimension. */ protected int mainSetDimension; @@ -84,10 +84,10 @@ public abstract class AdaptiveStepsizeIntegrator private double initialStep; /** Minimal step. */ - private final double minStep; + private double minStep; /** Maximal step. */ - private final double maxStep; + private double maxStep; /** Build an integrator with the given stepsize bounds. * The default step handler does nothing. @@ -107,16 +107,7 @@ public abstract class AdaptiveStepsizeIntegrator final double scalRelativeTolerance) { super(name); - - this.minStep = FastMath.abs(minStep); - this.maxStep = FastMath.abs(maxStep); - this.initialStep = -1.0; - - this.scalAbsoluteTolerance = scalAbsoluteTolerance; - this.scalRelativeTolerance = scalRelativeTolerance; - this.vecAbsoluteTolerance = null; - this.vecRelativeTolerance = null; - + setStepSizeControl(minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); resetInternalState(); } @@ -139,20 +130,69 @@ public abstract class AdaptiveStepsizeIntegrator final double[] vecRelativeTolerance) { super(name); - - this.minStep = minStep; - this.maxStep = maxStep; - this.initialStep = -1.0; - - this.scalAbsoluteTolerance = 0; - this.scalRelativeTolerance = 0; - this.vecAbsoluteTolerance = vecAbsoluteTolerance.clone(); - this.vecRelativeTolerance = vecRelativeTolerance.clone(); - + setStepSizeControl(minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance); resetInternalState(); } + /** Set the adaptive step size control parameters. + *

+ * A side effect of this method is to also reset the initial + * step so it will be automatically computed by the integrator + * if {@link #setInitialStepSize(double) setInitialStepSize} + * is not called by the user. + *

+ * @param minimalStep minimal step (must be positive even for backward + * integration), the last step can be smaller than this + * @param maximalStep maximal step (must be positive even for backward + * integration) + * @param absoluteTolerance allowed absolute error + * @param relativeTolerance allowed relative error + */ + public void setStepSizeControl(final double minimalStep, final double maximalStep, + final double absoluteTolerance, + final double relativeTolerance) { + + minStep = FastMath.abs(minimalStep); + maxStep = FastMath.abs(maximalStep); + initialStep = -1; + + scalAbsoluteTolerance = absoluteTolerance; + scalRelativeTolerance = relativeTolerance; + vecAbsoluteTolerance = null; + vecRelativeTolerance = null; + + } + + /** Set the adaptive step size control parameters. + *

+ * A side effect of this method is to also reset the initial + * step so it will be automatically computed by the integrator + * if {@link #setInitialStepSize(double) setInitialStepSize} + * is not called by the user. + *

+ * @param minimalStep minimal step (must be positive even for backward + * integration), the last step can be smaller than this + * @param maximalStep maximal step (must be positive even for backward + * integration) + * @param absoluteTolerance allowed absolute error + * @param relativeTolerance allowed relative error + */ + public void setStepSizeControl(final double minimalStep, final double maximalStep, + final double[] absoluteTolerance, + final double[] relativeTolerance) { + + minStep = FastMath.abs(minimalStep); + maxStep = FastMath.abs(maximalStep); + initialStep = -1; + + scalAbsoluteTolerance = 0; + scalRelativeTolerance = 0; + vecAbsoluteTolerance = absoluteTolerance.clone(); + vecRelativeTolerance = relativeTolerance.clone(); + + } + /** Set the initial step size. *

This method allows the user to specify an initial positive * step size instead of letting the integrator guess it by diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index b1372bdc5..cb59ead1d 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -52,6 +52,10 @@ The type attribute can be add,update,fix,remove. If the output is not quite correct, check for invisible trailing spaces! --> + + Added setters allowing to change the step size control parameters of adaptive + step size ODE integrators + Added a compareTo method to MathUtils that uses a number of ulps as a tolerance error, and works well on all numbers, including normals, subnormals, diff --git a/src/test/java/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java b/src/test/java/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java index 5c97eab3f..4bf043581 100644 --- a/src/test/java/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java +++ b/src/test/java/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java @@ -158,16 +158,17 @@ public class DormandPrince853IntegratorTest { throws MathUserException, IntegratorException { int previousCalls = Integer.MAX_VALUE; + AdaptiveStepsizeIntegrator integ = + new DormandPrince853Integrator(0, Double.POSITIVE_INFINITY, + Double.NaN, Double.NaN); for (int i = -12; i < -2; ++i) { TestProblem1 pb = new TestProblem1(); double minStep = 0; double maxStep = pb.getFinalTime() - pb.getInitialTime(); double scalAbsoluteTolerance = FastMath.pow(10.0, i); double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance; + integ.setStepSizeControl(minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); - FirstOrderIntegrator integ = new DormandPrince853Integrator(minStep, maxStep, - scalAbsoluteTolerance, - scalRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate(pb,