Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Enable exporting GAMER and FLASH datasets to octrees #4134

Merged
merged 10 commits into from
May 24, 2023
2 changes: 1 addition & 1 deletion yt/frontends/stream/data_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ def _setup_data_io(self):

def _initialize_oct_handler(self):
header = dict(
dims=[1, 1, 1],
dims=self.ds.domain_dimensions // self.ds.num_zones,
left_edge=self.ds.domain_left_edge,
right_edge=self.ds.domain_right_edge,
octree=self.ds.octree_mask,
Expand Down
26 changes: 23 additions & 3 deletions yt/geometry/oct_container.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ cdef class OctreeContainer:
pos[2] = self.DLE[2] + dds[2]/2.0
for k in range(self.nn[2]):
if self.root_mesh[i][j][k] == NULL:
raise RuntimeError
raise KeyError(i,j,k)
Copy link
Member

Choose a reason for hiding this comment

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

I guess an IndexError would be slightly more appropriate

Copy link
Member Author

Choose a reason for hiding this comment

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

No, I think KeyError is fine. The issue is that we have constructed what amounts to a mapping, and that mapping has nothing in it for a given key.

Copy link
Member

Choose a reason for hiding this comment

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

ok, makes sense

visitor.pos[0] = i
visitor.pos[1] = j
visitor.pos[2] = k
Expand All @@ -185,6 +185,16 @@ cdef class OctreeContainer:
cdef np.int64_t get_domain_offset(self, int domain_id):
return 0

def check_root_mesh(self):
cdef count = 0
for i in range(self.nn[0]):
for j in range(self.nn[1]):
for k in range(self.nn[2]):
if self.root_mesh[i][j][k] == NULL:
print("Missing ", i, j, k)
count += 1
print("Missing total of %s out of %s" % (count, self.nn[0] * self.nn[1] * self.nn[2]))
matthewturk marked this conversation as resolved.
Show resolved Hide resolved

cdef int get_root(self, int ind[3], Oct **o) nogil:
cdef int i
for i in range(3):
Expand Down Expand Up @@ -567,7 +577,11 @@ cdef class OctreeContainer:
def add(self, int curdom, int curlevel,
np.ndarray[np.float64_t, ndim=2] pos,
int skip_boundary = 1,
int count_boundary = 0):
int count_boundary = 0,
np.ndarray[np.uint64_t, ndim=1, cast=True] levels = None
):
# In this function, if we specify curlevel = -1, then we query the
# (optional) levels array for the oct level.
cdef int no, p, i
cdef int ind[3]
cdef int nb = 0
Expand All @@ -582,6 +596,12 @@ cdef class OctreeContainer:
cdef int in_boundary = 0
# How do we bootstrap ourselves?
for p in range(no):
# We allow specifying curlevel = -1 to query from the levels array
# instead.
if curlevel == -1:
this_level = levels[p]
else:
this_level = curlevel
Comment on lines +598 to +603
Copy link
Member

Choose a reason for hiding this comment

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

this doesn't depend on the iteration variable (p), so it would be clearer (and more efficient) to put it outside the loop

Copy link
Member Author

Choose a reason for hiding this comment

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

levels[p]

Copy link
Member

Choose a reason for hiding this comment

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

🤦🏻‍♂️

#for every oct we're trying to add find the
#floating point unitary position on this level
in_boundary = 0
Expand All @@ -599,7 +619,7 @@ cdef class OctreeContainer:
if cur == NULL: raise RuntimeError
# Now we find the location we want
# Note that RAMSES I think 1-findiceses levels, but we don't.
for _ in range(curlevel):
for _ in range(this_level):
# At every level, find the cell this oct
# lives inside
for i in range(3):
Expand Down
10 changes: 9 additions & 1 deletion yt/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,7 @@ def load_octree(
default_species_fields=None,
*,
parameters=None,
domain_dimensions=None,
):
r"""Load an octree mask into yt.

Expand Down Expand Up @@ -980,6 +981,9 @@ def load_octree(
parameters: dictionary, optional
Optional dictionary used to populate the dataset parameters, useful
for storing dataset metadata.
domain_dimensions : array_like, optional
matthewturk marked this conversation as resolved.
Show resolved Hide resolved
This is the domain dimensions of the root *mesh*, which can be used to
specify (indirectly) the number of root oct nodes.

Example
-------
Expand Down Expand Up @@ -1015,7 +1019,11 @@ def load_octree(
# for compatibility
if over_refine_factor is not None:
nz = 1 << over_refine_factor
domain_dimensions = np.array([nz, nz, nz])
if domain_dimensions is None:
# We assume that if it isn't specified, it defaults to the number of
# zones (i.e., a single root oct.)
domain_dimensions = [nz, nz, nz]
domain_dimensions = np.array(domain_dimensions)
matthewturk marked this conversation as resolved.
Show resolved Hide resolved
nprocs = 1
if bbox is None:
bbox = np.array([[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]], "float64")
Expand Down