|
10 | 10 | #include "openmc/geometry.h" |
11 | 11 | #include "openmc/geometry_aux.h" |
12 | 12 | #include "openmc/hdf5_interface.h" |
| 13 | +#include "openmc/math_functions.h" |
13 | 14 | #include "openmc/string_utils.h" |
14 | 15 | #include "openmc/vector.h" |
15 | 16 | #include "openmc/xml_interface.h" |
@@ -260,25 +261,33 @@ std::pair<double, array<int, 3>> RectLattice::distance( |
260 | 261 | // Determine the oncoming edge. |
261 | 262 | double x0 {copysign(0.5 * pitch_[0], u.x)}; |
262 | 263 | double y0 {copysign(0.5 * pitch_[1], u.y)}; |
263 | | - double z0; |
264 | 264 |
|
265 | | - double d = std::min( |
266 | | - u.x != 0.0 ? (x0 - x) / u.x : INFTY, u.y != 0.0 ? (y0 - y) / u.y : INFTY); |
| 265 | + // Evaluate the distance to each oncoming edge independently. Comparing these |
| 266 | + // distances directly (rather than reconstructing the crossing position) |
| 267 | + // avoids the floating-point cancellation that occurs for large pitches. |
| 268 | + double dx = u.x != 0.0 ? (x0 - x) / u.x : INFTY; |
| 269 | + double dy = u.y != 0.0 ? (y0 - y) / u.y : INFTY; |
| 270 | + double dz = INFTY; |
267 | 271 | if (is_3d_) { |
268 | | - z0 = copysign(0.5 * pitch_[2], u.z); |
269 | | - d = std::min(d, u.z != 0.0 ? (z0 - z) / u.z : INFTY); |
| 272 | + double z0 {copysign(0.5 * pitch_[2], u.z)}; |
| 273 | + dz = u.z != 0.0 ? (z0 - z) / u.z : INFTY; |
270 | 274 | } |
271 | 275 |
|
272 | | - // Determine which lattice boundaries are being crossed |
| 276 | + // The distance to the nearest lattice boundary is the smallest axial |
| 277 | + // distance. |
| 278 | + double d = std::min({dx, dy, dz}); |
| 279 | + |
| 280 | + // Determine which lattice boundaries are being crossed. The axis attaining |
| 281 | + // the minimum is exactly equal to d, so at least one translation is always |
| 282 | + // set for a finite crossing; a near-equal second axis indicates a corner |
| 283 | + // crossing. |
273 | 284 | array<int, 3> lattice_trans = {0, 0, 0}; |
274 | | - if (u.x != 0.0 && std::abs(x + u.x * d - x0) < FP_PRECISION) |
| 285 | + if (isclose(d, dx, FP_COINCIDENT, FP_PRECISION)) |
275 | 286 | lattice_trans[0] = copysign(1, u.x); |
276 | | - if (u.y != 0.0 && std::abs(y + u.y * d - y0) < FP_PRECISION) |
| 287 | + if (isclose(d, dy, FP_COINCIDENT, FP_PRECISION)) |
277 | 288 | lattice_trans[1] = copysign(1, u.y); |
278 | | - if (is_3d_) { |
279 | | - if (u.z != 0.0 && std::abs(z + u.z * d - z0) < FP_PRECISION) |
280 | | - lattice_trans[2] = copysign(1, u.z); |
281 | | - } |
| 289 | + if (is_3d_ && isclose(d, dz, FP_COINCIDENT, FP_PRECISION)) |
| 290 | + lattice_trans[2] = copysign(1, u.z); |
282 | 291 |
|
283 | 292 | return {d, lattice_trans}; |
284 | 293 | } |
|
0 commit comments