Skip to content

Skip cells whose bounding boxes do not contain the point in cell searches - #4163

Open
GuySten wants to merge 1 commit into
openmc-dev:developfrom
GuySten:claude/cell-search-box-filter
Open

GuySten wants to merge 1 commit into
openmc-dev:developfrom
GuySten:claude/cell-search-box-filter

Conversation

@GuySten

@GuySten GuySten commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Description

Finding the cell that contains a point is a linear search: the cells of a universe (or of a z-plane partition), or the neighbor list of the cell being left, are checked in order with Cell::contains, which evaluates the senses of the point with respect to the cell's surfaces. In universes with many cells, this search dominates the run time. In the Advanced Test Reactor model (5968 cells, the example used in #2593), cell search takes 42% of transport time. It takes 75% of a stochastic volume calculation and about 60% of coupled neutron-photon transport, where every secondary particle starts with an exhaustive search.

This PR computes a bounding box for each CSG cell once at initialization, enlarged by a relative 1e-9 for roundoff in positions on the cell boundary. The cell searches in Universe::find_cell and in neighbor lists then skip any cell whose box does not contain the point before calling contains.

Cells are still checked in the same order and the same cell is found, so results are unchanged, even for overlapping cells. The only added cost is one box test (six comparisons) per cell visited, and it replaces a contains call for every cell whose box does not contain the point. Search structures, neighbor lists, the z-plane partitioner and the input format are unchanged, and no settings are added.

Compared with #2593, this is exact by construction: boxes come from the region expressions rather than from sampling, so no cell can be missed and no fallback search is needed. It also needs no parameters or files. #2593 restructures the search with octrees or kd-trees and can be faster on ATR. This PR is a small change that never reorders the search; a tree for very large universes could be built on top of it later.

Performance

Single thread, median of 2 runs. Times are for transport, or for the whole calculation in volume mode. All results are bitwise identical to develop.

Model develop this PR speedup
ATR, stochastic volume calculation (42 materials, 3e5 samples) 6.72 s 1.84 s 3.65×
ATR, coupled neutron-photon transport 19.93 s 11.41 s 1.75×
ATR, neutron eigenvalue 12.12 s 9.70 s 1.25×
TRISO compact, 2603 particles as explicit cells (no lattice) 19.07 s 15.16 s 1.26×
Water tank with 400 rods 7.64 s 7.14 s 1.07×
PWR assembly 16.13 s 15.77 s 1.02×
Ring/sector core (360 cells cut by angled planes) 1.52 s 1.49 s 1.02×
D2O 15.92 s 15.78 s 1.01×
Concrete shield (union of convex blocks) 22.29 s 22.13 s 1.01×
GEOUNED-converted CAD model (Triangle) 3.04 s 3.04 s 1.00×

Run-to-run variation on this machine is about ±4%.

Tests

tests/unit_tests/test_cell_search.py checks openmc.lib.find_cell against Python's evaluation of the regions at random points in two cases:

  • a universe of 61 overlapping spheres and finite rods, with a background cell outside of all of them, plus a transport run with no lost particles;
  • random region expressions with unions, intersections, complements and angled planes, which also check that each point lies within the bounding box of the cell found. The search relies on that property.

The methods documentation describes the bounding box test in cell searches and neighbor lists.

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 18) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

…ches

A bounding box is computed for each CSG cell at initialization, enlarged
slightly for roundoff, and the searches over the cells of a universe and
over neighbor lists skip cells whose boxes do not contain the point before
evaluating whether the cell contains it. Cells are checked in the same order
as before, so the same cell is found, while expensive containment checks are
replaced by a box test for cells that cannot contain the point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RN7JroEkrbkLKVHbMDap9
@GuySten
GuySten marked this pull request as ready for review October 3, 2026 09:51
@GuySten
GuySten requested a review from paulromano October 3, 2026 09:51
@GuySten GuySten changed the title Skip cells whose bounding boxes do not contain the point in cell sear… Skip cells whose bounding boxes do not contain the point in cell searches Oct 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants