Skip to content

BUG: fix hard-coded 2x2x2 zone-count assumptions in octree neighbour-finding (issue 5402) - #5508

Open
jurb33 wants to merge 5 commits into
yt-project:mainfrom
jurb33:issue-5402
Open

BUG: fix hard-coded 2x2x2 zone-count assumptions in octree neighbour-finding (issue 5402)#5508
jurb33 wants to merge 5 commits into
yt-project:mainfrom
jurb33:issue-5402

Conversation

@jurb33

@jurb33 jurb33 commented Aug 27, 2026

Copy link
Copy Markdown

Addresses issue #5402.

PR Summary

Neighbour finding in oct_container.pyx/oct_visitors.pyx (used for ghost zone construction) assumed every oct is 2x2x2 cells, failing when non cubic zones encountered. The fix is changing how the index of neighbour cells are calculated in several places (issue list was not exhaustive)

Changes:
BaseNeighbourVisitor.set_neighbour_info: checking "am I still in this oct" and neighbour cell index used %2 and <=1, now uses self.nz[I] for the actual width.

NeighbourCellIndexVisitor.visit/NeighbourCellVisitor.visit: Used a shared bound 2 + n_ghost_zones to check each axis, and hardcoded 8 as the no cell condition. now uses self.nz[axis] and self.nz[0,1,2]**3(not real python, but you get the idea)

oct_container.pyx: the output for fill_octcellindex_neighbours/file_index_octs_with_ghost_zones were sized as 4**3 regardless of actual cell count.

Two of the cases above were not present in the original ticket set_neighbour_info.

Testing:

Added test_octcellindex_neighbours_num_zones:yt/data_objects/tests/test_octree.py which builds the error case with num_zones=(2,2,2) and (2,3,4) and asserts the expected cell count. Old code fails this, where this change fixes situations like these. All previous tests pass unchanged.

While tracing function calls, I noticed in a higher level function that yt/frontends/ramses/data_structures.py:fcoords
calls
oct_container.pyx:fill_octcellindex_neighbours
like oh.fill_octcellindex_neighbours(self.selector, self._num_ghost_zones)
which is actually num_octs in
def fill_octcellindex_neighbours(self, selector, num_octs=-1, domain_id=-1)
passing ghost_zones incorrectly. This could cause overflow of a single oct and give incorrect results. Maybe a Issue should be opened up for this?

PR Checklist

  • New features are documented, with docstrings and narrative docs
  • Adds a test for any bugs fixed. Adds tests for new features.

@welcome

welcome Bot commented Aug 27, 2026

Copy link
Copy Markdown

Hi! Welcome, and thanks for opening this pull request. We have some guidelines for new pull requests, and soon you'll hear back about the results of our tests and continuous integration checks. Thank you for your contribution!

@chrishavlin
chrishavlin requested a review from cphyc September 1, 2026 14:45
@cphyc

cphyc commented Sep 2, 2026

Copy link
Copy Markdown
Member

pre-commit.ci autofix

@cphyc cphyc added enhancement Making something better index: octree labels Sep 2, 2026

@cphyc cphyc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jurb33 for fixing this!

This looks reasonable to me, but I'm wondering whether it'd be possible to simplify the test? As far as I could understand, you're creating an octree from a collection of particles using an arbitrary nz.

Could we use the dedicated yt.testing.fake_octree_ds function instead? From what I could gather, I think the answer is not a straight yes, but if you could give it a try that'd be awesome!

Otherwise, the fixes look great.

NOTE: I edited your PR for cosmetic changes, so please git pull before adding anything new.

morton = get_morton_indices(np.floor((centers - DLE) / dx).astype("uint64"))
morton.sort()

for nz in ((2, 2, 2), (2, 3, 4)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest also testing that (1, 1, 1) doesn't work (it doesn't on main).

Suggested change
for nz in ((2, 2, 2), (2, 3, 4)):
for nz in ((1, 1, 1), (2, 2, 2), (2, 3, 4)):

Comment on lines +168 to +174
octree = ParticleOctreeContainer((1, 1, 1), DLE, DRE, num_zones=nz)
octree.n_ref = 1
octree.add(morton)
octree.finalize()

nzones = nz[0] * nz[1] * nz[2]
n_per_oct = (nz[0] + 2) * (nz[1] + 2) * (nz[2] + 2) # +1 ghost zone each side

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fairly convoluted - do you think it'd be possible to use instead yt.load_octree(..., num_zones=(1, 2, 3))?

EDIT: I just tested, and the short answer is no... because load_octree expects num_zones to be a scalar.

i1 = 2 + self.n_ghost_zones
# Loop over cells in and directly around oct
for i in range(i0, i1):
for i in range(i0, self.nz[0] + self.n_ghost_zones):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How confident are you that this shouldn't be the following?

Suggested change
for i in range(i0, self.nz[0] + self.n_ghost_zones):
for i in range(i0, self.nz[2] + self.n_ghost_zones):

(and self.nz[0] for the innermost loop)

@jurb33 jurb33 Sep 2, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct - looking at these lines:
yt/geometry/oct_visitors.pyx:391
local_oct &= (0 <= ishift[i] < self.nz[i])
yt/geometry/oct_visitors.pyx:415
self.neigh_ind[i] = <np.uint32_t>(ishift[i]) % self.nz[i]
is using the same ishift[i] self.nz[i] pairing convention everywhere else in oct_visitors.pyx
Using self.nz[2] would break the test case which is what this was intended to fix. (ran this locally)

As far as the test implementation, yes, I can make these changes. May be a bit since school is starting up for me and I am pursuing different projects.

Thank you for reviewing my changes!

@chrishavlin chrishavlin added this to the 4.5.0 milestone Sep 2, 2026
@chrishavlin

Copy link
Copy Markdown
Contributor

Will let @cphyc handle the review from here, but FYI I just added this to milestone 4.5.0 now so I don't make the same mistake I did with #5525 -- this is a bug fix for unreleased functionality on main that will be released with 4.5.0 so we don't want to backport to 4.4.x

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

Labels

enhancement Making something better index: octree

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants