Guest User

Untitled

a guest
Feb 16th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.53 KB | None | 0 0
  1. /**
  2. * @file matrix3d_boundary_traversal.cpp
  3. *
  4. * @author Johannes Sjolund (j.sjolund@gmail.com)
  5. *
  6. * @brief Traverse the boundary elements on the faces of a 3D matrix, by
  7. * iterating sequentially over integers 0 to the sum of the numbers of
  8. * elements on each face (2 * (nx * ny + nx * nz + ny * nz)) where matrix
  9. * dimensions nx >= ny >= nz.
  10. *
  11. * @copyright Copyright 2019 Johannes Sjolund. All rights reserved.
  12. * @license This project is released under the GNU Public License.
  13. *
  14. */
  15. #include <iomanip>
  16. #include <iostream>
  17.  
  18. //! Defines indexing for flattened 3D matrix
  19. #define I3D(x, y, z, nx, ny, nz) ((x) + (y) * (nx) + (z) * (nx) * (ny))
  20.  
  21. /**
  22. * @brief Calculate the coordinate of a boundary element on the faces of a 3D
  23. * matrix from an index between 0 and the sum of the numbers of elements on each
  24. * face. Matrix dimensions must be nx >= ny >= nz. Note that corners and edges
  25. * are repeated.
  26. *
  27. * @param i Index in range [0, 2 * (nx * ny + nx * nz + ny * nz) )
  28. * @param nx Matrix length on X-axis, range [0, ?]
  29. * @param ny Matrix length on Y-axis, range [0, nx]
  30. * @param nz Matrix length on Z-axis, range [0, ny]
  31. * @param x Matrix boundary face coordinate on X-axis
  32. * @param y Matrix boundary face coordinate on Y-axis
  33. * @param z Matrix boundary face coordinate on Z-axis
  34. */
  35. void getBoundaryElement(int i, int nx, int ny, int nz, int *x, int *y, int *z) {
  36. int n = nx * ny + nx * nz + ny * nz;
  37. int j = i % n;
  38. int xy = (2 * nx * ny) / (j + nx * ny + 1);
  39. int xy_xz = (2 * nx * ny + 2 * nx * nz) / (j + nx * ny + nx * nz + 1);
  40. int xy_xz_yz = (2 * n) / (j + n + 1);
  41. int xz = xy_xz - xy;
  42. int yz = xy_xz_yz - xy_xz;
  43. int xy_x = j % nx;
  44. int xy_y = j / nx;
  45. int xy_z = (nz - 1) * (i / n);
  46. int xz_x = j % nx;
  47. int xz_y = (ny - 1) * (i / n);
  48. int xz_z = (j % (nx * ny)) / nx;
  49. int yz_x = (nx - 1) * (i / n);
  50. int yz_y = (j % (nx * ny + nx * nz)) % ny;
  51. int yz_z = (j % (nx * ny + nx * nz)) / ny;
  52. *x = xy * xy_x + xz * xz_x + yz * yz_x;
  53. *y = xy * xy_y + xz * xz_y + yz * yz_y;
  54. *z = xy * xy_z + xz * xz_z + yz * yz_z;
  55. }
  56.  
  57. /**
  58. * @brief Fill a matrix with numbers > 0
  59. */
  60. void fillMatrix(int *matrix, int nx, int ny, int nz) {
  61. for (int x = 0; x < nx; x++)
  62. for (int y = 0; y < ny; y++)
  63. for (int z = 0; z < nz; z++) {
  64. int i = I3D(x, y, z, nx, ny, nz);
  65. matrix[i] = i + 1;
  66. }
  67. }
  68.  
  69. /**
  70. * @brief Check that all boundary face elements of the matrix are equal to zero,
  71. * while all others are not equal to zero
  72. */
  73. bool verifyMatrix(int *matrix, int nx, int ny, int nz) {
  74. for (int x = 0; x < nx; x++)
  75. for (int y = 0; y < ny; y++)
  76. for (int z = 0; z < nz; z++) {
  77. int val = matrix[I3D(x, y, z, nx, ny, nz)];
  78. if (x == 0 || x == nx - 1 || y == 0 || y == ny - 1 || z == 0 ||
  79. z == nz - 1) {
  80. if (val != 0) return false;
  81. } else {
  82. if (val == 0) return false;
  83. }
  84. }
  85. return true;
  86. }
  87.  
  88. /**
  89. * @brief Print the contents of a matrix to standard output
  90. */
  91. void printMatrix(int *matrix, int nx, int ny, int nz) {
  92. for (int z = 0; z < nz; z++) {
  93. for (int y = 0; y < ny; y++) {
  94. for (int x = 0; x < nx; x++) {
  95. std::cout << std::setfill('0') << std::setw(3)
  96. << matrix[I3D(x, y, z, nx, ny, nz)] << " ";
  97. }
  98. std::cout << std::endl;
  99. }
  100. std::cout << std::endl;
  101. }
  102. }
  103.  
  104. /**
  105. * @brief Test the matrix boundary element iteration with different size
  106. * matrices and check the result.
  107. */
  108. int main(int argc, char **argv) {
  109. int n_min = 1;
  110. int n_max = 50;
  111.  
  112. // Matrix dimensions must be nx >= ny >= nz
  113. for (int nx = n_min; nx <= n_max; nx++)
  114. for (int ny = n_min; ny <= nx; ny++)
  115. for (int nz = n_min; nz <= ny; nz++) {
  116. // 3D matrix flattened into 1D array
  117. int matrix[nx * ny * nz];
  118. // Fill matrix with numbers except 0
  119. fillMatrix(matrix, nx, ny, nz);
  120.  
  121. // Set all matrix boundary elements to zero
  122. const int n = 2 * (nx * ny + nx * nz + ny * nz);
  123. for (int i = 0; i < n; i++) {
  124. int x, y, z;
  125. getBoundaryElement(i, nx, ny, nz, &x, &y, &z);
  126. matrix[I3D(x, y, z, nx, ny, nz)] = 0;
  127. }
  128.  
  129. // Verify that the matrix has the correct content
  130. if (!verifyMatrix(matrix, nx, ny, nz)) {
  131. std::cout << "FAIL: "
  132. << "nx=" << nx << ", ny=" << ny << ", nz=" << nz
  133. << std::endl;
  134. printMatrix(matrix, nx, ny, nz);
  135. return 1;
  136. } else {
  137. std::cout << "OK: "
  138. << "nx=" << nx << ", ny=" << ny << ", nz=" << nz
  139. << std::endl;
  140. }
  141. }
  142. return 0;
  143. }
Add Comment
Please, Sign In to add comment