Example #1
0
        /// <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;
                        }
                    }
                }
            }
        }
Example #2
0
 public SPHSimulation(float cellSpace, RectangleF domain)
 {
     this.CellSpace   = cellSpace;
     this.Domain      = domain;
     this.Viscosity   = Constants.VISC0SITY;
     this.m_grid      = new IndexGrid(cellSpace, domain);
     this.SKGeneral   = new SKPoly6(cellSpace);
     this.SKPressure  = new SKSpiky(cellSpace);
     this.SKViscosity = new SKViscosity(cellSpace);
 }
Example #3
0
        /// <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();
            }
        }
Example #4
0
        /// <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;
                        }
                    }
                }
            }
        }