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

Java tutorial

Introduction

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

Source

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

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.math.FunctionUtils;
import com.opengamma.analytics.math.TrigonometricFunctionUtils;
import com.opengamma.util.ArgumentChecker;

/** 
       
 */
public class HyperbolicMeshing extends MeshingFunction {

    private final UniformMeshing _um;
    private final double[] _fpValues;
    private final double _alpha;
    private final double _beta;
    private final double _gamma;
    private final double _delta;
    private final double _l;
    private final double _r;

    /**
     * Creates a non-uniform set of points according to the formula x_i = alpha * beta*Sinh(i/N*gamma + delta), where the points run from 
     * x_0 to x_N (i.e. there are N+1 points) and the highest concentration is around some specified point (e.g. the strike for solving option problems)
     * @param xMin The value of x_0
     * @param xMax The value of x_N  
     * @param xCent The value where the concentration of points is highest (<b>Note</b> there is no guarantee the a point will correspond exactly 
     * with this value)
     * @param nPoints Number of Points (equal to N+1 in the above formula)
     * @param beta Bunching parameter. A value great than zero. Very small values gives a very high density of points around the specified point, with the
     * density quickly falling away in both directions (the total number of points is fixed), while the distribution tends to uniform for large values. Value 
     * greater than 1 are fairly uniform
     */
    public HyperbolicMeshing(final double xMin, final double xMax, final double xCent, final int nPoints,
            final double beta) {
        super(nPoints);
        Validate.isTrue(xMax > xMin, "need xMax > xMin");
        Validate.isTrue(xMax >= xCent && xCent >= xMin, "need xCent between upper and lower bounds");
        Validate.isTrue(beta > 0, "need beta > 0");

        _l = xMin;
        _r = xMax;
        _alpha = xCent;
        _beta = beta * (xMax - xMin);
        _delta = TrigonometricFunctionUtils.asinh((xMin - xCent) / _beta);
        _gamma = (TrigonometricFunctionUtils.asinh((xMax - xCent) / _beta) - _delta);
        _um = new UniformMeshing(nPoints);
        _fpValues = null;
    }

    public HyperbolicMeshing(final double xMin, final double xMax, final double xCent, final int nPoints,
            final double beta, final double[] fixedPoints) {
        super(nPoints);
        Validate.isTrue(xMax > xMin, "need xMax > xMin");
        Validate.isTrue(xMax >= xCent && xCent >= xMin, "need xCent between upper and lower bounds");
        Validate.isTrue(beta > 0, "need beta > 0");
        ArgumentChecker.notNull(fixedPoints, "null fixedPoints");

        _l = xMin;
        _r = xMax;
        _alpha = xCent;
        _beta = beta * (xMax - xMin);
        _delta = TrigonometricFunctionUtils.asinh((xMin - xCent) / _beta);
        _gamma = (TrigonometricFunctionUtils.asinh((xMax - xCent) / _beta) - _delta);

        _fpValues = FunctionUtils.unique(fixedPoints);
        int m = _fpValues.length;
        final double[] fp = new double[m];
        for (int ii = 0; ii < m; ii++) {
            fp[ii] = (TrigonometricFunctionUtils.asinh((_fpValues[ii] - _alpha) / _beta) - _delta) / _gamma;
        }

        _um = new UniformMeshing(nPoints, fp);
    }

    @Override
    public Double evaluate(Integer i) {
        Validate.isTrue(i >= 0 && i < getNumberOfPoints(), "i out of range");
        if (i == 0) {
            return _l;
        }
        if (i == getNumberOfPoints() - 1) {
            return _r;
        }

        //short cut if required point is one of the specified fixed points 
        if (_fpValues != null) {
            int index = _um.getFixedPointIndex(i);
            if (index >= 0) {
                return _fpValues[index];
            }
        }

        final double z = _um.evaluate(i);
        return _alpha + _beta * Math.sinh(_gamma * z + _delta);
    }

}