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 // Both solvers optimized by merging loops and precalculating 00026 // stuff used in iteration loop. 00027 // - MiikaH 00029 00030 #include "FLUID_3D.h" 00031 #include <cstring> 00032 #define SOLVER_ACCURACY 1e-06 00033 00035 // solve the heat equation with CG 00037 void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip) 00038 { 00039 int x, y, z; 00040 const int twoxr = 2 * _xRes; 00041 size_t index; 00042 const float heatConst = _dt * _heatDiffusion / (_dx * _dx); 00043 float *_q, *_residual, *_direction, *_Acenter; 00044 00045 // i = 0 00046 int i = 0; 00047 00048 _residual = new float[_totalCells]; // set 0 00049 _direction = new float[_totalCells]; // set 0 00050 _q = new float[_totalCells]; // set 0 00051 _Acenter = new float[_totalCells]; // set 0 00052 00053 memset(_residual, 0, sizeof(float)*_totalCells); 00054 memset(_q, 0, sizeof(float)*_totalCells); 00055 memset(_direction, 0, sizeof(float)*_totalCells); 00056 memset(_Acenter, 0, sizeof(float)*_totalCells); 00057 00058 float deltaNew = 0.0f; 00059 00060 // r = b - Ax 00061 index = _slabSize + _xRes + 1; 00062 for (z = 1; z < _zRes - 1; z++, index += twoxr) 00063 for (y = 1; y < _yRes - 1; y++, index += 2) 00064 for (x = 1; x < _xRes - 1; x++, index++) 00065 { 00066 // if the cell is a variable 00067 _Acenter[index] = 1.0f; 00068 if (!skip[index]) 00069 { 00070 // set the matrix to the Poisson stencil in order 00071 if (!skip[index + 1]) _Acenter[index] += heatConst; 00072 if (!skip[index - 1]) _Acenter[index] += heatConst; 00073 if (!skip[index + _xRes]) _Acenter[index] += heatConst; 00074 if (!skip[index - _xRes]) _Acenter[index] += heatConst; 00075 if (!skip[index + _slabSize]) _Acenter[index] += heatConst; 00076 if (!skip[index - _slabSize]) _Acenter[index] += heatConst; 00077 00078 _residual[index] = b[index] - (_Acenter[index] * field[index] + 00079 field[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) + 00080 field[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) + 00081 field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) + 00082 field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) + 00083 field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) + 00084 field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst)); 00085 } 00086 else 00087 { 00088 _residual[index] = 0.0f; 00089 } 00090 00091 _direction[index] = _residual[index]; 00092 deltaNew += _residual[index] * _residual[index]; 00093 } 00094 00095 00096 // While deltaNew > (eps^2) * delta0 00097 const float eps = SOLVER_ACCURACY; 00098 float maxR = 2.0f * eps; 00099 while ((i < _iterations) && (maxR > eps)) 00100 { 00101 // q = Ad 00102 float alpha = 0.0f; 00103 00104 index = _slabSize + _xRes + 1; 00105 for (z = 1; z < _zRes - 1; z++, index += twoxr) 00106 for (y = 1; y < _yRes - 1; y++, index += 2) 00107 for (x = 1; x < _xRes - 1; x++, index++) 00108 { 00109 // if the cell is a variable 00110 if (!skip[index]) 00111 { 00112 00113 _q[index] = (_Acenter[index] * _direction[index] + 00114 _direction[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) + 00115 _direction[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) + 00116 _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) + 00117 _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) + 00118 _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) + 00119 _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst)); 00120 } 00121 else 00122 { 00123 _q[index] = 0.0f; 00124 } 00125 alpha += _direction[index] * _q[index]; 00126 } 00127 00128 if (fabs(alpha) > 0.0f) 00129 alpha = deltaNew / alpha; 00130 00131 float deltaOld = deltaNew; 00132 deltaNew = 0.0f; 00133 00134 maxR = 0.0f; 00135 00136 index = _slabSize + _xRes + 1; 00137 for (z = 1; z < _zRes - 1; z++, index += twoxr) 00138 for (y = 1; y < _yRes - 1; y++, index += 2) 00139 for (x = 1; x < _xRes - 1; x++, index++) 00140 { 00141 field[index] += alpha * _direction[index]; 00142 00143 _residual[index] -= alpha * _q[index]; 00144 maxR = (_residual[index] > maxR) ? _residual[index] : maxR; 00145 00146 deltaNew += _residual[index] * _residual[index]; 00147 } 00148 00149 float beta = deltaNew / deltaOld; 00150 00151 index = _slabSize + _xRes + 1; 00152 for (z = 1; z < _zRes - 1; z++, index += twoxr) 00153 for (y = 1; y < _yRes - 1; y++, index += 2) 00154 for (x = 1; x < _xRes - 1; x++, index++) 00155 _direction[index] = _residual[index] + beta * _direction[index]; 00156 00157 00158 i++; 00159 } 00160 // cout << i << " iterations converged to " << maxR << endl; 00161 00162 if (_residual) delete[] _residual; 00163 if (_direction) delete[] _direction; 00164 if (_q) delete[] _q; 00165 if (_Acenter) delete[] _Acenter; 00166 } 00167 00168 00169 void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip) 00170 { 00171 int x, y, z; 00172 size_t index; 00173 float *_q, *_Precond, *_h, *_residual, *_direction; 00174 00175 // i = 0 00176 int i = 0; 00177 00178 _residual = new float[_totalCells]; // set 0 00179 _direction = new float[_totalCells]; // set 0 00180 _q = new float[_totalCells]; // set 0 00181 _h = new float[_totalCells]; // set 0 00182 _Precond = new float[_totalCells]; // set 0 00183 00184 memset(_residual, 0, sizeof(float)*_xRes*_yRes*_zRes); 00185 memset(_q, 0, sizeof(float)*_xRes*_yRes*_zRes); 00186 memset(_direction, 0, sizeof(float)*_xRes*_yRes*_zRes); 00187 memset(_h, 0, sizeof(float)*_xRes*_yRes*_zRes); 00188 memset(_Precond, 0, sizeof(float)*_xRes*_yRes*_zRes); 00189 00190 float deltaNew = 0.0f; 00191 00192 // r = b - Ax 00193 index = _slabSize + _xRes + 1; 00194 for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) 00195 for (y = 1; y < _yRes - 1; y++, index += 2) 00196 for (x = 1; x < _xRes - 1; x++, index++) 00197 { 00198 // if the cell is a variable 00199 float Acenter = 0.0f; 00200 if (!skip[index]) 00201 { 00202 // set the matrix to the Poisson stencil in order 00203 if (!skip[index + 1]) Acenter += 1.; 00204 if (!skip[index - 1]) Acenter += 1.; 00205 if (!skip[index + _xRes]) Acenter += 1.; 00206 if (!skip[index - _xRes]) Acenter += 1.; 00207 if (!skip[index + _slabSize]) Acenter += 1.; 00208 if (!skip[index - _slabSize]) Acenter += 1.; 00209 00210 _residual[index] = b[index] - (Acenter * field[index] + 00211 field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+ 00212 field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+ 00213 field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+ 00214 field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+ 00215 field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+ 00216 field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) ); 00217 } 00218 else 00219 { 00220 _residual[index] = 0.0f; 00221 } 00222 00223 // P^-1 00224 if(Acenter < 1.0) 00225 _Precond[index] = 0.0; 00226 else 00227 _Precond[index] = 1.0 / Acenter; 00228 00229 // p = P^-1 * r 00230 _direction[index] = _residual[index] * _Precond[index]; 00231 00232 deltaNew += _residual[index] * _direction[index]; 00233 } 00234 00235 00236 // While deltaNew > (eps^2) * delta0 00237 const float eps = SOLVER_ACCURACY; 00238 //while ((i < _iterations) && (deltaNew > eps*delta0)) 00239 float maxR = 2.0f * eps; 00240 // while (i < _iterations) 00241 while ((i < _iterations) && (maxR > 0.001*eps)) 00242 { 00243 00244 float alpha = 0.0f; 00245 00246 index = _slabSize + _xRes + 1; 00247 for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) 00248 for (y = 1; y < _yRes - 1; y++, index += 2) 00249 for (x = 1; x < _xRes - 1; x++, index++) 00250 { 00251 // if the cell is a variable 00252 float Acenter = 0.0f; 00253 if (!skip[index]) 00254 { 00255 // set the matrix to the Poisson stencil in order 00256 if (!skip[index + 1]) Acenter += 1.; 00257 if (!skip[index - 1]) Acenter += 1.; 00258 if (!skip[index + _xRes]) Acenter += 1.; 00259 if (!skip[index - _xRes]) Acenter += 1.; 00260 if (!skip[index + _slabSize]) Acenter += 1.; 00261 if (!skip[index - _slabSize]) Acenter += 1.; 00262 00263 _q[index] = Acenter * _direction[index] + 00264 _direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) + 00265 _direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) + 00266 _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) + 00267 _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+ 00268 _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) + 00269 _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f); 00270 } 00271 else 00272 { 00273 _q[index] = 0.0f; 00274 } 00275 00276 alpha += _direction[index] * _q[index]; 00277 } 00278 00279 00280 if (fabs(alpha) > 0.0f) 00281 alpha = deltaNew / alpha; 00282 00283 float deltaOld = deltaNew; 00284 deltaNew = 0.0f; 00285 00286 maxR = 0.0; 00287 00288 float tmp; 00289 00290 // x = x + alpha * d 00291 index = _slabSize + _xRes + 1; 00292 for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) 00293 for (y = 1; y < _yRes - 1; y++, index += 2) 00294 for (x = 1; x < _xRes - 1; x++, index++) 00295 { 00296 field[index] += alpha * _direction[index]; 00297 00298 _residual[index] -= alpha * _q[index]; 00299 00300 _h[index] = _Precond[index] * _residual[index]; 00301 00302 tmp = _residual[index] * _h[index]; 00303 deltaNew += tmp; 00304 maxR = (tmp > maxR) ? tmp : maxR; 00305 00306 } 00307 00308 00309 // beta = deltaNew / deltaOld 00310 float beta = deltaNew / deltaOld; 00311 00312 // d = h + beta * d 00313 index = _slabSize + _xRes + 1; 00314 for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) 00315 for (y = 1; y < _yRes - 1; y++, index += 2) 00316 for (x = 1; x < _xRes - 1; x++, index++) 00317 _direction[index] = _h[index] + beta * _direction[index]; 00318 00319 // i = i + 1 00320 i++; 00321 } 00322 // cout << i << " iterations converged to " << sqrt(maxR) << endl; 00323 00324 if (_h) delete[] _h; 00325 if (_Precond) delete[] _Precond; 00326 if (_residual) delete[] _residual; 00327 if (_direction) delete[] _direction; 00328 if (_q) delete[] _q; 00329 }