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