[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48049] branches/smoke2: - Rewrite PCG: Still in testing phase
Daniel Genrich
daniel.genrich at gmx.net
Mon Jun 18 19:55:38 CEST 2012
Revision: 48049
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48049
Author: genscher
Date: 2012-06-18 17:55:38 +0000 (Mon, 18 Jun 2012)
Log Message:
-----------
- Rewrite PCG: Still in testing phase
Modified Paths:
--------------
branches/smoke2/intern/smoke/intern/FLUID_3D_SOLVERS.cpp
branches/smoke2/source/blender/blenkernel/intern/smoke.c
Modified: branches/smoke2/intern/smoke/intern/FLUID_3D_SOLVERS.cpp
===================================================================
--- branches/smoke2/intern/smoke/intern/FLUID_3D_SOLVERS.cpp 2012-06-18 17:49:31 UTC (rev 48048)
+++ branches/smoke2/intern/smoke/intern/FLUID_3D_SOLVERS.cpp 2012-06-18 17:55:38 UTC (rev 48049)
@@ -168,227 +168,173 @@
if (_Acenter) delete[] _Acenter;
}
-#if USE_NEW_CG == 1
-#else
-void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
+
+#define SMOKE_LOOP \
+ index = _slabSize + _xRes + 1; \
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) \
+ for (y = 1; y < _yRes - 1; y++, index += 2) \
+ for (x = 1; x < _xRes - 1; x++, index++)
+
+void FLUID_3D::solvePressurePre(float* _x, float* b, unsigned char* skip)
{
int x, y, z;
size_t index;
- float *_q, *_Precond, *_h, *_residual, *_direction;
+ float *_q, *_Precond, *_z, *_r, *_p;
- // i = 0
- int i = 0;
+ float alpha = 0.0f, beta = 0;
- _residual = new float[_totalCells]; // set 0
- _direction = new float[_totalCells]; // set 0
+ float eps = SOLVER_ACCURACY;
+ float currentR = 0.0;
+
+ int k = 0;
+
+ _r = new float[_totalCells]; // set 0
+ _p = new float[_totalCells]; // set 0
+ _z = new float[_totalCells]; // set 0
+
+ // q = A p
_q = new float[_totalCells]; // set 0
- _h = new float[_totalCells]; // set 0
+
_Precond = new float[_totalCells]; // set 0
- memset(_residual, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_r, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_z, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_q, 0, sizeof(float)*_xRes*_yRes*_zRes);
- memset(_direction, 0, sizeof(float)*_xRes*_yRes*_zRes);
- memset(_h, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_p, 0, sizeof(float)*_xRes*_yRes*_zRes);
memset(_Precond, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ // delta = r^T z
+ float delta = 0.0f;
+
+ // deltaNew = r^T_k+1 z_k+1
float deltaNew = 0.0f;
- // r = b - Ax
- index = _slabSize + _xRes + 1;
- for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
- for (y = 1; y < _yRes - 1; y++, index += 2)
- for (x = 1; x < _xRes - 1; x++, index++)
- {
- // if the cell is a variable
- float Acenter = 0.0f;
- if (!skip[index])
- {
- // set the matrix to the Poisson stencil in order
- if (!skip[index + 1]) Acenter += 1.;
- if (!skip[index - 1]) Acenter += 1.;
- if (!skip[index + _xRes]) Acenter += 1.;
- if (!skip[index - _xRes]) Acenter += 1.;
- if (!skip[index + _slabSize]) Acenter += 1.;
- if (!skip[index - _slabSize]) Acenter += 1.;
+ // r_0 = b - A x_0
+ SMOKE_LOOP
+ {
+ // if the cell is a variable
+ float Acenter = 0.0f;
+ if (!skip[index])
+ {
+ // set the matrix to the Poisson stencil in order
+ if (!skip[index + 1]) Acenter += 1.;
+ if (!skip[index - 1]) Acenter += 1.;
+ if (!skip[index + _xRes]) Acenter += 1.;
+ if (!skip[index - _xRes]) Acenter += 1.;
+ if (!skip[index + _slabSize]) Acenter += 1.;
+ if (!skip[index - _slabSize]) Acenter += 1.;
- _residual[index] = b[index] - (Acenter * field[index] +
- field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
- field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
- field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
- field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
- field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
- field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
- }
- else
- {
- _residual[index] = 0.0f;
- }
+ _r[index] = b[index] - (Acenter * _x[index] +
+ _x[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
+ _x[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
+ _x[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
+ _x[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
+ _x[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
+ _x[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
+ }
+ else
+ {
+ _r[index] = 0.0f;
+ }
- // P^-1
- if(Acenter < 1.0)
- _Precond[index] = 0.0;
- else
- _Precond[index] = 1.0 / Acenter;
+ // P^-1
+ if(Acenter < 1.0)
+ _Precond[index] = 0.0;
+ else
+ _Precond[index] = 1.0 / Acenter;
- // p = P^-1 * r
- _direction[index] = _residual[index] * _Precond[index];
+ // z_0 = P^-1 * r_0
+ _z[index] = _Precond[index] * _r[index];
- deltaNew += _residual[index] * _direction[index];
- }
+ // p = z
+ _p[index] = _z[index];
+ }
- // While deltaNew > (eps^2) * delta0
- const float eps = SOLVER_ACCURACY;
- //while ((i < _iterations) && (deltaNew > eps*delta0))
- float maxR = 2.0f * eps;
- // while (i < _iterations)
- while ((i < _iterations) && (maxR > 0.001*eps))
+ while (k < _iterations)
{
+ alpha = 0.0f;
+ delta = 0.0f;
- float alpha = 0.0f;
+ SMOKE_LOOP
+ {
+ // if the cell is a variable
+ float Acenter = 0.0f;
+ if (!skip[index])
+ {
+ // set the matrix to the Poisson stencil in order
+ if (!skip[index + 1]) Acenter += 1.;
+ if (!skip[index - 1]) Acenter += 1.;
+ if (!skip[index + _xRes]) Acenter += 1.;
+ if (!skip[index - _xRes]) Acenter += 1.;
+ if (!skip[index + _slabSize]) Acenter += 1.;
+ if (!skip[index - _slabSize]) Acenter += 1.;
- index = _slabSize + _xRes + 1;
- for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
- for (y = 1; y < _yRes - 1; y++, index += 2)
- for (x = 1; x < _xRes - 1; x++, index++)
- {
- // if the cell is a variable
- float Acenter = 0.0f;
- if (!skip[index])
- {
- // set the matrix to the Poisson stencil in order
- if (!skip[index + 1]) Acenter += 1.;
- if (!skip[index - 1]) Acenter += 1.;
- if (!skip[index + _xRes]) Acenter += 1.;
- if (!skip[index - _xRes]) Acenter += 1.;
- if (!skip[index + _slabSize]) Acenter += 1.;
- if (!skip[index - _slabSize]) Acenter += 1.;
+ _q[index] = Acenter * _p[index] +
+ _p[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
+ _p[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
+ _p[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
+ _p[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
+ _p[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
+ _p[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
+ }
+ else
+ {
+ _q[index] = 0.0f;
+ }
- _q[index] = Acenter * _direction[index] +
- _direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
- _direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
- _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
- _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
- _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
- _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
- }
- else
- {
- _q[index] = 0.0f;
- }
+ // p^T A p
+ alpha += _p[index] * _q[index];
- alpha += _direction[index] * _q[index];
- }
-
- if (fabs(alpha) > 0.0f)
- {
- alpha = deltaNew / alpha;
+ // r^T z
+ delta += _r[index] * _z[index];
}
- float deltaOld = deltaNew;
+ // alpha = r^T * z / p^T A p
+ alpha = delta / alpha;
- deltaNew = 0.0f;
+ currentR = 0.0f;
- maxR = 0.0;
+ SMOKE_LOOP
+ {
+ // x_k+1 = x_k + alpha * p
+ _x[index] += alpha * _p[index];
- float tmp;
+ // r_k+1 = r_k - alpha A p
+ _r[index] -= alpha * _q[index];
- // x = x + alpha * d
- index = _slabSize + _xRes + 1;
- for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
- for (y = 1; y < _yRes - 1; y++, index += 2)
- for (x = 1; x < _xRes - 1; x++, index++)
- {
- field[index] += alpha * _direction[index];
+ currentR = (_r[index] > currentR) ? _r[index] : currentR;
+ }
- _residual[index] -= alpha * _q[index];
+ //if (r_k+1 > EPSILON) exit
+ if(currentR < 0.001*eps)
+ break;
- _h[index] = _Precond[index] * _residual[index];
+ deltaNew = 0.0f;
- tmp = _residual[index] * _h[index];
- deltaNew += tmp;
- maxR = (tmp > maxR) ? tmp : maxR;
+ SMOKE_LOOP
+ {
+ // z_k+1 = P^-1 r_k+1
+ _z[index] = _Precond[index] * _r[index];
- }
+ deltaNew += _z[index] * _r[index];
+ }
- // beta = deltaNew / deltaOld
- float beta = deltaNew / deltaOld;
+ // beta = z^T_k+1 r_k+1 / z^T r
+ beta = deltaNew / delta;
- // d = h + beta * d
- index = _slabSize + _xRes + 1;
- for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
- for (y = 1; y < _yRes - 1; y++, index += 2)
- for (x = 1; x < _xRes - 1; x++, index++)
- _direction[index] = _h[index] + beta * _direction[index];
+ // p_k+1 = z + beta * p
+ SMOKE_LOOP
+ {
+ _p[index] = _z[index] + beta * _p[index];
+ }
- // i = i + 1
- i++;
+ k++;
}
- // cout << i << " iterations converged to " << sqrt(maxR) << endl;
+ cout << k << " iterations converged to " << sqrt(currentR) << endl;
- if (_h) delete[] _h;
if (_Precond) delete[] _Precond;
- if (_residual) delete[] _residual;
- if (_direction) delete[] _direction;
- if (_q) delete[] _q;
+ if (_r) delete[] _r;
+ if (_p) delete[] _p;
+ if (_z) delete[] _z;
+ if (_q) delete[] _q;
}
-#endif
-#if 0
-void FLUID_3D::solvePressureJacobian(float* p, float* d, unsigned char* ob)
-{
- float *_tmp = new float[_totalCells];
- unsigned int x, y, z;
-
- float maxdp = 0.0f;
-
- do
- {
- maxdp = 0.0f;
-
- size_t index = _slabSize + _xRes + 1;
- for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
- for (y = 1; y < _yRes - 1; y++, index += 2)
- for (x = 1; x < _xRes - 1; x++, index++)
- {
- float dC = d[index];
- float pC = p[index]; // center
-
- float pR = p[index + 1]; // right
- float pL = p[index - 1]; // left
- float pT = p[index + _slabSize]; // top
- float pB = p[index - _slabSize]; // bottom
- float pU = p[index + _xRes]; // Up
- float pD = p[index - _xRes]; // Down
-
- if(ob[index + 1]) pR = pC;
- if(ob[index - 1]) pL = pC;
- if(ob[index + _slabSize]) pT = pC;
- if(ob[index - _slabSize]) pB = pC;
- if(ob[index + _xRes]) pU = pC;
- if(ob[index - _xRes]) pD = pC;
-
- _tmp[index] = (pR + pL + pT + pB + pU + pD + dC) / 6.0f;
-
- if(ob[index])
- _tmp[index] = 0;
- }
-
- for(unsigned int i = 0; i < _totalCells; i++)
- {
- float dp = _tmp[i] - p[i];
-
- if(dp < 0)
- dp *= -1.0f;
-
- if(dp > maxdp)
- maxdp = dp;
-
- p[i] = _tmp[i];
- }
- printf("maxdp: %f\n", maxdp);
- } while(maxdp > SOLVER_ACCURACY);
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list