[yt-svn] commit/yt: xarthisius: Merged in MatthewTurk/yt (pull request #1901)

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Feb 3 09:06:31 PST 2016


1 new commit in yt:

https://bitbucket.org/yt_analysis/yt/commits/45dc609be9e8/
Changeset:   45dc609be9e8
Branch:      yt
User:        xarthisius
Date:        2016-02-03 17:06:20+00:00
Summary:     Merged in MatthewTurk/yt (pull request #1901)

Octree visitor refactoring
Affected #:  9 files

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/data_objects/octree_subset.py
--- a/yt/data_objects/octree_subset.py
+++ b/yt/data_objects/octree_subset.py
@@ -90,10 +90,11 @@
         return self._num_zones + 2*self._num_ghost_zones
 
     def _reshape_vals(self, arr):
-        if len(arr.shape) == 4 and arr.flags["F_CONTIGUOUS"]:
-            return arr
         nz = self.nz
-        n_oct = arr.shape[0] / (nz**3.0)
+        if len(arr.shape) <= 2:
+            n_oct = arr.shape[0] / (nz**3.0)
+        else:
+            n_oct = max(arr.shape)
         if arr.size == nz*nz*nz*n_oct:
             new_shape = (nz, nz, nz, n_oct)
         elif arr.size == nz*nz*nz*n_oct * 3:
@@ -115,10 +116,9 @@
 
     def select_blocks(self, selector):
         mask = self.oct_handler.mask(selector, domain_id = self.domain_id)
-        mask = self._reshape_vals(mask)
         slicer = OctreeSubsetBlockSlice(self)
         for i, sl in slicer:
-            yield sl, mask[:,:,:,i]
+            yield sl, mask[i,...]
 
     def select_tcoords(self, dobj):
         # These will not be pre-allocated, which can be a problem for speed and

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/frontends/artio/_artio_caller.pyx
--- a/yt/frontends/artio/_artio_caller.pyx
+++ b/yt/frontends/artio/_artio_caller.pyx
@@ -8,9 +8,7 @@
 from yt.utilities.lib.fp_utils cimport imax
 from yt.geometry.oct_container cimport \
     SparseOctreeContainer
-from yt.geometry.oct_visitors cimport \
-    OctVisitorData, oct_visitor_function, Oct, \
-    fill_file_indices_oind, fill_file_indices_rind
+from yt.geometry.oct_visitors cimport Oct
 from yt.geometry.particle_deposit cimport \
     ParticleDepositOperation
 from libc.stdint cimport int32_t, int64_t

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/oct_container.pxd
--- a/yt/geometry/oct_container.pxd
+++ b/yt/geometry/oct_container.pxd
@@ -19,8 +19,7 @@
 from fp_utils cimport *
 cimport oct_visitors
 cimport selection_routines
-from .oct_visitors cimport \
-    OctVisitorData, oct_visitor_function, Oct, cind
+from .oct_visitors cimport OctVisitor, Oct, cind
 from libc.stdlib cimport bsearch, qsort, realloc, malloc, free
 from libc.math cimport floor
 
@@ -59,7 +58,6 @@
     cdef OctAllocationContainer *cont
     cdef OctAllocationContainer **domains
     cdef Oct ****root_mesh
-    cdef oct_visitor_function *fill_func
     cdef int partial_coverage
     cdef int level_offset
     cdef int nn[3]
@@ -79,13 +77,14 @@
     cdef np.int64_t get_domain_offset(self, int domain_id)
     cdef void visit_all_octs(self,
                         selection_routines.SelectorObject selector,
-                        oct_visitor_function *func,
-                        OctVisitorData *data,
+                        OctVisitor visitor,
                         int vc = ?)
     cdef Oct *next_root(self, int domain_id, int ind[3])
     cdef Oct *next_child(self, int domain_id, int ind[3], Oct *parent)
-    cdef void setup_data(self, OctVisitorData *data, int domain_id = ?)
     cdef void append_domain(self, np.int64_t domain_count)
+    # The fill_style is the ordering, C or F, of the octs in the file.  "o"
+    # corresponds to C, and "r" is for Fortran.
+    cdef public object fill_style
 
 cdef class SparseOctreeContainer(OctreeContainer):
     cdef OctKey *root_nodes

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/oct_container.pyx
--- a/yt/geometry/oct_container.pyx
+++ b/yt/geometry/oct_container.pyx
@@ -99,7 +99,7 @@
             self.DLE[i] = domain_left_edge[i] #0
             self.DRE[i] = domain_right_edge[i] #num_grid
         self._initialize_root_mesh()
-        self.fill_func = oct_visitors.fill_file_indices_oind
+        self.fill_style = "o"
 
     def _initialize_root_mesh(self):
         self.root_mesh = <Oct****> malloc(sizeof(void*) * self.nn[0])
@@ -132,16 +132,16 @@
                 partial_coverage = header['partial_coverage'])
         # NOTE: We do not allow domain/file indices to be specified.
         cdef SelectorObject selector = selection_routines.AlwaysSelector(None)
-        cdef OctVisitorData data
-        obj.setup_data(&data, -1)
+        cdef oct_visitors.LoadOctree visitor
+        visitor = oct_visitors.LoadOctree(obj, -1)
         cdef int i, j, k, n
-        data.global_index = -1
-        data.level = 0
-        data.oref = 0
-        data.nz = 1
-        assert(ref_mask.shape[0] / float(data.nz) ==
-            <int>(ref_mask.shape[0]/float(data.nz)))
-        obj.allocate_domains([ref_mask.shape[0] / data.nz])
+        visitor.global_index = -1
+        visitor.level = 0
+        visitor.oref = 0
+        visitor.nz = 1
+        assert(ref_mask.shape[0] / float(visitor.nz) ==
+            <int>(ref_mask.shape[0]/float(visitor.nz)))
+        obj.allocate_domains([ref_mask.shape[0] / visitor.nz])
         cdef np.float64_t pos[3]
         cdef np.float64_t dds[3]
         # This dds is the oct-width
@@ -150,13 +150,11 @@
         # Pos is the center of the octs
         cdef OctAllocationContainer *cur = obj.domains[0]
         cdef Oct *o
-        cdef void *p[4]
         cdef np.int64_t nfinest = 0
-        p[0] = ref_mask.data
-        p[1] = <void *> cur.my_octs
-        p[2] = <void *> &cur.n_assigned
-        p[3] = <void *> &nfinest
-        data.array = p
+        visitor.ref_mask = ref_mask
+        visitor.octs = cur.my_octs
+        visitor.nocts = &cur.n_assigned
+        visitor.nfinest = &nfinest
         pos[0] = obj.DLE[0] + dds[0]/2.0
         for i in range(obj.nn[0]):
             pos[1] = obj.DLE[1] + dds[1]/2.0
@@ -170,38 +168,22 @@
                     o.domain = 1
                     obj.root_mesh[i][j][k] = o
                     cur.n_assigned += 1
-                    data.pos[0] = i
-                    data.pos[1] = j
-                    data.pos[2] = k
+                    visitor.pos[0] = i
+                    visitor.pos[1] = j
+                    visitor.pos[2] = k
                     # Always visit covered
                     selector.recursively_visit_octs(
                         obj.root_mesh[i][j][k],
-                        pos, dds, 0, oct_visitors.load_octree,
-                        &data, 1)
+                        pos, dds, 0, visitor, 1)
                     pos[2] += dds[2]
                 pos[1] += dds[1]
             pos[0] += dds[0]
         obj.nocts = cur.n_assigned
-        if obj.nocts * data.nz != ref_mask.size:
+        if obj.nocts * visitor.nz != ref_mask.size:
             raise KeyError(ref_mask.size, obj.nocts, obj.oref,
                 obj.partial_coverage)
         return obj
 
-    cdef void setup_data(self, OctVisitorData *data, int domain_id = -1):
-        cdef int i
-        data.index = 0
-        data.last = -1
-        data.global_index = -1
-        for i in range(3):
-            data.pos[i] = -1
-            data.ind[i] = -1
-        data.array = NULL
-        data.dims = 0
-        data.domain = domain_id
-        data.level = -1
-        data.oref = self.oref
-        data.nz = (1 << (data.oref*3))
-
     def __dealloc__(self):
         free_octs(self.cont)
         if self.root_mesh == NULL: return
@@ -229,14 +211,12 @@
 
     @cython.cdivision(True)
     cdef void visit_all_octs(self, SelectorObject selector,
-                        oct_visitor_function *func,
-                        OctVisitorData *data,
-                        int vc = -1):
+                        OctVisitor visitor, int vc = -1):
         cdef int i, j, k, n
         if vc == -1:
             vc = self.partial_coverage
-        data.global_index = -1
-        data.level = 0
+        visitor.global_index = -1
+        visitor.level = 0
         cdef np.float64_t pos[3]
         cdef np.float64_t dds[3]
         # This dds is the oct-width
@@ -251,12 +231,12 @@
                 for k in range(self.nn[2]):
                     if self.root_mesh[i][j][k] == NULL:
                         raise RuntimeError
-                    data.pos[0] = i
-                    data.pos[1] = j
-                    data.pos[2] = k
+                    visitor.pos[0] = i
+                    visitor.pos[1] = j
+                    visitor.pos[2] = k
                     selector.recursively_visit_octs(
                         self.root_mesh[i][j][k],
-                        pos, dds, 0, func, data, vc)
+                        pos, dds, 0, visitor, vc)
                     pos[2] += dds[2]
                 pos[1] += dds[1]
             pos[0] += dds[0]
@@ -340,10 +320,10 @@
     def domain_identify(self, SelectorObject selector):
         cdef np.ndarray[np.uint8_t, ndim=1] domain_mask
         domain_mask = np.zeros(self.num_domains, dtype="uint8")
-        cdef OctVisitorData data
-        self.setup_data(&data)
-        data.array = domain_mask.data
-        self.visit_all_octs(selector, oct_visitors.identify_octs, &data)
+        cdef oct_visitors.IdentifyOcts visitor
+        visitor = oct_visitors.IdentifyOcts(self)
+        visitor.domain_mask = domain_mask
+        self.visit_all_octs(selector, visitor)
         cdef int i
         domain_ids = []
         for i in range(self.num_domains):
@@ -441,13 +421,14 @@
              int domain_id = -1):
         if num_cells == -1:
             num_cells = selector.count_octs(self, domain_id)
-        cdef np.ndarray[np.uint8_t, ndim=1] coords
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
-        coords = np.zeros((num_cells*data.nz), dtype="uint8")
-        data.array = <void *> coords.data
-        self.visit_all_octs(selector, oct_visitors.mask_octs, &data)
-        return coords.astype("bool")
+        cdef np.ndarray[np.uint8_t, ndim=4] mask
+        cdef oct_visitors.MaskOcts visitor
+        visitor = oct_visitors.MaskOcts(self, domain_id)
+        cdef int ns = 1 << self.oref
+        mask = np.zeros((num_cells, ns, ns, ns), dtype="uint8")
+        visitor.mask = mask
+        self.visit_all_octs(selector, visitor)
+        return mask.astype("bool")
 
     @cython.boundscheck(False)
     @cython.wraparound(False)
@@ -456,12 +437,12 @@
                 int domain_id = -1):
         if num_cells == -1:
             num_cells = selector.count_oct_cells(self, domain_id)
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
+        cdef oct_visitors.ICoordsOcts visitor
+        visitor = oct_visitors.ICoordsOcts(self, domain_id)
         cdef np.ndarray[np.int64_t, ndim=2] coords
         coords = np.empty((num_cells, 3), dtype="int64")
-        data.array = <void *> coords.data
-        self.visit_all_octs(selector, oct_visitors.icoords_octs, &data)
+        visitor.icoords = coords
+        self.visit_all_octs(selector, visitor)
         return coords
 
     @cython.boundscheck(False)
@@ -472,13 +453,13 @@
         cdef int i
         if num_cells == -1:
             num_cells = selector.count_oct_cells(self, domain_id)
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
+        cdef oct_visitors.IResOcts visitor
+        visitor = oct_visitors.IResOcts(self, domain_id)
         #Return the 'resolution' of each cell; ie the level
         cdef np.ndarray[np.int64_t, ndim=1] res
         res = np.empty(num_cells, dtype="int64")
-        data.array = <void *> res.data
-        self.visit_all_octs(selector, oct_visitors.ires_octs, &data)
+        visitor.ires = res
+        self.visit_all_octs(selector, visitor)
         if self.level_offset > 0:
             for i in range(num_cells):
                 res[i] += self.level_offset
@@ -491,12 +472,12 @@
                 int domain_id = -1):
         if num_cells == -1:
             num_cells = selector.count_oct_cells(self, domain_id)
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
+        cdef oct_visitors.FWidthOcts visitor
+        visitor = oct_visitors.FWidthOcts(self, domain_id)
         cdef np.ndarray[np.float64_t, ndim=2] fwidth
         fwidth = np.empty((num_cells, 3), dtype="float64")
-        data.array = <void *> fwidth.data
-        self.visit_all_octs(selector, oct_visitors.fwidth_octs, &data)
+        visitor.fwidth = fwidth
+        self.visit_all_octs(selector, visitor)
         cdef np.float64_t base_dx
         for i in range(3):
             base_dx = (self.DRE[i] - self.DLE[i])/self.nn[i]
@@ -510,13 +491,13 @@
                 int domain_id = -1):
         if num_cells == -1:
             num_cells = selector.count_oct_cells(self, domain_id)
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
+        cdef oct_visitors.FCoordsOcts visitor
+        visitor = oct_visitors.FCoordsOcts(self, domain_id)
         #Return the floating point unitary position of every cell
         cdef np.ndarray[np.float64_t, ndim=2] coords
         coords = np.empty((num_cells, 3), dtype="float64")
-        data.array = <void *> coords.data
-        self.visit_all_octs(selector, oct_visitors.fcoords_octs, &data)
+        visitor.fcoords = coords
+        self.visit_all_octs(selector, visitor)
         cdef int i
         cdef np.float64_t base_dx
         for i in range(3):
@@ -534,17 +515,15 @@
                       partial_coverage = self.partial_coverage)
         cdef SelectorObject selector = selection_routines.AlwaysSelector(None)
         # domain_id = -1 here, because we want *every* oct
-        cdef OctVisitorData data
-        self.setup_data(&data, -1)
-        data.oref = 0
-        data.nz = 1
+        cdef oct_visitors.StoreOctree visitor
+        visitor = oct_visitors.StoreOctree(self, -1)
+        visitor.oref = 0
+        visitor.nz = 1
         cdef np.ndarray[np.uint8_t, ndim=1] ref_mask
-        ref_mask = np.zeros(self.nocts * data.nz, dtype="uint8") - 1
-        cdef void *p[1]
-        p[0] = ref_mask.data
-        data.array = p
+        ref_mask = np.zeros(self.nocts * visitor.nz, dtype="uint8") - 1
+        visitor.ref_mask = ref_mask
         # Enforce partial_coverage here
-        self.visit_all_octs(selector, oct_visitors.store_octree, &data, 1)
+        self.visit_all_octs(selector, visitor, 1)
         header['octree'] = ref_mask
         return header
 
@@ -562,53 +541,60 @@
             # means we actually do want the number of Octs, not the number of
             # cells.
             num_cells = selector.count_oct_cells(self, domain_id)
-            if dims > 1:
-                dest = np.zeros((num_cells, dims), dtype=source.dtype,
-                    order='C')
-            else:
-                dest = np.zeros(num_cells, dtype=source.dtype, order='C')
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
-        data.index = offset
-        # We only need this so we can continue calculating the offset
-        data.dims = dims
-        cdef void *p[2]
-        p[0] = source.data
-        p[1] = dest.data
-        data.array = &p
-        cdef oct_visitor_function *func
+            dest = np.zeros((num_cells, dims), dtype=source.dtype,
+                            order='C')
+        if dims != 1:
+            raise RuntimeError
+        # Just make sure that we're in the right shape.  Ideally this will not
+        # duplicate memory.  Since we're in Cython, we want to avoid modifying
+        # the .shape attributes directly.
+        dest = dest.reshape((num_cells, 1))
+        source = source.reshape((source.shape[0], source.shape[1],
+                    source.shape[2], source.shape[3], dims))
+        cdef OctVisitor visitor
+        cdef oct_visitors.CopyArrayI64 visitor_i64
+        cdef oct_visitors.CopyArrayF64 visitor_f64
         if source.dtype != dest.dtype:
             raise RuntimeError
         if source.dtype == np.int64:
-            func = oct_visitors.copy_array_i64
+            visitor_i64 = oct_visitors.CopyArrayI64(self, domain_id)
+            visitor_i64.source = source
+            visitor_i64.dest = dest
+            visitor = visitor_i64
         elif source.dtype == np.float64:
-            func = oct_visitors.copy_array_f64
+            visitor_f64 = oct_visitors.CopyArrayF64(self, domain_id)
+            visitor_f64.source = source
+            visitor_f64.dest = dest
+            visitor = visitor_f64
         else:
             raise NotImplementedError
-        self.visit_all_octs(selector, func, &data)
-        if (data.global_index + 1) * data.nz * data.dims > source.size:
+        visitor.index = offset
+        # We only need this so we can continue calculating the offset
+        visitor.dims = dims
+        self.visit_all_octs(selector, visitor)
+        if (visitor.global_index + 1) * visitor.nz * visitor.dims > source.size:
             print "GLOBAL INDEX RAN AHEAD.",
-            print (data.global_index + 1) * data.nz * data.dims - source.size
+            print (visitor.global_index + 1) * visitor.nz * visitor.dims - source.size
             print dest.size, source.size, num_cells
             raise RuntimeError
-        if data.index > dest.size:
+        if visitor.index > dest.size:
             print "DEST INDEX RAN AHEAD.",
-            print data.index - dest.size
-            print (data.global_index + 1) * data.nz * data.dims, source.size
+            print visitor.index - dest.size
+            print (visitor.global_index + 1) * visitor.nz * visitor.dims, source.size
             print num_cells
             raise RuntimeError
         if num_cells >= 0:
             return dest
-        return data.index - offset
+        return visitor.index - offset
 
     def domain_ind(self, selector, int domain_id = -1):
         cdef np.ndarray[np.int64_t, ndim=1] ind
         # Here's where we grab the masked items.
         ind = np.zeros(self.nocts, 'int64') - 1
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
-        data.array = ind.data
-        self.visit_all_octs(selector, oct_visitors.index_octs, &data)
+        cdef oct_visitors.IndexOcts visitor
+        visitor = oct_visitors.IndexOcts(self, domain_id)
+        visitor.oct_index = ind
+        self.visit_all_octs(selector, visitor)
         return ind
 
     @cython.boundscheck(False)
@@ -740,14 +726,23 @@
             levels[i] = 100
             file_inds[i] = -1
             cell_inds[i] = 9
-        cdef OctVisitorData data
-        self.setup_data(&data, domain_id)
-        cdef void *p[3]
-        p[0] = levels.data
-        p[1] = file_inds.data
-        p[2] = cell_inds.data
-        data.array = p
-        self.visit_all_octs(selector, self.fill_func, &data)
+        cdef oct_visitors.FillFileIndicesO visitor_o
+        cdef oct_visitors.FillFileIndicesR visitor_r
+        if self.fill_style == "r":
+            visitor_r = oct_visitors.FillFileIndicesR(self, domain_id)
+            visitor_r.levels = levels
+            visitor_r.file_inds = file_inds
+            visitor_r.cell_inds = cell_inds
+            visitor = visitor_r
+        elif self.fill_style == "o":
+            visitor_o = oct_visitors.FillFileIndicesO(self, domain_id)
+            visitor_o.levels = levels
+            visitor_o.file_inds = file_inds
+            visitor_o.cell_inds = cell_inds
+            visitor = visitor_o
+        else:
+            raise RuntimeError
+        self.visit_all_octs(selector, visitor)
         return levels, cell_inds, file_inds
 
     def domain_count(self, SelectorObject selector):
@@ -755,10 +750,10 @@
         cdef np.int64_t i, num_octs
         cdef np.ndarray[np.int64_t, ndim=1] domain_counts
         domain_counts = np.zeros(self.num_domains, dtype="int64")
-        cdef OctVisitorData data
-        self.setup_data(&data, -1)
-        data.array = <void*> domain_counts.data
-        self.visit_all_octs(selector, oct_visitors.count_by_domain, &data)
+        cdef oct_visitors.CountByDomain visitor
+        visitor = oct_visitors.CountByDomain(self, -1)
+        visitor.domain_counts = domain_counts
+        self.visit_all_octs(selector, visitor)
         return domain_counts
 
     @cython.boundscheck(False)
@@ -786,10 +781,10 @@
 
     def finalize(self):
         cdef SelectorObject selector = selection_routines.AlwaysSelector(None)
-        cdef OctVisitorData data
-        self.setup_data(&data, 1)
-        self.visit_all_octs(selector, oct_visitors.assign_domain_ind, &data)
-        assert ((data.global_index+1)*data.nz == data.index)
+        cdef oct_visitors.AssignDomainInd visitor
+        visitor = oct_visitors.AssignDomainInd(self, 1)
+        self.visit_all_octs(selector, visitor)
+        assert ((visitor.global_index+1)*visitor.nz == visitor.index)
 
 cdef int root_node_compare(void *a, void *b) nogil:
     cdef OctKey *ao
@@ -824,7 +819,7 @@
         for i in range(3):
             self.DLE[i] = domain_left_edge[i] #0
             self.DRE[i] = domain_right_edge[i] #num_grid
-        self.fill_func = oct_visitors.fill_file_indices_rind
+        self.fill_style = "r"
 
     @classmethod
     def load_octree(self, header):
@@ -869,13 +864,12 @@
 
     @cython.cdivision(True)
     cdef void visit_all_octs(self, SelectorObject selector,
-                        oct_visitor_function *func,
-                        OctVisitorData *data,
+                        OctVisitor visitor,
                         int vc = -1):
         cdef int i, j, k, n
         cdef np.int64_t key, ukey
-        data.global_index = -1
-        data.level = 0
+        visitor.global_index = -1
+        visitor.level = 0
         if vc == -1:
             vc = self.partial_coverage
         cdef np.float64_t pos[3]
@@ -888,11 +882,11 @@
         for i in range(self.num_root):
             o = self.root_nodes[i].node
             key = self.root_nodes[i].key
-            self.key_to_ipos(key, data.pos)
+            self.key_to_ipos(key, visitor.pos)
             for j in range(3):
-                pos[j] = self.DLE[j] + (data.pos[j] + 0.5) * dds[j]
+                pos[j] = self.DLE[j] + (visitor.pos[j] + 0.5) * dds[j]
             selector.recursively_visit_octs(
-                o, pos, dds, 0, func, data, vc)
+                o, pos, dds, 0, visitor, vc)
 
     cdef np.int64_t get_domain_offset(self, int domain_id):
         return 0 # We no longer have a domain offset.
@@ -946,7 +940,7 @@
         OctreeContainer.__init__(self, oct_domain_dimensions,
                 domain_left_edge, domain_right_edge, partial_coverage,
                  over_refine)
-        self.fill_func = oct_visitors.fill_file_indices_rind
+        self.fill_style = "r"
 
 cdef OctList *OctList_subneighbor_find(OctList *olist, Oct *top,
                                        int i, int j, int k):

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/oct_visitors.pxd
--- a/yt/geometry/oct_visitors.pxd
+++ b/yt/geometry/oct_visitors.pxd
@@ -30,50 +30,97 @@
     np.int64_t domain
     np.int64_t padding
 
-cdef struct OctVisitorData:
-    np.uint64_t index
-    np.uint64_t last
-    np.int64_t global_index
-    np.int64_t pos[3]       # position in ints
-    np.uint8_t ind[3]              # cell position
-    void *array
-    int dims
-    np.int32_t domain
-    np.int8_t level
-    np.int8_t oref # This is the level of overref.  1 => 8 zones, 2 => 64, etc.
-                   # To calculate nzones, 1 << (oref * 3)
-    np.int32_t nz
-                            
-ctypedef void oct_visitor_function(Oct *, OctVisitorData *visitor,
-                                   np.uint8_t selected)
+cdef class OctVisitor:
+    cdef np.uint64_t index
+    cdef np.uint64_t last
+    cdef np.int64_t global_index
+    cdef np.int64_t pos[3]       # position in ints
+    cdef np.uint8_t ind[3]              # cell position
+    cdef int dims
+    cdef np.int32_t domain
+    cdef np.int8_t level
+    cdef np.int8_t oref # This is the level of overref.  1 => 8 zones, 2 => 64, etc.
+                        # To calculate nzones, 1 << (oref * 3)
+    cdef np.int32_t nz
 
-cdef oct_visitor_function count_total_octs
-cdef oct_visitor_function count_total_cells
-cdef oct_visitor_function mark_octs
-cdef oct_visitor_function mask_octs
-cdef oct_visitor_function index_octs
-cdef oct_visitor_function icoords_octs
-cdef oct_visitor_function ires_octs
-cdef oct_visitor_function fcoords_octs
-cdef oct_visitor_function fwidth_octs
-cdef oct_visitor_function copy_array_f64
-cdef oct_visitor_function copy_array_i64
-cdef oct_visitor_function identify_octs
-cdef oct_visitor_function assign_domain_ind
-cdef oct_visitor_function fill_file_indices_oind
-cdef oct_visitor_function fill_file_indices_rind
-cdef oct_visitor_function count_by_domain
-cdef oct_visitor_function store_octree
-cdef oct_visitor_function load_octree
+    # There will also be overrides for the memoryviews associated with the
+    # specific instance.
+
+    cdef void visit(self, Oct*, np.uint8_t selected)
+
+    cdef inline int oind(self):
+        cdef int d = (1 << self.oref)
+        return (((self.ind[0]*d)+self.ind[1])*d+self.ind[2])
+
+    cdef inline int rind(self):
+        cdef int d = (1 << self.oref)
+        return (((self.ind[2]*d)+self.ind[1])*d+self.ind[0])
+
+cdef class CountTotalOcts(OctVisitor):
+    pass
+
+cdef class CountTotalCells(OctVisitor):
+    pass
+
+cdef class MarkOcts(OctVisitor):
+    # Unused
+    cdef np.uint8_t[:,:,:,:] mark
+
+cdef class MaskOcts(OctVisitor):
+    cdef np.uint8_t[:,:,:,:] mask
+
+cdef class IndexOcts(OctVisitor):
+    cdef np.int64_t[:] oct_index
+
+cdef class ICoordsOcts(OctVisitor):
+    cdef np.int64_t[:,:] icoords
+
+cdef class IResOcts(OctVisitor):
+    cdef np.int64_t[:] ires
+
+cdef class FCoordsOcts(OctVisitor):
+    cdef np.float64_t[:,:] fcoords
+
+cdef class FWidthOcts(OctVisitor):
+    cdef np.float64_t[:,:] fwidth
+
+cdef class CopyArrayI64(OctVisitor):
+    cdef np.int64_t[:,:,:,:,:,:] source
+    cdef np.int64_t[:,:] dest
+
+cdef class CopyArrayF64(OctVisitor):
+    cdef np.float64_t[:,:,:,:,:] source
+    cdef np.float64_t[:,:] dest
+
+cdef class IdentifyOcts(OctVisitor):
+    cdef np.uint8_t[:] domain_mask
+
+cdef class AssignDomainInd(OctVisitor):
+    pass
+
+cdef class FillFileIndicesO(OctVisitor):
+    cdef np.uint8_t[:] levels
+    cdef np.uint8_t[:] file_inds
+    cdef np.uint8_t[:] cell_inds
+
+cdef class FillFileIndicesR(OctVisitor):
+    cdef np.uint8_t[:] levels
+    cdef np.int64_t[:] file_inds
+    cdef np.uint8_t[:] cell_inds
+
+cdef class CountByDomain(OctVisitor):
+    cdef np.int64_t[:] domain_counts
+
+cdef class StoreOctree(OctVisitor):
+    cdef np.uint8_t[:] ref_mask
+
+cdef class LoadOctree(OctVisitor):
+    cdef np.uint8_t[:] ref_mask
+    cdef Oct* octs
+    cdef np.int64_t *nocts
+    cdef np.int64_t *nfinest
 
 cdef inline int cind(int i, int j, int k):
     # THIS ONLY WORKS FOR CHILDREN.  It is not general for zones.
     return (((i*2)+j)*2+k)
 
-cdef inline int oind(OctVisitorData *data):
-    cdef int d = (1 << data.oref)
-    return (((data.ind[0]*d)+data.ind[1])*d+data.ind[2])
-
-cdef inline int rind(OctVisitorData *data):
-    cdef int d = (1 << data.oref)
-    return (((data.ind[2]*d)+data.ind[1])*d+data.ind[0])

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/oct_visitors.pyx
--- a/yt/geometry/oct_visitors.pyx
+++ b/yt/geometry/oct_visitors.pyx
@@ -19,209 +19,264 @@
 import numpy
 from fp_utils cimport *
 from libc.stdlib cimport malloc, free
+from yt.geometry.oct_container cimport OctreeContainer
 
 # Now some visitor functions
 
-cdef void copy_array_f64(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We should always have global_index less than our source.
-    # "last" here tells us the dimensionality of the array.
-    if selected == 0: return
-    cdef int i
-    # There are this many records between "octs"
-    cdef np.int64_t index = (data.global_index * data.nz)*data.dims
-    cdef np.float64_t **p = <np.float64_t**> data.array
-    index += oind(data)*data.dims
-    for i in range(data.dims):
-        p[1][data.index + i] = p[0][index + i]
-    data.index += data.dims
+cdef class OctVisitor:
+    def __init__(self, OctreeContainer octree, int domain_id = -1):
+        cdef int i
+        self.index = 0
+        self.last = -1
+        self.global_index = -1
+        for i in range(3):
+            self.pos[i] = -1
+            self.ind[i] = -1
+        self.dims = 0
+        self.domain = domain_id
+        self.level = -1
+        self.oref = octree.oref
+        self.nz = (1 << (self.oref*3))
 
-cdef void copy_array_i64(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We should always have global_index less than our source.
-    # "last" here tells us the dimensionality of the array.
-    if selected == 0: return
-    cdef int i
-    cdef np.int64_t index = (data.global_index * data.nz)*data.dims
-    cdef np.int64_t **p = <np.int64_t**> data.array
-    index += oind(data)*data.dims
-    for i in range(data.dims):
-        p[1][data.index + i] = p[0][index + i]
-    data.index += data.dims
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        raise NotImplementedError
 
-cdef void count_total_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # Count even if not selected.
-    # Number of *octs* visited.
-    if data.last != o.domain_ind:
-        data.index += 1
-        data.last = o.domain_ind
+# This copies an integer array from the source to the destination, based on the
+# selection criteria.
+cdef class CopyArrayI64(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We should always have global_index less than our source.
+        # "last" here tells us the dimensionality of the array.
+        if selected == 0: return
+        # There are this many records between "octs"
+        self.dest[self.index, :] = self.source[
+                self.ind[2], self.ind[1], self.ind[0],
+                self.global_index, :]
+        self.index += 1
 
-cdef void count_total_cells(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # Number of *cells* visited and selected.
-    data.index += selected
+# This copies a floating point array from the source to the destination, based
+# on the selection criteria.
+cdef class CopyArrayF64(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We should always have global_index less than our source.
+        # "last" here tells us the dimensionality of the array.
+        if selected == 0: return
+        # There are this many records between "octs"
+        self.dest[self.index, :] = self.source[
+                self.ind[2], self.ind[1], self.ind[0],
+                self.global_index, :]
+        self.index += 1
 
-cdef void mark_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We mark them even if they are not selected
-    cdef int i
-    cdef np.uint8_t *arr = <np.uint8_t *> data.array
-    if data.last != o.domain_ind:
-        data.last = o.domain_ind
-        data.index += 1
-    cdef np.int64_t index = data.index * data.nz
-    index += oind(data)
-    arr[index] = 1
+# This counts the number of octs, selected or not, that the selector hits.
+# Note that the selector will not recursively visit unselected octs, so this is
+# still useful.
+cdef class CountTotalOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # Count even if not selected.
+        # Number of *octs* visited.
+        if self.last != o.domain_ind:
+            self.index += 1
+            self.last = o.domain_ind
 
-cdef void mask_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    if selected == 0: return
-    cdef int i
-    cdef np.uint8_t *arr = <np.uint8_t *> data.array
-    cdef np.int64_t index = data.global_index * data.nz
-    index += oind(data)
-    arr[index] = 1
+# This counts the number of selected cells.
+cdef class CountTotalCells(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # Number of *cells* visited and selected.
+        self.index += selected
 
-cdef void index_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # Note that we provide an index even if the cell is not selected.
-    cdef int i
-    cdef np.int64_t *arr
-    if data.last != o.domain_ind:
-        data.last = o.domain_ind
-        arr = <np.int64_t *> data.array
-        arr[o.domain_ind] = data.index
-        data.index += 1
+# Every time a cell is visited, mark it.  This will be for all visited octs.
+cdef class MarkOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We mark them even if they are not selected
+        if self.last != o.domain_ind:
+            self.last = o.domain_ind
+            self.index += 1
+        self.mark[self.index, self.ind[2], self.ind[1], self.ind[0]] = 1
 
-cdef void icoords_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    if selected == 0: return
-    cdef np.int64_t *coords = <np.int64_t*> data.array
-    cdef int i
-    for i in range(3):
-        coords[data.index * 3 + i] = (data.pos[i] << data.oref) + data.ind[i]
-    data.index += 1
+# Mask all the selected cells.
+cdef class MaskOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        if selected == 0: return
+        self.mask[self.global_index, self.ind[2], self.ind[1], self.ind[0]] = 1
 
-cdef void ires_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    if selected == 0: return
-    cdef np.int64_t *ires = <np.int64_t*> data.array
-    ires[data.index] = data.level
-    data.index += 1
+# Compute a mapping from domain_ind to flattened index.
+cdef class IndexOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # Note that we provide an index even if the cell is not selected.
+        if self.last != o.domain_ind:
+            self.last = o.domain_ind
+            self.oct_index[o.domain_ind] = self.index
+            self.index += 1
 
- at cython.cdivision(True)
-cdef void fcoords_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # Note that this does not actually give the correct floating point
-    # coordinates.  It gives them in some unit system where the domain is 1.0
-    # in all directions, and assumes that they will be scaled later.
-    if selected == 0: return
-    cdef np.float64_t *fcoords = <np.float64_t*> data.array
-    cdef int i
-    cdef np.float64_t c, dx
-    dx = 1.0 / ((1 << data.oref) << data.level)
-    for i in range(3):
-        c = <np.float64_t> ((data.pos[i] << data.oref ) + data.ind[i])
-        fcoords[data.index * 3 + i] = (c + 0.5) * dx
-    data.index += 1
+# Integer coordinates
+cdef class ICoordsOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        if selected == 0: return
+        cdef int i
+        for i in range(3):
+            self.icoords[self.index,i] = (self.pos[i] << self.oref) + self.ind[i]
+        self.index += 1
 
- at cython.cdivision(True)
-cdef void fwidth_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # Note that this does not actually give the correct floating point
-    # coordinates.  It gives them in some unit system where the domain is 1.0
-    # in all directions, and assumes that they will be scaled later.
-    if selected == 0: return
-    cdef np.float64_t *fwidth = <np.float64_t*> data.array
-    cdef int i
-    cdef np.float64_t dx
-    dx = 1.0 / ((1 << data.oref) << data.level)
-    for i in range(3):
-        fwidth[data.index * 3 + i] = dx
-    data.index += 1
+# Level
+cdef class IResOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        if selected == 0: return
+        self.ires[self.index] = self.level
+        self.index += 1
 
-cdef void identify_octs(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We assume that our domain has *already* been selected by, which means
-    # we'll get all cells within the domain for a by-domain selector and all
-    # cells within the domain *and* selector for the selector itself.
-    if selected == 0: return
-    cdef np.uint8_t *arr = <np.uint8_t *> data.array
-    arr[o.domain - 1] = 1
+# Floating point coordinates
+cdef class FCoordsOcts(OctVisitor):
+    @cython.cdivision(True)
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # Note that this does not actually give the correct floating point
+        # coordinates.  It gives them in some unit system where the domain is 1.0
+        # in all directions, and assumes that they will be scaled later.
+        if selected == 0: return
+        cdef int i
+        cdef np.float64_t c, dx
+        dx = 1.0 / ((1 << self.oref) << self.level)
+        for i in range(3):
+            c = <np.float64_t> ((self.pos[i] << self.oref ) + self.ind[i])
+            self.fcoords[self.index,i] = (c + 0.5) * dx
+        self.index += 1
 
-cdef void assign_domain_ind(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    o.domain_ind = data.global_index
-    data.index += 1
+# Floating point widths; domain modifications are done later.
+cdef class FWidthOcts(OctVisitor):
+    @cython.cdivision(True)
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # Note that this does not actually give the correct floating point
+        # coordinates.  It gives them in some unit system where the domain is 1.0
+        # in all directions, and assumes that they will be scaled later.
+        if selected == 0: return
+        cdef int i
+        cdef np.float64_t dx
+        dx = 1.0 / ((1 << self.oref) << self.level)
+        for i in range(3):
+            self.fwidth[self.index,i] = dx
+        self.index += 1
 
-cdef void fill_file_indices_oind(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We fill these arrays, then inside the level filler we use these as
-    # indices as we fill a second array from the data.
-    if selected == 0: return
-    cdef void **p = <void **> data.array
-    cdef np.uint8_t *level_arr = <np.uint8_t *> p[0]
-    cdef np.int64_t *find_arr = <np.int64_t *> p[1]
-    cdef np.uint8_t *cell_arr = <np.uint8_t *> p[2]
-    level_arr[data.index] = data.level
-    find_arr[data.index] = o.file_ind
-    cell_arr[data.index] = oind(data)
-    data.index +=1
+# Mark which domains are touched by a selector.
+cdef class IdentifyOcts(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We assume that our domain has *already* been selected by, which means
+        # we'll get all cells within the domain for a by-domain selector and all
+        # cells within the domain *and* selector for the selector itself.
+        if selected == 0: return
+        self.domain_mask[o.domain - 1] = 1
 
-cdef void fill_file_indices_rind(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    # We fill these arrays, then inside the level filler we use these as
-    # indices as we fill a second array from the data.
-    if selected == 0: return
-    cdef void **p = <void **> data.array
-    cdef np.uint8_t *level_arr = <np.uint8_t *> p[0]
-    cdef np.int64_t *find_arr = <np.int64_t *> p[1]
-    cdef np.uint8_t *cell_arr = <np.uint8_t *> p[2]
-    level_arr[data.index] = data.level
-    find_arr[data.index] = o.file_ind
-    cell_arr[data.index] = rind(data)
-    data.index +=1
+# Assign domain indices to octs
+cdef class AssignDomainInd(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        o.domain_ind = self.global_index
+        self.index += 1
 
-cdef void count_by_domain(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    cdef np.int64_t *arr
-    if selected == 0: return
-    # NOTE: We do this for every *cell*.
-    arr = <np.int64_t *> data.array
-    arr[o.domain - 1] += 1
+# From the file, fill in C order
+cdef class FillFileIndicesO(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We fill these arrays, then inside the level filler we use these as
+        # indices as we fill a second array from the self.
+        if selected == 0: return
+        self.levels[self.index] = self.level
+        self.file_inds[self.index] = o.file_ind
+        self.cell_inds[self.index] = self.oind()
+        self.index +=1
 
-cdef void store_octree(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    cdef np.uint8_t res, ii
-    cdef np.uint8_t *arr
-    cdef np.uint8_t *always_descend
-    ii = cind(data.ind[0], data.ind[1], data.ind[2])
-    cdef void **p = <void **> data.array
-    arr = <np.uint8_t *> p[0]
-    if o.children == NULL:
-        # Not refined.
-        res = 0
-    else:
-        res = 1
-    arr[data.index] = res
-    data.index += 1
+# From the file, fill in F order
+cdef class FillFileIndicesR(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        # We fill these arrays, then inside the level filler we use these as
+        # indices as we fill a second array from the self.
+        if selected == 0: return
+        self.levels[self.index] = self.level
+        self.file_inds[self.index] = o.file_ind
+        self.cell_inds[self.index] = self.rind()
+        self.index +=1
 
-cdef void load_octree(Oct *o, OctVisitorData *data, np.uint8_t selected):
-    cdef void **p = <void **> data.array
-    cdef np.uint8_t *arr = <np.uint8_t *> p[0]
-    cdef Oct* octs = <Oct*> p[1]
-    cdef np.int64_t *nocts = <np.int64_t*> p[2]
-    cdef np.int64_t *nfinest = <np.int64_t*> p[3]
-    cdef int i, ii
-    ii = cind(data.ind[0], data.ind[1], data.ind[2])
-    if arr[data.index] == 0:
-        # We only want to do this once.  Otherwise we end up with way too many
-        # nfinest for our tastes.
-        if o.file_ind == -1:
-            o.children = NULL
-            o.file_ind = nfinest[0]
-            o.domain = 1
-            nfinest[0] += 1
-    elif arr[data.index] > 0:
-        if arr[data.index] != 1 and arr[data.index] != 8:
-            print "ARRAY CLUE: ", arr[data.index], "UNKNOWN"
+# Count octs by domain
+cdef class CountByDomain(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        if selected == 0: return
+        # NOTE: We do this for every *cell*.
+        self.domain_counts[o.domain - 1] += 1
+
+# Store the refinement mapping of the octree to be loaded later
+cdef class StoreOctree(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        cdef np.uint8_t res, ii
+        ii = cind(self.ind[0], self.ind[1], self.ind[2])
+        if o.children == NULL:
+            # Not refined.
+            res = 0
+        else:
+            res = 1
+        self.ref_mask[self.index] = res
+        self.index += 1
+
+# Go from a refinement mapping to a new octree
+cdef class LoadOctree(OctVisitor):
+    @cython.boundscheck(False)
+    @cython.initializedcheck(False)
+    cdef void visit(self, Oct* o, np.uint8_t selected):
+        cdef int i, ii
+        ii = cind(self.ind[0], self.ind[1], self.ind[2])
+        if self.ref_mask[self.index] == 0:
+            # We only want to do this once.  Otherwise we end up with way too many
+            # nfinest for our tastes.
+            if o.file_ind == -1:
+                o.children = NULL
+                o.file_ind = self.nfinest[0]
+                o.domain = 1
+                self.nfinest[0] += 1
+        elif self.ref_mask[self.index] > 0:
+            if self.ref_mask[self.index] != 1 and self.ref_mask[self.index] != 8:
+                print "ARRAY CLUE: ", self.ref_mask[self.index], "UNKNOWN"
+                raise RuntimeError
+            if o.children == NULL:
+                o.children = <Oct **> malloc(sizeof(Oct *) * 8)
+                for i in range(8):
+                    o.children[i] = NULL
+            for i in range(8):
+                o.children[ii + i] = &self.octs[self.nocts[0]]
+                o.children[ii + i].domain_ind = self.nocts[0]
+                o.children[ii + i].file_ind = -1
+                o.children[ii + i].domain = -1
+                o.children[ii + i].children = NULL
+                self.nocts[0] += 1
+        else:
+            print "SOMETHING IS AMISS", self.index
             raise RuntimeError
-        if o.children == NULL:
-            o.children = <Oct **> malloc(sizeof(Oct *) * 8)
-            for i in range(8):
-                o.children[i] = NULL
-        for i in range(8):
-            o.children[ii + i] = &octs[nocts[0]]
-            o.children[ii + i].domain_ind = nocts[0]
-            o.children[ii + i].file_ind = -1
-            o.children[ii + i].domain = -1
-            o.children[ii + i].children = NULL
-            nocts[0] += 1
-    else:
-        print "SOMETHING IS AMISS", data.index
-        raise RuntimeError
-    data.index += 1
+        self.index += 1

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/particle_oct_container.pyx
--- a/yt/geometry/particle_oct_container.pyx
+++ b/yt/geometry/particle_oct_container.pyx
@@ -15,15 +15,13 @@
 #-----------------------------------------------------------------------------
 
 from oct_container cimport OctreeContainer, Oct, OctInfo, ORDER_MAX
-cimport oct_visitors
 from oct_visitors cimport cind
 from libc.stdlib cimport malloc, free, qsort
 from libc.math cimport floor
 from fp_utils cimport *
 cimport numpy as np
 import numpy as np
-from selection_routines cimport SelectorObject, \
-    OctVisitorData, oct_visitor_function
+from selection_routines cimport SelectorObject
 cimport cython
 
 cdef class ParticleOctreeContainer(OctreeContainer):

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/selection_routines.pxd
--- a/yt/geometry/selection_routines.pxd
+++ b/yt/geometry/selection_routines.pxd
@@ -15,8 +15,7 @@
 #-----------------------------------------------------------------------------
 
 cimport numpy as np
-from oct_visitors cimport Oct, OctVisitorData, \
-    oct_visitor_function
+from oct_visitors cimport Oct, OctVisitor
 from grid_visitors cimport GridTreeNode, GridVisitorData, \
     grid_visitor_function, check_child_masked
 
@@ -43,12 +42,11 @@
     cdef void recursively_visit_octs(self, Oct *root,
                         np.float64_t pos[3], np.float64_t dds[3],
                         int level,
-                        oct_visitor_function *func,
-                        OctVisitorData *data,
+                        OctVisitor visitor,
                         int visit_covered = ?)
-    cdef void visit_oct_cells(self, OctVisitorData *data, Oct *root, Oct *ch,
+    cdef void visit_oct_cells(self, Oct *root, Oct *ch,
                               np.float64_t spos[3], np.float64_t sdds[3],
-                              oct_visitor_function *func, int i, int j, int k)
+                              OctVisitor visitor, int i, int j, int k)
     cdef int select_grid(self, np.float64_t left_edge[3],
                                np.float64_t right_edge[3],
                                np.int32_t level, Oct *o = ?) nogil

diff -r 5beb2280f5c889b80eaa6cfa962e298b105aff1d -r 45dc609be9e893c48cdfc2e568eb26ca0a0f8cbe yt/geometry/selection_routines.pyx
--- a/yt/geometry/selection_routines.pyx
+++ b/yt/geometry/selection_routines.pyx
@@ -164,16 +164,16 @@
         return gridi.astype("bool")
 
     def count_octs(self, OctreeContainer octree, int domain_id = -1):
-        cdef OctVisitorData data
-        octree.setup_data(&data, domain_id)
-        octree.visit_all_octs(self, oct_visitors.count_total_octs, &data)
-        return data.index
+        cdef oct_visitors.CountTotalOcts visitor
+        visitor = oct_visitors.CountTotalOcts(octree, domain_id)
+        octree.visit_all_octs(self, visitor)
+        return visitor.index
 
     def count_oct_cells(self, OctreeContainer octree, int domain_id = -1):
-        cdef OctVisitorData data
-        octree.setup_data(&data, domain_id)
-        octree.visit_all_octs(self, oct_visitors.count_total_cells, &data)
-        return data.index
+        cdef oct_visitors.CountTotalCells visitor
+        visitor = oct_visitors.CountTotalCells(octree, domain_id)
+        octree.visit_all_octs(self, visitor)
+        return visitor.index
 
     @cython.boundscheck(False)
     @cython.wraparound(False)
@@ -181,8 +181,7 @@
     cdef void recursively_visit_octs(self, Oct *root,
                         np.float64_t pos[3], np.float64_t dds[3],
                         int level,
-                        oct_visitor_function *func,
-                        OctVisitorData *data,
+                        OctVisitor visitor,
                         int visit_covered = 0):
         # visit_covered tells us whether this octree supports partial
         # refinement.  If it does, we need to handle this specially -- first
@@ -203,7 +202,7 @@
             RE[i] = pos[i] + dds[i]/2.0
         #print LE[0], RE[0], LE[1], RE[1], LE[2], RE[2]
         res = self.select_grid(LE, RE, level, root)
-        if res == 1 and data.domain > 0 and root.domain != data.domain:
+        if res == 1 and visitor.domain > 0 and root.domain != visitor.domain:
             res = -1
         cdef int increment = 1
         cdef int next_level, this_level
@@ -243,52 +242,52 @@
                         if root.children != NULL:
                             ch = root.children[cind(i, j, k)]
                         if iter == 1 and next_level == 1 and ch != NULL:
-                            # Note that data.pos is always going to be the
+                            # Note that visitor.pos is always going to be the
                             # position of the Oct -- it is *not* always going
                             # to be the same as the position of the cell under
                             # investigation.
-                            data.pos[0] = (data.pos[0] << 1) + i
-                            data.pos[1] = (data.pos[1] << 1) + j
-                            data.pos[2] = (data.pos[2] << 1) + k
-                            data.level += 1
+                            visitor.pos[0] = (visitor.pos[0] << 1) + i
+                            visitor.pos[1] = (visitor.pos[1] << 1) + j
+                            visitor.pos[2] = (visitor.pos[2] << 1) + k
+                            visitor.level += 1
                             self.recursively_visit_octs(
-                                ch, spos, sdds, level + 1, func, data,
+                                ch, spos, sdds, level + 1, visitor,
                                 visit_covered)
-                            data.pos[0] = (data.pos[0] >> 1)
-                            data.pos[1] = (data.pos[1] >> 1)
-                            data.pos[2] = (data.pos[2] >> 1)
-                            data.level -= 1
-                        elif this_level == 1 and data.oref > 0:
-                            data.global_index += increment
+                            visitor.pos[0] = (visitor.pos[0] >> 1)
+                            visitor.pos[1] = (visitor.pos[1] >> 1)
+                            visitor.pos[2] = (visitor.pos[2] >> 1)
+                            visitor.level -= 1
+                        elif this_level == 1 and visitor.oref > 0:
+                            visitor.global_index += increment
                             increment = 0
-                            self.visit_oct_cells(data, root, ch, spos, sdds,
-                                                 func, i, j, k)
+                            self.visit_oct_cells(root, ch, spos, sdds,
+                                                 visitor, i, j, k)
                         elif this_level == 1 and increment == 1:
-                            data.global_index += increment
+                            visitor.global_index += increment
                             increment = 0
-                            data.ind[0] = data.ind[1] = data.ind[2] = 0
-                            func(root, data, 1)
+                            visitor.ind[0] = visitor.ind[1] = visitor.ind[2] = 0
+                            visitor.visit(root, 1)
                         spos[2] += sdds[2]
                     spos[1] += sdds[1]
                 spos[0] += sdds[0]
             this_level = 0 # We turn this off for the second pass.
             iter += 1
 
-    cdef void visit_oct_cells(self, OctVisitorData *data, Oct *root, Oct *ch,
+    cdef void visit_oct_cells(self, Oct *root, Oct *ch,
                               np.float64_t spos[3], np.float64_t sdds[3],
-                              oct_visitor_function *func, int i, int j, int k):
+                              OctVisitor visitor, int i, int j, int k):
         # We can short-circuit the whole process if data.oref == 1.
         # This saves us some funny-business.
         cdef int selected
-        if data.oref == 1:
+        if visitor.oref == 1:
             selected = self.select_cell(spos, sdds)
             if ch != NULL:
                 selected *= self.overlap_cells
-            # data.ind refers to the cell, not to the oct.
-            data.ind[0] = i
-            data.ind[1] = j
-            data.ind[2] = k
-            func(root, data, selected)
+            # visitor.ind refers to the cell, not to the oct.
+            visitor.ind[0] = i
+            visitor.ind[1] = j
+            visitor.ind[2] = k
+            visitor.visit(root, selected)
             return
         # Okay, now that we've got that out of the way, we have to do some
         # other checks here.  In this case, spos[] is the position of the
@@ -298,7 +297,7 @@
         cdef np.float64_t dds[3]
         cdef np.float64_t pos[3]
         cdef int ci, cj, ck
-        cdef int nr = (1 << (data.oref - 1))
+        cdef int nr = (1 << (visitor.oref - 1))
         for ci in range(3):
             dds[ci] = sdds[ci] / nr
         # Boot strap at the first index.
@@ -311,10 +310,10 @@
                     selected = self.select_cell(pos, dds)
                     if ch != NULL:
                         selected *= self.overlap_cells
-                    data.ind[0] = ci + i * nr
-                    data.ind[1] = cj + j * nr
-                    data.ind[2] = ck + k * nr
-                    func(root, data, selected)
+                    visitor.ind[0] = ci + i * nr
+                    visitor.ind[1] = cj + j * nr
+                    visitor.ind[2] = ck + k * nr
+                    visitor.visit(root, selected)
                     pos[2] += dds[2]
                 pos[1] += dds[1]
             pos[0] += dds[0]

Repository URL: https://bitbucket.org/yt_analysis/yt/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.



More information about the yt-svn mailing list