/** * 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 com.opengamma.analytics.math.function.PiecewisePolynomialFunction1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.util.ArgumentChecker; /** * 2D interpolator for gridded data using 1D piecewise polynomial spline interpolators. * Given a set of data (x0Values_i, x1Values_j, yValues_{ij}), find values, first derivatives and second derivatives of the corresponding interpolant at (x0Keys_k, x1Keys_l). */ public class MeshgridInterpolator2D { private PiecewisePolynomialInterpolator[] _method; /** * Constructor which can take different methods for x0 and x1 * @param method Choose 2 of {@link PiecewisePolynomialInterpolator} */ public MeshgridInterpolator2D(final PiecewisePolynomialInterpolator[] method) { ArgumentChecker.notNull(method, "method"); ArgumentChecker.isTrue(method.length == 2, "two methods should be chosen"); _method = new PiecewisePolynomialInterpolator[2]; for (int i = 0; i < 2; ++i) { _method[i] = method[i]; } } /** * Constructor using the same interpolation method for x0 and x1 * @param method {@link PiecewisePolynomialInterpolator} */ public MeshgridInterpolator2D(final PiecewisePolynomialInterpolator method) { _method = new PiecewisePolynomialInterpolator[] {method, method }; } /** * @param x0Values * @param x1Values * @param yValues * @param x0Key * @param x1Key * @return Value of 2D interpolant at (x0Key, x1Key) */ public double interpolate(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double x0Key, final double x1Key) { final double[] interpX1 = _method[1].interpolate(x1Values, yValues, x1Key).getData(); return _method[0].interpolate(x0Values, interpX1, x0Key); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Keys * @param x1Keys * @return Values of 2D interpolant at (x0Key_i, x1Keys_j) */ public DoubleMatrix2D interpolate(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double[] x0Keys, final double[] x1Keys) { final double[][] interpX1 = OG_ALGEBRA.getTranspose(_method[1].interpolate(x1Values, yValues, x1Keys)).getData(); return OG_ALGEBRA.getTranspose(_method[0].interpolate(x0Values, interpX1, x0Keys)); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Key * @param x1Key * @return Value of first derivative with respect to x0 at (x0Key, x1Key) */ public double differentiateX0(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double x0Key, final double x1Key) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[] interpX0Diff = func.differentiate(_method[0].interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()), x0Key).getData(); return _method[1].interpolate(x1Values, interpX0Diff, x1Key); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Keys * @param x1Keys * @return Values of first derivative with respect to x0 at (x0Key_i, x1Keys_j) */ public DoubleMatrix2D differentiateX0(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double[] x0Keys, final double[] x1Keys) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[][] interpX0Diff = OG_ALGEBRA.getTranspose(func.differentiate(_method[0].interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()), x0Keys)).getData(); return _method[1].interpolate(x1Values, interpX0Diff, x1Keys); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Key * @param x1Key * @return Value of second derivative with respect to x0 at (x0Key, x1Key) */ public double differentiateX0Twice(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double x0Key, final double x1Key) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[] interpX0Diff = func.differentiateTwice(_method[0].interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()), x0Key).getData(); return _method[1].interpolate(x1Values, interpX0Diff, x1Key); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Keys * @param x1Keys * @return Values of second derivative with respect to x0 at (x0Key_i, x1Keys_j) */ public DoubleMatrix2D differentiateX0Twice(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double[] x0Keys, final double[] x1Keys) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[][] interpX0Diff = OG_ALGEBRA.getTranspose(func.differentiateTwice(_method[0].interpolate(x0Values, OG_ALGEBRA.getTranspose(new DoubleMatrix2D(yValues)).getData()), x0Keys)) .getData(); return _method[1].interpolate(x1Values, interpX0Diff, x1Keys); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Key * @param x1Key * @return Value of first derivative with respect to x1 at (x0Key, x1Key) */ public double differentiateX1(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double x0Key, final double x1Key) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[] interpX1Diff = func.differentiate(_method[1].interpolate(x1Values, yValues), x1Key).getData(); return _method[0].interpolate(x0Values, interpX1Diff, x0Key); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Keys * @param x1Keys * @return Values of first derivative with respect to x1 at (x0Key_i, x1Keys_j) */ public DoubleMatrix2D differentiateX1(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double[] x0Keys, final double[] x1Keys) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[][] interpX1Diff = OG_ALGEBRA.getTranspose(func.differentiate(_method[1].interpolate(x1Values, yValues), x1Keys)).getData(); return OG_ALGEBRA.getTranspose(_method[0].interpolate(x0Values, interpX1Diff, x0Keys)); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Key * @param x1Key * @return Value of second derivative with respect to x1 at (x0Key, x1Key) */ public double differentiateX1Twice(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double x0Key, final double x1Key) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[] interpX1Diff = func.differentiateTwice(_method[1].interpolate(x1Values, yValues), x1Key).getData(); return _method[0].interpolate(x0Values, interpX1Diff, x0Key); } /** * @param x0Values * @param x1Values * @param yValues * @param x0Keys * @param x1Keys * @return Values of second derivative with respect to x1 at (x0Key_i, x1Keys_j) */ public DoubleMatrix2D differentiateX1Twice(final double[] x0Values, final double[] x1Values, final double[][] yValues, final double[] x0Keys, final double[] x1Keys) { final PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D(); final double[][] interpX1Diff = OG_ALGEBRA.getTranspose(func.differentiateTwice(_method[1].interpolate(x1Values, yValues), x1Keys)).getData(); return OG_ALGEBRA.getTranspose(_method[0].interpolate(x0Values, interpX1Diff, x0Keys)); } }