/** * 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(); }
// // 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; } } }
// // 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; } } }