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 )
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()
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
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 )
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()
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()