def setUp(self): """ The setup consists of four particles placed at the vertices of a unit square. The pressure gradient term to be tested is ..math:: \frac{\nablaP}{\rho}_i = \sum_{j=1}^{4} -m_j(\frac{Pa}{\rho_a^2} + \frac{Pb}{\rho_b^2})\nabla W_{ab} The mass of each particle is 1 """ self.precision = "single" self.np = 4 x = numpy.array([0, 0, 1, 1], numpy.float64) y = numpy.array([0, 1, 1, 0], numpy.float64) z = numpy.zeros_like(x) m = numpy.ones_like(x) u = numpy.array([1, 0, 0, -1], numpy.float64) p = numpy.array([0, 0, 1, 1], numpy.float64) tmpx = numpy.zeros_like(x) tmpy = numpy.zeros_like(x) tmpz = numpy.zeros_like(x) self.pa = pa = base.get_particle_array(name="test", x=x, y=y, z=z, m=m, u=u, p=p, tmpx=tmpx, tmpy=tmpy, tmpz=tmpz, cl_precision=self.precision) grad_func = sph.SPHPressureGradient.withargs() mom_func = sph.MomentumEquation.withargs(alpha=1.0, beta=1.0, gamma=1.4, eta=0.1) self.grad_func = grad_func.get_func(pa,pa) self.mom_func = mom_func.get_func(pa,pa) self.grad_func.kernel = base.CubicSplineKernel(dim=2) self.grad_func.nbr_locator = \ base.Particles.get_neighbor_particle_locator(pa, pa) self.mom_func.kernel = base.CubicSplineKernel(dim=2) self.mom_func.nbr_locator = \ base.Particles.get_neighbor_particle_locator(pa, pa) self.setup_cl()
def setUp(self): """ A Dummy fluid solver is created with the following operations (i) -- Equation of State (ii) -- Density Rate (iii)-- Momentum Equation Pressure Gradient (iv) -- Momentum Equation Viscosity """ self.kernel = kernel = base.CubicSplineKernel(dim=2) self.solver = s = solver.Solver(dim=2, integrator_type=solver.EulerIntegrator) s.default_kernel = kernel self.particles = base.Particles(arrays=[base.get_particle_array()]) # Create some replacement operations self.visc = solver.SPHIntegration(sph.MorrisViscosity, on_types=[Fluids], from_types=[Fluids, Solids], updates=['u', 'v'], id='visc') self.summation_density = solver.SPHOperation(sph.SPHRho, on_types=[Fluids, Solids], updates=['rho'], id='sd')
def setUp(self): """ Setup a default simulation in 2D. The setup consists of four particles on a circle of radius 2/pi. The particles are constrained to move along the circle with forcing functions defined in pysph/sph/funcs/external_forces.pyx With the choice of radius and unit magnitude of velocity, the particles move by pi/2 radians in 1 second. """ self.r = r = 2. / numpy.pi self.x = x = numpy.array([1.0, 0.0, -1.0, 0.0]) self.y = y = numpy.array([0.0, 1.0, 0.0, -1.0]) x *= r y *= r p = numpy.zeros_like(x) e = numpy.zeros_like(x) h = numpy.ones_like(x) self.pa = pa = base.get_particle_array(x=x, y=y, p=p, e=e, h=h, name='tmp') self.particles = particles = base.Particles(arrays=[pa]) self.kernel = base.CubicSplineKernel(dim=2) circlex = solver.SPHIntegration(sph.MoveCircleX, from_types=[Fluids], on_types=[Fluids], updates=['x', 'y'], id='circlex') circley = solver.SPHIntegration(sph.MoveCircleY, from_types=[Fluids], on_types=[Fluids], updates=['x', 'y'], id='circley') self.calcx = circlex.get_calcs(particles, self.kernel) self.calcy = circley.get_calcs(particles, self.kernel) self.calcs = [] self.calcs.extend(self.calcx) self.calcs.extend(self.calcy) self.integrator = Integrator(particles=particles, calcs=self.calcs) self.setup()
def __init__(self, dim, integrator_type): self.particles = None self.integrator_type = integrator_type self.dim = dim self.default_kernel = base.CubicSplineKernel(dim=dim) self.initialize() self.setup_solver() self.with_cl = False self.cl_integrator_types = {EulerIntegrator: CLEulerIntegrator}
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 test_eval(self): """ Test the PySPH solution """ pa = self.pa calc = self.rho_calc k = base.CubicSplineKernel(dim=2) calc.sph() tmpx = pa.properties['_tmpx'] reference_solution = self.get_reference_solution() for i in range(self.np): self.assertAlmostEqual(reference_solution[i], tmpx[i])
def setUp(self): parrays = [] for i in range(np): x = numpy.array([x0[i]]) y = numpy.array([y0[i]]) z = numpy.array([z0[i]]) h = numpy.array([h0[i]]) mi = numpy.array([m[i]]) name = 'array' + str(i) pa = base.get_particle_array(name=name, x=x, y=y, z=z, h=h, m=mi) parrays.append(pa) self.parrays = parrays self.particles = base.Particles(arrays=parrays) kernel = base.CubicSplineKernel(dim=3) self.solver = s = solver.Solver(dim=3, integrator_type=solver.EulerIntegrator) # NBodyForce operation s.add_operation( solver.SPHIntegration(sph.NBodyForce.withargs(eps=eps), on_types=[Fluids], from_types=[Fluids], updates=['u', 'v', 'w'], id='nbody_force')) # position stepping s.add_operation_step([Fluids]) # time step and final time s.set_final_time(tf) s.set_time_step(dt) # setup the integrator s.setup_integrator(self.particles)
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 test_eval(self): """ Test the PySPH solution """ pa = self.pa func = self.mom_func k = base.CubicSplineKernel(dim=2) tmpx = pa.properties['tmpx'] tmpy = pa.properties['tmpy'] tmpz = pa.properties['tmpz'] func.eval(k, tmpx, tmpy, tmpz) reference_solution = self.get_reference_solution() for i in range(self.np): self.assertAlmostEqual(reference_solution[i].x, tmpx[i]) self.assertAlmostEqual(reference_solution[i].y, tmpy[i]) self.assertAlmostEqual(reference_solution[i].z, tmpz[i])
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 setup_solver(self): kernel = base.CubicSplineKernel(dim=1) #create the sph operation objects self.add_operation( SPHOperation(sph.SPHRho.withargs(), from_types=[Fluids], on_types=[Fluids], updates=['rho'], id='density', kernel=kernel)) self.add_operation( SPHOperation(sph.IdealGasEquation.withargs(), on_types=[Fluids], updates=['p', 'cs'], id='eos', kernel=kernel)) self.add_operation( SPHIntegration(sph.MomentumEquation.withargs(), from_types=[Fluids], on_types=[Fluids], updates=['u'], id='mom', kernel=kernel)) self.add_operation( SPHIntegration(sph.EnergyEquation.withargs(hks=False), from_types=[Fluids], on_types=[Fluids], updates=['e'], id='enr', kernel=kernel)) # Indicate that stepping is only needed for Fluids self.add_operation_step([Fluids])
def setUp(self): """ Setup for SPHOperationTestCase Setup: ------ Create two particle arrays, one Fluid and one Solid. Instantiate the class with a default function `SPHRho` with various combinations of the from and on types and check for the filtering of the arrays. """ x = numpy.linspace(0, 1, 11) h = numpy.ones_like(x) * 2 * (x[1] - x[0]) #create the fluid particle array self.fluid = base.get_particle_array(name='fluid', type=Fluid, x=x, h=h) #create the solid particle array self.solid = base.get_particle_array(name="solid", type=Solid, x=x, h=h) #create the particles self.particles = particles = base.Particles( arrays=[self.fluid, self.solid]) #set the kernel self.kernel = base.CubicSplineKernel()
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 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
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
print "\n========================================================" print "Summation Density Comparison using %s precision" % (prec) pa = base.get_particle_array(cl_precision=prec, name="test", x=x, h=h, m=m, rho=rho) particles = base.Particles(arrays=[ pa, ], locator_type=NSquareNeighborLocator) kernel = base.CubicSplineKernel(dim=1) # create the function func = sph.SPHRho.get_func(pa, pa) # create the CLCalc object cl_calc = sph.CLCalc(particles=particles, sources=[ pa, ], dest=pa, kernel=kernel, funcs=[ func, ], updates=['rho'])
def setUp(self): """ The setup consists of two fluid particle arrays, each having one particle. The fluids are acted upon by an external vector force and gravity. Comparison is made with the PySPH integration of the system. """ x1 = numpy.array([ -0.5, ]) y1 = numpy.array([ 1.0, ]) x2 = numpy.array([ 0.5, ]) y2 = numpy.array([ 1.0, ]) tmpx1 = numpy.ones_like(x1) tmpx2 = numpy.ones_like(x2) self.f1 = base.get_particle_array(name="fluid1", x=x1, y=y1, tmpx=tmpx1) self.f2 = base.get_particle_array(name="fluid2", x=x2, y=y2, tmpx=tmpx2) self.particles = base.Particles(arrays=[self.f1, self.f2]) self.kernel = kernel = base.CubicSplineKernel(dim=2) gravity = solver.SPHIntegration(sph.GravityForce.withargs(gy=-10.0), on_types=[Fluid], updates=['u', 'v'], id='gravity') force = solver.SPHIntegration(sph.GravityForce.withargs(gx=-10.0), on_types=[Fluid], updates=['u', 'v'], id='force') position = solver.SPHIntegration( sph.PositionStepping, on_types=[Fluid], updates=['x', 'y'], id='step', ) gravity.calc_type = sph.CLCalc force.calc_type = sph.CLCalc position.calc_type = sph.CLCalc gravity_calcs = gravity.get_calcs(self.particles, kernel) force_calcs = force.get_calcs(self.particles, kernel) position_calcs = position.get_calcs(self.particles, kernel) self.calcs = calcs = [] calcs.extend(gravity_calcs) calcs.extend(force_calcs) calcs.extend(position_calcs) self.integrator = CLIntegrator(self.particles, calcs) self.ctx = ctx = cl.create_some_context() self.integrator.setup_integrator(ctx) self.queue = calcs[0].queue self.dt = 0.1 self.nsteps = 10
def setUp(self): """ The setup consists of four particles placed at the vertices of a unit square. """ self.precision = "single" self.np = 4 x = numpy.array([0, 0, 1, 1], numpy.float64) y = numpy.array([0, 1, 1, 0], numpy.float64) z = numpy.zeros_like(x) m = numpy.ones_like(x) u = numpy.array([1, 0, 0, -1], numpy.float64) p = numpy.array([0, 0, 1, 1], numpy.float64) self.pa = pa = base.get_particle_array(name="test", x=x, y=y, z=z, m=m, u=u, p=p, cl_precision=self.precision) self.particles = particles = base.Particles([ pa, ]) sphrho_func = sph.SPHRho.withargs() density_rate_func = sph.SPHDensityRate.withargs() self.sphrho_func = sphrho_func.get_func(pa, pa) self.density_rate_func = density_rate_func.get_func(pa, pa) self.sphrho_func.kernel = base.CubicSplineKernel(dim=2) self.density_rate_func.kernel = base.CubicSplineKernel(dim=2) self.rho_calc = sph.SPHCalc(particles, [ pa, ], pa, base.CubicSplineKernel(dim=2), [ self.sphrho_func, ], updates=['rho']) self.rho_calc_cl = sph.CLCalc(particles, [ pa, ], pa, base.CubicSplineKernel(dim=2), [ self.sphrho_func, ], updates=['rho']) if solver.HAS_CL: self.ctx = ctx = cl.create_some_context() self.q = q = cl.CommandQueue(ctx) self.rho_calc_cl.setup_cl(ctx)
def setUp(self): """ The setup consists of four particles placed at the vertices of a unit square. The function tested is ..math:: \frac{DU_a}{Dt} = \frac{1}{2}\sum_{b=1}^{N}m_b\left[ \left(\frac{p_a}{\rho_a^2} + \frac{p_b}{\rho_b^2}\right)\,(v_a - v_b)\right]\,\nabla_a \cdot W_{ab} The mass of each particle is 1 """ self.precision = "single" self.np = 4 x = numpy.array([0, 0, 1, 1], numpy.float64) y = numpy.array([0, 1, 1, 0], numpy.float64) z = numpy.zeros_like(x) m = numpy.ones_like(x) u = numpy.array([1, 0, 0, -1], numpy.float64) p = numpy.array([0, 0, 1, 1], numpy.float64) tmpx = numpy.zeros_like(x) tmpy = numpy.zeros_like(x) tmpz = numpy.zeros_like(x) self.pa = pa = base.get_particle_array(name="test", x=x, y=y, z=z, m=m, u=u, p=p, tmpx=tmpx, tmpy=tmpy, tmpz=tmpz, cl_precision=self.precision) env = sph.EnergyEquationNoVisc.withargs() ewv = sph.EnergyEquation.withargs(alpha=1.0, beta=1.0, gamma=1.4, eta=0.1) self.env = env.get_func(pa, pa) self.ewv = ewv.get_func(pa, pa) self.env.kernel = base.CubicSplineKernel(dim=2) self.env.nbr_locator = \ base.Particles.get_neighbor_particle_locator(pa, pa) self.ewv.kernel = base.CubicSplineKernel(dim=2) self.ewv.nbr_locator = \ base.Particles.get_neighbor_particle_locator(pa, pa) self.setup_cl()
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