Skip to content

Support (N, M, L) per-dimension zones in octree containers#5391

Merged
matthewturk merged 3 commits intoyt-project:mainfrom
cphyc:feature/support-non-cubic-zones
Apr 28, 2026
Merged

Support (N, M, L) per-dimension zones in octree containers#5391
matthewturk merged 3 commits intoyt-project:mainfrom
cphyc:feature/support-non-cubic-zones

Conversation

@cphyc
Copy link
Copy Markdown
Member

@cphyc cphyc commented Feb 26, 2026

PR Summary

Currently, yt only supports cubic "zones" for octrees: this means that octree datasets can only contain (N, N, N) cells in each leaf oct, where N is controlled with the dataset parameter num_zones.

This PR allows passing a tuple of values of num_zones, increasing flexibility in support of #5390. In practice, this allows having an octree of blocks, where each block contains (N, M, L) cells.

This PR should leave the RAMSES, Art and Stream frontends behaviour unchanged.

PR Checklist

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

@cphyc cphyc added this to the 4.5.0 milestone Feb 26, 2026
@cphyc cphyc added new feature Something fun and new! index: octree labels Feb 26, 2026
@cphyc cphyc mentioned this pull request Feb 26, 2026
@cphyc cphyc force-pushed the feature/support-non-cubic-zones branch from cf2d51e to d126ef5 Compare February 26, 2026 15:13
@cphyc cphyc marked this pull request as ready for review February 27, 2026 08:40
Blocks may contain more than 256 cells - prevent overflow of the uint8
@chrishavlin chrishavlin self-assigned this Mar 2, 2026
matthewturk
matthewturk previously approved these changes Mar 6, 2026
Copy link
Copy Markdown
Member

@matthewturk matthewturk left a comment

Choose a reason for hiding this comment

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

I have gone over this and everything I can see suggests it looks exactly correct.

This is a really great improvement. I'd like to see if we could discuss reviving efforts to move the Enzo-P frontend to use this ...

With arbitrary zones, is it also potentially the case that any and all block-based grid systems could utilize all this machinery, rather than the more complex (and not fully working) grid visitor stuff? I suspect not, based on how the refinement patterns go, but I wanted to ask.

new_shape = (nz, nz, nz, n_oct)
elif arr.size == nz * nz * nz * n_oct * 3:
new_shape = (nz, nz, nz, n_oct, 3)
if arr.size == nzones * n_oct:
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 don't think this changes the F/C ordering issues, right? Like, if we were ordered correctly with symmetric dimensions we'd be similarly ordered correctly with asymmetric dimensions? (And vice versa.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's too late in the week for me to fully process that question, but I think I understand it, and I think the answer is yes. How could I convince us of it?

Copy link
Copy Markdown
Contributor

@chrishavlin chrishavlin left a comment

Choose a reason for hiding this comment

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

only took a cursory look to see where the test failures were coming from

# We create oct arrays of the correct size
cdef np.ndarray[np.uint8_t, ndim=1] levels
cdef np.ndarray[np.uint8_t, ndim=1] cell_inds
cdef np.ndarray[np.uint32_t, ndim=1] cell_inds
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is the source of the test failures: the return will now be uint32_t, but fill_level is expecting uint8_t still, so presumably fill_level's types should be updated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

and should file_index_octs_with_ghost_zones be updated too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh and fill_level_with_domain ?

Copy link
Copy Markdown
Member Author

@cphyc cphyc Mar 20, 2026

Choose a reason for hiding this comment

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

So I followed the white rabbit and ended up replacing lots of hits. Let's see whether tests pass now!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Funnily, I think yt never worked with nz > 6 for which nz**3 > 255 which overflows an uint8_t!

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.

Oh dang, that's somehow not surprising, but should be. I wonder if this is related to some other weird problems I saw in some other work a few years ago.

This will potentially increase the peak memory usage quite a lot, but I don't know that it's going to be a long-lived increase that will make a difference.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To be fair, the memory increase is on the order of $(32-8) \mathrm{bit} \times N_\mathrm{cell}$ to be compared to the $64\mathrm{bit} \times N_\mathrm{cell}$ used by file_inds and a similar amount used to read the data in double precision.

I agree this is slightly wasteful, but in the grand scheme of things, it's probably OK. But I could make it a uint16 if you wanted.

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 definitely do not! I think we're in fine territory.

When allowing larger block sizes, we may easily overflow 8-bit counters.
Note that this was *already* overflowing for nz > 6, but it appears
it was never tested.
cdef np.uint8_t[::1] cell_inds
cdef np.int64_t[::1] oct_inds

cell_inds = np.full(num_octs*4**3, 8, dtype=np.uint8)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So, reading this with a fresh mind, I think this is incorrect again, and never worked for cases where nz ≠ 2. The 4**3 is one oct (harcoded 2×2×2) with one neighbour in each dimension (so 4×4×4).

At this point, I'm starting to wonder how deep I need to go to fix all these hard-coded assumptions.

I could either try to fix them all in this PR or open another one to fix it afterwards. What do you suggest @chrishavlin?

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 an interesting one, and I'm not sure how it worked before, if indeed it is a problem.

One thing to keep in mind is that there are, occasionally, sloppy references to "cells" when it should be "leaf nodes." So while this may indeed be an error, it's possible that it's actually just marking the selected leaf nodes and not the cells.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think I'm the author of this sloppy piece of code, and I'm pretty sure I hard-coded that it only works in the 2×2×2 case.

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 wanted to say that it's not that big a deal, but in looking it over, it does get used in the Stream and ART frontends, so it's possible that this may impede our ability moving forward if we wanted to convert any Block-structured code to using this.

For instance, it could potentially be very beneficial to use the octree machinery for enzo-p (and a student worked on that a couple summers ago). (Maybe he even issued a pull request to make the number of zones generic? I will investigate.)


cdef np.int64_t[:, :, :, :] cell_inds

cell_inds = np.full((self.nocts, 2, 2, 2), -1, dtype=np.int64)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For reference, here is another place where it is hard-coded that nz=2.

@cphyc
Copy link
Copy Markdown
Member Author

cphyc commented Mar 21, 2026

@matthewturk and @chrishavlin I've:

  • made the requested modification,
  • opened an issue ([BUG] Oct container has hard-coded assumptions nz=2 #5402) for the incorrect assumption about the number of cells in an oct that was already in yt. I propose fixing it in another PR. The impact seems to be limited to neighbour finding and ghost zone reconstruction.

@cphyc cphyc requested a review from chrishavlin March 31, 2026 07:59
@matthewturk
Copy link
Copy Markdown
Member

If you think this is good to go in with a followup, I say do it.

@cphyc
Copy link
Copy Markdown
Member Author

cphyc commented Apr 28, 2026

If you think this is good to go in with a followup, I say do it.

I think that would be the best option (especially if we want to release a new version soon). All the bugs with hardcoded 2×2×2 assumptions have been with us essentially forever; this PR is merely revealing them and it's documented in #5402.

Plus, I'm starting to work with datasets that break this assumption explicitly, so I'll eventually fix them!

@matthewturk
Copy link
Copy Markdown
Member

OK -- so you think this one is good to go in? I reviewed it and it looks like you made the appropriate changes ... going once, going twice?

@cphyc
Copy link
Copy Markdown
Member Author

cphyc commented Apr 28, 2026

OK -- so you think this one is good to go in? I reviewed it and it looks like you made the appropriate changes ... going once, going twice?

I do!

@chrishavlin
Copy link
Copy Markdown
Contributor

I won't have time to get to this for a while, but don't hold it up for me! if @matthewturk took a look and you're both happy, merge away!

@matthewturk matthewturk merged commit 11e166f into yt-project:main Apr 28, 2026
38 of 41 checks passed
@cphyc cphyc deleted the feature/support-non-cubic-zones branch April 29, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

index: octree new feature Something fun and new!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants