diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript index 7d6cba24f2c..3ef20b9be3a 100644 --- a/intern/elbeem/SConscript +++ b/intern/elbeem/SConscript @@ -29,24 +29,27 @@ else: "intern/attributes.cpp", "intern/elbeem.cpp", - "intern/factory_fsgr.cpp", "intern/isosurface.cpp", - "intern/lbminterface.cpp", "intern/ntl_blenderdumper.cpp", "intern/ntl_bsptree.cpp", "intern/ntl_geometrymodel.cpp", "intern/ntl_geometryobject.cpp", "intern/ntl_lightobject.cpp", "intern/ntl_ray.cpp", - "intern/ntl_raytracer.cpp", "intern/ntl_scene.cpp", + "intern/ntl_world.cpp", "intern/parametrizer.cpp", "intern/particletracer.cpp", "intern/simulation_object.cpp", "intern/utilities.cpp", - "intern/blendercall.cpp" + "intern/blendercall.cpp", - ]; # sources + "intern/solver_init.cpp", + "intern/solver_interface.cpp", + "intern/solver_main.cpp", + "intern/solver_util.cpp" + + ]; # sources elbeem_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/blender_elbeem', source=Sources) diff --git a/intern/elbeem/intern/blendercall.cpp b/intern/elbeem/intern/blendercall.cpp index 7ac80eedc3a..2d241ae623a 100644 --- a/intern/elbeem/intern/blendercall.cpp +++ b/intern/elbeem/intern/blendercall.cpp @@ -10,7 +10,6 @@ *****************************************************************************/ #include "globals.h" -#include "ntl_raytracer.h" #include "ntl_blenderdumper.h" #include diff --git a/intern/elbeem/intern/cfglexer.cpp b/intern/elbeem/intern/cfglexer.cpp index 3b29f79469f..c8492f8105c 100644 --- a/intern/elbeem/intern/cfglexer.cpp +++ b/intern/elbeem/intern/cfglexer.cpp @@ -810,9 +810,9 @@ char *yy_text; #define CHAR_BUFFER_SIZE 8000 char charBuffer[ CHAR_BUFFER_SIZE ]; -extern "C" int yy_wrap (void ) { return 1; } int lineCount = 1; +extern "C" int yy_wrap (void ) { return 1; } #define YY_NO_UNISTD_H /*----------------------------------------------------------------------------*/ diff --git a/intern/elbeem/intern/cfgparser.cpp b/intern/elbeem/intern/cfgparser.cpp index 22f2af8f962..8984fce107c 100644 --- a/intern/elbeem/intern/cfgparser.cpp +++ b/intern/elbeem/intern/cfgparser.cpp @@ -1233,7 +1233,6 @@ yysymprint (yyoutput, yytype, yyvaluep) # endif switch (yytype) { - case 0: default: break; } diff --git a/intern/elbeem/intern/elbeem.cpp b/intern/elbeem/intern/elbeem.cpp index b9806a6a142..a8bd99e2082 100644 --- a/intern/elbeem/intern/elbeem.cpp +++ b/intern/elbeem/intern/elbeem.cpp @@ -21,8 +21,8 @@ double guiRoiEZ = 1.0; int guiRoiMaxLev=6, guiRoiMinLev=0; //! global raytracer pointer (=world) -class ntlRaytracer; -ntlRaytracer *gpWorld = (ntlRaytracer*)0; +class ntlWorld; +ntlWorld *gpWorld = (ntlWorld*)0; //! debug output switch bool myDebugOut = false; diff --git a/intern/elbeem/intern/factory_fsgr.cpp b/intern/elbeem/intern/factory_fsgr.cpp deleted file mode 100644 index 8b5128a0254..00000000000 --- a/intern/elbeem/intern/factory_fsgr.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004,2005 Nils Thuerey - * - * Standard LBM Factory implementation - * - *****************************************************************************/ - -// disable sometimes to speed up compiling/2d tests -#define DISABLE 0 - -#include "lbmfsgrsolver.h" -#include "factory_lbm.h" - -//! lbm factory functions -LbmSolverInterface* createSolverLbmFsgr() { -#if DISABLE!=1 -#if LBMDIM==2 - return new LbmFsgrSolver< LbmBGK2D >(); -#endif // LBMDIM==2 -#if LBMDIM==3 - return new LbmFsgrSolver< LbmBGK3D >(); -#endif // LBMDIM==3 -#endif // DISABLE - return NULL; -} - - diff --git a/intern/elbeem/intern/factory_lbm.h b/intern/elbeem/intern/factory_lbm.h deleted file mode 100644 index 0e7e4dcb9f8..00000000000 --- a/intern/elbeem/intern/factory_lbm.h +++ /dev/null @@ -1,18 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * 2D/3D LBM Factory header - * - *****************************************************************************/ - -#include "lbminterface.h" - -//! lbm factory functions -LbmSolverInterface* createSolverLbmFsgr(); -#ifdef LBM_INCLUDE_TESTSOLVERS -LbmSolverInterface* createSolverOld(); -#endif // LBM_INCLUDE_OLD - - diff --git a/intern/elbeem/intern/globals.h b/intern/elbeem/intern/globals.h index 864c3052ad3..60a60b45e5a 100644 --- a/intern/elbeem/intern/globals.h +++ b/intern/elbeem/intern/globals.h @@ -15,8 +15,8 @@ //! user interface variables // global raytracer pointer (=world) -class ntlRaytracer; -extern ntlRaytracer *gpWorld; +class ntlWorld; +extern ntlWorld *gpWorld; // debug output switch extern bool myDebugOut; diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index fecb5ed4bf8..f81a0069006 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -14,10 +14,13 @@ #include #include + +// sirdude fix for solaris #if !defined(linux) && (defined (__sparc) || defined (__sparc__)) #include #endif + /****************************************************************************** * Constructor *****************************************************************************/ @@ -176,9 +179,6 @@ void IsoSurface::triangulate( void ) value[5] = *getData(i+1,j ,k+1); value[6] = *getData(i+1,j+1,k+1); value[7] = *getData(i ,j+1,k+1); - //errMsg("ISOT2D"," at "<-10.0) { - // standard interpolation - //vertInfo[e].type = 0; - /*if (ABS(mIsoValue-valp1) < 0.000000001) { - mu = 0.0; - } else { - if (ABS(mIsoValue-valp2) < 0.000000001) { - mu = 1.0; - } else { - mu = (mIsoValue - valp1) / (valp2 - valp1); - } - } */ - /*} else { - errorOut(" ? "); - // use fill grade (=karo) - vertInfo[e].type = 1; - if(valp1 < valp2) { mu = 1.0- (valp1 + valp2 - mIsoValue); - } else { mu = 0.0+ (valp1 + valp2 - mIsoValue); } - } */ - - //const float mu = (mIsoValue - valp1) / (valp2 - valp1); float mu; if(valp1 < valp2) { mu = 1.0 - 1.0*(valp1 + valp2 - mIsoValue); @@ -270,15 +243,11 @@ void IsoSurface::triangulate( void ) mu = 0.0 + 1.0*(valp1 + valp2 - mIsoValue); } - float isov2 = mIsoValue; - isov2 = (valp1+valp2)*0.5; - mu = (isov2 - valp1) / (valp2 - valp1); - mu = (isov2) / (valp2 - valp1); - + //float isov2 = mIsoValue; + //isov2 = (valp1+valp2)*0.5; + //mu = (isov2 - valp1) / (valp2 - valp1); + //mu = (isov2) / (valp2 - valp1); mu = (mIsoValue - valp1) / (valp2 - valp1); - //mu *= mu; - - // init isolevel vertex ilv.v = p1 + (p2-p1)*mu; @@ -319,14 +288,9 @@ void IsoSurface::triangulate( void ) normalize( mPoints[ni].n ); } - if(mSmoothSurface>0.0) { - // not needed for post normal smoothing? - // if(mSmoothNormals<=0.0) { smoothNormals(mSmoothSurface*0.5); } - smoothSurface(mSmoothSurface); - } - if(mSmoothNormals>0.0) { - smoothNormals(mSmoothNormals); - } + //for(int i=0; i0.0) { smoothSurface(mSmoothSurface); } + if(mSmoothNormals>0.0) { smoothNormals(mSmoothNormals); } myTime_t tritimeend = getTime(); debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< ((tritimeend-tritimestart)/(double)1000.0)<<"s, ss="< &a1 = mAdjacentFaces[v1]; + const vector &a2 = mAdjacentFaces[v2]; + for (int k1 = 0; k1 < (int)a1.size(); k1++) { + int other = a1[k1]; + if (other == i) + continue; + vector::const_iterator it = + std::find(a2.begin(), a2.end(), other); + if (it == a2.end()) + continue; + + //int ind = (faces[other].indexof(v1)+1)%3; + int ind = -1; + if( mIndices[other*3+0] == (unsigned int)v1 ) ind = 0; + else if( mIndices[other*3+1] == (unsigned int)v1 ) ind = 1; + else if( mIndices[other*3+2] == (unsigned int)v1 ) ind = 2; + ind = (ind+1)%3; + + if ( (int)mIndices[other*3 + ((ind+1)%3)] != v2) + continue; + mAcrossEdge[i*3 + j] = other; + mAcrossEdge[other*3 + ind] = i; + break; + } + } + } + + //errMsg("SUBDIV ACREDG", "Done.\n"); + } + + //errMsg("SUBDIV","start"); + // Introduce new vertices + int nf = (int)mIndices.size() / 3; + + //vector newverts(nf, TriMesh::Face(-1,-1,-1)); + vector newverts(nf*3); //, TriMesh::Face(-1,-1,-1)); + for(int j=0; j<(int)newverts.size(); j++) newverts[j] = -1; + + int old_nv = (int)mPoints.size(); + mPoints.reserve(4 * old_nv); + vector newvert_count(old_nv + 3*nf); // wichtig...? + //errMsg("NC", newvert_count.size() ); + + for (i = 0; i < nf; i++) { + for (int j = 0; j < 3; j++) { + int ae = mAcrossEdge[i*3 + j]; + if (newverts[i*3 + j] == -1 && ae != -1) { + if (mAcrossEdge[ae*3 + 0] == i) + newverts[i*3 + j] = newverts[ae*3 + 0]; + else if (mAcrossEdge[ae*3 + 1] == i) + newverts[i*3 + j] = newverts[ae*3 + 1]; + else if (mAcrossEdge[ae*3 + 2] == i) + newverts[i*3 + j] = newverts[ae*3 + 2]; + } + if (newverts[i*3 + j] == -1) { + IsoLevelVertex ilv; + ilv.v = ntlVec3Gfx(0.0); + ilv.n = ntlVec3Gfx(0.0); + mPoints.push_back(ilv); + newverts[i*3 + j] = (int)mPoints.size() - 1; + if (ae != -1) { + if (mAcrossEdge[ae*3 + 0] == i) + newverts[ae*3 + 0] = newverts[i*3 + j]; + else if (mAcrossEdge[ae*3 + 1] == i) + newverts[ae*3 + 1] = newverts[i*3 + j]; + else if (mAcrossEdge[ae*3 + 2] == i) + newverts[ae*3 + 2] = newverts[i*3 + j]; + } + } + if(ae != -1) { + mPoints[newverts[i*3 + j]].v += + mPoints[ mIndices[i*3 + ( j )] ].v * 0.25f + // j = 0,1,2? + mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.375f + + mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.375f; +#if RECALCNORMALS==0 + mPoints[newverts[i*3 + j]].n += + mPoints[ mIndices[i*3 + ( j )] ].n * 0.25f + // j = 0,1,2? + mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.375f + + mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.375f; +#endif // RECALCNORMALS==0 + } else { + mPoints[newverts[i*3 + j]].v += + mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.5f + + mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.5f ; +#if RECALCNORMALS==0 + mPoints[newverts[i*3 + j]].n += + mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.5f + + mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.5f ; +#endif // RECALCNORMALS==0 + } + + newvert_count[newverts[i*3 + j]]++; + } + } + for (i = old_nv; i < (int)mPoints.size(); i++) { + if (!newvert_count[i]) + continue; + float scale = 1.0f / newvert_count[i]; + mPoints[i].v *= scale; + +#if RECALCNORMALS==0 + //mPoints[i].n *= scale; + //normalize( mPoints[i].n ); +#endif // RECALCNORMALS==0 + } + + // Update old vertices + for (i = 0; i < old_nv; i++) { + ntlVec3Gfx bdyavg(0.0), nbdyavg(0.0); + ntlVec3Gfx norm_bdyavg(0.0), norm_nbdyavg(0.0); // N + int nbdy = 0, nnbdy = 0; + int naf = (int)mAdjacentFaces[i].size(); + if (!naf) + continue; + for (int j = 0; j < naf; j++) { + int af = mAdjacentFaces[i][j]; + + int afi = -1; + if( mIndices[af*3+0] == (unsigned int)i ) afi = 0; + else if( mIndices[af*3+1] == (unsigned int)i ) afi = 1; + else if( mIndices[af*3+2] == (unsigned int)i ) afi = 2; + + int n1 = (afi+1) % 3; + int n2 = (afi+2) % 3; + if (mAcrossEdge[af*3 + n1] == -1) { + bdyavg += mPoints[newverts[af*3 + n1]].v; +#if RECALCNORMALS==0 + //norm_bdyavg += mPoints[newverts[af*3 + n1]].n; +#endif // RECALCNORMALS==0 + nbdy++; + } else { + nbdyavg += mPoints[newverts[af*3 + n1]].v; +#if RECALCNORMALS==0 + //norm_nbdyavg += mPoints[newverts[af*3 + n1]].n; +#endif // RECALCNORMALS==0 + nnbdy++; + } + if (mAcrossEdge[af*3 + n2] == -1) { + bdyavg += mPoints[newverts[af*3 + n2]].v; +#if RECALCNORMALS==0 + //norm_bdyavg += mPoints[newverts[af*3 + n2]].n; +#endif // RECALCNORMALS==0 + nbdy++; + } else { + nbdyavg += mPoints[newverts[af*3 + n2]].v; +#if RECALCNORMALS==0 + //norm_nbdyavg += mPoints[newverts[af*3 + n2]].n; +#endif // RECALCNORMALS==0 + nnbdy++; + } + } + + float alpha; + ntlVec3Gfx newpt; + if (nbdy) { + newpt = bdyavg / (float) nbdy; + alpha = 0.5f; + } else if (nnbdy) { + newpt = nbdyavg / (float) nnbdy; + if (nnbdy == 6) + alpha = 1.05; + else if (nnbdy == 8) + alpha = 0.86; + else if (nnbdy == 10) + alpha = 0.7; + else + alpha = 0.6; + } else { + continue; + } + mPoints[i].v *= 1.0f - alpha; + mPoints[i].v += newpt * alpha; + +#if RECALCNORMALS==0 + //mPoints[i].n *= 1.0f - alpha; + //mPoints[i].n += newpt * alpha; +#endif // RECALCNORMALS==0 + } + + // Insert new faces + mIndices.reserve(4*nf); + for (i = 0; i < nf; i++) { + mIndices.push_back( mIndices[i*3 + 0]); + mIndices.push_back( newverts[i*3 + 2]); + mIndices.push_back( newverts[i*3 + 1]); + + mIndices.push_back( mIndices[i*3 + 1]); + mIndices.push_back( newverts[i*3 + 0]); + mIndices.push_back( newverts[i*3 + 2]); + + mIndices.push_back( mIndices[i*3 + 2]); + mIndices.push_back( newverts[i*3 + 1]); + mIndices.push_back( newverts[i*3 + 0]); + + mIndices[i*3+0] = newverts[i*3+0]; + mIndices[i*3+1] = newverts[i*3+1]; + mIndices[i*3+2] = newverts[i*3+2]; + } + + // recalc normals +#if RECALCNORMALS==1 + { + int nf = (int)mIndices.size()/3, nv = (int)mPoints.size(), i; + for (i = 0; i < nv; i++) { + mPoints[i].n = ntlVec3Gfx(0.0); + } + for (i = 0; i < nf; i++) { + const ntlVec3Gfx &p0 = mPoints[mIndices[i*3+0]].v; + const ntlVec3Gfx &p1 = mPoints[mIndices[i*3+1]].v; + const ntlVec3Gfx &p2 = mPoints[mIndices[i*3+2]].v; + ntlVec3Gfx a = p0-p1, b = p1-p2, c = p2-p0; + float l2a = normNoSqrt(a), l2b = normNoSqrt(b), l2c = normNoSqrt(c); + + ntlVec3Gfx facenormal = cross(a, b); + + mPoints[mIndices[i*3+0]].n += facenormal * (1.0f / (l2a * l2c)); + mPoints[mIndices[i*3+1]].n += facenormal * (1.0f / (l2b * l2a)); + mPoints[mIndices[i*3+2]].n += facenormal * (1.0f / (l2c * l2b)); + } + + for (i = 0; i < nv; i++) { + normalize(mPoints[i].n); + } + } +#else // RECALCNORMALS==1 + for (i = 0; i < (int)mPoints.size(); i++) { + normalize(mPoints[i].n); + } +#endif // RECALCNORMALS==1 + + //errMsg("SUBDIV","done nv:"< - - -//! shorten static const definitions -#define STCON static const - - -/*****************************************************************************/ -/*! class for solver templating - 3D implementation */ -//class LbmD3Q19 : public LbmSolverInterface { -class LbmD3Q19 { - - public: - - // constructor, init interface - LbmD3Q19() {}; - // virtual destructor - virtual ~LbmD3Q19() {}; - //! id string of solver - string getIdString() { return string("3D"); } - - //! how many dimensions? - STCON int cDimension; - - // Wi factors for collide step - STCON LbmFloat cCollenZero; - STCON LbmFloat cCollenOne; - STCON LbmFloat cCollenSqrtTwo; - - //! threshold value for filled/emptied cells - STCON LbmFloat cMagicNr2; - STCON LbmFloat cMagicNr2Neg; - STCON LbmFloat cMagicNr; - STCON LbmFloat cMagicNrNeg; - - //! size of a single set of distribution functions - STCON int cDfNum; - //! direction vector contain vecs for all spatial dirs, even if not used for LBM model - STCON int cDirNum; - - //! distribution functions directions - typedef enum { - cDirInv= -1, - cDirC = 0, - cDirN = 1, - cDirS = 2, - cDirE = 3, - cDirW = 4, - cDirT = 5, - cDirB = 6, - cDirNE = 7, - cDirNW = 8, - cDirSE = 9, - cDirSW = 10, - cDirNT = 11, - cDirNB = 12, - cDirST = 13, - cDirSB = 14, - cDirET = 15, - cDirEB = 16, - cDirWT = 17, - cDirWB = 18 - } dfDir; - - /* Vector Order 3D: - * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 - * 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 - * 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 - * 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 - */ - - /*! name of the dist. function - only for nicer output */ - STCON char* dfString[ 19 ]; - - /*! index of normal dist func, not used so far?... */ - STCON int dfNorm[ 19 ]; - - /*! index of inverse dist func, not fast, but useful... */ - STCON int dfInv[ 19 ]; - - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefX[ 19 ]; - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefY[ 19 ]; - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefZ[ 19 ]; - - /*! dist func vectors */ - STCON int dfVecX[ 27 ]; - STCON int dfVecY[ 27 ]; - STCON int dfVecZ[ 27 ]; - - /*! arrays as before with doubles */ - STCON LbmFloat dfDvecX[ 27 ]; - STCON LbmFloat dfDvecY[ 27 ]; - STCON LbmFloat dfDvecZ[ 27 ]; - - /*! principal directions */ - STCON int princDirX[ 2*3 ]; - STCON int princDirY[ 2*3 ]; - STCON int princDirZ[ 2*3 ]; - - /*! vector lengths */ - STCON LbmFloat dfLength[ 19 ]; - - /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ - static LbmFloat dfEquil[ 19 ]; - - /*! arrays for les model coefficients */ - static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ]; - static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ]; - -}; // LbmData3D - - - -/*****************************************************************************/ -//! class for solver templating - 2D implementation -//class LbmD2Q9 : public LbmSolverInterface { -class LbmD2Q9 { - - public: - - // constructor, init interface - LbmD2Q9() {}; - // virtual destructor - virtual ~LbmD2Q9() {}; - //! id string of solver - string getIdString() { return string("2D"); } - - //! how many dimensions? - STCON int cDimension; - - //! Wi factors for collide step - STCON LbmFloat cCollenZero; - STCON LbmFloat cCollenOne; - STCON LbmFloat cCollenSqrtTwo; - - //! threshold value for filled/emptied cells - STCON LbmFloat cMagicNr2; - STCON LbmFloat cMagicNr2Neg; - STCON LbmFloat cMagicNr; - STCON LbmFloat cMagicNrNeg; - - //! size of a single set of distribution functions - STCON int cDfNum; - STCON int cDirNum; - - //! distribution functions directions - typedef enum { - cDirInv= -1, - cDirC = 0, - cDirN = 1, - cDirS = 2, - cDirE = 3, - cDirW = 4, - cDirNE = 5, - cDirNW = 6, - cDirSE = 7, - cDirSW = 8 - } dfDir; - - /* Vector Order 2D: - * 0 1 2 3 4 5 6 7 8 - * 0, 0,0, 1,-1, 1,-1,1,-1 - * 0, 1,-1, 0,0, 1,1,-1,-1 */ - - /* name of the dist. function - only for nicer output */ - STCON char* dfString[ 9 ]; - - /* index of normal dist func, not used so far?... */ - STCON int dfNorm[ 9 ]; - - /* index of inverse dist func, not fast, but useful... */ - STCON int dfInv[ 9 ]; - - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefX[ 9 ]; - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefY[ 9 ]; - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefZ[ 9 ]; - - /* dist func vectors */ - STCON int dfVecX[ 9 ]; - STCON int dfVecY[ 9 ]; - /* Z, 2D values are all 0! */ - STCON int dfVecZ[ 9 ]; - - /* arrays as before with doubles */ - STCON LbmFloat dfDvecX[ 9 ]; - STCON LbmFloat dfDvecY[ 9 ]; - /* Z, 2D values are all 0! */ - STCON LbmFloat dfDvecZ[ 9 ]; - - /*! principal directions */ - STCON int princDirX[ 2*2 ]; - STCON int princDirY[ 2*2 ]; - STCON int princDirZ[ 2*2 ]; - - /* vector lengths */ - STCON LbmFloat dfLength[ 9 ]; - - /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ - static LbmFloat dfEquil[ 9 ]; - - /*! arrays for les model coefficients */ - static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ]; - static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ]; - -}; // LbmData3D - - - -// not needed hereafter -#undef STCON - - - -/*****************************************************************************/ -//! class for solver templating - lbgk (srt) model implementation -template -class LbmModelLBGK : public DQ , public LbmSolverInterface { - public: - - /*! type for cells contents, needed for cell id interface */ - typedef DQ LbmCellContents; - /*! type for cells */ - typedef LbmCellTemplate< LbmCellContents > LbmCell; - - // constructor - LbmModelLBGK() : DQ(), LbmSolverInterface() {}; - // virtual destructor - virtual ~LbmModelLBGK() {}; - //! id string of solver - string getIdString() { return DQ::getIdString() + string("lbgk]"); } - - /*! calculate length of velocity vector */ - static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) { - return ((ux)*DQ::dfDvecX[l]+(uy)*DQ::dfDvecY[l]+(uz)*DQ::dfDvecZ[l]); - }; - - /*! calculate equilibrium DF for given values */ - static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) { - LbmFloat tmp = getVelVecLen(l,ux,uy,uz); - return( DQ::dfLength[l] *( - + rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) - + 3.0 *tmp - + 9.0/2.0 *(tmp*tmp) ) - ); - }; - - - // input mux etc. as acceleration - // outputs rho,ux,uy,uz - /*inline void collideArrays_org(LbmFloat df[19], - LbmFloat &outrho, // out only! - // velocity modifiers (returns actual velocity!) - LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, - LbmFloat omega - ) { - LbmFloat rho=df[0]; - LbmFloat ux = mux; - LbmFloat uy = muy; - LbmFloat uz = muz; - for(int l=1; l0.0) { - LbmFloat Qo = getLesNoneqTensorCoeff(df,feq); - omegaNew = getLesOmega(omega,csmago,Qo); - } else { - omegaNew = omega; // smago off... - } - if(newOmegaRet) *newOmegaRet=omegaNew; // return value for stats - - for(int l=0; l LbmBGK2D; -typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D; - - -#define LBMHEADER_H -#endif - - - diff --git a/intern/elbeem/intern/lbmfsgrsolver.h b/intern/elbeem/intern/lbmfsgrsolver.h deleted file mode 100644 index 074522a9708..00000000000 --- a/intern/elbeem/intern/lbmfsgrsolver.h +++ /dev/null @@ -1,6602 +0,0 @@ -/****************************************************************************** - * - * El'Beem - the visual lattice boltzmann freesurface simulator - * All code distributed as part of El'Beem is covered by the version 2 of the - * GNU General Public License. See the file COPYING for details. - * Copyright 2003-2005 Nils Thuerey - * - * Combined 2D/3D Lattice Boltzmann standard solver classes - * - *****************************************************************************/ - - -#ifndef LBMFSGRSOLVER_H - -// blender interface -#if ELBEEM_BLENDER==1 -// warning - for MSVC this has to be included -// _before_ ntl_vector3dim -#include "SDL.h" -#include "SDL_thread.h" -#include "SDL_mutex.h" -extern "C" { - void simulateThreadIncreaseFrame(void); - extern SDL_mutex *globalBakeLock; - extern int globalBakeState; - extern int globalBakeFrame; -} -#endif // ELBEEM_BLENDER==1 - -#include "utilities.h" -#include "lbmdimensions.h" -#include "lbmfunctions.h" -#include "ntl_scene.h" -#include - -#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) -#include - #ifndef expf - #define expf exp - #endif -#endif - -#if PARALLEL==1 -#include -#endif // PARALLEL=1 -#ifndef PARALLEL -#define PARALLEL 0 -#endif // PARALLEL - - -#ifndef LBMMODEL_DEFINED -// force compiler error! -ERROR - define model first! -#endif // LBMMODEL_DEFINED - - -// general solver setting defines - -//! debug coordinate accesses and the like? (much slower) -#define FSGR_STRICT_DEBUG 0 - -//! debug coordinate accesses and the like? (much slower) -#define FSGR_OMEGA_DEBUG 0 - -//! OPT3D quick LES on/off, only debug/benachmarking -#define USE_LES 1 - -//! order of interpolation (1/2) -#define INTORDER 2 - -//! order of interpolation (0=always current/1=interpolate/2=always other) -//#define TIMEINTORDER 0 -// TODO remove interpol t param, also interTime - -//! refinement border method (1 = small border / 2 = larger) -#define REFINEMENTBORDER 1 - -// use optimized 3D code? -#if LBMDIM==2 -#define OPT3D false -#else -// determine with debugging... -# if FSGR_STRICT_DEBUG==1 -# define OPT3D false -# else // FSGR_STRICT_DEBUG==1 -// usually switch optimizations for 3d on, when not debugging -# define OPT3D true -// COMPRT -//# define OPT3D false -# endif // FSGR_STRICT_DEBUG==1 -#endif - -// enable/disable fine grid compression for finest level -#if LBMDIM==3 -#define COMPRESSGRIDS 1 -#else -#define COMPRESSGRIDS 0 -#endif - -//! threshold for level set fluid generation/isosurface -#define LS_FLUIDTHRESHOLD 0.5 - -//! invalid mass value for unused mass data -#define MASS_INVALID -1000.0 - -// empty/fill cells without fluid/empty NB's by inserting them into the full/empty lists? -#define FSGR_LISTTRICK true -#define FSGR_LISTTTHRESHEMPTY 0.10 -#define FSGR_LISTTTHRESHFULL 0.90 -#define FSGR_MAGICNR 0.025 -//0.04 - -//! maxmimum no. of grid levels -#define FSGR_MAXNOOFLEVELS 5 - -// helper for comparing floats with epsilon -#define GFX_FLOATNEQ(x,y) ( ABS((x)-(y)) > (VECTOR_EPSILON) ) -#define LBM_FLOATNEQ(x,y) ( ABS((x)-(y)) > (10.0*LBM_EPSILON) ) - - -// macros for loops over all DFs -#define FORDF0 for(int l= 0; l< LBM_DFNUM; ++l) -#define FORDF1 for(int l= 1; l< LBM_DFNUM; ++l) -// and with different loop var to prevent shadowing -#define FORDF0M for(int m= 0; m< LBM_DFNUM; ++m) -#define FORDF1M for(int m= 1; m< LBM_DFNUM; ++m) - -// aux. field indices (same for 2d) -#define dFfrac 19 -#define dMass 20 -#define dFlux 21 -// max. no. of cell values for 3d -#define dTotalNum 22 - -// iso value defines -// border for marching cubes -#define ISOCORR 3 - - -/*****************************************************************************/ -/*! cell access classes */ -template -class UniformFsgrCellIdentifier : - public CellIdentifierInterface -{ - public: - //! which grid level? - int level; - //! location in grid - int x,y,z; - - //! reset constructor - UniformFsgrCellIdentifier() : - x(0), y(0), z(0) { }; - - // implement CellIdentifierInterface - virtual string getAsString() { - std::ostringstream ret; - ret <<"{ i"<2) ret<<",k"< *cid = dynamic_cast *>( other ); - UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( other ); - if(!cid) return false; - if( x==cid->x && y==cid->y && z==cid->z && level==cid->level ) return true; - return false; - } -}; - -//! information needed for each level in the simulation -class FsgrLevelData { -public: - int id; // level number - - //! node size on this level (geometric, in world coordinates, not simulation units!) - LbmFloat nodeSize; - //! node size on this level in simulation units - LbmFloat simCellSize; - //! quadtree node relaxation parameter - LbmFloat omega; - //! size this level was advanced to - LbmFloat time; - //! size of a single lbm step in time units on this level - LbmFloat stepsize; - //! step count - int lsteps; - //! gravity force for this level - LbmVec gravity; - //! level array - LbmFloat *mprsCells[2]; - CellFlagType *mprsFlags[2]; - - //! smago params and precalculated values - LbmFloat lcsmago; - LbmFloat lcsmago_sqr; - LbmFloat lcnu; - - // LES statistics per level - double avgOmega; - double avgOmegaCnt; - - //! current set of dist funcs - int setCurr; - //! target/other set of dist funcs - int setOther; - - //! mass&volume for this level - LbmFloat lmass; - LbmFloat lvolume; - LbmFloat lcellfactor; - - //! local storage of mSizes - int lSizex, lSizey, lSizez; - int lOffsx, lOffsy, lOffsz; - -}; - - - -/*****************************************************************************/ -/*! class for solving a LBM problem */ -template -class LbmFsgrSolver : - public /*? virtual */ D // this means, the solver is a lbmData object and implements the lbmInterface -{ - - public: - //! Constructor - LbmFsgrSolver(); - //! Destructor - virtual ~LbmFsgrSolver(); - //! id string of solver - virtual string getIdString() { return string("FsgrSolver[") + D::getIdString(); } - - //! initilize variables fom attribute list - virtual void parseAttrList(); - //! Initialize omegas and forces on all levels (for init/timestep change) - void initLevelOmegas(); - //! finish the init with config file values (allocate arrays...) - virtual bool initialize( ntlTree* /*tree*/, vector* /*objects*/ ); - -#if LBM_USE_GUI==1 - //! show simulation info (implement SimulationObject pure virtual func) - virtual void debugDisplay(fluidDispSettings *set); -#endif - - - // implement CellIterator interface - typedef UniformFsgrCellIdentifier stdCellId; - virtual CellIdentifierInterface* getFirstCell( ); - virtual void advanceCell( CellIdentifierInterface* ); - virtual bool noEndCell( CellIdentifierInterface* ); - virtual void deleteCellIterator( CellIdentifierInterface** ); - virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos ); - virtual int getCellSet ( CellIdentifierInterface* ); - virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* ); - virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* ); - virtual int getCellLevel ( CellIdentifierInterface* ); - virtual LbmFloat getCellDensity ( CellIdentifierInterface* ,int set); - virtual LbmVec getCellVelocity ( CellIdentifierInterface* ,int set); - virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir); - virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set); - virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set); - virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set); - virtual LbmFloat getEquilDf ( int ); - virtual int getDfNum ( ); - // convert pointers - stdCellId* convertBaseCidToStdCid( CellIdentifierInterface* basecid); - - //! perform geometry init (if switched on) - bool initGeometryFlags(); - //! init part for all freesurface testcases - void initFreeSurfaces(); - //! init density gradient if enabled - void initStandingFluidGradient(); - - /*! init a given cell with flag, density, mass and equilibrium dist. funcs */ - inline void initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass); - inline void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel); - inline void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag); - - /*! perform a single LBM step */ - virtual void step() { stepMain(); } - void stepMain(); - void fineAdvance(); - void coarseAdvance(int lev); - void coarseCalculateFluxareas(int lev); - // coarsen a given level (returns true if sth. was changed) - bool performRefinement(int lev); - bool performCoarsening(int lev); - //void oarseInterpolateToFineSpaceTime(int lev,LbmFloat t); - void interpolateFineFromCoarse(int lev,LbmFloat t); - void coarseRestrictFromFine(int lev); - - /*! init particle positions */ - virtual int initParticles(ParticleTracer *partt); - /*! move all particles */ - virtual void advanceParticles(ParticleTracer *partt ); - - - /*! debug object display (used e.g. for preview surface) */ - virtual vector getDebugObjects(); - - //! access the fillfrac field (for viz) - inline float getFillFrac(int i, int j, int k); - - //! retrieve the fillfrac field ready to display - void getIsofieldWeighted(float *iso); - void getIsofield(float *iso){ return getIsofieldWeighted(iso); } - //! for raytracing, preprocess - void prepareVisualization( void ); - - // rt interface - void addDrop(bool active, float mx, float my); - void initDrop(float mx, float my); - void printCellStats(); - int checkGfxEndTime(); // {return 9;}; - //! get gfx geo setup id - int getGfxGeoSetup() { return mGfxGeoSetup; } - - /*! type for cells */ - typedef typename D::LbmCell LbmCell; - - protected: - - //! internal quick print function (for debugging) - void printLbmCell(int level, int i, int j, int k,int set); - // debugging use CellIterator interface to mark cell - void debugMarkCellCall(int level, int vi,int vj,int vk); - - void mainLoop(int lev); - void adaptTimestep(); - //! init mObjectSpeeds for current parametrization - void recalculateObjectSpeeds(); - //! flag reinit step - always works on finest grid! - void reinitFlags( int workSet ); - //! mass dist weights - LbmFloat getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l); - //! add point to mListNewInter list - inline void addToNewInterList( int ni, int nj, int nk ); - //! cell is interpolated from coarse level (inited into set, source sets are determined by t) - inline void interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet,bool markNbs); - - //! minimal and maximal z-coords (for 2D/3D loops) - int getForZMinBnd() { return 0; } - int getForZMin1() { - if(D::cDimension==2) return 0; - return 1; - } - - int getForZMaxBnd(int lev) { - if(D::cDimension==2) return 1; - return mLevel[lev].lSizez -0; - } - int getForZMax1(int lev) { - if(D::cDimension==2) return 1; - return mLevel[lev].lSizez -1; - } - - - // member vars - - //! mass calculated during streaming step - LbmFloat mCurrentMass; - LbmFloat mCurrentVolume; - LbmFloat mInitialMass; - - //! count problematic cases, that occured so far... - int mNumProblems; - - // average mlsups, count how many so far... - double mAvgMLSUPS; - double mAvgMLSUPSCnt; - - //! Mcubes object for surface reconstruction - IsoSurface *mpPreviewSurface; - float mSmoothSurface; - float mSmoothNormals; - - //! use time adaptivity? - bool mTimeAdap; - - //! output surface preview? if >0 yes, and use as reduzed size - int mOutputSurfacePreview; - LbmFloat mPreviewFactor; - //! fluid vol height - LbmFloat mFVHeight; - LbmFloat mFVArea; - bool mUpdateFVHeight; - - //! require some geo setup from the viz? - int mGfxGeoSetup; - //! force quit for gfx - LbmFloat mGfxEndTime; - //! smoother surface initialization? - int mInitSurfaceSmoothing; - - int mTimestepReduceLock; - int mTimeSwitchCounts; - //! total simulation time so far - LbmFloat mSimulationTime; - //! smallest and largest step size so far - LbmFloat mMinStepTime, mMaxStepTime; - //! track max. velocity - LbmFloat mMxvx, mMxvy, mMxvz, mMaxVlen; - - //! list of the cells to empty at the end of the step - vector mListEmpty; - //! list of the cells to make fluid at the end of the step - vector mListFull; - //! list of new interface cells to init - vector mListNewInter; - //! class for handling redist weights in reinit flag function - class lbmFloatSet { - public: - LbmFloat val[dTotalNum]; - LbmFloat numNbs; - }; - //! normalized vectors for all neighboring cell directions (for e.g. massdweight calc) - LbmVec mDvecNrm[27]; - - - //! debugging - bool checkSymmetry(string idstring); - //! symmetric init? - //bool mStartSymm; - //! kepp track of max/min no. of filled cells - int mMaxNoCells, mMinNoCells; -#ifndef USE_MSVC6FIXES - long long int mAvgNumUsedCells; -#else - _int64 mAvgNumUsedCells; -#endif - - //! for interactive - how to drop drops? - int mDropMode; - LbmFloat mDropSize; - LbmVec mDropSpeed; - //! dropping variables - bool mDropping; - LbmFloat mDropX, mDropY; - LbmFloat mDropHeight; - //! precalculated objects speeds for current parametrization - vector mObjectSpeeds; - - //! get isofield weights - int mIsoWeightMethod; - float mIsoWeight[27]; - - // grid coarsening vars - - /*! vector for the data for each level */ - FsgrLevelData mLevel[FSGR_MAXNOOFLEVELS]; - - /*! minimal and maximal refinement levels */ - int mMaxRefine; - - /*! df scale factors for level up/down */ - LbmFloat mDfScaleUp, mDfScaleDown; - - /*! precomputed cell area values */ - LbmFloat mFsgrCellArea[27]; - - /*! LES C_smago paramter for finest grid */ - float mInitialCsmago; - /*! LES stats for non OPT3D */ - LbmFloat mDebugOmegaRet; - - //! fluid stats - int mNumInterdCells; - int mNumInvIfCells; - int mNumInvIfTotal; - int mNumFsgrChanges; - - //! debug function to disable standing f init - int mDisableStandingFluidInit; - //! debug function to force tadap syncing - int mForceTadapRefine; - - - // strict debug interface -# if FSGR_STRICT_DEBUG==1 - int debLBMGI(int level, int ii,int ij,int ik, int is); - CellFlagType& debRFLAG(int level, int xx,int yy,int zz,int set); - CellFlagType& debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir); - CellFlagType& debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir); - int debLBMQI(int level, int ii,int ij,int ik, int is, int l); - LbmFloat& debQCELL(int level, int xx,int yy,int zz,int set,int l); - LbmFloat& debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l); - LbmFloat& debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l); - LbmFloat* debRACPNT(int level, int ii,int ij,int ik, int is ); - LbmFloat& debRAC(LbmFloat* s,int l); -# endif // FSGR_STRICT_DEBUG==1 -}; - - - -/*****************************************************************************/ -// relaxation_macros - - - -// cell mark debugging -#if FSGR_STRICT_DEBUG==10 -#define debugMarkCell(lev,x,y,z) \ - errMsg("debugMarkCell",D::mName<<" step: "<1.0)) {\ - errMsg("STREAMCHECK","Invalid streamed DF l"<2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\ - errMsg("COLLCHECK","Invalid collision values r:"<CmMaxVlen) { \ - CmMxvx = Cux; CmMxvy = Cuy; CmMxvz = Cuz; CmMaxVlen = Cusqr; \ - } /* stats */ - - - -// loops over _all_ cells (including boundary layer) -#define FSGR_FORIJK_BOUNDS(leveli) \ - for(int k= getForZMinBnd(); k< getForZMaxBnd(leveli); ++k) \ - for(int j=0;j -LbmFsgrSolver::LbmFsgrSolver() : - D(), - mCurrentMass(0.0), mCurrentVolume(0.0), - mNumProblems(0), - mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0), - mpPreviewSurface(NULL), - mSmoothSurface(0.0), mSmoothNormals(0.0), - mTimeAdap(false), - mOutputSurfacePreview(0), mPreviewFactor(0.25), - mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false), - mGfxGeoSetup(0), mGfxEndTime(-1.0), mInitSurfaceSmoothing(0), - mTimestepReduceLock(0), - mTimeSwitchCounts(0), - mSimulationTime(0.0), - mMinStepTime(0.0), mMaxStepTime(0.0), - mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0), - mDropMode(1), mDropSize(0.15), mDropSpeed(0.0), - mDropping(false), - mDropX(0.0), mDropY(0.0), mDropHeight(0.8), - mIsoWeightMethod(2), - mMaxRefine(1), - mDfScaleUp(-1.0), mDfScaleDown(-1.0), - mInitialCsmago(0.04), mDebugOmegaRet(0.0), - mNumInvIfTotal(0), mNumFsgrChanges(0), - mDisableStandingFluidInit(0), - mForceTadapRefine(-1) -{ - // not much to do here... - D::mpIso = new IsoSurface( D::mIsoValue, false ); - - // init equilibrium dist. func - LbmFloat rho=1.0; - FORDF0 { - D::dfEquil[l] = D::getCollideEq( l,rho, 0.0, 0.0, 0.0); - } - - // init LES - int odm = 0; - for(int m=0; m -void -LbmFsgrSolver::parseAttrList() -{ - LbmSolverInterface::parseStdAttrList(); - - string matIso("default"); - matIso = D::mpAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false ); - D::mpIso->setMaterialName( matIso ); - mOutputSurfacePreview = D::mpAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false ); - mTimeAdap = D::mpAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false ); - - mIsoWeightMethod= D::mpAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false ); - mInitSurfaceSmoothing = D::mpAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false ); - mSmoothSurface = D::mpAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); - mSmoothNormals = D::mpAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); - - mInitialCsmago = D::mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); - // deprecated! - float mInitialCsmagoCoarse = 0.0; - mInitialCsmagoCoarse = D::mpAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false ); -#if USE_LES==1 -#else // USE_LES==1 - debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2); - mInitialCsmago = 0.0; -#endif // USE_LES==1 - - // refinement - mMaxRefine = D::mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", true); - if(mMaxRefine<0) mMaxRefine=0; - if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1; - mDisableStandingFluidInit = D::mpAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false); - mForceTadapRefine = D::mpAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false); - - // demo mode settings - mDropMode = D::mpAttrs->readInt("dropmode", mDropMode, "SimulationLbm","mDropMode", false ); - mDropSize = D::mpAttrs->readFloat("dropsize", mDropSize, "SimulationLbm","mDropSize", false ); - mDropHeight = D::mpAttrs->readFloat("dropheight", mDropHeight, "SimulationLbm","mDropHeight", false ); - mDropSpeed = vec2L( D::mpAttrs->readVec3d("dropspeed", ntlVec3d(0.0), "SimulationLbm","mDropSpeed", false ) ); - if( (mDropMode>2) || (mDropMode<-1) ) mDropMode=1; - mGfxGeoSetup = D::mpAttrs->readInt("gfxgeosetup", mGfxGeoSetup, "SimulationLbm","mGfxGeoSetup", false ); - mGfxEndTime = D::mpAttrs->readFloat("gfxendtime", mGfxEndTime, "SimulationLbm","mGfxEndTime", false ); - mFVHeight = D::mpAttrs->readFloat("fvolheight", mFVHeight, "SimulationLbm","mFVHeight", false ); - mFVArea = D::mpAttrs->readFloat("fvolarea", mFVArea, "SimulationLbm","mFArea", false ); - -} - - -/****************************************************************************** - * Initialize omegas and forces on all levels (for init/timestep change) - *****************************************************************************/ -template -void -LbmFsgrSolver::initLevelOmegas() -{ - // no explicit settings - D::mOmega = D::mpParam->calculateOmega(); - D::mGravity = vec2L( D::mpParam->calculateGravity() ); - D::mSurfaceTension = D::mpParam->calculateSurfaceTension(); // unused - - if(mInitialCsmago<=0.0) { - if(OPT3D==1) { - errFatal("LbmFsgrSolver::initLevelOmegas","Csmago-LES = 0 not supported for optimized 3D version...",SIMWORLD_INITERROR); - return; - } - } - - // use Tau instead of Omega for calculations - { // init base level - int i = mMaxRefine; - mLevel[i].omega = D::mOmega; - mLevel[i].stepsize = D::mpParam->getStepTime(); - mLevel[i].lcsmago = mInitialCsmago; //CSMAGO_INITIAL; - mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; - mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); - } - - // init all sub levels - for(int i=mMaxRefine-1; i>=0; i--) { - //mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5; - double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5; - nomega = 1.0/nomega; - mLevel[i].omega = (LbmFloat)nomega; - mLevel[i].stepsize = 2.0 * mLevel[i+1].stepsize; - //mLevel[i].lcsmago = mLevel[i+1].lcsmago*mCsmagoRefineMultiplier; - //if(mLevel[i].lcsmago>1.0) mLevel[i].lcsmago = 1.0; - //if(strstr(D::getName().c_str(),"Debug")){ - //mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago; // DEBUG - // if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago * (LbmFloat)(mMaxRefine-i)*0.5+1.0; - //if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago * ((LbmFloat)(mMaxRefine-i)*1.0 + 1.0 ); - //if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = 0.99; - mLevel[i].lcsmago = mInitialCsmago; - mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; - mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); - } - - // for lbgk - mLevel[ mMaxRefine ].gravity = D::mGravity / mLevel[ mMaxRefine ].omega; - for(int i=mMaxRefine-1; i>=0; i--) { - // should be the same on all levels... - // for lbgk - mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega; - } - - // debug? invalidate old values... - D::mGravity = -100.0; - D::mOmega = -100.0; - - for(int i=0; i<=mMaxRefine; i++) { - if(!D::mSilent) { - errMsg("LbmFsgrSolver", "Level init "<0) { - mDfScaleUp = (mLevel[0 ].stepsize/mLevel[0+1].stepsize)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu - mDfScaleDown = (mLevel[0+1].stepsize/mLevel[0 ].stepsize)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu - } -} - - -/****************************************************************************** - * Init Solver (values should be read from config file) - *****************************************************************************/ -template -bool -LbmFsgrSolver::initialize( ntlTree* /*tree*/, vector* /*objects*/ ) -{ - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<maxGridSize) maxGridSize = D::mSizey; - if(D::mSizez>maxGridSize) maxGridSize = D::mSizez; - LbmFloat maxGeoSize = (D::mvGeoEnd[0]-D::mvGeoStart[0]); // get max size - if((D::mvGeoEnd[1]-D::mvGeoStart[1])>maxGridSize) maxGeoSize = (D::mvGeoEnd[1]-D::mvGeoStart[1]); - if((D::mvGeoEnd[2]-D::mvGeoStart[2])>maxGridSize) maxGeoSize = (D::mvGeoEnd[2]-D::mvGeoStart[2]); - // FIXME better divide max geo size by corresponding resolution rather than max? no prob for rx==ry==rz though - LbmFloat cellSize = (maxGeoSize / (LbmFloat)maxGridSize); - if(debugGridsizeInit) debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Start:"<setSize(D::mSizex, D::mSizey, D::mSizez); - - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<setSimulationMaxSpeed(0.0); - if(mFVHeight>0.0) D::mpParam->setFluidVolumeHeight(mFVHeight); - D::mpParam->setTadapLevels( mMaxRefine+1 ); - - if(mForceTadapRefine>mMaxRefine) { - D::mpParam->setTadapLevels( mForceTadapRefine+1 ); - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<calculateAllMissingValues()) { - errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR); - return false; - } - // recalc objects speeds in geo init - - - - // init vectors - //if(mMaxRefine >= FSGR_MAXNOOFLEVELS) { errFatal("LbmFsgrSolver::initializeLbmGridref"," error: Too many levels!", SIMWORLD_INITERROR); return false; } - for(int i=0; i<=mMaxRefine; i++) { - mLevel[i].id = i; - mLevel[i].nodeSize = 0.0; - mLevel[i].simCellSize = 0.0; - mLevel[i].omega = 0.0; - mLevel[i].time = 0.0; - mLevel[i].stepsize = 1.0; - mLevel[i].gravity = LbmVec(0.0); - mLevel[i].mprsCells[0] = NULL; - mLevel[i].mprsCells[1] = NULL; - mLevel[i].mprsFlags[0] = NULL; - mLevel[i].mprsFlags[1] = NULL; - - mLevel[i].avgOmega = 0.0; - mLevel[i].avgOmegaCnt = 0.0; - } - - // init sizes - mLevel[mMaxRefine].lSizex = D::mSizex; - mLevel[mMaxRefine].lSizey = D::mSizey; - mLevel[mMaxRefine].lSizez = D::mSizez; - for(int i=mMaxRefine-1; i>=0; i--) { - mLevel[i].lSizex = mLevel[i+1].lSizex/2; - mLevel[i].lSizey = mLevel[i+1].lSizey/2; - mLevel[i].lSizez = mLevel[i+1].lSizez/2; - /*if( ((mLevel[i].lSizex % 4) != 0) || ((mLevel[i].lSizey % 4) != 0) || ((mLevel[i].lSizez % 4) != 0) ) { - errMsg("LbmFsgrSolver","Init: error invalid sizes on level "<=0; i--) { - rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); - memCnt += sizeof(CellFlagType) * (rcellSize/dTotalNum +4) *2; - memCnt += sizeof(LbmFloat) * (rcellSize +4) *2; - } - double memd = memCnt; - char *sizeStr = ""; - const double sfac = 1000.0; - if(memd>sfac){ memd /= sfac; sizeStr="KB"; } - if(memd>sfac){ memd /= sfac; sizeStr="MB"; } - if(memd>sfac){ memd /= sfac; sizeStr="GB"; } - if(memd>sfac){ memd /= sfac; sizeStr="TB"; } - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Required Grid memory: "<< memd <<" "<< sizeStr<<" ",4); - } - - // safety check - if(sizeof(CellFlagType) != CellFlagTypeSize) { - errFatal("LbmFsgrSolver::initialize","Fatal Error: CellFlagType has wrong size! Is:"<getCellSize(); - mLevel[ mMaxRefine ].lcellfactor = 1.0; - unsigned long int rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); - // +4 for safety ? - mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - -#if COMPRESSGRIDS==0 - mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; - mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; -#else // COMPRESSGRIDS==0 - unsigned long int compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); - mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ]; - mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset; - //errMsg("CGD","rcs:"<=0; i--) { - mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize; - mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize; - mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac; - - if(D::cDimension==2){ mLevel[i].lSizez = 1; } // 2D - rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); - mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; - mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; - } - - // init sizes for _all_ levels - for(int i=mMaxRefine; i>=0; i--) { - mLevel[i].lOffsx = mLevel[i].lSizex; - mLevel[i].lOffsy = mLevel[i].lOffsx*mLevel[i].lSizey; - mLevel[i].lOffsz = mLevel[i].lOffsy*mLevel[i].lSizez; - mLevel[i].setCurr = 0; - mLevel[i].setOther = 1; - mLevel[i].lsteps = 0; - mLevel[i].lmass = 0.0; - mLevel[i].lvolume = 0.0; - } - - // calc omega, force for all levels - initLevelOmegas(); - mMinStepTime = D::mpParam->getStepTime(); - mMaxStepTime = D::mpParam->getStepTime(); - - // init isosurf - D::mpIso->setIsolevel( D::mIsoValue ); - // approximate feature size with mesh resolution - float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5; - D::mpIso->setSmoothSurface( mSmoothSurface * featureSize ); - D::mpIso->setSmoothNormals( mSmoothNormals * featureSize ); - - // init iso weight values mIsoWeightMethod - int wcnt = 0; - float totw = 0.0; - for(int ak=-1;ak<=1;ak++) - for(int aj=-1;aj<=1;aj++) - for(int ai=-1;ai<=1;ai++) { - switch(mIsoWeightMethod) { - case 1: // light smoothing - mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); - break; - case 2: // very light smoothing - mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); - mIsoWeight[wcnt] *= mIsoWeight[wcnt]; - break; - case 3: // no smoothing - if(ai==0 && aj==0 && ak==0) mIsoWeight[wcnt] = 1.0; - else mIsoWeight[wcnt] = 0.0; - break; - default: // strong smoothing (=0) - mIsoWeight[wcnt] = 1.0; - break; - } - totw += mIsoWeight[wcnt]; - wcnt++; - } - for(int i=0; i<27; i++) mIsoWeight[i] /= totw; - - LbmVec isostart = vec2L(D::mvGeoStart); - LbmVec isoend = vec2L(D::mvGeoEnd); - int twodOff = 0; // 2d slices - if(D::cDimension==2) { - LbmFloat sn,se; - sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; - se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; - isostart[2] = sn; - isoend[2] = se; - twodOff = 2; - } - //errMsg(" SETISO ", " "<setStart( vec2G(isostart) ); - D::mpIso->setEnd( vec2G(isoend) ); - LbmVec isodist = isoend-isostart; - D::mpIso->initializeIsosurface( D::mSizex+2, D::mSizey+2, D::mSizez+2+twodOff, vec2G(isodist) ); - for(int ak=0;akgetData(ai,aj,ak) = 0.0; } - - /* init array (set all invalid first) */ - for(int lev=0; lev<=mMaxRefine; lev++) { - FSGR_FORIJK_BOUNDS(lev) { - RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage - initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0); - } - } - - // init defaults - mAvgNumUsedCells = 0; - D::mFixMass= 0.0; - - /* init boundaries */ - debugOut("LbmFsgrSolver::initialize : Boundary init...",10); - - - // use the density init? - initGeometryFlags(); - D::initGenericTestCases(); - - // new - init noslip 1 everywhere... - // half fill boundary cells? - - for(int k=0;kcalculateCellSize(); - if(D::cDimension==2) cspv[2] = 1.0; - inmCellCnt = 1; - double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<=0; lev--) { - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<setMaterialName( mpPreviewSurface->getMaterialName() ); - mpPreviewSurface->setIsolevel( D::mIsoValue ); - // usually dont display for rendering - mpPreviewSurface->setVisible( false ); - - mpPreviewSurface->setStart( vec2G(isostart) ); - mpPreviewSurface->setEnd( vec2G(isoend) ); - LbmVec pisodist = isoend-isostart; - mpPreviewSurface->initializeIsosurface( (int)(mPreviewFactor*D::mSizex)+2, (int)(mPreviewFactor*D::mSizey)+2, (int)(mPreviewFactor*D::mSizez)+2, vec2G(pisodist) ); - //mpPreviewSurface->setName( D::getName() + "preview" ); - mpPreviewSurface->setName( "preview" ); - - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(mPreviewFactor*D::mSizex)<<","<<(mPreviewFactor*D::mSizey)<<","<<(mPreviewFactor*D::mSizez)<<" enabled",10); - } - -#if ELBEEM_BLENDER==1 - // make sure fill fracs are right for first surface generation - stepMain(); -#endif // ELBEEM_BLENDER==1 - - // prepare once... - prepareVisualization(); - // copy again for stats counting - for(int lev=0; lev<=mMaxRefine; lev++) { - FSGR_FORIJK_BOUNDS(lev) { - RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr); - } } // first copy flags */ - - /*{ int lev=mMaxRefine; - FSGR_FORIJK_BOUNDS(lev) { // COMPRT deb out - debMsgDirect("\n x="<calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); - D::mpParam->setSimulationMaxSpeed( norm(maxIniVel) + norm(mLevel[level].gravity) ); - LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxIniVel <<", allowed Max="<getSimulationMaxSpeed() > allowMax) { - // similar to adaptTimestep(); - LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed(); - LbmFloat newdt = D::mpParam->getStepTime() * (allowMax / nextmax); // newtr - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< D::mpParam->getStepTime() <<" ",5); - D::mpParam->setDesiredStepTime( newdt ); - D::mpParam->calculateAllMissingValues( D::mSilent ); - maxIniVel = vec2G( D::mpParam->calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxIniVel,5); - } - recalculateObjectSpeeds(); - - ntlVec3Gfx pos,iniPos; // position of current cell - LbmFloat rhomass = 0.0; - int savedNodes = 0; - int OId = -1; - gfxReal distance; - - // 2d display as rectangles - if(D::cDimension==2) { - dvec[2] = 0.0; - iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ))-(dvec*0.0); - //iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))+dvec; - } else { - iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0); - iniPos[2] = D::mvGeoStart[2] + dvec[2]*getForZMin1(); - } - - - // first init boundary conditions -#define GETPOS(i,j,k) \ - ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \ - iniPos[1]+ dvec[1]*(gfxReal)(j), \ - iniPos[2]+ dvec[2]*(gfxReal)(k) ) - for(int k= getForZMin1(); k< getForZMax1(level); ++k) { - for(int j=1;jgetGeoInitType() ){ - case FGI_MBNDINFLOW: - rhomass = 1.0; - ntype = CFFluid|CFMbndInflow; - break; - case FGI_MBNDOUTFLOW: - rhomass = 0.0; - ntype = CFEmpty|CFMbndOutflow; - break; - default: - rhomass = BND_FILL; - ntype = CFBnd; break; - } - } - if(ntype != CFInvalid) { - // initDefaultCell - if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { - ntype |= (OId<<24); - } - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - - // walk along x until hit for following inits - if(distance<=-1.0) { distance = 100.0; } - if(distance>0.0) { - gfxReal dcnt=dvec[0]; - while(( dcnt< distance )&&(i+10.0) { - gfxReal dcnt=dvec[0]; - while((dcnt< distance )&&(i+10 - - } - } - } // zmax - - D::freeGeoTree(); - myTime_t geotimeend = getTime(); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< ((geotimeend-geotimestart)/(double)1000.0)<<"s,"< -void -LbmFsgrSolver::initFreeSurfaces() { - double interfaceFill = 0.45; // filling level of interface cells - - // set interface cells - FSGR_FORIJK1(mMaxRefine) { - - /*if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFEmpty )) { - int initInter = 0; - // check for neighboring fluid cells - FORDF1 { - if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l), CFFluid ) ) { - initInter = 1; - } - } - - if(initInter) { - initEmptyCell(mMaxRefine, i,j,k, CFInter, 1.0, interfaceFill); - } - - } // empty cells OLD */ - - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid )) { - int initInter = 0; // check for neighboring empty cells - FORDF1 { - if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l), CFEmpty ) ) { - initInter = 1; - } - } - if(initInter) { - QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr, dMass) = - //QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setOther, dMass) = // COMPRT OFF - interfaceFill; - RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) = RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setOther) = CFInter; - } - } - } - - // remove invalid interface cells - FSGR_FORIJK1(mMaxRefine) { - // remove invalid interface cells - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { - int delit = 0; - int NBs = 0; // neighbor flags or'ed - int noEmptyNB = 1; - - FORDF1 { - if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l ), CFEmpty ) ) { - noEmptyNB = 0; - } - NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l); - } - - // remove cells with no fluid or interface neighbors - if((NBs & CFFluid)==0) { delit = 1; } - if((NBs & CFInter)==0) { delit = 1; } - - // remove cells with no empty neighbors - if(noEmptyNB) { delit = 2; } - - // now we can remove the cell - if(delit==1) { - initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0); - } - if(delit==2) { - initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); - } - } // interface - } - - // another brute force init, make sure the fill values are right... - // and make sure both sets are equal - for(int lev=0; lev<=mMaxRefine; lev++) { - FSGR_FORIJK_BOUNDS(lev) { - if( (RFLAG(lev, i,j,k,0) & (CFBnd)) ) { - QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = BND_FILL; - continue; - } - if( (RFLAG(lev, i,j,k,0) & (CFEmpty)) ) { - QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = 0.0; - continue; - } - } } - - // ---------------------------------------------------------------------- - // smoother surface... - if(mInitSurfaceSmoothing>0) { - debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing steps ",10); -#if COMPRESSGRIDS==1 - errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return; -#endif // COMPRESSGRIDS==0 - } - for(int s=0; s -void -LbmFsgrSolver::initStandingFluidGradient() { - // ---------------------------------------------------------------------- - // standing fluid preinit - const int debugStandingPreinit = 0; - int haveStandingFluid = 0; - -#define STANDFLAGCHECK(iindex) \ - if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || \ - ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ \ - if((iindex)>1) { haveStandingFluid=(iindex); } \ - j = mLevel[mMaxRefine].lSizey; i=mLevel[mMaxRefine].lSizex; k=D::getForZMaxBnd(); \ - continue; \ - } - int gravIndex[3] = {0,0,0}; - int gravDir[3] = {1,1,1}; - int maxGravComp = 1; // by default y - int gravComp1 = 0; // by default y - int gravComp2 = 2; // by default y - if( ABS(mLevel[mMaxRefine].gravity[0]) > ABS(mLevel[mMaxRefine].gravity[1]) ){ maxGravComp = 0; gravComp1=1; gravComp2=2; } - if( ABS(mLevel[mMaxRefine].gravity[2]) > ABS(mLevel[mMaxRefine].gravity[0]) ){ maxGravComp = 2; gravComp1=0; gravComp2=1; } - - int gravIMin[3] = { 0 , 0 , 0 }; - int gravIMax[3] = { - mLevel[mMaxRefine].lSizex + 0, - mLevel[mMaxRefine].lSizey + 0, - mLevel[mMaxRefine].lSizez + 0 }; - if(LBMDIM==2) gravIMax[2] = 1; - - //int gravDir = 1; - if( mLevel[mMaxRefine].gravity[maxGravComp] > 0.0 ) { - // swap directions - int i=maxGravComp; - int tmp = gravIMin[i]; - gravIMin[i] = gravIMax[i] - 1; - gravIMax[i] = tmp - 1; - gravDir[i] = -1; - } -#define PRINTGDIRS \ - errMsg("Standing fp","X start="<>2); // not much use...? - //preinitSteps = 4; // DEBUG!!!! - //D::mInitDone = 1; // GRAVTEST - //preinitSteps = 0; - debMsgNnl("Standing fluid preinit", DM_MSG, "Performing "< -void LbmFsgrSolver::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) { - CellFlagType pers = RFLAG(level,xx,yy,zz,set) & CFPersistMask; - RFLAG(level,xx,yy,zz,set) = newflag | pers; -} - -template -void -LbmFsgrSolver::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) { - /* init eq. dist funcs */ - LbmFloat *ecel; - int workSet = mLevel[level].setCurr; - - ecel = RACPNT(level, i,j,k, workSet); - FORDF0 { RAC(ecel, l) = D::dfEquil[l] * rho; } - RAC(ecel, dMass) = mass; - RAC(ecel, dFfrac) = mass/rho; - RAC(ecel, dFlux) = FLUX_INIT; - //RFLAG(level, i,j,k, workSet)= flag; - changeFlag(level, i,j,k, workSet, flag); - - workSet ^= 1; - changeFlag(level, i,j,k, workSet, flag); - return; -} - -template -void -LbmFsgrSolver::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) { - LbmFloat *ecel; - int workSet = mLevel[level].setCurr; - - ecel = RACPNT(level, i,j,k, workSet); - FORDF0 { RAC(ecel, l) = D::getCollideEq(l, rho,vel[0],vel[1],vel[2]); } - RAC(ecel, dMass) = mass; - RAC(ecel, dFfrac) = mass/rho; - RAC(ecel, dFlux) = FLUX_INIT; - //RFLAG(level, i,j,k, workSet) = flag; - changeFlag(level, i,j,k, workSet, flag); - - workSet ^= 1; - changeFlag(level, i,j,k, workSet, flag); - return; -} - -template -bool -LbmFsgrSolver::checkSymmetry(string idstring) -{ - bool erro = false; - bool symm = true; - int msgs = 0; - const int maxMsgs = 10; - const bool markCells = false; - - //for(int lev=0; lev<=mMaxRefine; lev++) { - { int lev = mMaxRefine; - - // no point if not symm. - if( (mLevel[lev].lSizex==mLevel[lev].lSizey) && (mLevel[lev].lSizex==mLevel[lev].lSizez)) { - // ok - } else { - return false; - } - - for(int s=0; s<2; s++) { - FSGR_FORIJK1(lev) { - if(i<(mLevel[lev].lSizex/2)) { - int inb = (mLevel[lev].lSizey-1-i); - - if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T - - if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true; - if(D::cDimension==2) { - if(msgs -vector LbmFsgrSolver::getDebugObjects() { - vector debo; - if(mOutputSurfacePreview) { - debo.push_back( mpPreviewSurface ); - } - return debo; -} - -/*****************************************************************************/ -/*! perform a single LBM step */ -/*****************************************************************************/ - -template -void -LbmFsgrSolver::stepMain() -{ -#if ELBEEM_BLENDER==1 - // update gui display - SDL_mutexP(globalBakeLock); - if(globalBakeState<0) { - // this means abort... cause panic - D::mPanic = 1; - errMsg("LbmFsgrSolver::step","Got abort signal from GUI, causing panic, aborting..."); - } - SDL_mutexV(globalBakeLock); -#endif // ELBEEM_BLENDER==1 - D::markedClearList(); // DMC clearMarkedCellsList - if(mDropping) { - initDrop(mDropX, mDropY); - } - if(mGfxGeoSetup==6) { - // xobs init hack - if(mSimulationTime<0.400) { - if((mSimulationTime>0.25) && (mSimulationTime<0.325)) { - // stop shortly... - mDropping = false; - } else { - initDrop(0.0, 1.0); - } - } else { - mDropping=false; - } - } - - // safety check, counter reset - D::mNumUsedCells = 0; - mNumInterdCells = 0; - mNumInvIfCells = 0; - - //debugOutNnl("LbmFsgrSolver::step : "<mMaxNoCells) mMaxNoCells = D::mNumUsedCells; - if(D::mNumUsedCells0)&&(mInitialMass>0.0)) { - LbmFloat mscale = mInitialMass/mCurrentMass; - - mscale = 1.0; - const LbmFloat dchh = 0.001; - if(mCurrentMassmInitialMass) mscale = 1.0-dchh; - - // use mass rescaling? - // with float precision this seems to be nonsense... - const bool MREnable = false; - - const int MSInter = 2; - static int mscount = 0; - if( (MREnable) && ((mLevel[0].lsteps%MSInter)== (MSInter-1)) && ( ABS( (mInitialMass/mCurrentMass)-1.0 ) > 0.01) && ( dsbits & (1<<(mMaxRefine-0)) ) ){ - // example: FORCE RESCALE MASS! ini:1843.5, cur:1817.6, f=1.01425 step:22153 levstep:5539 msc:37 - // mass rescale MASS RESCALE check - errMsg("MDTDD","\n\n"); - errMsg("MDTDD","FORCE RESCALE MASS! " - <<"ini:"<=0 ; lev--) { - //for(int workSet = 0; workSet<=1; workSet++) { - int wss = 0; - int wse = 1; -#if COMPRESSGRIDS==1 - if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; -#endif // COMPRESSGRIDS==1 - for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT - - FSGR_FORIJK1(lev) { - if( (RFLAG(lev,i,j,k, workSet) & (CFFluid| CFInter| CFGrFromCoarse| CFGrFromFine| CFGrNorm)) - ) { - - FORDF0 { QCELL(lev, i,j,k,workSet, l) *= mscale; } - QCELL(lev, i,j,k,workSet, dMass) *= mscale; - QCELL(lev, i,j,k,workSet, dFfrac) *= mscale; - - } else { - continue; - } - } - } - mLevel[lev].lmass *= mscale; - } - } - - mCurrentMass *= mscale; - }// if mass scale test */ - else { - // use current mass after full step for initial setting - if((mMaxRefine>0)&&(mInitialMass<=0.0) && (levsteps == (mMaxRefine+1))) { - mInitialMass = mCurrentMass; - debMsgStd("MDTDD",DM_NOTIFY,"Second Initial Mass Init: "< -void -LbmFsgrSolver::fineAdvance() -{ - // do the real thing... - mainLoop( mMaxRefine ); - if(mUpdateFVHeight) { - // warning assume -Y gravity... - mFVHeight = mCurrentMass*mFVArea/((LbmFloat)(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizez)); - if(mFVHeight<1.0) mFVHeight = 1.0; - D::mpParam->setFluidVolumeHeight(mFVHeight); - } - - // advance time before timestep change - mSimulationTime += D::mpParam->getStepTime(); - // time adaptivity - D::mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) ); - //if(mStartSymm) { checkSymmetry("step2"); } // DEBUG - if(!D::mSilent){ errMsg("fineAdvance"," stepped from "< -void -LbmFsgrSolver::mainLoop(int lev) -{ - // loops over _only inner_ cells ----------------------------------------------------------------------------------- - LbmFloat calcCurrentMass = 0.0; //mCurrentMass; - LbmFloat calcCurrentVolume = 0.0; //mCurrentVolume; - int calcCellsFilled = D::mNumFilledCells; - int calcCellsEmptied = D::mNumEmptiedCells; - int calcNumUsedCells = D::mNumUsedCells; - -#if PARALLEL==1 -#include "paraloop.h" -#else // PARALLEL==1 - { // main loop region - int kstart=D::getForZMin1(), kend=D::getForZMax1(); -#define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); -#endif // PARALLEL==1 - - - // local to loop - CellFlagType nbflag[LBM_DFNUM]; -#define NBFLAG(l) nbflag[(l)] - // */ - - LbmFloat *ccel = NULL; - LbmFloat *tcel = NULL; - int oldFlag; - int newFlag; - int nbored; - LbmFloat m[LBM_DFNUM]; - LbmFloat rho, ux, uy, uz, tmp, usqr; - LbmFloat mass, change; - usqr = tmp = 0.0; -#if OPT3D==true - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; -#endif // OPT3D==true - - - // ifempty cell conversion flags - bool iffilled, ifemptied; - int recons[LBM_DFNUM]; // reconstruct this DF? - int numRecons; // how many are reconstructed? - - - CellFlagType *pFlagSrc; - CellFlagType *pFlagDst; - pFlagSrc = &RFLAG(lev, 0,1, kstart,SRCS(lev)); // omp - pFlagDst = &RFLAG(lev, 0,1, kstart,TSET(lev)); // omp - ccel = RACPNT(lev, 0,1, kstart ,SRCS(lev)); // omp - tcel = RACPNT(lev, 0,1, kstart ,TSET(lev)); // omp - //CellFlagType *pFlagTar = NULL; - int pFlagTarOff; - if(mLevel[lev].setOther==1) pFlagTarOff = mLevel[lev].lOffsz; - else pFlagTarOff = -mLevel[lev].lOffsz; -#define ADVANCE_POINTERS(p) \ - ccel += (QCELLSTEP*(p)); \ - tcel += (QCELLSTEP*(p)); \ - pFlagSrc+= (p); \ - pFlagDst+= (p); \ - i+= (p); - - // nutshell outflow HACK - if(mGfxGeoSetup==2) { - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - {const int j=1; - for(int i=1;i>24; - if(!isValid) { - // make new if cell - const LbmVec vel(mObjectSpeeds[OId]); - // TODO add OPT3D treatment - FORDF0 { RAC(tcel, l) = D::getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } - RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; - RAC(tcel, dFlux) = FLUX_INIT; - changeFlag(lev, i,j,k, TSET(lev), CFInter); - calcCurrentMass += iniRho; calcCurrentVolume += 1.0; calcNumUsedCells++; - mInitialMass += iniRho; - // dont treat cell until next step - continue; - } - } - else // these are exclusive - if(oldFlag & (CFMbndOutflow)) { - //errMsg("OUTFLOW"," ar "<>24; - LbmFloat fluidRho = m[0]; FORDF1 { fluidRho += m[l]; } - mInitialMass -= fluidRho; - const LbmFloat iniRho = 0.0; - RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; - RAC(tcel, dFlux) = FLUX_INIT; - changeFlag(lev, i,j,k, TSET(lev), CFInter); - - // same as ifemptied for if below - LbmPoint emptyp; - emptyp.x = i; emptyp.y = j; emptyp.z = k; -#if PARALLEL==1 - calcListEmpty[id].push_back( emptyp ); -#else // PARALLEL==1 - mListEmpty.push_back( emptyp ); -#endif // PARALLEL==1 - calcCellsEmptied++; - continue; - } - } - - if(oldFlag & (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused)) { - *pFlagDst = oldFlag; - //RAC(tcel,dFfrac) = 0.0; - //RAC(tcel,dFlux) = FLUX_INIT; // necessary? - continue; - } - /*if( oldFlag & CFNoBndFluid ) { // TEST ME FASTER? - OPTIMIZED_STREAMCOLLIDE; PERFORM_USQRMAXCHECK; - RAC(tcel,dFfrac) = 1.0; - *pFlagDst = (CellFlagType)oldFlag; // newFlag; - calcCurrentMass += rho; calcCurrentVolume += 1.0; - calcNumUsedCells++; - continue; - }// TEST ME FASTER? */ - - // only neighbor flags! not own flag - nbored = 0; - -#if OPT3D==false - FORDF1 { - nbflag[l] = RFLAG_NB(lev, i,j,k,SRCS(lev),l); - nbored |= nbflag[l]; - } -#else - nbflag[dSB] = *(pFlagSrc + (-mLevel[lev].lOffsy+-mLevel[lev].lOffsx)); nbored |= nbflag[dSB]; - nbflag[dWB] = *(pFlagSrc + (-mLevel[lev].lOffsy+-1)); nbored |= nbflag[dWB]; - nbflag[ dB] = *(pFlagSrc + (-mLevel[lev].lOffsy)); nbored |= nbflag[dB]; - nbflag[dEB] = *(pFlagSrc + (-mLevel[lev].lOffsy+ 1)); nbored |= nbflag[dEB]; - nbflag[dNB] = *(pFlagSrc + (-mLevel[lev].lOffsy+ mLevel[lev].lOffsx)); nbored |= nbflag[dNB]; - - nbflag[dSW] = *(pFlagSrc + (-mLevel[lev].lOffsx+-1)); nbored |= nbflag[dSW]; - nbflag[ dS] = *(pFlagSrc + (-mLevel[lev].lOffsx)); nbored |= nbflag[dS]; - nbflag[dSE] = *(pFlagSrc + (-mLevel[lev].lOffsx+ 1)); nbored |= nbflag[dSE]; - - nbflag[ dW] = *(pFlagSrc + (-1)); nbored |= nbflag[dW]; - nbflag[ dE] = *(pFlagSrc + ( 1)); nbored |= nbflag[dE]; - - nbflag[dNW] = *(pFlagSrc + ( mLevel[lev].lOffsx+-1)); nbored |= nbflag[dNW]; - nbflag[ dN] = *(pFlagSrc + ( mLevel[lev].lOffsx)); nbored |= nbflag[dN]; - nbflag[dNE] = *(pFlagSrc + ( mLevel[lev].lOffsx+ 1)); nbored |= nbflag[dNE]; - - nbflag[dST] = *(pFlagSrc + ( mLevel[lev].lOffsy+-mLevel[lev].lOffsx)); nbored |= nbflag[dST]; - nbflag[dWT] = *(pFlagSrc + ( mLevel[lev].lOffsy+-1)); nbored |= nbflag[dWT]; - nbflag[ dT] = *(pFlagSrc + ( mLevel[lev].lOffsy)); nbored |= nbflag[dT]; - nbflag[dET] = *(pFlagSrc + ( mLevel[lev].lOffsy+ 1)); nbored |= nbflag[dET]; - nbflag[dNT] = *(pFlagSrc + ( mLevel[lev].lOffsy+ mLevel[lev].lOffsx)); nbored |= nbflag[dNT]; - // */ -#endif - - // pointer to destination cell - calcNumUsedCells++; - - // FLUID cells - if( oldFlag & CFFluid ) { - // only standard fluid cells (with nothing except fluid as nbs - - if(oldFlag&CFMbndInflow) { - // force velocity for inflow - const int OId = oldFlag>>24; - DEFAULT_STREAM; - //const LbmFloat fluidRho = 1.0; - // for submerged inflows, streaming would have to be performed... - LbmFloat fluidRho = m[0]; FORDF1 { fluidRho += m[l]; } - const LbmVec vel(mObjectSpeeds[OId]); - ux=vel[0], uy=vel[1], uz=vel[2]; - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); - FORDF0 { RAC(tcel, l) = D::getCollideEq(l, fluidRho,ux,uy,uz); } - } else { - if(nbored&CFBnd) { - DEFAULT_STREAM; - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - DEFAULT_COLLIDE; - oldFlag &= (~CFNoBndFluid); - } else { - // do standard stream/collide - OPTIMIZED_STREAMCOLLIDE; - // FIXME check for which cells this is executed! - oldFlag |= CFNoBndFluid; - } - } - - PERFORM_USQRMAXCHECK; - // "normal" fluid cells - RAC(tcel,dFfrac) = 1.0; - *pFlagDst = (CellFlagType)oldFlag; // newFlag; - LbmFloat ofrho=RAC(ccel,0); - for(int l=1; l just empty - change = - mynbfac*MYDF(l) ; goto changeDone; - } - break; - - case CFNoNbEmpty: - // we dont have empty nb's so... - switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { - case 0: - case CFNoNbFluid: - // we have no empty nb's -> just fill - change = nbnbfac*nbdf(l); goto changeDone; - } - break; - }} // inter-inter exchange - - // just do normal mass exchange... - change = ( nbnbfac*nbdf(l) - mynbfac*MYDF(l) ) ; - changeDone: ; - change *= ( myfrac + QCELL_NB(lev, i,j,k, SRCS(lev),l, dFfrac) ) * 0.5; - } // the other cell is interface - - // last alternative - reconstruction in this direction - else { - //if(NBFLAG(l) & CFEmpty) { recons[l] = true; } - recons[l] = 1; - numRecons++; - change = 0.0; - // which case is this...? empty + bnd - } - - // modify mass at SRCS - mass += change; - } // l - // normal interface, no if empty/fluid - - LbmFloat nv1,nv2; - LbmFloat nx,ny,nz; - - if(NBFLAG(dE) &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); } else nv1 = 0.0; - if(NBFLAG(dW) &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); } else nv2 = 0.0; - nx = 0.5* (nv2-nv1); - if(NBFLAG(dN) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[lev].lOffsx*QCELLSTEP)),dFfrac); } else nv1 = 0.0; - if(NBFLAG(dS) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[lev].lOffsx*QCELLSTEP)),dFfrac); } else nv2 = 0.0; - ny = 0.5* (nv2-nv1); -#if LBMDIM==3 - if(NBFLAG(dT) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[lev].lOffsy*QCELLSTEP)),dFfrac); } else nv1 = 0.0; - if(NBFLAG(dB) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[lev].lOffsy*QCELLSTEP)),dFfrac); } else nv2 = 0.0; - nz = 0.5* (nv2-nv1); -#else // LBMDIM==3 - nz = 0.0; -#endif // LBMDIM==3 - - if( (ABS(nx)+ABS(ny)+ABS(nz)) > LBM_EPSILON) { - // normal ok and usable... - FORDF1 { - if( (D::dfDvecX[l]*nx + D::dfDvecY[l]*ny + D::dfDvecZ[l]*nz) // dot Dvec,norml - > LBM_EPSILON) { - recons[l] = 2; - numRecons++; - } - } - } - - // calculate macroscopic cell values - LbmFloat oldUx, oldUy, oldUz; - LbmFloat oldRho; // OLD rho = ccel->rho; -#if OPT3D==false - oldRho=RAC(ccel,0); - oldUx = oldUy = oldUz = 0.0; - for(int l=1; l= (rho * (1.0+FSGR_MAGICNR)) ) { iffilled = 1; } - // interface cell if empty? - if( (mass) <= (rho * ( -FSGR_MAGICNR)) ) { ifemptied = 1; } - - if(oldFlag & (CFMbndOutflow)) { - mInitialMass -= mass; - mass = myfrac = 0.0; - iffilled = 0; ifemptied = 1; - } - - // looks much nicer... LISTTRICK -#if FSGR_LISTTRICK==true - if(!iffilled) { - // remove cells independent from amount of change... - if( (oldFlag & CFNoNbEmpty)&&(newFlag & CFNoNbEmpty)&& - ( (mass>(rho*FSGR_LISTTTHRESHFULL)) || ((nbored&CFInter)==0) ) - ) { - //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","filled "< better cell conversions - RAC(tcel,dFfrac) = (mass/rho); - - // init new flux value - float flux = 0.5*(float)(D::cDfNum); // dxqn on - //flux = 50.0; // extreme on - for(int nn=1; nnmMaxVlen) { - mMxvx = calcMxvx[i]; - mMxvy = calcMxvy[i]; - mMxvz = calcMxvz[i]; - mMaxVlen = calcMaxVlen[i]; - } - errMsg("PARALLELusqrcheck"," curr: "< -void -LbmFsgrSolver::coarseCalculateFluxareas(int lev) -{ - //LbmFloat calcCurrentMass = 0.0; - //LbmFloat calcCurrentVolume = 0.0; - //LbmFloat *ccel = NULL; - //LbmFloat *tcel = NULL; - //LbmFloat m[LBM_DFNUM]; - //LbmFloat rho, ux, uy, uz, tmp, usqr; -#if OPT3D==true - //LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; -#endif // OPT3D==true - //m[0] = tmp = usqr = 0.0; - - //for(int lev=0; lev -void -LbmFsgrSolver::coarseAdvance(int lev) -{ - LbmFloat calcCurrentMass = 0.0; - LbmFloat calcCurrentVolume = 0.0; - - LbmFloat *ccel = NULL; - LbmFloat *tcel = NULL; - LbmFloat m[LBM_DFNUM]; - LbmFloat rho, ux, uy, uz, tmp, usqr; -#if OPT3D==true - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; -#endif // OPT3D==true - m[0] = tmp = usqr = 0.0; - - coarseCalculateFluxareas(lev); - // copied from fineAdv. - CellFlagType *pFlagSrc = &RFLAG(lev, 1,1,getForZMin1(),SRCS(lev)); - CellFlagType *pFlagDst = &RFLAG(lev, 1,1,getForZMin1(),TSET(lev)); - pFlagSrc -= 1; - pFlagDst -= 1; - ccel = RACPNT(lev, 1,1,getForZMin1() ,SRCS(lev)); // QTEST - ccel -= QCELLSTEP; - tcel = RACPNT(lev, 1,1,getForZMin1() ,TSET(lev)); // QTEST - tcel -= QCELLSTEP; - //if(strstr(D::getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } - - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j remove - if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - bool invNb = false; - FORDF1 { - if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } - } - if(!invNb) { - *pFlagSrc = CFFluid|CFGrNorm; -#if ELBEEM_BLENDER!=1 - errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<0.0) { - const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feq); - omegaDst = D::getLesOmega(mLevel[lev ].omega,mLevel[lev ].lcsmago,Qo); - omegaSrc = D::getLesOmega(mLevel[lev+1].omega,mLevel[lev+1].lcsmago,Qo); - } else { - omegaDst = mLevel[lev+0].omega; /* NEWSMAGOT*/ - omegaSrc = mLevel[lev+1].omega; - } - dfScale = (mLevel[lev ].stepsize/mLevel[lev+1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); // yu - FORDF0{ - RAC(tcel, l) = feq[l]+ (df[l]-feq[l])*dfScale; - } -# else // OPT3D - // similar to OPTIMIZED_STREAMCOLLIDE_UNUSED - - //rho = ux = uy = uz = 0.0; - MSRC_C = CCELG_C(0) ; - MSRC_N = CCELG_N(0) ; - MSRC_S = CCELG_S(0) ; - MSRC_E = CCELG_E(0) ; - MSRC_W = CCELG_W(0) ; - MSRC_T = CCELG_T(0) ; - MSRC_B = CCELG_B(0) ; - MSRC_NE = CCELG_NE(0); - MSRC_NW = CCELG_NW(0); - MSRC_SE = CCELG_SE(0); - MSRC_SW = CCELG_SW(0); - MSRC_NT = CCELG_NT(0); - MSRC_NB = CCELG_NB(0); - MSRC_ST = CCELG_ST(0); - MSRC_SB = CCELG_SB(0); - MSRC_ET = CCELG_ET(0); - MSRC_EB = CCELG_EB(0); - MSRC_WT = CCELG_WT(0); - MSRC_WB = CCELG_WB(0); - for(int n=1;(n -bool -LbmFsgrSolver::performRefinement(int lev) { - if((lev<0) || ((lev+1)>mMaxRefine)) return false; - bool change = false; - //bool nbsok; - // FIXME remove TIMEINTORDER ? - LbmFloat interTime = 0.0; - // update curr from other, as streaming afterwards works on curr - // thus read only from srcSet, modify other - const int srcSet = mLevel[lev].setOther; - const int dstSet = mLevel[lev].setCurr; - const int srcFineSet = mLevel[lev+1].setCurr; - const bool debugRefinement = false; - - // use template functions for 2D/3D - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j remove - /*if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - bool invNb = false; - FORDF1 { - if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } - } - if(!invNb) { - *pFlagSrc = CFFluid|CFGrNorm; - errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "< remove - bool invNb = false; - bool fluidNb = false; - for(int l=1; l calculate normally from now on - RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - } // from advance */ - if(!fluidNb) { - // no fluid cells near -> no transfer necessary - RFLAG(lev, i,j,k, dstSet) = CFUnused; - //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFUnused; // FLAGTEST - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - } // from advance */ - - - // dont allow double transfer - // this might require fixing the neighborhood - if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse)) { - // dont turn CFGrFromFine above interface cells into CFGrNorm - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<0) RFLAG(lev-1, i/2,j/2,k/2, mLevel[lev-1].setCurr) &= (~CFGrToFine); // TODO add more of these? - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - for(int l=1; l -bool -LbmFsgrSolver::performCoarsening(int lev) { - //if(D::mInitDone){ errMsg("performCoarsening","skip"); return 0;} // DEBUG - - if((lev<0) || ((lev+1)>mMaxRefine)) return false; - bool change = false; - bool nbsok; - // hence work on modified curr set - const int srcSet = mLevel[lev].setCurr; - const int dstlev = lev+1; - const int dstFineSet = mLevel[dstlev].setCurr; - const bool debugCoarsening = false; - - // use template functions for 2D/3D - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j remove - // perform check from coarseAdvance here? - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - // remove from fine cells now that are completely in fluid - // FIXME? check that new from fine in performRefinement never get deleted here afterwards? - // or more general, one cell never changed more than once? - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - //const CellFlagType notNbAllowed = (CFInter|CFBnd|CFGrFromFine); unused - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - - nbsok = true; - for(int l=0; l from fine conversion - bool changeToFromFine = false; - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - -#if REFINEMENTBORDER==1 - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ - changeToFromFine=true; - } - /*if(strstr(D::getName().c_str(),"Debug")) - if((changeToFromFine)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l -void -LbmFsgrSolver::adaptTimestep() -{ - LbmFloat massTOld=0.0, massTNew=0.0; - LbmFloat volTOld=0.0, volTNew=0.0; - - bool rescale = false; // do any rescale at all? - LbmFloat scaleFac = -1.0; // timestep scaling - - LbmFloat levOldOmega[FSGR_MAXNOOFLEVELS]; - LbmFloat levOldStepsize[FSGR_MAXNOOFLEVELS]; - for(int lev=mMaxRefine; lev>=0 ; lev--) { - levOldOmega[lev] = mLevel[lev].omega; - levOldStepsize[lev] = mLevel[lev].stepsize; - } - //if(mTimeSwitchCounts>0){ errMsg("DEB CSKIP",""); return; } // DEBUG - - LbmFloat fac = 0.8; // modify time step by 20%, TODO? do multiple times for large changes? - LbmFloat diffPercent = 0.05; // dont scale if less than 5% - LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity - LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); - - //newdt = D::mpParam->getStepTime() * (allowMax/nextmax); - LbmFloat newdt = D::mpParam->getStepTime(); // newtr - if(nextmax>allowMax/fac) { - newdt = D::mpParam->getStepTime() * fac; - } else { - if(nextmaxgetStepTime() / fac; - } - } // newtr - //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<getMaxStepTime()<<" min"<getMinStepTime()<<" diff"<getStepTime() ) // DEBUG - LbmFloat rhoAvg = mCurrentMass/mCurrentVolume; - if( (newdt<=D::mpParam->getMaxStepTime()) && (newdt>=D::mpParam->getMinStepTime()) - && (dtdiff>(D::mpParam->getStepTime()*diffPercent)) ) { - if((newdt>levOldStepsize[mMaxRefine])&&(mTimestepReduceLock)) { - // wait some more... - //debMsgNnl("LbmFsgrSolver::TAdp",DM_NOTIFY," Delayed... "<setDesiredStepTime( newdt ); - rescale = true; - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"\n\n\n\n",10); - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<getSimulationMaxSpeed()<<" next:"<getStepTime(); - D::mpParam->setDesiredStepTime( newdt ); - } else - if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || - ((D::mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ - rescale = true; minCutoff = false; - newdt = D::mpParam->getStepTime()/tadtogSwitch ; - D::mpParam->setDesiredStepTime( newdt ); - } else { - rescale = false; minCutoff = false; - } - // */ - - // test mass rescale - - scaleFac = newdt/D::mpParam->getStepTime(); - if(rescale) { - // fixme - warum y, wird jetzt gemittelt... - mTimestepReduceLock = 4*(mLevel[mMaxRefine].lSizey+mLevel[mMaxRefine].lSizez+mLevel[mMaxRefine].lSizex)/3; - - mTimeSwitchCounts++; - D::mpParam->calculateAllMissingValues( D::mSilent ); - recalculateObjectSpeeds(); - // calc omega, force for all levels - initLevelOmegas(); - if(D::mpParam->getStepTime()getStepTime(); - if(D::mpParam->getStepTime()>mMaxStepTime) mMaxStepTime = D::mpParam->getStepTime(); - - for(int lev=mMaxRefine; lev>=0 ; lev--) { - LbmFloat newSteptime = mLevel[lev].stepsize; - LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); - - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<getCurrentGStar() , 10); - } - } // rescale? - - //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG - if(minCutoff) { - errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<=0 ; lev--) { - int rescs=0; - int wss = 0, wse = 1; -#if COMPRESSGRIDS==1 - if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; -#endif // COMPRESSGRIDS==1 - for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT - //for(int workSet = 0; workSet<=1; workSet++) { - FSGR_FORIJK1(lev) { - - //if( (RFLAG(lev, i,j,k, workSet) & CFFluid) || (RFLAG(lev, i,j,k, workSet) & CFInter) ) { - if( - (RFLAG(lev,i,j,k, workSet) & CFFluid) || - (RFLAG(lev,i,j,k, workSet) & CFInter) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || - (RFLAG(lev,i,j,k, workSet) & CFGrNorm) - ) { - // these cells have to be scaled... - } else { - continue; - } - - // collide on current set - LbmFloat rho, ux,uy,uz; - rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l (allowMax*allowMax) ) { - LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); - ux *= cfac; - uy *= cfac; - uz *= cfac; - for(int l=0; l0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } - debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"< -LbmFloat -LbmFsgrSolver::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l) { - //return 0.0; // test - int level = mMaxRefine; - LbmFloat *ccel = RACPNT(level, i,j,k, workSet); - - LbmFloat nx,ny,nz, nv1,nv2; - if(RFLAG_NB(level,i,j,k,workSet, dE) &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(level,i,j,k,workSet, dW) &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); } else nv2 = 0.0; - nx = 0.5* (nv2-nv1); - if(RFLAG_NB(level,i,j,k,workSet, dN) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(level,i,j,k,workSet, dS) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv2 = 0.0; - ny = 0.5* (nv2-nv1); -#if LBMDIM==3 - if(RFLAG_NB(level,i,j,k,workSet, dT) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(level,i,j,k,workSet, dB) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv2 = 0.0; - nz = 0.5* (nv2-nv1); -#else //LBMDIM==3 - nz = 0.0; -#endif //LBMDIM==3 - LbmFloat scal = mDvecNrm[l][0]*nx + mDvecNrm[l][1]*ny + mDvecNrm[l][2]*nz; - - LbmFloat ret = 1.0; - // forward direction, add mass (for filling cells): - if(dirForw) { - if(scal-LBM_EPSILON) ret = 0.0; - else ret = scal * -1.0; - } - //errMsg("massd", PRINT_IJK<<" nv"<0.0) && (!(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )&(CFInter|CFFluid|CFGrCoarseInited) ))) || \ - ((( (at))>0.0) && (!(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther)&(CFInter|CFFluid|CFGrCoarseInited) ))) ){ \ - errMsg("INVFLAGCINTCHECK", " l"<<(alev)<<" at:"<<(at)<<" "<10)&&(iy>5)&&(iz>5)) { debugMarkCell(lev+1, (ix),(iy),(iz) ); } -#define INTUNUTCHECK(ix,iy,iz) \ - if( (RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) != (CFFluid|CFGrFromCoarse)) ){\ - errMsg("INTFLAGUNU_CHECK", PRINT_VEC(i,j,k)<<" child not unused at l"<<(lev+1)<<" "< only current -// t=0.5 -> mix -// t=1.0 -> only other -#if OPT3D==false -#define ADD_INT_DFS(alev, ai,aj,ak, at, afac) \ - ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac); \ - FORDF0{ \ - LbmFloat df = ( \ - QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr , l)*(1.0-(at)) + \ - QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setOther, l)*( (at)) \ - ) ; \ - ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l); \ - df *= (afac); \ - rho += df; \ - ux += (D::dfDvecX[l]*df); \ - uy += (D::dfDvecY[l]*df); \ - uz += (D::dfDvecZ[l]*df); \ - intDf[l] += df; \ - } -// write interpolated dfs back to cell (correct non-eq. parts) -#define IDF_WRITEBACK_ \ - FORDF0{ \ - LbmFloat eq = D::getCollideEq(l, rho,ux,uy,uz);\ - QCELL(lev,i,j,k, dstSet, l) = (eq+ (intDf[l]-eq)*mDfScaleDown);\ - } \ - /* check that all values are ok */ \ - INTDEBOUT -#define IDF_WRITEBACK \ - LbmFloat omegaDst, omegaSrc;\ - /* smago new */ \ - LbmFloat feq[LBM_DFNUM]; \ - LbmFloat dfScale = mDfScaleDown; \ - FORDF0{ \ - feq[l] = D::getCollideEq(l, rho,ux,uy,uz); \ - } \ - if(mLevel[lev ].lcsmago>0.0) {\ - LbmFloat Qo = D::getLesNoneqTensorCoeff(intDf,feq); \ - omegaDst = D::getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \ - omegaSrc = D::getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \ - } else {\ - omegaDst = mLevel[lev+0].omega; \ - omegaSrc = mLevel[lev-1].omega;\ - } \ - \ - dfScale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \ - FORDF0{ \ - /*errMsg("SMAGO"," org"< -void LbmFsgrSolver::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { - //errMsg("INV DEBUG REINIT! off!",""); xit(1); // DEBUG quit - //if(markNbs) errMsg("interpolateCellFromCoarse"," l"< -void LbmFsgrSolver::reinitFlags( int workSet ) -{ - // OLD mods: - // add all to intel list? - // check ffrac for new cells - // new if cell inits (last loop) - // vweights handling - -#if ELBEEM_BLENDER==1 - const int debugFlagreinit = 0; -#else // ELBEEM_BLENDER==1 - const int debugFlagreinit = 0; -#endif // ELBEEM_BLENDER==1 - - // some things need to be read/modified on the other set - int otherSet = (workSet^1); - // fixed level on which to perform - int workLev = mMaxRefine; - - /* modify interface cells from lists */ - /* mark filled interface cells as fluid, or emptied as empty */ - /* count neighbors and distribute excess mass to interface neighbor cells - * problems arise when there are no interface neighbors anymore - * then just distribute to any fluid neighbors... - */ - - // for symmetry, first init all neighbor cells */ - for( vector::iterator iter=mListFull.begin(); - iter != mListFull.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if(debugFlagreinit) errMsg("FULL", PRINT_IJK<<" mss"<::iterator iter=mListEmpty.begin(); - iter != mListEmpty.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if((RFLAG(workLev,i,j,k, workSet)&(CFInter|CFNoDelete)) == (CFInter|CFNoDelete)) { - // remove entry - if(debugFlagreinit) errMsg("EMPT REMOVED!!!", PRINT_IJK<<" mss"< - let fill cells+surrounding interface cells have the higher importance */ - for( vector::iterator iter=mListEmpty.begin(); - iter != mListEmpty.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if((RFLAG(workLev,i,j,k, workSet)&(CFInter|CFNoDelete)) == (CFInter|CFNoDelete)){ errMsg("A"," ARGHARGRAG "); } // DEBUG - if(debugFlagreinit) errMsg("EMPT", PRINT_IJK<<" mss"<interface - //RFLAG(workLev,ni,nj,nk, workSet) = (CellFlagType)(CFInter); - changeFlag(workLev,ni,nj,nk, workSet, CFInter); - /* new mass = current density */ - LbmFloat nbrho = QCELL(workLev,ni,nj,nk, workSet, dC); - for(int rl=1; rl< D::cDfNum ; ++rl) { nbrho += QCELL(workLev,ni,nj,nk, workSet, rl); } - QCELL(workLev,ni,nj,nk, workSet, dMass) = nbrho; - QCELL(workLev,ni,nj,nk, workSet, dFfrac) = 1.0; - - // store point - addToNewInterList(ni,nj,nk); - } - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter){ - // test, also add to list... - addToNewInterList(ni,nj,nk); - } // NEW? - } - - /* for symmetry, set our flag right now */ - //RFLAG(workLev,i,j,k, workSet) = CFEmpty; - changeFlag(workLev,i,j,k, workSet, CFEmpty); - // mark cell not be changed mass... - not necessary, not in list anymore anyway! - } // emptylist - - - - // precompute weights to get rid of order dependancies - vector vWeights; - vWeights.reserve( mListFull.size() + mListEmpty.size() ); - int weightIndex = 0; - int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - LbmFloat nbTotWeights = 0.0; - for( vector::iterator iter=mListFull.begin(); - iter != mListFull.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - nbCount = 0; nbTotWeights = 0.0; - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { - nbCount++; - nbWeights[l] = getMassdWeight(1,i,j,k,workSet,l); - nbTotWeights += nbWeights[l]; - } else { - nbWeights[l] = -100.0; // DEBUG; - } - } - if(nbCount>0) { - //errMsg("FF I", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); - iter != mListEmpty.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - nbCount = 0; nbTotWeights = 0.0; - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { - nbCount++; - nbWeights[l] = getMassdWeight(0,i,j,k,workSet,l); - nbTotWeights += nbWeights[l]; - } else { - nbWeights[l] = -100.0; // DEBUG; - } - } - if(nbCount>0) { - //errMsg("EE I", PRINT_IJK<<" "<::iterator iter=mListFull.begin(); - iter != mListFull.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - - LbmFloat myrho = QCELL(workLev,i,j,k, workSet, dC); - FORDF1 { myrho += QCELL(workLev,i,j,k, workSet, l); } // QCELL.rho - - LbmFloat massChange = QCELL(workLev,i,j,k, workSet, dMass) - myrho; - /*int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { - nbCount++; - nbWeights[l] = vWeights[weightIndex].val[l]; - } else { - } - }*/ - - //errMsg("FDIST", PRINT_IJK<<" mss"<0.0) { - const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; - //errMsg("FF I", PRINT_IJK<<" "<0.0) { - //change = massChange * ( nbWeights[l]/nbTotWeightsp ); - change = massChange * ( vWeights[weightIndex].val[l]/nbTotWeightsp ); - } else { - change = (LbmFloat)(massChange/vWeights[weightIndex].numNbs); - } - QCELL(workLev,ni,nj,nk, workSet, dMass) += change; - } - } - massChange = 0.0; - } else { - // Problem! no interface neighbors - D::mFixMass += massChange; - //TTT mNumProblems++; - //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); - iter != mListEmpty.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - - LbmFloat massChange = QCELL(workLev, i,j,k, workSet, dMass); - /*int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { - nbCount++; - nbWeights[l] = vWeights[weightIndex].val[l]; - } else { - nbWeights[l] = -100.0; // DEBUG; - } - }*/ - - //errMsg("EDIST", PRINT_IJK<<" mss"<0) { - if(vWeights[weightIndex].numNbs>0.0) { - const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; - //errMsg("EE I", PRINT_IJK<<" "<0.0) { - change = massChange * ( vWeights[weightIndex].val[l]/nbTotWeightsp ); - } else { - change = (LbmFloat)(massChange/vWeights[weightIndex].numNbs); - } - QCELL(workLev, ni,nj,nk, workSet, dMass) += change; - } - } - massChange = 0.0; - } else { - // Problem! no interface neighbors - D::mFixMass += massChange; - //TTT mNumProblems++; - //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); - iter != mListEmpty.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - //RFLAG(workLev,i,j,k, otherSet) = CFEmpty; - changeFlag(workLev,i,j,k, otherSet, CFEmpty); - /*QCELL(workLev,i,j,k, otherSet, dMass) = 0.0; - QCELL(workLev,i,j,k, otherSet, dFfrac) = 0.0; // COMPRT OFF */ - } - - - // check if some of the new interface cells can be removed again - // never happens !!! not necessary - // calculate ffrac for new IF cells NEW - - // how many are really new interface cells? - int numNewIf = 0; - for( vector::iterator iter=mListNewInter.begin(); - iter != mListNewInter.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { - continue; - // FIXME remove from list? - } - numNewIf++; - } - - // redistribute mass, reinit flags - float newIfFac = 1.0/(LbmFloat)numNewIf; - for( vector::iterator iter=mListNewInter.begin(); - iter != mListNewInter.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { - //errMsg("???"," "<::iterator iter=mListNewInter.begin(); - iter != mListNewInter.end(); iter++ ) { - int i=iter->x, j=iter->y, k=iter->z; - if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { continue; } - - LbmFloat nrho = 0.0; - FORDF0 { nrho += QCELL(workLev, i,j,k, workSet, l); } - QCELL(workLev,i,j,k, workSet, dFfrac) = QCELL(workLev,i,j,k, workSet, dMass)/nrho; - QCELL(workLev,i,j,k, workSet, dFlux) = FLUX_INIT; - } - - if(mListNewInter.size()>0){ - //errMsg("FixMassDisted"," fm:"< -void LbmFsgrSolver::prepareVisualization( void ) { - int lev = mMaxRefine; - int workSet = mLevel[lev].setCurr; - - //make same prepareVisualization and getIsoSurface... -#if LBMDIM==2 - // 2d, place in the middle of isofield slice (k=2) -# define ZKD1 0 - // 2d z offset = 2, lbmGetData adds 1, so use one here -# define ZKOFF 1 - // reset all values... - for(int k= 0; k< 5; ++k) - for(int j=0;jlbmGetData(i,j,ZKOFF)=0.0; - } -#else // LBMDIM==2 - // 3d, use normal bounds -# define ZKD1 1 -# define ZKOFF k - // reset all values... - for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) - for(int j=0;jlbmGetData(i,j,ZKOFF)=0.0; - } -#endif // LBMDIM==2 - - - - // add up... - float val = 0.0; - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) - for(int j=1;jlbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[2] ); - - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[5] ); - - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[8] ); - - - *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[11] ); - - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF ) += ( val * mIsoWeight[14] ); - - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[17] ); - - - *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[20] ); - - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[23] ); - - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] ); - } - - // update preview, remove 2d? - if(mOutputSurfacePreview) { - //int previewSize = mOutputSurfacePreview; - int pvsx = (int)(mPreviewFactor*D::mSizex); - int pvsy = (int)(mPreviewFactor*D::mSizey); - int pvsz = (int)(mPreviewFactor*D::mSizez); - //float scale = (float)D::mSizex / previewSize; - LbmFloat scalex = (LbmFloat)D::mSizex/(LbmFloat)pvsx; - LbmFloat scaley = (LbmFloat)D::mSizey/(LbmFloat)pvsy; - LbmFloat scalez = (LbmFloat)D::mSizez/(LbmFloat)pvsz; - for(int k= 0; k< ((D::cDimension==3) ? (pvsz-1):1) ; ++k) - for(int j=0;j< pvsy;j++) - for(int i=0;i< pvsx;i++) { - *mpPreviewSurface->lbmGetData(i,j,k) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) ); - } - // set borders again... - for(int k= 0; k< ((D::cDimension == 3) ? (pvsz-1):1) ; ++k) { - for(int j=0;j< pvsy;j++) { - *mpPreviewSurface->lbmGetData(0,j,k) = *D::mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) ); - *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *D::mpIso->lbmGetData( D::mSizex-1, (int)(j*scaley), (int)(k*scalez) ); - } - for(int i=0;i< pvsx;i++) { - *mpPreviewSurface->lbmGetData(i,0,k) = *D::mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) ); - *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *D::mpIso->lbmGetData( (int)(i*scalex), D::mSizey-1, (int)(k*scalez) ); - } - } - if(D::cDimension == 3) { - // only for 3D - for(int j=0;jlbmGetData(i,j,0) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0); - *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , D::mSizez-1); - } - } // borders done... - } - - // correction - return; -} - - -/***************************************************************************** - * demo functions - *****************************************************************************/ - -template -float LbmFsgrSolver::getFillFrac(int i, int j, int k) { - return QCELL(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther, dFfrac); -} - -template -void LbmFsgrSolver::getIsofieldWeighted(float *iso) { - //errMsg("XxxX", " "<<( szx+ISOCORR) ); - float val; - int szx = mLevel[mMaxRefine].lSizex; - int szy = mLevel[mMaxRefine].lSizey; - int szz = mLevel[mMaxRefine].lSizez; - int oz = (szx+ISOCORR)*(szy+ISOCORR); - int oy = (szx+ISOCORR); - //int wcnt = 0; - - // reset all values... - const LbmFloat initVal = -0.42; - for(int i=0;i<(szz+ISOCORR)*(szy+ISOCORR)*(szx+ISOCORR);i++) { - iso[i] = initVal; - } - - // add up... - FSGR_FORIJK1(mMaxRefine) { - if(RFLAG(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther)&CFFluid) { - val = 1.0; ///27.0; - } else - //if(RFLAG(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther)&CFBnd) { - //continue; - //val = initVal + 0.05; - //val = (initVal + 0.05) * -1.0; - //} else - if(RFLAG(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther)&CFInter) { - val = (QCELL(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther, dFfrac)); // (1.0/27.0); - } else { - // bnd, empty, etc... - continue; - } - - /* - // */ - - const int index =((k)+1)*oz + ((j)+1)*oy + (i)+1; - iso[ index -oz -oy -1 ] += ( val * mIsoWeight[0] ); - iso[ index -oz -oy ] += ( val * mIsoWeight[1] ); - iso[ index -oz -oy +1 ] += ( val * mIsoWeight[2] ); - - iso[ index -oz -1 ] += ( val * mIsoWeight[3] ); - iso[ index -oz ] += ( val * mIsoWeight[4] ); - iso[ index -oz +1 ] += ( val * mIsoWeight[5] ); - - iso[ index -oz +oy -1 ] += ( val * mIsoWeight[6] ); - iso[ index -oz +oy ] += ( val * mIsoWeight[7] ); - iso[ index -oz +oy +1 ] += ( val * mIsoWeight[8] ); - - - iso[ index -oy -1 ] += ( val * mIsoWeight[9] ); - iso[ index -oy ] += ( val * mIsoWeight[10] ); - iso[ index -oy +1 ] += ( val * mIsoWeight[11] ); - - iso[ index -1 ] += ( val * mIsoWeight[12] ); - iso[ index ] += ( val * mIsoWeight[13] ); - iso[ index +1 ] += ( val * mIsoWeight[14] ); - - iso[ index +oy -1 ] += ( val * mIsoWeight[15] ); - iso[ index +oy ] += ( val * mIsoWeight[16] ); - iso[ index +oy +1 ] += ( val * mIsoWeight[17] ); - - - iso[ index +oz -oy -1 ] += ( val * mIsoWeight[18] ); - iso[ index +oz -oy ] += ( val * mIsoWeight[19] ); - iso[ index +oz -oy +1 ] += ( val * mIsoWeight[20] ); - - iso[ index +oz -1 ] += ( val * mIsoWeight[21] ); - iso[ index +oz ] += ( val * mIsoWeight[22] ); - iso[ index +oz +1 ] += ( val * mIsoWeight[23] ); - - iso[ index +oz +oy -1 ] += ( val * mIsoWeight[24] ); - iso[ index +oz +oy ] += ( val * mIsoWeight[25] ); - iso[ index +oz +oy +1 ] += ( val * mIsoWeight[26] ); - } - - return; -} - -template -void LbmFsgrSolver::addDrop(bool active, float mx, float my) { - mDropping = active; - mDropX = mx; - mDropY = my; -} - -template -void LbmFsgrSolver::initDrop(float mx, float my) { - // invert for convenience - mx = 1.0-mx; - int workSet = mLevel[mMaxRefine].setCurr; - - int px = (int)(mLevel[mMaxRefine].lSizex * mx); - int py = (int)(mLevel[mMaxRefine].lSizey * mDropHeight); - int pz = (int)(mLevel[mMaxRefine].lSizez * my); - int rad = (int)(mDropSize*mLevel[mMaxRefine].lSizex) + 1; - //errMsg("Rad", " "<=mLevel[mMaxRefine].lSizex-1 ) px = mLevel[mMaxRefine].lSizex-offset-rad-1; - if( (py-rad)<=offset ) py = rad + offset; - if( (py+rad)>=mLevel[mMaxRefine].lSizey-1 ) py = mLevel[mMaxRefine].lSizey-offset-rad-1; - if( (pz-rad)<=offset ) pz = rad + offset; - if( (pz+rad)>=mLevel[mMaxRefine].lSizez-1 ) pz = mLevel[mMaxRefine].lSizez-offset-rad-1; - - mUpdateFVHeight=true; - //errMsg("T", " \n\n\n"< (float)(rad*rad) ) continue; - LbmFloat fill = forceFill; //rad - sqrt(dx*dx+dz*dz); - - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFFluid)) { - } else if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFInter)) { - if(QCELL(mMaxRefine, i,j,k,workSet, dMass) < 0.75) { - initVelocityCell(mMaxRefine, i,j,k, CFInter, 1.0, fill, mDropSpeed); - } - } else if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFEmpty)) { - initVelocityCell(mMaxRefine, i,j,k, CFInter, 1.0, fill, mDropSpeed); - } else { - } - - } - } - } - - // stream - continue dropping - return; - - } else - if( (mDropMode==1) || (mDropMode==2) ) { - mDropping = false; - - // mode 2 - only single drops - if(mDropMode==2) { - for(int k= pz-rad-offset; k<= pz+rad+offset; k++) - for(int j= py-rad-offset; j<= py+rad+offset; j++) - for(int i= px-rad-offset; i<= px+rad+offset; i++) { - // make sure no fluid cells near... - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFBnd)) continue; - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFEmpty)) continue; - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFInter)) continue; - return; - } - } - - // single drops - for(int k= pz-rad-offset; k<= pz+rad+offset; k++) - for(int j= py-rad-offset; j<= py+rad+offset; j++) - for(int i= px-rad-offset; i<= px+rad+offset; i++) { - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFBnd)) continue; - float dz = pz-k; - float dy = py-j; - float dx = px-i; - if( dx*dx+dy*dy+dz*dz > (float)(rad*rad) ) { - if(mDropMode==1) { - // overwrite everything... - initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 0.0, 0.0); - } - continue; - } - LbmFloat fill = rad - sqrt(dx*dx+dy*dy+dz*dz); - if(fill > 1.0) fill = 1.0; - - initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, fill); - } - - for(int k= pz-rad-offset-1; k<= pz+rad+offset+1; k++) - for(int j= py-rad-offset-1; j<= py+rad+offset+1; j++) - for(int i= px-rad-offset-1; i<= px+rad+offset+1; i++) { - if(i<1) continue; - if(i>=(mLevel[mMaxRefine].lSizex-2) ) continue; - if(j<1) continue; - if(j>=(mLevel[mMaxRefine].lSizey-2) ) continue; - if(k<1) continue; - if(k>=(mLevel[mMaxRefine].lSizez-2) ) continue; - if(RFLAG(mMaxRefine, i,j,k,workSet)&(CFBnd)) continue; - - if( (RFLAG(mMaxRefine, i,j,k,workSet )&(CFFluid)) ) { - bool emptyNb = false; - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if(RFLAG(mMaxRefine, ni,nj,nk, workSet) & CFEmpty ){ - emptyNb = true; - } - } - if(emptyNb) { - RFLAG(mMaxRefine, i,j,k,workSet ) = CFInter; - } - } - } - } // single drop -} - - //! avg. used cell count stats -template -void LbmFsgrSolver::printCellStats() { - debMsgStd("CellStats", DM_NOTIFY, "Min:"< -int LbmFsgrSolver::checkGfxEndTime() { - //errMsg("LbmFsgrSolver","GfxEndTime "<0.0) && (mSimulationTime>mGfxEndTime)) { - errMsg("LbmFsgrSolver","GfxEndTime "< -void LbmFsgrSolver::advanceParticles(ParticleTracer *partt ) { - partt = NULL; // remove warning -} - - -/****************************************************************************** - * reset particle positions to default - *****************************************************************************/ -/*! init particle positions */ -template -int LbmFsgrSolver::initParticles(ParticleTracer *partt) { - partt = NULL; // remove warning - return 0; -} - - -/*! init particle positions */ -template -void LbmFsgrSolver::recalculateObjectSpeeds() { - int numobjs = (int)(D::mpGiObjects->size()); - if(numobjs>255) { - errFatal("LbmFsgrSolver::recalculateObjectSpeeds","More than 256 objects currently not supported...",SIMWORLD_INITERROR); - return; - } - mObjectSpeeds.resize(numobjs+0); - for(int i=0; i<(int)(numobjs+0); i++) { - mObjectSpeeds[i] = vec2L(D::mpParam->calculateLattVelocityFromRw( vec2P( (*D::mpGiObjects)[i]->getInitialVelocity() ))); - //errMsg("recalculateObjectSpeeds","id"<getInitialVelocity() )); - } -} - -/*****************************************************************************/ -/*! internal quick print function (for debugging) */ -/*****************************************************************************/ -template -void -LbmFsgrSolver::printLbmCell(int level, int i, int j, int k, int set) { - stdCellId *newcid = new stdCellId; - newcid->level = level; - newcid->x = i; - newcid->y = j; - newcid->z = k; - - // this function is not called upon clicking, then its from setMouseClick - ::debugPrintNodeInfo< LbmFsgrSolver >( this, newcid, D::mNodeInfoString, set ); - - delete newcid; -} -template -void -LbmFsgrSolver::debugMarkCellCall(int level, int vi,int vj,int vk) { - stdCellId *newcid = new stdCellId; - newcid->level = level; - newcid->x = vi; - newcid->y = vj; - newcid->z = vk; - addCellToMarkedList( newcid ); -} - - -/*****************************************************************************/ -// implement CellIterator interface -/*****************************************************************************/ - - - -// values from guiflkt.cpp -extern double guiRoiSX, guiRoiSY, guiRoiSZ, guiRoiEX, guiRoiEY, guiRoiEZ; -extern int guiRoiMaxLev, guiRoiMinLev; -#define CID_SX (int)( (mLevel[cid->level].lSizex-1) * guiRoiSX ) -#define CID_SY (int)( (mLevel[cid->level].lSizey-1) * guiRoiSY ) -#define CID_SZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiSZ ) - -#define CID_EX (int)( (mLevel[cid->level].lSizex-1) * guiRoiEX ) -#define CID_EY (int)( (mLevel[cid->level].lSizey-1) * guiRoiEY ) -#define CID_EZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiEZ ) - -template -CellIdentifierInterface* -LbmFsgrSolver::getFirstCell( ) { - int level = mMaxRefine; - -#if LBMDIM==3 - if(mMaxRefine>0) { level = mMaxRefine-1; } // NO1HIGHESTLEV DEBUG -#endif - level = guiRoiMaxLev; - if(level>mMaxRefine) level = mMaxRefine; - - //errMsg("LbmFsgrSolver::getFirstCell","Celliteration started..."); - stdCellId *cid = new stdCellId; - cid->level = level; - cid->x = CID_SX; - cid->y = CID_SY; - cid->z = CID_SZ; - return cid; -} - -template -typename LbmFsgrSolver::stdCellId* -LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { - //stdCellId *cid = dynamic_cast( basecid ); - stdCellId *cid = (stdCellId*)( basecid ); - return cid; -} - -template -void -LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - if(cid->getEnd()) return; - - //debugOut(" ADb "<x<<","<y<<","<z<<" e"<getEnd(), 10); - cid->x++; - if(cid->x > CID_EX){ cid->x = CID_SX; cid->y++; - if(cid->y > CID_EY){ cid->y = CID_SY; cid->z++; - if(cid->z > CID_EZ){ - cid->level--; - cid->x = CID_SX; - cid->y = CID_SY; - cid->z = CID_SZ; - if(cid->level < guiRoiMinLev) { - cid->level = guiRoiMaxLev; - cid->setEnd( true ); - } - } - } - } - //debugOut(" ADa "<x<<","<y<<","<z<<" e"<getEnd(), 10); -} - -template -bool -LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return (!cid->getEnd()); -} - -template -void -LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { - delete *cid; - *cid = NULL; -} - -template -CellIdentifierInterface* -LbmFsgrSolver::getCellAt( ntlVec3Gfx pos ) { - //int cellok = false; - pos -= (D::mvGeoStart); - - LbmFloat mmaxsize = mLevel[mMaxRefine].nodeSize; - for(int level=mMaxRefine; level>=0; level--) { // finest first - //for(int level=0; level<=mMaxRefine; level++) { // coarsest first - LbmFloat nsize = mLevel[level].nodeSize; - int x,y,z; - //LbmFloat nsize = getCellSize(NULL)[0]*2.0; - x = (int)((pos[0]-0.5*mmaxsize) / nsize ); - y = (int)((pos[1]-0.5*mmaxsize) / nsize ); - z = (int)((pos[2]-0.5*mmaxsize) / nsize ); - if(D::cDimension==2) z = 0; - - // double check... - //int level = mMaxRefine; - if(x<0) continue; - if(y<0) continue; - if(z<0) continue; - if(x>=mLevel[level].lSizex) continue; - if(y>=mLevel[level].lSizey) continue; - if(z>=mLevel[level].lSizez) continue; - - /*if( (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFFluid|CFInter)) ){ - // ok... - } else { - // comment out to always retrieve finest cells ( not working ) - continue; - } - // O */ - - // only return fluid/if cells - /*if( (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused|CFGrFromFine|CFGrFromCoarse)) ){ - continue; - } // */ - - // return fluid/if/border cells - if( ( (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused)) ) || - ( (levellevel = level; - newcid->x = x; - newcid->y = y; - newcid->z = z; - //errMsg("cellAt",D::mName<<" "< -int -LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return mLevel[cid->level].setCurr; - //return mLevel[cid->level].setOther; -} - -template -int -LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return cid->level; -} - -template -ntlVec3Gfx -LbmFsgrSolver::getCellOrigin ( CellIdentifierInterface* basecid) { - ntlVec3Gfx ret; - - stdCellId *cid = convertBaseCidToStdCid(basecid); - ntlVec3Gfx cs( mLevel[cid->level].nodeSize ); - if(D::cDimension==2) { cs[2] = 0.0; } - - if(D::cDimension==2) { - ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ) - + ntlVec3Gfx(0.0,0.0,cs[1]*-0.25)*cid->level ) - +getCellSize(basecid); - } else { - ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], cid->z *cs[2] )) - +getCellSize(basecid); - } - return (ret); -} - -template -ntlVec3Gfx -LbmFsgrSolver::getCellSize ( CellIdentifierInterface* basecid) { - // return half size - stdCellId *cid = convertBaseCidToStdCid(basecid); - ntlVec3Gfx retvec( mLevel[cid->level].nodeSize * 0.5 ); - // 2d display as rectangles - if(D::cDimension==2) { retvec[2] = 0.0; } - return (retvec); -} - -template -LbmFloat -LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - - LbmFloat rho = 0.0; - FORDF0 { - rho += QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - } - return ((rho-1.0) * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize) +1.0; // normal - //return ((rho-1.0) * D::mpParam->getCellSize() / D::mpParam->getStepTime()) +1.0; -} - -template -LbmVec -LbmFsgrSolver::getCellVelocity ( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - - LbmFloat ux,uy,uz; - ux=uy=uz= 0.0; - FORDF0 { - ux += D::dfDvecX[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - uy += D::dfDvecY[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - uz += D::dfDvecZ[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - } - LbmVec vel(ux,uy,uz); - // TODO fix... - return (vel * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize * D::mDebugVelScale); // normal -} - -template -LbmFloat -LbmFsgrSolver::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); -} -template -LbmFloat -LbmFsgrSolver::getCellMass( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); -} -template -LbmFloat -LbmFsgrSolver::getCellFill( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); - if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFFluid) return 1.0; - return 0.0; - //return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); -} -template -CellFlagType -LbmFsgrSolver::getCellFlag( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return RFLAG(cid->level, cid->x,cid->y,cid->z, set); -} - -template -LbmFloat -LbmFsgrSolver::getEquilDf( int l ) { - return D::dfEquil[l]; -} - -template -int -LbmFsgrSolver::getDfNum( ) { - return D::cDfNum; -} - -#if LBM_USE_GUI==1 -//! show simulation info (implement SimulationObject pure virtual func) -template -void -LbmFsgrSolver::debugDisplay(fluidDispSettings *set){ - lbmDebugDisplay< LbmFsgrSolver >( set, this ); -} -#endif - -/*****************************************************************************/ -// strict debugging functions -/*****************************************************************************/ -#if FSGR_STRICT_DEBUG==1 -#define STRICT_EXIT *((int *)0)=0; - -template -int LbmFsgrSolver::debLBMGI(int level, int ii,int ij,int ik, int is) { - if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"< mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<1){ errMsg("LbmStrict"," invS+ l"< -CellFlagType& LbmFsgrSolver::debRFLAG(int level, int xx,int yy,int zz,int set){ - return _RFLAG(level, xx,yy,zz,set); -}; - -template -CellFlagType& LbmFsgrSolver::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"< -CellFlagType& LbmFsgrSolver::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"< -int LbmFsgrSolver::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { - if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"< mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<1){ errMsg("LbmStrict"," invS+ l"<D::cDfNum){ // dFfrac is an exception - if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"< -LbmFloat& LbmFsgrSolver::debQCELL(int level, int xx,int yy,int zz,int set,int l) { - //errMsg("LbmStrict","debQCELL debug: l"< -LbmFloat& LbmFsgrSolver::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"< -LbmFloat& LbmFsgrSolver::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"< -LbmFloat* LbmFsgrSolver::debRACPNT(int level, int ii,int ij,int ik, int is ) { - return _RACPNT(level, ii,ij,ik, is ); -}; - -template -LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { - if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<D::cDfNum){ // dFfrac is an exception - //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"< -void -debugDisplayNode(fluidDispSettings *dispset, D *lbm, typename D::CellIdentifier cell ) { - //debugOut(" DD: "<getAsString() , 10); - ntlVec3Gfx org = lbm->getCellOrigin( cell ); - ntlVec3Gfx halfsize = lbm->getCellSize( cell ); - int set = lbm->getCellSet( cell ); - //debugOut(" DD: "<getAsString()<<" "<< (dispset->type) , 10); - - bool showcell = true; - int linewidth = 1; - ntlColor col(0.5); - LbmFloat cscale = dispset->scale; - -#define DRAWDISPCUBE(col,scale) \ - { glLineWidth( linewidth ); \ - glColor3f( (col)[0], (col)[1], (col)[2]); \ - ntlVec3Gfx s = org-(halfsize * (scale)); \ - ntlVec3Gfx e = org+(halfsize * (scale)); \ - drawCubeWire( s,e ); } - - switch(dispset->type) { - case FLUIDDISPNothing: { - showcell = false; - } break; - case FLUIDDISPCelltypes: { - CellFlagType flag = lbm->getCellFlag(cell, set ); - cscale = 0.5; - - if(flag& CFInvalid ) { if(!guiShowInvalid ) return; } - if(flag& CFUnused ) { if(!guiShowInvalid ) return; } - if(flag& CFEmpty ) { if(!guiShowEmpty ) return; } - if(flag& CFInter ) { if(!guiShowInterface) return; } - if(flag& CFNoDelete ) { if(!guiShowNoDelete ) return; } - if(flag& CFBnd ) { if(!guiShowBnd ) return; } - - // only dismiss one of these types - if(flag& CFGrFromCoarse) { if(!guiShowCoarseInner ) return; } // inner not really interesting - else - if(flag& CFGrFromFine) { if(!guiShowCoarseBorder ) return; } - else - if(flag& CFFluid ) { if(!guiShowFluid ) return; } - - if(flag& CFNoDelete) { // debug, mark nodel cells - ntlColor ccol(0.7,0.0,0.0); - DRAWDISPCUBE(ccol, 0.1); - } - if(flag& CFPersistMask) { // mark persistent flags - ntlColor ccol(0.5); - DRAWDISPCUBE(ccol, 0.125); - } - if(flag& CFNoBndFluid) { // mark persistent flags - ntlColor ccol(0,0,1); - DRAWDISPCUBE(ccol, 0.075); - } - - /*if(flag& CFAccelerator) { - cscale = 0.55; - col = ntlColor(0,1,0); - } */ - if(flag& CFInvalid) { - cscale = 0.50; - col = ntlColor(0.0,0,0.0); - } - /*else if(flag& CFSpeedSet) { - cscale = 0.55; - col = ntlColor(0.2,1,0.2); - }*/ - else if(flag& CFBnd) { - cscale = 0.59; - col = ntlColor(0.4); - } - - else if(flag& CFInter) { - cscale = 0.55; - col = ntlColor(0,1,1); - - } else if(flag& CFGrFromCoarse) { - // draw as - with marker - ntlColor col2(0.0,1.0,0.3); - DRAWDISPCUBE(col2, 0.1); - cscale = 0.5; - showcell=false; // DEBUG - } - else if(flag& CFFluid) { - cscale = 0.5; - if(flag& CFGrToFine) { - ntlColor col2(0.5,0.0,0.5); - DRAWDISPCUBE(col2, 0.1); - col = ntlColor(0,0,1); - } - if(flag& CFGrFromFine) { - ntlColor col2(1.0,1.0,0.0); - DRAWDISPCUBE(col2, 0.1); - col = ntlColor(0,0,1); - } else if(flag& CFGrFromCoarse) { - // draw as fluid with marker - ntlColor col2(0.0,1.0,0.3); - DRAWDISPCUBE(col2, 0.1); - col = ntlColor(0,0,1); - } else { - col = ntlColor(0,0,1); - } - } - else if(flag& CFEmpty) { - showcell=false; - } - - } break; - case FLUIDDISPVelocities: { - // dont use cube display - LbmVec vel = lbm->getCellVelocity( cell, set ); - glBegin(GL_LINES); - glColor3f( 0.0,0.0,0.0 ); - glVertex3f( org[0], org[1], org[2] ); - org += vec2G(vel * 10.0 * cscale); - glColor3f( 1.0,1.0,1.0 ); - glVertex3f( org[0], org[1], org[2] ); - glEnd(); - showcell = false; - } break; - case FLUIDDISPCellfills: { - CellFlagType flag = lbm->getCellFlag( cell,set ); - cscale = 0.5; - - if(flag& CFFluid) { - cscale = 0.75; - col = ntlColor(0,0,0.5); - } - else if(flag& CFInter) { - cscale = 0.75 * lbm->getCellMass(cell,set); - col = ntlColor(0,1,1); - } - else { - showcell=false; - } - - if( ABS(lbm->getCellMass(cell,set)) < 10.0 ) { - cscale = 0.75 * lbm->getCellMass(cell,set); - } else { - showcell = false; - } - if(cscale>0.0) { - col = ntlColor(0,1,1); - } else { - col = ntlColor(1,1,0); - } - // TODO - } break; - case FLUIDDISPDensity: { - LbmFloat rho = lbm->getCellDensity(cell,set); - cscale = rho*rho * 0.25; - col = ntlColor( MIN(0.5+cscale,1.0) , MIN(0.0+cscale,1.0), MIN(0.0+cscale,1.0) ); - cscale *= 2.0; - } break; - case FLUIDDISPGrid: { - cscale = 0.59; - col = ntlColor(1.0); - } break; - default: { - cscale = 0.5; - col = ntlColor(1.0,0.0,0.0); - } break; - } - - if(!showcell) return; - DRAWDISPCUBE(col, cscale); -} - -//! debug display function -// D has to implement the CellIterator interface -template -void -lbmDebugDisplay(fluidDispSettings *dispset, D *lbm) { - //je nach solver...? - if(!dispset->on) return; - glDisable( GL_LIGHTING ); // dont light lines - - typename D::CellIdentifier cid = lbm->getFirstCell(); - for(; lbm->noEndCell( cid ); - lbm->advanceCell( cid ) ) { - // display... -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - ::debugDisplayNode<>(dispset, lbm, cid ); -#else - debugDisplayNode(dispset, lbm, cid ); -#endif - } - delete cid; - - glEnable( GL_LIGHTING ); // dont light lines -} - -//! debug display function -// D has to implement the CellIterator interface -template -void -lbmMarkedCellDisplay(D *lbm) { - fluidDispSettings dispset; - // trick - display marked cells as grid displa -> white, big - dispset.type = FLUIDDISPGrid; - dispset.on = true; - glDisable( GL_LIGHTING ); // dont light lines - - typename D::CellIdentifier cid = lbm->markedGetFirstCell(); - while(cid) { - //for(; lbm->markedNoEndCell( cid ); - //cid = lbm->markedAdvanceCell( cid ) ) { - // display... FIXME? this is a bit inconvenient... - //MarkedCellIdentifier *mid = dynamic_cast( cid ); -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - //::debugDisplayNode<>(&dispset, lbm, mid->mpCell ); - ::debugDisplayNode<>(&dispset, lbm, cid ); -#else - //debugDisplayNode(&dispset, lbm, mid->mpCell ); - debugDisplayNode(&dispset, lbm, cid ); -#endif - cid = lbm->markedAdvanceCell(); - } - delete cid; - - glEnable( GL_LIGHTING ); // dont light lines -} - -#endif // LBM_USE_GUI - -//! display a single node -template -void -debugPrintNodeInfo(D *lbm, typename D::CellIdentifier cell, string printInfo, - // force printing of one set? default = -1 = off - int forceSet=-1) { - bool printDF = false; - bool printRho = false; - bool printVel = false; - bool printFlag = false; - bool printGeom = false; - bool printMass=false; - bool printBothSets = false; - - for(size_t i=0; igetCellOrigin( cell ); - ntlVec3Gfx halfsize = lbm->getCellSize( cell ); - int set = lbm->getCellSet( cell ); - debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<getAsString()<<" from "<getName()<<" currSet:"<=0) setmax = 1; - - for(int s=0; s=0) workset = forceSet; - debMsgStd(" ",DM_MSG, "Printing set:"<getDfNum(); l++) { // FIXME ?? - debMsgStd(" ",DM_MSG, " Df"<getCellDf(cell,workset,l), 1); - } - } - if(printRho) { - debMsgStd(" ",DM_MSG, " Rho: "<getCellDensity(cell,workset), 1); - } - if(printVel) { - debMsgStd(" ",DM_MSG, " Vel: "<getCellVelocity(cell,workset), 1); - } - if(printFlag) { - CellFlagType flag = lbm->getCellFlag(cell,workset); - debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<getCellMass(cell,workset), 1); - } - } -} - -#define LBMFUNCTIONS_H -#endif - diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp index 9c7fbc70b16..d6ac0b84ed7 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.cpp +++ b/intern/elbeem/intern/ntl_blenderdumper.cpp @@ -24,7 +24,7 @@ * Constructor *****************************************************************************/ ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) : - ntlRaytracer(filename,commandlineMode), + ntlWorld(filename,commandlineMode), mpTrafo(NULL) { ntlRenderGlobals *glob = mpGlob; @@ -194,7 +194,7 @@ int ntlBlenderDumper::renderScene( void ) // still render for preview... if(debugOut) { debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1); - ntlRaytracer::renderScene(); } + ntlWorld::renderScene(); } else { // next frame glob->setAniCount( glob->getAniCount() +1 ); diff --git a/intern/elbeem/intern/ntl_blenderdumper.h b/intern/elbeem/intern/ntl_blenderdumper.h index 0178feff145..403531a10a4 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.h +++ b/intern/elbeem/intern/ntl_blenderdumper.h @@ -7,12 +7,12 @@ * *****************************************************************************/ #ifndef NTL_BLENDERDUMPER_H -#include "ntl_raytracer.h" +#include "ntl_world.h" template class ntlMatrix4x4; class ntlBlenderDumper : - public ntlRaytracer + public ntlWorld { public: /*! Constructor */ diff --git a/intern/elbeem/intern/ntl_bsptree.cpp b/intern/elbeem/intern/ntl_bsptree.cpp index 0c6cdbd3d83..8f25272e496 100644 --- a/intern/elbeem/intern/ntl_bsptree.cpp +++ b/intern/elbeem/intern/ntl_bsptree.cpp @@ -579,18 +579,6 @@ void ntlTree::intersect(const ntlRay &ray, gfxReal &distance, mint = t; hit = (*iter); mintu = u; mintv = v; - - if((ray.getRenderglobals())&&(ray.getRenderglobals()->getDebugOut() > 5)) { // DEBUG!!! - errorOut("Tree tri hit at "<readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false)); + mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false); debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<getName()<<"': gid="< #include #include "utilities.h" -#include "ntl_raytracer.h" +#include "ntl_world.h" #include "ntl_scene.h" #include "parametrizer.h" #include "globals.h" @@ -34,7 +34,7 @@ void setPointers( ntlRenderGlobals *setglob); /****************************************************************************** * Constructor *****************************************************************************/ -ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : +ntlWorld::ntlWorld(string filename, bool commandlineMode) : mpGlob(NULL), mpLightList(NULL), mpPropList(NULL), mpSims(NULL), mpOpenGLRenderer(NULL), @@ -71,7 +71,7 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : long sstartTime = getTime(); scene->buildScene(); long sstopTime = getTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); // TODO check simulations, run first steps mFirstSim = -1; @@ -89,31 +89,31 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : if(mFirstSim>=0) { if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) { mFirstSim = i; - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"First Sim changed: "<=0) { - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) { - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<getStartTime()<<" simtime:"<getStartTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); #ifndef NOGUI guiResetSimulationTimeRange( mSimulationTime ); #endif } else { - if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlRaytracer::ntlRaytracer",DM_WARNING,"No active simulations!", 1); + if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); } } @@ -132,7 +132,7 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : /****************************************************************************** * Destructor *****************************************************************************/ -ntlRaytracer::~ntlRaytracer() +ntlWorld::~ntlWorld() { delete mpGlob->getScene(); delete mpGlob; @@ -146,7 +146,7 @@ ntlRaytracer::~ntlRaytracer() /******************************************************************************/ /*! set single frame rendering to filename */ -void ntlRaytracer::setSingleFrameOut(string singleframeFilename) { +void ntlWorld::setSingleFrameOut(string singleframeFilename) { mpGlob->setSingleFrameMode(true); mpGlob->setSingleFrameFilename(singleframeFilename); } @@ -159,17 +159,17 @@ extern "C" { void simulateThreadIncreaseFrame(void); } #endif // ELBEEM_BLENDER==1 -int ntlRaytracer::renderAnimation( void ) +int ntlWorld::renderAnimation( void ) { // only single pic currently - //debMsgStd("ntlRaytracer::renderAnimation : Warning only simulating...",1); + //debMsgStd("ntlWorld::renderAnimation : Warning only simulating...",1); if(mpGlob->getAniFrames() < 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No frames to render... ",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No frames to render... ",1); return 1; } if(mFirstSim<0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No reference animation found...",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No reference animation found...",1); return 1; } @@ -184,7 +184,7 @@ int ntlRaytracer::renderAnimation( void ) #endif // ELBEEM_BLENDER==1 if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); return 1; } } @@ -198,7 +198,7 @@ int ntlRaytracer::renderAnimation( void ) * this function is run in another thread, and communicates * with the parent thread via a mutex *****************************************************************************/ -int ntlRaytracer::renderVisualization( bool multiThreaded ) +int ntlWorld::renderVisualization( bool multiThreaded ) { #ifndef NOGUI //gfxReal deltat = 0.0015; @@ -206,7 +206,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) while(!getStopRenderVisualization()) { if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); + debMsgStd("ntlWorld::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); stopSimulationThread(); break; } @@ -216,7 +216,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) long startTime = getTime(); advanceSims(); long stopTime = getTime(); - debMsgStd("ntlRaytracer::renderVisualization",DM_MSG,"Time for "<getStepTime(); singleStepSims(targetTime); @@ -227,11 +227,11 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) if(!(*mpSims)[i]->getPanic()) allPanic = false; } if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } if(!SIMWORLD_OK()) { - warnMsg("ntlRaytracer::advanceSims","World state error... stopping" ); + warnMsg("ntlWorld::advanceSims","World state error... stopping" ); setStopRenderVisualization( true ); } } @@ -254,7 +254,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) return 0; } /*! render a single step for viz mode */ -int ntlRaytracer::singleStepVisualization( void ) +int ntlWorld::singleStepVisualization( void ) { mThreadRunning = true; double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); @@ -279,12 +279,12 @@ int ntlRaytracer::singleStepVisualization( void ) /****************************************************************************** * advance simulations by time t *****************************************************************************/ -int ntlRaytracer::advanceSims() +int ntlWorld::advanceSims() { bool done = false; bool allPanic = true; double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(); - //debMsgStd("ntlRaytracer::advanceSims",DM_MSG,"Advancing sims to "<getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime(); @@ -296,14 +296,14 @@ int ntlRaytracer::advanceSims() for(size_t i=0;isize();i++) { if(!(*mpSims)[i]->getVisible()) continue; if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? - //debMsgStd("ntlRaytracer::advanceSims",DM_MSG, " sim "<getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<getCurrentTime()) > LBM_TIME_EPSILON) done=false; if(allPanic) done = true; } if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } for(size_t i=0;isize();i++) { @@ -318,10 +318,10 @@ int ntlRaytracer::advanceSims() /* advance simulations by a single step */ /* dont check target time, if *targetTime==NULL */ -void ntlRaytracer::singleStepSims(double targetTime) { +void ntlWorld::singleStepSims(double targetTime) { const bool debugTime = false; //double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Target time: "<size();i++) { SimulationObject *sim = (*mpSims)[i]; @@ -330,9 +330,9 @@ void ntlRaytracer::singleStepSims(double targetTime) { bool done = false; while(!done) { // try to prevent round off errs - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Test sim "<getCurrentTime()<<" target:"<getCurrentTime())<<" stept:"<getStepTime()<<" leps:"<getCurrentTime()<<" target:"<getCurrentTime())<<" stept:"<getStepTime()<<" leps:"<getCurrentTime()) > LBM_TIME_EPSILON) { - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Stepping sim "<getCurrentTime()); // timedebug + if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping sim "<getCurrentTime()); // timedebug sim->step(); } else { done = true; @@ -353,7 +353,7 @@ void ntlRaytracer::singleStepSims(double targetTime) { * Render the current scene * uses the global variables from the parser *****************************************************************************/ -int ntlRaytracer::renderScene( void ) +int ntlWorld::renderScene( void ) { #ifndef ELBEEM_BLENDER char nrStr[5]; /* nr conversion */ @@ -374,7 +374,7 @@ int ntlRaytracer::renderScene( void ) if(mpGlob->getFrameSkip()) { struct stat statBuf; if(stat(outfn_conv.str().c_str(),&statBuf) == 0) { - errorOut("ntlRaytracer::renderscene Warning: file "<setAniCount( glob->getAniCount() +1 ); return(2); } @@ -472,7 +472,7 @@ int ntlRaytracer::renderScene( void ) glob->setCounterSceneInter(0); for (int scanline=Yres ; scanline > 0 ; --scanline) { - debugOutInter( "ntlRaytracer::renderScene: Line "<getLookat() + upVec*((2.0*scanline-Yres)/Yres) - rightVec; @@ -679,7 +679,7 @@ int ntlRaytracer::renderScene( void ) #ifndef NOPNG writePng(outfn_conv.str().c_str(), rows, w, h); #else // NOPNG - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); #endif // NOPNG } @@ -696,7 +696,7 @@ int ntlRaytracer::renderScene( void ) getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(), glob->getCounterShades(), glob->getCounterSceneInter() ); - debMsgStd("ntlRaytracer::renderScene",DM_MSG, resout, 1 ); + debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 ); /* clean stuff up */ delete [] aaCol; @@ -705,7 +705,7 @@ int ntlRaytracer::renderScene( void ) glob->getScene()->cleanupScene(); if(mpGlob->getSingleFrameMode() ) { - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); return 1; } #endif // ELBEEM_BLENDER diff --git a/intern/elbeem/intern/ntl_raytracer.h b/intern/elbeem/intern/ntl_world.h similarity index 96% rename from intern/elbeem/intern/ntl_raytracer.h rename to intern/elbeem/intern/ntl_world.h index 3f36fabaf92..0da7171bad6 100644 --- a/intern/elbeem/intern/ntl_raytracer.h +++ b/intern/elbeem/intern/ntl_world.h @@ -18,13 +18,13 @@ #include "simulation_object.h" class ntlOpenGLRenderer; -class ntlRaytracer +class ntlWorld { public: /*! Constructor */ - ntlRaytracer(string filename, bool commandlineMode); + ntlWorld(string filename, bool commandlineMode); /*! Destructor */ - virtual ~ntlRaytracer( void ); + virtual ~ntlWorld( void ); /*! render a whole animation (command line mode) */ int renderAnimation( void ); diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp index 15fb79fa5f2..dfb92050af4 100644 --- a/intern/elbeem/intern/simulation_object.cpp +++ b/intern/elbeem/intern/simulation_object.cpp @@ -10,8 +10,6 @@ #include "simulation_object.h" #include "ntl_bsptree.h" #include "ntl_scene.h" -#include "factory_lbm.h" -#include "lbmfunctions.h" #ifdef _WIN32 #else @@ -19,6 +17,8 @@ #endif +//! lbm factory functions +LbmSolverInterface* createSolver(); /****************************************************************************** @@ -109,13 +109,8 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) //mDimension is deprecated mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); if(mSolverType == stnFsgr) { - mpLbm = createSolverLbmFsgr(); + mpLbm = createSolver(); } else if(mSolverType == stnOld) { -#ifdef LBM_INCLUDE_TESTSOLVERS - // old solver for gfx demo - mpLbm = createSolverOld(); -#endif // LBM_TESTSOLVER - } else { errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); return 1; } @@ -311,7 +306,8 @@ void SimulationObject::drawDebugDisplay() { //errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type ); mpLbm->debugDisplay( &mDebDispSet[ mDebugType ] ); - ::lbmMarkedCellDisplay<>( mpLbm ); + //::lbmMarkedCellDisplay<>( mpLbm ); + mpLbm->lbmMarkedCellDisplay(); #endif } @@ -322,7 +318,7 @@ void SimulationObject::drawInteractiveDisplay() if(!getVisible()) return; if(mSelectedCid) { // in debugDisplayNode if dispset is on is ignored... - ::debugDisplayNode<>( &mDebDispSet[ FLUIDDISPGrid ], mpLbm, mSelectedCid ); + mpLbm->debugDisplayNode( &mDebDispSet[ FLUIDDISPGrid ], mSelectedCid ); } #endif } @@ -351,7 +347,8 @@ void SimulationObject::setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir) void SimulationObject::setMouseClick() { if(mSelectedCid) { - ::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() ); + //::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() ); + mpLbm->debugPrintNodeInfo( mSelectedCid ); } } diff --git a/intern/elbeem/intern/simulation_object.h b/intern/elbeem/intern/simulation_object.h index 84a0fd8222a..ae9060db859 100644 --- a/intern/elbeem/intern/simulation_object.h +++ b/intern/elbeem/intern/simulation_object.h @@ -7,13 +7,13 @@ * *****************************************************************************/ -#ifndef ELBEEM_SIMINTERFACE -#define ELBEEM_SIMINTERFACE +#ifndef SIMULATION_OBJECT_H +#define SIMULATION_OBJECT_H #define USE_GLUTILITIES #include "ntl_geometryshader.h" -#include "lbmdimensions.h" +#include "solver_interface.h" #include "parametrizer.h" #include "particletracer.h" diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h new file mode 100644 index 00000000000..3e8d2c3e849 --- /dev/null +++ b/intern/elbeem/intern/solver_class.h @@ -0,0 +1,690 @@ +/****************************************************************************** + * + * El'Beem - the visual lattice boltzmann freesurface simulator + * All code distributed as part of El'Beem is covered by the version 2 of the + * GNU General Public License. See the file COPYING for details. + * Copyright 2003-2005 Nils Thuerey + * + * Combined 2D/3D Lattice Boltzmann standard solver classes + * + *****************************************************************************/ + + +#ifndef LBMFSGRSOLVER_H + +// blender interface +#if ELBEEM_BLENDER==1 +// warning - for MSVC this has to be included +// _before_ ntl_vector3dim +#include "SDL.h" +#include "SDL_thread.h" +#include "SDL_mutex.h" +extern "C" { + void simulateThreadIncreaseFrame(void); + extern SDL_mutex *globalBakeLock; + extern int globalBakeState; + extern int globalBakeFrame; +} +#endif // ELBEEM_BLENDER==1 + +#include "utilities.h" +#include "solver_interface.h" +#include "ntl_scene.h" +#include + +#if PARALLEL==1 +#include +#endif // PARALLEL=1 +#ifndef PARALLEL +#define PARALLEL 0 +#endif // PARALLEL + +#ifndef LBMMODEL_DEFINED +// force compiler error! +ERROR - define model first! +#endif // LBMMODEL_DEFINED + + +// general solver setting defines + +//! debug coordinate accesses and the like? (much slower) +#define FSGR_STRICT_DEBUG 0 + +//! debug coordinate accesses and the like? (much slower) +#define FSGR_OMEGA_DEBUG 0 + +//! OPT3D quick LES on/off, only debug/benchmarking +#define USE_LES 1 + +//! order of interpolation (0=always current/1=interpolate/2=always other) +//#define TIMEINTORDER 0 +// TODO remove interpol t param, also interTime + +//! refinement border method (1 = small border / 2 = larger) +#define REFINEMENTBORDER 1 + +// use optimized 3D code? +#if LBMDIM==2 +#define OPT3D 0 +#else +// determine with debugging... +# if FSGR_STRICT_DEBUG==1 +# define OPT3D 0 +# else // FSGR_STRICT_DEBUG==1 +// usually switch optimizations for 3d on, when not debugging +# define OPT3D 1 +// COMPRT +//# define OPT3D 0 +# endif // FSGR_STRICT_DEBUG==1 +#endif + +// enable/disable fine grid compression for finest level +#if LBMDIM==3 +#define COMPRESSGRIDS 1 +#else +#define COMPRESSGRIDS 0 +#endif + +//! threshold for level set fluid generation/isosurface +#define LS_FLUIDTHRESHOLD 0.5 + +//! invalid mass value for unused mass data +#define MASS_INVALID -1000.0 + +// empty/fill cells without fluid/empty NB's by inserting them into the full/empty lists? +#define FSGR_LISTTRICK 1 +#define FSGR_LISTTTHRESHEMPTY 0.10 +#define FSGR_LISTTTHRESHFULL 0.90 +#define FSGR_MAGICNR 0.025 +//0.04 + +//! maxmimum no. of grid levels +#define FSGR_MAXNOOFLEVELS 5 + +// helper for comparing floats with epsilon +#define GFX_FLOATNEQ(x,y) ( ABS((x)-(y)) > (VECTOR_EPSILON) ) +#define LBM_FLOATNEQ(x,y) ( ABS((x)-(y)) > (10.0*LBM_EPSILON) ) + + +// macros for loops over all DFs +#define FORDF0 for(int l= 0; l< LBM_DFNUM; ++l) +#define FORDF1 for(int l= 1; l< LBM_DFNUM; ++l) +// and with different loop var to prevent shadowing +#define FORDF0M for(int m= 0; m< LBM_DFNUM; ++m) +#define FORDF1M for(int m= 1; m< LBM_DFNUM; ++m) + +// aux. field indices (same for 2d) +#define dFfrac 19 +#define dMass 20 +#define dFlux 21 +// max. no. of cell values for 3d +#define dTotalNum 22 + +// iso value defines +// border for marching cubes +#define ISOCORR 3 + + +// sirdude fix for solaris +#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) +#include +#ifndef expf +#define expf exp +#endif +#endif + + +/*****************************************************************************/ +/*! cell access classes */ +template +class UniformFsgrCellIdentifier : + public CellIdentifierInterface +{ + public: + //! which grid level? + int level; + //! location in grid + int x,y,z; + + //! reset constructor + UniformFsgrCellIdentifier() : + x(0), y(0), z(0) { }; + + // implement CellIdentifierInterface + virtual string getAsString() { + std::ostringstream ret; + ret <<"{ i"<2) ret<<",k"< *cid = dynamic_cast *>( other ); + UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( other ); + if(!cid) return false; + if( x==cid->x && y==cid->y && z==cid->z && level==cid->level ) return true; + return false; + } +}; + +//! information needed for each level in the simulation +class FsgrLevelData { +public: + int id; // level number + + //! node size on this level (geometric, in world coordinates, not simulation units!) + LbmFloat nodeSize; + //! node size on this level in simulation units + LbmFloat simCellSize; + //! quadtree node relaxation parameter + LbmFloat omega; + //! size this level was advanced to + LbmFloat time; + //! size of a single lbm step in time units on this level + LbmFloat stepsize; + //! step count + int lsteps; + //! gravity force for this level + LbmVec gravity; + //! level array + LbmFloat *mprsCells[2]; + CellFlagType *mprsFlags[2]; + + //! smago params and precalculated values + LbmFloat lcsmago; + LbmFloat lcsmago_sqr; + LbmFloat lcnu; + + // LES statistics per level + double avgOmega; + double avgOmegaCnt; + + //! current set of dist funcs + int setCurr; + //! target/other set of dist funcs + int setOther; + + //! mass&volume for this level + LbmFloat lmass; + LbmFloat lvolume; + LbmFloat lcellfactor; + + //! local storage of mSizes + int lSizex, lSizey, lSizez; + int lOffsx, lOffsy, lOffsz; + +}; + + + +/*****************************************************************************/ +/*! class for solving a LBM problem */ +template +class LbmFsgrSolver : + public D // this means, the solver is a lbmData object and implements the lbmInterface +{ + + public: + //! Constructor + LbmFsgrSolver(); + //! Destructor + virtual ~LbmFsgrSolver(); + //! id string of solver + virtual string getIdString() { return string("FsgrSolver[") + D::getIdString(); } + + //! initilize variables fom attribute list + virtual void parseAttrList(); + //! Initialize omegas and forces on all levels (for init/timestep change) + void initLevelOmegas(); + //! finish the init with config file values (allocate arrays...) + virtual bool initialize( ntlTree* /*tree*/, vector* /*objects*/ ); + +#if LBM_USE_GUI==1 + //! show simulation info (implement LbmSolverInterface pure virtual func) + virtual void debugDisplay(fluidDispSettings *set); +#endif + + + // implement CellIterator interface + typedef UniformFsgrCellIdentifier stdCellId; + virtual CellIdentifierInterface* getFirstCell( ); + virtual void advanceCell( CellIdentifierInterface* ); + virtual bool noEndCell( CellIdentifierInterface* ); + virtual void deleteCellIterator( CellIdentifierInterface** ); + virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos ); + virtual int getCellSet ( CellIdentifierInterface* ); + virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* ); + virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* ); + virtual int getCellLevel ( CellIdentifierInterface* ); + virtual LbmFloat getCellDensity ( CellIdentifierInterface* ,int set); + virtual LbmVec getCellVelocity ( CellIdentifierInterface* ,int set); + virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir); + virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set); + virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set); + virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set); + virtual LbmFloat getEquilDf ( int ); + virtual int getDfNum ( ); + // convert pointers + stdCellId* convertBaseCidToStdCid( CellIdentifierInterface* basecid); + + //! perform geometry init (if switched on) + bool initGeometryFlags(); + //! init part for all freesurface testcases + void initFreeSurfaces(); + //! init density gradient if enabled + void initStandingFluidGradient(); + + /*! init a given cell with flag, density, mass and equilibrium dist. funcs */ + inline void initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass); + inline void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel); + inline void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag); + + /*! perform a single LBM step */ + virtual void step() { stepMain(); } + void stepMain(); + void fineAdvance(); + void coarseAdvance(int lev); + void coarseCalculateFluxareas(int lev); + // coarsen a given level (returns true if sth. was changed) + bool performRefinement(int lev); + bool performCoarsening(int lev); + //void oarseInterpolateToFineSpaceTime(int lev,LbmFloat t); + void interpolateFineFromCoarse(int lev,LbmFloat t); + void coarseRestrictFromFine(int lev); + + /*! init particle positions */ + virtual int initParticles(ParticleTracer *partt); + /*! move all particles */ + virtual void advanceParticles(ParticleTracer *partt ); + + + /*! debug object display (used e.g. for preview surface) */ + virtual vector getDebugObjects(); + + // gui/output debugging functions +#if LBM_USE_GUI==1 + virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ); + virtual void lbmDebugDisplay(fluidDispSettings *dispset); + virtual void lbmMarkedCellDisplay(); +#endif // LBM_USE_GUI==1 + virtual void debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet=-1); + + //! for raytracing, preprocess + void prepareVisualization( void ); + + /*! type for cells */ + typedef typename D::LbmCell LbmCell; + + protected: + + //! internal quick print function (for debugging) + void printLbmCell(int level, int i, int j, int k,int set); + // debugging use CellIterator interface to mark cell + void debugMarkCellCall(int level, int vi,int vj,int vk); + + void mainLoop(int lev); + void adaptTimestep(); + //! init mObjectSpeeds for current parametrization + void recalculateObjectSpeeds(); + //! flag reinit step - always works on finest grid! + void reinitFlags( int workSet ); + //! mass dist weights + LbmFloat getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l); + //! add point to mListNewInter list + inline void addToNewInterList( int ni, int nj, int nk ); + //! cell is interpolated from coarse level (inited into set, source sets are determined by t) + // inline, test? + void interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet,bool markNbs); + + //! minimal and maximal z-coords (for 2D/3D loops) + int getForZMinBnd() { return 0; } + int getForZMin1() { + if(D::cDimension==2) return 0; + return 1; + } + + int getForZMaxBnd(int lev) { + if(D::cDimension==2) return 1; + return mLevel[lev].lSizez -0; + } + int getForZMax1(int lev) { + if(D::cDimension==2) return 1; + return mLevel[lev].lSizez -1; + } + + + // member vars + + //! mass calculated during streaming step + LbmFloat mCurrentMass; + LbmFloat mCurrentVolume; + LbmFloat mInitialMass; + + //! count problematic cases, that occured so far... + int mNumProblems; + + // average mlsups, count how many so far... + double mAvgMLSUPS; + double mAvgMLSUPSCnt; + + //! Mcubes object for surface reconstruction + IsoSurface *mpPreviewSurface; + float mSmoothSurface; + float mSmoothNormals; + + //! use time adaptivity? + bool mTimeAdap; + //! domain boundary free/no slip type + string mDomainBound; + //! part slip value for domain + LbmFloat mDomainPartSlipValue; + + //! output surface preview? if >0 yes, and use as reduzed size + int mOutputSurfacePreview; + LbmFloat mPreviewFactor; + //! fluid vol height + LbmFloat mFVHeight; + LbmFloat mFVArea; + bool mUpdateFVHeight; + + //! require some geo setup from the viz? + //int mGfxGeoSetup; + //! force quit for gfx + LbmFloat mGfxEndTime; + //! smoother surface initialization? + int mInitSurfaceSmoothing; + + int mTimestepReduceLock; + int mTimeSwitchCounts; + //! total simulation time so far + LbmFloat mSimulationTime; + //! smallest and largest step size so far + LbmFloat mMinStepTime, mMaxStepTime; + //! track max. velocity + LbmFloat mMxvx, mMxvy, mMxvz, mMaxVlen; + + //! list of the cells to empty at the end of the step + vector mListEmpty; + //! list of the cells to make fluid at the end of the step + vector mListFull; + //! list of new interface cells to init + vector mListNewInter; + //! class for handling redist weights in reinit flag function + class lbmFloatSet { + public: + LbmFloat val[dTotalNum]; + LbmFloat numNbs; + }; + //! normalized vectors for all neighboring cell directions (for e.g. massdweight calc) + LbmVec mDvecNrm[27]; + + + //! debugging + bool checkSymmetry(string idstring); + //! kepp track of max/min no. of filled cells + int mMaxNoCells, mMinNoCells; +#ifndef USE_MSVC6FIXES + long long int mAvgNumUsedCells; +#else + _int64 mAvgNumUsedCells; +#endif + + //! for interactive - how to drop drops? + int mDropMode; + LbmFloat mDropSize; + LbmVec mDropSpeed; + //! precalculated objects speeds for current parametrization + vector mObjectSpeeds; + //! partslip bc. values for obstacle boundary conditions + vector mObjectPartslips; + + //! get isofield weights + int mIsoWeightMethod; + float mIsoWeight[27]; + + // grid coarsening vars + + /*! vector for the data for each level */ + FsgrLevelData mLevel[FSGR_MAXNOOFLEVELS]; + + /*! minimal and maximal refinement levels */ + int mMaxRefine; + + /*! df scale factors for level up/down */ + LbmFloat mDfScaleUp, mDfScaleDown; + + /*! precomputed cell area values */ + LbmFloat mFsgrCellArea[27]; + + /*! LES C_smago paramter for finest grid */ + float mInitialCsmago; + /*! LES stats for non OPT3D */ + LbmFloat mDebugOmegaRet; + + //! fluid stats + int mNumInterdCells; + int mNumInvIfCells; + int mNumInvIfTotal; + int mNumFsgrChanges; + + //! debug function to disable standing f init + int mDisableStandingFluidInit; + //! debug function to force tadap syncing + int mForceTadapRefine; + + + // strict debug interface +# if FSGR_STRICT_DEBUG==1 + int debLBMGI(int level, int ii,int ij,int ik, int is); + CellFlagType& debRFLAG(int level, int xx,int yy,int zz,int set); + CellFlagType& debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir); + CellFlagType& debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir); + int debLBMQI(int level, int ii,int ij,int ik, int is, int l); + LbmFloat& debQCELL(int level, int xx,int yy,int zz,int set,int l); + LbmFloat& debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l); + LbmFloat& debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l); + LbmFloat* debRACPNT(int level, int ii,int ij,int ik, int is ); + LbmFloat& debRAC(LbmFloat* s,int l); +# endif // FSGR_STRICT_DEBUG==1 +}; + + + +/*****************************************************************************/ +// relaxation_macros + + + +// cell mark debugging +#if FSGR_STRICT_DEBUG==10 +#define debugMarkCell(lev,x,y,z) \ + errMsg("debugMarkCell",D::mName<<" step: "< +void LbmFsgrSolver::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) { + CellFlagType pers = RFLAG(level,xx,yy,zz,set) & CFPersistMask; + RFLAG(level,xx,yy,zz,set) = newflag | pers; +} + +template +void +LbmFsgrSolver::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) { + /* init eq. dist funcs */ + LbmFloat *ecel; + int workSet = mLevel[level].setCurr; + + ecel = RACPNT(level, i,j,k, workSet); + FORDF0 { RAC(ecel, l) = D::dfEquil[l] * rho; } + RAC(ecel, dMass) = mass; + RAC(ecel, dFfrac) = mass/rho; + RAC(ecel, dFlux) = FLUX_INIT; + //RFLAG(level, i,j,k, workSet)= flag; + changeFlag(level, i,j,k, workSet, flag); + + workSet ^= 1; + changeFlag(level, i,j,k, workSet, flag); + return; +} + +template +void +LbmFsgrSolver::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) { + LbmFloat *ecel; + int workSet = mLevel[level].setCurr; + + ecel = RACPNT(level, i,j,k, workSet); + FORDF0 { RAC(ecel, l) = D::getCollideEq(l, rho,vel[0],vel[1],vel[2]); } + RAC(ecel, dMass) = mass; + RAC(ecel, dFfrac) = mass/rho; + RAC(ecel, dFlux) = FLUX_INIT; + //RFLAG(level, i,j,k, workSet) = flag; + changeFlag(level, i,j,k, workSet, flag); + + workSet ^= 1; + changeFlag(level, i,j,k, workSet, flag); + return; +} + +#define LBMFSGRSOLVER_H +#endif + + diff --git a/intern/elbeem/intern/solver_dimenions.h b/intern/elbeem/intern/solver_dimenions.h new file mode 100644 index 00000000000..04f9eb5c125 --- /dev/null +++ b/intern/elbeem/intern/solver_dimenions.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * All code distributed as part of El'Beem is covered by the version 2 of the + * GNU General Public License. See the file COPYING for details. + * Copyright 2003-2005 Nils Thuerey + * + * Combined 2D/3D Lattice Boltzmann Solver auxiliary classes + * + *****************************************************************************/ +#ifndef LBMHEADER_H + +/* LBM Files */ +#include "solver_interface.h" + + +#define LBMHEADER_H +#endif + + + diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp new file mode 100644 index 00000000000..3ebd3ff4453 --- /dev/null +++ b/intern/elbeem/intern/solver_init.cpp @@ -0,0 +1,1449 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004,2005 Nils Thuerey + * + * Standard LBM Factory implementation + * + *****************************************************************************/ + +#include "solver_class.h" +#include "solver_relax.h" + + +/****************************************************************************** + * Lbm Constructor + *****************************************************************************/ +template +LbmFsgrSolver::LbmFsgrSolver() : + D(), + mCurrentMass(0.0), mCurrentVolume(0.0), + mNumProblems(0), + mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0), + mpPreviewSurface(NULL), + mSmoothSurface(0.0), mSmoothNormals(0.0), + mTimeAdap(false), mDomainBound("noslip"), mDomainPartSlipValue(0.1), + mOutputSurfacePreview(0), mPreviewFactor(0.25), + mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false), + mInitSurfaceSmoothing(0), + mTimestepReduceLock(0), + mTimeSwitchCounts(0), + mSimulationTime(0.0), + mMinStepTime(0.0), mMaxStepTime(0.0), + mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0), + mDropMode(1), mDropSize(0.15), mDropSpeed(0.0), + mObjectSpeeds(), mObjectPartslips(), + mIsoWeightMethod(2), + mMaxRefine(1), + mDfScaleUp(-1.0), mDfScaleDown(-1.0), + mInitialCsmago(0.04), mDebugOmegaRet(0.0), + mNumInvIfTotal(0), mNumFsgrChanges(0), + mDisableStandingFluidInit(0), + mForceTadapRefine(-1) +{ + // not much to do here... + D::mpIso = new IsoSurface( D::mIsoValue, false ); + + // init equilibrium dist. func + LbmFloat rho=1.0; + FORDF0 { + D::dfEquil[l] = D::getCollideEq( l,rho, 0.0, 0.0, 0.0); + } + + // init LES + int odm = 0; + for(int m=0; m +void +LbmFsgrSolver::parseAttrList() +{ + LbmSolverInterface::parseStdAttrList(); + + string matIso("default"); + matIso = D::mpAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false ); + D::mpIso->setMaterialName( matIso ); + mOutputSurfacePreview = D::mpAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false ); + mTimeAdap = D::mpAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false ); + mDomainBound = D::mpAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false ); + mDomainPartSlipValue = D::mpAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false ); + + mIsoWeightMethod= D::mpAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false ); + mInitSurfaceSmoothing = D::mpAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false ); + mSmoothSurface = D::mpAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); + mSmoothNormals = D::mpAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); + + mInitialCsmago = D::mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); + // deprecated! + float mInitialCsmagoCoarse = 0.0; + mInitialCsmagoCoarse = D::mpAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false ); +#if USE_LES==1 +#else // USE_LES==1 + debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2); + mInitialCsmago = 0.0; +#endif // USE_LES==1 + + // refinement + mMaxRefine = D::mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", true); + if(mMaxRefine<0) mMaxRefine=0; + if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1; + mDisableStandingFluidInit = D::mpAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false); + mForceTadapRefine = D::mpAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false); + + // demo mode settings + mFVHeight = D::mpAttrs->readFloat("fvolheight", mFVHeight, "SimulationLbm","mFVHeight", false ); + // FIXME check needed? + mFVArea = D::mpAttrs->readFloat("fvolarea", mFVArea, "SimulationLbm","mFArea", false ); + +} + + +/****************************************************************************** + * Initialize omegas and forces on all levels (for init/timestep change) + *****************************************************************************/ +template +void +LbmFsgrSolver::initLevelOmegas() +{ + // no explicit settings + D::mOmega = D::mpParam->calculateOmega(); + D::mGravity = vec2L( D::mpParam->calculateGravity() ); + D::mSurfaceTension = D::mpParam->calculateSurfaceTension(); // unused + + if(mInitialCsmago<=0.0) { + if(OPT3D==1) { + errFatal("LbmFsgrSolver::initLevelOmegas","Csmago-LES = 0 not supported for optimized 3D version...",SIMWORLD_INITERROR); + return; + } + } + + // use Tau instead of Omega for calculations + { // init base level + int i = mMaxRefine; + mLevel[i].omega = D::mOmega; + mLevel[i].stepsize = D::mpParam->getStepTime(); + mLevel[i].lcsmago = mInitialCsmago; //CSMAGO_INITIAL; + mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; + mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); + } + + // init all sub levels + for(int i=mMaxRefine-1; i>=0; i--) { + //mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5; + double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5; + nomega = 1.0/nomega; + mLevel[i].omega = (LbmFloat)nomega; + mLevel[i].stepsize = 2.0 * mLevel[i+1].stepsize; + //mLevel[i].lcsmago = mLevel[i+1].lcsmago*mCsmagoRefineMultiplier; + //if(mLevel[i].lcsmago>1.0) mLevel[i].lcsmago = 1.0; + //if(strstr(D::getName().c_str(),"Debug")){ + //mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago; // DEBUG + // if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago * (LbmFloat)(mMaxRefine-i)*0.5+1.0; + //if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = mLevel[mMaxRefine].lcsmago * ((LbmFloat)(mMaxRefine-i)*1.0 + 1.0 ); + //if(strstr(D::getName().c_str(),"Debug")) mLevel[i].lcsmago = 0.99; + mLevel[i].lcsmago = mInitialCsmago; + mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; + mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); + } + + // for lbgk + mLevel[ mMaxRefine ].gravity = D::mGravity / mLevel[ mMaxRefine ].omega; + for(int i=mMaxRefine-1; i>=0; i--) { + // should be the same on all levels... + // for lbgk + mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega; + } + + // debug? invalidate old values... + D::mGravity = -100.0; + D::mOmega = -100.0; + + for(int i=0; i<=mMaxRefine; i++) { + if(!D::mSilent) { + errMsg("LbmFsgrSolver", "Level init "<0) { + mDfScaleUp = (mLevel[0 ].stepsize/mLevel[0+1].stepsize)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu + mDfScaleDown = (mLevel[0+1].stepsize/mLevel[0 ].stepsize)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu + } +} + + +/****************************************************************************** + * Init Solver (values should be read from config file) + *****************************************************************************/ +template +bool +LbmFsgrSolver::initialize( ntlTree* /*tree*/, vector* /*objects*/ ) +{ + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<maxGridSize) maxGridSize = D::mSizey; + if(D::mSizez>maxGridSize) maxGridSize = D::mSizez; + LbmFloat maxGeoSize = (D::mvGeoEnd[0]-D::mvGeoStart[0]); // get max size + if((D::mvGeoEnd[1]-D::mvGeoStart[1])>maxGridSize) maxGeoSize = (D::mvGeoEnd[1]-D::mvGeoStart[1]); + if((D::mvGeoEnd[2]-D::mvGeoStart[2])>maxGridSize) maxGeoSize = (D::mvGeoEnd[2]-D::mvGeoStart[2]); + // FIXME better divide max geo size by corresponding resolution rather than max? no prob for rx==ry==rz though + LbmFloat cellSize = (maxGeoSize / (LbmFloat)maxGridSize); + if(debugGridsizeInit) debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Start:"<setSize(D::mSizex, D::mSizey, D::mSizez); + + //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<setSimulationMaxSpeed(0.0); + if(mFVHeight>0.0) D::mpParam->setFluidVolumeHeight(mFVHeight); + D::mpParam->setTadapLevels( mMaxRefine+1 ); + + if(mForceTadapRefine>mMaxRefine) { + D::mpParam->setTadapLevels( mForceTadapRefine+1 ); + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<calculateAllMissingValues()) { + errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR); + return false; + } + // recalc objects speeds in geo init + + + + // init vectors + //if(mMaxRefine >= FSGR_MAXNOOFLEVELS) { errFatal("LbmFsgrSolver::initializeLbmGridref"," error: Too many levels!", SIMWORLD_INITERROR); return false; } + for(int i=0; i<=mMaxRefine; i++) { + mLevel[i].id = i; + mLevel[i].nodeSize = 0.0; + mLevel[i].simCellSize = 0.0; + mLevel[i].omega = 0.0; + mLevel[i].time = 0.0; + mLevel[i].stepsize = 1.0; + mLevel[i].gravity = LbmVec(0.0); + mLevel[i].mprsCells[0] = NULL; + mLevel[i].mprsCells[1] = NULL; + mLevel[i].mprsFlags[0] = NULL; + mLevel[i].mprsFlags[1] = NULL; + + mLevel[i].avgOmega = 0.0; + mLevel[i].avgOmegaCnt = 0.0; + } + + // init sizes + mLevel[mMaxRefine].lSizex = D::mSizex; + mLevel[mMaxRefine].lSizey = D::mSizey; + mLevel[mMaxRefine].lSizez = D::mSizez; + for(int i=mMaxRefine-1; i>=0; i--) { + mLevel[i].lSizex = mLevel[i+1].lSizex/2; + mLevel[i].lSizey = mLevel[i+1].lSizey/2; + mLevel[i].lSizez = mLevel[i+1].lSizez/2; + /*if( ((mLevel[i].lSizex % 4) != 0) || ((mLevel[i].lSizey % 4) != 0) || ((mLevel[i].lSizez % 4) != 0) ) { + errMsg("LbmFsgrSolver","Init: error invalid sizes on level "<=0; i--) { + rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); + memCnt += sizeof(CellFlagType) * (rcellSize/dTotalNum +4) *2; + memCnt += sizeof(LbmFloat) * (rcellSize +4) *2; + } + double memd = memCnt; + char *sizeStr = ""; + const double sfac = 1000.0; + if(memd>sfac){ memd /= sfac; sizeStr="KB"; } + if(memd>sfac){ memd /= sfac; sizeStr="MB"; } + if(memd>sfac){ memd /= sfac; sizeStr="GB"; } + if(memd>sfac){ memd /= sfac; sizeStr="TB"; } + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Required Grid memory: "<< memd <<" "<< sizeStr<<" ",4); + } + + // safety check + if(sizeof(CellFlagType) != CellFlagTypeSize) { + errFatal("LbmFsgrSolver::initialize","Fatal Error: CellFlagType has wrong size! Is:"<getCellSize(); + mLevel[ mMaxRefine ].lcellfactor = 1.0; + unsigned long int rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); + // +4 for safety ? + mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + +#if COMPRESSGRIDS==0 + mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; + mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; +#else // COMPRESSGRIDS==0 + unsigned long int compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); + mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ]; + mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset; + //errMsg("CGD","rcs:"<=0; i--) { + mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize; + mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize; + mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac; + + if(D::cDimension==2){ mLevel[i].lSizez = 1; } // 2D + rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); + mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; + mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; + } + + // init sizes for _all_ levels + for(int i=mMaxRefine; i>=0; i--) { + mLevel[i].lOffsx = mLevel[i].lSizex; + mLevel[i].lOffsy = mLevel[i].lOffsx*mLevel[i].lSizey; + mLevel[i].lOffsz = mLevel[i].lOffsy*mLevel[i].lSizez; + mLevel[i].setCurr = 0; + mLevel[i].setOther = 1; + mLevel[i].lsteps = 0; + mLevel[i].lmass = 0.0; + mLevel[i].lvolume = 0.0; + } + + // calc omega, force for all levels + initLevelOmegas(); + mMinStepTime = D::mpParam->getStepTime(); + mMaxStepTime = D::mpParam->getStepTime(); + + // init isosurf + D::mpIso->setIsolevel( D::mIsoValue ); + // approximate feature size with mesh resolution + float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5; + D::mpIso->setSmoothSurface( mSmoothSurface * featureSize ); + D::mpIso->setSmoothNormals( mSmoothNormals * featureSize ); + + // init iso weight values mIsoWeightMethod + int wcnt = 0; + float totw = 0.0; + for(int ak=-1;ak<=1;ak++) + for(int aj=-1;aj<=1;aj++) + for(int ai=-1;ai<=1;ai++) { + switch(mIsoWeightMethod) { + case 1: // light smoothing + mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); + break; + case 2: // very light smoothing + mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); + mIsoWeight[wcnt] *= mIsoWeight[wcnt]; + break; + case 3: // no smoothing + if(ai==0 && aj==0 && ak==0) mIsoWeight[wcnt] = 1.0; + else mIsoWeight[wcnt] = 0.0; + break; + default: // strong smoothing (=0) + mIsoWeight[wcnt] = 1.0; + break; + } + totw += mIsoWeight[wcnt]; + wcnt++; + } + for(int i=0; i<27; i++) mIsoWeight[i] /= totw; + + LbmVec isostart = vec2L(D::mvGeoStart); + LbmVec isoend = vec2L(D::mvGeoEnd); + int twodOff = 0; // 2d slices + if(D::cDimension==2) { + LbmFloat sn,se; + sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; + se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; + isostart[2] = sn; + isoend[2] = se; + twodOff = 2; + } + //errMsg(" SETISO ", " "<setStart( vec2G(isostart) ); + D::mpIso->setEnd( vec2G(isoend) ); + LbmVec isodist = isoend-isostart; + D::mpIso->initializeIsosurface( D::mSizex+2, D::mSizey+2, D::mSizez+2+twodOff, vec2G(isodist) ); + for(int ak=0;akgetData(ai,aj,ak) = 0.0; } + + /* init array (set all invalid first) */ + for(int lev=0; lev<=mMaxRefine; lev++) { + FSGR_FORIJK_BOUNDS(lev) { + RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage + initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0); + } + } + + // init defaults + mAvgNumUsedCells = 0; + D::mFixMass= 0.0; + + /* init boundaries */ + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10); + + + // use the density init? + initGeometryFlags(); + D::initGenericTestCases(); + + // new - init noslip 1 everywhere... + // half fill boundary cells? + + CellFlagType domainBoundType = CFInvalid; + if(mDomainBound.find(string("free")) != string::npos) { + domainBoundType = CFBnd | CFBndFreeslip; + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<size()); + domainBoundType |= (domainobj<<24); + //for(int i=0; i<(int)(domainobj+0); i++) { + //errMsg("GEOIN","i"<getName()); + //if((*D::mpGiObjects)[i] == D::mpIso) { + //check... + //} + //} + //errMsg("GEOIN"," dm "<<(domainBoundType>>24)); + + for(int k=0;kcalculateCellSize(); + if(D::cDimension==2) cspv[2] = 1.0; + inmCellCnt = 1; + double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0; + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<=0; lev--) { + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<setMaterialName( mpPreviewSurface->getMaterialName() ); + mpPreviewSurface->setIsolevel( D::mIsoValue ); + // usually dont display for rendering + mpPreviewSurface->setVisible( false ); + + mpPreviewSurface->setStart( vec2G(isostart) ); + mpPreviewSurface->setEnd( vec2G(isoend) ); + LbmVec pisodist = isoend-isostart; + mpPreviewSurface->initializeIsosurface( (int)(mPreviewFactor*D::mSizex)+2, (int)(mPreviewFactor*D::mSizey)+2, (int)(mPreviewFactor*D::mSizez)+2, vec2G(pisodist) ); + //mpPreviewSurface->setName( D::getName() + "preview" ); + mpPreviewSurface->setName( "preview" ); + + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(mPreviewFactor*D::mSizex)<<","<<(mPreviewFactor*D::mSizey)<<","<<(mPreviewFactor*D::mSizez)<<" enabled",10); + } + +#if ELBEEM_BLENDER==1 + // make sure fill fracs are right for first surface generation + stepMain(); +#endif // ELBEEM_BLENDER==1 + + // prepare once... + prepareVisualization(); + // copy again for stats counting + for(int lev=0; lev<=mMaxRefine; lev++) { + FSGR_FORIJK_BOUNDS(lev) { + RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr); + } } // first copy flags */ + + /*{ int lev=mMaxRefine; + FSGR_FORIJK_BOUNDS(lev) { // COMPRT deb out + debMsgDirect("\n x="<calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); + D::mpParam->setSimulationMaxSpeed( norm(maxIniVel) + norm(mLevel[level].gravity) ); + LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxIniVel <<", allowed Max="<getSimulationMaxSpeed() > allowMax) { + // similar to adaptTimestep(); + LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed(); + LbmFloat newdt = D::mpParam->getStepTime() * (allowMax / nextmax); // newtr + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< D::mpParam->getStepTime() <<" ",5); + D::mpParam->setDesiredStepTime( newdt ); + D::mpParam->calculateAllMissingValues( D::mSilent ); + maxIniVel = vec2G( D::mpParam->calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxIniVel,5); + } + recalculateObjectSpeeds(); + + ntlVec3Gfx pos,iniPos; // position of current cell + LbmFloat rhomass = 0.0; + int savedNodes = 0; + int OId = -1; + gfxReal distance; + + // 2d display as rectangles + if(D::cDimension==2) { + dvec[2] = 0.0; + iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ))-(dvec*0.0); + //iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))+dvec; + } else { + iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0); + iniPos[2] = D::mvGeoStart[2] + dvec[2]*getForZMin1(); + } + + + // first init boundary conditions +#define GETPOS(i,j,k) \ + ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \ + iniPos[1]+ dvec[1]*(gfxReal)(j), \ + iniPos[2]+ dvec[2]*(gfxReal)(k) ) + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + for(int j=1;jgetGeoInitType() ){ + case FGI_MBNDINFLOW: + rhomass = 1.0; + ntype = CFFluid|CFMbndInflow; + break; + case FGI_MBNDOUTFLOW: + rhomass = 0.0; + ntype = CFEmpty|CFMbndOutflow; + break; + case FGI_BNDNO: + rhomass = BND_FILL; + ntype = CFBnd|CFBndNoslip; break; + case FGI_BNDFREE: + rhomass = BND_FILL; + ntype = CFBnd|CFBndFreeslip; break; + default: // warn here? + rhomass = BND_FILL; + ntype = CFBnd|CFBndNoslip; break; + } + } + if(ntype != CFInvalid) { + // initDefaultCell + if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { } + ntype |= (OId<<24); // NEWTEST2 + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + } + + // walk along x until hit for following inits + if(distance<=-1.0) { distance = 100.0; } // FIXME dangerous + if(distance>=0.0) { + gfxReal dcnt=dvec[0]; + while(( dcnt< distance-dvec[0] )&&(i+1 +void +LbmFsgrSolver::initFreeSurfaces() { + double interfaceFill = 0.45; // filling level of interface cells + + // set interface cells + FSGR_FORIJK1(mMaxRefine) { + + /*if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFEmpty )) { + int initInter = 0; + // check for neighboring fluid cells + FORDF1 { + if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l), CFFluid ) ) { + initInter = 1; + } + } + + if(initInter) { + initEmptyCell(mMaxRefine, i,j,k, CFInter, 1.0, interfaceFill); + } + + } // empty cells OLD */ + + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid )) { + int initInter = 0; // check for neighboring empty cells + FORDF1 { + if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l), CFEmpty ) ) { + initInter = 1; + } + } + if(initInter) { + QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr, dMass) = + //QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setOther, dMass) = // COMPRT OFF + interfaceFill; + RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) = RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setOther) = CFInter; + } + } + } + + // remove invalid interface cells + FSGR_FORIJK1(mMaxRefine) { + // remove invalid interface cells + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { + int delit = 0; + int NBs = 0; // neighbor flags or'ed + int noEmptyNB = 1; + + FORDF1 { + if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l ), CFEmpty ) ) { + noEmptyNB = 0; + } + NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l); + } + + // remove cells with no fluid or interface neighbors + if((NBs & CFFluid)==0) { delit = 1; } + if((NBs & CFInter)==0) { delit = 1; } + + // remove cells with no empty neighbors + if(noEmptyNB) { delit = 2; } + + // now we can remove the cell + if(delit==1) { + initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0); + } + if(delit==2) { + initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); + } + } // interface + } + + // another brute force init, make sure the fill values are right... + // and make sure both sets are equal + for(int lev=0; lev<=mMaxRefine; lev++) { + FSGR_FORIJK_BOUNDS(lev) { + if( (RFLAG(lev, i,j,k,0) & (CFBnd)) ) { + QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = BND_FILL; + continue; + } + if( (RFLAG(lev, i,j,k,0) & (CFEmpty)) ) { + QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = 0.0; + continue; + } + } } + + // ---------------------------------------------------------------------- + // smoother surface... + if(mInitSurfaceSmoothing>0) { + debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing steps ",10); +#if COMPRESSGRIDS==1 + errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return; +#endif // COMPRESSGRIDS==0 + } + for(int s=0; s +void +LbmFsgrSolver::initStandingFluidGradient() { + // ---------------------------------------------------------------------- + // standing fluid preinit + const int debugStandingPreinit = 0; + int haveStandingFluid = 0; + +#define STANDFLAGCHECK(iindex) \ + if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || \ + ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ \ + if((iindex)>1) { haveStandingFluid=(iindex); } \ + j = mLevel[mMaxRefine].lSizey; i=mLevel[mMaxRefine].lSizex; k=D::getForZMaxBnd(); \ + continue; \ + } + int gravIndex[3] = {0,0,0}; + int gravDir[3] = {1,1,1}; + int maxGravComp = 1; // by default y + int gravComp1 = 0; // by default y + int gravComp2 = 2; // by default y + if( ABS(mLevel[mMaxRefine].gravity[0]) > ABS(mLevel[mMaxRefine].gravity[1]) ){ maxGravComp = 0; gravComp1=1; gravComp2=2; } + if( ABS(mLevel[mMaxRefine].gravity[2]) > ABS(mLevel[mMaxRefine].gravity[0]) ){ maxGravComp = 2; gravComp1=0; gravComp2=1; } + + int gravIMin[3] = { 0 , 0 , 0 }; + int gravIMax[3] = { + mLevel[mMaxRefine].lSizex + 0, + mLevel[mMaxRefine].lSizey + 0, + mLevel[mMaxRefine].lSizez + 0 }; + if(LBMDIM==2) gravIMax[2] = 1; + + //int gravDir = 1; + if( mLevel[mMaxRefine].gravity[maxGravComp] > 0.0 ) { + // swap directions + int i=maxGravComp; + int tmp = gravIMin[i]; + gravIMin[i] = gravIMax[i] - 1; + gravIMax[i] = tmp - 1; + gravDir[i] = -1; + } +#define PRINTGDIRS \ + errMsg("Standing fp","X start="<>2); // not much use...? + //preinitSteps = 4; // DEBUG!!!! + //D::mInitDone = 1; // GRAVTEST + //preinitSteps = 0; + debMsgNnl("Standing fluid preinit", DM_MSG, "Performing "< +bool +LbmFsgrSolver::checkSymmetry(string idstring) +{ + bool erro = false; + bool symm = true; + int msgs = 0; + const int maxMsgs = 10; + const bool markCells = false; + + //for(int lev=0; lev<=mMaxRefine; lev++) { + { int lev = mMaxRefine; + + // no point if not symm. + if( (mLevel[lev].lSizex==mLevel[lev].lSizey) && (mLevel[lev].lSizex==mLevel[lev].lSizez)) { + // ok + } else { + return false; + } + + for(int s=0; s<2; s++) { + FSGR_FORIJK1(lev) { + if(i<(mLevel[lev].lSizex/2)) { + int inb = (mLevel[lev].lSizey-1-i); + + if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T + + if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true; + if(D::cDimension==2) { + if(msgs; +#endif // LBMDIM==2 +#if LBMDIM==3 +template class LbmFsgrSolver< LbmBGK3D >; +#endif // LBMDIM==3 diff --git a/intern/elbeem/intern/lbminterface.cpp b/intern/elbeem/intern/solver_interface.cpp similarity index 82% rename from intern/elbeem/intern/lbminterface.cpp rename to intern/elbeem/intern/solver_interface.cpp index db7705de0a8..3d77e4a4968 100644 --- a/intern/elbeem/intern/lbminterface.cpp +++ b/intern/elbeem/intern/solver_interface.cpp @@ -11,12 +11,9 @@ *****************************************************************************/ /* LBM Files */ -#include "lbmdimensions.h" -#include "lbminterface.h" -#include "lbmfunctions.h" +#include "solver_interface.h" #include "ntl_scene.h" #include "ntl_ray.h" -#include "typeslbm.h" /*****************************************************************************/ @@ -401,6 +398,7 @@ void LbmSolverInterface::initGeoTree(int id) { mpGiObjects = scene->getObjects(); mGiObjInside.resize( mpGiObjects->size() ); mGiObjDistance.resize( mpGiObjects->size() ); + mGiObjSecondDist.resize( mpGiObjects->size() ); for(size_t i=0; isize(); i++) { if((*mpGiObjects)[i]->getGeoInitIntersect()) mAccurateGeoinit=true; } @@ -436,6 +434,7 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int for(size_t i=0; iintersect(ray,distance,normal, triIns, flags, true); + if(triIns) { + ntlVec3Gfx norg = ray.getOrigin() + ray.getDirection()*distance; + LbmFloat orientation = dot(normal, dir); + OId = triIns->getObjectId(); + if(orientation<=0.0) { + // outside hit + normal *= -1.0; + //mGiObjDistance[OId] = -1.0; + //errMsg("IIO"," oid:"<0.0)) { + if( (distance<0.0) || // first intersection -> good + ((distance>0.0)&&(distance>mGiObjDistance[i])) // more than one intersection -> use closest one + ) { + distance = mGiObjDistance[i]; + OId = i; + inside = true; + } + } + } + // now check for thin hits + if(!inside) { + distance = -1.0; + for(size_t i=0; i=2)&&(mGiObjDistance[i]>0.0)&&(mGiObjSecondDist[i]>0.0)&& + (mGiObjDistance[i]<1.0*halfCellsize)&&(mGiObjSecondDist[i]<2.0*halfCellsize) ) { + if( (distance<0.0) || // first intersection -> good + ((distance>0.0)&&(distance>mGiObjDistance[i])) // more than one intersection -> use closest one + ) { + distance = mGiObjDistance[i]; + OId = i; + inside = true; + thinHit = true; + } + } + } + } + if(!inside) { + // check for hit in this cell, opposite to current dir (only recurse once) + if(recurse) { + gfxReal r_distance; + int r_OId; + bool ret = geoInitCheckPointInside(org, dir*-1.0, flags, r_OId, r_distance, halfCellsize, thinHit, false); + if((ret)&&(thinHit)) { + OId = r_OId; + distance = 0.0; + return true; + } + } + } + // really no hit... + if(!inside) { + distance = firstHit; + OId = firstOId; + /*if((mGiObjDistance[OId]>0.0)&&(mGiObjSecondDist[OId]>0.0)) { + const gfxReal thisdist = mGiObjSecondDist[OId]-mGiObjDistance[OId]; + // dont walk over this cell... + if(thisdistintersect(ray,distance,normal, triIns, flags, true); + if(triIns) { + // check outside intersect + LbmFloat orientation = dot(normal, dir); + if(orientation<=0.0) return false; + + OId = triIns->getObjectId(); + return true; + } + return false; + } +} /*****************************************************************************/ /*! get max. velocity of all objects to initialize as fluid regions */ diff --git a/intern/elbeem/intern/lbminterface.h b/intern/elbeem/intern/solver_interface.h similarity index 59% rename from intern/elbeem/intern/lbminterface.h rename to intern/elbeem/intern/solver_interface.h index 073558e1309..55e5d61fe45 100644 --- a/intern/elbeem/intern/lbminterface.h +++ b/intern/elbeem/intern/solver_interface.h @@ -288,6 +288,8 @@ class LbmSolverInterface void freeGeoTree(); /*! check for a certain flag type at position org (needed for e.g. quadtree refinement) */ bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance); + bool geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir, int flags, int &OId, gfxReal &distance, + const gfxReal halfCellsize, bool &thinHit, bool recurse); /*! set render globals, for scene/tree access */ void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; }; /*! get max. velocity of all objects to initialize as fluid regions */ @@ -378,6 +380,13 @@ class LbmSolverInterface virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0; virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0; + // gui/output debugging functions +#if LBM_USE_GUI==1 + virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifier cell ) = 0; + virtual void lbmDebugDisplay(fluidDispSettings *dispset) = 0; + virtual void lbmMarkedCellDisplay() = 0; +#endif // LBM_USE_GUI==1 + virtual void debugPrintNodeInfo(CellIdentifier cell, int forceSet=-1) = 0; // debugging cell marker functions @@ -500,6 +509,7 @@ class LbmSolverInterface vector mGiObjInside; /*! inside which objects? */ vector mGiObjDistance; + vector mGiObjSecondDist; /*! remember globals */ ntlRenderGlobals *mpGlob; @@ -509,6 +519,375 @@ class LbmSolverInterface }; +//! shorten static const definitions +#define STCON static const + + +/*****************************************************************************/ +/*! class for solver templating - 3D implementation */ +class LbmD3Q19 { + + public: + + // constructor, init interface + LbmD3Q19() {}; + // virtual destructor + virtual ~LbmD3Q19() {}; + //! id string of solver + string getIdString() { return string("3D"); } + + //! how many dimensions? + STCON int cDimension; + + // Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + //! direction vector contain vecs for all spatial dirs, even if not used for LBM model + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirT = 5, + cDirB = 6, + cDirNE = 7, + cDirNW = 8, + cDirSE = 9, + cDirSW = 10, + cDirNT = 11, + cDirNB = 12, + cDirST = 13, + cDirSB = 14, + cDirET = 15, + cDirEB = 16, + cDirWT = 17, + cDirWB = 18 + } dfDir; + + /* Vector Order 3D: + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + * 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 + * 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 + * 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 + */ + + /*! name of the dist. function + only for nicer output */ + STCON char* dfString[ 19 ]; + + /*! index of normal dist func, not used so far?... */ + STCON int dfNorm[ 19 ]; + + /*! index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 19 ]; + + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 19 ]; + + /*! dist func vectors */ + STCON int dfVecX[ 27 ]; + STCON int dfVecY[ 27 ]; + STCON int dfVecZ[ 27 ]; + + /*! arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 27 ]; + STCON LbmFloat dfDvecY[ 27 ]; + STCON LbmFloat dfDvecZ[ 27 ]; + + /*! principal directions */ + STCON int princDirX[ 2*3 ]; + STCON int princDirY[ 2*3 ]; + STCON int princDirZ[ 2*3 ]; + + /*! vector lengths */ + STCON LbmFloat dfLength[ 19 ]; + + /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 19 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ]; + static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ]; + +}; // LbmData3D + + + +/*****************************************************************************/ +//! class for solver templating - 2D implementation +class LbmD2Q9 { + + public: + + // constructor, init interface + LbmD2Q9() {}; + // virtual destructor + virtual ~LbmD2Q9() {}; + //! id string of solver + string getIdString() { return string("2D"); } + + //! how many dimensions? + STCON int cDimension; + + //! Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirNE = 5, + cDirNW = 6, + cDirSE = 7, + cDirSW = 8 + } dfDir; + + /* Vector Order 2D: + * 0 1 2 3 4 5 6 7 8 + * 0, 0,0, 1,-1, 1,-1,1,-1 + * 0, 1,-1, 0,0, 1,1,-1,-1 */ + + /* name of the dist. function + only for nicer output */ + STCON char* dfString[ 9 ]; + + /* index of normal dist func, not used so far?... */ + STCON int dfNorm[ 9 ]; + + /* index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 9 ]; + + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 9 ]; + + /* dist func vectors */ + STCON int dfVecX[ 9 ]; + STCON int dfVecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON int dfVecZ[ 9 ]; + + /* arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 9 ]; + STCON LbmFloat dfDvecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON LbmFloat dfDvecZ[ 9 ]; + + /*! principal directions */ + STCON int princDirX[ 2*2 ]; + STCON int princDirY[ 2*2 ]; + STCON int princDirZ[ 2*2 ]; + + /* vector lengths */ + STCON LbmFloat dfLength[ 9 ]; + + /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 9 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ]; + static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ]; + +}; // LbmData3D + + + +// lbmdimensions + +// not needed hereafter +#undef STCON + + + +/*****************************************************************************/ +//! class for solver templating - lbgk (srt) model implementation +template +class LbmModelLBGK : public DQ , public LbmSolverInterface { + public: + + /*! type for cells contents, needed for cell id interface */ + typedef DQ LbmCellContents; + /*! type for cells */ + typedef LbmCellTemplate< LbmCellContents > LbmCell; + + // constructor + LbmModelLBGK() : DQ(), LbmSolverInterface() {}; + // virtual destructor + virtual ~LbmModelLBGK() {}; + //! id string of solver + string getIdString() { return DQ::getIdString() + string("lbgk]"); } + + /*! calculate length of velocity vector */ + static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) { + return ((ux)*DQ::dfDvecX[l]+(uy)*DQ::dfDvecY[l]+(uz)*DQ::dfDvecZ[l]); + }; + + /*! calculate equilibrium DF for given values */ + static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) { + LbmFloat tmp = getVelVecLen(l,ux,uy,uz); + return( DQ::dfLength[l] *( + + rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) + + 3.0 *tmp + + 9.0/2.0 *(tmp*tmp) ) + ); + }; + + + // input mux etc. as acceleration + // outputs rho,ux,uy,uz + /*inline void collideArrays_org(LbmFloat df[19], + LbmFloat &outrho, // out only! + // velocity modifiers (returns actual velocity!) + LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, + LbmFloat omega + ) { + LbmFloat rho=df[0]; + LbmFloat ux = mux; + LbmFloat uy = muy; + LbmFloat uz = muz; + for(int l=1; l0.0) { + LbmFloat Qo = getLesNoneqTensorCoeff(df,feq); + omegaNew = getLesOmega(omega,csmago,Qo); + } else { + omegaNew = omega; // smago off... + } + if(newOmegaRet) *newOmegaRet=omegaNew; // return value for stats + + for(int l=0; l LbmBGK2D; +typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D; + + //! helper function to convert flag to string (for debuggin) string convertCellFlagType2String( CellFlagType flag ); string convertSingleFlag2String(CellFlagType cflag); diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp new file mode 100644 index 00000000000..8b4a33e42f3 --- /dev/null +++ b/intern/elbeem/intern/solver_main.cpp @@ -0,0 +1,2684 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004,2005 Nils Thuerey + * + * Standard LBM Factory implementation + * + *****************************************************************************/ + +#include "solver_class.h" +#include "solver_relax.h" + +/*****************************************************************************/ +/*! debug object display */ +/*****************************************************************************/ +template +vector LbmFsgrSolver::getDebugObjects() { + vector debo; + if(mOutputSurfacePreview) { + debo.push_back( mpPreviewSurface ); + } + return debo; +} + +/*****************************************************************************/ +/*! perform a single LBM step */ +/*****************************************************************************/ + +template +void +LbmFsgrSolver::stepMain() +{ +#if ELBEEM_BLENDER==1 + // update gui display + SDL_mutexP(globalBakeLock); + if(globalBakeState<0) { + // this means abort... cause panic + D::mPanic = 1; + errMsg("LbmFsgrSolver::step","Got abort signal from GUI, causing panic, aborting..."); + } + SDL_mutexV(globalBakeLock); +#endif // ELBEEM_BLENDER==1 + D::markedClearList(); // DMC clearMarkedCellsList + + // safety check, counter reset + D::mNumUsedCells = 0; + mNumInterdCells = 0; + mNumInvIfCells = 0; + + //debugOutNnl("LbmFsgrSolver::step : "<mMaxNoCells) mMaxNoCells = D::mNumUsedCells; + if(D::mNumUsedCells0)&&(mInitialMass>0.0)) { + LbmFloat mscale = mInitialMass/mCurrentMass; + + mscale = 1.0; + const LbmFloat dchh = 0.001; + if(mCurrentMassmInitialMass) mscale = 1.0-dchh; + + // use mass rescaling? + // with float precision this seems to be nonsense... + const bool MREnable = false; + + const int MSInter = 2; + static int mscount = 0; + if( (MREnable) && ((mLevel[0].lsteps%MSInter)== (MSInter-1)) && ( ABS( (mInitialMass/mCurrentMass)-1.0 ) > 0.01) && ( dsbits & (1<<(mMaxRefine-0)) ) ){ + // example: FORCE RESCALE MASS! ini:1843.5, cur:1817.6, f=1.01425 step:22153 levstep:5539 msc:37 + // mass rescale MASS RESCALE check + errMsg("MDTDD","\n\n"); + errMsg("MDTDD","FORCE RESCALE MASS! " + <<"ini:"<=0 ; lev--) { + //for(int workSet = 0; workSet<=1; workSet++) { + int wss = 0; + int wse = 1; +#if COMPRESSGRIDS==1 + if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; +#endif // COMPRESSGRIDS==1 + for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT + + FSGR_FORIJK1(lev) { + if( (RFLAG(lev,i,j,k, workSet) & (CFFluid| CFInter| CFGrFromCoarse| CFGrFromFine| CFGrNorm)) + ) { + + FORDF0 { QCELL(lev, i,j,k,workSet, l) *= mscale; } + QCELL(lev, i,j,k,workSet, dMass) *= mscale; + QCELL(lev, i,j,k,workSet, dFfrac) *= mscale; + + } else { + continue; + } + } + } + mLevel[lev].lmass *= mscale; + } + } + + mCurrentMass *= mscale; + }// if mass scale test */ + else { + // use current mass after full step for initial setting + if((mMaxRefine>0)&&(mInitialMass<=0.0) && (levsteps == (mMaxRefine+1))) { + mInitialMass = mCurrentMass; + debMsgStd("MDTDD",DM_NOTIFY,"Second Initial Mass Init: "< +void +LbmFsgrSolver::fineAdvance() +{ + // do the real thing... + mainLoop( mMaxRefine ); + if(mUpdateFVHeight) { + // warning assume -Y gravity... + mFVHeight = mCurrentMass*mFVArea/((LbmFloat)(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizez)); + if(mFVHeight<1.0) mFVHeight = 1.0; + D::mpParam->setFluidVolumeHeight(mFVHeight); + } + + // advance time before timestep change + mSimulationTime += D::mpParam->getStepTime(); + // time adaptivity + D::mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) ); + //if(mStartSymm) { checkSymmetry("step2"); } // DEBUG + if(!D::mSilent){ errMsg("fineAdvance"," stepped from "< +void +LbmFsgrSolver::mainLoop(int lev) +{ + // loops over _only inner_ cells ----------------------------------------------------------------------------------- + LbmFloat calcCurrentMass = 0.0; + LbmFloat calcCurrentVolume = 0.0; + int calcCellsFilled = D::mNumFilledCells; + int calcCellsEmptied = D::mNumEmptiedCells; + int calcNumUsedCells = D::mNumUsedCells; + +#if PARALLEL==1 +#include "paraloop.h" +#else // PARALLEL==1 + { // main loop region + int kstart=D::getForZMin1(), kend=D::getForZMax1(); +#define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); +#endif // PARALLEL==1 + + + // local to loop + CellFlagType nbflag[LBM_DFNUM]; +#define NBFLAG(l) nbflag[(l)] + // */ + + LbmFloat *ccel = NULL; + LbmFloat *tcel = NULL; + int oldFlag; + int newFlag; + int nbored; + LbmFloat m[LBM_DFNUM]; + LbmFloat rho, ux, uy, uz, tmp, usqr; + LbmFloat mass, change; + usqr = tmp = 0.0; +#if OPT3D==1 + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; +#endif // OPT3D==true + + + // ifempty cell conversion flags + bool iffilled, ifemptied; + int recons[LBM_DFNUM]; // reconstruct this DF? + int numRecons; // how many are reconstructed? + + + CellFlagType *pFlagSrc; + CellFlagType *pFlagDst; + pFlagSrc = &RFLAG(lev, 0,1, kstart,SRCS(lev)); // omp + pFlagDst = &RFLAG(lev, 0,1, kstart,TSET(lev)); // omp + ccel = RACPNT(lev, 0,1, kstart ,SRCS(lev)); // omp + tcel = RACPNT(lev, 0,1, kstart ,TSET(lev)); // omp + //CellFlagType *pFlagTar = NULL; + int pFlagTarOff; + if(mLevel[lev].setOther==1) pFlagTarOff = mLevel[lev].lOffsz; + else pFlagTarOff = -mLevel[lev].lOffsz; +#define ADVANCE_POINTERS(p) \ + ccel += (QCELLSTEP*(p)); \ + tcel += (QCELLSTEP*(p)); \ + pFlagSrc+= (p); \ + pFlagDst+= (p); \ + i+= (p); + + + // --- + // now stream etc. + + // use template functions for 2D/3D +#if COMPRESSGRIDS==0 + for(int k=kstart;k>24; + if(!isValid) { + // make new if cell + const LbmVec vel(mObjectSpeeds[OId]); + // TODO add OPT3D treatment + FORDF0 { RAC(tcel, l) = D::getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } + RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; + RAC(tcel, dFlux) = FLUX_INIT; + changeFlag(lev, i,j,k, TSET(lev), CFInter); + calcCurrentMass += iniRho; calcCurrentVolume += 1.0; calcNumUsedCells++; + mInitialMass += iniRho; + // dont treat cell until next step + continue; + } + } + else // these are exclusive + if(oldFlag & (CFMbndOutflow)) { + int isnotValid = oldFlag & (CFFluid); + if(isnotValid) { + // remove fluid cells, shouldnt be here anyway + LbmFloat fluidRho = m[0]; FORDF1 { fluidRho += m[l]; } + mInitialMass -= fluidRho; + const LbmFloat iniRho = 0.0; + RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; + RAC(tcel, dFlux) = FLUX_INIT; + changeFlag(lev, i,j,k, TSET(lev), CFInter); + + // same as ifemptied for if below + LbmPoint emptyp; + emptyp.x = i; emptyp.y = j; emptyp.z = k; +#if PARALLEL==1 + calcListEmpty[id].push_back( emptyp ); +#else // PARALLEL==1 + mListEmpty.push_back( emptyp ); +#endif // PARALLEL==1 + calcCellsEmptied++; + continue; + } + } + + if(oldFlag & (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused)) { + *pFlagDst = oldFlag; + //RAC(tcel,dFfrac) = 0.0; + //RAC(tcel,dFlux) = FLUX_INIT; // necessary? + continue; + } + /*if( oldFlag & CFNoBndFluid ) { // TEST ME FASTER? + OPTIMIZED_STREAMCOLLIDE; PERFORM_USQRMAXCHECK; + RAC(tcel,dFfrac) = 1.0; + *pFlagDst = (CellFlagType)oldFlag; // newFlag; + calcCurrentMass += rho; calcCurrentVolume += 1.0; + calcNumUsedCells++; + continue; + }// TEST ME FASTER? */ + + // only neighbor flags! not own flag + nbored = 0; + +#if OPT3D==0 + FORDF1 { + nbflag[l] = RFLAG_NB(lev, i,j,k,SRCS(lev),l); + nbored |= nbflag[l]; + } +#else + nbflag[dSB] = *(pFlagSrc + (-mLevel[lev].lOffsy+-mLevel[lev].lOffsx)); nbored |= nbflag[dSB]; + nbflag[dWB] = *(pFlagSrc + (-mLevel[lev].lOffsy+-1)); nbored |= nbflag[dWB]; + nbflag[ dB] = *(pFlagSrc + (-mLevel[lev].lOffsy)); nbored |= nbflag[dB]; + nbflag[dEB] = *(pFlagSrc + (-mLevel[lev].lOffsy+ 1)); nbored |= nbflag[dEB]; + nbflag[dNB] = *(pFlagSrc + (-mLevel[lev].lOffsy+ mLevel[lev].lOffsx)); nbored |= nbflag[dNB]; + + nbflag[dSW] = *(pFlagSrc + (-mLevel[lev].lOffsx+-1)); nbored |= nbflag[dSW]; + nbflag[ dS] = *(pFlagSrc + (-mLevel[lev].lOffsx)); nbored |= nbflag[dS]; + nbflag[dSE] = *(pFlagSrc + (-mLevel[lev].lOffsx+ 1)); nbored |= nbflag[dSE]; + + nbflag[ dW] = *(pFlagSrc + (-1)); nbored |= nbflag[dW]; + nbflag[ dE] = *(pFlagSrc + ( 1)); nbored |= nbflag[dE]; + + nbflag[dNW] = *(pFlagSrc + ( mLevel[lev].lOffsx+-1)); nbored |= nbflag[dNW]; + nbflag[ dN] = *(pFlagSrc + ( mLevel[lev].lOffsx)); nbored |= nbflag[dN]; + nbflag[dNE] = *(pFlagSrc + ( mLevel[lev].lOffsx+ 1)); nbored |= nbflag[dNE]; + + nbflag[dST] = *(pFlagSrc + ( mLevel[lev].lOffsy+-mLevel[lev].lOffsx)); nbored |= nbflag[dST]; + nbflag[dWT] = *(pFlagSrc + ( mLevel[lev].lOffsy+-1)); nbored |= nbflag[dWT]; + nbflag[ dT] = *(pFlagSrc + ( mLevel[lev].lOffsy)); nbored |= nbflag[dT]; + nbflag[dET] = *(pFlagSrc + ( mLevel[lev].lOffsy+ 1)); nbored |= nbflag[dET]; + nbflag[dNT] = *(pFlagSrc + ( mLevel[lev].lOffsy+ mLevel[lev].lOffsx)); nbored |= nbflag[dNT]; + // */ +#endif + + // pointer to destination cell + calcNumUsedCells++; + + // FLUID cells + if( oldFlag & CFFluid ) { + // only standard fluid cells (with nothing except fluid as nbs + + if(oldFlag&CFMbndInflow) { + // force velocity for inflow + const int OId = oldFlag>>24; + DEFAULT_STREAM; + //const LbmFloat fluidRho = 1.0; + // for submerged inflows, streaming would have to be performed... + LbmFloat fluidRho = m[0]; FORDF1 { fluidRho += m[l]; } + const LbmVec vel(mObjectSpeeds[OId]); + ux=vel[0], uy=vel[1], uz=vel[2]; + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); + FORDF0 { RAC(tcel, l) = D::getCollideEq(l, fluidRho,ux,uy,uz); } + rho = fluidRho; + } else { + if(nbored&CFBnd) { + DEFAULT_STREAM; + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + DEFAULT_COLLIDE; + oldFlag &= (~CFNoBndFluid); + } else { + // do standard stream/collide + OPTIMIZED_STREAMCOLLIDE; + // FIXME check for which cells this is executed! + oldFlag |= CFNoBndFluid; + } + } + + PERFORM_USQRMAXCHECK; + // "normal" fluid cells + RAC(tcel,dFfrac) = 1.0; + *pFlagDst = (CellFlagType)oldFlag; // newFlag; + //? LbmFloat ofrho=RAC(ccel,0); for(int l=1; l just empty + change = - mynbfac*MYDF(l) ; goto changeDone; + } + break; + + case CFNoNbEmpty: + // we dont have empty nb's so... + switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { + case 0: + case CFNoNbFluid: + // we have no empty nb's -> just fill + change = nbnbfac*nbdf(l); goto changeDone; + } + break; + }} // inter-inter exchange + + // just do normal mass exchange... + change = ( nbnbfac*nbdf(l) - mynbfac*MYDF(l) ) ; + changeDone: ; + change *= ( myfrac + QCELL_NB(lev, i,j,k, SRCS(lev),l, dFfrac) ) * 0.5; + } // the other cell is interface + + // last alternative - reconstruction in this direction + else { + //if(NBFLAG(l) & CFEmpty) { recons[l] = true; } + recons[l] = 1; + numRecons++; + change = 0.0; + // which case is this...? empty + bnd + } + + //FST errMsg("TTTIF","at "< LBM_EPSILON) { + // normal ok and usable... + FORDF1 { + if( (D::dfDvecX[l]*nx + D::dfDvecY[l]*ny + D::dfDvecZ[l]*nz) // dot Dvec,norml + > LBM_EPSILON) { + recons[l] = 2; + numRecons++; + } + } + } + + // calculate macroscopic cell values + LbmFloat oldUx, oldUy, oldUz; + LbmFloat oldRho; // OLD rho = ccel->rho; +#if OPT3D==0 + oldRho=RAC(ccel,0); + oldUx = oldUy = oldUz = 0.0; + for(int l=1; l= (rho * (1.0+FSGR_MAGICNR)) ) { iffilled = 1; } + // interface cell if empty? + if( (mass) <= (rho * ( -FSGR_MAGICNR)) ) { ifemptied = 1; } + + if(oldFlag & (CFMbndOutflow)) { + mInitialMass -= mass; + mass = myfrac = 0.0; + iffilled = 0; ifemptied = 1; + } + + // looks much nicer... LISTTRICK +#if FSGR_LISTTRICK==1 + if(!iffilled) { + // remove cells independent from amount of change... + if( (oldFlag & CFNoNbEmpty)&&(newFlag & CFNoNbEmpty)&& + ( (mass>(rho*FSGR_LISTTTHRESHFULL)) || ((nbored&CFInter)==0) ) + ) { + //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","filled "< better cell conversions + RAC(tcel,dFfrac) = (mass/rho); + + // init new flux value + float flux = 0.5*(float)(D::cDfNum); // dxqn on + //flux = 50.0; // extreme on + for(int nn=1; nnmMaxVlen) { + mMxvx = calcMxvx[i]; + mMxvy = calcMxvy[i]; + mMxvz = calcMxvz[i]; + mMaxVlen = calcMaxVlen[i]; + } + errMsg("PARALLELusqrcheck"," curr: "< +void +LbmFsgrSolver::coarseCalculateFluxareas(int lev) +{ + //LbmFloat calcCurrentMass = 0.0; + //LbmFloat calcCurrentVolume = 0.0; + //LbmFloat *ccel = NULL; + //LbmFloat *tcel = NULL; + //LbmFloat m[LBM_DFNUM]; + //LbmFloat rho, ux, uy, uz, tmp, usqr; +#if OPT3D==1 + //LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; +#endif // OPT3D==true + //m[0] = tmp = usqr = 0.0; + + //for(int lev=0; lev +void +LbmFsgrSolver::coarseAdvance(int lev) +{ + LbmFloat calcCurrentMass = 0.0; + LbmFloat calcCurrentVolume = 0.0; + + LbmFloat *ccel = NULL; + LbmFloat *tcel = NULL; + LbmFloat m[LBM_DFNUM]; + LbmFloat rho, ux, uy, uz, tmp, usqr; +#if OPT3D==1 + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; +#endif // OPT3D==true + m[0] = tmp = usqr = 0.0; + + coarseCalculateFluxareas(lev); + // copied from fineAdv. + CellFlagType *pFlagSrc = &RFLAG(lev, 1,1,getForZMin1(),SRCS(lev)); + CellFlagType *pFlagDst = &RFLAG(lev, 1,1,getForZMin1(),TSET(lev)); + pFlagSrc -= 1; + pFlagDst -= 1; + ccel = RACPNT(lev, 1,1,getForZMin1() ,SRCS(lev)); // QTEST + ccel -= QCELLSTEP; + tcel = RACPNT(lev, 1,1,getForZMin1() ,TSET(lev)); // QTEST + tcel -= QCELLSTEP; + //if(strstr(D::getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } + + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j remove + if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + bool invNb = false; + FORDF1 { + if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } + } + if(!invNb) { + *pFlagSrc = CFFluid|CFGrNorm; +#if ELBEEM_BLENDER!=1 + errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<0.0) { + const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feq); + omegaDst = D::getLesOmega(mLevel[lev ].omega,mLevel[lev ].lcsmago,Qo); + omegaSrc = D::getLesOmega(mLevel[lev+1].omega,mLevel[lev+1].lcsmago,Qo); + } else { + omegaDst = mLevel[lev+0].omega; /* NEWSMAGOT*/ + omegaSrc = mLevel[lev+1].omega; + } + dfScale = (mLevel[lev ].stepsize/mLevel[lev+1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); // yu + FORDF0{ + RAC(tcel, l) = feq[l]+ (df[l]-feq[l])*dfScale; + } +# else // OPT3D + // similar to OPTIMIZED_STREAMCOLLIDE_UNUSED + + //rho = ux = uy = uz = 0.0; + MSRC_C = CCELG_C(0) ; + MSRC_N = CCELG_N(0) ; + MSRC_S = CCELG_S(0) ; + MSRC_E = CCELG_E(0) ; + MSRC_W = CCELG_W(0) ; + MSRC_T = CCELG_T(0) ; + MSRC_B = CCELG_B(0) ; + MSRC_NE = CCELG_NE(0); + MSRC_NW = CCELG_NW(0); + MSRC_SE = CCELG_SE(0); + MSRC_SW = CCELG_SW(0); + MSRC_NT = CCELG_NT(0); + MSRC_NB = CCELG_NB(0); + MSRC_ST = CCELG_ST(0); + MSRC_SB = CCELG_SB(0); + MSRC_ET = CCELG_ET(0); + MSRC_EB = CCELG_EB(0); + MSRC_WT = CCELG_WT(0); + MSRC_WB = CCELG_WB(0); + for(int n=1;(n +bool +LbmFsgrSolver::performRefinement(int lev) { + if((lev<0) || ((lev+1)>mMaxRefine)) return false; + bool change = false; + //bool nbsok; + // FIXME remove TIMEINTORDER ? + LbmFloat interTime = 0.0; + // update curr from other, as streaming afterwards works on curr + // thus read only from srcSet, modify other + const int srcSet = mLevel[lev].setOther; + const int dstSet = mLevel[lev].setCurr; + const int srcFineSet = mLevel[lev+1].setCurr; + const bool debugRefinement = false; + + // use template functions for 2D/3D + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j remove + /*if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + bool invNb = false; + FORDF1 { + if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } + } + if(!invNb) { + *pFlagSrc = CFFluid|CFGrNorm; + errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "< remove + bool invNb = false; + bool fluidNb = false; + for(int l=1; l calculate normally from now on + RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + } // from advance */ + if(!fluidNb) { + // no fluid cells near -> no transfer necessary + RFLAG(lev, i,j,k, dstSet) = CFUnused; + //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFUnused; // FLAGTEST + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + } // from advance */ + + + // dont allow double transfer + // this might require fixing the neighborhood + if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse)) { + // dont turn CFGrFromFine above interface cells into CFGrNorm + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<0) RFLAG(lev-1, i/2,j/2,k/2, mLevel[lev-1].setCurr) &= (~CFGrToFine); // TODO add more of these? + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + for(int l=1; l +bool +LbmFsgrSolver::performCoarsening(int lev) { + //if(D::mInitDone){ errMsg("performCoarsening","skip"); return 0;} // DEBUG + + if((lev<0) || ((lev+1)>mMaxRefine)) return false; + bool change = false; + bool nbsok; + // hence work on modified curr set + const int srcSet = mLevel[lev].setCurr; + const int dstlev = lev+1; + const int dstFineSet = mLevel[dstlev].setCurr; + const bool debugCoarsening = false; + + // use template functions for 2D/3D + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j remove + // perform check from coarseAdvance here? + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + // remove from fine cells now that are completely in fluid + // FIXME? check that new from fine in performRefinement never get deleted here afterwards? + // or more general, one cell never changed more than once? + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + //const CellFlagType notNbAllowed = (CFInter|CFBnd|CFGrFromFine); unused + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + + nbsok = true; + for(int l=0; l from fine conversion + bool changeToFromFine = false; + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + +#if REFINEMENTBORDER==1 + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ + changeToFromFine=true; + } + /*if(strstr(D::getName().c_str(),"Debug")) + if((changeToFromFine)&&(lev+1==mMaxRefine)) { // mixborder + for(int l=0;((l +void +LbmFsgrSolver::adaptTimestep() +{ + LbmFloat massTOld=0.0, massTNew=0.0; + LbmFloat volTOld=0.0, volTNew=0.0; + + bool rescale = false; // do any rescale at all? + LbmFloat scaleFac = -1.0; // timestep scaling + + LbmFloat levOldOmega[FSGR_MAXNOOFLEVELS]; + LbmFloat levOldStepsize[FSGR_MAXNOOFLEVELS]; + for(int lev=mMaxRefine; lev>=0 ; lev--) { + levOldOmega[lev] = mLevel[lev].omega; + levOldStepsize[lev] = mLevel[lev].stepsize; + } + //if(mTimeSwitchCounts>0){ errMsg("DEB CSKIP",""); return; } // DEBUG + + LbmFloat fac = 0.8; // modify time step by 20%, TODO? do multiple times for large changes? + LbmFloat diffPercent = 0.05; // dont scale if less than 5% + LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity + LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); + + //newdt = D::mpParam->getStepTime() * (allowMax/nextmax); + LbmFloat newdt = D::mpParam->getStepTime(); // newtr + if(nextmax>allowMax/fac) { + newdt = D::mpParam->getStepTime() * fac; + } else { + if(nextmaxgetStepTime() / fac; + } + } // newtr + //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<getMaxStepTime()<<" min"<getMinStepTime()<<" diff"<getStepTime() ) // DEBUG + LbmFloat rhoAvg = mCurrentMass/mCurrentVolume; + if( (newdt<=D::mpParam->getMaxStepTime()) && (newdt>=D::mpParam->getMinStepTime()) + && (dtdiff>(D::mpParam->getStepTime()*diffPercent)) ) { + if((newdt>levOldStepsize[mMaxRefine])&&(mTimestepReduceLock)) { + // wait some more... + //debMsgNnl("LbmFsgrSolver::TAdp",DM_NOTIFY," Delayed... "<setDesiredStepTime( newdt ); + rescale = true; + if(!D::mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"\n\n\n\n",10); + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<getSimulationMaxSpeed()<<" next:"<getStepTime(); + D::mpParam->setDesiredStepTime( newdt ); + } else + if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || + ((D::mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ + rescale = true; minCutoff = false; + newdt = D::mpParam->getStepTime()/tadtogSwitch ; + D::mpParam->setDesiredStepTime( newdt ); + } else { + rescale = false; minCutoff = false; + } + // */ + + // test mass rescale + + scaleFac = newdt/D::mpParam->getStepTime(); + if(rescale) { + // fixme - warum y, wird jetzt gemittelt... + mTimestepReduceLock = 4*(mLevel[mMaxRefine].lSizey+mLevel[mMaxRefine].lSizez+mLevel[mMaxRefine].lSizex)/3; + + mTimeSwitchCounts++; + D::mpParam->calculateAllMissingValues( D::mSilent ); + recalculateObjectSpeeds(); + // calc omega, force for all levels + initLevelOmegas(); + if(D::mpParam->getStepTime()getStepTime(); + if(D::mpParam->getStepTime()>mMaxStepTime) mMaxStepTime = D::mpParam->getStepTime(); + + for(int lev=mMaxRefine; lev>=0 ; lev--) { + LbmFloat newSteptime = mLevel[lev].stepsize; + LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); + + if(!D::mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<getCurrentGStar() , 10); + } + } // rescale? + + //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG + if(minCutoff) { + errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<=0 ; lev--) { + int rescs=0; + int wss = 0, wse = 1; +#if COMPRESSGRIDS==1 + if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; +#endif // COMPRESSGRIDS==1 + for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT + //for(int workSet = 0; workSet<=1; workSet++) { + FSGR_FORIJK1(lev) { + + //if( (RFLAG(lev, i,j,k, workSet) & CFFluid) || (RFLAG(lev, i,j,k, workSet) & CFInter) ) { + if( + (RFLAG(lev,i,j,k, workSet) & CFFluid) || + (RFLAG(lev,i,j,k, workSet) & CFInter) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || + (RFLAG(lev,i,j,k, workSet) & CFGrNorm) + ) { + // these cells have to be scaled... + } else { + continue; + } + + // collide on current set + LbmFloat rho, ux,uy,uz; + rho=0.0; ux = uy = uz = 0.0; + for(int l=0; l (allowMax*allowMax) ) { + LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); + ux *= cfac; + uy *= cfac; + uz *= cfac; + for(int l=0; l0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } + debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"< +LbmFloat +LbmFsgrSolver::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l) { + //return 0.0; // test + int level = mMaxRefine; + LbmFloat *ccel = RACPNT(level, i,j,k, workSet); + + LbmFloat nx,ny,nz, nv1,nv2; + if(RFLAG_NB(level,i,j,k,workSet, dE) &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(level,i,j,k,workSet, dW) &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); } else nv2 = 0.0; + nx = 0.5* (nv2-nv1); + if(RFLAG_NB(level,i,j,k,workSet, dN) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(level,i,j,k,workSet, dS) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv2 = 0.0; + ny = 0.5* (nv2-nv1); +#if LBMDIM==3 + if(RFLAG_NB(level,i,j,k,workSet, dT) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(level,i,j,k,workSet, dB) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv2 = 0.0; + nz = 0.5* (nv2-nv1); +#else //LBMDIM==3 + nz = 0.0; +#endif //LBMDIM==3 + LbmFloat scal = mDvecNrm[l][0]*nx + mDvecNrm[l][1]*ny + mDvecNrm[l][2]*nz; + + LbmFloat ret = 1.0; + // forward direction, add mass (for filling cells): + if(dirForw) { + if(scal-LBM_EPSILON) ret = 0.0; + else ret = scal * -1.0; + } + //errMsg("massd", PRINT_IJK<<" nv"< +void LbmFsgrSolver::reinitFlags( int workSet ) +{ + // OLD mods: + // add all to intel list? + // check ffrac for new cells + // new if cell inits (last loop) + // vweights handling + +#if ELBEEM_BLENDER==1 + const int debugFlagreinit = 0; +#else // ELBEEM_BLENDER==1 + const int debugFlagreinit = 0; +#endif // ELBEEM_BLENDER==1 + + // some things need to be read/modified on the other set + int otherSet = (workSet^1); + // fixed level on which to perform + int workLev = mMaxRefine; + + /* modify interface cells from lists */ + /* mark filled interface cells as fluid, or emptied as empty */ + /* count neighbors and distribute excess mass to interface neighbor cells + * problems arise when there are no interface neighbors anymore + * then just distribute to any fluid neighbors... + */ + + // for symmetry, first init all neighbor cells */ + for( vector::iterator iter=mListFull.begin(); + iter != mListFull.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if(debugFlagreinit) errMsg("FULL", PRINT_IJK<<" mss"<::iterator iter=mListEmpty.begin(); + iter != mListEmpty.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if((RFLAG(workLev,i,j,k, workSet)&(CFInter|CFNoDelete)) == (CFInter|CFNoDelete)) { + // remove entry + if(debugFlagreinit) errMsg("EMPT REMOVED!!!", PRINT_IJK<<" mss"< + let fill cells+surrounding interface cells have the higher importance */ + for( vector::iterator iter=mListEmpty.begin(); + iter != mListEmpty.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if((RFLAG(workLev,i,j,k, workSet)&(CFInter|CFNoDelete)) == (CFInter|CFNoDelete)){ errMsg("A"," ARGHARGRAG "); } // DEBUG + if(debugFlagreinit) errMsg("EMPT", PRINT_IJK<<" mss"<interface + //RFLAG(workLev,ni,nj,nk, workSet) = (CellFlagType)(CFInter); + changeFlag(workLev,ni,nj,nk, workSet, CFInter); + /* new mass = current density */ + LbmFloat nbrho = QCELL(workLev,ni,nj,nk, workSet, dC); + for(int rl=1; rl< D::cDfNum ; ++rl) { nbrho += QCELL(workLev,ni,nj,nk, workSet, rl); } + QCELL(workLev,ni,nj,nk, workSet, dMass) = nbrho; + QCELL(workLev,ni,nj,nk, workSet, dFfrac) = 1.0; + + // store point + addToNewInterList(ni,nj,nk); + } + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter){ + // test, also add to list... + addToNewInterList(ni,nj,nk); + } // NEW? + } + + /* for symmetry, set our flag right now */ + //RFLAG(workLev,i,j,k, workSet) = CFEmpty; + changeFlag(workLev,i,j,k, workSet, CFEmpty); + // mark cell not be changed mass... - not necessary, not in list anymore anyway! + } // emptylist + + + + // precompute weights to get rid of order dependancies + vector vWeights; + vWeights.reserve( mListFull.size() + mListEmpty.size() ); + int weightIndex = 0; + int nbCount = 0; + LbmFloat nbWeights[LBM_DFNUM]; + LbmFloat nbTotWeights = 0.0; + for( vector::iterator iter=mListFull.begin(); + iter != mListFull.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + nbCount = 0; nbTotWeights = 0.0; + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { + nbCount++; + nbWeights[l] = getMassdWeight(1,i,j,k,workSet,l); + nbTotWeights += nbWeights[l]; + } else { + nbWeights[l] = -100.0; // DEBUG; + } + } + if(nbCount>0) { + //errMsg("FF I", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); + iter != mListEmpty.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + nbCount = 0; nbTotWeights = 0.0; + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { + nbCount++; + nbWeights[l] = getMassdWeight(0,i,j,k,workSet,l); + nbTotWeights += nbWeights[l]; + } else { + nbWeights[l] = -100.0; // DEBUG; + } + } + if(nbCount>0) { + //errMsg("EE I", PRINT_IJK<<" "<::iterator iter=mListFull.begin(); + iter != mListFull.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + + LbmFloat myrho = QCELL(workLev,i,j,k, workSet, dC); + FORDF1 { myrho += QCELL(workLev,i,j,k, workSet, l); } // QCELL.rho + + LbmFloat massChange = QCELL(workLev,i,j,k, workSet, dMass) - myrho; + /*int nbCount = 0; + LbmFloat nbWeights[LBM_DFNUM]; + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { + nbCount++; + nbWeights[l] = vWeights[weightIndex].val[l]; + } else { + } + }*/ + + //errMsg("FDIST", PRINT_IJK<<" mss"<0.0) { + const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; + //errMsg("FF I", PRINT_IJK<<" "<0.0) { + //change = massChange * ( nbWeights[l]/nbTotWeightsp ); + change = massChange * ( vWeights[weightIndex].val[l]/nbTotWeightsp ); + } else { + change = (LbmFloat)(massChange/vWeights[weightIndex].numNbs); + } + QCELL(workLev,ni,nj,nk, workSet, dMass) += change; + } + } + massChange = 0.0; + } else { + // Problem! no interface neighbors + D::mFixMass += massChange; + //TTT mNumProblems++; + //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); + iter != mListEmpty.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + + LbmFloat massChange = QCELL(workLev, i,j,k, workSet, dMass); + /*int nbCount = 0; + LbmFloat nbWeights[LBM_DFNUM]; + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { + nbCount++; + nbWeights[l] = vWeights[weightIndex].val[l]; + } else { + nbWeights[l] = -100.0; // DEBUG; + } + }*/ + + //errMsg("EDIST", PRINT_IJK<<" mss"<0) { + if(vWeights[weightIndex].numNbs>0.0) { + const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; + //errMsg("EE I", PRINT_IJK<<" "<0.0) { + change = massChange * ( vWeights[weightIndex].val[l]/nbTotWeightsp ); + } else { + change = (LbmFloat)(massChange/vWeights[weightIndex].numNbs); + } + QCELL(workLev, ni,nj,nk, workSet, dMass) += change; + } + } + massChange = 0.0; + } else { + // Problem! no interface neighbors + D::mFixMass += massChange; + //TTT mNumProblems++; + //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<::iterator iter=mListEmpty.begin(); + iter != mListEmpty.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + //RFLAG(workLev,i,j,k, otherSet) = CFEmpty; + changeFlag(workLev,i,j,k, otherSet, CFEmpty); + /*QCELL(workLev,i,j,k, otherSet, dMass) = 0.0; + QCELL(workLev,i,j,k, otherSet, dFfrac) = 0.0; // COMPRT OFF */ + } + + + // check if some of the new interface cells can be removed again + // never happens !!! not necessary + // calculate ffrac for new IF cells NEW + + // how many are really new interface cells? + int numNewIf = 0; + for( vector::iterator iter=mListNewInter.begin(); + iter != mListNewInter.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { + continue; + // FIXME remove from list? + } + numNewIf++; + } + + // redistribute mass, reinit flags + float newIfFac = 1.0/(LbmFloat)numNewIf; + for( vector::iterator iter=mListNewInter.begin(); + iter != mListNewInter.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { + //errMsg("???"," "<::iterator iter=mListNewInter.begin(); + iter != mListNewInter.end(); iter++ ) { + int i=iter->x, j=iter->y, k=iter->z; + if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { continue; } + + LbmFloat nrho = 0.0; + FORDF0 { nrho += QCELL(workLev, i,j,k, workSet, l); } + QCELL(workLev,i,j,k, workSet, dFfrac) = QCELL(workLev,i,j,k, workSet, dMass)/nrho; + QCELL(workLev,i,j,k, workSet, dFlux) = FLUX_INIT; + } + + if(mListNewInter.size()>0){ + //errMsg("FixMassDisted"," fm:"<(); +#endif // LBMDIM==2 +#if LBMDIM==3 + return new LbmFsgrSolver< LbmBGK3D >(); +#endif // LBMDIM==3 + return NULL; +} + +#if LBMDIM==2 +template class LbmFsgrSolver< LbmBGK2D >; +#endif // LBMDIM==2 +#if LBMDIM==3 +template class LbmFsgrSolver< LbmBGK3D >; +#endif // LBMDIM==3 diff --git a/intern/elbeem/intern/solver_relax.h b/intern/elbeem/intern/solver_relax.h new file mode 100644 index 00000000000..667e4bcab8a --- /dev/null +++ b/intern/elbeem/intern/solver_relax.h @@ -0,0 +1,1072 @@ +/****************************************************************************** + * + * El'Beem - the visual lattice boltzmann freesurface simulator + * All code distributed as part of El'Beem is covered by the version 2 of the + * GNU General Public License. See the file COPYING for details. + * Copyright 2003-2005 Nils Thuerey + * + * Combined 2D/3D Lattice Boltzmann relaxation macros + * + *****************************************************************************/ + + +/****************************************************************************** + * normal relaxation + *****************************************************************************/ + +// standard arrays +#define CSRC_C RAC(ccel , dC ) +#define CSRC_E RAC(ccel + (-1) *(dTotalNum), dE ) +#define CSRC_W RAC(ccel + (+1) *(dTotalNum), dW ) +#define CSRC_N RAC(ccel + (-mLevel[lev].lOffsx) *(dTotalNum), dN ) +#define CSRC_S RAC(ccel + (+mLevel[lev].lOffsx) *(dTotalNum), dS ) +#define CSRC_NE RAC(ccel + (-mLevel[lev].lOffsx-1) *(dTotalNum), dNE) +#define CSRC_NW RAC(ccel + (-mLevel[lev].lOffsx+1) *(dTotalNum), dNW) +#define CSRC_SE RAC(ccel + (+mLevel[lev].lOffsx-1) *(dTotalNum), dSE) +#define CSRC_SW RAC(ccel + (+mLevel[lev].lOffsx+1) *(dTotalNum), dSW) +#define CSRC_T RAC(ccel + (-mLevel[lev].lOffsy) *(dTotalNum), dT ) +#define CSRC_B RAC(ccel + (+mLevel[lev].lOffsy) *(dTotalNum), dB ) +#define CSRC_ET RAC(ccel + (-mLevel[lev].lOffsy-1) *(dTotalNum), dET) +#define CSRC_EB RAC(ccel + (+mLevel[lev].lOffsy-1) *(dTotalNum), dEB) +#define CSRC_WT RAC(ccel + (-mLevel[lev].lOffsy+1) *(dTotalNum), dWT) +#define CSRC_WB RAC(ccel + (+mLevel[lev].lOffsy+1) *(dTotalNum), dWB) +#define CSRC_NT RAC(ccel + (-mLevel[lev].lOffsy-mLevel[lev].lOffsx) *(dTotalNum), dNT) +#define CSRC_NB RAC(ccel + (+mLevel[lev].lOffsy-mLevel[lev].lOffsx) *(dTotalNum), dNB) +#define CSRC_ST RAC(ccel + (-mLevel[lev].lOffsy+mLevel[lev].lOffsx) *(dTotalNum), dST) +#define CSRC_SB RAC(ccel + (+mLevel[lev].lOffsy+mLevel[lev].lOffsx) *(dTotalNum), dSB) + +#define XSRC_C(x) RAC(ccel + (x) *dTotalNum, dC ) +#define XSRC_E(x) RAC(ccel + ((x)-1) *dTotalNum, dE ) +#define XSRC_W(x) RAC(ccel + ((x)+1) *dTotalNum, dW ) +#define XSRC_N(x) RAC(ccel + ((x)-mLevel[lev].lOffsx) *dTotalNum, dN ) +#define XSRC_S(x) RAC(ccel + ((x)+mLevel[lev].lOffsx) *dTotalNum, dS ) +#define XSRC_NE(x) RAC(ccel + ((x)-mLevel[lev].lOffsx-1) *dTotalNum, dNE) +#define XSRC_NW(x) RAC(ccel + ((x)-mLevel[lev].lOffsx+1) *dTotalNum, dNW) +#define XSRC_SE(x) RAC(ccel + ((x)+mLevel[lev].lOffsx-1) *dTotalNum, dSE) +#define XSRC_SW(x) RAC(ccel + ((x)+mLevel[lev].lOffsx+1) *dTotalNum, dSW) +#define XSRC_T(x) RAC(ccel + ((x)-mLevel[lev].lOffsy) *dTotalNum, dT ) +#define XSRC_B(x) RAC(ccel + ((x)+mLevel[lev].lOffsy) *dTotalNum, dB ) +#define XSRC_ET(x) RAC(ccel + ((x)-mLevel[lev].lOffsy-1) *dTotalNum, dET) +#define XSRC_EB(x) RAC(ccel + ((x)+mLevel[lev].lOffsy-1) *dTotalNum, dEB) +#define XSRC_WT(x) RAC(ccel + ((x)-mLevel[lev].lOffsy+1) *dTotalNum, dWT) +#define XSRC_WB(x) RAC(ccel + ((x)+mLevel[lev].lOffsy+1) *dTotalNum, dWB) +#define XSRC_NT(x) RAC(ccel + ((x)-mLevel[lev].lOffsy-mLevel[lev].lOffsx) *dTotalNum, dNT) +#define XSRC_NB(x) RAC(ccel + ((x)+mLevel[lev].lOffsy-mLevel[lev].lOffsx) *dTotalNum, dNB) +#define XSRC_ST(x) RAC(ccel + ((x)-mLevel[lev].lOffsy+mLevel[lev].lOffsx) *dTotalNum, dST) +#define XSRC_SB(x) RAC(ccel + ((x)+mLevel[lev].lOffsy+mLevel[lev].lOffsx) *dTotalNum, dSB) + + + +#define OMEGA(l) mLevel[(l)].omega + +#define EQC ( DFL1*(rho - usqr)) +#define EQN ( DFL2*(rho + uy*(4.5*uy + 3.0) - usqr)) +#define EQS ( DFL2*(rho + uy*(4.5*uy - 3.0) - usqr)) +#define EQE ( DFL2*(rho + ux*(4.5*ux + 3.0) - usqr)) +#define EQW ( DFL2*(rho + ux*(4.5*ux - 3.0) - usqr)) +#define EQT ( DFL2*(rho + uz*(4.5*uz + 3.0) - usqr)) +#define EQB ( DFL2*(rho + uz*(4.5*uz - 3.0) - usqr)) + +#define EQNE ( DFL3*(rho + (+ux+uy)*(4.5*(+ux+uy) + 3.0) - usqr)) +#define EQNW ( DFL3*(rho + (-ux+uy)*(4.5*(-ux+uy) + 3.0) - usqr)) +#define EQSE ( DFL3*(rho + (+ux-uy)*(4.5*(+ux-uy) + 3.0) - usqr)) +#define EQSW ( DFL3*(rho + (-ux-uy)*(4.5*(-ux-uy) + 3.0) - usqr)) +#define EQNT ( DFL3*(rho + (+uy+uz)*(4.5*(+uy+uz) + 3.0) - usqr)) +#define EQNB ( DFL3*(rho + (+uy-uz)*(4.5*(+uy-uz) + 3.0) - usqr)) +#define EQST ( DFL3*(rho + (-uy+uz)*(4.5*(-uy+uz) + 3.0) - usqr)) +#define EQSB ( DFL3*(rho + (-uy-uz)*(4.5*(-uy-uz) + 3.0) - usqr)) +#define EQET ( DFL3*(rho + (+ux+uz)*(4.5*(+ux+uz) + 3.0) - usqr)) +#define EQEB ( DFL3*(rho + (+ux-uz)*(4.5*(+ux-uz) + 3.0) - usqr)) +#define EQWT ( DFL3*(rho + (-ux+uz)*(4.5*(-ux+uz) + 3.0) - usqr)) +#define EQWB ( DFL3*(rho + (-ux-uz)*(4.5*(-ux-uz) + 3.0) - usqr)) + + +// this is a bit ugly, but necessary for the CSRC_ access... +#define MSRC_C m[dC ] +#define MSRC_N m[dN ] +#define MSRC_S m[dS ] +#define MSRC_E m[dE ] +#define MSRC_W m[dW ] +#define MSRC_T m[dT ] +#define MSRC_B m[dB ] +#define MSRC_NE m[dNE] +#define MSRC_NW m[dNW] +#define MSRC_SE m[dSE] +#define MSRC_SW m[dSW] +#define MSRC_NT m[dNT] +#define MSRC_NB m[dNB] +#define MSRC_ST m[dST] +#define MSRC_SB m[dSB] +#define MSRC_ET m[dET] +#define MSRC_EB m[dEB] +#define MSRC_WT m[dWT] +#define MSRC_WB m[dWB] + +// this is a bit ugly, but necessary for the ccel local access... +#define CCEL_C RAC(ccel, dC ) +#define CCEL_N RAC(ccel, dN ) +#define CCEL_S RAC(ccel, dS ) +#define CCEL_E RAC(ccel, dE ) +#define CCEL_W RAC(ccel, dW ) +#define CCEL_T RAC(ccel, dT ) +#define CCEL_B RAC(ccel, dB ) +#define CCEL_NE RAC(ccel, dNE) +#define CCEL_NW RAC(ccel, dNW) +#define CCEL_SE RAC(ccel, dSE) +#define CCEL_SW RAC(ccel, dSW) +#define CCEL_NT RAC(ccel, dNT) +#define CCEL_NB RAC(ccel, dNB) +#define CCEL_ST RAC(ccel, dST) +#define CCEL_SB RAC(ccel, dSB) +#define CCEL_ET RAC(ccel, dET) +#define CCEL_EB RAC(ccel, dEB) +#define CCEL_WT RAC(ccel, dWT) +#define CCEL_WB RAC(ccel, dWB) +// for coarse to fine interpol access +#define CCELG_C(f) (RAC(ccel, dC )*mGaussw[(f)]) +#define CCELG_N(f) (RAC(ccel, dN )*mGaussw[(f)]) +#define CCELG_S(f) (RAC(ccel, dS )*mGaussw[(f)]) +#define CCELG_E(f) (RAC(ccel, dE )*mGaussw[(f)]) +#define CCELG_W(f) (RAC(ccel, dW )*mGaussw[(f)]) +#define CCELG_T(f) (RAC(ccel, dT )*mGaussw[(f)]) +#define CCELG_B(f) (RAC(ccel, dB )*mGaussw[(f)]) +#define CCELG_NE(f) (RAC(ccel, dNE)*mGaussw[(f)]) +#define CCELG_NW(f) (RAC(ccel, dNW)*mGaussw[(f)]) +#define CCELG_SE(f) (RAC(ccel, dSE)*mGaussw[(f)]) +#define CCELG_SW(f) (RAC(ccel, dSW)*mGaussw[(f)]) +#define CCELG_NT(f) (RAC(ccel, dNT)*mGaussw[(f)]) +#define CCELG_NB(f) (RAC(ccel, dNB)*mGaussw[(f)]) +#define CCELG_ST(f) (RAC(ccel, dST)*mGaussw[(f)]) +#define CCELG_SB(f) (RAC(ccel, dSB)*mGaussw[(f)]) +#define CCELG_ET(f) (RAC(ccel, dET)*mGaussw[(f)]) +#define CCELG_EB(f) (RAC(ccel, dEB)*mGaussw[(f)]) +#define CCELG_WT(f) (RAC(ccel, dWT)*mGaussw[(f)]) +#define CCELG_WB(f) (RAC(ccel, dWB)*mGaussw[(f)]) + + +#if PARALLEL==1 +#define CSMOMEGA_STATS(dlev, domega) +#else // PARALLEL==1 +#if FSGR_OMEGA_DEBUG==1 +#define CSMOMEGA_STATS(dlev, domega) \ + mLevel[dlev].avgOmega += domega; mLevel[dlev].avgOmegaCnt+=1.0; +#else // FSGR_OMEGA_DEBUG==1 +#define CSMOMEGA_STATS(dlev, domega) +#endif // FSGR_OMEGA_DEBUG==1 +#endif // PARALLEL==1 + + +// used for main loops and grav init +// source set +#define SRCS(l) mLevel[(l)].setCurr +// target set +#define TSET(l) mLevel[(l)].setOther + +// treatment of freeslip reflection +// used both for OPT and nonOPT +#define DEFAULT_STREAM_FREESLIP(l,invl,mnbf) \ + /*const int inv_l = D::dfInv[l];*/ \ + int nb1 = 0, nb2 = 0; /* is neighbor in this direction an obstacle? */\ + LbmFloat newval = 0.0; /* new value for m[l], differs for free/part slip */\ + const int dx = D::dfVecX[invl], dy = D::dfVecY[invl], dz = D::dfVecZ[invl]; \ + if(dz==0) { \ + nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \ + nb2 = !(RFLAG(lev, i+dx,j, k, SRCS(lev))&(CFFluid|CFInter)); \ + if((nb1)&&(!nb2)) { \ + /* x reflection */\ + newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ + } else \ + if((!nb1)&&(nb2)) { \ + /* y reflection */\ + newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ + } else { \ + /* normal no slip in all other cases */\ + newval = QCELL(lev, i,j,k,SRCS(lev), invl); \ + } \ + } else /* z=0 */\ + if(dy==0) { \ + nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \ + nb2 = !(RFLAG(lev, i+dx,j,k, SRCS(lev))&(CFFluid|CFInter)); \ + if((nb1)&&(!nb2)) { \ + /* x reflection */\ + newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ + } else \ + if((!nb1)&&(nb2)) { \ + /* z reflection */\ + newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ + } else { \ + /* normal no slip in all other cases */\ + newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \ + } \ + /* end y=0 */ \ + } else { \ + /* x=0 */\ + nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \ + nb2 = !(RFLAG(lev, i,j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \ + if((nb1)&&(!nb2)) { \ + /* y reflection */\ + newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ + } else \ + if((!nb1)&&(nb2)) { \ + /* z reflection */\ + newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ + } else { \ + /* normal no slip in all other cases */\ + newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \ + } \ + } \ + if(mnbf & CFBndPartslip) { /* part slip interpolation */ \ + const LbmFloat partv = mObjectPartslips[(int)(mnbf>>24)]; \ + m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \ + } else {\ + m[l] = newval; /* normal free slip*/\ + }\ + +// complete default stream&collide, 2d/3d +/* read distribution funtions of adjacent cells = sweep step */ +#if OPT3D==0 + +#if FSGR_STRICT_DEBUG==1 +#define MARKCELLCHECK \ + debugMarkCell(lev,i,j,k); D::mPanic=1; +#define STREAMCHECK(ni,nj,nk,nl) \ + if((m[l] < -1.0) || (m[l]>1.0)) {\ + errMsg("STREAMCHECK","Invalid streamed DF l"<2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\ + errMsg("COLLCHECK","Invalid collision values r:"<2*dim free slip */ \ + \ + } /* type reflect */\ + else {\ + errMsg("LbmFsgrSolver","Invalid Bnd type at "<>24)]; \ + m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \ + } else {\ + m[l] = newval; /* normal free slip*/\ + }\ + /*if(RFLAG(lev, i,j,k, SRCS(lev))&CFInter) errMsg("FS","at "< "<2*dim free slip */ \ + \ + } /* type reflect */\ + else {\ + errMsg("LbmFsgrSolver","Invalid Bnd type at "<CmMaxVlen) { \ + CmMxvx = Cux; CmMxvy = Cuy; CmMxvz = Cuz; CmMaxVlen = Cusqr; \ + } /* stats */ + + + +/****************************************************************************** + * interpolateCellFromCoarse macros + *****************************************************************************/ + + +// WOXDY_N = Weight Order X Dimension Y _ number N +#define WO1D1 ( 1.0/ 2.0) +#define WO1D2 ( 1.0/ 4.0) +#define WO1D3 ( 1.0/ 8.0) + +#define WO2D1_1 (-1.0/16.0) +#define WO2D1_9 ( 9.0/16.0) + +#define WO2D2_11 (WO2D1_1 * WO2D1_1) +#define WO2D2_19 (WO2D1_9 * WO2D1_1) +#define WO2D2_91 (WO2D1_9 * WO2D1_1) +#define WO2D2_99 (WO2D1_9 * WO2D1_9) + +#define WO2D3_111 (WO2D1_1 * WO2D1_1 * WO2D1_1) +#define WO2D3_191 (WO2D1_9 * WO2D1_1 * WO2D1_1) +#define WO2D3_911 (WO2D1_9 * WO2D1_1 * WO2D1_1) +#define WO2D3_991 (WO2D1_9 * WO2D1_9 * WO2D1_1) +#define WO2D3_119 (WO2D1_1 * WO2D1_1 * WO2D1_9) +#define WO2D3_199 (WO2D1_9 * WO2D1_1 * WO2D1_9) +#define WO2D3_919 (WO2D1_9 * WO2D1_1 * WO2D1_9) +#define WO2D3_999 (WO2D1_9 * WO2D1_9 * WO2D1_9) + +#if FSGR_STRICT_DEBUG==1 +#define ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l) \ + if( (((1.0-(at))>0.0) && (!(QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr , l) > -1.0 ))) || \ + ((( (at))>0.0) && (!(QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setOther, l) > -1.0 ))) ){ \ + errMsg("INVDFSCHECK", " l"<<(alev)<<" "<0.0) && (!(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )&(CFInter|CFFluid|CFGrCoarseInited) ))) || \ + ((( (at))>0.0) && (!(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther)&(CFInter|CFFluid|CFGrCoarseInited) ))) ){ \ + errMsg("INVFLAGCINTCHECK", " l"<<(alev)<<" at:"<<(at)<<" "<10)&&(iy>5)&&(iz>5)) { debugMarkCell(lev+1, (ix),(iy),(iz) ); } +#define INTUNUTCHECK(ix,iy,iz) \ + if( (RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) != (CFFluid|CFGrFromCoarse)) ){\ + errMsg("INTFLAGUNU_CHECK", PRINT_VEC(i,j,k)<<" child not unused at l"<<(lev+1)<<" "< only current +// t=0.5 -> mix +// t=1.0 -> only other +#if OPT3D==0 +#define ADD_INT_DFS(alev, ai,aj,ak, at, afac) \ + ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac); \ + FORDF0{ \ + LbmFloat df = ( \ + QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr , l)*(1.0-(at)) + \ + QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setOther, l)*( (at)) \ + ) ; \ + ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l); \ + df *= (afac); \ + rho += df; \ + ux += (D::dfDvecX[l]*df); \ + uy += (D::dfDvecY[l]*df); \ + uz += (D::dfDvecZ[l]*df); \ + intDf[l] += df; \ + } +// write interpolated dfs back to cell (correct non-eq. parts) +#define IDF_WRITEBACK_ \ + FORDF0{ \ + LbmFloat eq = D::getCollideEq(l, rho,ux,uy,uz);\ + QCELL(lev,i,j,k, dstSet, l) = (eq+ (intDf[l]-eq)*mDfScaleDown);\ + } \ + /* check that all values are ok */ \ + INTDEBOUT +#define IDF_WRITEBACK \ + LbmFloat omegaDst, omegaSrc;\ + /* smago new */ \ + LbmFloat feq[LBM_DFNUM]; \ + LbmFloat dfScale = mDfScaleDown; \ + FORDF0{ \ + feq[l] = D::getCollideEq(l, rho,ux,uy,uz); \ + } \ + if(mLevel[lev ].lcsmago>0.0) {\ + LbmFloat Qo = D::getLesNoneqTensorCoeff(intDf,feq); \ + omegaDst = D::getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \ + omegaSrc = D::getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \ + } else {\ + omegaDst = mLevel[lev+0].omega; \ + omegaSrc = mLevel[lev-1].omega;\ + } \ + \ + dfScale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \ + FORDF0{ \ + /*errMsg("SMAGO"," org"< +void LbmFsgrSolver::prepareVisualization( void ) { + int lev = mMaxRefine; + int workSet = mLevel[lev].setCurr; + + //make same prepareVisualization and getIsoSurface... +#if LBMDIM==2 + // 2d, place in the middle of isofield slice (k=2) +# define ZKD1 0 + // 2d z offset = 2, lbmGetData adds 1, so use one here +# define ZKOFF 1 + // reset all values... + for(int k= 0; k< 5; ++k) + for(int j=0;jlbmGetData(i,j,ZKOFF)=0.0; + } +#else // LBMDIM==2 + // 3d, use normal bounds +# define ZKD1 1 +# define ZKOFF k + // reset all values... + for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) + for(int j=0;jlbmGetData(i,j,ZKOFF)=0.0; + } +#endif // LBMDIM==2 + + + + // add up... + float val = 0.0; + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) + for(int j=1;jlbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] ); + *D::mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] ); + *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[2] ); + + *D::mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] ); + *D::mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] ); + *D::mpIso->lbmGetData( i+1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[5] ); + + *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] ); + *D::mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] ); + *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[8] ); + + + *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] ); + *D::mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] ); + *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[11] ); + + *D::mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] ); + *D::mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] ); + *D::mpIso->lbmGetData( i+1 , j ,ZKOFF ) += ( val * mIsoWeight[14] ); + + *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] ); + *D::mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] ); + *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[17] ); + + + *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] ); + *D::mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] ); + *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[20] ); + + *D::mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] ); + *D::mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] ); + *D::mpIso->lbmGetData( i+1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[23] ); + + *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] ); + *D::mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] ); + *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] ); + } + + // update preview, remove 2d? + if(mOutputSurfacePreview) { + //int previewSize = mOutputSurfacePreview; + int pvsx = (int)(mPreviewFactor*D::mSizex); + int pvsy = (int)(mPreviewFactor*D::mSizey); + int pvsz = (int)(mPreviewFactor*D::mSizez); + //float scale = (float)D::mSizex / previewSize; + LbmFloat scalex = (LbmFloat)D::mSizex/(LbmFloat)pvsx; + LbmFloat scaley = (LbmFloat)D::mSizey/(LbmFloat)pvsy; + LbmFloat scalez = (LbmFloat)D::mSizez/(LbmFloat)pvsz; + for(int k= 0; k< ((D::cDimension==3) ? (pvsz-1):1) ; ++k) + for(int j=0;j< pvsy;j++) + for(int i=0;i< pvsx;i++) { + *mpPreviewSurface->lbmGetData(i,j,k) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) ); + } + // set borders again... + for(int k= 0; k< ((D::cDimension == 3) ? (pvsz-1):1) ; ++k) { + for(int j=0;j< pvsy;j++) { + *mpPreviewSurface->lbmGetData(0,j,k) = *D::mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *D::mpIso->lbmGetData( D::mSizex-1, (int)(j*scaley), (int)(k*scalez) ); + } + for(int i=0;i< pvsx;i++) { + *mpPreviewSurface->lbmGetData(i,0,k) = *D::mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *D::mpIso->lbmGetData( (int)(i*scalex), D::mSizey-1, (int)(k*scalez) ); + } + } + if(D::cDimension == 3) { + // only for 3D + for(int j=0;jlbmGetData(i,j,0) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0); + *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , D::mSizez-1); + } + } // borders done... + } + + // correction + return; +} + + + + +/***************************************************************************** + * move the particles + * uses updated velocities from mSetOther + *****************************************************************************/ +template +void LbmFsgrSolver::advanceParticles(ParticleTracer *partt ) { + partt = NULL; // remove warning +} + + +/****************************************************************************** + * reset particle positions to default + *****************************************************************************/ +/*! init particle positions */ +template +int LbmFsgrSolver::initParticles(ParticleTracer *partt) { + partt = NULL; // remove warning + return 0; +} + + +/*! init particle positions */ +template +void LbmFsgrSolver::recalculateObjectSpeeds() { + int numobjs = (int)(D::mpGiObjects->size()); + // note - (numobjs + 1) is entry for domain settings + if(numobjs>255-1) { + errFatal("LbmFsgrSolver::recalculateObjectSpeeds","More than 256 objects currently not supported...",SIMWORLD_INITERROR); + return; + } + mObjectSpeeds.resize(numobjs+1); + for(int i=0; i<(int)(numobjs+0); i++) { + mObjectSpeeds[i] = vec2L(D::mpParam->calculateLattVelocityFromRw( vec2P( (*D::mpGiObjects)[i]->getInitialVelocity() ))); + //errMsg("recalculateObjectSpeeds","id"<getInitialVelocity() ); + } + + // also reinit part slip values here + mObjectPartslips.resize(numobjs+1); + for(int i=0; i<(int)(numobjs+0); i++) { + mObjectPartslips[i] = (LbmFloat)(*D::mpGiObjects)[i]->getGeoPartSlipValue(); + } + //errMsg("GEOIN"," dm set "< +void +LbmFsgrSolver::printLbmCell(int level, int i, int j, int k, int set) { + stdCellId *newcid = new stdCellId; + newcid->level = level; + newcid->x = i; + newcid->y = j; + newcid->z = k; + + // this function is not called upon clicking, then its from setMouseClick + debugPrintNodeInfo( newcid, set ); + delete newcid; +} +template +void +LbmFsgrSolver::debugMarkCellCall(int level, int vi,int vj,int vk) { + stdCellId *newcid = new stdCellId; + newcid->level = level; + newcid->x = vi; + newcid->y = vj; + newcid->z = vk; + addCellToMarkedList( newcid ); +} + + +/*****************************************************************************/ +// implement CellIterator interface +/*****************************************************************************/ + + + +// values from guiflkt.cpp +extern double guiRoiSX, guiRoiSY, guiRoiSZ, guiRoiEX, guiRoiEY, guiRoiEZ; +extern int guiRoiMaxLev, guiRoiMinLev; +#define CID_SX (int)( (mLevel[cid->level].lSizex-1) * guiRoiSX ) +#define CID_SY (int)( (mLevel[cid->level].lSizey-1) * guiRoiSY ) +#define CID_SZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiSZ ) + +#define CID_EX (int)( (mLevel[cid->level].lSizex-1) * guiRoiEX ) +#define CID_EY (int)( (mLevel[cid->level].lSizey-1) * guiRoiEY ) +#define CID_EZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiEZ ) + +template +CellIdentifierInterface* +LbmFsgrSolver::getFirstCell( ) { + int level = mMaxRefine; + +#if LBMDIM==3 + if(mMaxRefine>0) { level = mMaxRefine-1; } // NO1HIGHESTLEV DEBUG +#endif + level = guiRoiMaxLev; + if(level>mMaxRefine) level = mMaxRefine; + + //errMsg("LbmFsgrSolver::getFirstCell","Celliteration started..."); + stdCellId *cid = new stdCellId; + cid->level = level; + cid->x = CID_SX; + cid->y = CID_SY; + cid->z = CID_SZ; + return cid; +} + +template +typename LbmFsgrSolver::stdCellId* +LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { + //stdCellId *cid = dynamic_cast( basecid ); + stdCellId *cid = (stdCellId*)( basecid ); + return cid; +} + +template +void +LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + if(cid->getEnd()) return; + + //debugOut(" ADb "<x<<","<y<<","<z<<" e"<getEnd(), 10); + cid->x++; + if(cid->x > CID_EX){ cid->x = CID_SX; cid->y++; + if(cid->y > CID_EY){ cid->y = CID_SY; cid->z++; + if(cid->z > CID_EZ){ + cid->level--; + cid->x = CID_SX; + cid->y = CID_SY; + cid->z = CID_SZ; + if(cid->level < guiRoiMinLev) { + cid->level = guiRoiMaxLev; + cid->setEnd( true ); + } + } + } + } + //debugOut(" ADa "<x<<","<y<<","<z<<" e"<getEnd(), 10); +} + +template +bool +LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return (!cid->getEnd()); +} + +template +void +LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { + delete *cid; + *cid = NULL; +} + +template +CellIdentifierInterface* +LbmFsgrSolver::getCellAt( ntlVec3Gfx pos ) { + //int cellok = false; + pos -= (D::mvGeoStart); + + LbmFloat mmaxsize = mLevel[mMaxRefine].nodeSize; + for(int level=mMaxRefine; level>=0; level--) { // finest first + //for(int level=0; level<=mMaxRefine; level++) { // coarsest first + LbmFloat nsize = mLevel[level].nodeSize; + int x,y,z; + //LbmFloat nsize = getCellSize(NULL)[0]*2.0; + x = (int)((pos[0]-0.5*mmaxsize) / nsize ); + y = (int)((pos[1]-0.5*mmaxsize) / nsize ); + z = (int)((pos[2]-0.5*mmaxsize) / nsize ); + if(D::cDimension==2) z = 0; + + // double check... + //int level = mMaxRefine; + if(x<0) continue; + if(y<0) continue; + if(z<0) continue; + if(x>=mLevel[level].lSizex) continue; + if(y>=mLevel[level].lSizey) continue; + if(z>=mLevel[level].lSizez) continue; + + // return fluid/if/border cells + if( ( (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused)) ) || + ( (levellevel = level; + newcid->x = x; + newcid->y = y; + newcid->z = z; + //errMsg("cellAt",D::mName<<" "< +int +LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return mLevel[cid->level].setCurr; + //return mLevel[cid->level].setOther; +} + +template +int +LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return cid->level; +} + +template +ntlVec3Gfx +LbmFsgrSolver::getCellOrigin ( CellIdentifierInterface* basecid) { + ntlVec3Gfx ret; + + stdCellId *cid = convertBaseCidToStdCid(basecid); + ntlVec3Gfx cs( mLevel[cid->level].nodeSize ); + if(D::cDimension==2) { cs[2] = 0.0; } + + if(D::cDimension==2) { + ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ) + + ntlVec3Gfx(0.0,0.0,cs[1]*-0.25)*cid->level ) + +getCellSize(basecid); + } else { + ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], cid->z *cs[2] )) + +getCellSize(basecid); + } + return (ret); +} + +template +ntlVec3Gfx +LbmFsgrSolver::getCellSize ( CellIdentifierInterface* basecid) { + // return half size + stdCellId *cid = convertBaseCidToStdCid(basecid); + ntlVec3Gfx retvec( mLevel[cid->level].nodeSize * 0.5 ); + // 2d display as rectangles + if(D::cDimension==2) { retvec[2] = 0.0; } + return (retvec); +} + +template +LbmFloat +LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + + LbmFloat rho = 0.0; + FORDF0 { + rho += QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + } + return ((rho-1.0) * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize) +1.0; // normal + //return ((rho-1.0) * D::mpParam->getCellSize() / D::mpParam->getStepTime()) +1.0; +} + +template +LbmVec +LbmFsgrSolver::getCellVelocity ( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + + LbmFloat ux,uy,uz; + ux=uy=uz= 0.0; + FORDF0 { + ux += D::dfDvecX[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + uy += D::dfDvecY[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + uz += D::dfDvecZ[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + } + LbmVec vel(ux,uy,uz); + // TODO fix... + return (vel * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize * D::mDebugVelScale); // normal +} + +template +LbmFloat +LbmFsgrSolver::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); +} +template +LbmFloat +LbmFsgrSolver::getCellMass( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); +} +template +LbmFloat +LbmFsgrSolver::getCellFill( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); + if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFFluid) return 1.0; + return 0.0; + //return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); +} +template +CellFlagType +LbmFsgrSolver::getCellFlag( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return RFLAG(cid->level, cid->x,cid->y,cid->z, set); +} + +template +LbmFloat +LbmFsgrSolver::getEquilDf( int l ) { + return D::dfEquil[l]; +} + +template +int +LbmFsgrSolver::getDfNum( ) { + return D::cDfNum; +} + +#if LBM_USE_GUI==1 +//! show simulation info (implement SimulationObject pure virtual func) +template +void +LbmFsgrSolver::debugDisplay(fluidDispSettings *set){ + //lbmDebugDisplay< LbmFsgrSolver >( set, this ); + lbmDebugDisplay( set ); +} +#endif + +/*****************************************************************************/ +// strict debugging functions +/*****************************************************************************/ +#if FSGR_STRICT_DEBUG==1 +#define STRICT_EXIT *((int *)0)=0; + +template +int LbmFsgrSolver::debLBMGI(int level, int ii,int ij,int ik, int is) { + if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"< mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<1){ errMsg("LbmStrict"," invS+ l"< +CellFlagType& LbmFsgrSolver::debRFLAG(int level, int xx,int yy,int zz,int set){ + return _RFLAG(level, xx,yy,zz,set); +}; + +template +CellFlagType& LbmFsgrSolver::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"< +CellFlagType& LbmFsgrSolver::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"< +int LbmFsgrSolver::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { + if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"< mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<1){ errMsg("LbmStrict"," invS+ l"<D::cDfNum){ // dFfrac is an exception + if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"< +LbmFloat& LbmFsgrSolver::debQCELL(int level, int xx,int yy,int zz,int set,int l) { + //errMsg("LbmStrict","debQCELL debug: l"< +LbmFloat& LbmFsgrSolver::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"< +LbmFloat& LbmFsgrSolver::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"< +LbmFloat* LbmFsgrSolver::debRACPNT(int level, int ii,int ij,int ik, int is ) { + return _RACPNT(level, ii,ij,ik, is ); +}; + +template +LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { + if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<D::cDfNum){ // dFfrac is an exception + //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"< +void LbmFsgrSolver::debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ) { + //debugOut(" DD: "<getAsString() , 10); + ntlVec3Gfx org = this->getCellOrigin( cell ); + ntlVec3Gfx halfsize = this->getCellSize( cell ); + int set = this->getCellSet( cell ); + //debugOut(" DD: "<getAsString()<<" "<< (dispset->type) , 10); + + bool showcell = true; + int linewidth = 1; + ntlColor col(0.5); + LbmFloat cscale = dispset->scale; + +#define DRAWDISPCUBE(col,scale) \ + { glLineWidth( linewidth ); \ + glColor3f( (col)[0], (col)[1], (col)[2]); \ + ntlVec3Gfx s = org-(halfsize * (scale)); \ + ntlVec3Gfx e = org+(halfsize * (scale)); \ + drawCubeWire( s,e ); } + + switch(dispset->type) { + case FLUIDDISPNothing: { + showcell = false; + } break; + case FLUIDDISPCelltypes: { + CellFlagType flag = this->getCellFlag(cell, set ); + cscale = 0.5; + + if(flag& CFInvalid ) { if(!guiShowInvalid ) return; } + if(flag& CFUnused ) { if(!guiShowInvalid ) return; } + if(flag& CFEmpty ) { if(!guiShowEmpty ) return; } + if(flag& CFInter ) { if(!guiShowInterface) return; } + if(flag& CFNoDelete ) { if(!guiShowNoDelete ) return; } + if(flag& CFBnd ) { if(!guiShowBnd ) return; } + + // only dismiss one of these types + if(flag& CFGrFromCoarse) { if(!guiShowCoarseInner ) return; } // inner not really interesting + else + if(flag& CFGrFromFine) { if(!guiShowCoarseBorder ) return; } + else + if(flag& CFFluid ) { if(!guiShowFluid ) return; } + + if(flag& CFNoDelete) { // debug, mark nodel cells + ntlColor ccol(0.7,0.0,0.0); + DRAWDISPCUBE(ccol, 0.1); + } + if(flag& CFPersistMask) { // mark persistent flags + ntlColor ccol(0.5); + DRAWDISPCUBE(ccol, 0.125); + } + if(flag& CFNoBndFluid) { // mark persistent flags + ntlColor ccol(0,0,1); + DRAWDISPCUBE(ccol, 0.075); + } + + if(flag& CFInvalid) { + cscale = 0.50; + col = ntlColor(0.0,0,0.0); + } + else if(flag& CFBnd) { + cscale = 0.59; + col = ntlColor(0.4); + } + + else if(flag& CFInter) { + cscale = 0.55; + col = ntlColor(0,1,1); + + } else if(flag& CFGrFromCoarse) { + // draw as - with marker + ntlColor col2(0.0,1.0,0.3); + DRAWDISPCUBE(col2, 0.1); + cscale = 0.5; + showcell=false; // DEBUG + } + else if(flag& CFFluid) { + cscale = 0.5; + if(flag& CFGrToFine) { + ntlColor col2(0.5,0.0,0.5); + DRAWDISPCUBE(col2, 0.1); + col = ntlColor(0,0,1); + } + if(flag& CFGrFromFine) { + ntlColor col2(1.0,1.0,0.0); + DRAWDISPCUBE(col2, 0.1); + col = ntlColor(0,0,1); + } else if(flag& CFGrFromCoarse) { + // draw as fluid with marker + ntlColor col2(0.0,1.0,0.3); + DRAWDISPCUBE(col2, 0.1); + col = ntlColor(0,0,1); + } else { + col = ntlColor(0,0,1); + } + } + else if(flag& CFEmpty) { + showcell=false; + } + + } break; + case FLUIDDISPVelocities: { + // dont use cube display + LbmVec vel = this->getCellVelocity( cell, set ); + glBegin(GL_LINES); + glColor3f( 0.0,0.0,0.0 ); + glVertex3f( org[0], org[1], org[2] ); + org += vec2G(vel * 10.0 * cscale); + glColor3f( 1.0,1.0,1.0 ); + glVertex3f( org[0], org[1], org[2] ); + glEnd(); + showcell = false; + } break; + case FLUIDDISPCellfills: { + CellFlagType flag = this->getCellFlag( cell,set ); + cscale = 0.5; + + if(flag& CFFluid) { + cscale = 0.75; + col = ntlColor(0,0,0.5); + } + else if(flag& CFInter) { + cscale = 0.75 * this->getCellMass(cell,set); + col = ntlColor(0,1,1); + } + else { + showcell=false; + } + + if( ABS(this->getCellMass(cell,set)) < 10.0 ) { + cscale = 0.75 * this->getCellMass(cell,set); + } else { + showcell = false; + } + if(cscale>0.0) { + col = ntlColor(0,1,1); + } else { + col = ntlColor(1,1,0); + } + // TODO + } break; + case FLUIDDISPDensity: { + LbmFloat rho = this->getCellDensity(cell,set); + cscale = rho*rho * 0.25; + col = ntlColor( MIN(0.5+cscale,1.0) , MIN(0.0+cscale,1.0), MIN(0.0+cscale,1.0) ); + cscale *= 2.0; + } break; + case FLUIDDISPGrid: { + cscale = 0.59; + col = ntlColor(1.0); + } break; + default: { + cscale = 0.5; + col = ntlColor(1.0,0.0,0.0); + } break; + } + + if(!showcell) return; + DRAWDISPCUBE(col, cscale); +} + +//! debug display function +// D has to implement the CellIterator interface +template +void LbmFsgrSolver::lbmDebugDisplay(fluidDispSettings *dispset) { + //je nach solver...? + if(!dispset->on) return; + glDisable( GL_LIGHTING ); // dont light lines + + typename D::CellIdentifier cid = this->getFirstCell(); + for(; this->noEndCell( cid ); + this->advanceCell( cid ) ) { + this->debugDisplayNode(dispset, cid ); + } + delete cid; + + glEnable( GL_LIGHTING ); // dont light lines +} + +//! debug display function +// D has to implement the CellIterator interface +template +void LbmFsgrSolver::lbmMarkedCellDisplay() { + fluidDispSettings dispset; + // trick - display marked cells as grid displa -> white, big + dispset.type = FLUIDDISPGrid; + dispset.on = true; + glDisable( GL_LIGHTING ); // dont light lines + + typename D::CellIdentifier cid = this->markedGetFirstCell(); + while(cid) { + this->debugDisplayNode(&dispset, cid ); + cid = this->markedAdvanceCell(); + } + delete cid; + + glEnable( GL_LIGHTING ); // dont light lines +} + +#endif // LBM_USE_GUI==1 + +//! display a single node +template +void LbmFsgrSolver::debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet) { + //string printInfo, + // force printing of one set? default = -1 = off + bool printDF = false; + bool printRho = false; + bool printVel = false; + bool printFlag = false; + bool printGeom = false; + bool printMass=false; + bool printBothSets = false; + string printInfo = this->getNodeInfoString(); + + for(size_t i=0; igetCellOrigin( cell ); + ntlVec3Gfx halfsize = this->getCellSize( cell ); + int set = this->getCellSet( cell ); + debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<getAsString()<<" from "<getName()<<" currSet:"<=0) setmax = 1; + + for(int s=0; s=0) workset = forceSet; + debMsgStd(" ",DM_MSG, "Printing set:"<getDfNum(); l++) { // FIXME ?? + debMsgStd(" ",DM_MSG, " Df"<getCellDf(cell,workset,l), 1); + } + } + if(printRho) { + debMsgStd(" ",DM_MSG, " Rho: "<getCellDensity(cell,workset), 1); + } + if(printVel) { + debMsgStd(" ",DM_MSG, " Vel: "<getCellVelocity(cell,workset), 1); + } + if(printFlag) { + CellFlagType flag = this->getCellFlag(cell,workset); + debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<getCellMass(cell,workset), 1); + } + } +} + + + +#if LBMDIM==2 +template class LbmFsgrSolver< LbmBGK2D >; +#endif // LBMDIM==2 +#if LBMDIM==3 +template class LbmFsgrSolver< LbmBGK3D >; +#endif // LBMDIM==3 diff --git a/intern/elbeem/intern/typeslbm.h b/intern/elbeem/intern/typeslbm.h deleted file mode 100644 index 3a00ffd7251..00000000000 --- a/intern/elbeem/intern/typeslbm.h +++ /dev/null @@ -1,260 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * Lattice-Boltzmann defines... - * - *****************************************************************************/ -#ifndef TYPES_LBM_H - -/* standard precision for LBM solver */ -typedef double LBM_Float; -//typedef float LBM_Float; - -typedef double LBM2D_Float; -//typedef float LBM2D_Float; // FLAGS might not work!!!! - - -/****************************************************************************** - * 2D - *****************************************************************************/ - - -//! use incompressible LGBK model? -#define LBM2D_INCOMPBGK 1 - - -/*! size of a single set of distribution functions */ -#define LBM2D_DISTFUNCSIZE 9 -/*! size of a single set for a cell (+cell flags, mass, bubble id) */ -#define LBM2D_SETSIZE 12 -/*! floats per LBM cell */ -#define LBM2D_FLOATSPERCELL (LBM2D_SETSIZE +LBM2D_SETSIZE ) - - -/*! sphere init full or empty */ -#define LBM2D_FILLED true -#define LBM2D_EMPTY false - -/*! distribution functions directions */ -#define WC 0 -#define WN 1 -#define WS 2 -#define WE 3 -#define WW 4 -#define WNE 5 -#define WNW 6 -#define WSE 7 -#define WSW 8 -#define FLAG2D_BND (9) -#define FLAG2D_MASS (10) -#define FLAG2D_BUBBLE (11) - -/* Wi factors for collide step */ -#define LBM2D_COLLEN_ZERO (4.0/9.0) -#define LBM2D_COLLEN_ONE (1.0/9.0) -#define LBM2D_COLLEN_SQRTWO (1.0/36.0) - - -/* calculate equlibrium function for a single direction at cell i,j - * pass 0 for the u_ terms that are not needed - */ -#define LBM2D_VELVEC(l, ux,uy) ((ux)*DF2DdvecX[l]+(uy)*DF2DdvecY[l]) -#if LBM2D_INCOMPBGK!=1 -#define LBM2D_COLLIDE_EQ(target, l,Rho, ux,uy) \ - {\ - LBM2D_Float tmp = LBM2D_VELVEC(l,ux,uy); \ - target = ( (DF2Dlength[l]*Rho) *( \ - + 1.0 - (3.0/2.0*(ux*ux + uy*uy)) \ - + 3.0 *tmp \ - + 9.0/2.0 *(tmp*tmp) ) \ - );\ - } -#endif - -/* incompressible LBGK model?? */ -#if LBM2D_INCOMPBGK==1 -#define LBM2D_COLLIDE_EQ(target, l,Rho, ux,uy) \ - {\ - LBM2D_Float tmp = LBM2D_VELVEC(l,ux,uy); \ - target = ( (DF2Dlength[l]) *( \ - + Rho - (3.0/2.0*(ux*ux + uy*uy )) \ - + 3.0 *tmp \ - + 9.0/2.0 *(tmp*tmp) ) \ - );\ - } -#endif - -/* calculate new distribution function for cell i,j - * Now also includes gravity - */ -#define LBM2D_COLLIDE(l,omega, Rho, ux,uy ) \ - {\ - LBM2D_Float collideTempVar; \ - LBM2D_COLLIDE_EQ(collideTempVar, l,Rho, (ux), (uy) ); \ - m[l] = (1.0-omega) * m[l] + \ - omega* collideTempVar \ - ; \ - }\ - - -#ifdef LBM2D_IMPORT -extern char *DF2Dstring[LBM2D_DISTFUNCSIZE]; -extern int DF2Dnorm[LBM2D_DISTFUNCSIZE]; -extern int DF2Dinv[LBM2D_DISTFUNCSIZE]; -extern int DF2DrefX[LBM2D_DISTFUNCSIZE]; -extern int DF2DrefY[LBM2D_DISTFUNCSIZE]; -extern LBM2D_Float DF2Dequil[ LBM2D_DISTFUNCSIZE ]; -extern int DF2DvecX[LBM2D_DISTFUNCSIZE]; -extern int DF2DvecY[LBM2D_DISTFUNCSIZE]; -extern LBM2D_Float DF2DdvecX[LBM2D_DISTFUNCSIZE]; -extern LBM2D_Float DF2DdvecY[LBM2D_DISTFUNCSIZE]; -extern LBM2D_Float DF2Dlength[LBM2D_DISTFUNCSIZE]; -#endif - - - -/****************************************************************************** - * 3D - *****************************************************************************/ - -// use incompressible LGBK model? -#define LBM_INCOMPBGK 1 - - - -/*! size of a single set of distribution functions */ -#define LBM_DISTFUNCSIZE 19 -/*! size of a single set for a cell (+cell flags, mass, bubble id) */ -#define LBM_SETSIZE 22 -/*! floats per LBM cell */ -#define LBM_FLOATSPERCELL (LBM_SETSIZE +LBM_SETSIZE ) - - -/*! distribution functions directions */ -#define MC 0 -#define MN 1 -#define MS 2 -#define ME 3 -#define MW 4 -#define MT 5 -#define MB 6 -#define MNE 7 -#define MNW 8 -#define MSE 9 -#define MSW 10 -#define MNT 11 -#define MNB 12 -#define MST 13 -#define MSB 14 -#define MET 15 -#define MEB 16 -#define MWT 17 -#define MWB 18 -#define FLAG_BND (19) -#define FLAG_MASS (20) -#define FLAG_BUBBLE (21) - -/* Wi factors for collide step */ -#define LBM_COLLEN_ZERO (1.0/3.0) -#define LBM_COLLEN_ONE (1.0/18.0) -#define LBM_COLLEN_SQRTWO (1.0/36.0) - - -/* calculate equlibrium function for a single direction at cell i,j,k - * pass 0 for the u_ terms that are not needed - */ -#define LBM_VELVEC(l, ux,uy,uz) ((ux)*DFdvecX[l]+(uy)*DFdvecY[l]+(uz)*DFdvecZ[l]) -#ifndef LBM_INCOMPBGK -#define LBM_COLLIDE_EQ(target, l,Rho, ux,uy,uz) \ - {\ - LBM_Float tmp = LBM_VELVEC(l,ux,uy,uz); \ - target = ( (DFlength[l]*Rho) *( \ - + 1.0 - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) \ - + 3.0 *tmp \ - + 9.0/2.0 *(tmp*tmp) ) \ - );\ - } -#endif - -/* incompressible LBGK model?? */ -#ifdef LBM_INCOMPBGK -#define LBM_COLLIDE_EQ(target, l,Rho, ux,uy,uz) \ - {\ - LBM_Float tmp = LBM_VELVEC(l,ux,uy,uz); \ - target = ( (DFlength[l]) *( \ - + Rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) \ - + 3.0 *tmp \ - + 9.0/2.0 *(tmp*tmp) ) \ - );\ - } -#endif - -/* calculate new distribution function for cell i,j,k - * Now also includes gravity - */ -#define LBM_COLLIDE(l,omega,Rho, ux,uy,uz ) \ - {\ - LBM_Float collideTempVar; \ - LBM_COLLIDE_EQ(collideTempVar, l,Rho, (ux), (uy), (uz) ); \ - m[l] = (1.0-omega) * m[l] + \ - omega* collideTempVar \ - ; \ - }\ - - -#ifdef LBM3D_IMPORT -char *DFstring[LBM_DISTFUNCSIZE]; -int DFnorm[LBM_DISTFUNCSIZE]; -int DFinv[LBM_DISTFUNCSIZE]; -int DFrefX[LBM_DISTFUNCSIZE]; -int DFrefY[LBM_DISTFUNCSIZE]; -int DFrefZ[LBM_DISTFUNCSIZE]; -LBM_Float DFequil[ LBM_DISTFUNCSIZE ]; -int DFvecX[LBM_DISTFUNCSIZE]; -int DFvecY[LBM_DISTFUNCSIZE]; -int DFvecZ[LBM_DISTFUNCSIZE]; -LBM_Float DFdvecX[LBM_DISTFUNCSIZE]; -LBM_Float DFdvecY[LBM_DISTFUNCSIZE]; -LBM_Float DFdvecZ[LBM_DISTFUNCSIZE]; -LBM_Float DFlength[LBM_DISTFUNCSIZE]; -#endif - - -/****************************************************************************** - * BOTH - *****************************************************************************/ - -/*! boundary flags - * only 1 should be active for a cell */ -#define BND (1<< 0) -#define ACCX (1<< 1) -#define ACCY (1<< 2) -#define ACCZ (1<< 3) -#define FREESLIP (1<< 4) -#define NOSLIP (1<< 5) -#define PERIODIC (1<< 6) -#define PARTSLIP (1<< 7) -/*! surface type, also only 1 should be active (2. flag byte) */ -#define EMPTY (0) -#define FLUID (1<< 8) -#define INTER (1<< 9) -/*! neighbor flags (3. flag byte) */ -#define I_NONBFLUID (1<<16) -#define I_NONBINTER (1<<17) -#define I_NONBEMPTY (1<<18) -#define I_NODELETE (1<<19) -#define I_NEWCELL (1<<20) -#define I_NEWINTERFACE (1<<21) -/*! marker only for debugging, this bit is reset each step */ -#define I_CELLMARKER ((int) (1<<30) ) -#define I_NOTCELLMARKER ((int) (~(1<<30)) ) - - - - - -#define TYPES_LBM_H -#endif -