IPhone : My Smoothed Particles Hydrodynamic Simulation is not working

on Sunday, March 29, 2015

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