////////////////////////////////////////////////////////////////////// // Advect using the MacCormack method from the Selle paper ////////////////////////////////////////////////////////////////////// void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd) { const float dt0 = _dt / _dx; Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); // use force array as temp arrays float* t1 = _xForce; // advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles) advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd); if(_domainBcLeft == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd); else setZeroX(_xVelocityTemp, res, zBegin, zEnd); if(_domainBcFront == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd); else setZeroY(_yVelocityTemp, res, zBegin, zEnd); if(_domainBcTop == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd); else setZeroZ(_zVelocityTemp, res, zBegin, zEnd); setZeroBorder(_density, res, zBegin, zEnd); setZeroBorder(_heat, res, zBegin, zEnd); /*int begin=zBegin * _slabSize; int end=begin + (zEnd - zBegin) * _slabSize; for (int x = begin; x < end; x++) _xForce[x] = _yForce[x] = 0.0f;*/ }
void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd) { Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); if(_domainBcLeft == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd); else setZeroX(_xVelocityOld, res, zBegin, zEnd); if(_domainBcFront == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd); else setZeroY(_yVelocityOld, res, zBegin, zEnd); if(_domainBcTop == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd); else setZeroZ(_zVelocityOld, res, zBegin, zEnd); }
////////////////////////////////////////////////////////////////////// // Advect using the MacCormack method from the Selle paper ////////////////////////////////////////////////////////////////////// void FLUID_3D::advectMacCormack() { Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res); else setZeroX(_xVelocity, res); if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res); else setZeroY(_yVelocity, res); if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res); else setZeroZ(_zVelocity, res); SWAP_POINTERS(_xVelocity, _xVelocityOld); SWAP_POINTERS(_yVelocity, _yVelocityOld); SWAP_POINTERS(_zVelocity, _zVelocityOld); SWAP_POINTERS(_density, _densityOld); SWAP_POINTERS(_heat, _heatOld); const float dt0 = _dt / _dx; // use force arrays as temp arrays for (int x = 0; x < _totalCells; x++) _xForce[x] = _yForce[x] = 0.0; float* t1 = _xForce; float* t2 = _yForce; advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, t1,t2, res, _obstacles); advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, t1,t2, res, _obstacles); advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, t1,t2, res, _obstacles); advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, t1,t2, res, _obstacles); advectFieldMacCormack(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, t1,t2, res, _obstacles); if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocity, res); else setZeroX(_xVelocity, res); if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocity, res); else setZeroY(_yVelocity, res); if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocity, res); else setZeroZ(_zVelocity, res); setZeroBorder(_density, res); setZeroBorder(_heat, res); for (int x = 0; x < _totalCells; x++) t1[x] = t2[x] = 0.0; }
////////////////////////////////////////////////////////////////////// // Advect using the MacCormack method from the Selle paper ////////////////////////////////////////////////////////////////////// void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd) { Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); const float dt0 = _dt / _dx; int begin=zBegin * _slabSize; int end=begin + (zEnd - zBegin) * _slabSize; for (int x = begin; x < end; x++) _xForce[x] = 0.0; // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res) advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd); // Have to wait untill all the threads are done -> so continuing in step 3 }
////////////////////////////////////////////////////////////////////// // constructor ////////////////////////////////////////////////////////////////////// WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors) { // if noise magnitude is below this threshold, its contribution // is negilgible, so stop evaluating new octaves _cullingThreshold = 1e-3; // factor by which to increase the simulation resolution _amplify = amplify; // manually adjust the overall amount of turbulence // DG - RNA-fied _strength = 2.; // add the corresponding octaves of noise _octaves = (int)(log((float)_amplify) / log(2.0f) + 0.5); // XXX DEBUG/ TODO: int casting correct? - dg // noise resolution _xResBig = _amplify * xResSm; _yResBig = _amplify * yResSm; _zResBig = _amplify * zResSm; _resBig = Vec3Int(_xResBig, _yResBig, _zResBig); _invResBig = Vec3(1./(float)_resBig[0], 1./(float)_resBig[1], 1./(float)_resBig[2]); _slabSizeBig = _xResBig*_yResBig; _totalCellsBig = _slabSizeBig * _zResBig; // original / small resolution _xResSm = xResSm; _yResSm = yResSm; _zResSm = zResSm; _resSm = Vec3Int(xResSm, yResSm, zResSm); _invResSm = Vec3(1./(float)_resSm[0], 1./(float)_resSm[1], 1./(float)_resSm[2] ); _slabSizeSm = _xResSm*_yResSm; _totalCellsSm = _slabSizeSm * _zResSm; // allocate high resolution density field _totalStepsBig = 0; _densityBig = new float[_totalCellsBig]; _densityBigOld = new float[_totalCellsBig]; for(int i = 0; i < _totalCellsBig; i++) { _densityBig[i] = _densityBigOld[i] = 0.; } /* fire */ _flameBig = _fuelBig = _fuelBigOld = NULL; _reactBig = _reactBigOld = NULL; if (init_fire) { initFire(); } /* colors */ _color_rBig = _color_rBigOld = NULL; _color_gBig = _color_gBigOld = NULL; _color_bBig = _color_bBigOld = NULL; if (init_colors) { initColors(0.0f, 0.0f, 0.0f); } // allocate & init texture coordinates _tcU = new float[_totalCellsSm]; _tcV = new float[_totalCellsSm]; _tcW = new float[_totalCellsSm]; _tcTemp = new float[_totalCellsSm]; // map all const float dx = 1./(float)(_resSm[0]); const float dy = 1./(float)(_resSm[1]); const float dz = 1./(float)(_resSm[2]); int index = 0; for (int z = 0; z < _zResSm; z++) for (int y = 0; y < _yResSm; y++) for (int x = 0; x < _xResSm; x++, index++) { _tcU[index] = x*dx; _tcV[index] = y*dy; _tcW[index] = z*dz; _tcTemp[index] = 0.; } // noise tiles _noiseTile = new float[noiseTileSize * noiseTileSize * noiseTileSize]; /* std::string noiseTileFilename = std::string("noise.wavelets"); generateTile_WAVELET(_noiseTile, noiseTileFilename); */ setNoise(noisetype); /* std::string noiseTileFilename = std::string("noise.fft"); generatTile_FFT(_noiseTile, noiseTileFilename); */ }
FLUID_3D::FLUID_3D(int *res, float *p0, float dt) : _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f), _dt(dt) { // set simulation consts // _dt = dt; // 0.10 // start point of array _p0[0] = p0[0]; _p0[1] = p0[1]; _p0[2] = p0[2]; _iterations = 100; _tempAmb = 0; _heatDiffusion = 1e-3; _vorticityEps = 2.0; _totalTime = 0.0f; _totalSteps = 0; _res = Vec3Int(_xRes,_yRes,_zRes); _maxRes = MAX3(_xRes, _yRes, _zRes); // initialize wavelet turbulence /* if(amplify) _wTurbulence = new WTURBULENCE(_res[0],_res[1],_res[2], amplify, noisetype); else _wTurbulence = NULL; */ // scale the constants according to the refinement of the grid _dx = 1.0f / (float)_maxRes; float scaling = 64.0f / _maxRes; scaling = (scaling < 1.0f) ? 1.0f : scaling; _vorticityEps /= scaling; // allocate arrays _totalCells = _xRes * _yRes * _zRes; _slabSize = _xRes * _yRes; _xVelocity = new float[_totalCells]; _yVelocity = new float[_totalCells]; _zVelocity = new float[_totalCells]; _xVelocityOld = new float[_totalCells]; _yVelocityOld = new float[_totalCells]; _zVelocityOld = new float[_totalCells]; _xForce = new float[_totalCells]; _yForce = new float[_totalCells]; _zForce = new float[_totalCells]; _density = new float[_totalCells]; _densityOld = new float[_totalCells]; _heat = new float[_totalCells]; _heatOld = new float[_totalCells]; _obstacles = new unsigned char[_totalCells]; // set 0 at end of step // DG TODO: check if alloc went fine for (int x = 0; x < _totalCells; x++) { _density[x] = 0.0f; _densityOld[x] = 0.0f; _heat[x] = 0.0f; _heatOld[x] = 0.0f; _xVelocity[x] = 0.0f; _yVelocity[x] = 0.0f; _zVelocity[x] = 0.0f; _xVelocityOld[x] = 0.0f; _yVelocityOld[x] = 0.0f; _zVelocityOld[x] = 0.0f; _xForce[x] = 0.0f; _yForce[x] = 0.0f; _zForce[x] = 0.0f; _obstacles[x] = false; } // 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(DOMAIN_BC_FRONT==1) _obstacles[index] = 1; // back slab index += _totalCells - _slabSize; if(DOMAIN_BC_BACK==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(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1; // top slab index += _slabSize - _xRes; if(DOMAIN_BC_TOP==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(DOMAIN_BC_LEFT==1) _obstacles[index] = 1; // right slab index += _xRes - 1; if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1; } }
FLUID_3D::FLUID_3D(int *res, float *p0) : _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f) { // set simulation consts _dt = DT_DEFAULT; // just in case. set in step from a RNA factor // start point of array _p0[0] = p0[0]; _p0[1] = p0[1]; _p0[2] = p0[2]; _iterations = 100; _tempAmb = 0; _heatDiffusion = 1e-3; _totalTime = 0.0f; _totalSteps = 0; _res = Vec3Int(_xRes,_yRes,_zRes); _maxRes = MAX3(_xRes, _yRes, _zRes); // initialize wavelet turbulence /* if(amplify) _wTurbulence = new WTURBULENCE(_res[0],_res[1],_res[2], amplify, noisetype); else _wTurbulence = NULL; */ // scale the constants according to the refinement of the grid _dx = 1.0f / (float)_maxRes; _constantScaling = 64.0f / _maxRes; _constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling; _vorticityEps = 2.0f / _constantScaling; // Just in case set a default value // allocate arrays _totalCells = _xRes * _yRes * _zRes; _slabSize = _xRes * _yRes; _xVelocity = new float[_totalCells]; _yVelocity = new float[_totalCells]; _zVelocity = new float[_totalCells]; _xVelocityOld = new float[_totalCells]; _yVelocityOld = new float[_totalCells]; _zVelocityOld = new float[_totalCells]; _xForce = new float[_totalCells]; _yForce = new float[_totalCells]; _zForce = new float[_totalCells]; _density = new float[_totalCells]; _densityOld = new float[_totalCells]; _heat = new float[_totalCells]; _heatOld = new float[_totalCells]; _obstacles = new unsigned char[_totalCells]; // set 0 at end of step // For threaded version: _xVelocityTemp = new float[_totalCells]; _yVelocityTemp = new float[_totalCells]; _zVelocityTemp = new float[_totalCells]; _densityTemp = new float[_totalCells]; _heatTemp = new float[_totalCells]; // DG TODO: check if alloc went fine for (int x = 0; x < _totalCells; x++) { _density[x] = 0.0f; _densityOld[x] = 0.0f; _heat[x] = 0.0f; _heatOld[x] = 0.0f; _xVelocity[x] = 0.0f; _yVelocity[x] = 0.0f; _zVelocity[x] = 0.0f; _xVelocityOld[x] = 0.0f; _yVelocityOld[x] = 0.0f; _zVelocityOld[x] = 0.0f; _xForce[x] = 0.0f; _yForce[x] = 0.0f; _zForce[x] = 0.0f; _obstacles[x] = false; } // boundary conditions of the fluid domain // set default values -> vertically non-colliding _domainBcFront = true; _domainBcTop = false; _domainBcLeft = true; _domainBcBack = _domainBcFront; _domainBcBottom = _domainBcTop; _domainBcRight = _domainBcLeft; _colloPrev = 1; // default value // set side obstacles int index; for (int y = 0; y < _yRes; y++) for (int x = 0; x < _xRes; x++) { // bottom slab index = x + y * _xRes; if(_domainBcBottom==1) _obstacles[index] = 1; // top slab index += _totalCells - _slabSize; if(_domainBcTop==1) _obstacles[index] = 1; } for (int z = 0; z < _zRes; z++) for (int x = 0; x < _xRes; x++) { // front slab index = x + z * _slabSize; if(_domainBcFront==1) _obstacles[index] = 1; // back slab index += _slabSize - _xRes; if(_domainBcBack==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; } }