Skip to content

Commit 38f731c

Browse files
GuyStenpaulromano
authored andcommitted
Fix raytrace infinite loop. (openmc-dev#3423)
Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
1 parent ba375f3 commit 38f731c

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

src/mesh.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,14 +989,18 @@ void StructuredMesh::raytrace_mesh(
989989
// For all directions outside the mesh, find the distance that we need
990990
// to travel to reach the next surface. Use the largest distance, as
991991
// only this will cross all outer surfaces.
992-
int k_max {0};
992+
int k_max {-1};
993993
for (int k = 0; k < n; ++k) {
994994
if ((ijk[k] < 1 || ijk[k] > shape_[k]) &&
995995
(distances[k].distance > traveled_distance)) {
996996
traveled_distance = distances[k].distance;
997997
k_max = k;
998998
}
999999
}
1000+
// Assure some distance is traveled
1001+
if (k_max == -1) {
1002+
traveled_distance += TINY_BIT;
1003+
}
10001004

10011005
// If r1 is not inside the mesh, exit here
10021006
if (traveled_distance >= total_distance)
@@ -1011,7 +1015,7 @@ void StructuredMesh::raytrace_mesh(
10111015
}
10121016

10131017
// If inside the mesh, Tally inward current
1014-
if (in_mesh)
1018+
if (in_mesh && k_max >= 0)
10151019
tally.surface(ijk, k_max, !distances[k_max].max_surface, true);
10161020
}
10171021
}
@@ -1207,6 +1211,7 @@ StructuredMesh::MeshDistance RegularMesh::distance_to_grid_boundary(
12071211
d.next_index--;
12081212
d.distance = (negative_grid_boundary(ijk, i) - r0[i]) / u[i];
12091213
}
1214+
12101215
return d;
12111216
}
12121217

tests/unit_tests/test_mesh.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,36 @@ def test_mesh_material_volumes_serialize():
534534
assert new_volumes.by_element(1) == [(None, 1.0)]
535535
assert new_volumes.by_element(2) == [(2, 0.5), (1, 0.5)]
536536
assert new_volumes.by_element(3) == [(2, 1.0)]
537+
538+
539+
def test_raytrace_mesh_infinite_loop():
540+
# Create a model with one large spherical cell
541+
sphere = openmc.Sphere(r=100, boundary_type='vacuum')
542+
cell = openmc.Cell(region=-sphere)
543+
model = openmc.Model()
544+
model.geometry = openmc.Geometry([cell])
545+
546+
# Create a regular mesh and associated tally
547+
mesh_surface = openmc.RegularMesh()
548+
mesh_surface.lower_left = (-30, -30, 30)
549+
mesh_surface.upper_right = (30, 30, 60)
550+
mesh_surface.dimension = (1, 1, 1)
551+
reg_filter = openmc.MeshSurfaceFilter(mesh_surface)
552+
mesh_surface_tally = openmc.Tally()
553+
mesh_surface_tally.filters = [reg_filter]
554+
mesh_surface_tally.scores = ['current']
555+
model.tallies = [mesh_surface_tally]
556+
557+
# Define a source such that the z position is on a mesh boundary with a very
558+
# small directional cosine in the z direction
559+
polar = openmc.stats.delta_function(1.75e-7)
560+
azimuthal = openmc.stats.Uniform(0.0, 2.0*pi)
561+
model.settings.source = openmc.IndependentSource(
562+
angle=openmc.stats.PolarAzimuthal(polar, azimuthal)
563+
)
564+
model.settings.run_mode = 'fixed source'
565+
model.settings.particles = 10
566+
model.settings.batches = 1
567+
568+
# Run the model; this should not cause an infinite loop
569+
model.run()

0 commit comments

Comments
 (0)