public DEMParticles simulate(DEMParticles particles, float t) { Vector2[] forces = particles.forces; List<Vector2> positions = particles.positions; List<Vector2> velocities = particles.velocities; List<float> massesInv = particles.massesInv; for (int iTarget = 0; iTarget < particles.length; iTarget++) { AABB boundingBox = particles.buildAABB(iTarget); int[] neighborIndices = spacePartitioner.search(boundingBox); forces[iTarget] = estimateForce(particles, iTarget, neighborIndices, t); } for (int iTarget = 0; iTarget < particles.length; iTarget++) { forces[iTarget] += boundaryForce.calcForce(particles, iTarget, t); } for (int iTarget = 0; iTarget < particles.length; iTarget++) { Vector2 accel = forces[iTarget] * massesInv[iTarget]; Vector2 velocity = velocities[iTarget]; positions[iTarget] += t * velocity; velocities[iTarget] += t * accel; } return particles; }
public Vector2 estimateForce(DEMParticles particles, int iTarget, int[] neighbors, float t) { Vector2 resForce = externalForce.calcForce(particles, iTarget, t); Vector2 targetPosition = particles.positions[iTarget]; Vector2 targetVelocity = particles.velocities[iTarget]; float targetRadius = particles.radii[iTarget]; for (int i = 0; i < neighbors.Length; i++) { int iNeighbor = neighbors[i]; if (iTarget == iNeighbor) continue; Vector2 pos = targetPosition - particles.positions[iNeighbor]; Vector2 v = targetVelocity - particles.velocities[iNeighbor]; float r12 = particles.radii[iNeighbor] + targetRadius; float dist2 = Vector2.SqrMagnitude(pos); if (dist2 >= (r12 * r12) || dist2 <= Mathf.Epsilon) continue; float dist = Mathf.Sqrt((float)dist2); float dxCoeff = ((r12 - dist) / dist); resForce += (kn * dxCoeff * pos - cn * v); } return resForce; }
public Vector2 calcForce(DEMParticles particles, int iParticle, float dt) { Vector2 position = particles.positions[iParticle]; Vector2 velocity = particles.velocities[iParticle]; Vector2 dx = new Vector2( Mathf.Min(0, position.x - boundary[0]) + Mathf.Max(0, position.x - boundary[2]), Mathf.Min(0, position.y - boundary[1]) + Mathf.Max(0, position.y - boundary[3])); Vector2 dv = new Vector2((dx.x == 0 ? 0 : velocity.x), (dx.y == 0 ? 0 : velocity.y)); return - kn * dx - cn * dv; }
// Use this for initialization void Start() { this.particles = new DEMParticles(); this.spacePartitioner = new GridSP<int>( boundBL, boundTR, 20, 20, new IntEqualityComparer()); this.gravitationalForce = new GravitationalForce(new Vector2(0, -9.8f)); this.boundaryForce = new BoundaryForce( kn, cn, boundBL.x, boundBL.y, boundTR.x, boundTR.y); this.dem = new DEM(spacePartitioner, gravitationalForce, boundaryForce); spheres = new GameObject[nParticles]; for (int i = 0; i < nParticles; i++) { GameObject s = GameObject.CreatePrimitive(PrimitiveType.Sphere); s.transform.localScale = new Vector3(diameter, diameter, diameter); s.transform.position = new Vector3( Random.Range(boundBL.x, boundTR.x), Random.Range(boundBL.y, boundTR.y), 0); Destroy(s.collider); spheres[i] = s; } int length = spheres.Length; float[] radii = new float[length]; float[] masses = new float[length]; Vector2[] positions = new Vector2[length]; Vector2[] velocities = new Vector2[length]; for (int i = 0; i < length; i++) { GameObject sphere = spheres[i]; float radius = 0.5f * sphere.transform.localScale.x; radii[i] = radius; masses[i] = mass; //(rho * Mathf.PI * radius); positions[i] = new Vector2( sphere.transform.position.x, sphere.transform.position.y); velocities[i] = Vector2.zero; } particles.addParticle(masses, radii, positions, velocities); for (int i = 0; i < length; i++) { spacePartitioner.add(particles.buildAABB(i), i); } }
public Vector2 calcForce(DEMParticles particles, int iParticle, float dt) { return Vector2.zero; }
public Vector2 calcForce(DEMParticles particles, int iParticle, float dt) { return particles.masses[iParticle] * gravity; }