Blender V2.61 - r43446

FLUID_3D_SOLVERS.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 // 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 }