AdamsBashforthIntegrator extends AdamsIntegrator { @Override public void integrate(final ExpandableStatefulODE equations, final double t) throws NumberIsTooSmallException, DimensionMismatchException, MaxCountExceededException, NoBracketingException { sanityChecks(equations, t); setEquations(equations); final boolean forward = t > equations.getTime(); final double[] y0 = equations.getCompleteState(); final double[] y = y0.clone(); final double[] yDot = new double[y.length]; final NordsieckStepInterpolator interpolator = new NordsieckStepInterpolator(); interpolator.reinitialize(y, forward, equations.getPrimaryMapper(), equations.getSecondaryMappers()); initIntegration(equations.getTime(), y0, t); start(equations.getTime(), y, t); interpolator.reinitialize(stepStart, stepSize, scaled, nordsieck); interpolator.storeTime(stepStart); final int lastRow = nordsieck.getRowDimension() - 1; double hNew = stepSize; interpolator.rescale(hNew); isLastStep = false; do { double error = 10; while (error >= 1.0) { stepSize = hNew; error = 0; for (int i = 0; i < mainSetDimension; ++i) { final double yScale = FastMath.abs(y[i]); final double tol = (vecAbsoluteTolerance == null) ? (scalAbsoluteTolerance + scalRelativeTolerance * yScale) : (vecAbsoluteTolerance[i] + vecRelativeTolerance[i] * yScale); final double ratio = nordsieck.getEntry(lastRow, i) / tol; error += ratio * ratio; } error = FastMath.sqrt(error / mainSetDimension); if (error >= 1.0) { final double factor = computeStepGrowShrinkFactor(error); hNew = filterStep(stepSize * factor, forward, false); interpolator.rescale(hNew); } } final double stepEnd = stepStart + stepSize; interpolator.shift(); interpolator.setInterpolatedTime(stepEnd); final ExpandableStatefulODE expandable = getExpandable(); final EquationsMapper primary = expandable.getPrimaryMapper(); primary.insertEquationData(interpolator.getInterpolatedState(), y); int index = 0; for (final EquationsMapper secondary : expandable.getSecondaryMappers()) { secondary.insertEquationData(interpolator.getInterpolatedSecondaryState(index), y); ++index; } computeDerivatives(stepEnd, y, yDot); final double[] predictedScaled = new double[y0.length]; for (int j = 0; j < y0.length; ++j) { predictedScaled[j] = stepSize * yDot[j]; } final Array2DRowRealMatrix nordsieckTmp = updateHighOrderDerivativesPhase1(nordsieck); updateHighOrderDerivativesPhase2(scaled, predictedScaled, nordsieckTmp); interpolator.reinitialize(stepEnd, stepSize, predictedScaled, nordsieckTmp); interpolator.storeTime(stepEnd); stepStart = acceptStep(interpolator, y, yDot, t); scaled = predictedScaled; nordsieck = nordsieckTmp; interpolator.reinitialize(stepEnd, stepSize, scaled, nordsieck); if (!isLastStep) { interpolator.storeTime(stepStart); if (resetOccurred) { start(stepStart, y, t); interpolator.reinitialize(stepStart, stepSize, scaled, nordsieck); } final double factor = computeStepGrowShrinkFactor(error); final double scaledH = stepSize * factor; final double nextT = stepStart + scaledH; final boolean nextIsLast = forward ? (nextT >= t) : (nextT <= t); hNew = filterStep(scaledH, forward, nextIsLast); final double filteredNextT = stepStart + hNew; final boolean filteredNextIsLast = forward ? (filteredNextT >= t) : (filteredNextT <= t); if (filteredNextIsLast) { hNew = t - stepStart; } interpolator.rescale(hNew); } } while (!isLastStep); equations.setTime(stepStart); equations.setCompleteState(y); resetInternalState(); } AdamsBashforthIntegrator(final int nSteps,
                                    final double minStep, final double maxStep,
                                    final double scalAbsoluteTolerance,
                                    final double scalRelativeTolerance);  AdamsBashforthIntegrator(final int nSteps,
                                    final double minStep, final double maxStep,
                                    final double[] vecAbsoluteTolerance,
                                    final double[] vecRelativeTolerance); @Override void integrate(final ExpandableStatefulODE equations, final double t);  }
@Test public void testIncreasingTolerance() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { int previousCalls = Integer.MAX_VALUE; for (int i = -12; i < -5; ++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; FirstOrderIntegrator integ = new AdamsBashforthIntegrator(4, minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertTrue(handler.getMaximalValueError() > (50.0 * scalAbsoluteTolerance)); Assert.assertTrue(handler.getMaximalValueError() < (300.0 * scalAbsoluteTolerance)); Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-16); int calls = pb.getCalls(); Assert.assertEquals(integ.getEvaluations(), calls); Assert.assertTrue(calls <= previousCalls); previousCalls = calls; } }
@Test(expected = MaxCountExceededException.class) public void exceedMaxEvaluations() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem1 pb = new TestProblem1(); double range = pb.getFinalTime() - pb.getInitialTime(); AdamsBashforthIntegrator integ = new AdamsBashforthIntegrator(2, 0, range, 1.0e-12, 1.0e-12); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.setMaxEvaluations(650); integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); }
@Test public void backward() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem5 pb = new TestProblem5(); double range = FastMath.abs(pb.getFinalTime() - pb.getInitialTime()); FirstOrderIntegrator integ = new AdamsBashforthIntegrator(4, 0, range, 1.0e-12, 1.0e-12); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertTrue(handler.getLastError() < 1.5e-8); Assert.assertTrue(handler.getMaximalValueError() < 1.5e-8); Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-16); Assert.assertEquals("Adams-Bashforth", integ.getName()); }
@Test public void polynomial() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem6 pb = new TestProblem6(); double range = FastMath.abs(pb.getFinalTime() - pb.getInitialTime()); for (int nSteps = 2; nSteps < 8; ++nSteps) { AdamsBashforthIntegrator integ = new AdamsBashforthIntegrator(nSteps, 1.0e-6 * range, 0.1 * range, 1.0e-5, 1.0e-5); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); if (nSteps < 4) { Assert.assertTrue(handler.getMaximalValueError() > 1.0e-03); } else { Assert.assertTrue(handler.getMaximalValueError() < 4.0e-12); } } }
@Test(expected=DimensionMismatchException.class) public void dimensionCheck() throws NumberIsTooSmallException, DimensionMismatchException, MaxCountExceededException, NoBracketingException { TestProblem1 pb = new TestProblem1(); FirstOrderIntegrator integ = new AdamsBashforthIntegrator(2, 0.0, 1.0, 1.0e-10, 1.0e-10); integ.integrate(pb, 0.0, new double[pb.getDimension()+10], 1.0, new double[pb.getDimension()+10]); }
@Test(expected=NumberIsTooSmallException.class) public void testMinStep() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem1 pb = new TestProblem1(); double minStep = 0.1 * (pb.getFinalTime() - pb.getInitialTime()); double maxStep = pb.getFinalTime() - pb.getInitialTime(); double[] vecAbsoluteTolerance = { 1.0e-15, 1.0e-16 }; double[] vecRelativeTolerance = { 1.0e-15, 1.0e-16 }; FirstOrderIntegrator integ = new AdamsBashforthIntegrator(4, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); }