/// <summary> /// Checks the distance between the particles and corrects it, if they are to near. /// </summary> /// <param name="particles">The particles.</param> /// <param name="grid">The grid.</param> private void CheckParticleDistance(FluidParticles particles, IndexGrid grid) { float minDist = 0.5f * CellSpace; float minDistSq = minDist * minDist; Vector2 dist; for (int i = 0; i < particles.Count; i++) { foreach (var nIdx in grid.GetNeighbourIndex(particles[i])) { Vector2.Sub(ref particles[nIdx].Position, ref particles[i].Position, out dist); float distLenSq = dist.LengthSquared; if (distLenSq < minDistSq) { if (distLenSq > Constants.FLOAT_EPSILON) { float distLen = (float)Math.Sqrt((double)distLenSq); Vector2.Mult(ref dist, 0.5f * (distLen - minDist) / distLen, out dist); Vector2.Sub(ref particles[nIdx].Position, ref dist, out particles[nIdx].Position); Vector2.Sub(ref particles[nIdx].PositionOld, ref dist, out particles[nIdx].PositionOld); Vector2.Add(ref particles[i].Position, ref dist, out particles[i].Position); Vector2.Add(ref particles[i].PositionOld, ref dist, out particles[i].PositionOld); } else { float diff = 0.5f * minDist; particles[nIdx].Position.Y -= diff; particles[nIdx].PositionOld.Y -= diff; particles[i].Position.Y += diff; particles[i].PositionOld.Y += diff; } } } } }
/// <summary> /// Calculates the pressure and densities. /// </summary> /// <param name="particles">The particles.</param> /// <param name="grid">The grid.</param> private void CalculatePressureAndDensities(FluidParticles particles, IndexGrid grid) { Vector2 dist; foreach (var particle in particles) { particle.Density = 0.0f; foreach (var nIdx in grid.GetNeighbourIndex(particle)) { Vector2.Sub(ref particle.Position, ref particles[nIdx].Position, out dist); particle.Density += particle.Mass * this.SKGeneral.Calculate(ref dist); } particle.UpdatePressure(); } }
/// <summary> /// Calculates the pressure and viscosity forces. /// </summary> /// <param name="particles">The particles.</param> /// <param name="grid">The grid.</param> /// <param name="globalForce">The global force.</param> private void CalculateForces(FluidParticles particles, IndexGrid grid, Vector2 globalForce) { Vector2 f, dist; float scalar; for (int i = 0; i < particles.Count; i++) { // Add global force to every particle particles[i].Force += globalForce; foreach (var nIdx in grid.GetNeighbourIndex(particles[i])) { // Prevent double tests if (nIdx < i) { if (particles[nIdx].Density > Constants.FLOAT_EPSILON) { Vector2.Sub(ref particles[i].Position, ref particles[nIdx].Position, out dist); // pressure // f = particles[nIdx].Mass * ((particles[i].Pressure + particles[nIdx].Pressure) / (2.0f * particles[nIdx].Density)) * WSpikyGrad(ref dist); scalar = particles[nIdx].Mass * (particles[i].Pressure + particles[nIdx].Pressure) / (2.0f * particles[nIdx].Density); f = this.SKPressure.CalculateGradient(ref dist); Vector2.Mult(ref f, scalar, out f); particles[i].Force -= f; particles[nIdx].Force += f; // viscosity // f = particles[nIdx].Mass * ((particles[nIdx].Velocity - particles[i].Velocity) / particles[nIdx].Density) * WViscosityLap(ref dist) * Constants.VISC0SITY; scalar = particles[nIdx].Mass * this.SKViscosity.CalculateLaplacian(ref dist) * this.Viscosity * 1 / particles[nIdx].Density; f = particles[nIdx].Velocity - particles[i].Velocity; Vector2.Mult(ref f, scalar, out f); particles[i].Force += f; particles[nIdx].Force -= f; } } } } }