2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
17
package org.apache.commons.math.analysis.interpolation;
19
import org.apache.commons.math.FunctionEvaluationException;
20
import org.apache.commons.math.exception.DimensionMismatchException;
21
import org.apache.commons.math.util.FastMath;
22
import org.apache.commons.math.analysis.TrivariateRealFunction;
23
import org.junit.Assert;
24
import org.junit.Test;
27
* Testcase for the bicubic function.
29
* @version $Revision: 821626 $ $Date: 2009-10-04 23:57:30 +0200 (Sun, 04 Oct 2009) $
31
public final class TricubicSplineInterpolatingFunctionTest {
36
public void testPreconditions() {
37
double[] xval = new double[] {3, 4, 5, 6.5};
38
double[] yval = new double[] {-4, -3, -1, 2.5};
39
double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
40
double[][][] fval = new double[xval.length][yval.length][zval.length];
42
@SuppressWarnings("unused")
43
TrivariateRealFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
44
fval, fval, fval, fval,
45
fval, fval, fval, fval);
47
double[] wxval = new double[] {3, 2, 5, 6.5};
49
tcf = new TricubicSplineInterpolatingFunction(wxval, yval, zval,
50
fval, fval, fval, fval,
51
fval, fval, fval, fval);
52
Assert.fail("an exception should have been thrown");
53
} catch (IllegalArgumentException e) {
56
double[] wyval = new double[] {-4, -1, -1, 2.5};
58
tcf = new TricubicSplineInterpolatingFunction(xval, wyval, zval,
59
fval, fval, fval, fval,
60
fval, fval, fval, fval);
61
Assert.fail("an exception should have been thrown");
62
} catch (IllegalArgumentException e) {
65
double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5};
67
tcf = new TricubicSplineInterpolatingFunction(xval, yval, wzval,
68
fval, fval, fval, fval,
69
fval, fval, fval, fval);
70
Assert.fail("an exception should have been thrown");
71
} catch (IllegalArgumentException e) {
74
double[][][] wfval = new double[xval.length - 1][yval.length - 1][zval.length];
76
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
77
wfval, fval, fval, fval,
78
fval, fval, fval, fval);
79
Assert.fail("an exception should have been thrown");
80
} catch (DimensionMismatchException e) {
84
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
85
fval, wfval, fval, fval,
86
fval, fval, fval, fval);
87
Assert.fail("an exception should have been thrown");
88
} catch (DimensionMismatchException e) {
92
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
93
fval, fval, wfval, fval,
94
fval, fval, fval, fval);
95
Assert.fail("an exception should have been thrown");
96
} catch (DimensionMismatchException e) {
100
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
101
fval, fval, fval, wfval,
102
fval, fval, fval, fval);
103
Assert.fail("an exception should have been thrown");
104
} catch (DimensionMismatchException e) {
108
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
109
fval, fval, fval, fval,
110
wfval, fval, fval, fval);
111
Assert.fail("an exception should have been thrown");
112
} catch (DimensionMismatchException e) {
116
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
117
fval, fval, fval, fval,
118
fval, wfval, fval, fval);
119
Assert.fail("an exception should have been thrown");
120
} catch (DimensionMismatchException e) {
124
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
125
fval, fval, fval, fval,
126
fval, fval, wfval, fval);
127
Assert.fail("an exception should have been thrown");
128
} catch (DimensionMismatchException e) {
132
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
133
fval, fval, fval, fval,
134
fval, fval, fval, wfval);
135
Assert.fail("an exception should have been thrown");
136
} catch (DimensionMismatchException e) {
139
wfval = new double[xval.length][yval.length - 1][zval.length];
141
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
142
wfval, fval, fval, fval,
143
fval, fval, fval, fval);
144
Assert.fail("an exception should have been thrown");
145
} catch (DimensionMismatchException e) {
149
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
150
fval, wfval, fval, fval,
151
fval, fval, fval, fval);
152
Assert.fail("an exception should have been thrown");
153
} catch (DimensionMismatchException e) {
157
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
158
fval, fval, wfval, fval,
159
fval, fval, fval, fval);
160
Assert.fail("an exception should have been thrown");
161
} catch (DimensionMismatchException e) {
165
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
166
fval, fval, fval, wfval,
167
fval, fval, fval, fval);
168
Assert.fail("an exception should have been thrown");
169
} catch (DimensionMismatchException e) {
173
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
174
fval, fval, fval, fval,
175
wfval, fval, fval, fval);
176
Assert.fail("an exception should have been thrown");
177
} catch (DimensionMismatchException e) {
181
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
182
fval, fval, fval, fval,
183
fval, wfval, fval, fval);
184
Assert.fail("an exception should have been thrown");
185
} catch (DimensionMismatchException e) {
189
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
190
fval, fval, fval, fval,
191
fval, fval, wfval, fval);
192
Assert.fail("an exception should have been thrown");
193
} catch (DimensionMismatchException e) {
197
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
198
fval, fval, fval, fval,
199
fval, fval, fval, wfval);
200
Assert.fail("an exception should have been thrown");
201
} catch (DimensionMismatchException e) {
204
wfval = new double[xval.length][yval.length][zval.length - 1];
206
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
207
wfval, fval, fval, fval,
208
fval, fval, fval, fval);
209
Assert.fail("an exception should have been thrown");
210
} catch (DimensionMismatchException e) {
214
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
215
fval, wfval, fval, fval,
216
fval, fval, fval, fval);
217
Assert.fail("an exception should have been thrown");
218
} catch (DimensionMismatchException e) {
222
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
223
fval, fval, wfval, fval,
224
fval, fval, fval, fval);
225
Assert.fail("an exception should have been thrown");
226
} catch (DimensionMismatchException e) {
230
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
231
fval, fval, fval, wfval,
232
fval, fval, fval, fval);
233
Assert.fail("an exception should have been thrown");
234
} catch (DimensionMismatchException e) {
238
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
239
fval, fval, fval, fval,
240
wfval, fval, fval, fval);
241
Assert.fail("an exception should have been thrown");
242
} catch (DimensionMismatchException e) {
246
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
247
fval, fval, fval, fval,
248
fval, wfval, fval, fval);
249
Assert.fail("an exception should have been thrown");
250
} catch (DimensionMismatchException e) {
254
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
255
fval, fval, fval, fval,
256
fval, fval, wfval, fval);
257
Assert.fail("an exception should have been thrown");
258
} catch (DimensionMismatchException e) {
262
tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
263
fval, fval, fval, fval,
264
fval, fval, fval, wfval);
265
Assert.fail("an exception should have been thrown");
266
} catch (DimensionMismatchException e) {
269
Assert.assertNotNull(tcf); // Avoid Findbugs "dead store" warning
275
* f(x, y, z) = 2 x - 3 y - 4 z + 5
279
public void testPlane() throws FunctionEvaluationException {
280
double[] xval = new double[] {3, 4, 5, 6.5};
281
double[] yval = new double[] {-4, -3, -1, 2, 2.5};
282
double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
285
TrivariateRealFunction f = new TrivariateRealFunction() {
286
public double value(double x, double y, double z) {
287
return 2 * x - 3 * y - 4 * z + 5;
291
double[][][] fval = new double[xval.length][yval.length][zval.length];
293
for (int i = 0; i < xval.length; i++) {
294
for (int j = 0; j < yval.length; j++) {
295
for (int k = 0; k < zval.length; k++) {
296
fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
300
// Partial derivatives with respect to x
301
double[][][] dFdX = new double[xval.length][yval.length][zval.length];
302
for (int i = 0; i < xval.length; i++) {
303
for (int j = 0; j < yval.length; j++) {
304
for (int k = 0; k < zval.length; k++) {
309
// Partial derivatives with respect to y
310
double[][][] dFdY = new double[xval.length][yval.length][zval.length];
311
for (int i = 0; i < xval.length; i++) {
312
for (int j = 0; j < yval.length; j++) {
313
for (int k = 0; k < zval.length; k++) {
319
// Partial derivatives with respect to z
320
double[][][] dFdZ = new double[xval.length][yval.length][zval.length];
321
for (int i = 0; i < xval.length; i++) {
322
for (int j = 0; j < yval.length; j++) {
323
for (int k = 0; k < zval.length; k++) {
328
// Partial cross-derivatives
329
double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length];
330
double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length];
331
double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length];
332
double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length];
333
for (int i = 0; i < xval.length; i++) {
334
for (int j = 0; j < yval.length; j++) {
335
for (int k = 0; k < zval.length; k++) {
336
d2FdXdY[i][j][k] = 0;
337
d2FdXdZ[i][j][k] = 0;
338
d2FdYdZ[i][j][k] = 0;
339
d3FdXdYdZ[i][j][k] = 0;
344
TrivariateRealFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
345
fval, dFdX, dFdY, dFdZ,
346
d2FdXdY, d2FdXdZ, d2FdYdZ,
349
double expected, result;
354
expected = f.value(x, y, z);
355
result = tcf.value(x, y, z);
356
Assert.assertEquals("On sample point",
357
expected, result, 1e-15);
362
expected = f.value(x, y, z);
363
result = tcf.value(x, y, z);
364
Assert.assertEquals("Half-way between sample points (middle of the patch)",
365
expected, result, 0.3);
370
expected = f.value(x, y, z);
371
result = tcf.value(x, y, z);
372
Assert.assertEquals("Half-way between sample points (border of the patch)",
373
expected, result, 0.3);
379
* f(x, y, z) = a cos [ω z - k<sub>y</sub> x - k<sub>y</sub> y]
381
* with A = 0.2, ω = 0.5, k<sub>x</sub> = 2, k<sub>y</sub> = 1.
384
public void testWave() throws FunctionEvaluationException {
385
double[] xval = new double[] {3, 4, 5, 6.5};
386
double[] yval = new double[] {-4, -3, -1, 2, 2.5};
387
double[] zval = new double[] {-12, -8, -5.5, -3, 0, 4};
389
final double a = 0.2;
390
final double omega = 0.5;
395
TrivariateRealFunction f = new TrivariateRealFunction() {
396
public double value(double x, double y, double z) {
397
return a * FastMath.cos(omega * z - kx * x - ky * y);
401
double[][][] fval = new double[xval.length][yval.length][zval.length];
402
for (int i = 0; i < xval.length; i++) {
403
for (int j = 0; j < yval.length; j++) {
404
for (int k = 0; k < zval.length; k++) {
405
fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
410
// Partial derivatives with respect to x
411
double[][][] dFdX = new double[xval.length][yval.length][zval.length];
412
TrivariateRealFunction dFdX_f = new TrivariateRealFunction() {
413
public double value(double x, double y, double z) {
414
return a * FastMath.sin(omega * z - kx * x - ky * y) * kx;
417
for (int i = 0; i < xval.length; i++) {
418
for (int j = 0; j < yval.length; j++) {
419
for (int k = 0; k < zval.length; k++) {
420
dFdX[i][j][k] = dFdX_f.value(xval[i], yval[j], zval[k]);
425
// Partial derivatives with respect to y
426
double[][][] dFdY = new double[xval.length][yval.length][zval.length];
427
TrivariateRealFunction dFdY_f = new TrivariateRealFunction() {
428
public double value(double x, double y, double z) {
429
return a * FastMath.sin(omega * z - kx * x - ky * y) * ky;
432
for (int i = 0; i < xval.length; i++) {
433
for (int j = 0; j < yval.length; j++) {
434
for (int k = 0; k < zval.length; k++) {
435
dFdY[i][j][k] = dFdY_f.value(xval[i], yval[j], zval[k]);
440
// Partial derivatives with respect to z
441
double[][][] dFdZ = new double[xval.length][yval.length][zval.length];
442
TrivariateRealFunction dFdZ_f = new TrivariateRealFunction() {
443
public double value(double x, double y, double z) {
444
return -a * FastMath.sin(omega * z - kx * x - ky * y) * omega;
447
for (int i = 0; i < xval.length; i++) {
448
for (int j = 0; j < yval.length; j++) {
449
for (int k = 0; k < zval.length; k++) {
450
dFdZ[i][j][k] = dFdZ_f.value(xval[i], yval[j], zval[k]);
455
// Partial second derivatives w.r.t. (x, y)
456
double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length];
457
TrivariateRealFunction d2FdXdY_f = new TrivariateRealFunction() {
458
public double value(double x, double y, double z) {
459
return -a * FastMath.cos(omega * z - kx * x - ky * y) * kx * ky;
462
for (int i = 0; i < xval.length; i++) {
463
for (int j = 0; j < yval.length; j++) {
464
for (int k = 0; k < zval.length; k++) {
465
d2FdXdY[i][j][k] = d2FdXdY_f.value(xval[i], yval[j], zval[k]);
470
// Partial second derivatives w.r.t. (x, z)
471
double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length];
472
TrivariateRealFunction d2FdXdZ_f = new TrivariateRealFunction() {
473
public double value(double x, double y, double z) {
474
return a * FastMath.cos(omega * z - kx * x - ky * y) * kx * omega;
477
for (int i = 0; i < xval.length; i++) {
478
for (int j = 0; j < yval.length; j++) {
479
for (int k = 0; k < zval.length; k++) {
480
d2FdXdZ[i][j][k] = d2FdXdZ_f.value(xval[i], yval[j], zval[k]);
485
// Partial second derivatives w.r.t. (y, z)
486
double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length];
487
TrivariateRealFunction d2FdYdZ_f = new TrivariateRealFunction() {
488
public double value(double x, double y, double z) {
489
return a * FastMath.cos(omega * z - kx * x - ky * y) * ky * omega;
492
for (int i = 0; i < xval.length; i++) {
493
for (int j = 0; j < yval.length; j++) {
494
for (int k = 0; k < zval.length; k++) {
495
d2FdYdZ[i][j][k] = d2FdYdZ_f.value(xval[i], yval[j], zval[k]);
500
// Partial third derivatives
501
double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length];
502
TrivariateRealFunction d3FdXdYdZ_f = new TrivariateRealFunction() {
503
public double value(double x, double y, double z) {
504
return a * FastMath.sin(omega * z - kx * x - ky * y) * kx * ky * omega;
507
for (int i = 0; i < xval.length; i++) {
508
for (int j = 0; j < yval.length; j++) {
509
for (int k = 0; k < zval.length; k++) {
510
d3FdXdYdZ[i][j][k] = d3FdXdYdZ_f.value(xval[i], yval[j], zval[k]);
515
TrivariateRealFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
516
fval, dFdX, dFdY, dFdZ,
517
d2FdXdY, d2FdXdZ, d2FdYdZ,
520
double expected, result;
525
expected = f.value(x, y, z);
526
result = tcf.value(x, y, z);
527
Assert.assertEquals("On sample point",
528
expected, result, 1e-14);
533
expected = f.value(x, y, z);
534
result = tcf.value(x, y, z);
535
Assert.assertEquals("Half-way between sample points (middle of the patch)",
536
expected, result, 0.1);
541
expected = f.value(x, y, z);
542
result = tcf.value(x, y, z);
543
Assert.assertEquals("Half-way between sample points (border of the patch)",
544
expected, result, 0.1);