コード例 #1
0
    def update_ghost_particles(self, particles, mesh, domain):

        # relabel all particles
        self.flag_exterior_particles(particles, domain.xmin, domain.xmax)

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

        # create new exterior boundary ghost particles
        cumsum_neighbors = mesh["number of neighbors"].cumsum()
        ghost_indices = np.where(particles["tag"] == ParticleTAGS.OldGhost)[0]
        create_reflect_ghost(particles, boundary_indices, domain, ghost_indices,
                ghost_indices, mesh['neighbors'], mesh['number of neighbors'],
                cumsum_neighbors, -1)

        # remove old ghost particles
        particles.remove_tagged_particles(ParticleTAGS.OldGhost)

        # place real particles in begginning of the array
        particles.align_particles()
        particles['type'][:] = ParticleTAGS.Undefined
コード例 #2
0
    def update_ghost_particles(self, particles, mesh, domain, load_balance, comm):

        rank = comm.Get_rank()
        size = comm.Get_size()

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

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

        # we are puting new ghost at the end of the array
        current_size = particles.get_number_of_particles()

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

        # relabel all particles
        particles["tag"][:]  = ParticleTAGS.Undefined
        particles["type"][:] = ParticleTAGS.Undefined

        # flag particles that have left the domain and particles
        # that remained
        load_balance.flag_migrate_particles(particles, rank)

        # find particles that have left the domain
        export_indices = np.where(particles["type"] == ParticleTAGS.ExportInterior)[0]

        if export_indices.size > 0:

            # extract export particles 
            export_particles = particles.extract_items(export_indices)

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

            export_particles["tag"][:]  = ParticleTAGS.Real
            export_particles["type"][:] = ParticleTAGS.Undefined

        else:
            export_particles = ParticleContainer()

        # bin particle process
        send_particles[:] = np.bincount(export_particles["process"], minlength=size)

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

        # create container for incoming particles 
        import_particles = ParticleContainer(np.sum(recv_particles))

        exchange_particles(import_particles, export_particles, send_particles, recv_particles,
                0, comm)

        # copy import particle data to ghost place holders and turn to real particles
        migrate.transfer_migrate_particles(particles, import_particles)

        # flag export particles back to interior ghost particles
        particles["type"][export_indices] = ParticleTAGS.Interior

        ghost_indices = np.where(particles["tag"] == ParticleTAGS.OldGhost)[0]

        # find indices of interior/exterior ghost particles 
        cumsum_neighbors = mesh["number of neighbors"].cumsum()
        exterior_ghost_indices = np.where(particles["type"] == ParticleTAGS.Exterior)[0]
        interior_ghost_indices = np.where(particles["type"] == ParticleTAGS.Interior)[0]

        #---------- create exterior ghost particles ----------#
        num_exterior_ghost = 0
        if exterior_ghost_indices.size > 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 ----------#
        send_particles[:] = 0
        recv_particles[:] = 0
        interior_ghost_proc = particles["process"][interior_ghost_indices]

        # arrange particles in process order
        ind = interior_ghost_proc.argsort()
        interior_ghost_proc = interior_ghost_proc[ind]
        interior_ghost_indices = interior_ghost_indices[ind]

        # bin processors
        interior_ghost_proc_bin = np.bincount(interior_ghost_proc, minlength=size)

        cumsum_neighbors = mesh["number of neighbors"].cumsum()

        # 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.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

        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)

        comm.Alltoall(sendbuf=send_particles, recvbuf=recv_particles)
        sp = particles.get_number_of_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)

        # finally remove old ghost particles from previous time step
        # and also put real particles in front and ghost in the back
        particles.remove_tagged_particles(ParticleTAGS.OldGhost)
        particles.align_particles()

        particles['type'][:] = ParticleTAGS.Undefined
コード例 #3
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()
コード例 #4
0
def create_reflect_ghost(parray, boundary_indices, domain, exterior_ghost_indices,
        ghost_indices, neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank):

    indices = LongArray()

    # sides
    left   = boundary_indices["left"]
    right  = boundary_indices["right"]
    bottom = boundary_indices["bottom"]
    top    = boundary_indices["top"]

    # corners
    lt = boundary_indices["left-top"]
    lb = boundary_indices["left-bottom"]
    rt = boundary_indices["right-top"]
    rb = boundary_indices["right-bottom"]

    xmin = domain.xmin
    xmax = domain.xmax
    ymin = domain.ymin
    ymax = domain.ymax

    x = parray['position-x']
    y = parray['position-y']

    for i in exterior_ghost_indices:

        xi = x[i]; yi = y[i]

        # left boundary condition
        if xi < xmin:

            # left top corner
            if yi > ymax:
                lt.append(i)
            # left bottom corner
            elif yi < ymin:
                lb.append(i)
            # left
            else:
                left.append(i)

        # right boundary condition
        elif xi > xmax:

            # left top corner
            if yi > ymax:
                rt.append(i)
            # left bottom corner
            elif yi < ymin:
                rb.append(i)
            # right
            else:
                right.append(i)

        # bottom boundary condition
        elif yi < ymin:
            bottom.append(i)

        # top boundary condition
        elif yi > ymax:
            top.append(i)

    num_new_ghost = 0

    # left 
    if left.length > 0:
        num_new_ghost += reflect_axis(parray, indices, left, 'x', xmin, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

   # right
    if right.length > 0:
        num_new_ghost += reflect_axis(parray, indices, right, 'x', xmax, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # bottom
    if bottom.length > 0:
        num_new_ghost += reflect_axis(parray, indices, bottom, 'y', ymin, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # top
    if top.length > 0:
        num_new_ghost += reflect_axis(parray, indices, top, 'y', ymax, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # left top
    if lt.length > 0:
        num_new_ghost += reflect_corner(parray, indices, lt, xmin, ymax, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # left bottom
    if lb.length > 0:
        num_new_ghost += reflect_corner(parray, indices, lb, xmin, ymin, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # right top
    if rt.length > 0:
        num_new_ghost += reflect_corner(parray, indices, rt, xmax, ymax, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    # right bottom
    if rb.length > 0:
        num_new_ghost += reflect_corner(parray, indices, rb, xmax, ymin, ghost_indices,
                neighbors_graph, neighbors_graph_size, cumsum_neighbors, rank)

    return num_new_ghost