Пример #1
0
    def box_coordinates(self, origin, diameter):
        """
        Return the 8 coordinates of the box associated with the key.

        Let the unit cube be described as follows:

        [
            [0, 0, 0],
            [1, 0, 0],
            [0, 1, 0],
            [1, 1, 0],
            [0, 0, 1],
            [1, 0, 1],
            [0, 1, 1],
            [1, 1, 1]
         ]

        The function returns the box coordinates in the same order
        as the above unit cube coordinates.

        """
        coords = np.empty(24, dtype=np.float64)
        coords_data = ffi.from_buffer("double(*)[24]", coords)

        origin = np.array(origin, dtype=np.float64)
        origin_data = ffi.from_buffer("double(*)[3]", origin)
        diameter = np.array(diameter, dtype=np.float64)
        diameter_data = ffi.from_buffer("double(*)[3]", diameter)

        lib.morton_key_box_coordinates(self.ctype, origin_data, diameter_data,
                                       coords_data)

        return coords.reshape(8, 3)
Пример #2
0
    def from_point(cls, point, origin, diameter):
        """Create a Morton key from a point at the deepest level."""
        point = np.array(point, dtype=np.float64)
        point_data = ffi.from_buffer("double(*)[3]", point)

        origin = np.array(origin, dtype=np.float64)
        origin_data = ffi.from_buffer("double(*)[3]", origin)

        diameter = np.array(diameter, dtype=np.float64)
        diameter_data = ffi.from_buffer("double(*)[3]", diameter)

        return cls(
            lib.morton_key_from_point(point_data, origin_data, diameter_data))
Пример #3
0
    def to_coordinates(self, origin, diameter):
        """Return the coordinates of the anchor."""
        coords = np.empty(3, dtype=np.float64)
        coords_data = ffi.from_buffer("double(*)[3]", coords)
        origin = np.array(origin, dtype=np.float64)
        origin_data = ffi.from_buffer("double(*)[3]", origin)
        diameter = np.array(diameter, dtype=np.float64)
        diameter_data = ffi.from_buffer("double(*)[3]", diameter)

        lib.morton_key_to_coordinates(self.ctype, origin_data, diameter_data,
                                      coords_data)

        return coords
Пример #4
0
    def from_global_points(cls, points, balanced, comm):
        """
        Construct a distributed tree from a set of globally distributed points.

        Params:
        ------
        points : np.array(shape=(n_points, 3), dtype=np.float64)
            Cartesian points at this processor.
        balanced : bool
            If 'True' constructs a balanced tree, if 'False' constructs an unbalanced tree.
        comm : Intracomm
           An mpi4py Intracommunicator.
        """
        points = np.array(points, dtype=np.float64, order="C", copy=False)
        npoints, _ = points.shape
        points_data = ffi.from_buffer(f"double(*)[3]", points)
        balanced_data = ffi.cast("bool", np.bool(balanced))
        npoints_data = ffi.cast("size_t", npoints)
        p_comm = MPI._addressof(comm)
        raw_comm = ffi.cast("uintptr_t*", p_comm)

        return cls(
            lib.distributed_tree_from_points(points_data, npoints_data,
                                             balanced_data, raw_comm),
            comm,
            p_comm,
            raw_comm,
        )
Пример #5
0
    def find_key_in_direction(self, direction):
        """
        Find a key in a given direction.

        Given an integer list `direction` containing
        3 elements, return the key obtained by moving
        from the current key `direction[j]` steps along
        dimension [j]. For example, if `direction = [2, -1, 1]`
        the method returns the key by moving two boxes in positive
        x-direction, one box in the negative y direction and one box
        in the positive z direction. Boxes are counted with respect to
        the current level.

        If there is no box in the given direction, i.e. the new coordinates
        are out of bounds, the method retunrs None.

        """

        direction = np.array(direction, dtype=np.int64)
        direction_data = ffi.from_buffer("int64_t(*)[3]", direction)

        ptr = lib.morton_key_key_in_direction(self.ctype, direction_data)

        if ptr == ffi.NULL:
            return None
        else:
            return MortonKey(ptr)
Пример #6
0
 def children(self):
     """Return the children."""
     ptr = np.empty(8, dtype=np.uint64)
     ptr_data = ffi.from_buffer("uintptr_t *", ptr)
     lib.morton_key_children(self.ctype, ptr_data)
     children = [
         MortonKey(ffi.cast("MortonKey *", ptr[index]))
         for index in range(8)
     ]
     return children
Пример #7
0
 def _clone(self, start, stop):
     """Clone a slice of the exposed Vec<T> into a Python datatype."""
     n = ffi.cast("size_t", len(self))
     nslice = stop - start
     start = ffi.cast("size_t", start)
     stop = ffi.cast("size_t", stop)
     ptr = np.empty(nslice, dtype=np.uint64)
     ptr_data = ffi.from_buffer("uintptr_t *", ptr)
     self._iterator_protocol.clone(self._head, ptr_data, n, start, stop)
     return [
         self._iterator_protocol.p_type(
             ffi.cast(f"{self._iterator_protocol.c_name} *", ptr[index])
         )
         for index in range(nslice)
     ]
Пример #8
0
 def from_global_points(cls, points, comm):
     points = np.array(points, dtype=np.float64, order="C")
     npoints, _ = points.shape
     points_data = ffi.from_buffer(f"double(*)[3]", points)
     n_points_data = ffi.cast("size_t", npoints)
     return cls(lib.domain_from_global_points(points_data, npoints, comm))
Пример #9
0
 def from_anchor(cls, anchor):
     """Create a Morton key from a given anchor."""
     anchor = np.array(anchor, dtype=np.uint64)
     data = ffi.from_buffer("uint64_t(*)[3]", anchor)
     return cls(lib.morton_key_from_anchor(data))