| /* |
| * 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.math3.ode.nonstiff; |
| |
| |
| import org.apache.commons.math3.analysis.UnivariateFunction; |
| import org.apache.commons.math3.analysis.polynomials.PolynomialFunction; |
| import org.apache.commons.math3.linear.Array2DRowRealMatrix; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| public class AdamsNordsieckTransformerTest { |
| |
| @Test |
| public void testPolynomialExtraDerivative() { |
| checkNordsieckStart(new PolynomialFunction(new double[] { 6, 5, 4, 3, 2, 1 }), |
| 5, 0.0, 0.125, 3.2e-16); |
| } |
| |
| @Test |
| public void testPolynomialRegular() { |
| checkNordsieckStart(new PolynomialFunction(new double[] { 6, 5, 4, 3, 2, 1 }), |
| 4, 0.0, 0.125, 3.1e-16); |
| } |
| |
| @Test |
| public void testPolynomialMissingLastDerivative() { |
| // this test intentionally uses not enough start points, |
| // the Nordsieck vector is therefore not expected to match the exact scaled derivatives |
| checkNordsieckStart(new PolynomialFunction(new double[] { 6, 5, 4, 3, 2, 1 }), |
| 3, 0.0, 0.125, 1.6e-4); |
| } |
| |
| @Test |
| public void testTransformExact() { |
| // a 5 steps transformer handles a degree 5 polynomial exactly |
| // the Nordsieck vector holds the full information about the function |
| // transforming the vector from t0 to t0+h or recomputing it from scratch |
| // at t0+h yields the same result |
| checkTransform(new PolynomialFunction(new double[] { 6, 5, 4, 3, 2, 1 }), 5, 2.567e-15); |
| } |
| |
| @Test |
| public void testTransformInexact() { |
| // a 4 steps transformer cannot handle a degree 5 polynomial exactly |
| // the Nordsieck vector lacks some high degree information about the function |
| // transforming the vector from t0 to t0+h or recomputing it from scratch |
| // at t0+h yields different results |
| checkTransform(new PolynomialFunction(new double[] { 6, 5, 4, 3, 2, 1 }), 4, 5.658e-4); |
| } |
| |
| private void checkNordsieckStart(final PolynomialFunction polynomial, final int nbSteps, final double t0, |
| final double h, final double epsilon) { |
| |
| final AdamsNordsieckTransformer transformer = AdamsNordsieckTransformer.getInstance(nbSteps); |
| PolynomialFunction derivative = polynomial.polynomialDerivative(); |
| final Array2DRowRealMatrix nordsieck = start(transformer, nbSteps, t0, h, polynomial, derivative); |
| |
| Assert.assertEquals(nbSteps - 1, nordsieck.getRowDimension()); |
| double coeff = h; |
| for (int i = 0; i < nordsieck.getRowDimension(); ++i) { |
| coeff *= h / (i + 2); |
| derivative = derivative.polynomialDerivative(); |
| Assert.assertEquals(derivative.value(t0) * coeff, nordsieck.getEntry(i, 0), epsilon); |
| } |
| |
| } |
| |
| private void checkTransform(final PolynomialFunction polynomial, final int nbSteps, final double expectedError) { |
| |
| final AdamsNordsieckTransformer transformer = AdamsNordsieckTransformer.getInstance(nbSteps); |
| final PolynomialFunction derivative = polynomial.polynomialDerivative(); |
| |
| final double t0 = 0.0; |
| final double h = 0.125; |
| final Array2DRowRealMatrix n0 = start(transformer, nbSteps, t0, h, polynomial, derivative); |
| final Array2DRowRealMatrix n1 = transformer.updateHighOrderDerivativesPhase1(n0); |
| transformer.updateHighOrderDerivativesPhase2(new double[] { h * derivative.value(t0) }, |
| new double[] { h * derivative.value(t0 + h) }, |
| n1); |
| final Array2DRowRealMatrix n2 = start(transformer, nbSteps, t0 + h, h, polynomial, derivative); |
| |
| Assert.assertEquals(expectedError, n2.subtract(n1).getNorm(), expectedError * 0.001); |
| |
| } |
| |
| private Array2DRowRealMatrix start(final AdamsNordsieckTransformer transformer, final int nbSteps, |
| final double t0, final double h, |
| final UnivariateFunction f0, final UnivariateFunction f1) { |
| |
| final int nbStartPoints = (nbSteps + 3) / 2; |
| final double[] t = new double[nbStartPoints]; |
| final double[][] y = new double[nbStartPoints][1]; |
| final double[][] yDot = new double[nbStartPoints][1]; |
| for (int i = 0; i < nbStartPoints; ++i) { |
| t[i] = t0 + i * h; |
| y[i][0] = f0.value(t[i]); |
| yDot[i][0] = f1.value(t[i]); |
| } |
| |
| return transformer.initializeHighOrderDerivatives(h, t, y, yDot); |
| |
| } |
| |
| } |