GaussianGrid.java
package net.finmath.finitedifference.grids;
import net.finmath.functions.NormalDistribution;
/**
* Non-uniform grid based on the Gaussian (normal) distribution between
* {@code minimumValue} and {@code maximumValue}.
*
* <p>
* The grid points are distributed according to the cumulative distribution
* function (CDF) of a normal distribution with mean {@code centering} and
* standard deviation {@code sigma}. This results in a higher density of
* points near the {@code centering} value and sparser points further away.
* </p>
*
* <p>
* The grid is constructed by mapping uniformly spaced probabilities between
* the CDF values at {@code minimumValue} and {@code maximumValue} back to
* the original domain using the inverse CDF (quantile function).
* </p>
*
* @author Michela Birtele
*/
public class GaussianGrid extends AbstractGrid {
/**
* The number of steps.
*/
private final int numberOfSteps;
/**
* The minimum value.
*/
private final double minimumValue;
/**
* The maximum value.
*/
private final double maximumValue;
/**
* The centering.
*/
private final double centering;
/**
* The sigma.
*/
private final double sigma;
/**
* The grid.
*/
private double[] grid;
/**
* The delta.
*/
private double[] delta;
/**
* Constructs a Gaussian-distributed grid.
*
* @param numberOfSteps The number of intervals in the grid.
* @param minimumValue The lower bound of the grid.
* @param maximumValue The upper bound of the grid.
* @param centering The mean (center) of the Gaussian distribution.
* @param sigma The standard deviation controlling the spread
* around the centering.
*/
public GaussianGrid(
final int numberOfSteps,
final double minimumValue,
final double maximumValue,
final double centering,
final double sigma) {
super();
this.numberOfSteps = numberOfSteps;
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
this.centering = centering;
this.sigma = sigma;
}
/**
* Generates the grid points distributed according to the Gaussian distribution.
*/
private void generateGrid() {
grid = new double[numberOfSteps + 1];
final double pMin =
NormalDistribution.cumulativeDistribution(
(minimumValue - centering) / sigma);
final double pMax =
NormalDistribution.cumulativeDistribution(
(maximumValue - centering) / sigma);
for (int i = 0; i <= numberOfSteps; i++) {
final double p =
pMin + (i / (double) numberOfSteps) * (pMax - pMin);
grid[i] =
centering + sigma
* NormalDistribution.inverseCumulativeDistribution(p);
}
grid[0] = minimumValue;
grid[numberOfSteps] = maximumValue;
}
/**
* Computes the differences (delta) between consecutive grid points.
*
* @param vector Array of values at grid points (typically the grid itself).
*/
private void generateDelta(final double[] vector) {
delta = new double[numberOfSteps];
for (int i = 0; i < vector.length - 1; i++) {
delta[i] = vector[i + 1] - vector[i];
}
}
/**
* Returns the generated grid points, generating them if necessary.
*
* @return The grid points distributed via Gaussian quantiles.
*/
@Override
public double[] getGrid() {
if (grid == null) {
generateGrid();
}
return grid;
}
/**
* Returns the spacing (delta) between consecutive grid points,
* generating it if necessary.
*
* @param vector Array of values at grid points (usually the grid itself).
* @return The spacing between adjacent grid points.
*/
@Override
public double[] getDelta(final double[] vector) {
if (delta == null) {
generateDelta(vector);
}
return delta;
}
}