////////////////////////////////////////////////////////////////////// // step simulation once ////////////////////////////////////////////////////////////////////// void FLUID_3D::step() { // addSmokeTestCase(_density, _res); // addSmokeTestCase(_heat, _res); wipeBoundaries(); // run the solvers addVorticity(); addBuoyancy(_heat, _density); addForce(); project(); diffuseHeat(); // advect everything advectMacCormack(); // if(_wTurbulence) { // _wTurbulence->stepTurbulenceFull(_dt/_dx, // _xVelocity, _yVelocity, _zVelocity, _obstacles); // _wTurbulence->stepTurbulenceReadable(_dt/_dx, // _xVelocity, _yVelocity, _zVelocity, _obstacles); // } /* // no file output float *src = _density; string prefix = string("./original.preview/density_fullxy_"); writeImageSliceXY(src,_res, _res[2]/2, prefix, _totalSteps); */ // artificial damping -- this is necessary because we use a // collated grid, and at very coarse grid resolutions, banding // artifacts can occur artificialDamping(_xVelocity); artificialDamping(_yVelocity); artificialDamping(_zVelocity); /* // no file output string pbrtPrefix = string("./pbrt/density_small_"); IMAGE::dumpPBRT(_totalSteps, pbrtPrefix, _density, _res[0],_res[1],_res[2]); */ _totalTime += _dt; _totalSteps++; // todo xxx dg: only clear obstacles, not boundaries // memset(_obstacles, 0, sizeof(unsigned char)*_xRes*_yRes*_zRes); // wipe forces // for external forces we can't do it at the beginning of this function but at the end for (int i = 0; i < _totalCells; i++) { _xForce[i] = _yForce[i] = _zForce[i] = 0.0f; } }
////////////////////////////////////////////////////////////////////// // step simulation once ////////////////////////////////////////////////////////////////////// void FLUID_3D::step(float dt) { // If border rules have been changed if (_colloPrev != *_borderColli) { setBorderCollisions(); } // set delta time by dt_factor _dt = (*_dtFactor) * dt; // set vorticity from RNA value _vorticityEps = (*_vorticityRNA)/_constantScaling; #if PARALLEL==1 int threadval = 1; threadval = omp_get_max_threads(); int stepParts = 1; float partSize = _zRes; stepParts = threadval*2; // Dividing parallelized sections into numOfThreads * 2 sections partSize = (float)_zRes/stepParts; // Size of one part; if (partSize < 4) {stepParts = threadval; // If the slice gets too low (might actually slow things down, change it to larger partSize = (float)_zRes/stepParts;} if (partSize < 4) {stepParts = (int)(ceil((float)_zRes/4.0f)); // If it's still too low (only possible on future systems with +24 cores), change it to 4 partSize = (float)_zRes/stepParts;} #else int zBegin=0; int zEnd=_zRes; #endif #if PARALLEL==1 #pragma omp parallel { #pragma omp for schedule(static,1) for (int i=0; i<stepParts; i++) { int zBegin = (int)((float)i*partSize + 0.5f); int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif wipeBoundariesSL(zBegin, zEnd); addVorticity(zBegin, zEnd); addBuoyancy(_heat, _density, zBegin, zEnd); addForce(zBegin, zEnd); #if PARALLEL==1 } // end of parallel #pragma omp barrier #pragma omp single { #endif /* * addForce() changed Temp values to preserve thread safety * (previous functions in per thread loop still needed * original velocity data) * * So swap temp values to velocity */ SWAP_POINTERS(_xVelocity, _xVelocityTemp); SWAP_POINTERS(_yVelocity, _yVelocityTemp); SWAP_POINTERS(_zVelocity, _zVelocityTemp); #if PARALLEL==1 } // end of single #pragma omp barrier #pragma omp for for (int i=0; i<2; i++) { if (i==0) { #endif project(); #if PARALLEL==1 } else { #endif diffuseHeat(); #if PARALLEL==1 } } #pragma omp barrier #pragma omp single { #endif /* * For thread safety use "Old" to read * "current" values but still allow changing values. */ SWAP_POINTERS(_xVelocity, _xVelocityOld); SWAP_POINTERS(_yVelocity, _yVelocityOld); SWAP_POINTERS(_zVelocity, _zVelocityOld); SWAP_POINTERS(_density, _densityOld); SWAP_POINTERS(_heat, _heatOld); advectMacCormackBegin(0, _zRes); #if PARALLEL==1 } // end of single #pragma omp barrier #pragma omp for schedule(static,1) for (int i=0; i<stepParts; i++) { int zBegin = (int)((float)i*partSize + 0.5f); int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif advectMacCormackEnd1(zBegin, zEnd); #if PARALLEL==1 } // end of parallel #pragma omp barrier #pragma omp for schedule(static,1) for (int i=0; i<stepParts; i++) { int zBegin = (int)((float)i*partSize + 0.5f); int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif advectMacCormackEnd2(zBegin, zEnd); artificialDampingSL(zBegin, zEnd); // Using forces as temp arrays #if PARALLEL==1 } } for (int i=1; i<stepParts; i++) { int zPos=(int)((float)i*partSize + 0.5f); artificialDampingExactSL(zPos); } #endif /* * swap final velocity back to Velocity array * from temp xForce storage */ SWAP_POINTERS(_xVelocity, _xForce); SWAP_POINTERS(_yVelocity, _yForce); SWAP_POINTERS(_zVelocity, _zForce); _totalTime += _dt; _totalSteps++; for (int i = 0; i < _totalCells; i++) { _xForce[i] = _yForce[i] = _zForce[i] = 0.0f; } }