Esempio n. 1
0
/**
 * set the values of all ghost cells depending on the specifed 
 * boundary conditions;
 * if the ghost layer replicates the variables of a remote SWE_Block, 
 * the values are copied
 */
void SWE_Block::setGhostLayer() {

#ifdef DBG
  cout << "Set simple boundary conditions " << endl << flush;
#endif
  // call to virtual function to set ghost layer values 
  setBoundaryConditions();

  // for a CONNECT boundary, data will be copied from a neighbouring
  // SWE_Block (via a SWE_Block1D proxy object)
  // -> these copy operations cannot be executed in GPU/accelerator memory, e.g.
  //    setBoundaryConditions then has to take care that values are copied.
  
#ifdef DBG
  cout << "Set CONNECT boundary conditions in main memory " << endl << flush;
#endif
  // left boundary
  if (boundary[BND_LEFT] == CONNECT) {
     for(int j=0; j<=ny+1; j++) {
       h[0][j] = neighbour[BND_LEFT]->h[j];
       hu[0][j] = neighbour[BND_LEFT]->hu[j];
       hv[0][j] = neighbour[BND_LEFT]->hv[j];
      };
  };
  
  // right boundary
  if(boundary[BND_RIGHT] == CONNECT) {
     for(int j=0; j<=ny+1; j++) {
       h[nx+1][j] = neighbour[BND_RIGHT]->h[j];
       hu[nx+1][j] = neighbour[BND_RIGHT]->hu[j];
       hv[nx+1][j] = neighbour[BND_RIGHT]->hv[j];
      };
  };

  // bottom boundary
  if(boundary[BND_BOTTOM] == CONNECT) {
     for(int i=0; i<=nx+1; i++) {
       h[i][0] = neighbour[BND_BOTTOM]->h[i];
       hu[i][0] = neighbour[BND_BOTTOM]->hu[i];
       hv[i][0] = neighbour[BND_BOTTOM]->hv[i];
      };
  };

  // top boundary
  if(boundary[BND_TOP] == CONNECT) {
     for(int i=0; i<=nx+1; i++) {
       h[i][ny+1] = neighbour[BND_TOP]->h[i];
       hu[i][ny+1] = neighbour[BND_TOP]->hu[i];
       hv[i][ny+1] = neighbour[BND_TOP]->hv[i];
     }
  };

#ifdef DBG
  cout << "Synchronize ghost layers (for heterogeneous memory) " << endl << flush;
#endif
  // synchronize the ghost layers (for PASSIVE and CONNECT conditions)
  // with accelerator memory
  synchGhostLayerAfterWrite();
}
Esempio n. 2
0
//
// This method is a modified version of the FluidSimulator2d::updateVelocity
// method to reflect sand behavior
//
void SandSimulator2d::updateVelocity( float dt )
{
	//FluidSimulator2d::updateVelocity(dt);
	//return;

	// store the velocity in the oldVelocity member of each cell so that we later can compute the change in velocity --------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
		(*it).second.oldVelocity = (*it).second.velocity;

	// if advection is not done through particles (PIC/FLIP)
	if( !particleBasedAdvection )
		// then we use a sem-lagrange method to advect velocities...
		advectGridVelocities( dt );

	// apply external forces ----------------------------------
	applyGravity( dt, 0.0f, -9.1f );


	// apply viscosity ----------------------------------------
	solveViscosity( dt );




	// extrapolate velocities into surrounding buffer cells ------
	extrapolateVelocities();
	// set Boundary conditions -------
	setBoundaryConditions();


	// solve for pressure and make the velocity grid divergence free ----
	solvePressure( dt );

	// extrapolate velocity into buffer cells second time -----------------
	extrapolateVelocities();
	// set solid cell velocities ------------------------------
	setBoundaryConditions();

	// sand
	applySandModel( dt );

	// extrapolate velocity into buffer cells second time -----------------
	//extrapolateVelocities();
	// set solid cell velocities ------------------------------
	//setBoundaryConditions();



	// compute the change in velocity using the oldVelocity member which we have stored at the beginning of this procedure ----------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		(*it).second.velocityChange.x = (*it).second.velocity.x - (*it).second.oldVelocity.x;
		(*it).second.velocityChange.y = (*it).second.velocity.y - (*it).second.oldVelocity.y;
	}


	// if advection is not done through particles (PIC/FLIP)
	if( particleBasedAdvection )
	{
		// update the velocities of the particles from the grid --------------------------------------
		for( std::vector<Particle2d>::iterator it=markerParticles.begin(); it != markerParticles.end(); ++it )
		{
			// the solution of PIC and FLIP are blended together according to a specified blendweight
			// FLIP
			math::Vec2f flipVelocity = (*it).velocity + getVelocityChange( (*it).position.x, (*it).position.y );
			// PIC
			math::Vec2f picVelocity = getVelocity( (*it).position.x, (*it).position.y );
			// FINAL
			(*it).velocity = PICFLIPWeight*flipVelocity + (1.0f - PICFLIPWeight)*picVelocity;
		}
	}
}
Esempio n. 3
0
//
// This method is a modified version of the FluidSimulator2d::updateVelocity
// method to reflect viscoelastic behavior
//
void ViscoElasticFluid2d::updateVelocity( float dt )
{
	//FluidSimulator2d::updateVelocity(dt);
	//return;

	// store the velocity in the oldVelocity member of each cell so that we later can compute the change in velocity --------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
		(*it).second.oldVelocity = (*it).second.velocity;

	// update total strain for each fluid cell ------------------------------------------------------------------------------
	// calculate T and accumulate new strain in E
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		Cell *cell = &(*it).second;

		if( cell->type != Cell::Fluid )
			continue;

		// first term T
		math::Matrix22f D = computeStrainRateTensor( cell );

		cell->strainTensor += dt*D;

		// second term -kyr*...
		float norm = math::frobeniusNorm( cell->strainTensor );
		math::Matrix22f plasticYielding = math::Matrix22f::Zero();
		if( norm )
			plasticYielding = plasticYieldRate*std::max<float>( 0, norm - elasticYieldPoint )*cell->strainTensor*(1.0f / norm);

		cell->strainTensor -= dt*plasticYielding;
	}

	// advect elastic strain tensor E -------------------------------------------------------------------------------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
		// clear temp variable for the intermediate result
		(*it).second.temp = math::Matrix22f::Zero();

	// now advect the tensor components for each fluid-cell
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		Cell *cell = &(*it).second;

		float e11, e22, e12;


		e11 = cell->strainTensor.m[0][0];
		e22 = cell->strainTensor.m[1][1];
		e12 = cell->strainTensor.m[0][1];

		if(cell->type == Cell::Fluid)
		{
			// track strain tensor components which lie at the cell center -> E[1][1] && E[2][2]
			math::Vec2f centerPos = traceParticle( math::Vec2f( (*it).first.i * cellSize+(cellSize/2.0f), (*it).first.j * cellSize+(cellSize/2.0f) ), dt );
			e11 = getInterpolatedStrainTensorComponent( centerPos.x/cellSize - 0.5f, centerPos.y/cellSize - 0.5f, 0, 0 );
			e22 = getInterpolatedStrainTensorComponent( centerPos.x/cellSize - 0.5f, centerPos.y/cellSize - 0.5f, 1, 1 );
		}

		if( cell->xNeighboursFluid || cell->yNeighboursFluid )
		{
			// track strain tensor components which lie at the cell edges -> E[1][2]
			math::Vec2f offPos = traceParticle( math::Vec2f( (*it).first.i * cellSize, (*it).first.j * cellSize ), dt );
			e12 = getInterpolatedStrainTensorComponent( offPos.x/cellSize, offPos.y/cellSize, 0, 1 );
		}

		cell->temp.m[0][0] = e11;
		cell->temp.m[1][1] = e22;
		cell->temp.m[0][1] = e12;
		cell->temp.m[1][0] = e12;

	}

	// copy the intermediate results to the final values
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		if( (*it).second.type == Cell::Fluid )
			(*it).second.strainTensor = (*it).second.temp;
		else
			(*it).second.strainTensor = (*it).second.temp;
	}

	// extrapolate elastic strain into air
	extrapolateStrain();

	// advect velocities (if advection is not done through particles (PIC/FLIP) ) --------------------------------
	if( !particleBasedAdvection )
		// then we use a sem-lagrange method to advect velocities...
		advectGridVelocities( dt );

	// apply external forces ------------------------------------------------------------------------------------
	applyGravity( dt, 0.0f, -9.1f );


	/*
	// stretch test
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		Cell *cell = &it->second;

		// we have to advance velocity-components of all cells which border fluid cells
		if( cell->xNeighboursFluid )
		{
		if( cell->center.x > 0.6f )
		{
			cell->velocity.x += 10.0f*dt;
			//cell->velocity.y += 0.0f;
		}else
		if( cell->center.x < 0.4f )
		{
			cell->velocity.x += -10.0f*dt;
			//cell->velocity.y += 0.0f;
		}
		}
	}
	*/


	// apply elastic strain force to u -----------------------------------------------------------------------------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		Cell *cell = &(*it).second;

		cell->vonMisesEquivalentStress = 0.0f;

		if( cell->xNeighboursFluid || cell->yNeighboursFluid )
		{
			math::Vec2f f = elasticModulus*computeDivE( cell );

			if( cell->xNeighboursFluid )
				cell->velocity.x += dt*f.x;
			if( cell->yNeighboursFluid )
				cell->velocity.y += dt*f.y;

			// compute equivalent stress
			cell->stressTensor = -elasticModulus*cell->strainTensor;
			cell->vonMisesEquivalentStress = sqrt( 3.0f/2.0f ) * math::frobeniusNorm( cell->stressTensor );
		}
	}



	// apply viscosity ----------------------------------------------------
	solveViscosity( dt );




	// extrapolate velocities into surrounding buffer cells ---------------
	extrapolateVelocities();
	// set Boundary conditions --------------------------------------------
	setBoundaryConditions();


	// solve for pressure and make the velocity grid divergence free ------
	solvePressure( dt );

	// extrapolate velocity into buffer cells second time -----------------
	extrapolateVelocities();
	// set solid cell velocities ------------------------------------------
	setBoundaryConditions();

	

	// compute the change in velocity using the oldVelocity member which we have stored at the beginning of this procedure ----------
	for( stdext::hash_map<Cell::Coordinate, Cell, hash_compare>::iterator it = gridCells.begin(); it != gridCells.end(); ++it )
	{
		(*it).second.velocityChange.x = (*it).second.velocity.x - (*it).second.oldVelocity.x;
		(*it).second.velocityChange.y = (*it).second.velocity.y - (*it).second.oldVelocity.y;
	}

	// if advection is not done through particles (PIC/FLIP)
	if( particleBasedAdvection )
	{
		// update the velocities of the particles from the grid --------------------------------------
		for( std::vector<Particle2d>::iterator it=markerParticles.begin(); it != markerParticles.end(); ++it )
		{
			// the solution of PIC and FLIP are blended together according to a specified blendweight
			// FLIP
			math::Vec2f flipVelocity = (*it).velocity + getVelocityChange( (*it).position.x, (*it).position.y );
			// PIC
			math::Vec2f picVelocity = getVelocity( (*it).position.x, (*it).position.y );
			// FINAL
			(*it).velocity = PICFLIPWeight*flipVelocity + (1.0f - PICFLIPWeight)*picVelocity;
		}
	}

}