VEC3I fluid_detection::cellPos(VEC3D& pos) { if (sph->dimension() == DIM2){ return VEC3I( (int)floor((pos.x - gMin.x) * cSize_inv), (int)floor((pos.y - gMin.y) * cSize_inv), (int)0); } return VEC3I( (int)floor((pos.x - gMin.x) * cSize_inv), (int)floor((pos.y - gMin.y) * cSize_inv), (int)floor((pos.z - gMin.z) * cSize_inv)); }
////////////////////////////////////////////////////////////////////// // Advect using the semi-Lagrangian method of Stam ////////////////////////////////////////////////////////////////////// void FLUID_3D_MIC::advectStam() { TIMER functionTimer(__FUNCTION__); VEC3I res = VEC3I(_xRes,_yRes,_zRes); if(_domainBcLeft == 0) _velocity.copyBorderX(); else _velocity.setZeroX(); if(_domainBcTop == 0) _velocity.copyBorderY(); else _velocity.setZeroY(); if(_domainBcFront == 0) _velocity.copyBorderZ(); else _velocity.setZeroZ(); _preadvection = _velocity; _velocity.swapPointers(_velocityOld); _density.swapPointers(_densityOld); _heat.swapPointers(_heatOld); const Real dt0 = _dt / _dx; VECTOR3_FIELD_3D::advect(dt0, _velocityOld, _densityOld, _density); VECTOR3_FIELD_3D::advect(dt0, _velocityOld, _heatOld, _heat); VECTOR3_FIELD_3D::advect(dt0, _velocityOld, _velocityOld, _velocity); _cachedQuadratic = _velocity - _velocityOld; _postadvection = _velocity; // this seems to fix things relative to explicit advection -- // otherwise new values appear at the boundaries _velocity.setZeroBorder(); if(_domainBcLeft == 0) _velocity.copyBorderX(); else _velocity.setZeroX(); if(_domainBcTop == 0) _velocity.copyBorderY(); else _velocity.setZeroY(); if(_domainBcFront == 0) _velocity.copyBorderZ(); else _velocity.setZeroZ(); _density.setZeroBorder(); _heat.setZeroBorder(); }
FLUID_3D_MIC::FLUID_3D_MIC(int xRes, int yRes, int zRes, int amplify, unsigned int* boundaries) : _xRes(xRes), _yRes(yRes), _zRes(zRes), _res(0.) { // set simulation consts _dt = 0.10; _iterations = 1000; _buoyancy = 0.1f; _heatDiffusion = 1e-3; _vorticityEps = 2.0; _totalTime = 0.0f; _totalSteps = 0; _res = VEC3I(_xRes,_yRes,_zRes); _maxRes = _res.maxElement(); // scale the constants according to the refinement of the grid _dx = 1.0f / (Real)_maxRes; Real scaling = 64.0f / _maxRes; scaling = (scaling < 1.0f) ? 1.0f : scaling; _vorticityEps /= scaling; // precision of the CG solver _solverEps = 1e-10; _center = VEC3F(0,0,0); _lengths = VEC3F(_dx * _xRes, _dx * _yRes, _dx * _zRes); _density = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _densityOld = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _heat = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _heatOld = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _pressure = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _divergence = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _residual = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _direction = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _q = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _dudt0 = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _dudt1 = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _velocity = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _velocityOld = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _force = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _vorticity = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _precon = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _z = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Adiag = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aplusi = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aplusj = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aplusk = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aminui = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aminuj = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); _Aminuk = FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); // allocate arrays _totalCells = _xRes * _yRes * _zRes; _slabSize = _xRes * _yRes; _xs = 1; _ys = _xRes; _zs = _slabSize; _obstacles = new unsigned char[_totalCells]; _dirichletObstacleField = new bool[_totalCells]; _neumannObstacleField = new bool[_totalCells]; _neumannVelocityField = VECTOR3_FIELD_3D(_xRes, _yRes, _zRes, _center, _lengths); for (int x = 0; x < _totalCells; x++) { _obstacles[x] = false; _dirichletObstacleField[x] = false; _neumannObstacleField[x] = false; } // set up the boundary conditions if (boundaries != NULL) { _domainBcFront = boundaries[0]; _domainBcBack = boundaries[1]; _domainBcLeft = boundaries[2]; _domainBcRight = boundaries[3]; _domainBcTop = boundaries[4]; _domainBcBottom = boundaries[5]; } else { _domainBcFront = 1; _domainBcBack = 1; _domainBcLeft = 1; _domainBcRight = 1; _domainBcTop = 0; _domainBcBottom = 0; } // set side obstacles int index; for (int y = 0; y < _yRes; y++) for (int x = 0; x < _xRes; x++) { // front slab index = x + y * _xRes; if(_domainBcFront==1) _obstacles[index] = 1; // back slab index += _totalCells - _slabSize; if(_domainBcBack==1) _obstacles[index] = 1; } for (int z = 0; z < _zRes; z++) for (int x = 0; x < _xRes; x++) { // bottom slab index = x + z * _slabSize; if(_domainBcBottom==1) _obstacles[index] = 1; // top slab index += _slabSize - _xRes; if(_domainBcTop==1) _obstacles[index] = 1; } for (int z = 0; z < _zRes; z++) for (int y = 0; y < _yRes; y++) { // left slab index = y * _xRes + z * _slabSize; if(_domainBcLeft==1) _obstacles[index] = 1; // right slab index += _xRes - 1; if(_domainBcRight==1) _obstacles[index] = 1; } }
bool fluid_detection::initGrid() { cells = 0; // VEC3D fMax = sph->particle(0)->position(); // VEC3D fMin = fMax; // if (sph->getPeriodicDirection() == PERI_X) // { // for (unsigned int i = 0; i < sph->nParticleByType(FLUID); i++) // { // VEC3D p = sph->particle(i)->position(); // if (fMax <= p) // fMax = p; // if (fMin >= p) // fMin = p; // } // } gMin = gMin - VEC3D(gcSize); gMax = gMax + VEC3D(gcSize); gSize = gMax - gMin; gcCount.x = static_cast<int>(ceil(gSize.x / gcSize)); gcCount.y = static_cast<int>(ceil(gSize.y / gcSize)); cells = gcCount.x * gcCount.y; if (sph->dimension() == DIM3){ gcCount.z = static_cast<int>(ceil(gSize.z / gcSize)); cells *= gcCount.z; } if (!gcCount.x || !gcCount.y){ std::cout << "You need to correctly set simulation boundaries" << std::endl; return false; } cellCount_1 = gcCount - VEC3I(1); cSize_inv = 1.0 / gcSize; size_t np = sph->nParticle(); if (sph->getPeriodicParticles()) { np += sph->getPeriodicParticles()->nParticle(); } hashes = new VEC2UI[np]; cell_id = new size_t[np]; memset(cell_id, 0, sizeof(size_t)*np); cell_start = new size_t[cells]; memset(cell_start, 0, sizeof(size_t)*cells); // if (sph->getPeriodicDirection() == PERI_X) // { // VEC3I _cmax = cellPos(fMax); // peri_maxCI.x = _cmax.x; // VEC3I _cmin = cellPos(fMin); // peri_minCI.x = _cmin.x; // } // if (sph->Device() == GPU){ // checkCudaErrors(cudaMalloc((void**)&d_hashes, sizeof(int2) * np)); // checkCudaErrors(cudaMalloc((void**)&d_cell_id, sizeof(uint) * np)); // checkCudaErrors(cudaMalloc((void**)&d_cell_start, sizeof(uint) * cells)); // } return true; }