def _add_prop_or_const(self, name, carray): """Add a new property or constant given the name and carray, note that this assumes that this property is already added to the particle array. """ np_array = self._get_array(carray) g_ary = Array(np_array.dtype, n=carray.length, backend=self.backend) g_ary.set(np_array) self._data[name] = g_ary setattr(self, name, g_ary)
def _remove_particles_bool(self, if_remove): """ Remove particle i if if_remove[i] is True """ num_indices = int(array.sum(if_remove, backend=self.backend)) if num_indices == 0: return num_particles = self.get_number_of_particles() new_indices = Array(np.uint32, n=(num_particles - num_indices), backend=self.backend) num_removed_particles = array.empty(1, dtype=np.int32, backend=self.backend) remove_knl, stride_knl = self._get_remove_particles_bool_kernels() remove_knl(if_remove=if_remove, new_indices=new_indices, num_removed_particles=num_removed_particles, num_particles=num_particles) new_num_particles = num_particles - int(num_removed_particles.get()) strides = set(self._particle_array.stride.values()) s_indices = {1: new_indices} for stride in strides: if stride == 1: continue size = new_num_particles * stride s_index = Array(np.uint32, n=size, backend=self.backend) stride_knl(new_indices, s_index, size, stride) s_indices[stride] = s_index for prop in self.properties: stride = self._particle_array.stride.get(prop, 1) s_index = s_indices[stride] self._data[prop].align(s_index) setattr(self, prop, self._data[prop]) self.align_particles()
def test_align(backend): check_import(backend) # Given dev_array = Array(np.int32, backend=backend) orig_array = array.arange(0, 16, 1, dtype=np.int32, backend=backend) dev_array.set_data(orig_array) indices = array.arange(15, -1, -1, dtype=np.int32, backend=backend) # When dev_array.align(indices) # Then assert np.all(dev_array.get() == indices.get())
def test_remove(backend): check_import(backend) # Given dev_array = Array(np.int32, backend=backend) orig_array = array.arange(0, 16, 1, dtype=np.int32, backend=backend) dev_array.set_data(orig_array) indices = array.arange(0, 8, 1, dtype=np.int32, backend=backend) # When dev_array.remove(indices) # Then assert np.all(dev_array.get() == (8 + indices).get())
def append_parray(self, parray): """ Add particles from a particle array properties that are not there in self will be added """ if parray.gpu is None: parray.set_device_helper(DeviceHelper(parray)) if parray.gpu.get_number_of_particles() == 0: return num_extra_particles = parray.gpu.get_number_of_particles() old_num_particles = self.get_number_of_particles() new_num_particles = num_extra_particles + old_num_particles # extend current arrays by the required number of particles self.extend(num_extra_particles) my_stride = self._particle_array.stride for prop_name in parray.gpu.properties: stride = parray.stride.get(prop_name, 1) if stride > 1 and prop_name not in my_stride: my_stride[prop_name] = stride if prop_name in self.properties: arr = self._data[prop_name] source = parray.gpu.get_device_array(prop_name) arr.dev[old_num_particles * stride:] = source.dev else: # meaning this property is not there in self. dtype = parray.gpu.get_device_array(prop_name).dtype arr = Array(dtype, n=new_num_particles * stride, backend=self.backend) arr.fill(parray.default_values[prop_name]) self.update_prop(prop_name, arr) # now add the values to the end of the created array dest = self._data[prop_name] source = parray.gpu.get_device_array(prop_name) dest.dev[old_num_particles * stride:] = source.dev for const in parray.gpu.constants: if const not in self.constants: arr = parray.gpu.get_device_array(const) self.update_const(const, arr.copy()) if num_extra_particles > 0: self.align_particles()
def remove_particles(self, indices): """ Remove particles whose indices are given in index_list. We repeatedly interchange the values of the last element and values from the index_list and reduce the size of the array by one. This is done for every property that is being maintained. Parameters ---------- indices : array an array of indices, this array can be a list, numpy array or a LongArray. Notes ----- Pseudo-code for the implementation:: if index_list.length > number of particles raise ValueError sorted_indices <- index_list sorted in ascending order. for every every array in property_array array.remove(sorted_indices) """ if len(indices) > self.get_number_of_particles(): msg = 'Number of particles to be removed is greater than' msg += 'number of particles in array' raise ValueError(msg) num_particles = self.get_number_of_particles() if_remove = Array(np.int32, n=num_particles, backend=self.backend) if_remove.fill(0) fill_if_remove_knl = self._get_remove_particles_kernel() fill_if_remove_knl(indices, if_remove, num_particles) self._remove_particles_bool(if_remove)
def make_dev_array(backend, n=16): dev_array = Array(np.int32, n=n, backend=backend) dev_array.fill(0) dev_array[0] = 1 return dev_array