/* * 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.math4.ode.sampling; import org.junit.Assert; import java.util.ArrayList; import java.util.List; import org.apache.commons.math4.exception.DimensionMismatchException; import org.apache.commons.math4.exception.MaxCountExceededException; import org.apache.commons.math4.exception.NoBracketingException; import org.apache.commons.math4.exception.NumberIsTooSmallException; import org.apache.commons.math4.ode.FirstOrderDifferentialEquations; import org.apache.commons.math4.ode.FirstOrderIntegrator; import org.apache.commons.math4.ode.nonstiff.GraggBulirschStoerIntegrator; import org.apache.commons.math4.ode.sampling.FixedStepHandler; import org.apache.commons.math4.ode.sampling.StepNormalizer; import org.apache.commons.math4.ode.sampling.StepNormalizerBounds; import org.apache.commons.math4.ode.sampling.StepNormalizerMode; import org.junit.Test; /** Base class for step normalizer output tests. */ public abstract class StepNormalizerOutputTestBase implements FirstOrderDifferentialEquations, FixedStepHandler { /** The normalized output time values. */ private List<Double> output; /** * Returns the start time. * @return the start time */ protected abstract double getStart(); /** * Returns the end time. * @return the end time */ protected abstract double getEnd(); /** * Returns the expected normalized output time values for increment mode. * @return the expected normalized output time values for increment mode */ protected abstract double[] getExpInc(); /** * Returns the expected reversed normalized output time values for * increment mode. * @return the expected reversed normalized output time values for * increment mode */ protected abstract double[] getExpIncRev(); /** * Returns the expected normalized output time values for multiples mode. * @return the expected normalized output time values for multiples mode */ protected abstract double[] getExpMul(); /** * Returns the expected reversed normalized output time values for * multiples mode. * @return the expected reversed normalized output time values for * multiples mode */ protected abstract double[] getExpMulRev(); /** * Returns the offsets for the unit tests below, in the order they are * given below. For each test, the left and right offsets are returned. * @return the offsets for the unit tests below, in the order they are * given below */ protected abstract int[][] getO(); /** * Get the array, given left and right offsets. * @param a the input array * @param offsetL the left side offset * @param offsetR the right side offset * @return the modified array */ private double[] getArray(double[] a, int offsetL, int offsetR) { double[] copy = new double[a.length - offsetR - offsetL]; System.arraycopy(a, offsetL, copy, 0, copy.length); return copy; } @Test public void testIncNeither() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpInc(), getO()[0][0], getO()[0][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.NEITHER, exp, false); } @Test public void testIncNeitherRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpIncRev(), getO()[1][0], getO()[1][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.NEITHER, exp, true); } @Test public void testIncFirst() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpInc(), getO()[2][0], getO()[2][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.FIRST, exp, false); } @Test public void testIncFirstRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpIncRev(), getO()[3][0], getO()[3][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.FIRST, exp, true); } @Test public void testIncLast() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpInc(), getO()[4][0], getO()[4][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.LAST, exp, false); } @Test public void testIncLastRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpIncRev(), getO()[5][0], getO()[5][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.LAST, exp, true); } @Test public void testIncBoth() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpInc(), getO()[6][0], getO()[6][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.BOTH, exp, false); } @Test public void testIncBothRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpIncRev(), getO()[7][0], getO()[7][1]); doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.BOTH, exp, true); } @Test public void testMulNeither() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMul(), getO()[8][0], getO()[8][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.NEITHER, exp, false); } @Test public void testMulNeitherRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMulRev(), getO()[9][0], getO()[9][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.NEITHER, exp, true); } @Test public void testMulFirst() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMul(), getO()[10][0], getO()[10][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.FIRST, exp, false); } @Test public void testMulFirstRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMulRev(), getO()[11][0], getO()[11][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.FIRST, exp, true); } @Test public void testMulLast() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMul(), getO()[12][0], getO()[12][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.LAST, exp, false); } @Test public void testMulLastRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMulRev(), getO()[13][0], getO()[13][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.LAST, exp, true); } @Test public void testMulBoth() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMul(), getO()[14][0], getO()[14][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.BOTH, exp, false); } @Test public void testMulBothRev() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { double[] exp = getArray(getExpMulRev(), getO()[15][0], getO()[15][1]); doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.BOTH, exp, true); } /** * The actual step normalizer output test code, shared by all the unit * tests. * * @param mode the step normalizer mode to use * @param bounds the step normalizer bounds setting to use * @param expected the expected output (normalized time points) * @param reverse whether to reverse the integration direction * @throws NoBracketingException * @throws MaxCountExceededException * @throws NumberIsTooSmallException * @throws DimensionMismatchException */ private void doTest(StepNormalizerMode mode, StepNormalizerBounds bounds, double[] expected, boolean reverse) throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { // Forward test. FirstOrderIntegrator integ = new GraggBulirschStoerIntegrator( 1e-8, 1.0, 1e-5, 1e-5); integ.addStepHandler(new StepNormalizer(0.5, this, mode, bounds)); double[] y = {0.0}; double start = reverse ? getEnd() : getStart(); double end = reverse ? getStart() : getEnd(); output = new ArrayList<>(); integ.integrate(this, start, y, end, y); double[] actual = new double[output.size()]; for(int i = 0; i < actual.length; i++) { actual[i] = output.get(i); } Assert.assertArrayEquals(expected, actual, 1e-5); } /** {@inheritDoc} */ @Override public int getDimension() { return 1; } /** {@inheritDoc} */ @Override public void computeDerivatives(double t, double[] y, double[] yDot) { yDot[0] = y[0]; } /** {@inheritDoc} */ @Override public void init(double t0, double[] y0, double t) { } /** {@inheritDoc} */ @Override public void handleStep(double t, double[] y, double[] yDot, boolean isLast) { output.add(t); } }