com.opengamma.analytics.financial.model.finitedifference.ExtendedCoupledFiniteDifference.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.finitedifference.ExtendedCoupledFiniteDifference.java

Source

/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.model.finitedifference;

import java.util.Arrays;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.math.linearalgebra.Decomposition;
import com.opengamma.analytics.math.linearalgebra.DecompositionResult;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.surface.Surface;

/**
 *
 */
@SuppressWarnings("deprecation")
public class ExtendedCoupledFiniteDifference extends CoupledFiniteDifference {

    public ExtendedCoupledFiniteDifference(final double theta) {
        super(theta, true);
    }

    public PDEFullResults1D[] solve(final ExtendedCoupledPDEDataBundle pdeData1,
            final ExtendedCoupledPDEDataBundle pdeData2, final PDEGrid1D grid,
            final BoundaryCondition lowerBoundary1, final BoundaryCondition upperBoundary1,
            final BoundaryCondition lowerBoundary2, final BoundaryCondition upperBoundary2,
            @SuppressWarnings("unused") final Surface<Double, Double, Double> freeBoundary) {

        Validate.notNull(pdeData1, "pde1 data");
        Validate.notNull(pdeData2, "pde2 data");
        final int tNodes = grid.getNumTimeNodes();
        final int xNodes = grid.getNumSpaceNodes();
        final double theta = getTheta();
        final Decomposition<?> dcomp = getDecomposition();

        double[] f = new double[2 * xNodes];
        final double[][] full1 = new double[tNodes][xNodes];
        final double[][] full2 = new double[tNodes][xNodes];

        final double[] q = new double[2 * xNodes];
        final double[][] m = new double[2 * xNodes][2 * xNodes];

        final double[][] a1 = new double[2][xNodes - 2];
        final double[][] a2 = new double[2][xNodes - 2];
        final double[][] b1 = new double[2][xNodes - 2];
        final double[][] b2 = new double[2][xNodes - 2];
        final double[][] c1 = new double[2][xNodes - 2];
        final double[][] c2 = new double[2][xNodes - 2];
        final double[][] alpha1 = new double[2][xNodes];
        final double[][] alpha2 = new double[2][xNodes];
        final double[][] beta1 = new double[2][xNodes];
        final double[][] beta2 = new double[2][xNodes];

        final double lambda1 = pdeData1.getCoupling();
        final double lambda2 = pdeData2.getCoupling();

        //    final double omega = 1.5;
        //    final int oldCount = 0;
        //    final boolean omegaIncrease = false;

        double dt, t1, t2, x;
        double[] x1st, x2nd;

        for (int i = 0; i < xNodes; i++) {
            f[i] = pdeData1.getInitialCondition(grid.getSpaceNode(i));
        }
        for (int i = 0; i < xNodes; i++) {
            f[i + xNodes] = pdeData2.getInitialCondition(grid.getSpaceNode(i));
        }

        full1[0] = Arrays.copyOfRange(f, 0, xNodes);
        full2[0] = Arrays.copyOfRange(f, xNodes, 2 * xNodes);

        for (int i = 0; i < xNodes - 2; i++) {
            x = grid.getSpaceNode(i + 1);
            a1[0][i] = pdeData1.getA(0, x);
            b1[0][i] = pdeData1.getB(0, x);
            c1[0][i] = pdeData1.getC(0, x);
            a1[1][i] = pdeData2.getA(0, x);
            b1[1][i] = pdeData2.getB(0, x);
            c1[1][i] = pdeData2.getC(0, x);
        }

        for (int i = 0; i < xNodes; i++) {
            x = grid.getSpaceNode(i);
            alpha1[0][i] = pdeData1.getAlpha(0, x);
            beta1[0][i] = pdeData1.getBeta(0, x);
            alpha1[1][i] = pdeData2.getAlpha(0, x);
            beta1[1][i] = pdeData2.getBeta(0, x);
        }

        final boolean first = true;
        DecompositionResult decompRes = null;

        for (int n = 1; n < tNodes; n++) {

            t1 = grid.getTimeNode(n - 1);
            t2 = grid.getTimeNode(n);
            dt = grid.getTimeStep(n - 1);

            for (int i = 0; i < xNodes; i++) {
                x = grid.getSpaceNode(i);
                alpha2[0][i] = pdeData1.getAlpha(t2, x);
                beta2[0][i] = pdeData1.getBeta(t2, x);
                alpha2[1][i] = pdeData2.getAlpha(t2, x);
                beta2[1][i] = pdeData2.getBeta(t2, x);
            }

            for (int i = 1; i < xNodes - 1; i++) {
                x = grid.getSpaceNode(i);
                x1st = grid.getFirstDerivativeCoefficients(i);
                x2nd = grid.getSecondDerivativeCoefficients(i);

                q[i] = f[i];
                q[i] -= (1 - theta) * dt
                        * (x2nd[0] * a1[0][i - 1] * alpha1[0][i - 1] + x1st[0] * b1[0][i - 1] * beta1[0][i - 1])
                        * f[i - 1];
                q[i] -= (1 - theta) * dt * (x2nd[1] * a1[0][i - 1] * alpha1[0][i]
                        + x1st[1] * b1[0][i - 1] * beta1[0][i] + c1[0][i - 1]) * f[i];
                q[i] -= (1 - theta) * dt
                        * (x2nd[2] * a1[0][i - 1] * alpha1[0][i + 1] + x1st[2] * b1[0][i - 1] * beta1[0][i + 1])
                        * f[i + 1];
                q[i] -= (1 - theta) * dt * lambda1 * f[i + xNodes];

                q[xNodes + i] = f[xNodes + i];
                q[xNodes + i] -= (1 - theta) * dt
                        * (x2nd[0] * a1[1][i - 1] * alpha1[1][i - 1] + x1st[0] * b1[1][i - 1] * beta1[1][i - 1])
                        * f[xNodes + i - 1];
                q[xNodes + i] -= (1 - theta) * dt * (x2nd[1] * a1[1][i - 1] * alpha1[1][i]
                        + x1st[1] * b1[1][i - 1] * beta1[1][i] + c1[1][i - 1]) * f[xNodes + i];
                q[xNodes + i] -= (1 - theta) * dt
                        * (x2nd[2] * a1[1][i - 1] * alpha1[1][i + 1] + x1st[2] * b1[1][i - 1] * beta1[1][i + 1])
                        * f[xNodes + i + 1];
                q[xNodes + i] -= (1 - theta) * dt * lambda2 * f[i];

                a2[0][i - 1] = pdeData1.getA(t2, x);
                b2[0][i - 1] = pdeData1.getB(t2, x);
                c2[0][i - 1] = pdeData1.getC(t2, x);
                a2[1][i - 1] = pdeData2.getA(t2, x);
                b2[1][i - 1] = pdeData2.getB(t2, x);
                c2[1][i - 1] = pdeData2.getC(t2, x);

                m[i][i - 1] = theta * dt
                        * (x2nd[0] * a2[0][i - 1] * alpha2[0][i - 1] + x1st[0] * b2[0][i - 1] * beta2[0][i - 1]);
                m[i][i] = 1 + theta * dt * (x2nd[1] * a2[0][i - 1] * alpha2[0][i]
                        + x1st[1] * b2[0][i - 1] * beta2[0][i] + c2[0][i - 1]);
                m[i][i + 1] = theta * dt
                        * (x2nd[2] * a2[0][i - 1] * alpha2[0][i + 1] + x1st[2] * b2[0][i - 1] * beta2[0][i + 1]);
                m[i][i + xNodes] = dt * theta * lambda1;

                m[xNodes + i][xNodes + i - 1] = theta * dt
                        * (x2nd[0] * a2[1][i - 1] * alpha2[1][i - 1] + x1st[0] * b2[1][i - 1] * beta2[1][i - 1]);
                m[xNodes + i][xNodes + i] = 1 + theta * dt * (x2nd[1] * a2[1][i - 1] * alpha2[1][i]
                        + x1st[1] * b2[1][i - 1] * beta2[1][i] + c2[1][i - 1]);
                m[xNodes + i][xNodes + i + 1] = theta * dt
                        * (x2nd[2] * a2[1][i - 1] * alpha2[1][i + 1] + x1st[2] * b2[1][i - 1] * beta2[1][i + 1]);
                m[xNodes + i][i] = dt * theta * lambda2;
            }

            double[] temp = lowerBoundary1.getLeftMatrixCondition(null, grid, t2);
            for (int k = 0; k < temp.length; k++) {
                m[0][k] = temp[k];
            }

            temp = upperBoundary1.getLeftMatrixCondition(null, grid, t2);
            for (int k = 0; k < temp.length; k++) {
                m[xNodes - 1][xNodes - temp.length + k] = temp[k];
            }

            temp = lowerBoundary2.getLeftMatrixCondition(null, grid, t2);
            for (int k = 0; k < temp.length; k++) {
                m[xNodes][xNodes + k] = temp[k];
            }

            temp = upperBoundary2.getLeftMatrixCondition(null, grid, t2);
            for (int k = 0; k < temp.length; k++) {
                m[2 * xNodes - 1][2 * xNodes - temp.length + k] = temp[k];
            }

            temp = lowerBoundary1.getRightMatrixCondition(null, grid, t1);
            double sum = 0;
            for (int k = 0; k < temp.length; k++) {
                sum += temp[k] * f[k];
            }
            q[0] = sum + lowerBoundary1.getConstant(null, t2);

            temp = upperBoundary1.getRightMatrixCondition(null, grid, t1);
            sum = 0;
            for (int k = 0; k < temp.length; k++) {
                sum += temp[k] * f[xNodes - 1 - k];
            }

            q[xNodes - 1] = sum + upperBoundary1.getConstant(null, t2);

            temp = lowerBoundary2.getRightMatrixCondition(null, grid, t1);
            sum = 0;
            for (int k = 0; k < temp.length; k++) {
                sum += temp[k] * f[k];
            }
            q[xNodes] = sum + lowerBoundary2.getConstant(null, t2);

            temp = upperBoundary2.getRightMatrixCondition(null, grid, t1);
            sum = 0;
            for (int k = 0; k < temp.length; k++) {
                sum += temp[k] * f[xNodes - 1 - k];
            }

            q[2 * xNodes - 1] = sum + upperBoundary2.getConstant(null, t2);

            if (first) {
                final DoubleMatrix2D mM = new DoubleMatrix2D(m);
                decompRes = dcomp.evaluate(mM);
                // first = false;
            }
            f = decompRes.solve(q);

            a1[0] = Arrays.copyOf(a2[0], xNodes - 2);
            b1[0] = Arrays.copyOf(b2[0], xNodes - 2);
            c1[0] = Arrays.copyOf(c2[0], xNodes - 2);
            alpha1[0] = Arrays.copyOf(alpha2[0], xNodes);
            beta1[0] = Arrays.copyOf(beta2[0], xNodes);
            a1[1] = Arrays.copyOf(a2[1], xNodes - 2);
            b1[1] = Arrays.copyOf(b2[1], xNodes - 2);
            c1[1] = Arrays.copyOf(c2[1], xNodes - 2);
            alpha1[1] = Arrays.copyOf(alpha2[1], xNodes);
            beta1[1] = Arrays.copyOf(beta2[1], xNodes);

            full1[n] = Arrays.copyOfRange(f, 0, xNodes);
            full2[n] = Arrays.copyOfRange(f, xNodes, 2 * xNodes);
        }
        final PDEFullResults1D[] res = new PDEFullResults1D[2];
        res[0] = new PDEFullResults1D(grid, full1);
        res[1] = new PDEFullResults1D(grid, full2);
        return res;
    }
}