////////////////////////////////////////////////////////////////////// // 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::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); }
void FLUID_3D::advectFieldMacCormack2(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity, float* oldField, float* newField, float* tempResult, float* temp1, Vec3Int res, const unsigned char* obstacles, int zBegin, int zEnd) { float* phiHatN = tempResult; float* t1 = temp1; const int sx= res[0]; const int sy= res[1]; float*& phiN = oldField; float*& phiN1 = newField; // phiHatN = A^R(phiHatN1) advectFieldSemiLagrange( -1.0*dt, xVelocity, yVelocity, zVelocity, phiHatN, t1, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole) // phiN1 = phiHatN1 + (phiN - phiHatN) / 2 const int border = 0; for (int z = zBegin+border; z < zEnd-border; z++) for (int y = border; y < sy-border; y++) for (int x = border; x < sx-border; x++) { int index = x + y * sx + z * sx*sy; phiN1[index] = phiHatN[index] + (phiN[index] - t1[index]) * 0.50f; //phiN1[index] = phiHatN1[index]; // debug, correction off } copyBorderX(phiN1, res, zBegin, zEnd); copyBorderY(phiN1, res, zBegin, zEnd); copyBorderZ(phiN1, res, zBegin, zEnd); // clamp any newly created extrema clampExtrema(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole) // if the error estimate was bad, revert to first order clampOutsideRays(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, obstacles, phiHatN, zBegin, zEnd); // phiHatN is only used at cells within thread range, so its ok }