SPH particles not clumping

Started by
15 comments, last by h4tt3n 10 years, 1 month ago

Hello,

I'm working on a SPH simulation demo based on the paper, Particle-based Viscoelastic Fluid Simulation, 2005 Clavet, and after translating the double density relaxation and viscosity functions into code, the simulation appears to work, with swirling movements and correct pressures through a U pipe. However, I noticed that my particles are not clumping together like they should in other videos, especially visible when gravity is disabled. I have tried tweaking the rest density, stiffness, near-stiffness and radius constants but I can't seem to get the desired parameters to make my particles clump.

Desired effect:

Here's my videos.

If anyone can offer me a clue of what is going on here I really apperciate it.

Project: https://drive.google.com/file/d/0B2macuhZeO18N3dJLUl5VU5ZVk0/edit?usp=sharing

Here are some relevant parts of my implementation:


public float kParticleRadius = 15.0f;
public float kGravity = 400.0f;
public float kLinearViscocity = 0.001f;
public float kQuadraticViscocity = 0.01f;
public float kRestDensity = 1000.0f;
public float kStiffness = 10.0f;
public float kStiffnessNear = 10.0f;

Update loop:


ApplyExternalForces(timeStep);
ApplyViscosity(timeStep);
AdvanceParticles(timeStep);
grid.UpdateNeighbours(listParticles);
DoubleDensityRelaxation(timeStep);
ResolveCollisions(timeStep);
UpdateVelocity(timeStep);
ColorAndRemoveStray();

ApplyViscosity():


void ApplyViscosity(float dt)
{
	foreach (Particle p in listParticles)
	{
		foreach (Particle n in p.Neighbours)
		{
			float q = (p.Position - n.Position).Length / p.Radius;
			if (q < 1.0f)
			{
				Vector2 vn = (n.Position - p.Position).Normalized();
				float u = Vector2.Dot(p.Velocity - n.Velocity, vn);
				if (u > 0.0f)
				{
					Vector2 i = 0.5f * dt * (1 - q) * (kLinearViscocity * u +
                                                    kQuadraticViscocity * u * u) * vn;
					p.Velocity -= i;
					n.Velocity += i;
				}
			}
		}
	}
}

DoubleDensityRelaxation():


void DoubleDensityRelaxation(float dt)
{
	foreach (Particle p in listParticles)
	{
		// Sample neighbouring particle's density
		p.Density = p.DensityNear = 0.0f;
		foreach (Particle n in p.Neighbours)
		{
			float q = (p.Position - n.Position).Length / p.Radius;
			if (q < 1.0f)
			{
				p.Density += (1 - q) * (1 - q);
				p.DensityNear += (1 - q) * (1 - q) * (1 - q);
			}
		}

		test = p.Density;

		// Push and pull particles
		// If particle's density > rest density, it will be pushed away
		p.Pressure = kStiffness * (p.Density - kRestDensity);
		p.PressureNear = kStiffnessNear * p.DensityNear;

		Vector2 dx = Vector2.Zero;
		foreach (Particle n in p.Neighbours)
		{
			Vector2 v = p.Position - n.Position;
			float q = v.Length / p.Radius;
			if (q < 1.0f)
			{
				Vector2 displacement = 0.5f * dt * dt * (p.Pressure * (1 - q) + 
                                                       p.PressureNear * (1 - q) * (1 - q)) * v.Normalized();
				n.Position += displacement;
				dx -= displacement;
			}
		}
		p.Position += dx;
	}
}
Advertisement

Well, it looks like your particles repel but don't attract. There could be a number of reasons for this, and maybe it's just a variable that needs tweaking. It looks like only your repulsive PressureNear force is working and not the both-ways Pressure force. What happens if you increase the KStiffnes variable?

Btw. your project looks cool. I like the on-the-fly wall making feature. I'm working on something similarly and have developed a nice working fluid simulator. What machine are you running your simulation on, and how many particles can you simulate while keeping a reasonable framerate? It seems like you are calling both a vector normalization and length routine twice per interaction which heavily reduces performance.

Cheers,

Mike

The videos look fine to me. In the standard SPH formulation there is no attractive force between SPH particles. If no body force is applied, and no boundaries exist, the particles should move away from one another given enough time. In reality you will always have boundaries and body forces

If you want attractive forces you should have a look in the literature on free-surface and multiphase flows.

Hey Mike,

Increasing kRestDensity and kStiffness both repels particles, and changing kNearStiffness doesn't seem to do anything. The only other respond I get is when kStiffness is less than 1.0f, which will make the particles attract into a few singles, and not clusters. I'm interested to know what are the parameters you've used?

It's preforming pretty well on my i7-4800MQ and GTX780M at 2000 particles @ 110fps, 3800 @ 50. I think the few optimizations i can do is to call vectors by ref and bring out the sqrt from .Length until after the radius check, but that's after when I get the simulation perfected.

Hi Jones,

The Clavet paper describes under 4.2. Incompressibility Relaxation that the particles should attract and repel based on a threshold, although I can't seem to find the magic numbers. sad.png

Thanks,

Alex

The videos look fine to me. In the standard SPH formulation there is no attractive force between SPH particles. If no body force is applied, and no boundaries exist, the particles should move away from one another given enough time. In reality you will always have boundaries and body forces

If you want attractive forces you should have a look in the literature on free-surface and multiphase flows.

This is simply not true, no offence intended. A liquid without density-controlled repulsion *and* attraction can only behave like a bunch of rubber balls and not show any of the liquid-specific properties like surface tension (forming droplets or "slimy" strings) and turbulence eddies.

@hl

Okay, nice to know. I'll take a closer look at your code later. I have developed my own algorithms from scratch, so my constants doesn't apply to this simulation.

Btw. the integration algorithm looks pretty funky, where does that come from?

For comparison I have a simulation that runs fluently on an 8 year old machine with 6000 particles and 130000 interactions, rendered in software. On our newer stationary machine it runs nice and smooth with more than twice those numbers.

Cheers,

Mike

I'm sorry you disagree with me h4tt3n but you are wrong. In the standard SPH formulation for single phase fluid flows there is no attraction between SPH particles. Surface tension in such flows has no meaning, hence it is not included in the algorithm.

Clavet has extended the SPH algorithm in two ways, one way is the double density approach, the second is the addition of springs between the particles. I didn't realise you were using this formulation, so my previous comment does not apply to your code.

You might want to try the bubble model Clavet did in figure 3. as it is easier to observe the effect in this model than the ones you have shown.

PS I'm enjoying playing with your code, nicely done.

@Brucedjones

Well okay then. I don't want to spoil a nice thread like this with endless arguments :-) But I hope we might still agree that single phased fluids are not nearly as interesting to use in games or interactive doodles, since they don't display the properties I mentioned?

The method I have developed has a purely repulsive local pressure force applied between any two interacting particles, and a repulsive / attractive global pressure force, applied to all particles within reach of any particle. Also, there is a local, particle-to-particle viscous damping force. In my opinion it displays very rewarding and entertaining properties, and I still haven't grown tired of playing around with it. In order to increase the number of particles I have developed a *completely square-root-free* algorithm. The cpu-expensive sqrt() function is not used at all.

Currently I am translating the code to c++, and I would be glad to share it here when I'm done. In the mean time I will try to post a video.

Cheers,

Mike

Looking forward to see your implementation. I've optimized the grid and some areas and updated the project link, but otherwise it has the same algorithms.

hl, I downloaded your code and tried to run it on my stationary quad core machine, but it only shows a gray screen with some text. When I add particles, a white box appears in the center of the screen, but no particles. Also, I get a lot of GLSL warnings at startup.

Cheers,

Mike

What are the warnings? My guess is to drop the #version tag to 330 in the shader files and see if it runs. It works on my intel HD4600, and should work on any card as long it supports the version profile (400 for DX11 equivalent).

This topic is closed to new replies.

Advertisement