Blender V2.61 - r43446

FLUID_3D.cpp

Go to the documentation of this file.
00001 
00004 
00005 // This file is part of Wavelet Turbulence.
00006 //
00007 // Wavelet Turbulence is free software: you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation, either version 3 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // Wavelet Turbulence is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Wavelet Turbulence.  If not, see <http://www.gnu.org/licenses/>.
00019 //
00020 // Copyright 2008 Theodore Kim and Nils Thuerey
00021 //
00022 // FLUID_3D.cpp: implementation of the FLUID_3D class.
00023 //
00025 // Heavy parallel optimization done. Many of the old functions now
00026 // take begin and end parameters and process only specified part of the data.
00027 // Some functions were divided into multiple ones.
00028 //      - MiikaH
00030 
00031 #include "FLUID_3D.h"
00032 #include "IMAGE.h"
00033 #include <INTERPOLATE.h>
00034 #include "SPHERE.h"
00035 #include <zlib.h>
00036 
00037 #if PARALLEL==1
00038 #include <omp.h>
00039 #endif // PARALLEL 
00040 
00042 // Construction/Destruction
00044 
00045 FLUID_3D::FLUID_3D(int *res, float *p0) :
00046     _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
00047 {
00048     // set simulation consts
00049     _dt = DT_DEFAULT;   // just in case. set in step from a RNA factor
00050     
00051     // start point of array
00052     _p0[0] = p0[0];
00053     _p0[1] = p0[1];
00054     _p0[2] = p0[2];
00055 
00056     _iterations = 100;
00057     _tempAmb = 0; 
00058     _heatDiffusion = 1e-3;
00059     _totalTime = 0.0f;
00060     _totalSteps = 0;
00061     _res = Vec3Int(_xRes,_yRes,_zRes);
00062     _maxRes = MAX3(_xRes, _yRes, _zRes);
00063     
00064     // initialize wavelet turbulence
00065     /*
00066     if(amplify)
00067         _wTurbulence = new WTURBULENCE(_res[0],_res[1],_res[2], amplify, noisetype);
00068     else
00069         _wTurbulence = NULL;
00070     */
00071     
00072     // scale the constants according to the refinement of the grid
00073     _dx = 1.0f / (float)_maxRes;
00074     _constantScaling = 64.0f / _maxRes;
00075     _constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling;
00076     _vorticityEps = 2.0f / _constantScaling; // Just in case set a default value
00077 
00078     // allocate arrays
00079     _totalCells   = _xRes * _yRes * _zRes;
00080     _slabSize = _xRes * _yRes;
00081     _xVelocity    = new float[_totalCells];
00082     _yVelocity    = new float[_totalCells];
00083     _zVelocity    = new float[_totalCells];
00084     _xVelocityOld = new float[_totalCells];
00085     _yVelocityOld = new float[_totalCells];
00086     _zVelocityOld = new float[_totalCells];
00087     _xForce       = new float[_totalCells];
00088     _yForce       = new float[_totalCells];
00089     _zForce       = new float[_totalCells];
00090     _density      = new float[_totalCells];
00091     _densityOld   = new float[_totalCells];
00092     _heat         = new float[_totalCells];
00093     _heatOld      = new float[_totalCells];
00094     _obstacles    = new unsigned char[_totalCells]; // set 0 at end of step
00095 
00096     // For threaded version:
00097     _xVelocityTemp = new float[_totalCells];
00098     _yVelocityTemp = new float[_totalCells];
00099     _zVelocityTemp = new float[_totalCells];
00100     _densityTemp   = new float[_totalCells];
00101     _heatTemp      = new float[_totalCells];
00102 
00103     // DG TODO: check if alloc went fine
00104 
00105     for (int x = 0; x < _totalCells; x++)
00106     {
00107         _density[x]      = 0.0f;
00108         _densityOld[x]   = 0.0f;
00109         _heat[x]         = 0.0f;
00110         _heatOld[x]      = 0.0f;
00111         _xVelocity[x]    = 0.0f;
00112         _yVelocity[x]    = 0.0f;
00113         _zVelocity[x]    = 0.0f;
00114         _xVelocityOld[x] = 0.0f;
00115         _yVelocityOld[x] = 0.0f;
00116         _zVelocityOld[x] = 0.0f;
00117         _xForce[x]       = 0.0f;
00118         _yForce[x]       = 0.0f;
00119         _zForce[x]       = 0.0f;
00120         _obstacles[x]    = false;
00121     }
00122 
00123     // boundary conditions of the fluid domain
00124     // set default values -> vertically non-colliding
00125     _domainBcFront = true;
00126     _domainBcTop = false;
00127     _domainBcLeft = true;
00128     _domainBcBack = _domainBcFront;
00129     _domainBcBottom = _domainBcTop;
00130     _domainBcRight  = _domainBcLeft;
00131 
00132     _colloPrev = 1; // default value
00133 
00134 
00135     // set side obstacles
00136     int index;
00137     for (int y = 0; y < _yRes; y++)
00138     for (int x = 0; x < _xRes; x++)
00139     {
00140         // bottom slab
00141         index = x + y * _xRes;
00142         if(_domainBcBottom==1) _obstacles[index] = 1;
00143 
00144         // top slab
00145         index += _totalCells - _slabSize;
00146         if(_domainBcTop==1) _obstacles[index] = 1;
00147     }
00148 
00149     for (int z = 0; z < _zRes; z++)
00150     for (int x = 0; x < _xRes; x++)
00151     {
00152         // front slab
00153         index = x + z * _slabSize;
00154         if(_domainBcFront==1) _obstacles[index] = 1;
00155 
00156         // back slab
00157         index += _slabSize - _xRes;
00158         if(_domainBcBack==1) _obstacles[index] = 1;
00159     }
00160 
00161     for (int z = 0; z < _zRes; z++)
00162     for (int y = 0; y < _yRes; y++)
00163     {
00164         // left slab
00165         index = y * _xRes + z * _slabSize;
00166         if(_domainBcLeft==1) _obstacles[index] = 1;
00167 
00168         // right slab
00169         index += _xRes - 1;
00170         if(_domainBcRight==1) _obstacles[index] = 1;
00171     }
00172 
00173 }
00174 
00175 FLUID_3D::~FLUID_3D()
00176 {
00177     if (_xVelocity) delete[] _xVelocity;
00178     if (_yVelocity) delete[] _yVelocity;
00179     if (_zVelocity) delete[] _zVelocity;
00180     if (_xVelocityOld) delete[] _xVelocityOld;
00181     if (_yVelocityOld) delete[] _yVelocityOld;
00182     if (_zVelocityOld) delete[] _zVelocityOld;
00183     if (_xForce) delete[] _xForce;
00184     if (_yForce) delete[] _yForce;
00185     if (_zForce) delete[] _zForce;
00186     if (_density) delete[] _density;
00187     if (_densityOld) delete[] _densityOld;
00188     if (_heat) delete[] _heat;
00189     if (_heatOld) delete[] _heatOld;
00190     if (_obstacles) delete[] _obstacles;
00191     // if (_wTurbulence) delete _wTurbulence;
00192 
00193     if (_xVelocityTemp) delete[] _xVelocityTemp;
00194     if (_yVelocityTemp) delete[] _yVelocityTemp;
00195     if (_zVelocityTemp) delete[] _zVelocityTemp;
00196     if (_densityTemp) delete[] _densityTemp;
00197     if (_heatTemp) delete[] _heatTemp;
00198 
00199     // printf("deleted fluid\n");
00200 }
00201 
00202 // init direct access functions from blender
00203 void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision)
00204 {
00205     _alpha = alpha;
00206     _beta = beta;
00207     _dtFactor = dt_factor;
00208     _vorticityRNA = vorticity;
00209     _borderColli = borderCollision;
00210 }
00211 
00213 // step simulation once
00215 void FLUID_3D::step(float dt)
00216 {
00217     // If border rules have been changed
00218     if (_colloPrev != *_borderColli) {
00219         setBorderCollisions();
00220     }
00221 
00222 
00223     // set delta time by dt_factor
00224     _dt = (*_dtFactor) * dt;
00225     // set vorticity from RNA value
00226     _vorticityEps = (*_vorticityRNA)/_constantScaling;
00227 
00228 
00229 #if PARALLEL==1
00230     int threadval = 1;
00231     threadval = omp_get_max_threads();
00232 
00233     int stepParts = 1;
00234     float partSize = _zRes;
00235 
00236     stepParts = threadval*2;    // Dividing parallelized sections into numOfThreads * 2 sections
00237     partSize = (float)_zRes/stepParts;  // Size of one part;
00238 
00239   if (partSize < 4) {stepParts = threadval;                 // If the slice gets too low (might actually slow things down, change it to larger
00240                     partSize = (float)_zRes/stepParts;}
00241   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
00242                     partSize = (float)_zRes/stepParts;}
00243 #else
00244     int zBegin=0;
00245     int zEnd=_zRes;
00246 #endif
00247 
00248 
00249 #if PARALLEL==1
00250     #pragma omp parallel
00251     {
00252     #pragma omp for schedule(static,1)
00253     for (int i=0; i<stepParts; i++)
00254     {
00255         int zBegin = (int)((float)i*partSize + 0.5f);
00256         int zEnd = (int)((float)(i+1)*partSize + 0.5f);
00257 #endif
00258 
00259         wipeBoundariesSL(zBegin, zEnd);
00260         addVorticity(zBegin, zEnd);
00261         addBuoyancy(_heat, _density, zBegin, zEnd);
00262         addForce(zBegin, zEnd);
00263 
00264 #if PARALLEL==1
00265     }   // end of parallel
00266     #pragma omp barrier
00267 
00268     #pragma omp single
00269     {
00270 #endif
00271     /*
00272     * addForce() changed Temp values to preserve thread safety
00273     * (previous functions in per thread loop still needed
00274     *  original velocity data)
00275     *
00276     * So swap temp values to velocity
00277     */
00278     SWAP_POINTERS(_xVelocity, _xVelocityTemp);
00279     SWAP_POINTERS(_yVelocity, _yVelocityTemp);
00280     SWAP_POINTERS(_zVelocity, _zVelocityTemp);
00281 #if PARALLEL==1
00282     }   // end of single
00283 
00284     #pragma omp barrier
00285 
00286     #pragma omp for
00287     for (int i=0; i<2; i++)
00288     {
00289         if (i==0)
00290         {
00291 #endif
00292         project();
00293 #if PARALLEL==1
00294         }
00295         else
00296         {
00297 #endif
00298         diffuseHeat();
00299 #if PARALLEL==1
00300         }
00301     }
00302 
00303     #pragma omp barrier
00304 
00305     #pragma omp single
00306     {
00307 #endif
00308     /*
00309     * For thread safety use "Old" to read
00310     * "current" values but still allow changing values.
00311     */
00312     SWAP_POINTERS(_xVelocity, _xVelocityOld);
00313     SWAP_POINTERS(_yVelocity, _yVelocityOld);
00314     SWAP_POINTERS(_zVelocity, _zVelocityOld);
00315     SWAP_POINTERS(_density, _densityOld);
00316     SWAP_POINTERS(_heat, _heatOld);
00317 
00318     advectMacCormackBegin(0, _zRes);
00319 
00320 #if PARALLEL==1
00321     }   // end of single
00322 
00323     #pragma omp barrier
00324 
00325 
00326     #pragma omp for schedule(static,1)
00327     for (int i=0; i<stepParts; i++)
00328     {
00329 
00330         int zBegin = (int)((float)i*partSize + 0.5f);
00331         int zEnd = (int)((float)(i+1)*partSize + 0.5f);
00332 #endif
00333 
00334     advectMacCormackEnd1(zBegin, zEnd);
00335 
00336 #if PARALLEL==1
00337     }   // end of parallel
00338 
00339     #pragma omp barrier
00340 
00341     #pragma omp for schedule(static,1)
00342     for (int i=0; i<stepParts; i++)
00343     {
00344 
00345         int zBegin = (int)((float)i*partSize + 0.5f);
00346         int zEnd = (int)((float)(i+1)*partSize + 0.5f);
00347 #endif
00348 
00349         advectMacCormackEnd2(zBegin, zEnd);
00350 
00351         artificialDampingSL(zBegin, zEnd);
00352 
00353         // Using forces as temp arrays
00354 
00355 #if PARALLEL==1
00356     }
00357     }
00358 
00359 
00360 
00361     for (int i=1; i<stepParts; i++)
00362     {
00363         int zPos=(int)((float)i*partSize + 0.5f);
00364         
00365         artificialDampingExactSL(zPos);
00366 
00367     }
00368 #endif
00369 
00370     /*
00371     * swap final velocity back to Velocity array
00372     * from temp xForce storage
00373     */
00374     SWAP_POINTERS(_xVelocity, _xForce);
00375     SWAP_POINTERS(_yVelocity, _yForce);
00376     SWAP_POINTERS(_zVelocity, _zForce);
00377 
00378 
00379 
00380 
00381     _totalTime += _dt;
00382     _totalSteps++;      
00383 
00384     for (int i = 0; i < _totalCells; i++)
00385     {
00386         _xForce[i] = _yForce[i] = _zForce[i] = 0.0f;
00387     }
00388 
00389 }
00390 
00391 
00392 // Set border collision model from RNA setting
00393 
00394 void FLUID_3D::setBorderCollisions() {
00395 
00396 
00397     _colloPrev = *_borderColli;     // saving the current value
00398 
00399     // boundary conditions of the fluid domain
00400     if (_colloPrev == 0)
00401     {
00402         // No collisions
00403         _domainBcFront = false;
00404         _domainBcTop = false;
00405         _domainBcLeft = false;
00406     }
00407     else if (_colloPrev == 2)
00408     {
00409         // Collide with all sides
00410         _domainBcFront = true;
00411         _domainBcTop = true;
00412         _domainBcLeft = true;
00413     }
00414     else
00415     {
00416         // Default values: Collide with "walls", but not top and bottom
00417         _domainBcFront = true;
00418         _domainBcTop = false;
00419         _domainBcLeft = true;
00420     }
00421 
00422     _domainBcBack = _domainBcFront;
00423     _domainBcBottom = _domainBcTop;
00424     _domainBcRight  = _domainBcLeft;
00425 
00426 
00427 
00428     // set side obstacles
00429     int index;
00430     for (int y = 0; y < _yRes; y++)
00431     for (int x = 0; x < _xRes; x++)
00432     {
00433         // front slab
00434         index = x + y * _xRes;
00435         if(_domainBcBottom==1) _obstacles[index] = 1;
00436         else _obstacles[index] = 0;
00437 
00438         // back slab
00439         index += _totalCells - _slabSize;
00440         if(_domainBcTop==1) _obstacles[index] = 1;
00441         else _obstacles[index] = 0;
00442     }
00443 
00444     for (int z = 0; z < _zRes; z++)
00445     for (int x = 0; x < _xRes; x++)
00446     {
00447         // bottom slab
00448         index = x + z * _slabSize;
00449         if(_domainBcFront==1) _obstacles[index] = 1;
00450         else _obstacles[index] = 0;
00451 
00452         // top slab
00453         index += _slabSize - _xRes;
00454         if(_domainBcBack==1) _obstacles[index] = 1;
00455         else _obstacles[index] = 0;
00456     }
00457 
00458     for (int z = 0; z < _zRes; z++)
00459     for (int y = 0; y < _yRes; y++)
00460     {
00461         // left slab
00462         index = y * _xRes + z * _slabSize;
00463         if(_domainBcLeft==1) _obstacles[index] = 1;
00464         else _obstacles[index] = 0;
00465 
00466         // right slab
00467         index += _xRes - 1;
00468         if(_domainBcRight==1) _obstacles[index] = 1;
00469         else _obstacles[index] = 0;
00470     }
00471 }
00472 
00474 // helper function to dampen co-located grid artifacts of given arrays in intervals
00475 // (only needed for velocity, strength (w) depends on testcase...
00477 
00478 
00479 void FLUID_3D::artificialDampingSL(int zBegin, int zEnd) {
00480     const float w = 0.9;
00481 
00482     memmove(_xForce+(_slabSize*zBegin), _xVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
00483     memmove(_yForce+(_slabSize*zBegin), _yVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
00484     memmove(_zForce+(_slabSize*zBegin), _zVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
00485 
00486 
00487     if(_totalSteps % 4 == 1) {
00488         for (int z = zBegin+1; z < zEnd-1; z++)
00489             for (int y = 1; y < _res[1]-1; y++)
00490                 for (int x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
00491                     const int index = x + y*_res[0] + z * _slabSize;
00492                     _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
00493                             _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
00494                             _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
00495                             _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
00496 
00497                     _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
00498                             _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
00499                             _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
00500                             _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
00501 
00502                     _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
00503                             _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
00504                             _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
00505                             _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
00506                 }
00507     }
00508 
00509     if(_totalSteps % 4 == 3) {
00510         for (int z = zBegin+1; z < zEnd-1; z++)
00511             for (int y = 1; y < _res[1]-1; y++)
00512                 for (int x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
00513                     const int index = x + y*_res[0] + z * _slabSize;
00514                     _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
00515                             _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
00516                             _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
00517                             _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
00518 
00519                     _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
00520                             _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
00521                             _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
00522                             _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
00523 
00524                     _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
00525                             _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
00526                             _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
00527                             _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
00528                 }
00529 
00530     }
00531 }
00532 
00533 
00534 
00535 void FLUID_3D::artificialDampingExactSL(int pos) {
00536     const float w = 0.9;
00537     int index, x,y,z;
00538     
00539 
00540     size_t posslab;
00541 
00542     for (z=pos-1; z<=pos; z++)
00543     {
00544     posslab=z * _slabSize;
00545 
00546     if(_totalSteps % 4 == 1) {
00547             for (y = 1; y < _res[1]-1; y++)
00548                 for (x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
00549                     index = x + y*_res[0] + posslab;
00550                     /*
00551                     * Uses xForce as temporary storage to allow other threads to read
00552                     * old values from xVelocityTemp
00553                     */
00554                     _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
00555                             _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
00556                             _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
00557                             _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
00558 
00559                     _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
00560                             _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
00561                             _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
00562                             _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
00563 
00564                     _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
00565                             _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
00566                             _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
00567                             _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
00568                     
00569                 }
00570     }
00571 
00572     if(_totalSteps % 4 == 3) {
00573             for (y = 1; y < _res[1]-1; y++)
00574                 for (x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
00575                     index = x + y*_res[0] + posslab;
00576 
00577                     /*
00578                     * Uses xForce as temporary storage to allow other threads to read
00579                     * old values from xVelocityTemp
00580                     */
00581                     _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
00582                             _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
00583                             _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
00584                             _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
00585 
00586                     _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
00587                             _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
00588                             _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
00589                             _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
00590 
00591                     _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
00592                             _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
00593                             _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
00594                             _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
00595                     
00596                 }
00597 
00598     }
00599     }
00600 }
00601 
00603 // copy out the boundary in all directions
00605 void FLUID_3D::copyBorderAll(float* field, int zBegin, int zEnd)
00606 {
00607     int index, x, y, z;
00608     int zSize = zEnd-zBegin;
00609     int _blockTotalCells=_slabSize * zSize;
00610 
00611     if (zBegin==0)
00612     for (int y = 0; y < _yRes; y++)
00613         for (int x = 0; x < _xRes; x++)
00614         {
00615             // front slab
00616             index = x + y * _xRes;
00617             field[index] = field[index + _slabSize];
00618     }
00619 
00620     if (zEnd==_zRes)
00621     for (y = 0; y < _yRes; y++)
00622         for (x = 0; x < _xRes; x++)
00623         {
00624 
00625             // back slab
00626             index = x + y * _xRes + _blockTotalCells - _slabSize;
00627             field[index] = field[index - _slabSize];
00628     }
00629 
00630     for (z = 0; z < zSize; z++)
00631         for (x = 0; x < _xRes; x++)
00632     {
00633             // bottom slab
00634             index = x + z * _slabSize;
00635             field[index] = field[index + _xRes];
00636 
00637             // top slab
00638             index += _slabSize - _xRes;
00639             field[index] = field[index - _xRes];
00640     }
00641 
00642     for (z = 0; z < zSize; z++)
00643         for (y = 0; y < _yRes; y++)
00644     {
00645             // left slab
00646             index = y * _xRes + z * _slabSize;
00647             field[index] = field[index + 1];
00648 
00649             // right slab
00650             index += _xRes - 1;
00651             field[index] = field[index - 1];
00652         }
00653 }
00654 
00656 // wipe boundaries of velocity and density
00658 void FLUID_3D::wipeBoundaries(int zBegin, int zEnd)
00659 {
00660     setZeroBorder(_xVelocity, _res, zBegin, zEnd);
00661     setZeroBorder(_yVelocity, _res, zBegin, zEnd);
00662     setZeroBorder(_zVelocity, _res, zBegin, zEnd);
00663     setZeroBorder(_density, _res, zBegin, zEnd);
00664 }
00665 
00666 void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
00667 {
00668     
00670     // setZeroBorder to all:
00672 
00674     // setZeroX
00676 
00677     const int slabSize = _xRes * _yRes;
00678     int index, x,y,z;
00679 
00680     for (z = zBegin; z < zEnd; z++)
00681         for (y = 0; y < _yRes; y++)
00682         {
00683             // left slab
00684             index = y * _xRes + z * slabSize;
00685             _xVelocity[index] = 0.0f;
00686             _yVelocity[index] = 0.0f;
00687             _zVelocity[index] = 0.0f;
00688             _density[index] = 0.0f;
00689 
00690             // right slab
00691             index += _xRes - 1;
00692             _xVelocity[index] = 0.0f;
00693             _yVelocity[index] = 0.0f;
00694             _zVelocity[index] = 0.0f;
00695             _density[index] = 0.0f;
00696         }
00697 
00699     // setZeroY
00701 
00702     for (z = zBegin; z < zEnd; z++)
00703         for (x = 0; x < _xRes; x++)
00704         {
00705             // bottom slab
00706             index = x + z * slabSize;
00707             _xVelocity[index] = 0.0f;
00708             _yVelocity[index] = 0.0f;
00709             _zVelocity[index] = 0.0f;
00710             _density[index] = 0.0f;
00711 
00712             // top slab
00713             index += slabSize - _xRes;
00714             _xVelocity[index] = 0.0f;
00715             _yVelocity[index] = 0.0f;
00716             _zVelocity[index] = 0.0f;
00717             _density[index] = 0.0f;
00718 
00719         }
00720 
00722     // setZeroZ
00724 
00725 
00726     const int totalCells = _xRes * _yRes * _zRes;
00727 
00728     index = 0;
00729     if (zBegin == 0)
00730     for (y = 0; y < _yRes; y++)
00731         for (x = 0; x < _xRes; x++, index++)
00732         {
00733             // front slab
00734             _xVelocity[index] = 0.0f;
00735             _yVelocity[index] = 0.0f;
00736             _zVelocity[index] = 0.0f;
00737             _density[index] = 0.0f;
00738     }
00739 
00740     if (zEnd == _zRes)
00741     {
00742         index=0;
00743         int indexx=0;
00744         const int cellsslab = totalCells - slabSize;
00745 
00746         for (y = 0; y < _yRes; y++)
00747             for (x = 0; x < _xRes; x++, index++)
00748             {
00749 
00750                 // back slab
00751                 indexx = index + cellsslab;
00752                 _xVelocity[indexx] = 0.0f;
00753                 _yVelocity[indexx] = 0.0f;
00754                 _zVelocity[indexx] = 0.0f;
00755                 _density[indexx] = 0.0f;
00756             }
00757     }
00758 
00759 }
00761 // add forces to velocity field
00763 void FLUID_3D::addForce(int zBegin, int zEnd)
00764 {
00765     int begin=zBegin * _slabSize;
00766     int end=begin + (zEnd - zBegin) * _slabSize;
00767 
00768     for (int i = begin; i < end; i++)
00769     {
00770         _xVelocityTemp[i] = _xVelocity[i] + _dt * _xForce[i];
00771         _yVelocityTemp[i] = _yVelocity[i] + _dt * _yForce[i];
00772         _zVelocityTemp[i] = _zVelocity[i] + _dt * _zForce[i];
00773     }
00774 }
00776 // project into divergence free field
00778 void FLUID_3D::project()
00779 {
00780     int x, y, z;
00781     size_t index;
00782 
00783     float *_pressure = new float[_totalCells];
00784     float *_divergence   = new float[_totalCells];
00785 
00786     memset(_pressure, 0, sizeof(float)*_totalCells);
00787     memset(_divergence, 0, sizeof(float)*_totalCells);
00788     
00789     setObstacleBoundaries(_pressure, 0, _zRes);
00790     
00791     // copy out the boundaries
00792     if(_domainBcLeft == 0)  setNeumannX(_xVelocity, _res, 0, _zRes);
00793     else setZeroX(_xVelocity, _res, 0, _zRes); 
00794 
00795     if(_domainBcFront == 0)   setNeumannY(_yVelocity, _res, 0, _zRes);
00796     else setZeroY(_yVelocity, _res, 0, _zRes); 
00797 
00798     if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
00799     else setZeroZ(_zVelocity, _res, 0, _zRes);
00800 
00801     // calculate divergence
00802     index = _slabSize + _xRes + 1;
00803     for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
00804         for (y = 1; y < _yRes - 1; y++, index += 2)
00805             for (x = 1; x < _xRes - 1; x++, index++)
00806             {
00807                 float xright = _xVelocity[index + 1];
00808                 float xleft  = _xVelocity[index - 1];
00809                 float yup    = _yVelocity[index + _xRes];
00810                 float ydown  = _yVelocity[index - _xRes];
00811                 float ztop   = _zVelocity[index + _slabSize];
00812                 float zbottom = _zVelocity[index - _slabSize];
00813 
00814                 if(_obstacles[index+1]) xright = - _xVelocity[index];
00815                 if(_obstacles[index-1]) xleft  = - _xVelocity[index];
00816                 if(_obstacles[index+_xRes]) yup    = - _yVelocity[index];
00817                 if(_obstacles[index-_xRes]) ydown  = - _yVelocity[index];
00818                 if(_obstacles[index+_slabSize]) ztop    = - _zVelocity[index];
00819                 if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
00820 
00821                 _divergence[index] = -_dx * 0.5f * (
00822                         xright - xleft +
00823                         yup - ydown +
00824                         ztop - zbottom );
00825 
00826                 // DG: commenting this helps CG to get a better start, 10-20% speed improvement
00827                 // _pressure[index] = 0.0f;
00828             }
00829     copyBorderAll(_pressure, 0, _zRes);
00830 
00831     // solve Poisson equation
00832     solvePressurePre(_pressure, _divergence, _obstacles);
00833 
00834     setObstaclePressure(_pressure, 0, _zRes);
00835 
00836     // project out solution
00837     float invDx = 1.0f / _dx;
00838     index = _slabSize + _xRes + 1;
00839     for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
00840         for (y = 1; y < _yRes - 1; y++, index += 2)
00841             for (x = 1; x < _xRes - 1; x++, index++)
00842             {
00843                 if(!_obstacles[index])
00844                 {
00845                     _xVelocity[index] -= 0.5f * (_pressure[index + 1]     - _pressure[index - 1]) * invDx;
00846                     _yVelocity[index] -= 0.5f * (_pressure[index + _xRes]  - _pressure[index - _xRes]) * invDx;
00847                     _zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx;
00848                 }
00849             }
00850 
00851     if (_pressure) delete[] _pressure;
00852     if (_divergence) delete[] _divergence;
00853 }
00854 
00855 
00856 
00857 
00859 // diffuse heat
00861 void FLUID_3D::diffuseHeat()
00862 {
00863     SWAP_POINTERS(_heat, _heatOld);
00864 
00865     copyBorderAll(_heatOld, 0, _zRes);
00866     solveHeat(_heat, _heatOld, _obstacles);
00867 
00868     // zero out inside obstacles
00869     for (int x = 0; x < _totalCells; x++)
00870         if (_obstacles[x])
00871             _heat[x] = 0.0f;
00872 
00873 }
00874 
00876 // stamp an obstacle in the _obstacles field
00878 void FLUID_3D::addObstacle(OBSTACLE* obstacle)
00879 {
00880     int index = 0;
00881     for (int z = 0; z < _zRes; z++)
00882         for (int y = 0; y < _yRes; y++)
00883             for (int x = 0; x < _xRes; x++, index++)
00884                 if (obstacle->inside(x * _dx, y * _dx, z * _dx)) {
00885                     _obstacles[index] = true;
00886         }
00887 }
00888 
00890 // calculate the obstacle directional types
00892 void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
00893 {
00894 
00895     // compleately TODO
00896 
00897     const size_t index_ = _slabSize + _xRes + 1;
00898 
00899     //int vIndex=_slabSize + _xRes + 1;
00900 
00901     int bb=0;
00902     int bt=0;
00903 
00904     if (zBegin == 0) {bb = 1;}
00905     if (zEnd == _zRes) {bt = 1;}
00906 
00907     // tag remaining obstacle blocks
00908     for (int z = zBegin + bb; z < zEnd - bt; z++)
00909     {
00910         size_t index = index_ +(z-1)*_slabSize;
00911 
00912         for (int y = 1; y < _yRes - 1; y++, index += 2)
00913         {
00914             for (int x = 1; x < _xRes - 1; x++, index++)
00915         {
00916             // could do cascade of ifs, but they are a pain
00917             if (_obstacles[index])
00918             {
00919                 const int top   = _obstacles[index + _slabSize];
00920                 const int bottom= _obstacles[index - _slabSize];
00921                 const int up    = _obstacles[index + _xRes];
00922                 const int down  = _obstacles[index - _xRes];
00923                 const int left  = _obstacles[index - 1];
00924                 const int right = _obstacles[index + 1];
00925 
00926                 // unused
00927                 // const bool fullz = (top && bottom);
00928                 // const bool fully = (up && down);
00929                 //const bool fullx = (left && right);
00930 
00931                 _xVelocity[index] =
00932                 _yVelocity[index] =
00933                 _zVelocity[index] = 0.0f;
00934                 _pressure[index] = 0.0f;
00935 
00936                 // average pressure neighbors
00937                 float pcnt = 0.;
00938                 if (left && !right) {
00939                     _pressure[index] += _pressure[index + 1];
00940                     pcnt += 1.;
00941                 }
00942                 if (!left && right) {
00943                     _pressure[index] += _pressure[index - 1];
00944                     pcnt += 1.;
00945                 }
00946                 if (up && !down) {
00947                     _pressure[index] += _pressure[index - _xRes];
00948                     pcnt += 1.;
00949                 }
00950                 if (!up && down) {
00951                     _pressure[index] += _pressure[index + _xRes];
00952                     pcnt += 1.;
00953                 }
00954                 if (top && !bottom) {
00955                     _pressure[index] += _pressure[index - _slabSize];
00956                     pcnt += 1.;
00957                 }
00958                 if (!top && bottom) {
00959                     _pressure[index] += _pressure[index + _slabSize];
00960                     pcnt += 1.;
00961                 }
00962                 
00963                 if(pcnt > 0.000001f)
00964                     _pressure[index] /= pcnt;
00965 
00966                 // TODO? set correct velocity bc's
00967                 // velocities are only set to zero right now
00968                 // this means it's not a full no-slip boundary condition
00969                 // but a "half-slip" - still looks ok right now
00970             }
00971             //vIndex++;
00972         }   // x loop
00973         //vIndex += 2;
00974         }   // y loop
00975         //vIndex += 2 * _xRes;
00976     }   // z loop
00977 }
00978 
00979 void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd)
00980 {
00981     // cull degenerate obstacles , move to addObstacle?
00982 
00983     // r = b - Ax
00984     const size_t index_ = _slabSize + _xRes + 1;
00985 
00986     int bb=0;
00987     int bt=0;
00988 
00989     if (zBegin == 0) {bb = 1;}
00990     if (zEnd == _zRes) {bt = 1;}
00991 
00992     for (int z = zBegin + bb; z < zEnd - bt; z++)
00993     {
00994         size_t index = index_ +(z-1)*_slabSize;
00995         
00996         for (int y = 1; y < _yRes - 1; y++, index += 2)
00997         {
00998             for (int x = 1; x < _xRes - 1; x++, index++)
00999             {
01000                 if (_obstacles[index] != EMPTY)
01001                 {
01002                     const int top   = _obstacles[index + _slabSize];
01003                     const int bottom= _obstacles[index - _slabSize];
01004                     const int up    = _obstacles[index + _xRes];
01005                     const int down  = _obstacles[index - _xRes];
01006                     const int left  = _obstacles[index - 1];
01007                     const int right = _obstacles[index + 1];
01008 
01009                     int counter = 0;
01010                     if (up)    counter++;
01011                     if (down)  counter++;
01012                     if (left)  counter++;
01013                     if (right) counter++;
01014                     if (top)  counter++;
01015                     if (bottom) counter++;
01016 
01017                     if (counter < 3)
01018                         _obstacles[index] = EMPTY;
01019                 }
01020                 if (_obstacles[index])
01021                 {
01022                     _xVelocity[index] =
01023                     _yVelocity[index] =
01024                     _zVelocity[index] = 0.0f;
01025                     _pressure[index] = 0.0f;
01026                 }
01027                 //vIndex++;
01028             }   // x-loop
01029             //vIndex += 2;
01030         }   // y-loop
01031         //vIndex += 2* _xRes;
01032     }   // z-loop
01033 }
01034 
01036 // add buoyancy forces
01038 void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
01039 {
01040     int index = zBegin*_slabSize;
01041 
01042     for (int z = zBegin; z < zEnd; z++)
01043         for (int y = 0; y < _yRes; y++)
01044             for (int x = 0; x < _xRes; x++, index++)
01045             {
01046                 _zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender
01047             }
01048 }
01049 
01051 // add vorticity to the force field
01053 void FLUID_3D::addVorticity(int zBegin, int zEnd)
01054 {
01055     //int x,y,z,index;
01056     if(_vorticityEps<=0.) return;
01057 
01058     int _blockSize=zEnd-zBegin;
01059     int _blockTotalCells = _slabSize * (_blockSize+2);
01060 
01061     float *_xVorticity, *_yVorticity, *_zVorticity, *_vorticity;
01062 
01063     int bb=0;
01064     int bt=0;
01065     int bb1=-1;
01066     int bt1=-1;
01067 
01068     if (zBegin == 0) {bb1 = 1; bb = 1; _blockTotalCells-=_blockSize;}
01069     if (zEnd == _zRes) {bt1 = 1;bt = 1; _blockTotalCells-=_blockSize;}
01070 
01071     _xVorticity = new float[_blockTotalCells];
01072     _yVorticity = new float[_blockTotalCells];
01073     _zVorticity = new float[_blockTotalCells];
01074     _vorticity = new float[_blockTotalCells];
01075 
01076     memset(_xVorticity, 0, sizeof(float)*_blockTotalCells);
01077     memset(_yVorticity, 0, sizeof(float)*_blockTotalCells);
01078     memset(_zVorticity, 0, sizeof(float)*_blockTotalCells);
01079     memset(_vorticity, 0, sizeof(float)*_blockTotalCells);
01080 
01081     //const size_t indexsetupV=_slabSize;
01082     const size_t index_ = _slabSize + _xRes + 1;
01083 
01084     // calculate vorticity
01085     float gridSize = 0.5f / _dx;
01086     //index = _slabSize + _xRes + 1;
01087 
01088 
01089     size_t vIndex=_xRes + 1;
01090 
01091     for (int z = zBegin + bb1; z < (zEnd - bt1); z++)
01092     {
01093         size_t index = index_ +(z-1)*_slabSize;
01094         vIndex = index-(zBegin-1+bb)*_slabSize;
01095 
01096         for (int y = 1; y < _yRes - 1; y++, index += 2)
01097         {
01098             for (int x = 1; x < _xRes - 1; x++, index++)
01099             {
01100 
01101                 int up    = _obstacles[index + _xRes] ? index : index + _xRes;
01102                 int down  = _obstacles[index - _xRes] ? index : index - _xRes;
01103                 float dy  = (up == index || down == index) ? 1.0f / _dx : gridSize;
01104                 int out   = _obstacles[index + _slabSize] ? index : index + _slabSize;
01105                 int in    = _obstacles[index - _slabSize] ? index : index - _slabSize;
01106                 float dz  = (out == index || in == index) ? 1.0f / _dx : gridSize;
01107                 int right = _obstacles[index + 1] ? index : index + 1;
01108                 int left  = _obstacles[index - 1] ? index : index - 1;
01109                 float dx  = (right == index || right == index) ? 1.0f / _dx : gridSize;
01110 
01111                 _xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz;
01112                 _yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx;
01113                 _zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy;
01114 
01115                 _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] +
01116                         _yVorticity[vIndex] * _yVorticity[vIndex] +
01117                         _zVorticity[vIndex] * _zVorticity[vIndex]);
01118 
01119                 vIndex++;
01120             }
01121             vIndex+=2;
01122         }
01123         //vIndex+=2*_xRes;
01124     }
01125 
01126     // calculate normalized vorticity vectors
01127     float eps = _vorticityEps;
01128     
01129     //index = _slabSize + _xRes + 1;
01130     vIndex=_slabSize + _xRes + 1;
01131 
01132     for (int z = zBegin + bb; z < (zEnd - bt); z++)
01133     {
01134         size_t index = index_ +(z-1)*_slabSize;
01135         vIndex = index-(zBegin-1+bb)*_slabSize;
01136 
01137         for (int y = 1; y < _yRes - 1; y++, index += 2)
01138         {
01139             for (int x = 1; x < _xRes - 1; x++, index++)
01140             {
01141                 //
01142 
01143                 if (!_obstacles[index])
01144                 {
01145                     float N[3];
01146 
01147                     int up    = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes;
01148                     int down  = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes;
01149                     float dy  = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize;
01150                     int out   = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize;
01151                     int in    = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize;
01152                     float dz  = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize;
01153                     int right = _obstacles[index + 1] ? vIndex : vIndex + 1;
01154                     int left  = _obstacles[index - 1] ? vIndex : vIndex - 1;
01155                     float dx  = (right == vIndex || right == vIndex) ? 1.0f / _dx : gridSize;
01156                     N[0] = (_vorticity[right] - _vorticity[left]) * dx;
01157                     N[1] = (_vorticity[up] - _vorticity[down]) * dy;
01158                     N[2] = (_vorticity[out] - _vorticity[in]) * dz;
01159 
01160                     float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
01161                     if (magnitude > 0.0f)
01162                     {
01163                         magnitude = 1.0f / magnitude;
01164                         N[0] *= magnitude;
01165                         N[1] *= magnitude;
01166                         N[2] *= magnitude;
01167 
01168                         _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps;
01169                         _yForce[index] -= (N[0] * _zVorticity[vIndex] - N[2] * _xVorticity[vIndex]) * _dx * eps;
01170                         _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps;
01171                     }
01172                     }   // if
01173                     vIndex++;
01174                     }   // x loop
01175                 vIndex+=2;
01176                 }       // y loop
01177             //vIndex+=2*_xRes;
01178         }               // z loop
01179                 
01180     if (_xVorticity) delete[] _xVorticity;
01181     if (_yVorticity) delete[] _yVorticity;
01182     if (_zVorticity) delete[] _zVorticity;
01183     if (_vorticity) delete[] _vorticity;
01184 }
01185 
01186 
01187 void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd)
01188 {
01189     Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
01190 
01191     if(_domainBcLeft == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
01192     else setZeroX(_xVelocityOld, res, zBegin, zEnd);
01193 
01194     if(_domainBcFront == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
01195     else setZeroY(_yVelocityOld, res, zBegin, zEnd); 
01196 
01197     if(_domainBcTop == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
01198     else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
01199 }
01200 
01202 // Advect using the MacCormack method from the Selle paper
01204 void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd)
01205 {
01206     Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
01207 
01208     const float dt0 = _dt / _dx;
01209 
01210     int begin=zBegin * _slabSize;
01211     int end=begin + (zEnd - zBegin) * _slabSize;
01212     for (int x = begin; x < end; x++)
01213         _xForce[x] = 0.0;
01214 
01215     // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res)
01216 
01217     advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd);
01218     advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
01219     advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd);
01220     advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd);
01221     advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd);
01222 
01223     // Have to wait untill all the threads are done -> so continuing in step 3
01224 }
01225 
01227 // Advect using the MacCormack method from the Selle paper
01229 void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
01230 {
01231     const float dt0 = _dt / _dx;
01232     Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
01233 
01234     // use force array as temp arrays
01235     float* t1 = _xForce;
01236 
01237     // advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles)
01238 
01239     advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd);
01240     advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
01241     advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd);
01242     advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
01243     advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
01244 
01245     if(_domainBcLeft == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
01246     else setZeroX(_xVelocityTemp, res, zBegin, zEnd);               
01247 
01248     if(_domainBcFront == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
01249     else setZeroY(_yVelocityTemp, res, zBegin, zEnd); 
01250 
01251     if(_domainBcTop == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
01252     else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
01253 
01254     setZeroBorder(_density, res, zBegin, zEnd);
01255     setZeroBorder(_heat, res, zBegin, zEnd);
01256 
01257 
01258     /*int begin=zBegin * _slabSize;
01259     int end=begin + (zEnd - zBegin) * _slabSize;
01260   for (int x = begin; x < end; x++)
01261     _xForce[x] = _yForce[x] = 0.0f;*/
01262 }