From a7e9a9d9c0e4154db41de6184eefcccfd6e4ed0a Mon Sep 17 00:00:00 2001 From: Nils Thuerey Date: Tue, 25 Oct 2005 08:07:52 +0000 Subject: Only restructured code: - added Hos fixes - split up solver into 3 cpp files (as suggested by jonathan) - de-inlined function that caused gcc33 to use >1GB of memory --- intern/elbeem/SConscript | 13 +- intern/elbeem/intern/blendercall.cpp | 1 - intern/elbeem/intern/cfglexer.cpp | 2 +- intern/elbeem/intern/cfgparser.cpp | 1 - intern/elbeem/intern/elbeem.cpp | 4 +- intern/elbeem/intern/factory_fsgr.cpp | 29 - intern/elbeem/intern/factory_lbm.h | 18 - intern/elbeem/intern/globals.h | 4 +- intern/elbeem/intern/isosurface.cpp | 335 +- intern/elbeem/intern/lbmdimensions.h | 391 -- intern/elbeem/intern/lbmfsgrsolver.h | 6602 --------------------------- intern/elbeem/intern/lbmfunctions.h | 320 -- intern/elbeem/intern/lbminterface.cpp | 674 --- intern/elbeem/intern/lbminterface.h | 516 --- intern/elbeem/intern/ntl_blenderdumper.cpp | 4 +- intern/elbeem/intern/ntl_blenderdumper.h | 4 +- intern/elbeem/intern/ntl_bsptree.cpp | 12 - intern/elbeem/intern/ntl_geometryobject.cpp | 1 + intern/elbeem/intern/ntl_geometryobject.h | 6 + intern/elbeem/intern/ntl_ray.cpp | 2 +- intern/elbeem/intern/ntl_raytracer.cpp | 716 --- intern/elbeem/intern/ntl_raytracer.h | 105 - intern/elbeem/intern/ntl_world.cpp | 716 +++ intern/elbeem/intern/ntl_world.h | 105 + intern/elbeem/intern/simulation_object.cpp | 19 +- intern/elbeem/intern/simulation_object.h | 6 +- intern/elbeem/intern/solver_class.h | 690 +++ intern/elbeem/intern/solver_dimenions.h | 21 + intern/elbeem/intern/solver_init.cpp | 1449 ++++++ intern/elbeem/intern/solver_interface.cpp | 809 ++++ intern/elbeem/intern/solver_interface.h | 895 ++++ intern/elbeem/intern/solver_main.cpp | 2684 +++++++++++ intern/elbeem/intern/solver_relax.h | 1072 +++++ intern/elbeem/intern/solver_util.cpp | 861 ++++ intern/elbeem/intern/typeslbm.h | 260 -- 35 files changed, 9626 insertions(+), 9721 deletions(-) delete mode 100644 intern/elbeem/intern/factory_fsgr.cpp delete mode 100644 intern/elbeem/intern/factory_lbm.h delete mode 100644 intern/elbeem/intern/lbmdimensions.h delete mode 100644 intern/elbeem/intern/lbmfsgrsolver.h delete mode 100644 intern/elbeem/intern/lbmfunctions.h delete mode 100644 intern/elbeem/intern/lbminterface.cpp delete mode 100644 intern/elbeem/intern/lbminterface.h delete mode 100644 intern/elbeem/intern/ntl_raytracer.cpp delete mode 100644 intern/elbeem/intern/ntl_raytracer.h create mode 100644 intern/elbeem/intern/ntl_world.cpp create mode 100644 intern/elbeem/intern/ntl_world.h create mode 100644 intern/elbeem/intern/solver_class.h create mode 100644 intern/elbeem/intern/solver_dimenions.h create mode 100644 intern/elbeem/intern/solver_init.cpp create mode 100644 intern/elbeem/intern/solver_interface.cpp create mode 100644 intern/elbeem/intern/solver_interface.h create mode 100644 intern/elbeem/intern/solver_main.cpp create mode 100644 intern/elbeem/intern/solver_relax.h create mode 100644 intern/elbeem/intern/solver_util.cpp delete mode 100644 intern/elbeem/intern/typeslbm.h (limited to 'intern/elbeem') 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/lbminterface.cpp b/intern/elbeem/intern/lbminterface.cpp deleted file mode 100644 index db7705de0a8..00000000000 --- a/intern/elbeem/intern/lbminterface.cpp +++ /dev/null @@ -1,674 +0,0 @@ -/****************************************************************************** - * - * 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 Interface Class - * contains stuff to be statically compiled - * - *****************************************************************************/ - -/* LBM Files */ -#include "lbmdimensions.h" -#include "lbminterface.h" -#include "lbmfunctions.h" -#include "ntl_scene.h" -#include "ntl_ray.h" -#include "typeslbm.h" - - -/*****************************************************************************/ -//! common variables - -/*****************************************************************************/ -/*! class for solver templating - 3D implementation D3Q19 */ - - //! how many dimensions? - const int LbmD3Q19::cDimension = 3; - - // Wi factors for collide step - const LbmFloat LbmD3Q19::cCollenZero = (1.0/3.0); - const LbmFloat LbmD3Q19::cCollenOne = (1.0/18.0); - const LbmFloat LbmD3Q19::cCollenSqrtTwo = (1.0/36.0); - - //! threshold value for filled/emptied cells - const LbmFloat LbmD3Q19::cMagicNr2 = 1.0005; - const LbmFloat LbmD3Q19::cMagicNr2Neg = -0.0005; - const LbmFloat LbmD3Q19::cMagicNr = 1.010001; - const LbmFloat LbmD3Q19::cMagicNrNeg = -0.010001; - - //! size of a single set of distribution functions - const int LbmD3Q19::cDfNum = 19; - //! direction vector contain vecs for all spatial dirs, even if not used for LBM model - const int LbmD3Q19::cDirNum = 27; - - //const string LbmD3Q19::dfString[ cDfNum ] = { - const char* LbmD3Q19::dfString[ cDfNum ] = { - " C", " N"," S"," E"," W"," T"," B", - "NE","NW","SE","SW", - "NT","NB","ST","SB", - "ET","EB","WT","WB" - }; - - const int LbmD3Q19::dfNorm[ cDfNum ] = { - cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB, - cDirNE, cDirNW, cDirSE, cDirSW, - cDirNT, cDirNB, cDirST, cDirSB, - cDirET, cDirEB, cDirWT, cDirWB - }; - - const int LbmD3Q19::dfInv[ cDfNum ] = { - cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT, - cDirSW, cDirSE, cDirNW, cDirNE, - cDirSB, cDirST, cDirNB, cDirNT, - cDirWB, cDirWT, cDirEB, cDirET - }; - - const int LbmD3Q19::dfRefX[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - cDirSE, cDirSW, cDirNE, cDirNW, - 0, 0, 0, 0, - cDirEB, cDirET, cDirWB, cDirWT - }; - - const int LbmD3Q19::dfRefY[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - cDirNW, cDirNE, cDirSW, cDirSE, - cDirNB, cDirNT, cDirSB, cDirST, - 0, 0, 0, 0 - }; - - const int LbmD3Q19::dfRefZ[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - cDirST, cDirSB, cDirNT, cDirNB, - cDirWT, cDirWB, cDirET, cDirEB - }; - - // 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 - - const int LbmD3Q19::dfVecX[ cDirNum ] = { - 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, - }; - const int LbmD3Q19::dfVecY[ cDirNum ] = { - 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 - }; - const int LbmD3Q19::dfVecZ[ cDirNum ] = { - 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 - }; - - const LbmFloat LbmD3Q19::dfDvecX[ cDirNum ] = { - 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 - }; - const LbmFloat LbmD3Q19::dfDvecY[ cDirNum ] = { - 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 - }; - const LbmFloat LbmD3Q19::dfDvecZ[ cDirNum ] = { - 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 - }; - - /* principal directions */ - const int LbmD3Q19::princDirX[ 2*LbmD3Q19::cDimension ] = { - 1,-1, 0,0, 0,0 - }; - const int LbmD3Q19::princDirY[ 2*LbmD3Q19::cDimension ] = { - 0,0, 1,-1, 0,0 - }; - const int LbmD3Q19::princDirZ[ 2*LbmD3Q19::cDimension ] = { - 0,0, 0,0, 1,-1 - }; - - /*! arrays for les model coefficients, inited in lbmsolver constructor */ - LbmFloat LbmD3Q19::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; - LbmFloat LbmD3Q19::lesCoeffOffdiag[ cDimension ][ cDirNum ]; - - - const LbmFloat LbmD3Q19::dfLength[ cDfNum ]= { - cCollenZero, - cCollenOne, cCollenOne, cCollenOne, - cCollenOne, cCollenOne, cCollenOne, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo - }; - - /* precalculated equilibrium dfs, inited in lbmsolver constructor */ - LbmFloat LbmD3Q19::dfEquil[ cDfNum ]; - -// D3Q19 end - - - -/*****************************************************************************/ -/*! class for solver templating - 2D implementation D2Q9 */ - - //! how many dimensions? - const int LbmD2Q9::cDimension = 2; - - //! Wi factors for collide step - const LbmFloat LbmD2Q9::cCollenZero = (4.0/9.0); - const LbmFloat LbmD2Q9::cCollenOne = (1.0/9.0); - const LbmFloat LbmD2Q9::cCollenSqrtTwo = (1.0/36.0); - - //! threshold value for filled/emptied cells - const LbmFloat LbmD2Q9::cMagicNr2 = 1.0005; - const LbmFloat LbmD2Q9::cMagicNr2Neg = -0.0005; - const LbmFloat LbmD2Q9::cMagicNr = 1.010001; - const LbmFloat LbmD2Q9::cMagicNrNeg = -0.010001; - - //! size of a single set of distribution functions - const int LbmD2Q9::cDfNum = 9; - const int LbmD2Q9::cDirNum = 9; - - //const string LbmD2Q9::dfString[ cDfNum ] = { - const char* LbmD2Q9::dfString[ cDfNum ] = { - " C", - " N", " S", " E", " W", - "NE", "NW", "SE","SW" - }; - - const int LbmD2Q9::dfNorm[ cDfNum ] = { - cDirC, - cDirN, cDirS, cDirE, cDirW, - cDirNE, cDirNW, cDirSE, cDirSW - }; - - const int LbmD2Q9::dfInv[ cDfNum ] = { - cDirC, - cDirS, cDirN, cDirW, cDirE, - cDirSW, cDirSE, cDirNW, cDirNE - }; - - const int LbmD2Q9::dfRefX[ cDfNum ] = { - 0, - 0, 0, 0, 0, - cDirSE, cDirSW, cDirNE, cDirNW - }; - - const int LbmD2Q9::dfRefY[ cDfNum ] = { - 0, - 0, 0, 0, 0, - cDirNW, cDirNE, cDirSW, cDirSE - }; - - const int LbmD2Q9::dfRefZ[ cDfNum ] = { - 0, 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - // 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 - - const int LbmD2Q9::dfVecX[ cDirNum ] = { - 0, - 0,0, 1,-1, - 1,-1,1,-1 - }; - const int LbmD2Q9::dfVecY[ cDirNum ] = { - 0, - 1,-1, 0,0, - 1,1,-1,-1 - }; - const int LbmD2Q9::dfVecZ[ cDirNum ] = { - 0, 0,0,0,0, 0,0,0,0 - }; - - const LbmFloat LbmD2Q9::dfDvecX[ cDirNum ] = { - 0, - 0,0, 1,-1, - 1,-1,1,-1 - }; - const LbmFloat LbmD2Q9::dfDvecY[ cDirNum ] = { - 0, - 1,-1, 0,0, - 1,1,-1,-1 - }; - const LbmFloat LbmD2Q9::dfDvecZ[ cDirNum ] = { - 0, 0,0,0,0, 0,0,0,0 - }; - - const int LbmD2Q9::princDirX[ 2*LbmD2Q9::cDimension ] = { - 1,-1, 0,0 - }; - const int LbmD2Q9::princDirY[ 2*LbmD2Q9::cDimension ] = { - 0,0, 1,-1 - }; - const int LbmD2Q9::princDirZ[ 2*LbmD2Q9::cDimension ] = { - 0,0, 0,0 - }; - - - /*! arrays for les model coefficients, inited in lbmsolver constructor */ - LbmFloat LbmD2Q9::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; - LbmFloat LbmD2Q9::lesCoeffOffdiag[ cDimension ][ cDirNum ]; - - - const LbmFloat LbmD2Q9::dfLength[ cDfNum ]= { - cCollenZero, - cCollenOne, cCollenOne, cCollenOne, cCollenOne, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo - }; - - /* precalculated equilibrium dfs, inited in lbmsolver constructor */ - LbmFloat LbmD2Q9::dfEquil[ cDfNum ]; - -// D2Q9 end - - - -/****************************************************************************** - * Interface Constructor - *****************************************************************************/ -LbmSolverInterface::LbmSolverInterface() : - mPanic( false ), - mSizex(10), mSizey(10), mSizez(10), - mStepCnt( 0 ), - mFixMass( 0.0 ), - mOmega( 1.0 ), - mGravity(0.0), - mSurfaceTension( 0.0 ), - mBoundaryEast( (CellFlagType)(CFBnd) ),mBoundaryWest( (CellFlagType)(CFBnd) ),mBoundaryNorth( (CellFlagType)(CFBnd) ), - mBoundarySouth( (CellFlagType)(CFBnd) ),mBoundaryTop( (CellFlagType)(CFBnd) ),mBoundaryBottom( (CellFlagType)(CFBnd) ), - mInitDone( false ), - mInitDensityGradient( false ), - mpAttrs( NULL ), mpParam( NULL ), - mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0), - mDebugVelScale( 1.0 ), mNodeInfoString("+"), - mRandom( 5123 ), - mvGeoStart(-1.0), mvGeoEnd(1.0), - mPerformGeoInit( false ), - mAccurateGeoinit(0), - mName("lbm_default") , - mpIso( NULL ), mIsoValue(0.49999), - mSilent(false) , - mGeoInitId( 0 ), - mpGiTree( NULL ), - mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL ), - mMarkedCells(), mMarkedCellIndex(0) -{ -#if ELBEEM_BLENDER==1 - if(gDebugLevel<=1) mSilent = true; -#endif -} - - -/*******************************************************************************/ -/*! parse a boundary flag string */ -CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed) { - string val = mpAttrs->readString(name, "", source, target, needed); - if(!strcmp(val.c_str(),"")) { - // no value given... - return CFEmpty; - } - if(!strcmp(val.c_str(),"bnd_no")) { - return (CellFlagType)( CFBnd ); - } - if(!strcmp(val.c_str(),"bnd_free")) { - return (CellFlagType)( CFBnd ); - } - if(!strcmp(val.c_str(),"fluid")) { - /* might be used for some in/out flow cases */ - return (CellFlagType)( CFFluid ); - } - errMsg("LbmStdSolver::readBoundaryFlagInt","Invalid value '"<readFloat("d_surfacetension", mSurfaceTension, "LbmStdSolver", "mSurfaceTension", false); - mBoundaryEast = readBoundaryFlagInt("boundary_east", mBoundaryEast, "LbmStdSolver", "mBoundaryEast", false); - mBoundaryWest = readBoundaryFlagInt("boundary_west", mBoundaryWest, "LbmStdSolver", "mBoundaryWest", false); - mBoundaryNorth = readBoundaryFlagInt("boundary_north", mBoundaryNorth,"LbmStdSolver", "mBoundaryNorth", false); - mBoundarySouth = readBoundaryFlagInt("boundary_south", mBoundarySouth,"LbmStdSolver", "mBoundarySouth", false); - mBoundaryTop = readBoundaryFlagInt("boundary_top", mBoundaryTop,"LbmStdSolver", "mBoundaryTop", false); - mBoundaryBottom= readBoundaryFlagInt("boundary_bottom", mBoundaryBottom,"LbmStdSolver", "mBoundaryBottom", false); - - LbmVec sizeVec(mSizex,mSizey,mSizez); - sizeVec = vec2L( mpAttrs->readVec3d("size", vec2P(sizeVec), "LbmStdSolver", "sizeVec", false) ); - mSizex = (int)sizeVec[0]; - mSizey = (int)sizeVec[1]; - mSizez = (int)sizeVec[2]; - mpParam->setSize(mSizex, mSizey, mSizez ); // param needs size in any case - - mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmStdSolver", "mInitDensityGradient", false); - mPerformGeoInit = mpAttrs->readBool("geoinit", mPerformGeoInit,"LbmStdSolver", "mPerformGeoInit", false); - mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmStdSolver", "mGeoInitId", false); - mIsoValue = mpAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false ); - - mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmStdSolver", "mDebugVelScale", false); - mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false ); -} - - -/*******************************************************************************/ -/*! geometry initialization */ -/*******************************************************************************/ - -/*****************************************************************************/ -/*! init tree for certain geometry init */ -void LbmSolverInterface::initGeoTree(int id) { - if(mpGlob == NULL) { errFatal("LbmSolverInterface::initGeoTree","Requires globals!",SIMWORLD_INITERROR); return; } - mGeoInitId = id; - ntlScene *scene = mpGlob->getScene(); - mpGiObjects = scene->getObjects(); - mGiObjInside.resize( mpGiObjects->size() ); - mGiObjDistance.resize( mpGiObjects->size() ); - for(size_t i=0; isize(); i++) { - if((*mpGiObjects)[i]->getGeoInitIntersect()) mAccurateGeoinit=true; - } - debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Accurate geo init: "<intersectX(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; - mGiObjInside[OId]++; - //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; - } - } - } - if(!inside) { - distance = firstHit; - OId = firstOId; - } - //errMsg("CHIII","i"<intersectX(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 */ -ntlVec3Gfx LbmSolverInterface::getGeoMaxInitialVelocity() { - ntlScene *scene = mpGlob->getScene(); - mpGiObjects = scene->getObjects(); - ntlVec3Gfx max(0.0); - - for(int i=0; i< (int)mpGiObjects->size(); i++) { - if( (*mpGiObjects)[i]->getGeoInitType() & FGI_FLUID ){ - ntlVec3Gfx ovel = (*mpGiObjects)[i]->getInitialVelocity(); - if( normNoSqrt(ovel) > normNoSqrt(max) ) { max = ovel; } - //errMsg("IVT","i"<getInitialVelocity() ); // DEBUG - } - } - //errMsg("IVT","max "<<" "<< max ); // DEBUG - // unused !? mGiInsideCnt.resize( mpGiObjects->size() ); - - return max; -} - - -/*******************************************************************************/ -/*! "traditional" initialization */ -/*******************************************************************************/ - - -/*****************************************************************************/ -// handle generic test cases (currently only reset geo init) -bool LbmSolverInterface::initGenericTestCases() { - bool initTypeFound = false; - LbmSolverInterface::CellIdentifier cid = getFirstCell(); - // deprecated! - only check for invalid cells... - - // this is the default init - check if the geometry flag init didnt - initTypeFound = true; - - while(noEndCell(cid)) { - // check node - if( (getCellFlag(cid,0)==CFInvalid) || (getCellFlag(cid,1)==CFInvalid) ) { - warnMsg("LbmSolverInterface::initGenericTestCases","GeoInit produced invalid Flag at "<getAsString()<<"!" ); - } - advanceCell( cid ); - } - - deleteCellIterator( &cid ); - return initTypeFound; -} - - -/*******************************************************************************/ -/*! cell iteration functions */ -/*******************************************************************************/ - - - - -/*****************************************************************************/ -//! add cell to mMarkedCells list -void -LbmSolverInterface::addCellToMarkedList( CellIdentifierInterface *cid ) { - for(size_t i=0; iequal(cid) ) return; - //mMarkedCells[i]->setEnd(false); - } - mMarkedCells.push_back( cid ); - //cid->setEnd(true); -} - -/*****************************************************************************/ -//! marked cell iteration methods -CellIdentifierInterface* -LbmSolverInterface::markedGetFirstCell( ) { - if(mMarkedCells.size() > 0){ return mMarkedCells[0]; } - return NULL; -} - -CellIdentifierInterface* -LbmSolverInterface::markedAdvanceCell() { - mMarkedCellIndex++; - if(mMarkedCellIndex>=(int)mMarkedCells.size()) return NULL; - return mMarkedCells[mMarkedCellIndex]; -} - -void LbmSolverInterface::markedClearList() { - // FIXME free cids? - mMarkedCells.clear(); -} - -/*******************************************************************************/ -/*! string helper functions */ -/*******************************************************************************/ - - - -// 32k -string convertSingleFlag2String(CellFlagType cflag) { - CellFlagType flag = cflag; - if(flag == CFUnused ) return string("cCFUnused"); - if(flag == CFEmpty ) return string("cCFEmpty"); - if(flag == CFBnd ) return string("cCFBnd"); - if(flag == CFNoInterpolSrc ) return string("cCFNoInterpolSrc"); - if(flag == CFFluid ) return string("cCFFluid"); - if(flag == CFInter ) return string("cCFInter"); - if(flag == CFNoNbFluid ) return string("cCFNoNbFluid"); - if(flag == CFNoNbEmpty ) return string("cCFNoNbEmpty"); - if(flag == CFNoDelete ) return string("cCFNoDelete"); - if(flag == CFNoBndFluid ) return string("cCFNoBndFluid"); - if(flag == CFGrNorm ) return string("cCFGrNorm"); - if(flag == CFGrFromFine ) return string("cCFGrFromFine"); - if(flag == CFGrFromCoarse ) return string("cCFGrFromCoarse"); - if(flag == CFGrCoarseInited ) return string("cCFGrCoarseInited"); - if(flag == CFMbndInflow ) return string("cCFMbndInflow"); - if(flag == CFMbndOutflow ) return string("cCFMbndOutflow"); - if(flag == CFInvalid ) return string("cfINVALID"); - - std::ostringstream mult; - int val = 0; - if(flag != 0) { - while(! (flag&1) ) { - flag = flag>>1; - val++; - } - } else { - val = -1; - } - mult << "cfUNKNOWN_" << val <<"_TYPE"; - return mult.str(); -} - -//! helper function to convert flag to string (for debuggin) -string convertCellFlagType2String( CellFlagType cflag ) { - int flag = cflag; - - const int jmax = sizeof(CellFlagType)*8; - bool somefound = false; - std::ostringstream mult; - mult << "["; - for(int j=0; j -#include "../gui/guifuncs.h" -#endif - -#include -#include "utilities.h" -#include "ntl_bsptree.h" -#include "ntl_geometryobject.h" -#include "ntl_rndstream.h" -#include "parametrizer.h" -#include "attributes.h" -#include "particletracer.h" -#include "isosurface.h" - -// use which fp-precision for LBM? 1=float, 2=double -#ifdef PRECISION_LBM_SINGLE -#define LBM_PRECISION 1 -#else -#ifdef PRECISION_LBM_DOUBLE -#define LBM_PRECISION 2 -#else -// default to floats -#define LBM_PRECISION 1 -#endif -#endif - -// default to 3dim -#ifndef LBMDIM -#define LBMDIM 3 -#endif // LBMDIM - -#if LBM_PRECISION==1 -/* low precision for LBM solver */ -typedef float LbmFloat; -typedef ntlVec3f LbmVec; -#define LBM_EPSILON (1e-5) -#else -/* standard precision for LBM solver */ -typedef double LbmFloat; -typedef ntlVec3d LbmVec; -#define LBM_EPSILON (1e-10) -#endif - -// conversions (lbm and parametrizer) -template inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); } -template inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); } - - -// bubble id type -typedef int BubbleId; - -// for both short int/char -#define CFUnused (1<< 0) -#define CFEmpty (1<< 1) -#define CFBnd (1<< 2) -#define CFBndNoslip (1<< 3) -#define CFBndFreeslip (1<< 4) -#define CFBndPartslip (1<< 5) -// force symmetry for flag reinit -#define CFNoInterpolSrc (1<< 6) -#define CFFluid (1<< 7) -#define CFInter (1<< 8) -#define CFNoNbFluid (1<< 9) -#define CFNoNbEmpty (1<<10) -#define CFNoDelete (1<<11) -#define CFNoBndFluid (1<<12) - -//! refinement tags -// cell treated normally on coarser grids -#define CFGrNorm (1<<13) -// border cells to be interpolated from finer grid -#define CFGrFromFine (1<<14) -#define CFGrFromCoarse (1<<15) -#define CFGrCoarseInited (1<<16) -// 32k aux border marker -#define CFGrToFine (1<<17) -#define CFMbndInflow (1<<18) -#define CFMbndOutflow (1<<19) - -// above 24 is used to encode in/outflow object type -#define CFPersistMask (0xFF000000 | CFMbndInflow | CFMbndOutflow) - -// nk -#define CFInvalid (CellFlagType)(1<<31) - -// use 32bit flag types -#ifdef __x86_64__ - typedef int cfINT32; -#else - typedef long cfINT32; -#endif // defined (_IA64) -#define CellFlagType cfINT32 -#define CellFlagTypeSize 4 - - - -/*****************************************************************************/ -/*! a single lbm cell */ -/* the template is only needed for - * dimension dependend constants e.g. - * number of df's in model */ -template -class LbmCellTemplate { - public: - LbmFloat df[ 27 ]; // be on the safe side here... - LbmFloat rho; - LbmVec vel; - LbmFloat mass; - CellFlagType flag; - BubbleId bubble; - LbmFloat ffrac; - - //! test if a flag is set - inline bool test(CellFlagType t) { - return ((flag & t)==t); - } - //! test if any of the given flags is set - inline bool testAny(CellFlagType t) { - return ((flag & t)!=0); - } - //! test if the cell is empty - inline bool isEmpty() { - return (flag == CFEmpty); - } - - //! init default values for a certain flag type - inline void initDefaults(CellFlagType type) { - flag = type; - vel = LbmVec(0.0); - for(int l=0; l *objects ) = 0; - /*! generic test case setup using iterator interface */ - bool initGenericTestCases(); - - /*! parse a boundary flag string */ - CellFlagType readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed); - /*! parse standard attributes */ - void parseStdAttrList(); - /*! initilize variables fom attribute list (should at least call std parse) */ - virtual void parseAttrList() = 0; - - virtual void step() = 0; - virtual void prepareVisualization() { /* by default off */ }; - - /*! particle handling */ - virtual int initParticles(ParticleTracer *partt) = 0; - virtual void advanceParticles(ParticleTracer *partt ) = 0; - /*! get surface object (NULL if no surface) */ - ntlGeometryObject* getSurfaceGeoObj() { return mpIso; } - - /*! debug object display */ - virtual vector getDebugObjects() { vector empty(0); return empty; } - -#if LBM_USE_GUI==1 - /*! show simulation info */ - virtual void debugDisplay(fluidDispSettings *) = 0; -#endif - - /*! init tree for certain geometry init */ - void initGeoTree(int id); - /*! destroy tree etc. when geometry init done */ - 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); - /*! set render globals, for scene/tree access */ - void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; }; - /*! get max. velocity of all objects to initialize as fluid regions */ - ntlVec3Gfx getGeoMaxInitialVelocity(); - - /* rt interface functions */ - unsigned int getIsoVertexCount() { return mpIso->getIsoVertexCount(); } - unsigned int getIsoIndexCount() { return mpIso->getIsoIndexCount(); } - char* getIsoVertexArray() { return mpIso->getIsoVertexArray(); } - unsigned int *getIsoIndexArray() { return mpIso->getIsoIndexArray(); } - void triangulateSurface() { mpIso->triangulate(); } - - /* access functions */ - - /*! return grid sizes */ - int getSizeX( void ) { return mSizex; } - int getSizeY( void ) { return mSizey; } - int getSizeZ( void ) { return mSizez; } - /*! return grid sizes */ - void setSizeX( int ns ) { mSizex = ns; } - void setSizeY( int ns ) { mSizey = ns; } - void setSizeZ( int ns ) { mSizez = ns; } - - /*! set attr list pointer */ - void setAttrList(AttributeList *set) { mpAttrs = set; } - /*! Returns the attribute list pointer */ - inline AttributeList *getAttributeList() { return mpAttrs; } - - /*! set parametrizer pointer */ - inline void setParametrizer(Parametrizer *set) { mpParam = set; } - /*! get parametrizer pointer */ - inline Parametrizer *getParametrizer() { return mpParam; } - - /*! set density gradient init from e.g. init test cases */ - inline void setInitDensityGradient(bool set) { mInitDensityGradient = set; } - - /*! access geometry start vector */ - inline void setGeoStart(ntlVec3Gfx set) { mvGeoStart = set; } - inline ntlVec3Gfx getGeoStart() const { return mvGeoStart; } - - /*! access geometry end vector */ - inline void setGeoEnd(ntlVec3Gfx set) { mvGeoEnd = set; } - inline ntlVec3Gfx getGeoEnd() const { return mvGeoEnd; } - - /*! access name string */ - inline void setName(string set) { mName = set; } - inline string getName() const { return mName; } - - /*! access string for node info debugging output */ - inline string getNodeInfoString() const { return mNodeInfoString; } - - /*! get panic flag */ - inline bool getPanic() { return mPanic; } - - //! set silent mode? - inline void setSilent(bool set){ mSilent = set; } - - - // cell iterator interface - - // cell id type - typedef CellIdentifierInterface* CellIdentifier; - - //! cell iteration methods - virtual CellIdentifierInterface* getFirstCell( ) = 0; - virtual void advanceCell( CellIdentifierInterface* ) = 0; - virtual bool noEndCell( CellIdentifierInterface* ) = 0; - //! clean up iteration, this should be called, when the iteration is not completely finished - virtual void deleteCellIterator( CellIdentifierInterface** ) = 0; - - //! find cell at a given position (returns NULL if not in domain) - virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos ) = 0; - - //! return node information - virtual int getCellSet ( CellIdentifierInterface* ) = 0; - virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* ) = 0; - virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* ) = 0; - virtual int getCellLevel ( CellIdentifierInterface* ) = 0; - virtual LbmFloat getCellDensity ( CellIdentifierInterface*,int ) = 0; - virtual LbmVec getCellVelocity ( CellIdentifierInterface*,int ) = 0; - /*! get equilibrium distribution functions */ - virtual LbmFloat getEquilDf ( int ) = 0; - /*! get number of distribution functions */ - virtual int getDfNum ( ) = 0; - /*! redundant cell functions */ - virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir) = 0; - virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set) = 0; - virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0; - virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0; - - - // debugging cell marker functions - - //! add cell to mMarkedCells list - void addCellToMarkedList( CellIdentifierInterface *cid ); - //! marked cell iteration methods - CellIdentifierInterface* markedGetFirstCell( ); - CellIdentifierInterface* markedAdvanceCell(); - void markedClearList(); - -#ifndef LBMDIM - LBMDIM has to be defined -#endif -#if LBMDIM==2 - //! minimal and maximal z-coords (for 2D/3D loops) , this is always 0-1 for 2D - int getForZMinBnd() { return 0; }; - int getForZMaxBnd() { return 1; }; - int getForZMin1() { return 0; }; - int getForZMax1() { return 1; }; -#else // LBMDIM==2 - //! minimal and maximal z-coords (for 2D/3D loops) - int getForZMinBnd() { return 0; }; - int getForZMaxBnd() { return getSizeZ()-0; }; - int getForZMin1() { return 1; }; - int getForZMax1() { return getSizeZ()-1; }; -#endif // LBMDIM==2 - - - protected: - - /*! abort simulation on error... */ - bool mPanic; - - - /*! Size of the array in x,y,z direction */ - int mSizex, mSizey, mSizez; - - - /*! step counter */ - int mStepCnt; - - /*! mass change from one step to the next, for extreme cases fix globally */ - LbmFloat mFixMass; - - // deprecated param vars - /*! omega for lbm */ - LbmFloat mOmega; - /*! gravity strength in neg. z direction */ - LbmVec mGravity; - /*! Surface tension of the fluid */ - LbmFloat mSurfaceTension; - - - /* boundary inits */ - CellFlagType mBoundaryEast, mBoundaryWest, - mBoundaryNorth, mBoundarySouth, - mBoundaryTop, mBoundaryBottom; - - /*! initialization from config file done? */ - int mInitDone; - - /*! init density gradient? */ - bool mInitDensityGradient; - - /*! pointer to the attribute list */ - AttributeList *mpAttrs; - - /*! get parameters from this parametrize in finishInit */ - Parametrizer *mpParam; - - /*! number of particles lost so far */ - int mNumParticlesLost; - /*! number of particles lost so far */ - int mNumInvalidDfs; - /*! no of filled/emptied cells per time step */ - int mNumFilledCells, mNumEmptiedCells; - /*! counter number of used cells for performance */ - int mNumUsedCells; - /*! MLSUPS counter */ - LbmFloat mMLSUPS; - /*! debug - velocity output scaling factor */ - LbmFloat mDebugVelScale; - /*! string for node info debugging output */ - string mNodeInfoString; - - - /*! an own random stream */ - ntlRandomStream mRandom; - - - // geo init vars - // TODO deprecate SimulationObject vars - - /*! for display - start and end vectors for geometry */ - ntlVec3Gfx mvGeoStart, mvGeoEnd; - - /*! perform geometry init? */ - bool mPerformGeoInit; - /*! perform accurate geometry init? */ - bool mAccurateGeoinit; - - /*! name of this lbm object (for debug output) */ - string mName; - - //! Mcubes object for surface reconstruction - IsoSurface *mpIso; - /*! isolevel value for marching cubes surface reconstruction */ - LbmFloat mIsoValue; - - //! debug output? - bool mSilent; - - /*! geometry init id */ - int mGeoInitId; - /*! tree object for geomerty initialization */ - ntlTree *mpGiTree; - /*! object vector for geo init */ - vector *mpGiObjects; - /*! inside which objects? */ - vector mGiObjInside; - /*! inside which objects? */ - vector mGiObjDistance; - /*! remember globals */ - ntlRenderGlobals *mpGlob; - - // list for marked cells - vector mMarkedCells; - int mMarkedCellIndex; -}; - - -//! helper function to convert flag to string (for debuggin) -string convertCellFlagType2String( CellFlagType flag ); -string convertSingleFlag2String(CellFlagType cflag); - -#endif // LBMINTERFACE_H 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_scene.h" -#include "parametrizer.h" -#include "globals.h" - -// for non-threaded renderViz -#ifndef NOGUI -#include "../gui/ntl_openglrenderer.h" -#include "../gui/guifuncs.h" -#include "../gui/frame.h" -#endif - - -/* external parser functions from cfgparser.cxx */ -/* parse given file as config file */ -void parseFile(string filename); -/* set pointers for parsing */ -void setPointers( ntlRenderGlobals *setglob); - - -/****************************************************************************** - * Constructor - *****************************************************************************/ -ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : - mpGlob(NULL), - mpLightList(NULL), mpPropList(NULL), mpSims(NULL), - mpOpenGLRenderer(NULL), - mStopRenderVisualization( false ), - mThreadRunning( false ), - mSimulationTime(0.0), mFirstSim(-1), - mSingleStepDebug( false ) -{ - /* create scene storage */ - mpGlob = new ntlRenderGlobals(); - mpLightList = new vector; - mpPropList = new vector; - mpSims = new vector; - - mpGlob->setLightList(mpLightList); - mpGlob->setMaterials(mpPropList); - mpGlob->setSims(mpSims); - - /* init default material */ - ntlMaterial *def = GET_GLOBAL_DEFAULT_MATERIAL; - mpPropList->push_back( def ); - - /* init the scene object */ - ntlScene *scene; - scene = new ntlScene( mpGlob ); - mpGlob->setScene( scene ); - - // load config - setPointers( getRenderGlobals() ); - parseFile( filename.c_str() ); - if(!SIMWORLD_OK()) return; - - // init the scene for the first time - long sstartTime = getTime(); - scene->buildScene(); - long sstopTime = getTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); - - // TODO check simulations, run first steps - mFirstSim = -1; - if(mpSims->size() > 0) { - - // use values from first simulation as master time scale - long startTime = getTime(); - - // remember first active sim - for(size_t i=0;isize();i++) { - if(!(*mpSims)[i]->getVisible()) continue; - if((*mpSims)[i]->getPanic()) continue; - - // check largest timestep - 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); - while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) { - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<getStartTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",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); - } - } - -#ifndef NOGUI - // setup opengl display, save first animation step for start time - if(!commandlineMode) { - mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob, scene ); - } -#else // NOGUI - commandlineMode = true; // remove warning... -#endif // NOGUI -} - - - -/****************************************************************************** - * Destructor - *****************************************************************************/ -ntlRaytracer::~ntlRaytracer() -{ - delete mpGlob->getScene(); - delete mpGlob; - delete mpLightList; - delete mpPropList; - delete mpSims; -#ifndef NOGUI - if(mpOpenGLRenderer) delete mpOpenGLRenderer; -#endif // NOGUI -} - -/******************************************************************************/ -/*! set single frame rendering to filename */ -void ntlRaytracer::setSingleFrameOut(string singleframeFilename) { - mpGlob->setSingleFrameMode(true); - mpGlob->setSingleFrameFilename(singleframeFilename); -} - -/****************************************************************************** - * render a whole animation (command line mode) - *****************************************************************************/ -#if ELBEEM_BLENDER==1 -extern "C" { - void simulateThreadIncreaseFrame(void); -} -#endif // ELBEEM_BLENDER==1 -int ntlRaytracer::renderAnimation( void ) -{ - // only single pic currently - //debMsgStd("ntlRaytracer::renderAnimation : Warning only simulating...",1); - if(mpGlob->getAniFrames() < 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No frames to render... ",1); - return 1; - } - - if(mFirstSim<0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No reference animation found...",1); - return 1; - } - - mThreadRunning = true; // not threaded, but still use the same flags - renderScene(); - for(int i=0; ((igetAniFrames()) && (!getStopRenderVisualization() )); i++) { - advanceSims(); - renderScene(); -#if ELBEEM_BLENDER==1 - // update gui display - simulateThreadIncreaseFrame(); -#endif // ELBEEM_BLENDER==1 - - if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); - return 1; - } - } - mThreadRunning = false; - - return 0; -} - -/****************************************************************************** - * render a whole animation (visualization mode) - * this function is run in another thread, and communicates - * with the parent thread via a mutex - *****************************************************************************/ -int ntlRaytracer::renderVisualization( bool multiThreaded ) -{ -#ifndef NOGUI - //gfxReal deltat = 0.0015; - if(multiThreaded) mThreadRunning = true; - while(!getStopRenderVisualization()) { - - if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); - stopSimulationThread(); - break; - } - - // determine stepsize - if(!mSingleStepDebug) { - long startTime = getTime(); - advanceSims(); - long stopTime = getTime(); - debMsgStd("ntlRaytracer::renderVisualization",DM_MSG,"Time for "<getStepTime(); - singleStepSims(targetTime); - - // check paniced sims (normally done by advanceSims - bool allPanic = true; - for(size_t i=0;isize();i++) { - if(!(*mpSims)[i]->getPanic()) allPanic = false; - } - if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); - setStopRenderVisualization( true ); - } - if(!SIMWORLD_OK()) { - warnMsg("ntlRaytracer::advanceSims","World state error... stopping" ); - setStopRenderVisualization( true ); - } - } - - // save frame - if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime ); - - // for non-threaded check events - if(!multiThreaded) { - Fl::check(); - gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw(); - } - - } - mThreadRunning = false; - stopSimulationRestoreGui(); -#else - multiThreaded = false; // remove warning -#endif - return 0; -} -/*! render a single step for viz mode */ -int ntlRaytracer::singleStepVisualization( void ) -{ - mThreadRunning = true; - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); - singleStepSims(targetTime); - mSimulationTime = (*mpSims)[0]->getCurrentTime(); - -#ifndef NOGUI - if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime ); - Fl::check(); - gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw(); - mThreadRunning = false; - stopSimulationRestoreGui(); -#else - mThreadRunning = false; -#endif // NOGUI - return 0; -} - -// dont use LBM_EPSILON here, time is always double-precision! -#define LBM_TIME_EPSILON 1e-10 - -/****************************************************************************** - * advance simulations by time t - *****************************************************************************/ -int ntlRaytracer::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(); - singleStepSims(nextTargetTime); - - // check target times - done = true; - allPanic = false; - 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()) > LBM_TIME_EPSILON) done=false; - if(allPanic) done = true; - } - - if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); - setStopRenderVisualization( true ); - } - for(size_t i=0;isize();i++) { - SimulationObject *sim = (*mpSims)[i]; - if(!sim->getVisible()) continue; - if(sim->getPanic()) continue; - sim->prepareVisualization(); - } - - return 0; -} - -/* advance simulations by a single step */ -/* dont check target time, if *targetTime==NULL */ -void ntlRaytracer::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]; - if(!sim->getVisible()) continue; - if(sim->getPanic()) continue; - 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()) > LBM_TIME_EPSILON) { - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Stepping sim "<getCurrentTime()); // timedebug - sim->step(); - } else { - done = true; - } - } - } - - mSimulationTime = (*mpSims)[mFirstSim]->getCurrentTime(); -#ifndef NOGUI - if(mpOpenGLRenderer) mpOpenGLRenderer->notifyOfNextStep(mSimulationTime); -#endif // NOGUI -} - - - - -/****************************************************************************** - * Render the current scene - * uses the global variables from the parser - *****************************************************************************/ -int ntlRaytracer::renderScene( void ) -{ -#ifndef ELBEEM_BLENDER - char nrStr[5]; /* nr conversion */ - //std::ostringstream outfilename(""); /* ppm file */ - std::ostringstream outfn_conv(""); /* converted ppm with other suffix */ - ntlRenderGlobals *glob; /* storage for global rendering parameters */ - myTime_t timeStart,totalStart,timeEnd; /* measure user running time */ - myTime_t rendStart,rendEnd; /* measure user rendering time */ - glob = mpGlob; - - /* check if picture already exists... */ - if(!glob->getSingleFrameMode() ) { - snprintf(nrStr, 5, "%04d", glob->getAniCount() ); - //outfilename << glob->getOutFilename() <<"_" << nrStr << ".ppm"; - outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png"; - - //if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) { - 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); - } - } // RAY mode - } else { - // single frame rendering, overwrite if necessary... - outfn_conv << glob->getSingleFrameFilename(); - } - - /* start program */ - timeStart = getTime(); - - /* build scene geometry */ - glob->getScene()->prepareScene(); - - /* start program */ - totalStart = getTime(); - - - /* view parameters are currently not animated */ - /* calculate rays through projection plane */ - ntlVec3Gfx direction = glob->getLookat() - glob->getEye(); - /* calculate width of screen using perpendicular triangle diven by - * viewing direction and screen plane */ - gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI ); - - /* calculate vector orthogonal to up and viewing direction */ - ntlVec3Gfx upVec = glob->getUpVec(); - ntlVec3Gfx rightVec( cross(upVec,direction) ); - normalize(rightVec); - - /* calculate screen plane up vector, perpendicular to viewdir and right vec */ - upVec = ntlVec3Gfx( cross(rightVec,direction) ); - normalize(upVec); - - /* check if vectors are valid */ - if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) { - errorOut("NTL ERROR: Invalid viewpoint vectors!\n"); - return(1); - } - - /* length from center to border of screen plane */ - rightVec *= (screenWidth*glob->getAspect() * -1.0); - upVec *= (screenWidth * -1.0); - - /* screen traversal variables */ - ntlVec3Gfx screenPos; /* current position on virtual screen */ - int Xres = glob->getResX(); /* X resolution */ - int Yres = glob->getResY(); /* Y resolution */ - ntlVec3Gfx rightStep = (rightVec/(Xres/2.0)); /* one step right for a pixel */ - ntlVec3Gfx upStep = (upVec/(Yres/2.0)); /* one step up for a pixel */ - - - /* anti alias init */ - char showAAPic = 0; - int aaDepth = glob->getAADepth(); - int aaLength; - if(aaDepth>=0) aaLength = (2<setCounterShades(0); - glob->setCounterSceneInter(0); - for (int scanline=Yres ; scanline > 0 ; --scanline) { - - debugOutInter( "ntlRaytracer::renderScene: Line "<getLookat() + upVec*((2.0*scanline-Yres)/Yres) - - rightVec; - - /* loop over all pixels in line */ - for (int sx=0 ; sx < Xres ; ++sx) { - - if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) { - // DEBUG!!! - glob->setDebugOut(10); - } else glob->setDebugOut(0); - - /* compute ray from eye through current pixel into scene... */ - ntlColor col; - if(aaDepth<0) { - ntlVec3Gfx dir(screenPos - glob->getEye()); - ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); - - /* ...and trace it */ - col = the_ray.shade(); - } else { - /* anti alias */ - int ai,aj; /* position in grid */ - int aOrg = sx*aaLength; /* grid offset x */ - int currStep = aaLength; /* step size */ - char colDiff = 1; /* do colors still differ too much? */ - ntlColor minCol,maxCol; /* minimum and maximum Color Values */ - minCol = ntlColor(1.0,1.0,1.0); - maxCol = ntlColor(0.0,0.0,0.0); - - while((colDiff) && (currStep>0)) { - colDiff = 0; - - for(aj = 0;aj<=aaLength;aj+= currStep) { - for(ai = 0;ai<=aaLength;ai+= currStep) { - - /* shade pixel if not done */ - if(aaUse[aj*aaArrayX +ai +aOrg] == 0) { - aaUse[aj*aaArrayX +ai +aOrg] = 1; - ntlVec3Gfx aaPos( screenPos + - (rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) + - (upStep * (aj- aaLength/2)/(gfxReal)aaLength ) ); - - ntlVec3Gfx dir(aaPos - glob->getEye()); - ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); - - /* ...and trace it */ - ntlColor newCol= the_ray.shade(); - aaCol[aj*aaArrayX +ai +aOrg]= newCol; - } /* not used? */ - - } - } - - /* check color differences */ - for(aj = 0;aj aaSensRed ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { - thisColDiff = 1; - } else - if( - (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) { - thisColDiff = 1; - } else - if( - (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || - (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { - thisColDiff = 1; - } - - //colDiff =1; - if(thisColDiff) { - /* set diff flag */ - colDiff = thisColDiff; - for(int bj=aj;bj<=aj+currStep;bj++) { - for(int bi=ai;bi<=ai+currStep;bi++) { - if(aaUse[bj*aaArrayX +bi +aOrg]==2) { - //if(showAAPic) - aaUse[bj*aaArrayX +bi +aOrg] = 0; - } - } - } - } else { - /* set all values */ - ntlColor avgCol = ( - aaCol[(aj+0 )*aaArrayX +(ai+0 ) +aOrg] + - aaCol[(aj+0 )*aaArrayX +(ai+currStep) +aOrg] + - aaCol[(aj+currStep)*aaArrayX +(ai+0 ) +aOrg] + - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25; - for(int bj=aj;bj<=aj+currStep;bj++) { - for(int bi=ai;bi<=ai+currStep;bi++) { - if(aaUse[bj*aaArrayX +bi +aOrg]==0) { - aaCol[bj*aaArrayX +bi +aOrg] = avgCol; - aaUse[bj*aaArrayX +bi +aOrg] = 2; - } - } - } - } /* smaller values set */ - - } - } - - /* half step size */ - currStep /= 2; - - } /* repeat until diff not too big */ - - /* get average color */ - gfxReal colNum = 0.0; - col = ntlColor(0.0, 0.0, 0.0); - for(aj = 0;aj<=aaLength;aj++) { - for(ai = 0;ai<=aaLength;ai++) { - col += aaCol[aj*aaArrayX +ai +aOrg]; - colNum += 1.0; - } - } - col /= colNum; - - } - - /* mark pixels with debugging */ - if( glob->getDebugOut() > 0) col = ntlColor(0,1,0); - - /* store pixel */ - if(!showAAPic) { - finalPic[(scanline-1)*picX+sx] = col; - } - screenPos += rightStep; - - } /* foreach x */ - - /* init aa array */ - if(showAAPic) { - for(int j=0;j<=aaArrayY-1;j++) { - for(int i=0;i<=aaArrayX-1;i++) { - if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0; - } - } - } - - for(int i=0;i= 1.0) col[cc] = 1.0; - } - *filler = (unsigned char)( col[0]*255.0 ); - filler++; - *filler = (unsigned char)( col[1]*255.0 ); - filler++; - *filler = (unsigned char)( col[2]*255.0 ); - filler++; - *filler = (unsigned char)( 255.0 ); - filler++; // alpha channel - } - } - - for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ]; -#ifndef NOPNG - writePng(outfn_conv.str().c_str(), rows, w, h); -#else // NOPNG - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); -#endif // NOPNG - } - - - // next frame - glob->setAniCount( glob->getAniCount() +1 ); - - // done - timeEnd = getTime(); - - char resout[1024]; - snprintf(resout,1024, "NTL Done %s, frame %d/%d (%s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", - outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1), - 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 ); - - /* clean stuff up */ - delete [] aaCol; - delete [] aaUse; - delete [] finalPic; - glob->getScene()->cleanupScene(); - - if(mpGlob->getSingleFrameMode() ) { - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); - return 1; - } -#endif // ELBEEM_BLENDER - return 0; -} - - - diff --git a/intern/elbeem/intern/ntl_raytracer.h b/intern/elbeem/intern/ntl_raytracer.h deleted file mode 100644 index 3f36fabaf92..00000000000 --- a/intern/elbeem/intern/ntl_raytracer.h +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * Main renderer class - * - *****************************************************************************/ -#ifndef NTL_RAYTRACER_HH -#define NTL_RAYTRACER_HH - -#include "ntl_vector3dim.h" -#include "ntl_ray.h" -#include "ntl_geometryobject.h" -#include "ntl_lightobject.h" -#include "ntl_renderglobals.h" -#include "ntl_material.h" -#include "simulation_object.h" -class ntlOpenGLRenderer; - -class ntlRaytracer -{ - public: - /*! Constructor */ - ntlRaytracer(string filename, bool commandlineMode); - /*! Destructor */ - virtual ~ntlRaytracer( void ); - - /*! render a whole animation (command line mode) */ - int renderAnimation( void ); - /*! render a whole animation (visualization mode) */ - int renderVisualization( bool ); - /*! render a single step for viz mode */ - int singleStepVisualization( void ); - /*! advance simulations by time frame time */ - int advanceSims(); - /*! advance simulations by a single step */ - void singleStepSims(double targetTime); - - /*! set stop rend viz flag */ - void setStopRenderVisualization(bool set) { mStopRenderVisualization = set; } - /*! should the rendering viz thread be stopped? */ - bool getStopRenderVisualization() { return mStopRenderVisualization; } - - /*! render scene (a single pictures) */ - virtual int renderScene( void ); - - /*! display world with opengl */ - //int draw( void ); - /*! set single frame rendering to filename */ - void setSingleFrameOut( string singleframeFilename ); - - /* access functions */ - - /*! set&get render globals */ - inline void setRenderGlobals( ntlRenderGlobals *set) { mpGlob = set; } - inline ntlRenderGlobals *getRenderGlobals( void ) { return mpGlob; } - - /*! set&get render globals */ - inline void setSimulationTime( double set) { mSimulationTime = set; } - inline double getSimulationTime( void ) { return mSimulationTime; } - - /*! set&get single step debug mode */ - inline void setSingleStepDebug( bool set) { mSingleStepDebug = set; } - inline bool getSingleStepDebug( void ) { return mSingleStepDebug; } - - /*! &get simulation object vector (debugging) */ - inline vector *getSimulations( void ) { return mpSims; } - - /*! get opengl renderer */ - inline ntlOpenGLRenderer *getOpenGLRenderer() { return mpOpenGLRenderer; } - - private: - - protected: - - /*! global render settings needed almost everywhere */ - ntlRenderGlobals *mpGlob; - - /*! a list of lights in the scene (geometry is store in ntl_scene) */ - vector *mpLightList; - /*! surface materials */ - vector *mpPropList; - /*! sims list */ - vector *mpSims; - - /*! opengl display */ - ntlOpenGLRenderer *mpOpenGLRenderer; - - /*! stop rend viz? */ - bool mStopRenderVisualization; - - /*! rend viz thread currently running? */ - bool mThreadRunning; - - /*! remember the current simulation time */ - double mSimulationTime; - /*! first simulation that is valid */ - int mFirstSim; - - /*! single step mode for debugging */ - bool mSingleStepDebug; -}; - -#endif diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp new file mode 100644 index 00000000000..bd7a6abeb6f --- /dev/null +++ b/intern/elbeem/intern/ntl_world.cpp @@ -0,0 +1,716 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004 Nils Thuerey + * + * Main renderer class + * + *****************************************************************************/ + + +#include +#include +#include "utilities.h" +#include "ntl_world.h" +#include "ntl_scene.h" +#include "parametrizer.h" +#include "globals.h" + +// for non-threaded renderViz +#ifndef NOGUI +#include "../gui/ntl_openglrenderer.h" +#include "../gui/guifuncs.h" +#include "../gui/frame.h" +#endif + + +/* external parser functions from cfgparser.cxx */ +/* parse given file as config file */ +void parseFile(string filename); +/* set pointers for parsing */ +void setPointers( ntlRenderGlobals *setglob); + + +/****************************************************************************** + * Constructor + *****************************************************************************/ +ntlWorld::ntlWorld(string filename, bool commandlineMode) : + mpGlob(NULL), + mpLightList(NULL), mpPropList(NULL), mpSims(NULL), + mpOpenGLRenderer(NULL), + mStopRenderVisualization( false ), + mThreadRunning( false ), + mSimulationTime(0.0), mFirstSim(-1), + mSingleStepDebug( false ) +{ + /* create scene storage */ + mpGlob = new ntlRenderGlobals(); + mpLightList = new vector; + mpPropList = new vector; + mpSims = new vector; + + mpGlob->setLightList(mpLightList); + mpGlob->setMaterials(mpPropList); + mpGlob->setSims(mpSims); + + /* init default material */ + ntlMaterial *def = GET_GLOBAL_DEFAULT_MATERIAL; + mpPropList->push_back( def ); + + /* init the scene object */ + ntlScene *scene; + scene = new ntlScene( mpGlob ); + mpGlob->setScene( scene ); + + // load config + setPointers( getRenderGlobals() ); + parseFile( filename.c_str() ); + if(!SIMWORLD_OK()) return; + + // init the scene for the first time + long sstartTime = getTime(); + scene->buildScene(); + long sstopTime = getTime(); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); + + // TODO check simulations, run first steps + mFirstSim = -1; + if(mpSims->size() > 0) { + + // use values from first simulation as master time scale + long startTime = getTime(); + + // remember first active sim + for(size_t i=0;isize();i++) { + if(!(*mpSims)[i]->getVisible()) continue; + if((*mpSims)[i]->getPanic()) continue; + + // check largest timestep + if(mFirstSim>=0) { + if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) { + mFirstSim = i; + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<=0) { + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); + while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) { + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<getStartTime(); + 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("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); + } + } + +#ifndef NOGUI + // setup opengl display, save first animation step for start time + if(!commandlineMode) { + mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob, scene ); + } +#else // NOGUI + commandlineMode = true; // remove warning... +#endif // NOGUI +} + + + +/****************************************************************************** + * Destructor + *****************************************************************************/ +ntlWorld::~ntlWorld() +{ + delete mpGlob->getScene(); + delete mpGlob; + delete mpLightList; + delete mpPropList; + delete mpSims; +#ifndef NOGUI + if(mpOpenGLRenderer) delete mpOpenGLRenderer; +#endif // NOGUI +} + +/******************************************************************************/ +/*! set single frame rendering to filename */ +void ntlWorld::setSingleFrameOut(string singleframeFilename) { + mpGlob->setSingleFrameMode(true); + mpGlob->setSingleFrameFilename(singleframeFilename); +} + +/****************************************************************************** + * render a whole animation (command line mode) + *****************************************************************************/ +#if ELBEEM_BLENDER==1 +extern "C" { + void simulateThreadIncreaseFrame(void); +} +#endif // ELBEEM_BLENDER==1 +int ntlWorld::renderAnimation( void ) +{ + // only single pic currently + //debMsgStd("ntlWorld::renderAnimation : Warning only simulating...",1); + if(mpGlob->getAniFrames() < 0) { + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No frames to render... ",1); + return 1; + } + + if(mFirstSim<0) { + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No reference animation found...",1); + return 1; + } + + mThreadRunning = true; // not threaded, but still use the same flags + renderScene(); + for(int i=0; ((igetAniFrames()) && (!getStopRenderVisualization() )); i++) { + advanceSims(); + renderScene(); +#if ELBEEM_BLENDER==1 + // update gui display + simulateThreadIncreaseFrame(); +#endif // ELBEEM_BLENDER==1 + + if(mpSims->size() <= 0) { + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); + return 1; + } + } + mThreadRunning = false; + + return 0; +} + +/****************************************************************************** + * render a whole animation (visualization mode) + * this function is run in another thread, and communicates + * with the parent thread via a mutex + *****************************************************************************/ +int ntlWorld::renderVisualization( bool multiThreaded ) +{ +#ifndef NOGUI + //gfxReal deltat = 0.0015; + if(multiThreaded) mThreadRunning = true; + while(!getStopRenderVisualization()) { + + if(mpSims->size() <= 0) { + debMsgStd("ntlWorld::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); + stopSimulationThread(); + break; + } + + // determine stepsize + if(!mSingleStepDebug) { + long startTime = getTime(); + advanceSims(); + long stopTime = getTime(); + debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for "<getStepTime(); + singleStepSims(targetTime); + + // check paniced sims (normally done by advanceSims + bool allPanic = true; + for(size_t i=0;isize();i++) { + if(!(*mpSims)[i]->getPanic()) allPanic = false; + } + if(allPanic) { + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); + setStopRenderVisualization( true ); + } + if(!SIMWORLD_OK()) { + warnMsg("ntlWorld::advanceSims","World state error... stopping" ); + setStopRenderVisualization( true ); + } + } + + // save frame + if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime ); + + // for non-threaded check events + if(!multiThreaded) { + Fl::check(); + gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw(); + } + + } + mThreadRunning = false; + stopSimulationRestoreGui(); +#else + multiThreaded = false; // remove warning +#endif + return 0; +} +/*! render a single step for viz mode */ +int ntlWorld::singleStepVisualization( void ) +{ + mThreadRunning = true; + double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); + singleStepSims(targetTime); + mSimulationTime = (*mpSims)[0]->getCurrentTime(); + +#ifndef NOGUI + if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime ); + Fl::check(); + gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw(); + mThreadRunning = false; + stopSimulationRestoreGui(); +#else + mThreadRunning = false; +#endif // NOGUI + return 0; +} + +// dont use LBM_EPSILON here, time is always double-precision! +#define LBM_TIME_EPSILON 1e-10 + +/****************************************************************************** + * advance simulations by time t + *****************************************************************************/ +int ntlWorld::advanceSims() +{ + bool done = false; + bool allPanic = true; + double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(); + //debMsgStd("ntlWorld::advanceSims",DM_MSG,"Advancing sims to "<getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime(); + singleStepSims(nextTargetTime); + + // check target times + done = true; + allPanic = false; + for(size_t i=0;isize();i++) { + if(!(*mpSims)[i]->getVisible()) continue; + if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? + //debMsgStd("ntlWorld::advanceSims",DM_MSG, " sim "<getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<getCurrentTime()) > LBM_TIME_EPSILON) done=false; + if(allPanic) done = true; + } + + if(allPanic) { + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); + setStopRenderVisualization( true ); + } + for(size_t i=0;isize();i++) { + SimulationObject *sim = (*mpSims)[i]; + if(!sim->getVisible()) continue; + if(sim->getPanic()) continue; + sim->prepareVisualization(); + } + + return 0; +} + +/* advance simulations by a single step */ +/* dont check target time, if *targetTime==NULL */ +void ntlWorld::singleStepSims(double targetTime) { + const bool debugTime = false; + //double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); + if(debugTime) errMsg("ntlWorld::singleStepSims","Target time: "<size();i++) { + SimulationObject *sim = (*mpSims)[i]; + if(!sim->getVisible()) continue; + if(sim->getPanic()) continue; + bool done = false; + while(!done) { + // try to prevent round off errs + if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<getCurrentTime()<<" target:"<getCurrentTime())<<" stept:"<getStepTime()<<" leps:"<getCurrentTime()) > LBM_TIME_EPSILON) { + if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping sim "<getCurrentTime()); // timedebug + sim->step(); + } else { + done = true; + } + } + } + + mSimulationTime = (*mpSims)[mFirstSim]->getCurrentTime(); +#ifndef NOGUI + if(mpOpenGLRenderer) mpOpenGLRenderer->notifyOfNextStep(mSimulationTime); +#endif // NOGUI +} + + + + +/****************************************************************************** + * Render the current scene + * uses the global variables from the parser + *****************************************************************************/ +int ntlWorld::renderScene( void ) +{ +#ifndef ELBEEM_BLENDER + char nrStr[5]; /* nr conversion */ + //std::ostringstream outfilename(""); /* ppm file */ + std::ostringstream outfn_conv(""); /* converted ppm with other suffix */ + ntlRenderGlobals *glob; /* storage for global rendering parameters */ + myTime_t timeStart,totalStart,timeEnd; /* measure user running time */ + myTime_t rendStart,rendEnd; /* measure user rendering time */ + glob = mpGlob; + + /* check if picture already exists... */ + if(!glob->getSingleFrameMode() ) { + snprintf(nrStr, 5, "%04d", glob->getAniCount() ); + //outfilename << glob->getOutFilename() <<"_" << nrStr << ".ppm"; + outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png"; + + //if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) { + if(mpGlob->getFrameSkip()) { + struct stat statBuf; + if(stat(outfn_conv.str().c_str(),&statBuf) == 0) { + errorOut("ntlWorld::renderscene Warning: file "<setAniCount( glob->getAniCount() +1 ); + return(2); + } + } // RAY mode + } else { + // single frame rendering, overwrite if necessary... + outfn_conv << glob->getSingleFrameFilename(); + } + + /* start program */ + timeStart = getTime(); + + /* build scene geometry */ + glob->getScene()->prepareScene(); + + /* start program */ + totalStart = getTime(); + + + /* view parameters are currently not animated */ + /* calculate rays through projection plane */ + ntlVec3Gfx direction = glob->getLookat() - glob->getEye(); + /* calculate width of screen using perpendicular triangle diven by + * viewing direction and screen plane */ + gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI ); + + /* calculate vector orthogonal to up and viewing direction */ + ntlVec3Gfx upVec = glob->getUpVec(); + ntlVec3Gfx rightVec( cross(upVec,direction) ); + normalize(rightVec); + + /* calculate screen plane up vector, perpendicular to viewdir and right vec */ + upVec = ntlVec3Gfx( cross(rightVec,direction) ); + normalize(upVec); + + /* check if vectors are valid */ + if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) { + errorOut("NTL ERROR: Invalid viewpoint vectors!\n"); + return(1); + } + + /* length from center to border of screen plane */ + rightVec *= (screenWidth*glob->getAspect() * -1.0); + upVec *= (screenWidth * -1.0); + + /* screen traversal variables */ + ntlVec3Gfx screenPos; /* current position on virtual screen */ + int Xres = glob->getResX(); /* X resolution */ + int Yres = glob->getResY(); /* Y resolution */ + ntlVec3Gfx rightStep = (rightVec/(Xres/2.0)); /* one step right for a pixel */ + ntlVec3Gfx upStep = (upVec/(Yres/2.0)); /* one step up for a pixel */ + + + /* anti alias init */ + char showAAPic = 0; + int aaDepth = glob->getAADepth(); + int aaLength; + if(aaDepth>=0) aaLength = (2<setCounterShades(0); + glob->setCounterSceneInter(0); + for (int scanline=Yres ; scanline > 0 ; --scanline) { + + debugOutInter( "ntlWorld::renderScene: Line "<getLookat() + upVec*((2.0*scanline-Yres)/Yres) + - rightVec; + + /* loop over all pixels in line */ + for (int sx=0 ; sx < Xres ; ++sx) { + + if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) { + // DEBUG!!! + glob->setDebugOut(10); + } else glob->setDebugOut(0); + + /* compute ray from eye through current pixel into scene... */ + ntlColor col; + if(aaDepth<0) { + ntlVec3Gfx dir(screenPos - glob->getEye()); + ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); + + /* ...and trace it */ + col = the_ray.shade(); + } else { + /* anti alias */ + int ai,aj; /* position in grid */ + int aOrg = sx*aaLength; /* grid offset x */ + int currStep = aaLength; /* step size */ + char colDiff = 1; /* do colors still differ too much? */ + ntlColor minCol,maxCol; /* minimum and maximum Color Values */ + minCol = ntlColor(1.0,1.0,1.0); + maxCol = ntlColor(0.0,0.0,0.0); + + while((colDiff) && (currStep>0)) { + colDiff = 0; + + for(aj = 0;aj<=aaLength;aj+= currStep) { + for(ai = 0;ai<=aaLength;ai+= currStep) { + + /* shade pixel if not done */ + if(aaUse[aj*aaArrayX +ai +aOrg] == 0) { + aaUse[aj*aaArrayX +ai +aOrg] = 1; + ntlVec3Gfx aaPos( screenPos + + (rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) + + (upStep * (aj- aaLength/2)/(gfxReal)aaLength ) ); + + ntlVec3Gfx dir(aaPos - glob->getEye()); + ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); + + /* ...and trace it */ + ntlColor newCol= the_ray.shade(); + aaCol[aj*aaArrayX +ai +aOrg]= newCol; + } /* not used? */ + + } + } + + /* check color differences */ + for(aj = 0;aj aaSensRed ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - + aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - + aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { + thisColDiff = 1; + } else + if( + (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - + aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - + aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - + aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) { + thisColDiff = 1; + } else + if( + (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || + (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { + thisColDiff = 1; + } + + //colDiff =1; + if(thisColDiff) { + /* set diff flag */ + colDiff = thisColDiff; + for(int bj=aj;bj<=aj+currStep;bj++) { + for(int bi=ai;bi<=ai+currStep;bi++) { + if(aaUse[bj*aaArrayX +bi +aOrg]==2) { + //if(showAAPic) + aaUse[bj*aaArrayX +bi +aOrg] = 0; + } + } + } + } else { + /* set all values */ + ntlColor avgCol = ( + aaCol[(aj+0 )*aaArrayX +(ai+0 ) +aOrg] + + aaCol[(aj+0 )*aaArrayX +(ai+currStep) +aOrg] + + aaCol[(aj+currStep)*aaArrayX +(ai+0 ) +aOrg] + + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25; + for(int bj=aj;bj<=aj+currStep;bj++) { + for(int bi=ai;bi<=ai+currStep;bi++) { + if(aaUse[bj*aaArrayX +bi +aOrg]==0) { + aaCol[bj*aaArrayX +bi +aOrg] = avgCol; + aaUse[bj*aaArrayX +bi +aOrg] = 2; + } + } + } + } /* smaller values set */ + + } + } + + /* half step size */ + currStep /= 2; + + } /* repeat until diff not too big */ + + /* get average color */ + gfxReal colNum = 0.0; + col = ntlColor(0.0, 0.0, 0.0); + for(aj = 0;aj<=aaLength;aj++) { + for(ai = 0;ai<=aaLength;ai++) { + col += aaCol[aj*aaArrayX +ai +aOrg]; + colNum += 1.0; + } + } + col /= colNum; + + } + + /* mark pixels with debugging */ + if( glob->getDebugOut() > 0) col = ntlColor(0,1,0); + + /* store pixel */ + if(!showAAPic) { + finalPic[(scanline-1)*picX+sx] = col; + } + screenPos += rightStep; + + } /* foreach x */ + + /* init aa array */ + if(showAAPic) { + for(int j=0;j<=aaArrayY-1;j++) { + for(int i=0;i<=aaArrayX-1;i++) { + if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0; + } + } + } + + for(int i=0;i= 1.0) col[cc] = 1.0; + } + *filler = (unsigned char)( col[0]*255.0 ); + filler++; + *filler = (unsigned char)( col[1]*255.0 ); + filler++; + *filler = (unsigned char)( col[2]*255.0 ); + filler++; + *filler = (unsigned char)( 255.0 ); + filler++; // alpha channel + } + } + + for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ]; +#ifndef NOPNG + writePng(outfn_conv.str().c_str(), rows, w, h); +#else // NOPNG + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); +#endif // NOPNG + } + + + // next frame + glob->setAniCount( glob->getAniCount() +1 ); + + // done + timeEnd = getTime(); + + char resout[1024]; + snprintf(resout,1024, "NTL Done %s, frame %d/%d (%s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", + outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1), + getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(), + glob->getCounterShades(), + glob->getCounterSceneInter() ); + debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 ); + + /* clean stuff up */ + delete [] aaCol; + delete [] aaUse; + delete [] finalPic; + glob->getScene()->cleanupScene(); + + if(mpGlob->getSingleFrameMode() ) { + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); + return 1; + } +#endif // ELBEEM_BLENDER + return 0; +} + + + diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h new file mode 100644 index 00000000000..0da7171bad6 --- /dev/null +++ b/intern/elbeem/intern/ntl_world.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004 Nils Thuerey + * + * Main renderer class + * + *****************************************************************************/ +#ifndef NTL_RAYTRACER_HH +#define NTL_RAYTRACER_HH + +#include "ntl_vector3dim.h" +#include "ntl_ray.h" +#include "ntl_geometryobject.h" +#include "ntl_lightobject.h" +#include "ntl_renderglobals.h" +#include "ntl_material.h" +#include "simulation_object.h" +class ntlOpenGLRenderer; + +class ntlWorld +{ + public: + /*! Constructor */ + ntlWorld(string filename, bool commandlineMode); + /*! Destructor */ + virtual ~ntlWorld( void ); + + /*! render a whole animation (command line mode) */ + int renderAnimation( void ); + /*! render a whole animation (visualization mode) */ + int renderVisualization( bool ); + /*! render a single step for viz mode */ + int singleStepVisualization( void ); + /*! advance simulations by time frame time */ + int advanceSims(); + /*! advance simulations by a single step */ + void singleStepSims(double targetTime); + + /*! set stop rend viz flag */ + void setStopRenderVisualization(bool set) { mStopRenderVisualization = set; } + /*! should the rendering viz thread be stopped? */ + bool getStopRenderVisualization() { return mStopRenderVisualization; } + + /*! render scene (a single pictures) */ + virtual int renderScene( void ); + + /*! display world with opengl */ + //int draw( void ); + /*! set single frame rendering to filename */ + void setSingleFrameOut( string singleframeFilename ); + + /* access functions */ + + /*! set&get render globals */ + inline void setRenderGlobals( ntlRenderGlobals *set) { mpGlob = set; } + inline ntlRenderGlobals *getRenderGlobals( void ) { return mpGlob; } + + /*! set&get render globals */ + inline void setSimulationTime( double set) { mSimulationTime = set; } + inline double getSimulationTime( void ) { return mSimulationTime; } + + /*! set&get single step debug mode */ + inline void setSingleStepDebug( bool set) { mSingleStepDebug = set; } + inline bool getSingleStepDebug( void ) { return mSingleStepDebug; } + + /*! &get simulation object vector (debugging) */ + inline vector *getSimulations( void ) { return mpSims; } + + /*! get opengl renderer */ + inline ntlOpenGLRenderer *getOpenGLRenderer() { return mpOpenGLRenderer; } + + private: + + protected: + + /*! global render settings needed almost everywhere */ + ntlRenderGlobals *mpGlob; + + /*! a list of lights in the scene (geometry is store in ntl_scene) */ + vector *mpLightList; + /*! surface materials */ + vector *mpPropList; + /*! sims list */ + vector *mpSims; + + /*! opengl display */ + ntlOpenGLRenderer *mpOpenGLRenderer; + + /*! stop rend viz? */ + bool mStopRenderVisualization; + + /*! rend viz thread currently running? */ + bool mThreadRunning; + + /*! remember the current simulation time */ + double mSimulationTime; + /*! first simulation that is valid */ + int mFirstSim; + + /*! single step mode for debugging */ + bool mSingleStepDebug; +}; + +#endif 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/solver_interface.cpp b/intern/elbeem/intern/solver_interface.cpp new file mode 100644 index 00000000000..3d77e4a4968 --- /dev/null +++ b/intern/elbeem/intern/solver_interface.cpp @@ -0,0 +1,809 @@ +/****************************************************************************** + * + * 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 Interface Class + * contains stuff to be statically compiled + * + *****************************************************************************/ + +/* LBM Files */ +#include "solver_interface.h" +#include "ntl_scene.h" +#include "ntl_ray.h" + + +/*****************************************************************************/ +//! common variables + +/*****************************************************************************/ +/*! class for solver templating - 3D implementation D3Q19 */ + + //! how many dimensions? + const int LbmD3Q19::cDimension = 3; + + // Wi factors for collide step + const LbmFloat LbmD3Q19::cCollenZero = (1.0/3.0); + const LbmFloat LbmD3Q19::cCollenOne = (1.0/18.0); + const LbmFloat LbmD3Q19::cCollenSqrtTwo = (1.0/36.0); + + //! threshold value for filled/emptied cells + const LbmFloat LbmD3Q19::cMagicNr2 = 1.0005; + const LbmFloat LbmD3Q19::cMagicNr2Neg = -0.0005; + const LbmFloat LbmD3Q19::cMagicNr = 1.010001; + const LbmFloat LbmD3Q19::cMagicNrNeg = -0.010001; + + //! size of a single set of distribution functions + const int LbmD3Q19::cDfNum = 19; + //! direction vector contain vecs for all spatial dirs, even if not used for LBM model + const int LbmD3Q19::cDirNum = 27; + + //const string LbmD3Q19::dfString[ cDfNum ] = { + const char* LbmD3Q19::dfString[ cDfNum ] = { + " C", " N"," S"," E"," W"," T"," B", + "NE","NW","SE","SW", + "NT","NB","ST","SB", + "ET","EB","WT","WB" + }; + + const int LbmD3Q19::dfNorm[ cDfNum ] = { + cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB, + cDirNE, cDirNW, cDirSE, cDirSW, + cDirNT, cDirNB, cDirST, cDirSB, + cDirET, cDirEB, cDirWT, cDirWB + }; + + const int LbmD3Q19::dfInv[ cDfNum ] = { + cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT, + cDirSW, cDirSE, cDirNW, cDirNE, + cDirSB, cDirST, cDirNB, cDirNT, + cDirWB, cDirWT, cDirEB, cDirET + }; + + const int LbmD3Q19::dfRefX[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + cDirSE, cDirSW, cDirNE, cDirNW, + 0, 0, 0, 0, + cDirEB, cDirET, cDirWB, cDirWT + }; + + const int LbmD3Q19::dfRefY[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + cDirNW, cDirNE, cDirSW, cDirSE, + cDirNB, cDirNT, cDirSB, cDirST, + 0, 0, 0, 0 + }; + + const int LbmD3Q19::dfRefZ[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + cDirST, cDirSB, cDirNT, cDirNB, + cDirWT, cDirWB, cDirET, cDirEB + }; + + // 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 + + const int LbmD3Q19::dfVecX[ cDirNum ] = { + 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, + }; + const int LbmD3Q19::dfVecY[ cDirNum ] = { + 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 + }; + const int LbmD3Q19::dfVecZ[ cDirNum ] = { + 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 + }; + + const LbmFloat LbmD3Q19::dfDvecX[ cDirNum ] = { + 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 + }; + const LbmFloat LbmD3Q19::dfDvecY[ cDirNum ] = { + 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 + }; + const LbmFloat LbmD3Q19::dfDvecZ[ cDirNum ] = { + 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 + }; + + /* principal directions */ + const int LbmD3Q19::princDirX[ 2*LbmD3Q19::cDimension ] = { + 1,-1, 0,0, 0,0 + }; + const int LbmD3Q19::princDirY[ 2*LbmD3Q19::cDimension ] = { + 0,0, 1,-1, 0,0 + }; + const int LbmD3Q19::princDirZ[ 2*LbmD3Q19::cDimension ] = { + 0,0, 0,0, 1,-1 + }; + + /*! arrays for les model coefficients, inited in lbmsolver constructor */ + LbmFloat LbmD3Q19::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; + LbmFloat LbmD3Q19::lesCoeffOffdiag[ cDimension ][ cDirNum ]; + + + const LbmFloat LbmD3Q19::dfLength[ cDfNum ]= { + cCollenZero, + cCollenOne, cCollenOne, cCollenOne, + cCollenOne, cCollenOne, cCollenOne, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo + }; + + /* precalculated equilibrium dfs, inited in lbmsolver constructor */ + LbmFloat LbmD3Q19::dfEquil[ cDfNum ]; + +// D3Q19 end + + + +/*****************************************************************************/ +/*! class for solver templating - 2D implementation D2Q9 */ + + //! how many dimensions? + const int LbmD2Q9::cDimension = 2; + + //! Wi factors for collide step + const LbmFloat LbmD2Q9::cCollenZero = (4.0/9.0); + const LbmFloat LbmD2Q9::cCollenOne = (1.0/9.0); + const LbmFloat LbmD2Q9::cCollenSqrtTwo = (1.0/36.0); + + //! threshold value for filled/emptied cells + const LbmFloat LbmD2Q9::cMagicNr2 = 1.0005; + const LbmFloat LbmD2Q9::cMagicNr2Neg = -0.0005; + const LbmFloat LbmD2Q9::cMagicNr = 1.010001; + const LbmFloat LbmD2Q9::cMagicNrNeg = -0.010001; + + //! size of a single set of distribution functions + const int LbmD2Q9::cDfNum = 9; + const int LbmD2Q9::cDirNum = 9; + + //const string LbmD2Q9::dfString[ cDfNum ] = { + const char* LbmD2Q9::dfString[ cDfNum ] = { + " C", + " N", " S", " E", " W", + "NE", "NW", "SE","SW" + }; + + const int LbmD2Q9::dfNorm[ cDfNum ] = { + cDirC, + cDirN, cDirS, cDirE, cDirW, + cDirNE, cDirNW, cDirSE, cDirSW + }; + + const int LbmD2Q9::dfInv[ cDfNum ] = { + cDirC, + cDirS, cDirN, cDirW, cDirE, + cDirSW, cDirSE, cDirNW, cDirNE + }; + + const int LbmD2Q9::dfRefX[ cDfNum ] = { + 0, + 0, 0, 0, 0, + cDirSE, cDirSW, cDirNE, cDirNW + }; + + const int LbmD2Q9::dfRefY[ cDfNum ] = { + 0, + 0, 0, 0, 0, + cDirNW, cDirNE, cDirSW, cDirSE + }; + + const int LbmD2Q9::dfRefZ[ cDfNum ] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + // 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 + + const int LbmD2Q9::dfVecX[ cDirNum ] = { + 0, + 0,0, 1,-1, + 1,-1,1,-1 + }; + const int LbmD2Q9::dfVecY[ cDirNum ] = { + 0, + 1,-1, 0,0, + 1,1,-1,-1 + }; + const int LbmD2Q9::dfVecZ[ cDirNum ] = { + 0, 0,0,0,0, 0,0,0,0 + }; + + const LbmFloat LbmD2Q9::dfDvecX[ cDirNum ] = { + 0, + 0,0, 1,-1, + 1,-1,1,-1 + }; + const LbmFloat LbmD2Q9::dfDvecY[ cDirNum ] = { + 0, + 1,-1, 0,0, + 1,1,-1,-1 + }; + const LbmFloat LbmD2Q9::dfDvecZ[ cDirNum ] = { + 0, 0,0,0,0, 0,0,0,0 + }; + + const int LbmD2Q9::princDirX[ 2*LbmD2Q9::cDimension ] = { + 1,-1, 0,0 + }; + const int LbmD2Q9::princDirY[ 2*LbmD2Q9::cDimension ] = { + 0,0, 1,-1 + }; + const int LbmD2Q9::princDirZ[ 2*LbmD2Q9::cDimension ] = { + 0,0, 0,0 + }; + + + /*! arrays for les model coefficients, inited in lbmsolver constructor */ + LbmFloat LbmD2Q9::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; + LbmFloat LbmD2Q9::lesCoeffOffdiag[ cDimension ][ cDirNum ]; + + + const LbmFloat LbmD2Q9::dfLength[ cDfNum ]= { + cCollenZero, + cCollenOne, cCollenOne, cCollenOne, cCollenOne, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo + }; + + /* precalculated equilibrium dfs, inited in lbmsolver constructor */ + LbmFloat LbmD2Q9::dfEquil[ cDfNum ]; + +// D2Q9 end + + + +/****************************************************************************** + * Interface Constructor + *****************************************************************************/ +LbmSolverInterface::LbmSolverInterface() : + mPanic( false ), + mSizex(10), mSizey(10), mSizez(10), + mStepCnt( 0 ), + mFixMass( 0.0 ), + mOmega( 1.0 ), + mGravity(0.0), + mSurfaceTension( 0.0 ), + mBoundaryEast( (CellFlagType)(CFBnd) ),mBoundaryWest( (CellFlagType)(CFBnd) ),mBoundaryNorth( (CellFlagType)(CFBnd) ), + mBoundarySouth( (CellFlagType)(CFBnd) ),mBoundaryTop( (CellFlagType)(CFBnd) ),mBoundaryBottom( (CellFlagType)(CFBnd) ), + mInitDone( false ), + mInitDensityGradient( false ), + mpAttrs( NULL ), mpParam( NULL ), + mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0), + mDebugVelScale( 1.0 ), mNodeInfoString("+"), + mRandom( 5123 ), + mvGeoStart(-1.0), mvGeoEnd(1.0), + mPerformGeoInit( false ), + mAccurateGeoinit(0), + mName("lbm_default") , + mpIso( NULL ), mIsoValue(0.49999), + mSilent(false) , + mGeoInitId( 0 ), + mpGiTree( NULL ), + mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL ), + mMarkedCells(), mMarkedCellIndex(0) +{ +#if ELBEEM_BLENDER==1 + if(gDebugLevel<=1) mSilent = true; +#endif +} + + +/*******************************************************************************/ +/*! parse a boundary flag string */ +CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed) { + string val = mpAttrs->readString(name, "", source, target, needed); + if(!strcmp(val.c_str(),"")) { + // no value given... + return CFEmpty; + } + if(!strcmp(val.c_str(),"bnd_no")) { + return (CellFlagType)( CFBnd ); + } + if(!strcmp(val.c_str(),"bnd_free")) { + return (CellFlagType)( CFBnd ); + } + if(!strcmp(val.c_str(),"fluid")) { + /* might be used for some in/out flow cases */ + return (CellFlagType)( CFFluid ); + } + errMsg("LbmStdSolver::readBoundaryFlagInt","Invalid value '"<readFloat("d_surfacetension", mSurfaceTension, "LbmStdSolver", "mSurfaceTension", false); + mBoundaryEast = readBoundaryFlagInt("boundary_east", mBoundaryEast, "LbmStdSolver", "mBoundaryEast", false); + mBoundaryWest = readBoundaryFlagInt("boundary_west", mBoundaryWest, "LbmStdSolver", "mBoundaryWest", false); + mBoundaryNorth = readBoundaryFlagInt("boundary_north", mBoundaryNorth,"LbmStdSolver", "mBoundaryNorth", false); + mBoundarySouth = readBoundaryFlagInt("boundary_south", mBoundarySouth,"LbmStdSolver", "mBoundarySouth", false); + mBoundaryTop = readBoundaryFlagInt("boundary_top", mBoundaryTop,"LbmStdSolver", "mBoundaryTop", false); + mBoundaryBottom= readBoundaryFlagInt("boundary_bottom", mBoundaryBottom,"LbmStdSolver", "mBoundaryBottom", false); + + LbmVec sizeVec(mSizex,mSizey,mSizez); + sizeVec = vec2L( mpAttrs->readVec3d("size", vec2P(sizeVec), "LbmStdSolver", "sizeVec", false) ); + mSizex = (int)sizeVec[0]; + mSizey = (int)sizeVec[1]; + mSizez = (int)sizeVec[2]; + mpParam->setSize(mSizex, mSizey, mSizez ); // param needs size in any case + + mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmStdSolver", "mInitDensityGradient", false); + mPerformGeoInit = mpAttrs->readBool("geoinit", mPerformGeoInit,"LbmStdSolver", "mPerformGeoInit", false); + mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmStdSolver", "mGeoInitId", false); + mIsoValue = mpAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false ); + + mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmStdSolver", "mDebugVelScale", false); + mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false ); +} + + +/*******************************************************************************/ +/*! geometry initialization */ +/*******************************************************************************/ + +/*****************************************************************************/ +/*! init tree for certain geometry init */ +void LbmSolverInterface::initGeoTree(int id) { + if(mpGlob == NULL) { errFatal("LbmSolverInterface::initGeoTree","Requires globals!",SIMWORLD_INITERROR); return; } + mGeoInitId = id; + ntlScene *scene = mpGlob->getScene(); + 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; + } + debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Accurate geo init: "<intersectX(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; + mGiObjInside[OId]++; + //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; + } + } + } + if(!inside) { + distance = firstHit; + OId = firstOId; + } + //errMsg("CHIII","i"<intersectX(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; + } +} +bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir, int flags, int &OId, gfxReal &distance, const gfxReal halfCellsize, bool &thinHit, bool recurse) { + // shift ve ctors to avoid rounding errors + org += ntlVec3Gfx(0.0001); //? + OId = -1; + ntlRay ray(org, dir, 0, 1.0, mpGlob); + //int insCnt = 0; + bool done = false; + bool inside = false; + 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 */ +ntlVec3Gfx LbmSolverInterface::getGeoMaxInitialVelocity() { + ntlScene *scene = mpGlob->getScene(); + mpGiObjects = scene->getObjects(); + ntlVec3Gfx max(0.0); + + for(int i=0; i< (int)mpGiObjects->size(); i++) { + if( (*mpGiObjects)[i]->getGeoInitType() & FGI_FLUID ){ + ntlVec3Gfx ovel = (*mpGiObjects)[i]->getInitialVelocity(); + if( normNoSqrt(ovel) > normNoSqrt(max) ) { max = ovel; } + //errMsg("IVT","i"<getInitialVelocity() ); // DEBUG + } + } + //errMsg("IVT","max "<<" "<< max ); // DEBUG + // unused !? mGiInsideCnt.resize( mpGiObjects->size() ); + + return max; +} + + +/*******************************************************************************/ +/*! "traditional" initialization */ +/*******************************************************************************/ + + +/*****************************************************************************/ +// handle generic test cases (currently only reset geo init) +bool LbmSolverInterface::initGenericTestCases() { + bool initTypeFound = false; + LbmSolverInterface::CellIdentifier cid = getFirstCell(); + // deprecated! - only check for invalid cells... + + // this is the default init - check if the geometry flag init didnt + initTypeFound = true; + + while(noEndCell(cid)) { + // check node + if( (getCellFlag(cid,0)==CFInvalid) || (getCellFlag(cid,1)==CFInvalid) ) { + warnMsg("LbmSolverInterface::initGenericTestCases","GeoInit produced invalid Flag at "<getAsString()<<"!" ); + } + advanceCell( cid ); + } + + deleteCellIterator( &cid ); + return initTypeFound; +} + + +/*******************************************************************************/ +/*! cell iteration functions */ +/*******************************************************************************/ + + + + +/*****************************************************************************/ +//! add cell to mMarkedCells list +void +LbmSolverInterface::addCellToMarkedList( CellIdentifierInterface *cid ) { + for(size_t i=0; iequal(cid) ) return; + //mMarkedCells[i]->setEnd(false); + } + mMarkedCells.push_back( cid ); + //cid->setEnd(true); +} + +/*****************************************************************************/ +//! marked cell iteration methods +CellIdentifierInterface* +LbmSolverInterface::markedGetFirstCell( ) { + if(mMarkedCells.size() > 0){ return mMarkedCells[0]; } + return NULL; +} + +CellIdentifierInterface* +LbmSolverInterface::markedAdvanceCell() { + mMarkedCellIndex++; + if(mMarkedCellIndex>=(int)mMarkedCells.size()) return NULL; + return mMarkedCells[mMarkedCellIndex]; +} + +void LbmSolverInterface::markedClearList() { + // FIXME free cids? + mMarkedCells.clear(); +} + +/*******************************************************************************/ +/*! string helper functions */ +/*******************************************************************************/ + + + +// 32k +string convertSingleFlag2String(CellFlagType cflag) { + CellFlagType flag = cflag; + if(flag == CFUnused ) return string("cCFUnused"); + if(flag == CFEmpty ) return string("cCFEmpty"); + if(flag == CFBnd ) return string("cCFBnd"); + if(flag == CFNoInterpolSrc ) return string("cCFNoInterpolSrc"); + if(flag == CFFluid ) return string("cCFFluid"); + if(flag == CFInter ) return string("cCFInter"); + if(flag == CFNoNbFluid ) return string("cCFNoNbFluid"); + if(flag == CFNoNbEmpty ) return string("cCFNoNbEmpty"); + if(flag == CFNoDelete ) return string("cCFNoDelete"); + if(flag == CFNoBndFluid ) return string("cCFNoBndFluid"); + if(flag == CFGrNorm ) return string("cCFGrNorm"); + if(flag == CFGrFromFine ) return string("cCFGrFromFine"); + if(flag == CFGrFromCoarse ) return string("cCFGrFromCoarse"); + if(flag == CFGrCoarseInited ) return string("cCFGrCoarseInited"); + if(flag == CFMbndInflow ) return string("cCFMbndInflow"); + if(flag == CFMbndOutflow ) return string("cCFMbndOutflow"); + if(flag == CFInvalid ) return string("cfINVALID"); + + std::ostringstream mult; + int val = 0; + if(flag != 0) { + while(! (flag&1) ) { + flag = flag>>1; + val++; + } + } else { + val = -1; + } + mult << "cfUNKNOWN_" << val <<"_TYPE"; + return mult.str(); +} + +//! helper function to convert flag to string (for debuggin) +string convertCellFlagType2String( CellFlagType cflag ) { + int flag = cflag; + + const int jmax = sizeof(CellFlagType)*8; + bool somefound = false; + std::ostringstream mult; + mult << "["; + for(int j=0; j +#include "../gui/guifuncs.h" +#endif + +#include +#include "utilities.h" +#include "ntl_bsptree.h" +#include "ntl_geometryobject.h" +#include "ntl_rndstream.h" +#include "parametrizer.h" +#include "attributes.h" +#include "particletracer.h" +#include "isosurface.h" + +// use which fp-precision for LBM? 1=float, 2=double +#ifdef PRECISION_LBM_SINGLE +#define LBM_PRECISION 1 +#else +#ifdef PRECISION_LBM_DOUBLE +#define LBM_PRECISION 2 +#else +// default to floats +#define LBM_PRECISION 1 +#endif +#endif + +// default to 3dim +#ifndef LBMDIM +#define LBMDIM 3 +#endif // LBMDIM + +#if LBM_PRECISION==1 +/* low precision for LBM solver */ +typedef float LbmFloat; +typedef ntlVec3f LbmVec; +#define LBM_EPSILON (1e-5) +#else +/* standard precision for LBM solver */ +typedef double LbmFloat; +typedef ntlVec3d LbmVec; +#define LBM_EPSILON (1e-10) +#endif + +// conversions (lbm and parametrizer) +template inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); } +template inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); } + + +// bubble id type +typedef int BubbleId; + +// for both short int/char +#define CFUnused (1<< 0) +#define CFEmpty (1<< 1) +#define CFBnd (1<< 2) +#define CFBndNoslip (1<< 3) +#define CFBndFreeslip (1<< 4) +#define CFBndPartslip (1<< 5) +// force symmetry for flag reinit +#define CFNoInterpolSrc (1<< 6) +#define CFFluid (1<< 7) +#define CFInter (1<< 8) +#define CFNoNbFluid (1<< 9) +#define CFNoNbEmpty (1<<10) +#define CFNoDelete (1<<11) +#define CFNoBndFluid (1<<12) + +//! refinement tags +// cell treated normally on coarser grids +#define CFGrNorm (1<<13) +// border cells to be interpolated from finer grid +#define CFGrFromFine (1<<14) +#define CFGrFromCoarse (1<<15) +#define CFGrCoarseInited (1<<16) +// 32k aux border marker +#define CFGrToFine (1<<17) +#define CFMbndInflow (1<<18) +#define CFMbndOutflow (1<<19) + +// above 24 is used to encode in/outflow object type +#define CFPersistMask (0xFF000000 | CFMbndInflow | CFMbndOutflow) + +// nk +#define CFInvalid (CellFlagType)(1<<31) + +// use 32bit flag types +#ifdef __x86_64__ + typedef int cfINT32; +#else + typedef long cfINT32; +#endif // defined (_IA64) +#define CellFlagType cfINT32 +#define CellFlagTypeSize 4 + + + +/*****************************************************************************/ +/*! a single lbm cell */ +/* the template is only needed for + * dimension dependend constants e.g. + * number of df's in model */ +template +class LbmCellTemplate { + public: + LbmFloat df[ 27 ]; // be on the safe side here... + LbmFloat rho; + LbmVec vel; + LbmFloat mass; + CellFlagType flag; + BubbleId bubble; + LbmFloat ffrac; + + //! test if a flag is set + inline bool test(CellFlagType t) { + return ((flag & t)==t); + } + //! test if any of the given flags is set + inline bool testAny(CellFlagType t) { + return ((flag & t)!=0); + } + //! test if the cell is empty + inline bool isEmpty() { + return (flag == CFEmpty); + } + + //! init default values for a certain flag type + inline void initDefaults(CellFlagType type) { + flag = type; + vel = LbmVec(0.0); + for(int l=0; l *objects ) = 0; + /*! generic test case setup using iterator interface */ + bool initGenericTestCases(); + + /*! parse a boundary flag string */ + CellFlagType readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed); + /*! parse standard attributes */ + void parseStdAttrList(); + /*! initilize variables fom attribute list (should at least call std parse) */ + virtual void parseAttrList() = 0; + + virtual void step() = 0; + virtual void prepareVisualization() { /* by default off */ }; + + /*! particle handling */ + virtual int initParticles(ParticleTracer *partt) = 0; + virtual void advanceParticles(ParticleTracer *partt ) = 0; + /*! get surface object (NULL if no surface) */ + ntlGeometryObject* getSurfaceGeoObj() { return mpIso; } + + /*! debug object display */ + virtual vector getDebugObjects() { vector empty(0); return empty; } + +#if LBM_USE_GUI==1 + /*! show simulation info */ + virtual void debugDisplay(fluidDispSettings *) = 0; +#endif + + /*! init tree for certain geometry init */ + void initGeoTree(int id); + /*! destroy tree etc. when geometry init done */ + 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 */ + ntlVec3Gfx getGeoMaxInitialVelocity(); + + /* rt interface functions */ + unsigned int getIsoVertexCount() { return mpIso->getIsoVertexCount(); } + unsigned int getIsoIndexCount() { return mpIso->getIsoIndexCount(); } + char* getIsoVertexArray() { return mpIso->getIsoVertexArray(); } + unsigned int *getIsoIndexArray() { return mpIso->getIsoIndexArray(); } + void triangulateSurface() { mpIso->triangulate(); } + + /* access functions */ + + /*! return grid sizes */ + int getSizeX( void ) { return mSizex; } + int getSizeY( void ) { return mSizey; } + int getSizeZ( void ) { return mSizez; } + /*! return grid sizes */ + void setSizeX( int ns ) { mSizex = ns; } + void setSizeY( int ns ) { mSizey = ns; } + void setSizeZ( int ns ) { mSizez = ns; } + + /*! set attr list pointer */ + void setAttrList(AttributeList *set) { mpAttrs = set; } + /*! Returns the attribute list pointer */ + inline AttributeList *getAttributeList() { return mpAttrs; } + + /*! set parametrizer pointer */ + inline void setParametrizer(Parametrizer *set) { mpParam = set; } + /*! get parametrizer pointer */ + inline Parametrizer *getParametrizer() { return mpParam; } + + /*! set density gradient init from e.g. init test cases */ + inline void setInitDensityGradient(bool set) { mInitDensityGradient = set; } + + /*! access geometry start vector */ + inline void setGeoStart(ntlVec3Gfx set) { mvGeoStart = set; } + inline ntlVec3Gfx getGeoStart() const { return mvGeoStart; } + + /*! access geometry end vector */ + inline void setGeoEnd(ntlVec3Gfx set) { mvGeoEnd = set; } + inline ntlVec3Gfx getGeoEnd() const { return mvGeoEnd; } + + /*! access name string */ + inline void setName(string set) { mName = set; } + inline string getName() const { return mName; } + + /*! access string for node info debugging output */ + inline string getNodeInfoString() const { return mNodeInfoString; } + + /*! get panic flag */ + inline bool getPanic() { return mPanic; } + + //! set silent mode? + inline void setSilent(bool set){ mSilent = set; } + + + // cell iterator interface + + // cell id type + typedef CellIdentifierInterface* CellIdentifier; + + //! cell iteration methods + virtual CellIdentifierInterface* getFirstCell( ) = 0; + virtual void advanceCell( CellIdentifierInterface* ) = 0; + virtual bool noEndCell( CellIdentifierInterface* ) = 0; + //! clean up iteration, this should be called, when the iteration is not completely finished + virtual void deleteCellIterator( CellIdentifierInterface** ) = 0; + + //! find cell at a given position (returns NULL if not in domain) + virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos ) = 0; + + //! return node information + virtual int getCellSet ( CellIdentifierInterface* ) = 0; + virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* ) = 0; + virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* ) = 0; + virtual int getCellLevel ( CellIdentifierInterface* ) = 0; + virtual LbmFloat getCellDensity ( CellIdentifierInterface*,int ) = 0; + virtual LbmVec getCellVelocity ( CellIdentifierInterface*,int ) = 0; + /*! get equilibrium distribution functions */ + virtual LbmFloat getEquilDf ( int ) = 0; + /*! get number of distribution functions */ + virtual int getDfNum ( ) = 0; + /*! redundant cell functions */ + virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir) = 0; + virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set) = 0; + 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 + + //! add cell to mMarkedCells list + void addCellToMarkedList( CellIdentifierInterface *cid ); + //! marked cell iteration methods + CellIdentifierInterface* markedGetFirstCell( ); + CellIdentifierInterface* markedAdvanceCell(); + void markedClearList(); + +#ifndef LBMDIM + LBMDIM has to be defined +#endif +#if LBMDIM==2 + //! minimal and maximal z-coords (for 2D/3D loops) , this is always 0-1 for 2D + int getForZMinBnd() { return 0; }; + int getForZMaxBnd() { return 1; }; + int getForZMin1() { return 0; }; + int getForZMax1() { return 1; }; +#else // LBMDIM==2 + //! minimal and maximal z-coords (for 2D/3D loops) + int getForZMinBnd() { return 0; }; + int getForZMaxBnd() { return getSizeZ()-0; }; + int getForZMin1() { return 1; }; + int getForZMax1() { return getSizeZ()-1; }; +#endif // LBMDIM==2 + + + protected: + + /*! abort simulation on error... */ + bool mPanic; + + + /*! Size of the array in x,y,z direction */ + int mSizex, mSizey, mSizez; + + + /*! step counter */ + int mStepCnt; + + /*! mass change from one step to the next, for extreme cases fix globally */ + LbmFloat mFixMass; + + // deprecated param vars + /*! omega for lbm */ + LbmFloat mOmega; + /*! gravity strength in neg. z direction */ + LbmVec mGravity; + /*! Surface tension of the fluid */ + LbmFloat mSurfaceTension; + + + /* boundary inits */ + CellFlagType mBoundaryEast, mBoundaryWest, + mBoundaryNorth, mBoundarySouth, + mBoundaryTop, mBoundaryBottom; + + /*! initialization from config file done? */ + int mInitDone; + + /*! init density gradient? */ + bool mInitDensityGradient; + + /*! pointer to the attribute list */ + AttributeList *mpAttrs; + + /*! get parameters from this parametrize in finishInit */ + Parametrizer *mpParam; + + /*! number of particles lost so far */ + int mNumParticlesLost; + /*! number of particles lost so far */ + int mNumInvalidDfs; + /*! no of filled/emptied cells per time step */ + int mNumFilledCells, mNumEmptiedCells; + /*! counter number of used cells for performance */ + int mNumUsedCells; + /*! MLSUPS counter */ + LbmFloat mMLSUPS; + /*! debug - velocity output scaling factor */ + LbmFloat mDebugVelScale; + /*! string for node info debugging output */ + string mNodeInfoString; + + + /*! an own random stream */ + ntlRandomStream mRandom; + + + // geo init vars + // TODO deprecate SimulationObject vars + + /*! for display - start and end vectors for geometry */ + ntlVec3Gfx mvGeoStart, mvGeoEnd; + + /*! perform geometry init? */ + bool mPerformGeoInit; + /*! perform accurate geometry init? */ + bool mAccurateGeoinit; + + /*! name of this lbm object (for debug output) */ + string mName; + + //! Mcubes object for surface reconstruction + IsoSurface *mpIso; + /*! isolevel value for marching cubes surface reconstruction */ + LbmFloat mIsoValue; + + //! debug output? + bool mSilent; + + /*! geometry init id */ + int mGeoInitId; + /*! tree object for geomerty initialization */ + ntlTree *mpGiTree; + /*! object vector for geo init */ + vector *mpGiObjects; + /*! inside which objects? */ + vector mGiObjInside; + /*! inside which objects? */ + vector mGiObjDistance; + vector mGiObjSecondDist; + /*! remember globals */ + ntlRenderGlobals *mpGlob; + + // list for marked cells + vector mMarkedCells; + int mMarkedCellIndex; +}; + + +//! 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); + +#endif // LBMINTERFACE_H 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 - -- cgit v1.2.3