ExponentialGrid.java
package net.finmath.finitedifference.grids;
/**
* Non-uniform exponential grid between {@code minimumValue} and {@code
* maximumValue}.
*
* <p>
* The grid points are distributed exponentially, with density concentrated near
* {@code minimumValue} or {@code maximumValue} depending on the parameter
* {@code alpha}.
* </p>
*
* <p>
* If {@code alpha = 0}, the grid reduces to a uniform grid.
* </p>
*
* <p>
* The grid is generated by transforming a uniform grid on {@code [0,1]}
* through an exponential mapping.
* </p>
*
* @author Michela Birtele
*/
public class ExponentialGrid 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 alpha.
*/
private final double alpha;
/**
* The grid.
*/
private double[] grid;
/**
* The delta.
*/
private double[] delta;
/**
* Constructs an exponential grid with the specified parameters.
*
* @param numberOfSteps The number of intervals in the grid.
* @param minimumValue The lower bound of the grid interval.
* @param maximumValue The upper bound of the grid interval.
* @param alpha Parameter controlling grid density:
* <ul>
* <li>If {@code alpha > 0}, points cluster near {@code maximumValue}.</li>
* <li>If {@code alpha < 0}, points cluster near {@code minimumValue}.</li>
* <li>If {@code alpha = 0}, the grid is uniform.</li>
* </ul>
*/
public ExponentialGrid(
final int numberOfSteps,
final double minimumValue,
final double maximumValue,
final double alpha) {
this.numberOfSteps = numberOfSteps;
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
this.alpha = alpha;
}
/**
* Generates the exponential grid points.
*/
private void generateGrid() {
grid = new double[numberOfSteps + 1];
final Grid uniformGrid = new UniformGrid(numberOfSteps, 0.0, 1.0);
final double[] x = uniformGrid.getGrid();
final double eta;
final double theta;
if (alpha == 0.0) {
eta = maximumValue - minimumValue;
theta = minimumValue;
} else {
eta = (maximumValue - minimumValue) / (Math.exp(alpha) - 1.0);
theta = minimumValue - eta;
}
for (int i = 0; i <= numberOfSteps; i++) {
grid[i] = theta + eta * Math.exp(alpha * x[i]);
}
}
/**
* Generates the spacing (delta) array as differences between
* consecutive grid points.
*
* @param vector Array of values at grid points (usually the grid itself).
*/
private void generateDelta(final double[] vector) {
if (grid == null) {
generateGrid();
}
delta = new double[numberOfSteps];
for (int i = 0; i < vector.length - 1; i++) {
delta[i] = vector[i + 1] - vector[i];
}
}
/**
* Returns the grid points, generating them if necessary.
*
* @return The exponentially distributed grid points.
*/
@Override
public double[] getGrid() {
if (grid == null) {
generateGrid();
}
return grid;
}
/**
* Returns the spacing between grid points, generating it if necessary.
*
* @param vector Array of values at grid points (usually the grid itself).
* @return The spacing between consecutive grid points.
*/
@Override
public double[] getDelta(final double[] vector) {
if (delta == null) {
generateDelta(vector);
}
return delta;
}
}