コード例 #1
0
ファイル: Lattice.py プロジェクト: jgslunde/Lanczos
        def __init__(self, box_nr, start_idx_global, a_local, N_fine,
                     corner_coord, nr_dims):
            self.nr_dims = nr_dims
            self.box_nr = box_nr  # Unique global numbering of boxes.
            self.start_idx_global = start_idx_global  # Global index of first point in box.
            self.a_local = a_local  # Local spacing in box, in units of finegrid spacing.
            self.N_fine = N_fine  # Number of finegrid points in each dim.
            self.N_local = math.ceil(
                N_fine / a_local)  # Number of local gridpoints in each dim.
            self.nr_points = self.N_local**nr_dims  # Total number of lattice points (on local grid).
            self.corner_coord = corner_coord  # Coordinate of box corner, where point with idx 0 is located, in units of finegrid spacing s.
            self.local_point_idxs = np.arange(
                0, self.N_local**nr_dims, dtype=int
            )  # Local indexes of points. Idx 0 is at corner_coord, and corresponds to global idx_start.
            self.global_point_idxs = self.local_point_idxs + start_idx_global  # Unique, global index of points in box.
            self.coords_local = get_combinations(
                0, self.N_local - 1, self.nr_dims
            )  # Local coordinates of points in box, in idxs order, in units of local spacing, a.
            self.coords_global = self.coords_local * self.a_local + self.corner_coord  # Above, but in global frame.

            self.neighbors = [
            ]  # List of box_nr for neighboring boxes, in established order. To be filled.
            self.neighbor_displacements = [
            ]  # List of vectors giving relative displacement in each dim of neighboring boxes, i.e. [-1, 0, -1].
            self.neighbor_disp_dict = {
            }  # Reverse of above. Dictionary holding the displacements of neighbors as (binary) keys, and their idxs as elements.

            self.test_constraints()
コード例 #2
0
ファイル: Lattice.py プロジェクト: jgslunde/Lanczos
    def setup_boxes(self, box_depth):
        """Setting up the boxes and relations between them. """
        # Checking some conditions.
        assert box_depth % 2 != 0, f"Currently only accepting odd number of boxes."
        #assert self.N%box_depth == 0, f"Number of boxes in each dim, {box_depth}, must be multiple of number of finegrid points, {self.N}."
        #assert (self.N//box_depth)%2 == 0, f"Number of points per box, {self.N//box_depth}, must be even."

        # Calculating some quantities.
        self.N_per_box = self.N // box_depth
        self.nr_boxes = box_depth**self.nr_dims
        self.a_list = np.array(self.calculate_grid_spacings())
        self.nr_points = np.sum(np.ceil(self.N_per_box /
                                        self.a_list)**self.nr_dims,
                                dtype=int)
        self.box_corners = get_combinations(0, box_depth - 1,
                                            self.nr_dims) * self.N // box_depth
        self.coords = np.zeros((self.nr_points, self.nr_dims), dtype=int)

        # Adding all Box instances to the box-list of Lattice class.
        current_nr_points = 0
        self.get_box_nr_from_idx = np.zeros(self.nr_points, dtype=int)
        for i in range(box_depth**self.nr_dims):
            box = self.Box(i, current_nr_points, self.a_list[i],
                           self.N_per_box, self.box_corners[i], self.nr_dims)
            self.Box_list.append(box)
            print(box.nr_points, box.coords_global.shape)
            self.coords[current_nr_points:current_nr_points +
                        box.nr_points] = box.coords_global
            self.get_box_nr_from_idx[current_nr_points:current_nr_points +
                                     box.nr_points] = i
            current_nr_points += box.nr_points

        displacements = get_combinations(-1, 1, self.nr_dims)
        for i in range(box_depth**self.nr_dims):
            box = self.Box_list[i]
            for j in range(3**self.nr_dims):
                disp = displacements[j]
                neighbor_idx = get_displaced_index(i, disp, box_depth,
                                                   self.nr_dims)
                box.neighbors.append(neighbor_idx)
                box.neighbor_displacements.append(disp)
                box.neighbor_disp_dict[disp.tobytes()] = neighbor_idx
コード例 #3
0
ファイル: Lattice.py プロジェクト: jgslunde/Lanczos
 def IsCloseToEdge(self, idx, D, nr_dims):
     # Returns True if idx is within D steps from a neighboring box, and False otherwise.
     box_nr = self.get_box_nr_from_idx[idx]
     box = self.Box_list[box_nr]
     coords = np.array(
         ravel(idx - box.start_idx_global, box.N_local, self.nr_dims)
     )  # Calculate the "internal" , where 0,0,0 corresponds to box corner.
     disp = get_combinations(-1, 1, self.nr_dims) * D
     neighbor_disp = (coords + disp > box.N_local - 1).astype(int) - (
         coords + disp < 0).astype(int)
     return len(np.unique(neighbor_disp, axis=0)) > 1
コード例 #4
0
ファイル: Lattice.py プロジェクト: jgslunde/Lanczos
 def IsCloseToEdgeWithHigherSpacing(self, idx, D, nr_dims):
     # Returns True if idx is withing D steps from a neighboring box with higher spacing than its own, and False otherwise.
     box_nr = self.get_box_nr_from_idx[idx]
     box = self.Box_list[box_nr]
     coords = np.array(
         ravel(idx - box.start_idx_global, box.N_local, self.nr_dims)
     )  # Calculate the "internal" i,j,k, where 0,0,0 corresponds to box corner.
     disp = get_combinations(-1, 1, self.nr_dims) * D
     neighbor_disp = (coords + disp > box.N_local - 1).astype(int) - (
         coords + disp < 0).astype(int)
     neighbor_disp = np.unique(neighbor_disp, axis=0)
     for x in neighbor_disp:
         if (x != 0).any():
             neighbor_nr = box.neighbor_disp_dict[x.tobytes()]
             if self.a_list[neighbor_nr] > box.a_local:
                 return True
     return False
コード例 #5
0
ファイル: Lattice.py プロジェクト: jgslunde/Lanczos
    def get_nearby_points(self, idx, D, return_disp=False):
        """ Returns the index and displacement of points within D*a_local finegrid
        steps, where a_local is the largest local steplength."""
        box_nr = self.get_box_nr_from_idx[idx]
        box = self.Box_list[box_nr]
        a_local = box.a_local
        disp = get_combinations(-D, D, self.nr_dims)
        coord_local = box.coords_local[idx - box.start_idx_global]
        coord_global = self.coords[idx]
        coords_local = coord_local + disp

        ### CASE 1: Point is entirely inside one box.
        if not self.IsCloseToEdge(idx, D, nr_dims=self.nr_dims):
            idxs = unravel(
                (coords_local.T), box.N_local) + box.start_idx_global

        ### CASE 2: Point is within D of other box(es), but they all have the same spacing.
        elif not self.IsCloseToEdgeWithDifferentSpacing(
                idx, D, self.nr_dims
        ):  # If nearby points crosses into one or more other boxes, but they have identical spacing.
            idxs = np.zeros((1 + 2 * D)**self.nr_dims, dtype=int) - 1
            neighbor_disp = (coords_local > box.N_local - 1).astype(int) - (
                coords_local < 0).astype(int)

            for i in range(disp.shape[0]):
                if (neighbor_disp[i] == 0
                    ).all():  # If this point is in our box.
                    idxs[i] = unravel(coords_local[i],
                                      box.N_local) + box.start_idx_global
                else:
                    neighbor_box_nr = box.neighbor_disp_dict[
                        neighbor_disp[i].tobytes()]
                    neighbor_box = self.Box_list[neighbor_box_nr]
                    neighbor_coord = coords_local[i].copy(
                    ) - neighbor_disp[i] * box.N_local
                    neighbor_coord = (neighbor_coord *
                                      box.a_local) // neighbor_box.a_local
                    idxs[i] = unravel(
                        neighbor_coord,
                        neighbor_box.N_local) + neighbor_box.start_idx_global

        ### CASE 3: Point is within D of other box(es), and they have different spacing.
        else:
            idxs = []
            neighbor_disp = (coords_local > box.N_local - 1).astype(int) - (
                coords_local < 0).astype(int)
            unique_neighbor_disp = np.unique(neighbor_disp, axis=0)

            # FINDING BIGGEST LOCAL a:
            a_local = box.a_local
            for i in range(len(unique_neighbor_disp)):
                neighbor_box_nr = box.neighbor_disp_dict[
                    unique_neighbor_disp[i].tobytes()]
                if self.Box_list[
                        neighbor_box_nr].a_local > a_local:  # If we find another box with higher a, that is the new local a.
                    a_local = self.Box_list[neighbor_box_nr].a_local

            disp = (disp * a_local) // box.a_local
            coords_local = coord_local + disp
            neighbor_disp = (coords_local > box.N_local - 1).astype(int) - (
                coords_local < 0).astype(int)
            unique_neighbor_disp = np.unique(neighbor_disp, axis=0)

            # SEARCHING FOR ALL POINTS WITHIN SET GRID SPACING
            searchcube = np.repeat(
                [[-1, 1]], self.nr_dims,
                axis=0) * a_local * D + coord_local[:, None] * box.a_local
            idxs = []
            for i in range(len(unique_neighbor_disp)):
                neighbor_box_nr = box.neighbor_disp_dict[
                    unique_neighbor_disp[i].tobytes()]
                current_box = self.Box_list[neighbor_box_nr]
                current_searchcube = searchcube - unique_neighbor_disp[
                    i][:, None] * box.N_fine
                current_searchcube.clip(min=0,
                                        max=current_box.N_fine - 1,
                                        out=current_searchcube)
                idxs_in_box = current_box.get_points_in_cube(
                    current_searchcube)
                idxs.extend(idxs_in_box)

            # FINALLY, REMOVE POINTS THAT ARE NOT MIRROR-SYMETRIC ABOUT THE CENTER COORD.
            # Obs: Now dealing only in fine-grid coords. This is very easy to f**k up.
            # if only_symetric:
            cut_idxs = np.ones(len(idxs), dtype=bool)
            for i in range(len(idxs)):
                current_coord = self.coords[idxs[i]]
                mirror_coord = coord_global - (current_coord - coord_global)
                neighbor_disp = (mirror_coord - box.corner_coord >
                                 box.N_fine - 1).astype(int) - (
                                     mirror_coord - box.corner_coord <
                                     0).astype(int)
                neighbor_box_nr = box.neighbor_disp_dict[
                    neighbor_disp.tobytes()]
                neighbor_box = self.Box_list[neighbor_box_nr]
                if (mirror_coord % neighbor_box.a_local != 0).any():
                    cut_idxs[i] = False
            idxs = np.array(idxs)[cut_idxs]
        return np.array(idxs)

        return idxs