1 /* 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 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 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. 16 */ 17 package org.apache.commons.math3.analysis.interpolation; 18 19 import org.apache.commons.math3.exception.DimensionMismatchException; 20 import org.apache.commons.math3.exception.MathIllegalArgumentException; 21 import org.apache.commons.math3.util.FastMath; 22 import org.apache.commons.math3.analysis.TrivariateFunction; 23 import org.junit.Assert; 24 import org.junit.Test; 25 26 /** 27 * Test case for the bicubic function. 28 * 29 * @deprecated To be removed in 4.0 (see MATH-1166). 30 */ 31 @Deprecated 32 public final class TricubicSplineInterpolatingFunctionTest { 33 /** 34 * Test preconditions. 35 */ 36 @Test testPreconditions()37 public void testPreconditions() { 38 double[] xval = new double[] {3, 4, 5, 6.5}; 39 double[] yval = new double[] {-4, -3, -1, 2.5}; 40 double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5}; 41 double[][][] fval = new double[xval.length][yval.length][zval.length]; 42 43 @SuppressWarnings("unused") 44 TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 45 fval, fval, fval, fval, 46 fval, fval, fval, fval); 47 48 double[] wxval = new double[] {3, 2, 5, 6.5}; 49 try { 50 tcf = new TricubicSplineInterpolatingFunction(wxval, yval, zval, 51 fval, fval, fval, fval, 52 fval, fval, fval, fval); 53 Assert.fail("an exception should have been thrown"); 54 } catch (MathIllegalArgumentException e) { 55 // Expected 56 } 57 double[] wyval = new double[] {-4, -1, -1, 2.5}; 58 try { 59 tcf = new TricubicSplineInterpolatingFunction(xval, wyval, zval, 60 fval, fval, fval, fval, 61 fval, fval, fval, fval); 62 Assert.fail("an exception should have been thrown"); 63 } catch (MathIllegalArgumentException e) { 64 // Expected 65 } 66 double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5}; 67 try { 68 tcf = new TricubicSplineInterpolatingFunction(xval, yval, wzval, 69 fval, fval, fval, fval, 70 fval, fval, fval, fval); 71 Assert.fail("an exception should have been thrown"); 72 } catch (MathIllegalArgumentException e) { 73 // Expected 74 } 75 double[][][] wfval = new double[xval.length - 1][yval.length - 1][zval.length]; 76 try { 77 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 78 wfval, fval, fval, fval, 79 fval, fval, fval, fval); 80 Assert.fail("an exception should have been thrown"); 81 } catch (DimensionMismatchException e) { 82 // Expected 83 } 84 try { 85 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 86 fval, wfval, fval, fval, 87 fval, fval, fval, fval); 88 Assert.fail("an exception should have been thrown"); 89 } catch (DimensionMismatchException e) { 90 // Expected 91 } 92 try { 93 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 94 fval, fval, wfval, fval, 95 fval, fval, fval, fval); 96 Assert.fail("an exception should have been thrown"); 97 } catch (DimensionMismatchException e) { 98 // Expected 99 } 100 try { 101 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 102 fval, fval, fval, wfval, 103 fval, fval, fval, fval); 104 Assert.fail("an exception should have been thrown"); 105 } catch (DimensionMismatchException e) { 106 // Expected 107 } 108 try { 109 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 110 fval, fval, fval, fval, 111 wfval, fval, fval, fval); 112 Assert.fail("an exception should have been thrown"); 113 } catch (DimensionMismatchException e) { 114 // Expected 115 } 116 try { 117 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 118 fval, fval, fval, fval, 119 fval, wfval, fval, fval); 120 Assert.fail("an exception should have been thrown"); 121 } catch (DimensionMismatchException e) { 122 // Expected 123 } 124 try { 125 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 126 fval, fval, fval, fval, 127 fval, fval, wfval, fval); 128 Assert.fail("an exception should have been thrown"); 129 } catch (DimensionMismatchException e) { 130 // Expected 131 } 132 try { 133 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 134 fval, fval, fval, fval, 135 fval, fval, fval, wfval); 136 Assert.fail("an exception should have been thrown"); 137 } catch (DimensionMismatchException e) { 138 // Expected 139 } 140 wfval = new double[xval.length][yval.length - 1][zval.length]; 141 try { 142 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 143 wfval, fval, fval, fval, 144 fval, fval, fval, fval); 145 Assert.fail("an exception should have been thrown"); 146 } catch (DimensionMismatchException e) { 147 // Expected 148 } 149 try { 150 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 151 fval, wfval, fval, fval, 152 fval, fval, fval, fval); 153 Assert.fail("an exception should have been thrown"); 154 } catch (DimensionMismatchException e) { 155 // Expected 156 } 157 try { 158 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 159 fval, fval, wfval, fval, 160 fval, fval, fval, fval); 161 Assert.fail("an exception should have been thrown"); 162 } catch (DimensionMismatchException e) { 163 // Expected 164 } 165 try { 166 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 167 fval, fval, fval, wfval, 168 fval, fval, fval, fval); 169 Assert.fail("an exception should have been thrown"); 170 } catch (DimensionMismatchException e) { 171 // Expected 172 } 173 try { 174 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 175 fval, fval, fval, fval, 176 wfval, fval, fval, fval); 177 Assert.fail("an exception should have been thrown"); 178 } catch (DimensionMismatchException e) { 179 // Expected 180 } 181 try { 182 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 183 fval, fval, fval, fval, 184 fval, wfval, fval, fval); 185 Assert.fail("an exception should have been thrown"); 186 } catch (DimensionMismatchException e) { 187 // Expected 188 } 189 try { 190 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 191 fval, fval, fval, fval, 192 fval, fval, wfval, fval); 193 Assert.fail("an exception should have been thrown"); 194 } catch (DimensionMismatchException e) { 195 // Expected 196 } 197 try { 198 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 199 fval, fval, fval, fval, 200 fval, fval, fval, wfval); 201 Assert.fail("an exception should have been thrown"); 202 } catch (DimensionMismatchException e) { 203 // Expected 204 } 205 wfval = new double[xval.length][yval.length][zval.length - 1]; 206 try { 207 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 208 wfval, fval, fval, fval, 209 fval, fval, fval, fval); 210 Assert.fail("an exception should have been thrown"); 211 } catch (DimensionMismatchException e) { 212 // Expected 213 } 214 try { 215 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 216 fval, wfval, fval, fval, 217 fval, fval, fval, fval); 218 Assert.fail("an exception should have been thrown"); 219 } catch (DimensionMismatchException e) { 220 // Expected 221 } 222 try { 223 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 224 fval, fval, wfval, fval, 225 fval, fval, fval, fval); 226 Assert.fail("an exception should have been thrown"); 227 } catch (DimensionMismatchException e) { 228 // Expected 229 } 230 try { 231 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 232 fval, fval, fval, wfval, 233 fval, fval, fval, fval); 234 Assert.fail("an exception should have been thrown"); 235 } catch (DimensionMismatchException e) { 236 // Expected 237 } 238 try { 239 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 240 fval, fval, fval, fval, 241 wfval, fval, fval, fval); 242 Assert.fail("an exception should have been thrown"); 243 } catch (DimensionMismatchException e) { 244 // Expected 245 } 246 try { 247 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 248 fval, fval, fval, fval, 249 fval, wfval, fval, fval); 250 Assert.fail("an exception should have been thrown"); 251 } catch (DimensionMismatchException e) { 252 // Expected 253 } 254 try { 255 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 256 fval, fval, fval, fval, 257 fval, fval, wfval, fval); 258 Assert.fail("an exception should have been thrown"); 259 } catch (DimensionMismatchException e) { 260 // Expected 261 } 262 try { 263 tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 264 fval, fval, fval, fval, 265 fval, fval, fval, wfval); 266 Assert.fail("an exception should have been thrown"); 267 } catch (DimensionMismatchException e) { 268 // Expected 269 } 270 } 271 272 /** 273 * Test for a plane. 274 * <p> 275 * f(x, y, z) = 2 x - 3 y - 4 z + 5 276 * </p> 277 */ 278 @Test testPlane()279 public void testPlane() { 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}; 283 284 // Function values 285 TrivariateFunction f = new TrivariateFunction() { 286 public double value(double x, double y, double z) { 287 return 2 * x - 3 * y - 4 * z + 5; 288 } 289 }; 290 291 double[][][] fval = new double[xval.length][yval.length][zval.length]; 292 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]); 297 } 298 } 299 } 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++) { 305 dFdX[i][j][k] = 2; 306 } 307 } 308 } 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++) { 314 dFdY[i][j][k] = -3; 315 } 316 } 317 } 318 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++) { 324 dFdZ[i][j][k] = -4; 325 } 326 } 327 } 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; 340 } 341 } 342 } 343 344 TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 345 fval, dFdX, dFdY, dFdZ, 346 d2FdXdY, d2FdXdZ, d2FdYdZ, 347 d3FdXdYdZ); 348 double x, y, z; 349 double expected, result; 350 351 x = 4; 352 y = -3; 353 z = 0; 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); 358 359 x = 4.5; 360 y = -1.5; 361 z = -4.25; 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); 366 367 x = 3.5; 368 y = -3.5; 369 z = -10; 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); 374 } 375 376 /** 377 * Sine wave. 378 * <p> 379 * f(x, y, z) = a cos [ω z - k<sub>y</sub> x - k<sub>y</sub> y] 380 * </p> 381 * with A = 0.2, ω = 0.5, k<sub>x</sub> = 2, k<sub>y</sub> = 1. 382 */ 383 @Test testWave()384 public void testWave() { 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}; 388 389 final double a = 0.2; 390 final double omega = 0.5; 391 final double kx = 2; 392 final double ky = 1; 393 394 // Function values 395 TrivariateFunction f = new TrivariateFunction() { 396 public double value(double x, double y, double z) { 397 return a * FastMath.cos(omega * z - kx * x - ky * y); 398 } 399 }; 400 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]); 406 } 407 } 408 } 409 410 // Partial derivatives with respect to x 411 double[][][] dFdX = new double[xval.length][yval.length][zval.length]; 412 TrivariateFunction dFdX_f = new TrivariateFunction() { 413 public double value(double x, double y, double z) { 414 return a * FastMath.sin(omega * z - kx * x - ky * y) * kx; 415 } 416 }; 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]); 421 } 422 } 423 } 424 425 // Partial derivatives with respect to y 426 double[][][] dFdY = new double[xval.length][yval.length][zval.length]; 427 TrivariateFunction dFdY_f = new TrivariateFunction() { 428 public double value(double x, double y, double z) { 429 return a * FastMath.sin(omega * z - kx * x - ky * y) * ky; 430 } 431 }; 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]); 436 } 437 } 438 } 439 440 // Partial derivatives with respect to z 441 double[][][] dFdZ = new double[xval.length][yval.length][zval.length]; 442 TrivariateFunction dFdZ_f = new TrivariateFunction() { 443 public double value(double x, double y, double z) { 444 return -a * FastMath.sin(omega * z - kx * x - ky * y) * omega; 445 } 446 }; 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]); 451 } 452 } 453 } 454 455 // Partial second derivatives w.r.t. (x, y) 456 double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length]; 457 TrivariateFunction d2FdXdY_f = new TrivariateFunction() { 458 public double value(double x, double y, double z) { 459 return -a * FastMath.cos(omega * z - kx * x - ky * y) * kx * ky; 460 } 461 }; 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]); 466 } 467 } 468 } 469 470 // Partial second derivatives w.r.t. (x, z) 471 double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length]; 472 TrivariateFunction d2FdXdZ_f = new TrivariateFunction() { 473 public double value(double x, double y, double z) { 474 return a * FastMath.cos(omega * z - kx * x - ky * y) * kx * omega; 475 } 476 }; 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]); 481 } 482 } 483 } 484 485 // Partial second derivatives w.r.t. (y, z) 486 double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length]; 487 TrivariateFunction d2FdYdZ_f = new TrivariateFunction() { 488 public double value(double x, double y, double z) { 489 return a * FastMath.cos(omega * z - kx * x - ky * y) * ky * omega; 490 } 491 }; 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]); 496 } 497 } 498 } 499 500 // Partial third derivatives 501 double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length]; 502 TrivariateFunction d3FdXdYdZ_f = new TrivariateFunction() { 503 public double value(double x, double y, double z) { 504 return a * FastMath.sin(omega * z - kx * x - ky * y) * kx * ky * omega; 505 } 506 }; 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]); 511 } 512 } 513 } 514 515 TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval, 516 fval, dFdX, dFdY, dFdZ, 517 d2FdXdY, d2FdXdZ, d2FdYdZ, 518 d3FdXdYdZ); 519 double x, y, z; 520 double expected, result; 521 522 x = 4; 523 y = -3; 524 z = 0; 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); 529 530 x = 4.5; 531 y = -1.5; 532 z = -4.25; 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); 537 538 x = 3.5; 539 y = -3.5; 540 z = -10; 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); 545 } 546 } 547