final double omega = 0.5;
final double kx = 2;
final double ky = 1;
// Function values
TrivariateFunction f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.cos(omega * z - kx * x - ky * y);
}
};
double[][][] fval = new double[xval.length][yval.length][zval.length];
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial derivatives with respect to x
double[][][] dFdX = new double[xval.length][yval.length][zval.length];
TrivariateFunction dFdX_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.sin(omega * z - kx * x - ky * y) * kx;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
dFdX[i][j][k] = dFdX_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial derivatives with respect to y
double[][][] dFdY = new double[xval.length][yval.length][zval.length];
TrivariateFunction dFdY_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.sin(omega * z - kx * x - ky * y) * ky;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
dFdY[i][j][k] = dFdY_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial derivatives with respect to z
double[][][] dFdZ = new double[xval.length][yval.length][zval.length];
TrivariateFunction dFdZ_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return -a * FastMath.sin(omega * z - kx * x - ky * y) * omega;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
dFdZ[i][j][k] = dFdZ_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial second derivatives w.r.t. (x, y)
double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length];
TrivariateFunction d2FdXdY_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return -a * FastMath.cos(omega * z - kx * x - ky * y) * kx * ky;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
d2FdXdY[i][j][k] = d2FdXdY_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial second derivatives w.r.t. (x, z)
double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length];
TrivariateFunction d2FdXdZ_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.cos(omega * z - kx * x - ky * y) * kx * omega;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
d2FdXdZ[i][j][k] = d2FdXdZ_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial second derivatives w.r.t. (y, z)
double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length];
TrivariateFunction d2FdYdZ_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.cos(omega * z - kx * x - ky * y) * ky * omega;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
d2FdYdZ[i][j][k] = d2FdYdZ_f.value(xval[i], yval[j], zval[k]);
}
}
}
// Partial third derivatives
double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length];
TrivariateFunction d3FdXdYdZ_f = new TrivariateFunction() {
public double value(double x, double y, double z) {
return a * FastMath.sin(omega * z - kx * x - ky * y) * kx * ky * omega;
}
};
for (int i = 0; i < xval.length; i++) {
for (int j = 0; j < yval.length; j++) {
for (int k = 0; k < zval.length; k++) {
d3FdXdYdZ[i][j][k] = d3FdXdYdZ_f.value(xval[i], yval[j], zval[k]);
}
}
}
TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
fval, dFdX, dFdY, dFdZ,
d2FdXdY, d2FdXdZ, d2FdYdZ,
d3FdXdYdZ);
double x, y, z;
double expected, result;
x = 4;
y = -3;
z = 0;
expected = f.value(x, y, z);
result = tcf.value(x, y, z);
Assert.assertEquals("On sample point",
expected, result, 1e-14);
x = 4.5;
y = -1.5;
z = -4.25;
expected = f.value(x, y, z);
result = tcf.value(x, y, z);
Assert.assertEquals("Half-way between sample points (middle of the patch)",
expected, result, 0.1);
x = 3.5;
y = -3.5;
z = -10;
expected = f.value(x, y, z);
result = tcf.value(x, y, z);
Assert.assertEquals("Half-way between sample points (border of the patch)",
expected, result, 0.1);
}