Blender  V2.59
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 }