def test_sph_calc(): x = numpy.array([ 0, ]) y = numpy.array([ 0, ]) z = numpy.array([ 0, ]) h = numpy.ones_like(x) pa = base.get_particle_array(name="test", x=x, y=y, z=z, h=h, _tmpx=z, _tmpy=z, _tmpz=z) particles = base.Particles(arrays=[ pa, ]) kernel = base.CubicSplineKernel(dim=1) vector_force1 = sph.VectorForce.withargs(force=base.Point(1, 1, 1)) vector_force2 = sph.VectorForce.withargs(force=base.Point(1, 1, 1)) func1 = vector_force1.get_func(pa, pa) func2 = vector_force2.get_func(pa, pa) calc = sph.SPHCalc(particles=particles, sources=[pa, pa], dest=pa, kernel=kernel, funcs=[func1, func2], updates=['u', 'v', 'w'], integrates=True) # evaluate the calc. Accelerations are stored in _tmpx, _tmpy and _tmpz calc.sph('_tmpx', '_tmpy', '_tmpz') tmpx, tmpy, tmpz = pa.get('_tmpx', '_tmpy', '_tmpz') # the acceleration should be 2 in each direction assert (abs(tmpx[0] - 2.0) < 1e-16) assert (abs(tmpy[0] - 2.0) < 1e-16) assert (abs(tmpz[0] - 2.0) < 1e-16)
def get_wall(): """ Get the wall particles """ left = base.Line(base.Point(), box_height, pi2) top = base.Line(base.Point(0, box_height), box_length, 0) right = base.Line(base.Point(box_length, box_height), box_height, pi + pi2) bottom = base.Line(base.Point(box_length), box_length, pi) box_geom = base.Geometry('box', [left, top, right, bottom], is_closed=True) box_geom.mesh_geometry(dx) box = box_geom.get_particle_array(re_orient=False) box.m[:] = m box.h[:] = h return box
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa forces = [] x,y,z,p,m,h,rho = pa.get('x','y','z','p','m','h','rho') kernel = base.CubicSplineKernel(dim=2) for i in range(self.np): force = base.Point() xi, yi, zi = x[i], y[i], z[i] ri = base.Point(xi,yi,zi) Pi, rhoi = p[i], rho[i] hi = h[i] for j in range(self.np): grad = base.Point() xj, yj, zj = x[j], y[j], z[j] Pj, rhoj = p[j], rho[j] hj, mj = m[j], h[j] havg = 0.5 * (hi + hj) rj = base.Point(xj, yj, zj) tmp = -mj * ( Pi/(rhoi*rhoi) + Pj/(rhoj*rhoj) ) kernel.py_gradient(ri, rj, havg, grad) force.x += tmp*grad.x force.y += tmp*grad.y force.z += tmp*grad.z forces.append(force) return forces
def eval(self, solver, count): if not ((count % self.count) == 0): return particles = solver.particles time = solver.t nnps = particles.nnps_manager locator_cache = nnps.particle_locator_cache num_locs = len(locator_cache) locators = locator_cache.values() fname_base = os.path.join(self.path + "/neighbors_" + str(self.rank)) cell_manager = particles.cell_manager cell_size = cell_manager.cell_size for i in range(num_locs): loc = locators[i] dest = loc.dest particle_indices = dest.get('idx') x, y, z = dest.get("x", "y", "z") neighbor_idx = {} nrp = dest.num_real_particles for j in range(nrp): neighbors = loc.py_get_nearest_particles(j) temp = dest.extract_particles(neighbors) particle_idx = particle_indices[j] pnt = base.Point(x[j], y[j], z[j]) cid = py_find_cell_id(pnt, cell_size) idx = temp.get_carray("idx") neighbor_idx[particle_idx] = {'neighbors': idx, 'cid': cid} fname = fname_base + "_" + dest.name + "_" + str(time) f = open(fname, 'w') pickle.dump(neighbor_idx, f) f.close() fname_cells = os.path.join(self.path + "/cells_" + str(self.rank)) fname_cells += "_" + str(time) cell_manager.get_particle_representation(fname_cells)
def draw_cell(cell, color="b"): centroid = base.Point() cell.get_centroid(centroid) half_size = 0.5 * cell.cell_size x1, y1 = centroid.x - half_size, centroid.y - half_size x2, y2 = x1 + cell.cell_size, y1 x3, y3 = x2, y1 + cell.cell_size x4, y4 = x1, y3 pylab.plot([x1,x2,x3,x4,x1], [y1, y2, y3, y4,y1], color)
def get_square(): """ Get the square particle array """ left = base.Line(base.Point(1, 2), square_side, pi2) top = base.Line(base.Point(1, 3), square_side, 0) right = base.Line(base.Point(2, 3), square_side, pi + pi2) bottom = base.Line(base.Point(2, 2), square_side, pi) square_geom = base.Geometry('square', [left, top, right, bottom], is_closed=True) square_geom.mesh_geometry(dx) square = square_geom.get_particle_array(name="square", re_orient=True) square.m[:] = m square.h[:] = h return square
def get_fluid_particles(): x, y = get_2D_staggered_grid(base.Point(dx, dx), base.Point(dx / 2, dx / 2), base.Point(1.0, 2.0), dx) print 'Number of fluid particles: ', len(x) hf = numpy.ones_like(x) * h mf = numpy.ones_like(x) * dx * dy * ro * 0.5 rhof = numpy.ones_like(x) * ro csf = numpy.ones_like(x) * co fluid = base.get_particle_array(name="fluid", type=Fluid, x=x, y=y, h=hf, m=mf, rho=rhof, cs=csf) return fluid
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa rhos = [] x, y, z, p, m, h, rho = pa.get('x', 'y', 'z', 'p', 'm', 'h', 'rho') kernel = base.CubicSplineKernel(dim=2) for i in range(self.np): rho = 0.0 xi, yi, zi = x[i], y[i], z[i] ri = base.Point(xi, yi, zi) hi = h[i] for j in range(self.np): grad = base.Point() xj, yj, zj = x[j], y[j], z[j] hj, mj = m[j], h[j] havg = 0.5 * (hi + hj) rj = base.Point(xj, yj, zj) wij = kernel.py_function(ri, rj, havg) rho += mj * wij rhos.append(rho) return rhos
def test_build_cell(self): """ Test the building of the base cell """ cm = self.cm cm.update_global_properties() cm.compute_block_size(0) cm.compute_cell_size(0,0) cm.py_rebuild_array_indices() cm.py_setup_cells_dict() cm.setup_processor_map() cm._build_cell() cells_dict = cm.cells_dict ncells = len(cells_dict) self.assertEqual(ncells, 1) cell = cells_dict.values()[0] centroid = base.Point() cell.get_centroid(centroid) self.assertAlmostEqual(centroid.x, 0.25, 10) self.assertAlmostEqual(centroid.y, 0.25, 10) self.assertAlmostEqual(centroid.z, 0.25, 10) indices = [] cell.get_particle_ids(indices) index_array = indices[0] index_array_numpy = index_array.get_npy_array() index_array_numpy.sort() np = len(index_array_numpy) self.assertEqual(np, 25) for i in range(np): self.assertEqual(index_array_numpy[i], i)
def get_force(i): xi = pa.x[i] yi = pa.y[i] force = base.Point() for j in range(self.np): xj = pa.x[j] yj = pa.y[j] xji = xj - xi yji = yj - yi dist = numpy.sqrt(xji**2 + yji**2) invr = 1.0 / (dist + self.eps) invr3 = invr * invr * invr if not (i == j): force.x += invr3 * xji force.y += invr3 * yji return force
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa forces = [] x, y, z, p, m, h, rho = pa.get('x', 'y', 'z', 'p', 'm', 'h', 'rho') u, v, w = pa.get('u', 'v', 'w') kernel = base.CubicSplineKernel(dim=2) for i in range(self.np): force = base.Point() xa, ya, za = x[i], y[i], z[i] ua, va, wa = u[i], v[i], w[i] ra = base.Point(xa, ya, za) Va = base.Point(ua, va, wa) Pa, rhoa = p[i], rho[i] ha = h[i] for j in range(self.np): grad = base.Point() xb, yb, zb = x[j], y[j], z[j] ub, vb, wb = u[j], v[j], w[j] Pb, rhob = p[j], rho[j] hb, mb = m[j], h[j] havg = 0.5 * (ha + hb) rb = base.Point(xb, yb, zb) Vb = base.Point(ub, vb, wb) tmp = 0.5 * mb * (Pa / (rhoa * rhoa) + Pb / (rhob * rhob)) kernel.py_gradient(ra, rb, havg, grad) force.x += tmp * grad.dot(Va - Vb) forces.append(force) return forces
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa result = [] rho, e = pa.get('rho', 'e') kernel = base.CubicSplineKernel(dim=2) gamma = 1.4 for i in range(self.np): force = base.Point() rhoa = rho[i] ea = e[i] force.x = (gamma - 1.0) * ea * rhoa force.y = numpy.sqrt( (gamma-1.0) * ea ) result.append(force) return result
dx = dy = h/(1.3) g = -9.81 xf = numpy.array([0]) yf = numpy.array([0.3]) hf = numpy.array([h]) mf = numpy.array([1.0]) vf = numpy.array([0.0]) cf = numpy.array([25.0]) rhof = numpy.array([1.0]) fluid = base.get_particle_array(name="fluid", type=Fluid, x=xf, y=yf, h=hf, m=mf, rho=rhof, v=vf, cs=cf) #generate the boundary l = base.Line(base.Point(-.5), 1.0, 0) g = base.Geometry('line', [l], False) g.mesh_geometry(dx) boundary = g.get_particle_array(re_orient=True) boundary.m[:] = 1.0 particles = base.Particles(arrays=[fluid, boundary]) app.particles = particles kernel = base.HarmonicKernel(dim=2, n=3) s = solver.Solver(dim=2, integrator_type=solver.PredictorCorrectorIntegrator) # set the kernel as the default for the solver
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa forces = [] x, y, z, p, m, h, rho = pa.get('x', 'y', 'z', 'p', 'm', 'h', 'rho') u, v, w, cs = pa.get('u', 'v', 'w', 'cs') kernel = base.CubicSplineKernel(dim=2) for i in range(self.np): force = base.Point() xa, ya, za = x[i], y[i], z[i] ua, va, wa = u[i], v[i], w[i] ra = base.Point(xa, ya, za) Va = base.Point(ua, va, wa) Pa, rhoa = p[i], rho[i] ha = h[i] for j in range(self.np): grad = base.Point() xb, yb, zb = x[j], y[j], z[j] Pb, rhob = p[j], rho[j] hb, mb = h[j], m[j] ub, vb, wb = u[j], v[j], w[j] Vb = base.Point(ub, vb, wb) havg = 0.5 * (hb + ha) rb = base.Point(xb, yb, zb) tmp = Pa / (rhoa * rhoa) + Pb / (rhob * rhob) kernel.py_gradient(ra, rb, havg, grad) vab = Va - Vb rab = ra - rb dot = vab.dot(rab) piab = 0.0 if dot < 0.0: alpha = 1.0 beta = 1.0 gamma = 1.4 eta = 0.1 cab = 0.5 * (cs[i] + cs[j]) rhoab = 0.5 * (rhoa + rhob) muab = havg * dot muab /= (rab.norm() + eta * eta * havg * havg) piab = -alpha * cab * muab + beta * muab * muab piab /= rhoab tmp += piab tmp *= 0.5 * mb force.x += tmp * (vab.dot(grad)) forces.append(force) return forces
def get_particle_position(self, idx): if idx < 0 or idx > self.np: raise RunTimeError, "Invalid Particle Index!" return base.Point(*self.particle_positions[idx].values())
def get_reference_solution(self): """ Evaluate the force on each particle manually """ pa = self.pa forces = [] x,y,z,p,m,h,rho = pa.get('x','y','z','p','m','h','rho') u,v,w,cs = pa.get('u','v','w','cs') kernel = base.CubicSplineKernel(dim=2) for i in range(self.np): force = base.Point() xi, yi, zi = x[i], y[i], z[i] ui, vi, wi = u[i], v[i], w[i] ri = base.Point(xi,yi,zi) Va = base.Point(ui,vi,wi) Pi, rhoi = p[i], rho[i] hi = h[i] for j in range(self.np): grad = base.Point() xj, yj, zj = x[j], y[j], z[j] Pj, rhoj = p[j], rho[j] hj, mj = h[j], m[j] uj, vj, wj = u[j], v[j], w[j] Vb = base.Point(uj,vj,wj) havg = 0.5 * (hi + hj) rj = base.Point(xj, yj, zj) tmp = Pi/(rhoi*rhoi) + Pj/(rhoj*rhoj) kernel.py_gradient(ri, rj, havg, grad) vab = Va-Vb rab = ri-rj dot = vab.dot(rab) piab = 0.0 if dot < 0.0: alpha = 1.0 beta = 1.0 gamma = 1.4 eta = 0.1 cab = 0.5 * (cs[i] + cs[j]) rhoab = 0.5 * (rhoi + rhoj) muab = havg * dot muab /= ( rab.norm() + eta*eta*havg*havg ) piab = -alpha*cab*muab + beta*muab*muab piab /= rhoab tmp += piab tmp *= -mj force.x += tmp*grad.x force.y += tmp*grad.y force.z += tmp*grad.z forces.append(force) return forces
def setUp(self): """ A simple simulation in 2D with boundary particles spaced with a distance dp. The fluid particles are in a row just above as shown in the fgure. dx o o o o o x x x x x x x x x x x x x x x Y | Z | / |/___ X Expected Behavior: ------------------- The Monaghan Boundary force is defned such that a particle moving parallel to the wall experiences a constant force. Each fluid particle can be thought of successive instances of a moving particle and hence each of them should experience the same force. """ #fluid particle spacing self.dx = dx = 0.1 #solid particle spacing self.dp = dp = 0.05 #the fluid properties xf = numpy.array([-.2, -.1, 0.0, 0.1, 0.2]) yf = numpy.array([dp, dp, dp, dp, dp]) hf = numpy.ones_like(xf) * 2 * dx mf = numpy.ones_like(xf) * dx cs = numpy.ones_like(xf) rhof = numpy.ones_like(xf) self.fluid = base.get_particle_array(x=xf, y=yf, h=hf, m=mf, rho=rhof, cs=cs, ax=mf, ay=mf, az=mf, name='fluid', type=Fluid) l = base.Line(base.Point(-0.35), 0.70, 0.0) g = base.Geometry('line', lines=[l], is_closed=False) g.mesh_geometry(dp) self.solid = g.get_particle_array(re_orient=True) self.particles = particles = base.Particles( arrays=[self.fluid, self.solid]) self.kernel = kernel = base.CubicSplineKernel(dim=2) self.solver = solver.Solver(kernel.dim, solver.EulerIntegrator) self.solver.add_operation( solver.SPHIntegration(sph.MonaghanBoundaryForce.withargs(delp=dp), from_types=[Solid], on_types=[Fluid], updates=['u', 'v', 'w'], id='boundary')) self.solver.setup_integrator(particles) self.integrator = self.solver.integrator