Ejemplo n.º 1
0
    def _cy_update(self):
        """ Construct the linked lists for the particle arrays using Cython"""

        ncx, ncy, ncz = self.ncx, self.ncy, self.ncz

        mx, my, mz = self.mx, self.my, self.mz
        cell_size = self.cell_size

        cell_size = get_real(self.cell_size, self.cl_precision)

        for i in range(self.narrays):
            pa = self.arrays[i]
            np = pa.get_number_of_particles()

            x, y, z = pa.get('x','y','z')
            if self.cl_precision == 'single':
                x = x.astype(numpy.float32)
                y = y.astype(numpy.float32)
                z = z.astype(numpy.float32)

            cbin( x, y, z,
                  self.cellids[pa.name],
                  self.ix[pa.name],
                  self.iy[pa.name],
                  self.iz[pa.name],
                  self.head[pa.name],
                  self.Next[pa.name],
                  mx, my, mz,
                  numpy.int32(ncx), numpy.int32(ncy), numpy.int32(ncz),
                  cell_size, numpy.int32(np),
                  self.mcx, self.mcy, self.mcz
                  )
Ejemplo n.º 2
0
    def _find_bounds(self):
        """ Find the bounds for the particle arrays.

        The bounds calculated are the simulation cube, defined by the
        minimum and maximum extents of the particle arrays and the
        maximum smoothing length which is used for determining an safe
        cell size for binning.

        """

        inf = numpy.inf

        mx, my, mz = inf, inf, inf
        Mx, My, Mz = -inf, -inf, -inf
        Mh = 0.0

        # update the minimum and maximum for the particle arrays
        for pa in self.arrays:
            pa.read_from_buffer()
            pa.update_min_max(props=['x','y','z','h'])

            if pa.properties['x'].minimum < mx:
                mx = get_real( pa.properties['x'].minimum, self.cl_precision )

            if pa.properties['y'].minimum < my:
                my = get_real( pa.properties['y'].minimum, self.cl_precision )

            if pa.properties['z'].minimum < mz:
                mz = get_real( pa.properties['z'].minimum, self.cl_precision )

            if pa.properties['x'].maximum > Mx:
                Mx = get_real( pa.properties['x'].maximum, self.cl_precision )

            if pa.properties['y'].maximum > My:
                My = get_real( pa.properties['y'].maximum, self.cl_precision )

            if pa.properties['z'].maximum > Mz:
                Mz = get_real( pa.properties['z'].maximum, self.cl_precision )

            if pa.properties['h'].maximum > Mh:
                Mh = get_real( pa.properties['h'].maximum, self.cl_precision )

        self.mx, self.my, self.mz = mx, my, mz
        self.Mx, self.My, self.Mz = Mx, My, Mz
        self.Mh = Mh

        self._set_cell_size()
        self._find_num_cells()
Ejemplo n.º 3
0
    def _set_cell_size(self):
        """ Set the cell size for binning

        Notes:
        ------

        If the cell size is being chosen based on the particle
        smoothing lengths, we choose a cell size slightly larger than
        $k\timesh$, where $k$ is the maximum scale factor for the SPH
        kernel. Currently we use the size k + 1

        If no bin sie is provided, the default
        value 2*max(h) is used

        """
        if not self.const_cell_size:
            self.cell_size = get_real((self.kernel_scale_factor+1)*self.Mh,
                                      self.cl_precision)
        else:
            self.cell_size = self.const_cell_size
Ejemplo n.º 4
0
    def test_get_domain_manager(self):

        particles = self.particles

        domain_manager = particles.get_domain_manager(self.ctx)

        self.assertEqual( domain_manager.cl_precision, "single" )

        self.assertEqual( domain_manager.with_cl, True )

        cell_size = 0.3 * (self.scale_fac + 1.0)
        cell_size = get_real(cell_size, "single")
        self.assertAlmostEqual( domain_manager.cell_size, cell_size, 6 )
        self.assertEqual( domain_manager.ncells, 4 )

        np = 4
        ncells = 4

        head = domain_manager.head['test']
        locks = domain_manager.locks['test']
        next = domain_manager.Next['test']
        cellids = domain_manager.cellids['test']
        ix = domain_manager.ix['test']
        iy = domain_manager.iy['test']
        iz = domain_manager.iz['test']

        for i in range(np):
            self.assertAlmostEqual( next[i], -1, 10 )
            self.assertAlmostEqual( cellids[i], 1.0, 10 )
            self.assertAlmostEqual( ix[i], 1.0, 10 )
            self.assertAlmostEqual( iy[i], 1.0, 10 )
            self.assertAlmostEqual( iz[i], 1.0, 10 )

        for i in range(ncells):
            self.assertAlmostEqual( head[i], -1, 10 )
            self.assertAlmostEqual( locks[i], 0, 10 )
Ejemplo n.º 5
0
    def __init__(self, arrays, cell_size=None, context=None,
                 kernel_scale_factor = 2.0, with_cl=True, device='CPU'):
        """ Construct a RadixSort manager.

        Parameters:
        ------------

        arrays -- list
                The ParticleArrays being managed.

        cell_size -- REAL
                The optional bin size to use

        kernel_scale_factor --REAL.
                the scale factor for the radius

        with_cl -- bool
            Explicitly choose OpenCL


        The RadixSort manager constructs and maintains the following
        attributes for each array being indexed:

        (i) cellids (size=np, uint32) : Flattened cell indices for the particles.
        (ii) indices (size=np, uint32) : Particle indices
        (iii) cell_counts(size=ncells+1, uint32) : Cell count array

        The bin size, if provided is constant in each coordinate
        direction. The default choice for the bin size is twice the
        maximum smoothing length for all particles in the domain.

        """
    
        DomainManager.__init__(self, arrays, context, with_cl, device)

        # set the kernel scale factor
        self.kernel_scale_factor = kernel_scale_factor

        # set the cell size
        self.const_cell_size = cell_size
        if cell_size is not None:
            self.const_cell_size = get_real(cell_size, self.cl_precision)

        # find global bounds (simulation box and ncells)
        self._find_bounds()

        # The arrays stored for the RadixSortManager
        self.cellids = {}
        self.indices = {}
        self.cell_counts = {}

        # setup the RadixSort objects
        self.rsort = rsort = {}
        self._setup_radix_sort()

        # Corresponding device arrays
        self.dcellids = {}
        self.dindices = {}
        self.dcell_counts = {}

        # dict for kernel launch parameters 
        self.global_sizes = {}
        self.local_sizes = {}

        # initialize counter for the iterator
        self._current_cell = 0

        # initialize the host and device buffers
        self._init_buffers()
Ejemplo n.º 6
0
    def __init__(self, arrays, cell_size=None, context=None,
                 kernel_scale_factor = 2.0, with_cl=True):
        """ Construct a linked list manager.

        Parameters:
        ------------

        arrays -- list
                The ParticleArrays being managed.

        cell_size -- REAL
                The optional bin size to use

        kernel_scale_factor --REAL.
                the scale factor for the radius

        with_cl -- bool
            Explicitly choose OpenCL


        A LinkedListManager constructs and maintains a linked list for
        a list of particle arrays. The linked list data structure is
        consists of two arrays per particle array

        head : An integer array of size ncells, where ncells is the
        total number of cells in the domain. Each entry points to the
        index of a particle belonging to the cell. A negative index
        (-1) indicates and empty cell.

        next : An integer array of size num_particles. Each entry
        points to the next particle in the same cell. A negative index
        (-1) indicates no more particles. 

        The bin size, if provided is constant in each coordinate
        direction. The default choice for the bin size is twice the
        maximum smoothing length for all particles in the domain.

        """

        DomainManager.__init__(self, arrays, context, with_cl)

        # set the kernel scale factor
        self.kernel_scale_factor = kernel_scale_factor

        # set the cell size
        self.const_cell_size = cell_size
        if cell_size:
            self.const_cell_size = get_real(cell_size, self.cl_precision)

        # find global bounds (simulation box and ncells)
        self._find_bounds()

        # The linked list structures for the arrays.
        self.Next = {}
        self.head = {}
        self.cellids = {}
        self.locks = {}
        self.indices = {}

        self.ix = {}
        self.iy = {}
        self.iz = {}

        # device linked list structures
        self.dnext = {}
        self.dhead = {}
        self.dcellids = {}
        self.dlocks = {}
        self.dindices = {}

        self.dix = {}
        self.diy = {}
        self.diz = {}

        # dict for kernel launch parameters 
        self.global_sizes = {}
        self.local_sizes = {}

        # initialize counter for the iterator
        self._current_cell = 0

        # initialize the linked list
        self._init_linked_list()