All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.math.impl.interpolation.CubicSplineClampedSolver Maven / Gradle / Ivy

There is a newer version: 2.12.46
Show newest version
/*
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.math.impl.interpolation;

import com.opengamma.strata.collect.array.DoubleMatrix;

/**
 * Solves cubic spline problem with clamped endpoint conditions, where the first derivative is specified at endpoints.
 */
public class CubicSplineClampedSolver extends CubicSplineSolver {

  private double[] _iniConds;
  private double[] _finConds;
  private double _iniCondUse;
  private double _finCondUse;

  /**
   * Constructor for a one-dimensional problem.
   * @param iniCond Left endpoint condition
   * @param finCond Right endpoint condition
   */
  public CubicSplineClampedSolver(final double iniCond, final double finCond) {

    _iniCondUse = iniCond;
    _finCondUse = finCond;
  }

  /**
   * Constructor for a multi-dimensional problem.
   * @param iniConds Set of left endpoint conditions
   * @param finConds Set of right endpoint conditions 
   */
  public CubicSplineClampedSolver(final double[] iniConds, final double[] finConds) {

    _iniConds = iniConds;
    _finConds = finConds;
  }

  @Override
  public DoubleMatrix solve(final double[] xValues, final double[] yValues) {

    final double[] intervals = getDiffs(xValues);

    return getCommonSplineCoeffs(xValues, yValues, intervals, matrixEqnSolver(getMatrix(intervals), getVector(yValues, intervals)));
  }

  @Override
  public DoubleMatrix[] solveWithSensitivity(final double[] xValues, final double[] yValues) {
    final double[] intervals = getDiffs(xValues);
    final double[][] toBeInv = getMatrix(intervals);
    final double[] vector = getVector(yValues, intervals);
    final double[][] vecSensitivity = getVectorSensitivity(intervals);

    return getCommonCoefficientWithSensitivity(xValues, yValues, intervals, toBeInv, vector, vecSensitivity);
  }

  @Override
  public DoubleMatrix[] solveMultiDim(final double[] xValues, final DoubleMatrix yValuesMatrix) {
    final int dim = yValuesMatrix.rowCount();
    DoubleMatrix[] coefMatrix = new DoubleMatrix[dim];

    for (int i = 0; i < dim; ++i) {
      resetConds(i);
      coefMatrix[i] = solve(xValues, yValuesMatrix.row(i).toArray());
    }

    return coefMatrix;
  }

  /**
   * Reset endpoint conditions.
   * @param i   the index
   */
  private void resetConds(final int i) {
    _iniCondUse = _iniConds[i];
    _finCondUse = _finConds[i];
  }

  /**
   * Cubic spline is obtained by solving a linear problem Ax=b where A is a square matrix and x,b are vector
   * @param intervals {xValues[1]-xValues[0], xValues[2]-xValues[1],...}
   * @return Matrix A
   */
  private double[][] getMatrix(final double[] intervals) {

    final int nData = intervals.length + 1;
    double[][] res = new double[nData][nData];

    res = getCommonMatrixElements(intervals);
    res[0][0] = 2. * intervals[0];
    res[0][1] = intervals[0];
    res[nData - 1][nData - 2] = intervals[nData - 2];
    res[nData - 1][nData - 1] = 2. * intervals[nData - 2];
    return res;
  }

  /**
   * Cubic spline is obtained by solving a linear problem Ax=b where A is a square matrix and x,b are vector
   * @param yValues Y Values of data
   * @param intervals {xValues[1]-xValues[0], xValues[2]-xValues[1],...}
   * @return Vector b
   */
  private double[] getVector(final double[] yValues, final double[] intervals) {

    final int nData = yValues.length;
    double[] res = new double[nData];
    res = getCommonVectorElements(yValues, intervals);

    res[0] = 6. * yValues[1] / intervals[0] - 6. * yValues[0] / intervals[0] - 6. * _iniCondUse;
    res[nData - 1] = 6. * _finCondUse - 6. * yValues[nData - 1] / intervals[nData - 2] + 6. * yValues[nData - 2] / intervals[nData - 2];

    return res;
  }

  private double[][] getVectorSensitivity(final double[] intervals) {

    final int nData = intervals.length + 1;
    double[][] res = new double[nData][nData];
    res = getCommonVectorSensitivity(intervals);

    res[0][0] = -6. / intervals[0];
    res[0][1] = 6. / intervals[0];
    res[nData - 1][nData - 1] = -6. / intervals[nData - 2];
    res[nData - 1][nData - 2] = 6. / intervals[nData - 2];

    return res;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy