diff --git a/src/java/org/apache/commons/math/ode/AbstractStepInterpolator.java b/src/java/org/apache/commons/math/ode/AbstractStepInterpolator.java index c4955dbe8..9efc08c17 100644 --- a/src/java/org/apache/commons/math/ode/AbstractStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/AbstractStepInterpolator.java @@ -38,7 +38,7 @@ import java.io.IOException; */ public abstract class AbstractStepInterpolator - implements StepInterpolator, Cloneable { + implements StepInterpolator { /** previous time */ protected double previousTime; @@ -163,32 +163,31 @@ public abstract class AbstractStepInterpolator } /** Copy the instance. + *
The copied instance is guaranteed to be independent from the + * original one. Both can be used with different settings for + * interpolated time without any side effect.
+ * @return a deep copy of the instance, which can be used independently. + * @throws DerivativeException if this call induces an automatic + * step finalization that throws one + * @see #setInterpolatedTime(double) + */ + public StepInterpolator copy() throws DerivativeException { - *The copied interpolator should have been finalized before the - * copy, otherwise the copy will not be able to perform correctly any - * interpolation and will throw a {@link NullPointerException} - * later. Since we don't want this constructor to throw the - * exceptions finalization may involve and since we don't want this - * method to modify the state of the copied interpolator, - * finalization is not done automatically, it - * remains under user control.
+ // finalize the step before performing copy + finalizeStep(); - *The copy is a deep copy: its arrays are separated from the - * original arrays of the instance.
+ // create the new independent instance + return doCopy(); - *This method has been redeclared as public instead of protected.
+ } - * @return a copy of the instance. - - */ - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException cnse) { - // should never happen - return null; - } - } + /** Really copy the finalized instance. + *This method is called by {@link #copy()} after the + * step has been finalized. It must perform a deep copy + * to have an new instance completely independent for the + * original instance. + */ + protected abstract StepInterpolator doCopy(); /** Shift one step forward. * Copy the current time into the previous time, hence preparing the diff --git a/src/java/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolator.java b/src/java/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolator.java index 5e0efb102..060a7da3e 100644 --- a/src/java/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/ClassicalRungeKuttaStepInterpolator.java @@ -68,13 +68,9 @@ class ClassicalRungeKuttaStepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new ClassicalRungeKuttaStepInterpolator(this); } diff --git a/src/java/org/apache/commons/math/ode/ContinuousOutputModel.java b/src/java/org/apache/commons/math/ode/ContinuousOutputModel.java index 778ce2db4..d7aab45b6 100644 --- a/src/java/org/apache/commons/math/ode/ContinuousOutputModel.java +++ b/src/java/org/apache/commons/math/ode/ContinuousOutputModel.java @@ -92,11 +92,14 @@ public class ContinuousOutputModel /** Append another model at the end of the instance. * @param model model to add at the end of the instance + * @exception DerivativeException if some step interpolators from + * the appended model cannot be copied * @exception IllegalArgumentException if the model to append is not * compatible with the instance (dimension of the state vector, * propagation direction, hole between the dates) */ - public void append(ContinuousOutputModel model) { + public void append(ContinuousOutputModel model) + throws DerivativeException { if (model.steps.size() == 0) { return; @@ -127,8 +130,7 @@ public class ContinuousOutputModel } for (Iterator iter = model.steps.iterator(); iter.hasNext(); ) { - AbstractStepInterpolator ai = (AbstractStepInterpolator) iter.next(); - steps.add(ai.clone()); + steps.add(((AbstractStepInterpolator) iter.next()).copy()); } index = steps.size() - 1; @@ -176,8 +178,7 @@ public class ContinuousOutputModel forward = interpolator.isForward(); } - ai.finalizeStep(); - steps.add(ai.clone()); + steps.add(ai.copy()); if (isLast) { finalTime = ai.getCurrentTime(); diff --git a/src/java/org/apache/commons/math/ode/DormandPrince54StepInterpolator.java b/src/java/org/apache/commons/math/ode/DormandPrince54StepInterpolator.java index 590a20345..95755d731 100644 --- a/src/java/org/apache/commons/math/ode/DormandPrince54StepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/DormandPrince54StepInterpolator.java @@ -77,16 +77,13 @@ class DormandPrince54StepInterpolator } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new DormandPrince54StepInterpolator(this); } + /** Reinitialize the instance * @param equations set of differential equations being integrated * @param y reference to the integrator array holding the state at diff --git a/src/java/org/apache/commons/math/ode/DormandPrince853StepInterpolator.java b/src/java/org/apache/commons/math/ode/DormandPrince853StepInterpolator.java index e96b96df3..226625f97 100644 --- a/src/java/org/apache/commons/math/ode/DormandPrince853StepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/DormandPrince853StepInterpolator.java @@ -46,7 +46,6 @@ class DormandPrince853StepInterpolator public DormandPrince853StepInterpolator() { super(); yDotKLast = null; - yTmp = null; v = null; vectorsInitialized = false; } @@ -87,18 +86,11 @@ class DormandPrince853StepInterpolator } - // the step has been finalized, we don't need this anymore - yTmp = null; - } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new DormandPrince853StepInterpolator(this); } @@ -135,8 +127,6 @@ class DormandPrince853StepInterpolator yDotKLast[k] = new double[dimension]; } - yTmp = new double[dimension]; - v = new double[7][]; for (int k = 0; k < v.length; ++k) { v[k] = new double[dimension]; @@ -225,7 +215,13 @@ class DormandPrince853StepInterpolator protected void doFinalize() throws DerivativeException { + if (currentState == null) { + // we are finalizing an uninitialized instance + return; + } + double s; + double[] yTmp = new double[currentState.length]; // k14 for (int j = 0; j < currentState.length; ++j) { @@ -311,9 +307,6 @@ class DormandPrince853StepInterpolator /** Last evaluations. */ private double[][] yDotKLast; - /** Temporary state vector. */ - private double[] yTmp; - /** Vectors for interpolation. */ private double[][] v; @@ -407,6 +400,6 @@ class DormandPrince853StepInterpolator }; - private static final long serialVersionUID = 4165537490327432186L; + private static final long serialVersionUID = 7152276390558450974L; } diff --git a/src/java/org/apache/commons/math/ode/DummyStepInterpolator.java b/src/java/org/apache/commons/math/ode/DummyStepInterpolator.java index fd38ea1b9..b88aef858 100644 --- a/src/java/org/apache/commons/math/ode/DummyStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/DummyStepInterpolator.java @@ -61,6 +61,21 @@ public class DummyStepInterpolator super(y, forward); } + /** Copy constructor. + * @param interpolator interpolator to copy from. The copy is a deep + * copy: its arrays are separated from the original arrays of the + * instance + */ + public DummyStepInterpolator(DummyStepInterpolator interpolator) { + super(interpolator); + } + + /** Really copy the finalized instance. + */ + protected StepInterpolator doCopy() { + return new DummyStepInterpolator(this); + } + /** Compute the state at the interpolated time. * In this class, this method does nothing: the interpolated state * is always the state at the end of the current step. diff --git a/src/java/org/apache/commons/math/ode/EulerStepInterpolator.java b/src/java/org/apache/commons/math/ode/EulerStepInterpolator.java index 77c660786..4a093afe6 100644 --- a/src/java/org/apache/commons/math/ode/EulerStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/EulerStepInterpolator.java @@ -61,16 +61,13 @@ class EulerStepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new EulerStepInterpolator(this); } + /** Compute the state at the interpolated time. * This is the main processing method that should be implemented by * the derived classes to perform the interpolation. diff --git a/src/java/org/apache/commons/math/ode/GillStepInterpolator.java b/src/java/org/apache/commons/math/ode/GillStepInterpolator.java index 0c82d2d63..078238699 100644 --- a/src/java/org/apache/commons/math/ode/GillStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/GillStepInterpolator.java @@ -66,16 +66,13 @@ class GillStepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new GillStepInterpolator(this); } + /** Compute the state at the interpolated time. * This is the main processing method that should be implemented by * the derived classes to perform the interpolation. diff --git a/src/java/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolator.java b/src/java/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolator.java index 289075c7b..db5c939b9 100644 --- a/src/java/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolator.java @@ -219,16 +219,13 @@ class GraggBulirschStoerStepInterpolator } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new GraggBulirschStoerStepInterpolator(this); } + /** Compute the interpolation coefficients for dense output. * @param mu degree of the interpolation polynom * @param h current step diff --git a/src/java/org/apache/commons/math/ode/HighamHall54StepInterpolator.java b/src/java/org/apache/commons/math/ode/HighamHall54StepInterpolator.java index 5b1bca337..9be50ec3c 100644 --- a/src/java/org/apache/commons/math/ode/HighamHall54StepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/HighamHall54StepInterpolator.java @@ -52,16 +52,13 @@ class HighamHall54StepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new HighamHall54StepInterpolator(this); } + /** Compute the state at the interpolated time. * @param theta normalized interpolation abscissa within the step * (theta is zero at the previous time step and one at the current time step) diff --git a/src/java/org/apache/commons/math/ode/MidpointStepInterpolator.java b/src/java/org/apache/commons/math/ode/MidpointStepInterpolator.java index 0635bb693..848c9639e 100644 --- a/src/java/org/apache/commons/math/ode/MidpointStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/MidpointStepInterpolator.java @@ -63,16 +63,13 @@ class MidpointStepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new MidpointStepInterpolator(this); } + /** Compute the state at the interpolated time. * This is the main processing method that should be implemented by * the derived classes to perform the interpolation. diff --git a/src/java/org/apache/commons/math/ode/RungeKuttaFehlbergIntegrator.java b/src/java/org/apache/commons/math/ode/RungeKuttaFehlbergIntegrator.java index f8a6a2425..a8811919a 100644 --- a/src/java/org/apache/commons/math/ode/RungeKuttaFehlbergIntegrator.java +++ b/src/java/org/apache/commons/math/ode/RungeKuttaFehlbergIntegrator.java @@ -179,7 +179,7 @@ public abstract class RungeKuttaFehlbergIntegrator // set up an interpolator sharing the integrator arrays AbstractStepInterpolator interpolator; if (handler.requiresDenseOutput() || (! switchesHandler.isEmpty())) { - RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.clone(); + RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.copy(); rki.reinitialize(equations, yTmp, yDotK, forward); interpolator = rki; } else { diff --git a/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java b/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java index 412c58293..75a0de534 100644 --- a/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java +++ b/src/java/org/apache/commons/math/ode/RungeKuttaIntegrator.java @@ -172,7 +172,7 @@ public abstract class RungeKuttaIntegrator // set up an interpolator sharing the integrator arrays AbstractStepInterpolator interpolator; if (handler.requiresDenseOutput() || (! switchesHandler.isEmpty())) { - RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.clone(); + RungeKuttaStepInterpolator rki = (RungeKuttaStepInterpolator) prototype.copy(); rki.reinitialize(equations, yTmp, yDotK, forward); interpolator = rki; } else { diff --git a/src/java/org/apache/commons/math/ode/StepInterpolator.java b/src/java/org/apache/commons/math/ode/StepInterpolator.java index f4e0ba3b6..f93daea37 100644 --- a/src/java/org/apache/commons/math/ode/StepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/StepInterpolator.java @@ -62,12 +62,14 @@ public interface StepInterpolator /** * Set the time of the interpolated point. - *
Setting the time outside of the current step is now allowed - * (it was not allowed up to version 5.4 of Mantissa), but should be - * used with care since the accuracy of the interpolator will + *
Setting the time outside of the current step is now allowed, but + * should be used with care since the accuracy of the interpolator will * probably be very poor far from this step. This allowance has been * added to simplify implementation of search algorithms near the * step endpoints.
+ *Setting the time changes the instance internal state. If a + * specific state must be preserved, a copy of the instance must be + * created using {@link #copy()}.
* @param time time of the interpolated point * @throws DerivativeException if this call induces an automatic * step finalization that throws one @@ -92,4 +94,15 @@ public interface StepInterpolator */ public boolean isForward(); + /** Copy the instance. + *The copied instance is guaranteed to be independent from the + * original one. Both can be used with different settings for + * interpolated time without any side effect.
+ * @return a deep copy of the instance, which can be used independently. + * @throws DerivativeException if this call induces an automatic + * step finalization that throws one + * @see #setInterpolatedTime(double) + */ + public StepInterpolator copy() throws DerivativeException; + } diff --git a/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java b/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java index 556a3fb99..965aaee09 100644 --- a/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java +++ b/src/java/org/apache/commons/math/ode/ThreeEighthesStepInterpolator.java @@ -68,16 +68,13 @@ class ThreeEighthesStepInterpolator super(interpolator); } - /** - * Clone the instance. - * the copy is a deep copy: its arrays are separated from the - * original arrays of the instance - * @return a copy of the instance + /** Really copy the finalized instance. */ - public Object clone() { + protected StepInterpolator doCopy() { return new ThreeEighthesStepInterpolator(this); } + /** Compute the state at the interpolated time. * This is the main processing method that should be implemented by * the derived classes to perform the interpolation. diff --git a/src/test/org/apache/commons/math/ode/DormandPrince54StepInterpolatorTest.java b/src/test/org/apache/commons/math/ode/DormandPrince54StepInterpolatorTest.java index a1601195b..dbb445bca 100644 --- a/src/test/org/apache/commons/math/ode/DormandPrince54StepInterpolatorTest.java +++ b/src/test/org/apache/commons/math/ode/DormandPrince54StepInterpolatorTest.java @@ -85,6 +85,50 @@ public class DormandPrince54StepInterpolatorTest } + public void testClone() + throws DerivativeException, IntegratorException { + TestProblem3 pb = new TestProblem3(0.9); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = scalAbsoluteTolerance; + DormandPrince54Integrator integ = new DormandPrince54Integrator(minStep, maxStep, + scalAbsoluteTolerance, + scalRelativeTolerance); + integ.setStepHandler(new StepHandler() { + public void handleStep(StepInterpolator interpolator, boolean isLast) + throws DerivativeException { + StepInterpolator cloned = interpolator.copy(); + double tA = cloned.getPreviousTime(); + double tB = cloned.getCurrentTime(); + double halfStep = Math.abs(tB - tA) / 2; + assertEquals(interpolator.getPreviousTime(), tA, 1.0e-12); + assertEquals(interpolator.getCurrentTime(), tB, 1.0e-12); + for (int i = 0; i < 10; ++i) { + double t = (i * tB + (9 - i) * tA) / 9; + interpolator.setInterpolatedTime(t); + assertTrue(Math.abs(cloned.getInterpolatedTime() - t) > (halfStep / 10)); + cloned.setInterpolatedTime(t); + assertEquals(t, cloned.getInterpolatedTime(), 1.0e-12); + double[] referenceState = interpolator.getInterpolatedState(); + double[] cloneState = cloned.getInterpolatedState(); + for (int j = 0; j < referenceState.length; ++j) { + assertEquals(referenceState[j], cloneState[j], 1.0e-12); + } + } + } + public boolean requiresDenseOutput() { + return true; + } + public void reset() { + } + }); + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + + } + public static Test suite() { return new TestSuite(DormandPrince54StepInterpolatorTest.class); } diff --git a/src/test/org/apache/commons/math/ode/DormandPrince853StepInterpolatorTest.java b/src/test/org/apache/commons/math/ode/DormandPrince853StepInterpolatorTest.java index 7c298dd13..e2ff07380 100644 --- a/src/test/org/apache/commons/math/ode/DormandPrince853StepInterpolatorTest.java +++ b/src/test/org/apache/commons/math/ode/DormandPrince853StepInterpolatorTest.java @@ -85,6 +85,50 @@ public class DormandPrince853StepInterpolatorTest } + public void testClone() + throws DerivativeException, IntegratorException { + TestProblem3 pb = new TestProblem3(0.9); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = scalAbsoluteTolerance; + DormandPrince853Integrator integ = new DormandPrince853Integrator(minStep, maxStep, + scalAbsoluteTolerance, + scalRelativeTolerance); + integ.setStepHandler(new StepHandler() { + public void handleStep(StepInterpolator interpolator, boolean isLast) + throws DerivativeException { + StepInterpolator cloned = interpolator.copy(); + double tA = cloned.getPreviousTime(); + double tB = cloned.getCurrentTime(); + double halfStep = Math.abs(tB - tA) / 2; + assertEquals(interpolator.getPreviousTime(), tA, 1.0e-12); + assertEquals(interpolator.getCurrentTime(), tB, 1.0e-12); + for (int i = 0; i < 10; ++i) { + double t = (i * tB + (9 - i) * tA) / 9; + interpolator.setInterpolatedTime(t); + assertTrue(Math.abs(cloned.getInterpolatedTime() - t) > (halfStep / 10)); + cloned.setInterpolatedTime(t); + assertEquals(t, cloned.getInterpolatedTime(), 1.0e-12); + double[] referenceState = interpolator.getInterpolatedState(); + double[] cloneState = cloned.getInterpolatedState(); + for (int j = 0; j < referenceState.length; ++j) { + assertEquals(referenceState[j], cloneState[j], 1.0e-12); + } + } + } + public boolean requiresDenseOutput() { + return true; + } + public void reset() { + } + }); + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + + } + public static Test suite() { return new TestSuite(DormandPrince853StepInterpolatorTest.class); } diff --git a/src/test/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolatorTest.java b/src/test/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolatorTest.java index 5a14c7a20..b678613d8 100644 --- a/src/test/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolatorTest.java +++ b/src/test/org/apache/commons/math/ode/GraggBulirschStoerStepInterpolatorTest.java @@ -86,6 +86,50 @@ public class GraggBulirschStoerStepInterpolatorTest } + public void testClone() + throws DerivativeException, IntegratorException { + TestProblem3 pb = new TestProblem3(0.9); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = scalAbsoluteTolerance; + GraggBulirschStoerIntegrator integ = new GraggBulirschStoerIntegrator(minStep, maxStep, + scalAbsoluteTolerance, + scalRelativeTolerance); + integ.setStepHandler(new StepHandler() { + public void handleStep(StepInterpolator interpolator, boolean isLast) + throws DerivativeException { + StepInterpolator cloned = interpolator.copy(); + double tA = cloned.getPreviousTime(); + double tB = cloned.getCurrentTime(); + double halfStep = Math.abs(tB - tA) / 2; + assertEquals(interpolator.getPreviousTime(), tA, 1.0e-12); + assertEquals(interpolator.getCurrentTime(), tB, 1.0e-12); + for (int i = 0; i < 10; ++i) { + double t = (i * tB + (9 - i) * tA) / 9; + interpolator.setInterpolatedTime(t); + assertTrue(Math.abs(cloned.getInterpolatedTime() - t) > (halfStep / 10)); + cloned.setInterpolatedTime(t); + assertEquals(t, cloned.getInterpolatedTime(), 1.0e-12); + double[] referenceState = interpolator.getInterpolatedState(); + double[] cloneState = cloned.getInterpolatedState(); + for (int j = 0; j < referenceState.length; ++j) { + assertEquals(referenceState[j], cloneState[j], 1.0e-12); + } + } + } + public boolean requiresDenseOutput() { + return true; + } + public void reset() { + } + }); + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + + } + public static Test suite() { return new TestSuite(GraggBulirschStoerStepInterpolatorTest.class); } diff --git a/src/test/org/apache/commons/math/ode/HighamHall54StepInterpolatorTest.java b/src/test/org/apache/commons/math/ode/HighamHall54StepInterpolatorTest.java index 68d97c00c..9304f880a 100644 --- a/src/test/org/apache/commons/math/ode/HighamHall54StepInterpolatorTest.java +++ b/src/test/org/apache/commons/math/ode/HighamHall54StepInterpolatorTest.java @@ -85,6 +85,50 @@ public class HighamHall54StepInterpolatorTest } + public void testClone() + throws DerivativeException, IntegratorException { + TestProblem3 pb = new TestProblem3(0.9); + double minStep = 0; + double maxStep = pb.getFinalTime() - pb.getInitialTime(); + double scalAbsoluteTolerance = 1.0e-8; + double scalRelativeTolerance = scalAbsoluteTolerance; + HighamHall54Integrator integ = new HighamHall54Integrator(minStep, maxStep, + scalAbsoluteTolerance, + scalRelativeTolerance); + integ.setStepHandler(new StepHandler() { + public void handleStep(StepInterpolator interpolator, boolean isLast) + throws DerivativeException { + StepInterpolator cloned = interpolator.copy(); + double tA = cloned.getPreviousTime(); + double tB = cloned.getCurrentTime(); + double halfStep = Math.abs(tB - tA) / 2; + assertEquals(interpolator.getPreviousTime(), tA, 1.0e-12); + assertEquals(interpolator.getCurrentTime(), tB, 1.0e-12); + for (int i = 0; i < 10; ++i) { + double t = (i * tB + (9 - i) * tA) / 9; + interpolator.setInterpolatedTime(t); + assertTrue(Math.abs(cloned.getInterpolatedTime() - t) > (halfStep / 10)); + cloned.setInterpolatedTime(t); + assertEquals(t, cloned.getInterpolatedTime(), 1.0e-12); + double[] referenceState = interpolator.getInterpolatedState(); + double[] cloneState = cloned.getInterpolatedState(); + for (int j = 0; j < referenceState.length; ++j) { + assertEquals(referenceState[j], cloneState[j], 1.0e-12); + } + } + } + public boolean requiresDenseOutput() { + return true; + } + public void reset() { + } + }); + integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + + } + public static Test suite() { return new TestSuite(HighamHall54StepInterpolatorTest.class); }