////////////////////////////////////////////////////////////////////// // project into divergence free field ////////////////////////////////////////////////////////////////////// void FLUID_3D_MIC::project() { TIMER functionTimer(__FUNCTION__); int index, x, y, z; setObstacleBoundaries(); // copy out the boundaries if(_domainBcLeft == 0) _velocity.setNeumannX(); else _velocity.setZeroX(); if(_domainBcTop == 0) _velocity.setNeumannY(); else _velocity.setZeroY(); if(_domainBcFront == 0) _velocity.setNeumannZ(); else _velocity.setZeroZ(); // calculate divergence index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { Real xright = _velocity[index + 1][0]; Real xleft = _velocity[index - 1][0]; Real yup = _velocity[index + _xRes][1]; Real ydown = _velocity[index - _xRes][1]; Real ztop = _velocity[index + _slabSize][2]; Real zbottom = _velocity[index - _slabSize][2]; if(_obstacles[index+1]) xright = - _velocity[index][0]; if(_obstacles[index-1]) xleft = - _velocity[index][0]; if(_obstacles[index+_xRes]) yup = - _velocity[index][1]; if(_obstacles[index-_xRes]) ydown = - _velocity[index][1]; if(_obstacles[index+_slabSize]) ztop = - _velocity[index][2]; if(_obstacles[index-_slabSize]) zbottom = - _velocity[index][2]; _divergence[index] = -_dx * 0.5f * ( xright - xleft + yup - ydown + ztop - zbottom ); _pressure[index] = 0.0f; } _pressure.copyBorderAll(); _cachedDivergence = _divergence; // solve Poisson equation solvePoisson(_pressure, _divergence, _obstacles, false); _cachedPressure = _pressure; // project out solution -- more matrix-friendly version Real invDx = 1.0f / _dx; index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { if (x == 1) _velocity[index][0] -= (_pressure[index + 1] - _pressure[index]) * invDx; else if (x == _xRes - 2) _velocity[index][0] -= (_pressure[index] - _pressure[index - 1]) * invDx; else _velocity[index][0] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx; if (y == 1) _velocity[index][1] -= (_pressure[index + _xRes] - _pressure[index]) * invDx; else if (y == _yRes - 2) _velocity[index][1] -= (_pressure[index] - _pressure[index - _xRes]) * invDx; else _velocity[index][1] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx; if (z == 1) _velocity[index][2] -= (_pressure[index + _slabSize] - _pressure[index]) * invDx; else if (z == _zRes - 2) _velocity[index][2] -= (_pressure[index] - _pressure[index - _slabSize]) * invDx; else _velocity[index][2] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx; } }
////////////////////////////////////////////////////////////////////// // project into divergence free field ////////////////////////////////////////////////////////////////////// void FLUID_3D::project() { int x, y, z; size_t index; float *_pressure = new float[_totalCells]; float *_divergence = new float[_totalCells]; memset(_pressure, 0, sizeof(float)*_totalCells); memset(_divergence, 0, sizeof(float)*_totalCells); setObstacleBoundaries(_pressure); // copy out the boundaries if(DOMAIN_BC_LEFT == 0) setNeumannX(_xVelocity, _res); else setZeroX(_xVelocity, _res); if(DOMAIN_BC_TOP == 0) setNeumannY(_yVelocity, _res); else setZeroY(_yVelocity, _res); if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res); else setZeroZ(_zVelocity, _res); // calculate divergence index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { float xright = _xVelocity[index + 1]; float xleft = _xVelocity[index - 1]; float yup = _yVelocity[index + _xRes]; float ydown = _yVelocity[index - _xRes]; float ztop = _zVelocity[index + _slabSize]; float zbottom = _zVelocity[index - _slabSize]; if(_obstacles[index+1]) xright = - _xVelocity[index]; if(_obstacles[index-1]) xleft = - _xVelocity[index]; if(_obstacles[index+_xRes]) yup = - _yVelocity[index]; if(_obstacles[index-_xRes]) ydown = - _yVelocity[index]; if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index]; if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index]; _divergence[index] = -_dx * 0.5f * ( xright - xleft + yup - ydown + ztop - zbottom ); // DG: commenting this helps CG to get a better start, 10-20% speed improvement // _pressure[index] = 0.0f; } copyBorderAll(_pressure); // solve Poisson equation solvePressurePre(_pressure, _divergence, _obstacles); setObstaclePressure(_pressure); // project out solution float invDx = 1.0f / _dx; index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { if(!_obstacles[index]) { _xVelocity[index] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx; _yVelocity[index] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx; _zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx; } } if (_pressure) delete[] _pressure; if (_divergence) delete[] _divergence; }