コード例 #1
0
    def create_ghost_particles(self, particles, mesh, domain, load_balance, comm, iteration=6):
        """Create initial ghost particles that hug the boundary after
        load balance
        """
        rank = comm.Get_rank()
        size = comm.Get_size()

        # remove current (if any) ghost particles
        particles.remove_tagged_particles(ParticleTAGS.Ghost)
        current_size = particles.get_number_of_particles()

        # create initial ghost particles, particles is now larger
        # these particles are centered in neighboring boundary leaf
        # cells of the octree
        load_balance.create_boundary_particles(particles, rank)

        # reorder ghost in processors order: exterior have a process id of -1 so
        # their put before interior ghost particles
        ghost_proc = np.array(particles["process"][current_size:])
        ind = np.argsort(ghost_proc)
        ghost_proc = ghost_proc[ind]

        for field in particles.properties.keys():
            array = particles[field][current_size:]
            array[:] = array[ind]

        # allocate arrays for boundary indices
        indices = LongArray()
        corner_ghost = ParticleContainer()

        # sides
        boundary_indices = {
                "left"   : LongArray(),
                "right"  : LongArray(),
                "bottom" : LongArray(),
                "top"    : LongArray(),
                "left-top"     : LongArray(),
                "left-bottom"  : LongArray(),
                "right-top"    : LongArray(),
                "right-bottom" : LongArray()
                }

        send_particles = np.zeros(size, dtype=np.int32)
        recv_particles = np.zeros(size, dtype=np.int32)

        # create ghost interior and exterior particles by iteration, using
        # the mesh to extract the needed neighbors
        for i in range(iteration):

            # build the mesh
            mesh.tessellate()
            cumsum_neighbors = mesh["number of neighbors"].cumsum()

            #---------- create exterior ghost particles ----------#

            # create indices for ghost particles
            ghost_indices = np.arange(current_size, particles.get_number_of_particles())

            # label current ghost as old ghost
            particles['tag'][ghost_indices] = ParticleTAGS.OldGhost

            # select exterior ghost particles
            exterior_ghost = ghost_proc == -1
            exterior_ghost_indices = ghost_indices[exterior_ghost]

            if np.sum(exterior_ghost_indices) > 0:

                num_exterior_ghost = create_reflect_ghost(particles, boundary_indices,
                        domain, exterior_ghost_indices, ghost_indices,
                        mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, -1)

            #---------- create interior ghost particles ----------#
            interior_ghost_indices = ghost_indices[~exterior_ghost]
            interior_ghost_proc = ghost_proc[~exterior_ghost]

            # bin processors - they are in order
            interior_ghost_proc_bin = np.bincount(interior_ghost_proc, minlength=size)

            send_particles[:] = 0
            recv_particles[:] = 0
            indices.reset()

            # collect the indices of particles to be export to each process
            cumsum_proc = interior_ghost_proc_bin.cumsum()
            for proc in range(size):
                if interior_ghost_proc_bin[proc] != 0:

                    start = cumsum_proc[proc] - interior_ghost_proc_bin[proc]
                    end   = cumsum_proc[proc]

                    send_particles[proc] = find_boundary_particles(indices, interior_ghost_indices[start:end], ghost_indices,
                            mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, False)

            # extract data to send and remove the particles
            send_data = {}
            for prop in particles.properties.keys():
                send_data[prop] = np.ascontiguousarray(particles[prop][indices.get_npy_array()])
            send_data["tag"][:] = ParticleTAGS.Ghost

            # how many particles are being sent from each process
            comm.Alltoall(sendbuf=send_particles, recvbuf=recv_particles)
            num_interior_ghost = np.sum(recv_particles)

            # resize arrays to give room for incoming particles
            sp = particles.get_number_of_particles()
            #particles.resize(current_size + num_exterior_ghost + num_interior_ghost)
            particles.extend(num_interior_ghost)

            exchange_particles(particles, send_data, send_particles, recv_particles,
                    sp, comm)

            #---------- create exterior corner ghost particles ----------#
            indices.reset()
            send_particles[:] = 0
            recv_particles[:] = 0

            # clear out corner ghost
            corner_ghost.resize(0)

            if boundary_indices['left'].length > 0:
                export_reflect(particles, corner_ghost, boundary_indices["left"], indices, send_particles, 'x', domain.xmin, ghost_indices,
                        mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, load_balance, current_size, rank, size)

            if boundary_indices['right'].length > 0:
                export_reflect(particles, corner_ghost, boundary_indices["right"], indices, send_particles, 'x', domain.xmax, ghost_indices,
                        mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, load_balance, current_size, rank, size)

            if boundary_indices['bottom'].length > 0:
                export_reflect(particles, corner_ghost, boundary_indices["bottom"], indices, send_particles, 'y', domain.ymin, ghost_indices,
                        mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, load_balance, current_size, rank, size)

            if boundary_indices['top'].length > 0:
                export_reflect(particles, corner_ghost, boundary_indices["top"], indices, send_particles, 'y', domain.ymax, ghost_indices,
                        mesh['neighbors'], mesh['number of neighbors'], cumsum_neighbors, load_balance, current_size, rank, size)

            #print rank, current_size, particles.get_number_of_particles(), current_size + num_exterior_ghost + num_interior_ghost

            sp = particles.get_number_of_particles()
            comm.Alltoall(sendbuf=send_particles, recvbuf=recv_particles)
            particles.extend(np.sum(recv_particles))

            # to export corners have to be reorderd by process
            if corner_ghost.get_number_of_particles() > 0:

                ind = np.argsort(corner_ghost['process'])
                for field in corner_ghost.properties.keys():
                    array = corner_ghost[field]
                    array[:] = array[ind]

                corner_ghost["process"][:] = -1

            # exchange patch corners
            exchange_particles(particles, corner_ghost, send_particles, recv_particles,
                    sp, comm)

            for bd in boundary_indices:
                boundary_indices[bd].reset()

            particles.remove_tagged_particles(ParticleTAGS.OldGhost)

            # put particles in process order for next loop
            ind = np.argsort(particles["process"][current_size:])
            for field in particles.properties.keys():
                array = particles[field][current_size:]
                array[:] = array[ind]

            ghost_proc = np.array(particles["process"][current_size:])

        print 'rank:', rank, 'fraction of real to ghost:', (particles.get_number_of_particles()-current_size)*1.0/particles.get_number_of_particles()
コード例 #2
0
class VoronoiMesh2D(VoronoiMeshBase):
    """
    2d voronoi mesh class
    """
    def __init__(self, *arg, **kw):
        super(VoronoiMesh2D, self).__init__(*arg, **kw)

        self.dim = 2
        self["neighbors"] = None
        self["number of neighbors"] = None
        self["faces"] = None
        self["voronoi vertices"] = None

        face_vars = {
            "area": "double",
            "velocity-x": "double",
            "velocity-y": "double",
            "normal-x": "double",
            "normal-y": "double",
            "com-x": "double",
            "com-y": "double",
            "pair-i": "longlong",
            "pair-j": "longlong",
        }
        self.faces = ParticleContainer(var_dict=face_vars)

    def compute_cell_info(self, particles):
        """
        compute volume and center of mass of all real particles and compute areas, center of mass, normal
        face pairs, and number of faces for faces
        """

        num_faces = mesh.number_of_faces(particles, self["neighbors"],
                                         self["number of neighbors"])
        self.faces.resize(num_faces)

        vol = particles["volume"]
        xcom = particles["com-x"]
        ycom = particles["com-y"]
        vol[:] = 0.0
        xcom[:] = 0.0
        ycom[:] = 0.0

        mesh.cell_face_info_2d(particles, self.faces, self["neighbors"],
                               self["number of neighbors"], self["faces"],
                               self["voronoi vertices"])

    def tessellate(self, particles):
        """
        create 2d voronoi tesselation from particle positions
        """
        # create the tesselation
        vor = Voronoi(particles.T)

        # total number of particles
        num_particles = particles.shape[1]

        # create neighbor and face graph
        neighbor_graph = [[] for i in range(num_particles)]
        face_graph = [[] for i in range(num_particles)]

        # loop through each face collecting the two particles
        # that made that face as well as the face itself
        for i, face in enumerate(vor.ridge_points):

            p1, p2 = face
            neighbor_graph[p1].append(p2)
            neighbor_graph[p2].append(p1)

            face_graph[p1] += vor.ridge_vertices[i]
            face_graph[p2] += vor.ridge_vertices[i]

        # sizes for 1d graphs
        neighbor_graph_sizes = np.array([len(n) for n in neighbor_graph],
                                        dtype=np.int32)

        # graphs in 1d
        neighbor_graph = np.array(list(
            itertools.chain.from_iterable(neighbor_graph)),
                                  dtype=np.int32)
        face_graph = np.array(list(itertools.chain.from_iterable(face_graph)),
                              dtype=np.int32)

        self["neighbors"] = neighbor_graph
        self["number of neighbors"] = neighbor_graph_sizes
        self["faces"] = face_graph
        self["voronoi vertices"] = vor.vertices
コード例 #3
0
class VoronoiMesh2D(VoronoiMeshBase):
    """
    2d voronoi mesh class
    """
    def __init__(self, particles):
        super(VoronoiMesh2D, self).__init__(particles)

        face_vars = {
            "area": "double",
            "velocity-x": "double",
            "velocity-y": "double",
            "normal-x": "double",
            "normal-y": "double",
            "com-x": "double",
            "com-y": "double",
            "pair-i": "longlong",
            "pair-j": "longlong",
        }
        self.faces = ParticleContainer(var_dict=face_vars)

    def compute_cell_info(self):
        """
        compute volume and center of mass of all real particles and compute areas, center of mass, normal
        face pairs, and number of faces for faces
        """

        num_faces = mesh.number_of_faces(self.particles,
                                         self.graph["neighbors"],
                                         self.graph["number of neighbors"])
        self.faces.resize(num_faces)

        # the algorithms are cumulative so we have to zero out the data
        self.particles["volume"][:] = 0.0
        self.particles["com-x"][:] = 0.0
        self.particles["com-y"][:] = 0.0

        mesh.cell_face_info_2d(self.particles, self.faces,
                               self.graph["neighbors"],
                               self.graph["number of neighbors"],
                               self.graph["faces"],
                               self.graph["voronoi vertices"])

    def update_boundary_particles(self):
        cumsum = np.cumsum(self.graph["number of neighbors"], dtype=np.int32)
        mesh.flag_boundary_particles(self.particles, self.graph["neighbors"],
                                     self.graph["number of neighbors"], cumsum)

    def update_second_boundary_particles(self):
        cumsum = np.cumsum(self.graph["number of neighbors"], dtype=np.int32)
        mesh.flag_second_boundary_particles(self.particles,
                                            self.graph["neighbors"],
                                            self.graph["number of neighbors"],
                                            cumsum)

    def tessellate(self):
        """
        create 2d voronoi tesselation from particle positions
        """
        pos = np.array(
            [self.particles["position-x"], self.particles["position-y"]],
            dtype=np.float64)

        # create the tesselation
        vor = Voronoi(pos.T)

        # total number of particles
        num_particles = self.particles.get_number_of_particles()

        # create neighbor and face graph
        neighbor_graph = [[] for i in range(num_particles)]
        face_graph = [[] for i in range(num_particles)]

        # loop through each face collecting the two particles
        # that made that face as well as the face itself
        for i, face in enumerate(vor.ridge_points):

            p1, p2 = face
            neighbor_graph[p1].append(p2)
            neighbor_graph[p2].append(p1)

            face_graph[p1] += vor.ridge_vertices[i]
            face_graph[p2] += vor.ridge_vertices[i]

        # sizes for 1d graphs
        neighbor_graph_sizes = np.array([len(n) for n in neighbor_graph],
                                        dtype=np.int32)

        # graphs in 1d
        neighbor_graph = np.array(list(
            itertools.chain.from_iterable(neighbor_graph)),
                                  dtype=np.int32)
        face_graph = np.array(list(itertools.chain.from_iterable(face_graph)),
                              dtype=np.int32)

        self.graph["neighbors"] = neighbor_graph
        self.graph["number of neighbors"] = neighbor_graph_sizes
        self.graph["faces"] = face_graph
        self.graph["voronoi vertices"] = vor.vertices

    def build_geometry(self, gamma):

        pc = self.particles

        self.tessellate()
        self.update_boundary_particles()
        self.update_second_boundary_particles()  #tmp delete
        self.compute_cell_info()

        indices = np.where((pc['tag'] == ParticleTAGS.Real)
                           | (pc['type'] == ParticleTAGS.Boundary)
                           | (pc['type'] == ParticleTAGS.BoundarySecond))[0]

        # now update primitive variables
        vol = pc['volume'][indices]

        mass = pc['mass'][indices]
        momx = pc['momentum-x'][indices]
        momy = pc['momentum-y'][indices]
        ener = pc['energy'][indices]

        # update primitive variables
        pc['density'][indices] = mass / vol
        pc['velocity-x'][indices] = momx / mass
        pc['velocity-y'][indices] = momy / mass
        pc['pressure'][indices] = (ener / vol - 0.5 * (mass / vol) *
                                   ((momx / mass)**2 +
                                    (momy / mass)**2)) * (gamma - 1.0)