/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.interpolation; import static com.opengamma.analytics.math.matrix.MatrixAlgebraFactory.OG_ALGEBRA; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.opengamma.analytics.math.function.PiecewisePolynomialFunction1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.util.test.TestGroup; /** * Test. */ @Test(groups = TestGroup.UNIT) public class MeshgridInterpolator2DTest { private static final double EPS = 1e-12; /** * */ @Test public void linearTest() { double[] x0Values = new double[] {1., 2., 3., 4. }; double[] x1Values = new double[] {-1., 0., 1., 2., 3. }; final int n0Data = x0Values.length; final int n1Data = x1Values.length; double[][] yValues = new double[n0Data][n1Data]; for (int i = 0; i < n0Data; ++i) { for (int j = 0; j < n1Data; ++j) { yValues[i][j] = (x0Values[i] + 2.) * (x1Values[j] + 5.); } } PiecewisePolynomialInterpolator method = new CubicSplineInterpolator(); MeshgridInterpolator2D interp = new MeshgridInterpolator2D(new PiecewisePolynomialInterpolator[] {method, method }); final int n0Keys = 51; final int n1Keys = 61; double[] x0Keys = new double[n0Keys]; double[] x1Keys = new double[n1Keys]; for (int i = 0; i < n0Keys; ++i) { x0Keys[i] = 0. + 5. * i / (n0Keys - 1); } for (int i = 0; i < n1Keys; ++i) { x1Keys[i] = -2. + 6. * i / (n1Keys - 1); } double[][] resValues = interp.interpolate(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); double[][] resX0 = interp.differentiateX0(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); double[][] resX1 = interp.differentiateX1(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); double[][] resX0Twice = interp.differentiateX0Twice(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); double[][] resX1Twice = interp.differentiateX1Twice(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double expVal = (x0Keys[i] + 2.) * (x1Keys[j] + 5.); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(resValues[i][j], expVal, ref * EPS); } } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double expVal = (x1Keys[j] + 5.); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(resX0[i][j], expVal, ref * EPS); } } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double expVal = (x0Keys[i] + 2.); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(resX1[i][j], expVal, ref * EPS); } } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { assertEquals(resX0Twice[i][j], 0., EPS); } } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { assertEquals(resX1Twice[i][j], 0., EPS); } } { final double expVal = (x0Keys[1] + 2.) * (x1Keys[2] + 5.); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Keys[1], x1Keys[2]), expVal, ref * EPS); } { final double expVal = (x0Keys[23] + 2.) * (x1Keys[20] + 5.); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Keys[23], x1Keys[20]), expVal, ref * EPS); } } /** * */ @Test public void generalTest() { double[] x0Values = new double[] {1., 2., 3., 4. }; double[] x1Values = new double[] {-1., 0., 1., 2., 3., 5. }; final int n0Data = x0Values.length; final int n1Data = x1Values.length; double[][] yValues = new double[n0Data][n1Data]; for (int i = 0; i < n0Data; ++i) { for (int j = 0; j < n1Data; ++j) { yValues[i][j] = (x0Values[i] + 1.) * (x0Values[i] + 5.) * (x0Values[i] + 2.) * (x1Values[j] + 4.) * (x1Values[j] + 3.) * (x1Values[j] + 1.); } } PiecewisePolynomialInterpolator method = new NaturalSplineInterpolator(); MeshgridInterpolator2D interp = new MeshgridInterpolator2D(method); PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final int n0Keys = 10 * n0Data + 1; final int n1Keys = 10 * n1Data + 1; final double eps = 1.e-6; double[] x0Keys = new double[n0Keys]; double[] x1Keys = new double[n1Keys]; double[] x0KeysUp = new double[n0Keys]; double[] x1KeysUp = new double[n1Keys]; double[] x0KeysDown = new double[n0Keys]; double[] x1KeysDown = new double[n1Keys]; for (int i = 0; i < n0Keys; ++i) { x0Keys[i] = x0Values[0] + (x0Values[n0Data - 1] - x0Values[0]) / (n0Keys - 1) * i; x0KeysUp[i] = x0Keys[i] == 0. ? eps : x0Keys[i] * (1. + eps); x0KeysDown[i] = x0Keys[i] == 0. ? -eps : x0Keys[i] * (1. - eps); } for (int i = 0; i < n1Keys; ++i) { x1Keys[i] = x1Values[0] + (x1Values[n1Data - 1] - x1Values[0]) / (n1Keys - 1) * i; x1KeysUp[i] = x1Keys[i] == 0. ? eps : x1Keys[i] * (1. + eps); x1KeysDown[i] = x1Keys[i] == 0. ? -eps : x1Keys[i] * (1. - eps); } final double[][] knotsRes = interp.interpolate(x0Values, x1Values, yValues, x0Values, x1Values).getData(); final double[][] res = interp.interpolate(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); final double[][] resX0 = interp.differentiateX0(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); final double[][] resX1 = interp.differentiateX1(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); final double[][] resX0Twice = interp.differentiateX0Twice(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); final double[][] resX1Twice = interp.differentiateX1Twice(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); final double[][] resTran = OG_ALGEBRA.getTranspose(interp.interpolate(x1Values, x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData(), x1Keys, x0Keys)).getData(); final double[][] resX0Tran = OG_ALGEBRA.getTranspose(interp.differentiateX1(x1Values, x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData(), x1Keys, x0Keys)).getData(); final double[][] resX1Tran = OG_ALGEBRA.getTranspose(interp.differentiateX0(x1Values, x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData(), x1Keys, x0Keys)).getData(); final double[][] resX0TwiceTran = OG_ALGEBRA.getTranspose(interp.differentiateX1Twice(x1Values, x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData(), x1Keys, x0Keys)) .getData(); final double[][] resX1TwiceTran = OG_ALGEBRA.getTranspose(interp.differentiateX0Twice(x1Values, x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData(), x1Keys, x0Keys)) .getData(); for (int i = 0; i < n0Data; ++i) { for (int j = 0; j < n1Data; ++j) { double ref = Math.abs(yValues[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(yValues[i][j]); assertEquals(knotsRes[i][j], yValues[i][j], EPS * ref); } } { double ref = Math.abs(yValues[1][2]) < 0.1 * EPS ? 0.1 : Math.abs(yValues[1][2]); assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Values[1], x1Values[2]), yValues[1][2], EPS * ref); } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { double ref = Math.abs(res[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(res[i][j]); assertEquals(res[i][j], resTran[i][j], EPS * ref); ref = Math.abs(resX0[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(resX0[i][j]); assertEquals(resX0[i][j], resX0Tran[i][j], EPS * ref); ref = Math.abs(resX1[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(resX1[i][j]); assertEquals(resX1[i][j], resX1Tran[i][j], EPS * ref); ref = Math.abs(resX0Twice[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(resX0Twice[i][j]); assertEquals(resX0Twice[i][j], resX0TwiceTran[i][j], EPS * ref); ref = Math.abs(resX1Twice[i][j]) < 0.1 * EPS ? 0.1 : Math.abs(resX1Twice[i][j]); assertEquals(resX1Twice[i][j], resX1TwiceTran[i][j], EPS * ref); } } { final double val = func.differentiate(method.interpolate(x1Values, yValues[1]), x1Keys[2]).getData()[0]; final double resVal = interp.differentiateX1(x0Values, x1Values, yValues, x0Values[1], x1Keys[2]); final double ref = Math.abs(val) < 0.1 * EPS ? 0.1 : Math.abs(val); assertEquals(resVal, val, EPS * ref); } { final double val = func.differentiate(method.interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()[1]), x0Keys[2]).getData()[0]; final double resVal = interp.differentiateX0(x0Values, x1Values, yValues, x0Keys[2], x1Values[1]); final double ref = Math.abs(val) < 0.1 * EPS ? 0.1 : Math.abs(val); assertEquals(resVal, val, EPS * ref); } { final double val = func.differentiateTwice(method.interpolate(x1Values, yValues[1]), x1Keys[2]).getData()[0]; final double resVal = interp.differentiateX1Twice(x0Values, x1Values, yValues, x0Values[1], x1Keys[2]); final double ref = Math.abs(val) < 0.1 * EPS ? 0.1 : Math.abs(val); assertEquals(resVal, val, EPS * ref); } { final double val = func.differentiateTwice(method.interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()[1]), x0Keys[2]).getData()[0]; final double resVal = interp.differentiateX0Twice(x0Values, x1Values, yValues, x0Keys[2], x1Values[1]); final double ref = Math.abs(val) < 0.1 * EPS ? 0.1 : Math.abs(val); assertEquals(resVal, val, EPS * ref); } } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void notTwoMethodsTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; MeshgridInterpolator2D interp = new MeshgridInterpolator2D(new PiecewisePolynomialInterpolator[] {new CubicSplineInterpolator() }); interp.interpolate(x0Values, x1Values, yValues, x0Values, x1Values); } }