def remove_overlap_particles(fluid_parray, solid_parray, dx_solid, dim=3): """ This function will take 2 particle arrays as input and will remove all the particles of the first particle array which are in the vicinity of the particles from second particle array. The function will remove all the particles within the dx_solid vicinity so some particles are removed at the outer surface of the particles from the second particle array. This uses a pysph nearest neighbour particles search which will output the particles within some range for every given particle. Parameters ---------- fluid_parray : a pysph particle array object solid_parray : a pysph particle array object dx_solid : a number which is the dx of the second particle array dim : dimensionality of the problem The particle arrays should atleast contain x, y and h values for a 2d case and atleast x, y, z and h values for a 3d case Returns ------- particle_array : pysph wcsph_particle_array with x, y, z and h values """ x = fluid_parray.x x1 = solid_parray.x y = fluid_parray.y y1 = solid_parray.y z = fluid_parray.z z1 = solid_parray.z h = fluid_parray.h if dim == 2: z = np.zeros_like(x) z1 = np.zeros_like(x1) modified_points = [] h_new = [] ll_nnps = LinkedListNNPS(dim, [fluid_parray, solid_parray]) for i in range(len(x)): nbrs = UIntArray() ll_nnps.get_nearest_particles(1, 0, i, nbrs) point_i = np.array([x[i], y[i], z[i]]) near_points = nbrs.get_npy_array() distances = [] for ind in near_points: dest = [x1[ind], y1[ind], z1[ind]] distances.append(distance(point_i, dest)) if len(distances) == 0: modified_points.append(point_i) h_new.append(h[i]) elif min(distances) >= (dx_solid * (1.0 - 1.0e-07)): modified_points.append(point_i) h_new.append(h[i]) modified_points = np.array(modified_points) x_new = modified_points[:, 0] y_new = modified_points[:, 1] z_new = modified_points[:, 2] p_array = get_particle_array_wcsph(x=x_new, y=y_new, z=z_new, h=h_new) return p_array
def test_corner_case_1d_few_cells(cls): x, y, z = [0.131, 0.359], [1.544, 1.809], [-3.6489999, -2.8559999] pa = get_particle_array(name='fluid', x=x, y=y, z=z, h=1.0) nbrs = UIntArray() bf_nbrs = UIntArray() nps = cls(dim=3, particles=[pa], radius_scale=0.7) for i in range(2): nps.get_nearest_particles(0, 0, i, nbrs) nps.brute_force_neighbors(0, 0, i, bf_nbrs) assert sorted(nbrs) == sorted(bf_nbrs), 'Failed for particle: %d' % i
def find_overlap_particles(fluid_parray, solid_parray, dx_solid, dim=3): """This function will take 2 particle arrays as input and will find all the particles of the first particle array which are in the vicinity of the particles from second particle array. The function will find all the particles within the dx_solid vicinity so some particles may be identified at the outer surface of the particles from the second particle array. The particle arrays should atleast contain x, y and h values for a 2d case and atleast x, y, z and h values for a 3d case. Parameters ---------- fluid_parray : a pysph particle array object solid_parray : a pysph particle array object dx_solid : a number which is the dx of the second particle array dim : dimensionality of the problem Returns ------- list of particle indices to remove from the first array. """ x = fluid_parray.x x1 = solid_parray.x y = fluid_parray.y y1 = solid_parray.y z = fluid_parray.z z1 = solid_parray.z if dim == 2: z = np.zeros_like(x) z1 = np.zeros_like(x1) to_remove = [] ll_nnps = LinkedListNNPS(dim, [fluid_parray, solid_parray]) for i in range(len(x)): nbrs = UIntArray() ll_nnps.get_nearest_particles(1, 0, i, nbrs) point_i = np.array([x[i], y[i], z[i]]) near_points = nbrs.get_npy_array() distances = [] for ind in near_points: dest = [x1[ind], y1[ind], z1[ind]] distances.append(distance(point_i, dest)) if len(distances) == 0: continue elif min(distances) < (dx_solid * (1.0 - 1.0e-07)): to_remove.append(i) return to_remove
def _test_neighbors_by_particle(self, src_index, dst_index, dst_numPoints): # nnps and the two neighbor lists nps = self.nps nbrs1 = UIntArray() nbrs2 = UIntArray() nps.set_context(src_index, dst_index) # get the neighbors and sort the result for i in range(dst_numPoints): nps.get_nearest_particles(src_index, dst_index, i, nbrs1) nps.brute_force_neighbors(src_index, dst_index, i, nbrs2) # ensure that the neighbor lists are the same self._assert_neighbors(nbrs1, nbrs2)
def test_nnps_sorts_without_gids(self): # Given pa, nps = self._make_particles(10) # When nps.set_context(0, 0) # Test the that gids are actually huge and invalid. self.assertEqual(numpy.max(pa.gid), numpy.min(pa.gid)) self.assertTrue(numpy.max(pa.gid) > pa.gid.size) # Then nbrs = UIntArray() for i in range(pa.get_number_of_particles()): nps.get_nearest_particles(0, 0, i, nbrs) nb = nbrs.get_npy_array() sorted_nbrs = nb.copy() sorted_nbrs.sort() self.assertTrue(numpy.all(nb == sorted_nbrs))
def test_use_3d_for_1d_data_with_llnps(): y = numpy.array([1.0, 1.5]) h = numpy.ones_like(y) pa = get_particle_array(name='fluid', y=y, h=h) nps = nnps.LinkedListNNPS(dim=3, particles=[pa], cache=False) nbrs = UIntArray() nps.get_nearest_particles(0, 0, 0, nbrs) print(nbrs.length) assert nbrs.length == len(y)
def _check_summation_density(self): fluid = self.fluid nnps = self.nnps kernel = self.kernel nnps.update_domain() nnps.update() # get the fluid arrays fx, fy, fz, fh, frho, fV, fm = fluid.get('x', 'y', 'z', 'h', 'rho', 'V', 'm', only_real_particles=True) # the source arrays. First source is also the fluid sx, sy, sz, sh, sm = fluid.get('x', 'y', 'z', 'h', 'm', only_real_particles=False) # initialize the fluid density and volume frho[:] = 0.0 fV[:] = 0.0 # compute density on the fluid nbrs = UIntArray() for i in range(fluid.num_real_particles): hi = fh[i] # compute density from the fluid from the source arrays nnps.get_nearest_particles(src_index=0, dst_index=0, d_idx=i, nbrs=nbrs) nnbrs = nbrs.length for indexj in range(nnbrs): j = nbrs[indexj] hij = 0.5 * (hi + sh[j]) frho[i] += sm[j] * kernel.kernel(fx[i], fy[i], fz[i], sx[j], sy[j], sz[j], hij) fV[i] += kernel.kernel(fx[i], fy[i], fz[i], sx[j], sy[j], sz[j], hij) # check the number density and density by summation voli = 1. / fV[i] #print voli, frho[i], fm[i], self.vol self.assertAlmostEqual(voli, self.vol, 5) self.assertAlmostEqual(frho[i], fm[i] / voli, 14)
def test_large_number_of_neighbors_octree(): x = numpy.random.random(1 << 14) * 0.1 y = x.copy() z = x.copy() h = numpy.ones_like(x) pa = get_particle_array(name='fluid', x=x, y=y, z=z, h=h) nps = nnps.OctreeNNPS(dim=3, particles=[pa], cache=False) nbrs = UIntArray() nps.get_nearest_particles(0, 0, 0, nbrs) # print(nbrs.length) assert nbrs.length == len(x)
def sd_evaluate(nnps, pm, mass, src_index, dst_index): # the destination particle array dst = nnps.particles[dst_index] src = nnps.particles[src_index] # particle coordinates dx, dy, dz, dh, drho = dst.get('x', 'y', 'z', 'h', 'rho', only_real_particles=True) sx, sy, sz, sh, srho = src.get('x', 'y', 'z', 'h', 'rho', only_real_particles=False) neighbors = UIntArray() cubic = get_compiled_kernel(CubicSpline(dim=dim)) # compute density for each destination particle num_particles = dst.num_real_particles # the number of local particles should have tag Local assert (num_particles == pm.num_local[dst_index]) for i in range(num_particles): hi = dh[i] nnps.get_nearest_particles(src_index, dst_index, i, neighbors) nnbrs = neighbors.length rho_sum = 0.0 for indexj in range(nnbrs): j = neighbors[indexj] wij = cubic.kernel(dx[i], dy[i], dz[i], sx[j], sy[j], sz[j], hi) rho_sum = rho_sum + mass * wij drho[i] += rho_sum
def interpolate(self, arr): """Interpolate data given in arr onto coordinate positions""" # the result array np = self.dst.get_number_of_particles() result = numpy.zeros(np) nbrs = UIntArray() # source arrays src = self.src sx, sy, sz, sh = src.get('x', 'y', 'z', 'h', only_real_particles=False) # dest arrays dst = self.dst dx, dy, dz, dh = dst.x, dst.y, dst.z, dst.h # kernel kernel = self.kernel for i in range(np): self.nnps.get_nearest_particles(src_index=1, dst_index=0, d_idx=i, nbrs=nbrs) nnbrs = nbrs.length _wij = 0.0 _sum = 0.0 for indexj in range(nnbrs): j = nbrs[indexj] hij = 0.5 * (sh[j] + dh[i]) wij = kernel.kernel(dx[i], dy[i], dz[i], sx[j], sy[j], sz[j], hij) _wij += wij _sum += arr[j] * wij # save the result result[i] = _sum / _wij return result
def test_compressed_octree_works_for_large_domain(self): # Given pa = self._make_particles(20) # We turn on cache so it computes all the neighbors quickly for us. nps = nnps.CompressedOctreeNNPS(dim=3, particles=[pa], cache=True) nbrs = UIntArray() direct = UIntArray() nps.set_context(0, 0) for i in range(pa.get_number_of_particles()): nps.get_nearest_particles(0, 0, i, nbrs) nps.brute_force_neighbors(0, 0, i, direct) x = nbrs.get_npy_array() y = direct.get_npy_array() x.sort(); y.sort() assert numpy.all(x == y)
def test_cache_updates_with_changed_particles(self): # Given pa1 = self._make_random_parray('pa1', 5) particles = [pa1] nnps = LinkedListNNPS(dim=3, particles=particles) cache = NeighborCache(nnps, dst_index=0, src_index=0) cache.update() # When pa2 = self._make_random_parray('pa2', 2) pa1.add_particles(x=pa2.x, y=pa2.y, z=pa2.z) nnps.update() cache.update() nb_cached = UIntArray() nb_direct = UIntArray() for i in range(len(particles[0].x)): nnps.get_nearest_particles_no_cache(0, 0, i, nb_direct, False) cache.get_neighbors(0, i, nb_cached) nb_e = nb_direct.get_npy_array() nb_c = nb_cached.get_npy_array() self.assertTrue(np.all(nb_e == nb_c))
def test_neighbors_cached_properly(self): # Given pa1 = self._make_random_parray('pa1', 5) pa2 = self._make_random_parray('pa2', 4) particles = [pa1, pa2] nnps = LinkedListNNPS(dim=3, particles=particles) for dst_index in (0, 1): for src_idx in (0, 1): # When cache = NeighborCache(nnps, dst_index, src_idx) cache.update() nb_cached = UIntArray() nb_direct = UIntArray() # Then. for i in range(len(particles[dst_index].x)): nnps.get_nearest_particles_no_cache( src_idx, dst_index, i, nb_direct, False) cache.get_neighbors(src_idx, i, nb_cached) nb_e = nb_direct.get_npy_array() nb_c = nb_cached.get_npy_array() self.assertTrue(np.all(nb_e == nb_c))
def test_empty_neigbors_works_correctly(self): # Given pa1 = self._make_random_parray('pa1', 5) pa2 = self._make_random_parray('pa2', 2) pa2.x += 10.0 particles = [pa1, pa2] # When nnps = LinkedListNNPS(dim=3, particles=particles) # Cache for neighbors of destination 0. cache = NeighborCache(nnps, dst_index=0, src_index=1) cache.update() # Then nb_cached = UIntArray() nb_direct = UIntArray() for i in range(len(particles[0].x)): nnps.get_nearest_particles_no_cache(1, 0, i, nb_direct, False) # Get neighbors from source 1 on destination 0. cache.get_neighbors(src_index=1, d_idx=i, nbrs=nb_cached) nb_e = nb_direct.get_npy_array() nb_c = nb_cached.get_npy_array() self.assertEqual(len(nb_e), 0) self.assertTrue(np.all(nb_e == nb_c))
def gradient(self, arr): """Compute the gradient on the interpolated data""" # the result array np = self.dst.get_number_of_particles() # result arrays resultx = numpy.zeros(np) resulty = numpy.zeros(np) resultz = numpy.zeros(np) nbrs = UIntArray() # data arrays # source arrays src = self.src sx, sy, sz, sh, srho, sm = src.get('x', 'y', 'z', 'h', 'rho', 'm', only_real_particles=False) # dest arrays dst = self.dst dx, dy, dz, dh = dst.x, dst.y, dst.z, dst.h # kernel kernel = self.kernel for i in range(np): self.nnps.get_nearest_particles(src_index=1, dst_index=0, d_idx=i, nbrs=nbrs) nnbrs = nbrs.length _wij = 0.0 _sumx = 0.0 _sumy = 0.0 _sumz = 0.0 for indexj in range(nnbrs): j = nbrs[indexj] hij = 0.5 * (sh[j] + dh[i]) wij = kernel.kernel(dx[i], dy[i], dz[i], sx[j], sy[j], sz[j], hij) rhoj = srho[j] mj = sm[j] fji = arr[j] - arr[i] # kernel gradient dwij = kernel.gradient(dx[i], dy[i], dz[i], sx[j], sy[j], sz[j], hij) _wij += wij tmp = 1. / rhoj * fji * mj _sumx += tmp * dwij.x _sumy += tmp * dwij.y _sumz += tmp * dwij.z # save the result resultx[i] = _sumx resulty[i] = _sumy resultz[i] = _sumz return resultx, resulty, resultz
slice(i * numPoints, (i + 1) * numPoints) for i in range(size) ] plot_points(X, Y, Z, slice_data, title="Initial Distribution", filename="initial.pdf") # partition the points using PyZoltan xa = DoubleArray(numPoints) xa.set_data(x) ya = DoubleArray(numPoints) ya.set_data(y) za = DoubleArray(numPoints) za.set_data(z) gida = UIntArray(numPoints) gida.set_data(gid) # create the geometric partitioner pz = zoltan.ZoltanGeometricPartitioner(dim=3, comm=comm, x=xa, y=ya, z=za, gid=gida) # call the load balancing function pz.set_lb_method('RIB') pz.Zoltan_Set_Param('DEBUG_LEVEL', '1') pz.Zoltan_LB_Balance()
xmax=1., ymin=0., ymax=1., periodic_in_x=True, periodic_in_y=True) # NNPS object for nearest neighbor queries nps = LinkedListNNPS(dim=2, particles=[ pa, ], radius_scale=k.radius_scale, domain=domain) # container for neighbors nbrs = UIntArray() # arrays including ghosts x, y, h, m = pa.get('x', 'y', 'h', 'm', only_real_particles=False) # iterate over destination particles t1 = time() max_ngb = -1 for i in range(pa.num_real_particles): xi = x[i] yi = y[i] hi = h[i] # get list of neighbors nps.get_nearest_particles(0, 0, i, nbrs) neighbors = nbrs.get_npy_array()
# read the input file and distribute objects across processors numMyPoints, myGlobalIds, x, y = read_input_file() rank = comm.Get_rank() parts = np.ones(shape=numMyPoints, dtype=np.int32) for i in range(numMyPoints): parts[i] = rank # now do the load balancing _x = np.asarray(x); _y = np.asarray(y); _gid = np.asarray(myGlobalIds) _z = np.zeros_like(x) x = DoubleArray(numMyPoints); x.set_data(_x) y = DoubleArray(numMyPoints); y.set_data(_y) z = DoubleArray(numMyPoints); z.set_data(_z) gid = UIntArray(numMyPoints); gid.set_data(_gid) pz = zoltan.ZoltanGeometricPartitioner(dim=2, comm=comm, x=x, y=y, z=z, gid=gid) # set the weights to 0 by default weights = pz.weights.get_npy_array() weights[:] = 0 pz.set_lb_method("RCB") pz.Zoltan_Set_Param("DEBUG_LEVEL","0") pz.Zoltan_LB_Balance() if rank == 0: print "\nMesh partition before Zoltan\n" comm.barrier()
if update: print "Neighbor search",nl_updates pa = get_particle_array(name='prot', x=rx, y=ry, z=rz, h=1.0) #h=1.0 must not be changed as it affects radius_scale in nnps.LinkedListNNPS nps = nnps.LinkedListNNPS(dim=3, particles=[pa], radius_scale=rcut2) #nps = nnps.SpatialHashNNPS(dim=3, particles=[pa], radius_scale=rcut2) src_index = 0 dst_index = 0 neighbors = [] tot = 0 for i in range(nca): nbrs = UIntArray() nps.get_nearest_particles(src_index, dst_index, i, nbrs) tmp = nbrs.get_npy_array().tolist() # patch if tmp.count(i) > 1: print "Problems: nbrs has multiple occurrences of residue %d, which might indicate something wrong in pysph (for certain radius_scale values)" %(i) print "Patching this problem by assuming that residue %d has no neighbors other than itself" % (i) tmp = [i] else: pass nneigh = len(tmp) tot += nneigh #I do not want neighbors that are only the i-th particle (i.e. self)
def _test_summation_density(self): "NNPS :: testing for summation density" fluid, channel = self.particles nnps = self.nnps kernel = self.kernel # get the fluid arrays fx, fy, fh, frho, fV, fm = fluid.get('x', 'y', 'h', 'rho', 'V', 'm', only_real_particles=True) # initialize the fluid density and volume frho[:] = 0.0 fV[:] = 0.0 # compute density on the fluid nbrs = UIntArray() for i in range(fluid.num_real_particles): hi = fh[i] # compute density from the fluid from the source arrays nnps.get_nearest_particles(src_index=0, dst_index=0, d_idx=i, nbrs=nbrs) nnbrs = nbrs.length # the source arrays. First source is also the fluid sx, sy, sh, sm = fluid.get('x', 'y', 'h', 'm', only_real_particles=False) for indexj in range(nnbrs): j = nbrs[indexj] xj = Point(sx[j], sy[j]) hij = 0.5 * (hi + sh[j]) frho[i] += sm[j] * kernel.kernel(fx[i], fy[i], 0.0, sx[j], sy[j], 0.0, hij) fV[i] += kernel.kernel(fx[i], fy[i], 0.0, sx[j], sy[j], 0.0, hij) # compute density from the channel nnps.get_nearest_particles(src_index=1, dst_index=0, d_idx=i, nbrs=nbrs) nnbrs = nbrs.length sx, sy, sh, sm = channel.get('x', 'y', 'h', 'm', only_real_particles=False) for indexj in range(nnbrs): j = nbrs[indexj] hij = 0.5 * (hi + sh[j]) frho[i] += sm[j] * kernel.kernel(fx[i], fy[i], 0.0, sx[j], sy[j], 0.0, hij) fV[i] += kernel.kernel(fx[i], fy[i], 0.0, sx[j], sy[j], 0.0, hij) # check the number density and density by summation voli = 1. / fV[i] self.assertAlmostEqual(voli, self.vol, 6) self.assertAlmostEqual(frho[i], fm[i] / voli, 6)
# read the input file and distribute objects across processors numMyPoints, myGlobalIds, x, y = read_input_file() rank = comm.Get_rank() parts = np.ones(shape=numMyPoints, dtype=np.int32) for i in range(numMyPoints): parts[i] = rank # now do the load balancing _x = np.asarray(x); _y = np.asarray(y); _gid = np.asarray(myGlobalIds) _z = np.zeros_like(x) x = DoubleArray(numMyPoints); x.set_data(_x) y = DoubleArray(numMyPoints); y.set_data(_y) z = DoubleArray(numMyPoints); z.set_data(_z) gid = UIntArray(numMyPoints); gid.set_data(_gid) pz = zoltan.ZoltanGeometricPartitioner(dim=2, comm=comm, x=x, y=y, z=z, gid=gid) # set the weights to 0 by default weights = pz.weights.get_npy_array() weights[:] = 0 pz.set_lb_method("RCB") pz.Zoltan_Set_Param("DEBUG_LEVEL","0") pz.Zoltan_LB_Balance() if rank == 0: print("\nMesh partition before Zoltan\n") comm.barrier()
h = numpy.ones_like(x) * h0 m = numpy.ones_like(x) * volume wij = numpy.zeros_like(x) # use the helper function get_particle_array to create a ParticleArray pa = utils.get_particle_array(x=x,y=y,h=h,m=m,wij=wij) # the simulation domain used to request periodicity domain = DomainManager( xmin=0., xmax=1., ymin=0., ymax=1.,periodic_in_x=True, periodic_in_y=True) # NNPS object for nearest neighbor queries nps = LinkedListNNPS(dim=2, particles=[pa,], radius_scale=k.radius_scale, domain=domain) # container for neighbors nbrs = UIntArray() # arrays including ghosts x, y, h, m = pa.get('x', 'y', 'h', 'm', only_real_particles=False) # iterate over destination particles t1 = time() max_ngb = -1 for i in range( pa.num_real_particles ): xi = x[i]; yi = y[i]; hi = h[i] # get list of neighbors nps.get_nearest_particles(0, 0, i, nbrs) neighbors = nbrs.get_npy_array() max_ngb = max( neighbors.size, max_ngb )
Z[i*numPoints:(i+1)*numPoints], c=colors[i], marker='o', linestyle='None', alpha=0.5) s1.axes.set_xlabel( 'X' ) s1.axes.set_ylabel( 'Y' ) s1.axes.set_zlabel( 'Z' ) plt.title('Initital Distribution') plt.savefig( 'initial.pdf' ) # partition the points using PyZoltan xa = DoubleArray(numPoints); xa.set_data(x) ya = DoubleArray(numPoints); ya.set_data(y) za = DoubleArray(numPoints); za.set_data(z) gida = UIntArray(numPoints); gida.set_data(gid) # create the geometric partitioner pz = zoltan.ZoltanGeometricPartitioner( dim=3, comm=comm, x=xa, y=ya, z=za, gid=gida) # call the load balancing function pz.set_lb_method('RIB') pz.Zoltan_Set_Param('DEBUG_LEVEL', '1') pz.Zoltan_LB_Balance() # get the new assignments my_global_ids = list( gid ) # remove points to be exported for i in range(pz.numExport):