// For every knot (xval[i], yval[j]) of the grid, calculate corrected
// values zY_1
final double[][] zY_1 = new double[xLen][yLen];
for (int j = 0; j < yLen; j++) {
final PolynomialSplineFunction f = ySplineX[j];
for (int i = 0; i < xLen; i++) {
zY_1[i][j] = f.value(xval[i]);
}
}
// For each line x[i] (0 <= i < xLen), construct a 1D spline with
// respect to variable y generated by array zY_1[i]
final PolynomialSplineFunction[] xSplineY = new PolynomialSplineFunction[xLen];
for (int i = 0; i < xLen; i++) {
xSplineY[i] = spInterpolator.interpolate(yval, zY_1[i]);
}
// For every knot (xval[i], yval[j]) of the grid, calculate corrected
// values zY_2
final double[][] zY_2 = new double[xLen][yLen];
for (int i = 0; i < xLen; i++) {
final PolynomialSplineFunction f = xSplineY[i];
for (int j = 0; j < yLen; j++) {
zY_2[i][j] = f.value(yval[j]);
}
}
// Partial derivatives with respect to x at the grid knots
final double[][] dZdX = new double[xLen][yLen];
for (int j = 0; j < yLen; j++) {
final UnivariateRealFunction f = ySplineX[j].derivative();
for (int i = 0; i < xLen; i++) {
dZdX[i][j] = f.value(xval[i]);
}
}
// Partial derivatives with respect to y at the grid knots
final double[][] dZdY = new double[xLen][yLen];
for (int i = 0; i < xLen; i++) {
final UnivariateRealFunction f = xSplineY[i].derivative();
for (int j = 0; j < yLen; j++) {
dZdY[i][j] = f.value(yval[j]);
}
}
// Cross partial derivatives
final double[][] dZdXdY = new double[xLen][yLen];