I'm just developed a Smoothed Particles Hydrodynamics Simulation in iOS. But the particles are moving like crazy and fliying all around.
I've been strugling for a while with this project. But nothing seems to work. And also, the due date on my class for this project is getting closer.
Can somebody help me with this? Thanks :)
This is the main part of my code:
/**
* It computes the next state of the particle system in time.
*
* @param
* @return
*/
- (void) update
{
// Creating particles if necessary
if ([particles count] < self.numberOfParticles)
[self createMoreParticles:10];
// Generating a new grid.
[self generateGrid];
// Computing accelerations for each particle
[self computeAccelerations];
for (int i=0; i<[particles count]; i++)
{
ECEParticle* particle;
// Getting particle from array
particle = particles[i];
GLKVector3 newPosition;
// Updating particle velocity
particle.velocity = [ECELeapFrogIntegrator integrateVector:particle.acceleration withDeltaTime:fluidMaterial.deltaTime previousVectorValue:particle.velocity];
// Updating particle position
newPosition = [ECELeapFrogIntegrator integrateVector:particle.velocity withDeltaTime:fluidMaterial.deltaTime previousVectorValue:particle.position];
particle.velocity = GLKVector3DivideScalar(GLKVector3Subtract(newPosition, particle.position), fluidMaterial.deltaTime);
// Updating particle position
[particle setParticlePosition:newPosition];
// Handling collisions with container
if (collisionShape)
[collisionShape handleCollisionFor:particle];
// Floor collision handling
if (newPosition.y <= 0)
{
// Putting particle on the floor's surface
newPosition.v[1] = 0;
// Changing velocity
particle.velocity.v[0] = particle.velocity.v[0] * 0.7;
particle.velocity.v[1] = particle.velocity.v[1] * 0.9 * (-1);
particle.velocity.v[2] = particle.velocity.v[2] * 0.7;
}
}
}
#pragma mark - Physics
/**
* It computes the acceleration of every particle in the system.
*
* @param
* @return
*/
- (void) computeAccelerations
{
// 1st cyle to calculate densities, pressures and nearest neighbours.
for (int i=0; i<[particles count]; i++)
{
NSMutableArray* neighbours;
ECEParticle *particle;
// Getting current particle
particle = particles[i];
if (particle)
{
// Getting particle's neighbours
//neighbours = [grid findNearestNeighborsToPosition:particle withRadius:fluidMaterial.supportRadius];
neighbours = particles;
// Computing particle's density.
[self computeDensityOfParticle:particle fromItsNeighbours:neighbours];
// Computing particle's pressure.
[self computePressureOfParticle:particle];
}
}
// 2do cyle to calculate the forces.
for (int i=0; i<[particles count]; i++)
{
NSMutableArray* neighbours;
ECEParticle *particle;
// Getting current particle
particle = particles[i];
if (particle)
{
GLKVector3 forces;
// Getting particle's neighbours
//neighbours = [grid findNearestNeighborsToPosition:particle withRadius:fluidMaterial.supportRadius];
neighbours = particles;
// Reseting forces to zero vector
forces = GLKVector3Make(0.0, 0.0, 0.0);
// Computing the pressure force acting over the particle.
[self computePressureForceOverParticle:particle fromItsNeighbours:neighbours];
// Computing the pressure force acting over the particle.
[self computeViscosityForceOverParticle:particle fromItsNeighbours:neighbours];
// Adding the gravity force
forces = GLKVector3Add(forces, gravity);
// Adding the pressure force
forces = GLKVector3Add(forces, particle.pressureForce);
// Adding the viscosity force
forces = GLKVector3Add(forces, particle.viscosityForce);
// Dividing the sum of all the forces by the mass of the particle in order to get the final acceleration.
particle.acceleration = GLKVector3DivideScalar(forces, particle.density);
}
};
}
/**
* It calculates the density of the input particle "particle" by interpolating the densities of the particle's neighbours found in input "neighbours".
*
* @param particle The particle which density will be calculated.
* @param neighbours The neighbours of the input particle.
* @return
*/
- (void) computeDensityOfParticle:(ECEParticle*)particle
fromItsNeighbours:(NSMutableArray*)neighbours
{
double density;
GLKVector3 diff;
// init
density = 0;
for (int i=0; i<[neighbours count]; i++)
{
// Getting the substraction vector
diff = GLKVector3Subtract(particle.position, ((ECEParticle*)neighbours[i]).position);
// Getting density
density += [ECEKernels usePolyKernel:diff];
}
// Setting calculated density to the particle.
particle.density = density * [fluidMaterial particlesMass];
}
/**
* It calculates the pressure of the input particle "particle".
*
* @param particle The particle which pressure will be calculated.
* @return
*/
- (void) computePressureOfParticle:(ECEParticle*)particle
{
particle.pressure = fluidMaterial.gassConstant * (particle.density - fluidMaterial.restDensity);
}
/**
* It computes the pressure force that is acting over the input particle "particle".
*
* @param particle The particle which pressure will be calculated.
* @return
*/
- (void) computePressureForceOverParticle:(ECEParticle*)particle
fromItsNeighbours:(NSMutableArray*)neighbours
{
GLKVector3 pressureForce, position, gradient;
double distance, auxiliar;
ECEParticle* neigh;
// init
distance = 0;
pressureForce = GLKVector3Make(0, 0, 0);
for (int i=0; i<[neighbours count]; i++)
{
// Getting neighbour i
neigh = ((ECEParticle*)neighbours[i]);
// Calculating distance between particles
position = GLKVector3Subtract(particle.position, neigh.position);
// Getting gradient
gradient = [ECEKernels useGradiantOfSpikyKernel:position];
// Calculating densities
auxiliar = (particle.pressure + neigh.pressure) / (2 * neigh.density);
//auxiliar = (particle.pressure / (particle.density * particle.density)) +
// (neigh.pressure / (neigh.density * neigh.density));
// Adding to pressure force
pressureForce = GLKVector3Add(pressureForce, GLKVector3MultiplyScalar(gradient, auxiliar));
}
// Setting calculated density to the particle.
particle.pressureForce = GLKVector3MultiplyScalar(pressureForce, - 1 * [fluidMaterial particlesMass]);
}
/**
* It computes the viscosity force that is acting over the input particle "particle".
*
* @param particle The particle which viscosity will be calculated.
* @return
*/
- (void) computeViscosityForceOverParticle:(ECEParticle*)particle
fromItsNeighbours:(NSMutableArray*)neighbours
{
GLKVector3 viscosityForce, position;
double distance, laplacian;
GLKVector3 velocities;
ECEParticle* neigh;
// init
distance = 0;
viscosityForce = GLKVector3Make(0, 0, 0);
for (int i=0; i<[neighbours count]; i++)
{
// Getting neighbour i
neigh = ((ECEParticle*)neighbours[i]);
// Calculating distance between particles
position = GLKVector3Subtract(particle.position, neigh.position);
// Getting gradient
laplacian = [ECEKernels useLaplacianOfViscosityKernel:position];
// Calculating densities
velocities = GLKVector3DivideScalar(GLKVector3Subtract(neigh.velocity, particle.velocity), (neigh.density));
// Adding to pressure force
viscosityForce = GLKVector3Add(viscosityForce, GLKVector3MultiplyScalar(velocities, laplacian));
}
// Setting calculated density to the particle.
particle.viscosityForce = GLKVector3MultiplyScalar(viscosityForce, [fluidMaterial particlesMass] * [fluidMaterial viscocityCoef]);
}
0 comments:
Post a Comment