FDM3DGridUtil.java

package net.finmath.finitedifference.solvers.adi;

/**
 * Utility methods for indexing and boundary handling on a three-dimensional
 * grid.
 *
 * <p>
 * The flattening convention is
 * </p>
 * <pre>
 * k = i0 + n0 * (i1 + n1 * i2)
 * </pre>
 *
 * <p>
 * This class is intentionally stateless and generic.
 * </p>
 *
 * @author Alessandro Gnoatto
 */
public final class FDM3DGridUtil {

	private FDM3DGridUtil() {
	}

	/**
	 * Performs the operation.
	 *
	 * @param i0 The value.
	 * @param i1 The value.
	 * @param i2 The value.
	 * @param n0 The value.
	 * @param n1 The value.
	 * @return The value.
	 */
	public static int flatten(
			final int i0,
			final int i1,
			final int i2,
			final int n0,
			final int n1) {
		return i0 + n0 * (i1 + n1 * i2);
	}

	/**
	 * Performs the operation.
	 *
	 * @param flatIndex The value.
	 * @param n0 The value.
	 * @param n1 The value.
	 * @param n2 The value.
	 * @return The value.
	 */
	public static int[] unflatten(
			final int flatIndex,
			final int n0,
			final int n1,
			final int n2) {

		final int n = n0 * n1 * n2;
		if (flatIndex < 0 || flatIndex >= n) {
			throw new IllegalArgumentException("flatIndex out of range.");
		}

		final int i2 = flatIndex / (n0 * n1);
		final int remainder = flatIndex - i2 * n0 * n1;
		final int i1 = remainder / n0;
		final int i0 = remainder - i1 * n0;

		return new int[] {i0, i1, i2 };
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i0 The value.
	 * @return The value.
	 */
	public static boolean isOnLowerBoundaryFirstDirection(final int i0) {
		return i0 == 0;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i0 The value.
	 * @param n0 The value.
	 * @return The value.
	 */
	public static boolean isOnUpperBoundaryFirstDirection(final int i0, final int n0) {
		return i0 == n0 - 1;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i1 The value.
	 * @return The value.
	 */
	public static boolean isOnLowerBoundarySecondDirection(final int i1) {
		return i1 == 0;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i1 The value.
	 * @param n1 The value.
	 * @return The value.
	 */
	public static boolean isOnUpperBoundarySecondDirection(final int i1, final int n1) {
		return i1 == n1 - 1;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i2 The value.
	 * @return The value.
	 */
	public static boolean isOnLowerBoundaryThirdDirection(final int i2) {
		return i2 == 0;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i2 The value.
	 * @param n2 The value.
	 * @return The value.
	 */
	public static boolean isOnUpperBoundaryThirdDirection(final int i2, final int n2) {
		return i2 == n2 - 1;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i0 The value.
	 * @param i1 The value.
	 * @param i2 The value.
	 * @param n0 The value.
	 * @param n1 The value.
	 * @param n2 The value.
	 * @return The value.
	 */
	public static boolean isOnAnyBoundary(
			final int i0,
			final int i1,
			final int i2,
			final int n0,
			final int n1,
			final int n2) {
		return i0 == 0 || i0 == n0 - 1
				|| i1 == 0 || i1 == n1 - 1
				|| i2 == 0 || i2 == n2 - 1;
	}

	/**
	 * Returns whether the condition holds.
	 *
	 * @param i0 The value.
	 * @param i1 The value.
	 * @param i2 The value.
	 * @param n0 The value.
	 * @param n1 The value.
	 * @param n2 The value.
	 * @return The value.
	 */
	public static boolean isInteriorPoint(
			final int i0,
			final int i1,
			final int i2,
			final int n0,
			final int n1,
			final int n2) {
		return i0 > 0 && i0 < n0 - 1
				&& i1 > 0 && i1 < n1 - 1
				&& i2 > 0 && i2 < n2 - 1;
	}

	/**
	 * Performs the operation.
	 *
	 * @param n0 The value.
	 * @param n1 The value.
	 * @param n2 The value.
	 */
	public static void validateGridShape(final int n0, final int n1, final int n2) {
		if (n0 < 2 || n1 < 2 || n2 < 2) {
			throw new IllegalArgumentException("All grid directions must have at least two nodes.");
		}
	}

	/**
	 * Performs the operation.
	 *
	 * @param i0 The value.
	 * @param i1 The value.
	 * @param i2 The value.
	 * @param n0 The value.
	 * @param n1 The value.
	 * @param n2 The value.
	 */
	public static void validateIndex(
			final int i0,
			final int i1,
			final int i2,
			final int n0,
			final int n1,
			final int n2) {

		if (i0 < 0 || i0 >= n0) {
			throw new IllegalArgumentException("Index i0 out of range.");
		}
		if (i1 < 0 || i1 >= n1) {
			throw new IllegalArgumentException("Index i1 out of range.");
		}
		if (i2 < 0 || i2 >= n2) {
			throw new IllegalArgumentException("Index i2 out of range.");
		}
	}
}