diff options
author | Nils Thuerey <nils@thuerey.de> | 2005-10-25 12:07:52 +0400 |
---|---|---|
committer | Nils Thuerey <nils@thuerey.de> | 2005-10-25 12:07:52 +0400 |
commit | a7e9a9d9c0e4154db41de6184eefcccfd6e4ed0a (patch) | |
tree | 145697e9d50c4cba0fee114091ea5706f25d6e28 /intern/elbeem | |
parent | edd998c042f3beaa8d26bc11c2e160a2751c3dbc (diff) |
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
Diffstat (limited to 'intern/elbeem')
31 files changed, 7658 insertions, 7753 deletions
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 <stdlib.h> 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 <algorithm> #include <stdio.h> + +// sirdude fix for solaris #if !defined(linux) && (defined (__sparc) || defined (__sparc__)) #include <ieeefp.h> #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 "<<PRINT_IJK<<" " - //<<" v0="<<value[0] <<" v1="<<value[1] <<" v2="<<value[2] <<" v3="<<value[3] - //<<" v4="<<value[4] <<" v5="<<value[5] <<" v6="<<value[6] <<" v7="<<value[7] ); // check intersections of isosurface with edges, and calculate cubie index cubeIndex = 0; @@ -235,34 +235,7 @@ void IsoSurface::triangulate( void ) const ntlVec3Gfx p2 = pos[ e2 ]; // scalar field pos 2 const float valp1 = value[ e1 ]; // scalar field val 1 const float valp2 = value[ e2 ]; // scalar field val 2 - //double mu; // interpolation value - //ntlVec3Gfx p; // new point - - // choose if point should be calculated by interpolation, - // or "Karolin" method - - //double deltaVal = ABS(valp2-valp1); - //if(deltaVal >-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; i<mLoopSubdivs; i++) { subdivide(); }// DEBUG test + if(mSmoothSurface>0.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="<<mSmoothSurface<<" sm="<<mSmoothNormals , 10 ); } @@ -444,6 +408,283 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) { * *****************************************************************************/ + +// Subdivide a mesh allways loop +/*void IsoSurface::subdivide() +{ + int i; + + mAdjacentFaces.clear(); + mAcrossEdge.clear(); + + //void TriMesh::need_adjacentfaces() + { + vector<int> numadjacentfaces(mPoints.size()); + //errMsg("SUBDIV ADJFA1", " "<<mPoints.size()<<" - "<<numadjacentfaces.size() ); + int i; + for (i = 0; i < (int)mIndices.size()/3; i++) { + numadjacentfaces[mIndices[i*3 + 0]]++; + numadjacentfaces[mIndices[i*3 + 1]]++; + numadjacentfaces[mIndices[i*3 + 2]]++; + } + + mAdjacentFaces.resize(mPoints.size()); + for (i = 0; i < (int)mPoints.size(); i++) + mAdjacentFaces[i].reserve(numadjacentfaces[i]); + + for (i = 0; i < (int)mIndices.size()/3; i++) { + for (int j = 0; j < 3; j++) + mAdjacentFaces[mIndices[i*3 + j]].push_back(i); + } + + } + + // Find the face across each edge from each other face (-1 on boundary) + // If topology is bad, not necessarily what one would expect... + //void TriMesh::need_across_edge() + { + mAcrossEdge.resize(mIndices.size(), -1); + + for (int i = 0; i < (int)mIndices.size()/3; i++) { + for (int j = 0; j < 3; j++) { + if (mAcrossEdge[i*3 + j] != -1) + continue; + int v1 = mIndices[i*3 + ((j+1)%3)]; + int v2 = mIndices[i*3 + ((j+2)%3)]; + const vector<int> &a1 = mAdjacentFaces[v1]; + const vector<int> &a2 = mAdjacentFaces[v2]; + for (int k1 = 0; k1 < (int)a1.size(); k1++) { + int other = a1[k1]; + if (other == i) + continue; + vector<int>::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<TriMesh::Face> newverts(nf, TriMesh::Face(-1,-1,-1)); + vector<int> 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<int> 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:"<<mPoints.size()<<" nf:"<<mIndices.size() ); +}*/ + + // Diffuse a vector field at 1 vertex, weighted by // a gaussian of width 1/sqrt(invsigma2) void IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt) diff --git a/intern/elbeem/intern/lbmdimensions.h b/intern/elbeem/intern/lbmdimensions.h deleted file mode 100644 index ca87e807500..00000000000 --- a/intern/elbeem/intern/lbmdimensions.h +++ /dev/null @@ -1,391 +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 Solver auxiliary classes - * - *****************************************************************************/ -#ifndef LBMHEADER_H - -/* LBM Files */ -#include "lbminterface.h" -#include <sstream> - - -//! 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 DQ> -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; l<DQ::cDfNum; l++) { - rho += df[l]; - ux += (DQ::dfDvecX[l]*df[l]); - uy += (DQ::dfDvecY[l]*df[l]); - uz += (DQ::dfDvecZ[l]*df[l]); - } - for(int l=0; l<DQ::cDfNum; l++) { - //LbmFloat tmp = (ux*DQ::dfDvecX[l]+uy*DQ::dfDvecY[l]+uz*DQ::dfDvecZ[l]); - df[l] = (1.0-omega ) * df[l] + omega * ( getCollideEq(l,rho,ux,uy,uz) ); - } - - mux = ux; - muy = uy; - muz = uz; - outrho = rho; - };*/ - - // LES functions - inline LbmFloat getLesNoneqTensorCoeff( - LbmFloat df[], - LbmFloat feq[] ) { - LbmFloat Qo = 0.0; - for(int m=0; m< ((DQ::cDimension*DQ::cDimension)-DQ::cDimension)/2 ; m++) { - LbmFloat qadd = 0.0; - for(int l=1; l<DQ::cDfNum; l++) { - if(DQ::lesCoeffOffdiag[m][l]==0.0) continue; - qadd += DQ::lesCoeffOffdiag[m][l]*(df[l]-feq[l]); - } - Qo += (qadd*qadd); - } - Qo *= 2.0; // off diag twice - for(int m=0; m<DQ::cDimension; m++) { - LbmFloat qadd = 0.0; - for(int l=1; l<DQ::cDfNum; l++) { - if(DQ::lesCoeffDiag[m][l]==0.0) continue; - qadd += DQ::lesCoeffDiag[m][l]*(df[l]-feq[l]); - } - Qo += (qadd*qadd); - } - Qo = sqrt(Qo); - return Qo; - } - inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) { - const LbmFloat tau = 1.0/omega; - const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0); - const LbmFloat C = csmago; - const LbmFloat Csqr = C*C; - LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr); - return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) ); - } - - // "normal" collision - inline void collideArrays(LbmFloat df[], - LbmFloat &outrho, // out only! - // velocity modifiers (returns actual velocity!) - LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, - LbmFloat omega, LbmFloat csmago, LbmFloat *newOmegaRet = NULL - ) { - LbmFloat rho=df[0]; - LbmFloat ux = mux; - LbmFloat uy = muy; - LbmFloat uz = muz; - for(int l=1; l<DQ::cDfNum; l++) { - rho += df[l]; - ux += (DQ::dfDvecX[l]*df[l]); - uy += (DQ::dfDvecY[l]*df[l]); - uz += (DQ::dfDvecZ[l]*df[l]); - } - LbmFloat feq[19]; - for(int l=0; l<DQ::cDfNum; l++) { - feq[l] = getCollideEq(l,rho,ux,uy,uz); - } - - LbmFloat omegaNew; - if(csmago>0.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<DQ::cDfNum; l++) { - df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l]; - } - - mux = ux; - muy = uy; - muz = uz; - outrho = rho; - }; - -}; // LBGK - -#ifdef LBMMODEL_DEFINED -// force compiler error! -ERROR - Dont include several LBM models at once... -#endif -#define LBMMODEL_DEFINED 1 - - -typedef LbmModelLBGK< LbmD2Q9 > 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 <stdio.h> - -#if !defined(linux) && (defined (__sparc) || defined (__sparc__)) -#include <ieeefp.h> - #ifndef expf - #define expf exp - #endif -#endif - -#if PARALLEL==1 -#include <omp.h> -#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<typename D> -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"<<x<<",j"<<y; - if(D::cDimension>2) ret<<",k"<<z; - ret <<" }"; - return ret.str(); - } - - virtual bool equal(CellIdentifierInterface* other) { - //UniformFsgrCellIdentifier<D> *cid = dynamic_cast<UniformFsgrCellIdentifier<D> *>( other ); - UniformFsgrCellIdentifier<D> *cid = (UniformFsgrCellIdentifier<D> *)( 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 D> -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<ntlGeometryObject*>* /*objects*/ ); - -#if LBM_USE_GUI==1 - //! show simulation info (implement SimulationObject pure virtual func) - virtual void debugDisplay(fluidDispSettings *set); -#endif - - - // implement CellIterator<UniformFsgrCellIdentifier> interface - typedef UniformFsgrCellIdentifier<typename D::LbmCellContents> 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<ntlGeometryObject*> 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<LbmPoint> mListEmpty; - //! list of the cells to make fluid at the end of the step - vector<LbmPoint> mListFull; - //! list of new interface cells to init - vector<LbmPoint> 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<LbmVec> 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: "<<D::mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \ - debugMarkCellCall((lev),(x),(y),(z)); -#else // FSGR_STRICT_DEBUG==1 -#define debugMarkCell(lev,x,y,z) \ - debugMarkCellCall((lev),(x),(y),(z)); -#endif // FSGR_STRICT_DEBUG==1 - - -// flag array defines ----------------------------------------------------------------------------------------------- - -// lbm testsolver get index define -#define _LBMGI(level, ii,ij,ik, is) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) - -//! flag array acces macro -#define _RFLAG(level,xx,yy,zz,set) mLevel[level].mprsFlags[set][ LBMGI((level),(xx),(yy),(zz),(set)) ] -#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set) ] -#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set) ] - -// array data layouts -// standard array layout ----------------------------------------------------------------------------------------------- -#define ALSTRING "Standard Array Layout" -//#define _LBMQI(level, ii,ij,ik, is, lunused) ( ((is)*mLevel[level].lOffsz) + (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) -#define _LBMQI(level, ii,ij,ik, is, lunused) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) -#define _QCELL(level,xx,yy,zz,set,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx),(yy),(zz),(set), l)*dTotalNum +(l)]) -#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set, l)*dTotalNum +(l)]) -#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set, l)*dTotalNum +(l)]) - -#define QCELLSTEP dTotalNum -#define _RACPNT(level, ii,ij,ik, is ) &QCELL(level,ii,ij,ik,is,0) -#define _RAC(s,l) (s)[(l)] - -// 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) - - - -#if FSGR_STRICT_DEBUG==1 - -#define LBMGI(level,ii,ij,ik, is) debLBMGI(level,ii,ij,ik, is) -#define RFLAG(level,xx,yy,zz,set) debRFLAG(level,xx,yy,zz,set) -#define RFLAG_NB(level,xx,yy,zz,set, dir) debRFLAG_NB(level,xx,yy,zz,set, dir) -#define RFLAG_NBINV(level,xx,yy,zz,set, dir) debRFLAG_NBINV(level,xx,yy,zz,set, dir) - -#define LBMQI(level,ii,ij,ik, is, l) debLBMQI(level,ii,ij,ik, is, l) -#define QCELL(level,xx,yy,zz,set,l) debQCELL(level,xx,yy,zz,set,l) -#define QCELL_NB(level,xx,yy,zz,set, dir,l) debQCELL_NB(level,xx,yy,zz,set, dir,l) -#define QCELL_NBINV(level,xx,yy,zz,set, dir,l) debQCELL_NBINV(level,xx,yy,zz,set, dir,l) -#define RACPNT(level, ii,ij,ik, is ) debRACPNT(level, ii,ij,ik, is ) -#define RAC(s,l) debRAC(s,l) - -#else // FSGR_STRICT_DEBUG==1 - -#define LBMGI(level,ii,ij,ik, is) _LBMGI(level,ii,ij,ik, is) -#define RFLAG(level,xx,yy,zz,set) _RFLAG(level,xx,yy,zz,set) -#define RFLAG_NB(level,xx,yy,zz,set, dir) _RFLAG_NB(level,xx,yy,zz,set, dir) -#define RFLAG_NBINV(level,xx,yy,zz,set, dir) _RFLAG_NBINV(level,xx,yy,zz,set, dir) - -#define LBMQI(level,ii,ij,ik, is, l) _LBMQI(level,ii,ij,ik, is, l) -#define QCELL(level,xx,yy,zz,set,l) _QCELL(level,xx,yy,zz,set,l) -#define QCELL_NB(level,xx,yy,zz,set, dir,l) _QCELL_NB(level,xx,yy,zz,set, dir, l) -#define QCELL_NBINV(level,xx,yy,zz,set, dir,l) _QCELL_NBINV(level,xx,yy,zz,set, dir,l) -#define RACPNT(level, ii,ij,ik, is ) _RACPNT(level, ii,ij,ik, is ) -#define RAC(s,l) _RAC(s,l) - -#endif // FSGR_STRICT_DEBUG==1 - -// general defines ----------------------------------------------------------------------------------------------- - -#define TESTFLAG(flag, compflag) ((flag & compflag)==compflag) - -#if LBMDIM==2 -#define dC 0 -#define dN 1 -#define dS 2 -#define dE 3 -#define dW 4 -#define dNE 5 -#define dNW 6 -#define dSE 7 -#define dSW 8 -#define LBM_DFNUM 9 -#else -// direction indices -#define dC 0 -#define dN 1 -#define dS 2 -#define dE 3 -#define dW 4 -#define dT 5 -#define dB 6 -#define dNE 7 -#define dNW 8 -#define dSE 9 -#define dSW 10 -#define dNT 11 -#define dNB 12 -#define dST 13 -#define dSB 14 -#define dET 15 -#define dEB 16 -#define dWT 17 -#define dWB 18 -#define LBM_DFNUM 19 -#endif -//? #define dWB 18 - -// default init for dFlux values -#define FLUX_INIT 0.5f * (float)(D::cDfNum) - -// only for non DF dir handling! -#define dNET 19 -#define dNWT 20 -#define dSET 21 -#define dSWT 22 -#define dNEB 23 -#define dNWB 24 -#define dSEB 25 -#define dSWB 26 - -//! fill value for boundary cells -#define BND_FILL 0.0 - -#define DFL1 (1.0/ 3.0) -#define DFL2 (1.0/18.0) -#define DFL3 (1.0/36.0) - -#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 - - -// complete default stream&collide, 2d/3d -/* read distribution funtions of adjacent cells = sweep step */ -#if OPT3D==false - -#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"<<l<<" value:"<<m[l]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\ - " nfc"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr)<<" nfo"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setOther) ); \ - MARKCELLCHECK; \ - } -#define COLLCHECK \ - if( (rho>2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\ - errMsg("COLLCHECK","Invalid collision values r:"<<rho<<" u:"PRINT_VEC(ux,uy,uz)<<" at? "<<PRINT_IJK ); \ - MARKCELLCHECK; \ - } -#else -#define STREAMCHECK(ni,nj,nk,nl) -#define COLLCHECK -#endif - -// careful ux,uy,uz need to be inited before! - -#define DEFAULT_STREAM \ - m[dC] = RAC(ccel,dC); \ - FORDF1 { \ - if(NBFLAG( D::dfInv[l] )&CFBnd) { \ - m[l] = RAC(ccel, D::dfInv[l] ); \ - STREAMCHECK(i,j,k, D::dfInv[l]); \ - } else { \ - m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ - } \ - } - -// careful ux,uy,uz need to be inited before! -#define DEFAULT_COLLIDE \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet ); \ - CSMOMEGA_STATS(lev,mDebugOmegaRet); \ - FORDF0 { RAC(tcel,l) = m[l]; } \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLLCHECK; -#define OPTIMIZED_STREAMCOLLIDE \ - m[0] = RAC(ccel,0); \ - FORDF1 { /* df0 is set later on... */ \ - /* FIXME CHECK INV ? */\ - if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ - } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ - } \ - rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ - CSMOMEGA_STATS(lev,mDebugOmegaRet); \ - FORDF0 { RAC(tcel,l) = m[l]; } \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLLCHECK; - -#else // 3D, opt OPT3D==true - -#define DEFAULT_STREAM \ - m[dC] = RAC(ccel,dC); \ - /* explicit streaming */ \ - if((!nbored & CFBnd)) { \ - /* no boundary near?, no real speed diff.? */ \ - m[dN ] = CSRC_N ; m[dS ] = CSRC_S ; \ - m[dE ] = CSRC_E ; m[dW ] = CSRC_W ; \ - m[dT ] = CSRC_T ; m[dB ] = CSRC_B ; \ - m[dNE] = CSRC_NE; m[dNW] = CSRC_NW; m[dSE] = CSRC_SE; m[dSW] = CSRC_SW; \ - m[dNT] = CSRC_NT; m[dNB] = CSRC_NB; m[dST] = CSRC_ST; m[dSB] = CSRC_SB; \ - m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \ - } else { \ - /* explicit streaming */ \ - if(NBFLAG(dS )&CFBnd) { m[dN ] = RAC(ccel,dS ); } else { m[dN ] = CSRC_N ; } \ - if(NBFLAG(dN )&CFBnd) { m[dS ] = RAC(ccel,dN ); } else { m[dS ] = CSRC_S ; } \ - if(NBFLAG(dW )&CFBnd) { m[dE ] = RAC(ccel,dW ); } else { m[dE ] = CSRC_E ; } \ - if(NBFLAG(dE )&CFBnd) { m[dW ] = RAC(ccel,dE ); } else { m[dW ] = CSRC_W ; } \ - if(NBFLAG(dB )&CFBnd) { m[dT ] = RAC(ccel,dB ); } else { m[dT ] = CSRC_T ; } \ - if(NBFLAG(dT )&CFBnd) { m[dB ] = RAC(ccel,dT ); } else { m[dB ] = CSRC_B ; } \ - \ - if(NBFLAG(dSW)&CFBnd) { m[dNE] = RAC(ccel,dSW); } else { m[dNE] = CSRC_NE; } \ - if(NBFLAG(dSE)&CFBnd) { m[dNW] = RAC(ccel,dSE); } else { m[dNW] = CSRC_NW; } \ - if(NBFLAG(dNW)&CFBnd) { m[dSE] = RAC(ccel,dNW); } else { m[dSE] = CSRC_SE; } \ - if(NBFLAG(dNE)&CFBnd) { m[dSW] = RAC(ccel,dNE); } else { m[dSW] = CSRC_SW; } \ - if(NBFLAG(dSB)&CFBnd) { m[dNT] = RAC(ccel,dSB); } else { m[dNT] = CSRC_NT; } \ - if(NBFLAG(dST)&CFBnd) { m[dNB] = RAC(ccel,dST); } else { m[dNB] = CSRC_NB; } \ - if(NBFLAG(dNB)&CFBnd) { m[dST] = RAC(ccel,dNB); } else { m[dST] = CSRC_ST; } \ - if(NBFLAG(dNT)&CFBnd) { m[dSB] = RAC(ccel,dNT); } else { m[dSB] = CSRC_SB; } \ - if(NBFLAG(dWB)&CFBnd) { m[dET] = RAC(ccel,dWB); } else { m[dET] = CSRC_ET; } \ - if(NBFLAG(dWT)&CFBnd) { m[dEB] = RAC(ccel,dWT); } else { m[dEB] = CSRC_EB; } \ - if(NBFLAG(dEB)&CFBnd) { m[dWT] = RAC(ccel,dEB); } else { m[dWT] = CSRC_WT; } \ - if(NBFLAG(dET)&CFBnd) { m[dWB] = RAC(ccel,dET); } else { m[dWB] = CSRC_WB; } \ - } - - - -#define COLL_CALCULATE_DFEQ(dstarray) \ - dstarray[dN ] = EQN ; dstarray[dS ] = EQS ; \ - dstarray[dE ] = EQE ; dstarray[dW ] = EQW ; \ - dstarray[dT ] = EQT ; dstarray[dB ] = EQB ; \ - dstarray[dNE] = EQNE; dstarray[dNW] = EQNW; dstarray[dSE] = EQSE; dstarray[dSW] = EQSW; \ - dstarray[dNT] = EQNT; dstarray[dNB] = EQNB; dstarray[dST] = EQST; dstarray[dSB] = EQSB; \ - dstarray[dET] = EQET; dstarray[dEB] = EQEB; dstarray[dWT] = EQWT; dstarray[dWB] = EQWB; -#define COLL_CALCULATE_NONEQTENSOR(csolev, srcArray ) \ - lcsmqadd = (srcArray##NE - lcsmeq[ dNE ]); \ - lcsmqadd -= (srcArray##NW - lcsmeq[ dNW ]); \ - lcsmqadd -= (srcArray##SE - lcsmeq[ dSE ]); \ - lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ - lcsmqo = (lcsmqadd* lcsmqadd); \ - lcsmqadd = (srcArray##ET - lcsmeq[ dET ]); \ - lcsmqadd -= (srcArray##EB - lcsmeq[ dEB ]); \ - lcsmqadd -= (srcArray##WT - lcsmeq[ dWT ]); \ - lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ - lcsmqo += (lcsmqadd* lcsmqadd); \ - lcsmqadd = (srcArray##NT - lcsmeq[ dNT ]); \ - lcsmqadd -= (srcArray##NB - lcsmeq[ dNB ]); \ - lcsmqadd -= (srcArray##ST - lcsmeq[ dST ]); \ - lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ - lcsmqo += (lcsmqadd* lcsmqadd); \ - lcsmqo *= 2.0; \ - lcsmqadd = (srcArray##E - lcsmeq[ dE ]); \ - lcsmqadd += (srcArray##W - lcsmeq[ dW ]); \ - lcsmqadd += (srcArray##NE - lcsmeq[ dNE ]); \ - lcsmqadd += (srcArray##NW - lcsmeq[ dNW ]); \ - lcsmqadd += (srcArray##SE - lcsmeq[ dSE ]); \ - lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ - lcsmqadd += (srcArray##ET - lcsmeq[ dET ]); \ - lcsmqadd += (srcArray##EB - lcsmeq[ dEB ]); \ - lcsmqadd += (srcArray##WT - lcsmeq[ dWT ]); \ - lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ - lcsmqo += (lcsmqadd* lcsmqadd); \ - lcsmqadd = (srcArray##N - lcsmeq[ dN ]); \ - lcsmqadd += (srcArray##S - lcsmeq[ dS ]); \ - lcsmqadd += (srcArray##NE - lcsmeq[ dNE ]); \ - lcsmqadd += (srcArray##NW - lcsmeq[ dNW ]); \ - lcsmqadd += (srcArray##SE - lcsmeq[ dSE ]); \ - lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ - lcsmqadd += (srcArray##NT - lcsmeq[ dNT ]); \ - lcsmqadd += (srcArray##NB - lcsmeq[ dNB ]); \ - lcsmqadd += (srcArray##ST - lcsmeq[ dST ]); \ - lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ - lcsmqo += (lcsmqadd* lcsmqadd); \ - lcsmqadd = (srcArray##T - lcsmeq[ dT ]); \ - lcsmqadd += (srcArray##B - lcsmeq[ dB ]); \ - lcsmqadd += (srcArray##NT - lcsmeq[ dNT ]); \ - lcsmqadd += (srcArray##NB - lcsmeq[ dNB ]); \ - lcsmqadd += (srcArray##ST - lcsmeq[ dST ]); \ - lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ - lcsmqadd += (srcArray##ET - lcsmeq[ dET ]); \ - lcsmqadd += (srcArray##EB - lcsmeq[ dEB ]); \ - lcsmqadd += (srcArray##WT - lcsmeq[ dWT ]); \ - lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ - lcsmqo += (lcsmqadd* lcsmqadd); \ - lcsmqo = sqrt(lcsmqo); /* FIXME check effect of sqrt*/ \ - -// COLL_CALCULATE_CSMOMEGAVAL(csolev, lcsmomega); - -// careful - need lcsmqo -#define COLL_CALCULATE_CSMOMEGAVAL(csolev, dstomega ) \ - dstomega = 1.0/\ - ( 3.0*( mLevel[(csolev)].lcnu+mLevel[(csolev)].lcsmago_sqr*(\ - -mLevel[(csolev)].lcnu + sqrt( mLevel[(csolev)].lcnu*mLevel[(csolev)].lcnu + 18.0*mLevel[(csolev)].lcsmago_sqr* lcsmqo ) \ - / (6.0*mLevel[(csolev)].lcsmago_sqr)) \ - ) +0.5 ); - -#define DEFAULT_COLLIDE_LES \ - rho = + MSRC_C + MSRC_N \ - + MSRC_S + MSRC_E \ - + MSRC_W + MSRC_T \ - + MSRC_B + MSRC_NE \ - + MSRC_NW + MSRC_SE \ - + MSRC_SW + MSRC_NT \ - + MSRC_NB + MSRC_ST \ - + MSRC_SB + MSRC_ET \ - + MSRC_EB + MSRC_WT \ - + MSRC_WB; \ - \ - ux += MSRC_E - MSRC_W \ - + MSRC_NE - MSRC_NW \ - + MSRC_SE - MSRC_SW \ - + MSRC_ET + MSRC_EB \ - - MSRC_WT - MSRC_WB ; \ - \ - uy += MSRC_N - MSRC_S \ - + MSRC_NE + MSRC_NW \ - - MSRC_SE - MSRC_SW \ - + MSRC_NT + MSRC_NB \ - - MSRC_ST - MSRC_SB ; \ - \ - uz += MSRC_T - MSRC_B \ - + MSRC_NT - MSRC_NB \ - + MSRC_ST - MSRC_SB \ - + MSRC_ET - MSRC_EB \ - + MSRC_WT - MSRC_WB ; \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev, MSRC_)\ - COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ - CSMOMEGA_STATS(lev,lcsmomega); \ - \ - RAC(tcel,dC ) = (1.0-lcsmomega)*MSRC_C + lcsmomega*EQC ; \ - \ - RAC(tcel,dN ) = (1.0-lcsmomega)*MSRC_N + lcsmomega*lcsmeq[ dN ]; \ - RAC(tcel,dS ) = (1.0-lcsmomega)*MSRC_S + lcsmomega*lcsmeq[ dS ]; \ - RAC(tcel,dE ) = (1.0-lcsmomega)*MSRC_E + lcsmomega*lcsmeq[ dE ]; \ - RAC(tcel,dW ) = (1.0-lcsmomega)*MSRC_W + lcsmomega*lcsmeq[ dW ]; \ - RAC(tcel,dT ) = (1.0-lcsmomega)*MSRC_T + lcsmomega*lcsmeq[ dT ]; \ - RAC(tcel,dB ) = (1.0-lcsmomega)*MSRC_B + lcsmomega*lcsmeq[ dB ]; \ - \ - RAC(tcel,dNE) = (1.0-lcsmomega)*MSRC_NE + lcsmomega*lcsmeq[ dNE]; \ - RAC(tcel,dNW) = (1.0-lcsmomega)*MSRC_NW + lcsmomega*lcsmeq[ dNW]; \ - RAC(tcel,dSE) = (1.0-lcsmomega)*MSRC_SE + lcsmomega*lcsmeq[ dSE]; \ - RAC(tcel,dSW) = (1.0-lcsmomega)*MSRC_SW + lcsmomega*lcsmeq[ dSW]; \ - RAC(tcel,dNT) = (1.0-lcsmomega)*MSRC_NT + lcsmomega*lcsmeq[ dNT]; \ - RAC(tcel,dNB) = (1.0-lcsmomega)*MSRC_NB + lcsmomega*lcsmeq[ dNB]; \ - RAC(tcel,dST) = (1.0-lcsmomega)*MSRC_ST + lcsmomega*lcsmeq[ dST]; \ - RAC(tcel,dSB) = (1.0-lcsmomega)*MSRC_SB + lcsmomega*lcsmeq[ dSB]; \ - RAC(tcel,dET) = (1.0-lcsmomega)*MSRC_ET + lcsmomega*lcsmeq[ dET]; \ - RAC(tcel,dEB) = (1.0-lcsmomega)*MSRC_EB + lcsmomega*lcsmeq[ dEB]; \ - RAC(tcel,dWT) = (1.0-lcsmomega)*MSRC_WT + lcsmomega*lcsmeq[ dWT]; \ - RAC(tcel,dWB) = (1.0-lcsmomega)*MSRC_WB + lcsmomega*lcsmeq[ dWB]; - -#define DEFAULT_COLLIDE_NOLES \ - rho = + MSRC_C + MSRC_N \ - + MSRC_S + MSRC_E \ - + MSRC_W + MSRC_T \ - + MSRC_B + MSRC_NE \ - + MSRC_NW + MSRC_SE \ - + MSRC_SW + MSRC_NT \ - + MSRC_NB + MSRC_ST \ - + MSRC_SB + MSRC_ET \ - + MSRC_EB + MSRC_WT \ - + MSRC_WB; \ - \ - ux += MSRC_E - MSRC_W \ - + MSRC_NE - MSRC_NW \ - + MSRC_SE - MSRC_SW \ - + MSRC_ET + MSRC_EB \ - - MSRC_WT - MSRC_WB ; \ - \ - uy += MSRC_N - MSRC_S \ - + MSRC_NE + MSRC_NW \ - - MSRC_SE - MSRC_SW \ - + MSRC_NT + MSRC_NB \ - - MSRC_ST - MSRC_SB ; \ - \ - uz += MSRC_T - MSRC_B \ - + MSRC_NT - MSRC_NB \ - + MSRC_ST - MSRC_SB \ - + MSRC_ET - MSRC_EB \ - + MSRC_WT - MSRC_WB ; \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - \ - RAC(tcel,dC ) = (1.0-OMEGA(lev))*MSRC_C + OMEGA(lev)*EQC ; \ - \ - RAC(tcel,dN ) = (1.0-OMEGA(lev))*MSRC_N + OMEGA(lev)*EQN ; \ - RAC(tcel,dS ) = (1.0-OMEGA(lev))*MSRC_S + OMEGA(lev)*EQS ; \ - RAC(tcel,dE ) = (1.0-OMEGA(lev))*MSRC_E + OMEGA(lev)*EQE ; \ - RAC(tcel,dW ) = (1.0-OMEGA(lev))*MSRC_W + OMEGA(lev)*EQW ; \ - RAC(tcel,dT ) = (1.0-OMEGA(lev))*MSRC_T + OMEGA(lev)*EQT ; \ - RAC(tcel,dB ) = (1.0-OMEGA(lev))*MSRC_B + OMEGA(lev)*EQB ; \ - \ - RAC(tcel,dNE) = (1.0-OMEGA(lev))*MSRC_NE + OMEGA(lev)*EQNE; \ - RAC(tcel,dNW) = (1.0-OMEGA(lev))*MSRC_NW + OMEGA(lev)*EQNW; \ - RAC(tcel,dSE) = (1.0-OMEGA(lev))*MSRC_SE + OMEGA(lev)*EQSE; \ - RAC(tcel,dSW) = (1.0-OMEGA(lev))*MSRC_SW + OMEGA(lev)*EQSW; \ - RAC(tcel,dNT) = (1.0-OMEGA(lev))*MSRC_NT + OMEGA(lev)*EQNT; \ - RAC(tcel,dNB) = (1.0-OMEGA(lev))*MSRC_NB + OMEGA(lev)*EQNB; \ - RAC(tcel,dST) = (1.0-OMEGA(lev))*MSRC_ST + OMEGA(lev)*EQST; \ - RAC(tcel,dSB) = (1.0-OMEGA(lev))*MSRC_SB + OMEGA(lev)*EQSB; \ - RAC(tcel,dET) = (1.0-OMEGA(lev))*MSRC_ET + OMEGA(lev)*EQET; \ - RAC(tcel,dEB) = (1.0-OMEGA(lev))*MSRC_EB + OMEGA(lev)*EQEB; \ - RAC(tcel,dWT) = (1.0-OMEGA(lev))*MSRC_WT + OMEGA(lev)*EQWT; \ - RAC(tcel,dWB) = (1.0-OMEGA(lev))*MSRC_WB + OMEGA(lev)*EQWB; - - - -#define OPTIMIZED_STREAMCOLLIDE_LES \ - /* only surrounded by fluid cells...!, so safe streaming here... */ \ - m[dC ] = CSRC_C ; \ - m[dN ] = CSRC_N ; m[dS ] = CSRC_S ; \ - m[dE ] = CSRC_E ; m[dW ] = CSRC_W ; \ - m[dT ] = CSRC_T ; m[dB ] = CSRC_B ; \ - m[dNE] = CSRC_NE; m[dNW] = CSRC_NW; m[dSE] = CSRC_SE; m[dSW] = CSRC_SW; \ - m[dNT] = CSRC_NT; m[dNB] = CSRC_NB; m[dST] = CSRC_ST; m[dSB] = CSRC_SB; \ - m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \ - \ - rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T \ - + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT \ - + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; \ - ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW \ - + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB + mLevel[lev].gravity[0]; \ - uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW \ - + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB + mLevel[lev].gravity[1]; \ - uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB \ - + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB + mLevel[lev].gravity[2]; \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev, MSRC_) \ - COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ - CSMOMEGA_STATS(lev,lcsmomega); \ - \ - RAC(tcel,dC ) = (1.0-lcsmomega)*MSRC_C + lcsmomega*EQC ; \ - RAC(tcel,dN ) = (1.0-lcsmomega)*MSRC_N + lcsmomega*lcsmeq[ dN ]; \ - RAC(tcel,dS ) = (1.0-lcsmomega)*MSRC_S + lcsmomega*lcsmeq[ dS ]; \ - RAC(tcel,dE ) = (1.0-lcsmomega)*MSRC_E + lcsmomega*lcsmeq[ dE ]; \ - RAC(tcel,dW ) = (1.0-lcsmomega)*MSRC_W + lcsmomega*lcsmeq[ dW ]; \ - RAC(tcel,dT ) = (1.0-lcsmomega)*MSRC_T + lcsmomega*lcsmeq[ dT ]; \ - RAC(tcel,dB ) = (1.0-lcsmomega)*MSRC_B + lcsmomega*lcsmeq[ dB ]; \ - \ - RAC(tcel,dNE) = (1.0-lcsmomega)*MSRC_NE + lcsmomega*lcsmeq[ dNE]; \ - RAC(tcel,dNW) = (1.0-lcsmomega)*MSRC_NW + lcsmomega*lcsmeq[ dNW]; \ - RAC(tcel,dSE) = (1.0-lcsmomega)*MSRC_SE + lcsmomega*lcsmeq[ dSE]; \ - RAC(tcel,dSW) = (1.0-lcsmomega)*MSRC_SW + lcsmomega*lcsmeq[ dSW]; \ - \ - RAC(tcel,dNT) = (1.0-lcsmomega)*MSRC_NT + lcsmomega*lcsmeq[ dNT]; \ - RAC(tcel,dNB) = (1.0-lcsmomega)*MSRC_NB + lcsmomega*lcsmeq[ dNB]; \ - RAC(tcel,dST) = (1.0-lcsmomega)*MSRC_ST + lcsmomega*lcsmeq[ dST]; \ - RAC(tcel,dSB) = (1.0-lcsmomega)*MSRC_SB + lcsmomega*lcsmeq[ dSB]; \ - \ - RAC(tcel,dET) = (1.0-lcsmomega)*MSRC_ET + lcsmomega*lcsmeq[ dET]; \ - RAC(tcel,dEB) = (1.0-lcsmomega)*MSRC_EB + lcsmomega*lcsmeq[ dEB]; \ - RAC(tcel,dWT) = (1.0-lcsmomega)*MSRC_WT + lcsmomega*lcsmeq[ dWT]; \ - RAC(tcel,dWB) = (1.0-lcsmomega)*MSRC_WB + lcsmomega*lcsmeq[ dWB]; \ - -#define OPTIMIZED_STREAMCOLLIDE_UNUSED \ - /* only surrounded by fluid cells...!, so safe streaming here... */ \ - rho = CSRC_C + CSRC_N + CSRC_S + CSRC_E + CSRC_W + CSRC_T \ - + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ - + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ - ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ - + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ - uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ - + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ - uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ - + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev, CSRC_) \ - COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ - \ - RAC(tcel,dC ) = (1.0-lcsmomega)*CSRC_C + lcsmomega*EQC ; \ - RAC(tcel,dN ) = (1.0-lcsmomega)*CSRC_N + lcsmomega*lcsmeq[ dN ]; \ - RAC(tcel,dS ) = (1.0-lcsmomega)*CSRC_S + lcsmomega*lcsmeq[ dS ]; \ - RAC(tcel,dE ) = (1.0-lcsmomega)*CSRC_E + lcsmomega*lcsmeq[ dE ]; \ - RAC(tcel,dW ) = (1.0-lcsmomega)*CSRC_W + lcsmomega*lcsmeq[ dW ]; \ - RAC(tcel,dT ) = (1.0-lcsmomega)*CSRC_T + lcsmomega*lcsmeq[ dT ]; \ - RAC(tcel,dB ) = (1.0-lcsmomega)*CSRC_B + lcsmomega*lcsmeq[ dB ]; \ - \ - RAC(tcel,dNE) = (1.0-lcsmomega)*CSRC_NE + lcsmomega*lcsmeq[ dNE]; \ - RAC(tcel,dNW) = (1.0-lcsmomega)*CSRC_NW + lcsmomega*lcsmeq[ dNW]; \ - RAC(tcel,dSE) = (1.0-lcsmomega)*CSRC_SE + lcsmomega*lcsmeq[ dSE]; \ - RAC(tcel,dSW) = (1.0-lcsmomega)*CSRC_SW + lcsmomega*lcsmeq[ dSW]; \ - \ - RAC(tcel,dNT) = (1.0-lcsmomega)*CSRC_NT + lcsmomega*lcsmeq[ dNT]; \ - RAC(tcel,dNB) = (1.0-lcsmomega)*CSRC_NB + lcsmomega*lcsmeq[ dNB]; \ - RAC(tcel,dST) = (1.0-lcsmomega)*CSRC_ST + lcsmomega*lcsmeq[ dST]; \ - RAC(tcel,dSB) = (1.0-lcsmomega)*CSRC_SB + lcsmomega*lcsmeq[ dSB]; \ - \ - RAC(tcel,dET) = (1.0-lcsmomega)*CSRC_ET + lcsmomega*lcsmeq[ dET]; \ - RAC(tcel,dEB) = (1.0-lcsmomega)*CSRC_EB + lcsmomega*lcsmeq[ dEB]; \ - RAC(tcel,dWT) = (1.0-lcsmomega)*CSRC_WT + lcsmomega*lcsmeq[ dWT]; \ - RAC(tcel,dWB) = (1.0-lcsmomega)*CSRC_WB + lcsmomega*lcsmeq[ dWB]; \ - -#define OPTIMIZED_STREAMCOLLIDE_NOLES \ - /* only surrounded by fluid cells...!, so safe streaming here... */ \ - rho = CSRC_C + CSRC_N + CSRC_S + CSRC_E + CSRC_W + CSRC_T \ - + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ - + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ - ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ - + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ - uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ - + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ - uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ - + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - RAC(tcel,dC ) = (1.0-OMEGA(lev))*CSRC_C + OMEGA(lev)*EQC ; \ - RAC(tcel,dN ) = (1.0-OMEGA(lev))*CSRC_N + OMEGA(lev)*EQN ; \ - RAC(tcel,dS ) = (1.0-OMEGA(lev))*CSRC_S + OMEGA(lev)*EQS ; \ - RAC(tcel,dE ) = (1.0-OMEGA(lev))*CSRC_E + OMEGA(lev)*EQE ; \ - RAC(tcel,dW ) = (1.0-OMEGA(lev))*CSRC_W + OMEGA(lev)*EQW ; \ - RAC(tcel,dT ) = (1.0-OMEGA(lev))*CSRC_T + OMEGA(lev)*EQT ; \ - RAC(tcel,dB ) = (1.0-OMEGA(lev))*CSRC_B + OMEGA(lev)*EQB ; \ - \ - RAC(tcel,dNE) = (1.0-OMEGA(lev))*CSRC_NE + OMEGA(lev)*EQNE; \ - RAC(tcel,dNW) = (1.0-OMEGA(lev))*CSRC_NW + OMEGA(lev)*EQNW; \ - RAC(tcel,dSE) = (1.0-OMEGA(lev))*CSRC_SE + OMEGA(lev)*EQSE; \ - RAC(tcel,dSW) = (1.0-OMEGA(lev))*CSRC_SW + OMEGA(lev)*EQSW; \ - \ - RAC(tcel,dNT) = (1.0-OMEGA(lev))*CSRC_NT + OMEGA(lev)*EQNT; \ - RAC(tcel,dNB) = (1.0-OMEGA(lev))*CSRC_NB + OMEGA(lev)*EQNB; \ - RAC(tcel,dST) = (1.0-OMEGA(lev))*CSRC_ST + OMEGA(lev)*EQST; \ - RAC(tcel,dSB) = (1.0-OMEGA(lev))*CSRC_SB + OMEGA(lev)*EQSB; \ - \ - RAC(tcel,dET) = (1.0-OMEGA(lev))*CSRC_ET + OMEGA(lev)*EQET; \ - RAC(tcel,dEB) = (1.0-OMEGA(lev))*CSRC_EB + OMEGA(lev)*EQEB; \ - RAC(tcel,dWT) = (1.0-OMEGA(lev))*CSRC_WT + OMEGA(lev)*EQWT; \ - RAC(tcel,dWB) = (1.0-OMEGA(lev))*CSRC_WB + OMEGA(lev)*EQWB; \ - - -// debug version1 -#define STREAMCHECK(ni,nj,nk,nl) -#define COLLCHECK -#define OPTIMIZED_STREAMCOLLIDE_DEBUG \ - m[0] = RAC(ccel,0); \ - FORDF1 { /* df0 is set later on... */ \ - if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ - } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ - } \ - rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ - CSMOMEGA_STATS(lev,mDebugOmegaRet); \ - FORDF0 { RAC(tcel,l) = m[l]; } \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - COLLCHECK; - - - -// more debugging -/*DEBUG \ - m[0] = RAC(ccel,0); \ - FORDF1 { \ - if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ - } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ - } \ -errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lcsmomega ); \ - rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ - CSMOMEGA_STATS(lev,mDebugOmegaRet); \ - */ -#if USE_LES==1 -#define DEFAULT_COLLIDE DEFAULT_COLLIDE_LES -#define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_LES -#else -#define DEFAULT_COLLIDE DEFAULT_COLLIDE_NOLES -#define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_NOLES -#endif - -#endif - -#define USQRMAXCHECK(Cusqr,Cux,Cuy,Cuz, CmMaxVlen,CmMxvx,CmMxvy,CmMxvz) \ - if(Cusqr>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<mLevel[leveli].lSizey-0;++j) \ - for(int i=0;i<mLevel[leveli].lSizex-0;++i) \ - -// loops over _only inner_ cells -#define FSGR_FORIJK1(leveli) \ - for(int k= getForZMin1(); k< getForZMax1(leveli); ++k) \ - for(int j=1;j<mLevel[leveli].lSizey-1;++j) \ - for(int i=1;i<mLevel[leveli].lSizex-1;++i) \ - -// relaxation_macros end - - -/****************************************************************************** - * Lbm Constructor - *****************************************************************************/ -template<class D> -LbmFsgrSolver<D>::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<D::cDimension; m++) { - for(int l=0; l<D::cDfNum; l++) { - D::lesCoeffDiag[m][l] = - D::lesCoeffOffdiag[m][l] = 0.0; - } - } - for(int m=0; m<D::cDimension; m++) { - for(int n=0; n<D::cDimension; n++) { - for(int l=1; l<D::cDfNum; l++) { - LbmFloat em; - switch(m) { - case 0: em = D::dfDvecX[l]; break; - case 1: em = D::dfDvecY[l]; break; - case 2: em = D::dfDvecZ[l]; break; - default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR); - } - LbmFloat en; - switch(n) { - case 0: en = D::dfDvecX[l]; break; - case 1: en = D::dfDvecY[l]; break; - case 2: en = D::dfDvecZ[l]; break; - default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR); - } - const LbmFloat coeff = em*en; - if(m==n) { - D::lesCoeffDiag[m][l] = coeff; - } else { - if(m>n) { - D::lesCoeffOffdiag[odm][l] = coeff; - } - } - } - - if(m==n) { - } else { - if(m>n) odm++; - } - } - } - - mDvecNrm[0] = LbmVec(0.0); - FORDF1 { - mDvecNrm[l] = getNormalized( - LbmVec(D::dfDvecX[D::dfInv[l]], D::dfDvecY[D::dfInv[l]], D::dfDvecZ[D::dfInv[l]] ) - ) * -1.0; - } - - addDrop(false,0,0); -} - -/*****************************************************************************/ -/* Destructor */ -/*****************************************************************************/ -template<class D> -LbmFsgrSolver<D>::~LbmFsgrSolver() -{ - if(!D::mInitDone){ debugOut("LbmFsgrSolver::LbmFsgrSolver : not inited...",0); return; } - -#if COMPRESSGRIDS==1 - delete mLevel[mMaxRefine].mprsCells[1]; - mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL; -#endif // COMPRESSGRIDS==1 - - for(int i=0; i<=mMaxRefine; i++) { - for(int s=0; s<2; s++) { - if(mLevel[i].mprsCells[s]) delete [] mLevel[i].mprsCells[s]; - if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s]; - } - } - delete D::mpIso; - if(mpPreviewSurface) delete mpPreviewSurface; - - // always output performance estimate - debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5); - if(!D::mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10); -} - - - - -/****************************************************************************** - * initilize variables fom attribute list - *****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::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<class D> -void -LbmFsgrSolver<D>::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 "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" offs:"<<mLevel[i].lOffsx<<","<<mLevel[i].lOffsy<<","<<mLevel[i].lOffsz - <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", " - <<" cmsagp:"<<mLevel[i].lcsmago<<", " - << " ss"<<mLevel[i].stepsize<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize ); - } else { - if(!D::mInitDone) { - debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" " - <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5); - } - } - } - if(mMaxRefine>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<class D> -bool -LbmFsgrSolver<D>::initialize( ntlTree* /*tree*/, vector<ntlGeometryObject*>* /*objects*/ ) -{ - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<<ALSTRING<<") ",1); - - // fix size inits to force cubic cells and mult4 level dimensions - const int debugGridsizeInit = 1; - mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)D::mSizex; - int maxGridSize = D::mSizex; // get max size - if(D::mSizey>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:"<<D::mvGeoStart<<" End:"<<D::mvGeoEnd<<" maxS:"<<maxGeoSize<<" maxG:"<<maxGridSize<<" cs:"<<cellSize, 10); - // force grid sizes according to geom. size, rounded - D::mSizex = (int) ((D::mvGeoEnd[0]-D::mvGeoStart[0]) / cellSize +0.5); - D::mSizey = (int) ((D::mvGeoEnd[1]-D::mvGeoStart[1]) / cellSize +0.5); - D::mSizez = (int) ((D::mvGeoEnd[2]-D::mvGeoStart[2]) / cellSize +0.5); - // match refinement sizes, round downwards to multiple of 4 - int sizeMask = 0; - int maskBits = mMaxRefine; - if(PARALLEL==1) maskBits+=2; - for(int i=0; i<maskBits; i++) { sizeMask |= (1<<i); } - sizeMask = ~sizeMask; - if(debugGridsizeInit) debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez<<" m"<<convertCellFlagType2String(sizeMask) ,10); - D::mSizex &= sizeMask; - D::mSizey &= sizeMask; - D::mSizez &= sizeMask; - // force geom size to match rounded grid sizes - D::mvGeoEnd[0] = D::mvGeoStart[0] + cellSize*(LbmFloat)D::mSizex; - D::mvGeoEnd[1] = D::mvGeoStart[1] + cellSize*(LbmFloat)D::mSizey; - D::mvGeoEnd[2] = D::mvGeoStart[2] + cellSize*(LbmFloat)D::mSizez; - - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Final domain size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez<< - ", Domain: "<<D::mvGeoStart<<":"<<D::mvGeoEnd<<", "<<(D::mvGeoEnd-D::mvGeoStart) ,2); - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG, ,2); - D::mpParam->setSize(D::mSizex, D::mSizey, D::mSizez); - - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez ,2); - -#if ELBEEM_BLENDER!=1 - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: " - <<"LBM_EPSILON="<<LBM_EPSILON <<" " - <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" " - <<"INTORDER="<<INTORDER <<" " - <<"REFINEMENTBORDER="<<REFINEMENTBORDER <<" " - <<"OPT3D="<<OPT3D <<" " - <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" " - <<"LS_FLUIDTHRESHOLD="<<LS_FLUIDTHRESHOLD <<" " - <<"MASS_INVALID="<<MASS_INVALID <<" " - <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" " - <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" " - <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" " - <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" " - <<"USE_LES="<<USE_LES <<" " - ,10); -#endif // ELBEEM_BLENDER!=1 - - // perform 2D corrections... - if(D::cDimension == 2) D::mSizez = 1; - - D::mpParam->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 "<<mForceTadapRefine, 6); - } - - if(!D::mpParam->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 "<<i<<" "<<PRINT_VEC(mLevel[i].lSizex,mLevel[i].lSizey,mLevel[i].lSizez) ); - xit(1); - }// old QUAD handling */ - } - - // estimate memory usage - { - unsigned long int memCnt = 0; - unsigned long int rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); - memCnt += sizeof(CellFlagType) * (rcellSize/dTotalNum +4) *2; -#if COMPRESSGRIDS==0 - memCnt += sizeof(LbmFloat) * (rcellSize +4) *2; -#else // COMPRESSGRIDS==0 - unsigned long int compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); - memCnt += sizeof(LbmFloat) * (rcellSize+compressOffset +4); -#endif // COMPRESSGRIDS==0 - for(int i=mMaxRefine-1; i>=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:"<<sizeof(CellFlagType)<<", should be:"<<CellFlagTypeSize, SIMWORLD_GENERICERROR); - return false; - } - - mLevel[ mMaxRefine ].nodeSize = ((D::mvGeoEnd[0]-D::mvGeoStart[0]) / (LbmFloat)(D::mSizex)); - mLevel[ mMaxRefine ].simCellSize = D::mpParam->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:"<<rcellSize<<" cpff:"<<compressOffset<< " c0:"<<mLevel[ mMaxRefine ].mprsCells[0]<<" c1:"<<mLevel[ mMaxRefine ].mprsCells[1]<< " c0e:"<<(mLevel[ mMaxRefine ].mprsCells[0]+rcellSize)<<" c1:"<<(mLevel[ mMaxRefine ].mprsCells[1]+rcellSize)); // DEBUG -#endif // COMPRESSGRIDS==0 - - LbmFloat lcfdimFac = 8.0; - if(D::cDimension==2) lcfdimFac = 4.0; - for(int i=mMaxRefine-1; i>=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 ", " "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5)<<" "<<(LbmFloat)(D::mSizex+1.0)<<" " ); - D::mpIso->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;ak<D::mSizez+2+twodOff;ak++) - for(int aj=0;aj<D::mSizey+2;aj++) - for(int ai=0;ai<D::mSizex+2;ai++) { *D::mpIso->getData(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;k<mLevel[mMaxRefine].lSizez;k++) - for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { - initEmptyCell(mMaxRefine, i,0,k, CFBnd, 0.0, BND_FILL); - initEmptyCell(mMaxRefine, i,mLevel[mMaxRefine].lSizey-1,k, CFBnd, 0.0, BND_FILL); - } - - if(D::cDimension == 3) { - // only for 3D - for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) - for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { - initEmptyCell(mMaxRefine, i,j,0, CFBnd, 0.0, BND_FILL); - initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-1, CFBnd, 0.0, BND_FILL); - } - } - - for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) - for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { - initEmptyCell(mMaxRefine, 0,j,k, CFBnd, 0.0, BND_FILL); - initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-1,j,k, CFBnd, 0.0, BND_FILL); - // DEBUG BORDER! - //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, CFBnd, 0.0, BND_FILL); - } - - // TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 - /*for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) - for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { - initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, CFBnd, 0.0, BND_FILL); - } - for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) - for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { - initEmptyCell(mMaxRefine, i,1,k, CFBnd, 0.0, BND_FILL); - } - // */ - - /*for(int ii=0; ii<(int)pow(2.0,mMaxRefine)-1; ii++) { - errMsg("BNDTESTSYMM","set "<<mLevel[mMaxRefine].lSizex-2-ii ); - for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) - for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { - initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2-ii,j,k, CFBnd, 0.0, BND_FILL); // SYMM!? 2D? - } - for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) - for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { - initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-2-ii, CFBnd, 0.0, BND_FILL); // SYMM!? 3D? - } - } - // Symmetry tests */ - - // prepare interface cells - initFreeSurfaces(); - initStandingFluidGradient(); - - // perform first step to init initial mass - mInitialMass = 0.0; - int inmCellCnt = 0; - FSGR_FORIJK1(mMaxRefine) { - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid) ) { - LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0); - FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); } - mInitialMass += fluidRho; - inmCellCnt ++; - } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { - mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass); - inmCellCnt ++; - } - } - mCurrentVolume = mCurrentMass = mInitialMass; - - ParamVec cspv = D::mpParam->calculateCellSize(); - 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:"<<mInitialMass<<" normalized:"<<nrmMass, 3); - mInitialMass = 0.0; // reset, and use actual value after first step - - //mStartSymm = false; -#if ELBEEM_BLENDER!=1 - if((D::cDimension==2)&&(D::mSizex<200)) { - if(!checkSymmetry("init")) { - errMsg("LbmFsgrSolver::initialize","Unsymmetric init..."); - } else { - errMsg("LbmFsgrSolver::initialize","Symmetric init!"); - } - } -#endif // ELBEEM_BLENDER!=1 - - - // ---------------------------------------------------------------------- - // coarsen region - myTime_t fsgrtstart = getTime(); - for(int lev=mMaxRefine-1; lev>=0; lev--) { - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<<lev<<".",8); - performRefinement(lev); - performCoarsening(lev); - coarseRestrictFromFine(lev); - performRefinement(lev); - performCoarsening(lev); - coarseRestrictFromFine(lev); - } - D::markedClearList(); - myTime_t fsgrtend = getTime(); - if(!D::mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< ((fsgrtend-fsgrtstart)/(double)1000.0)<<"s), changes:"<<mNumFsgrChanges , 10 ); } - mNumFsgrChanges = 0; - - for(int l=0; l<D::cDirNum; l++) { - LbmFloat area = 0.5 * 0.5 *0.5; - if(D::cDimension==2) area = 0.5 * 0.5; - - if(D::dfVecX[l]!=0) area *= 0.5; - if(D::dfVecY[l]!=0) area *= 0.5; - if(D::dfVecZ[l]!=0) area *= 0.5; - mFsgrCellArea[l] = area; - } // l - /*for(int lev=0; lev<mMaxRefine; lev++) { - FSGR_FORIJK_BOUNDS(lev) { - if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { - if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { - LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<D::cDirNum; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& - (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - ) { - //LbmFloat area = 0.25; if(D::dfVecX[l]!=0) area *= 0.5; if(D::dfVecY[l]!=0) area *= 0.5; if(D::dfVecZ[l]!=0) area *= 0.5; - totArea += mFsgrCellArea[l]; - } - } // l - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; - } else if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFEmpty) { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; - } else { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; - } - errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); - } - } } // */ - - // now really done... - debugOut("LbmFsgrSolver::initialize : Init done ...",10); - D::mInitDone = 1; - - // make sure both sets are ok - // copy from other to curr - 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 */ - - - - if(mOutputSurfacePreview) { - if(D::cDimension==2) { - errFatal("LbmFsgrSolver::init","No preview in 2D allowed!",SIMWORLD_INITERROR); return false; - } - - //int previewSize = mOutputSurfacePreview; - // same as normal one, but use reduced size - mpPreviewSurface = new IsoSurface( D::mIsoValue, false ); - mpPreviewSurface->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="<<PRINT_IJK); - for(int l=0; l<D::cDfNum; l++) { - debMsgDirect(" df="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, l) ); - } - debMsgDirect(" m="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dMass) ); - debMsgDirect(" f="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dFfrac) ); - debMsgDirect(" x="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); - } } // COMPRT ON */ - return true; -} - - - -/*****************************************************************************/ -/*! perform geometry init (if switched on) */ -/*****************************************************************************/ -template<class D> -bool -LbmFsgrSolver<D>::initGeometryFlags() { - int level = mMaxRefine; - myTime_t geotimestart = getTime(); - ntlGeometryObject *pObj; - // getCellSize (due to forced cubes, use x values) - ntlVec3Gfx dvec( (D::mvGeoEnd[0]-D::mvGeoStart[0])/ ((LbmFloat)D::mSizex*2.0)); - // real cell size from now on... - dvec *= 2.0; - ntlVec3Gfx nodesize = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; - dvec = nodesize; - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< D::mGeoInitId <<") v"<<dvec,3); - - /* set interface cells */ - D::initGeoTree(D::mGeoInitId); - ntlVec3Gfx maxIniVel = vec2G( D::mpParam->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="<<allowMax ,5); - if(D::mpParam->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;j<mLevel[level].lSizey-1;j++) { - for(int i=1;i<mLevel[level].lSizex-1;i++) { - CellFlagType ntype = CFInvalid; - if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance)) { - pObj = (*D::mpGiObjects)[OId]; - switch( pObj->getGeoInitType() ){ - 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+1<mLevel[level].lSizex-1)) { - dcnt += dvec[0]; i++; - savedNodes++; - if(ntype != CFInvalid) { - // rho,mass,OId are still inited from above - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - } - } - // */ - - } - } - } // zmax - - - // now init fluid layer - for(int k= getForZMin1(); k< getForZMax1(level); ++k) { - for(int j=1;j<mLevel[level].lSizey-1;j++) { - for(int i=1;i<mLevel[level].lSizex-1;i++) { - if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - - CellFlagType ntype = CFInvalid; - int inits = 0; - if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance)) { - ntype = CFFluid; - } - if(ntype != CFInvalid) { - // initDefaultCell - rhomass = 1.0; - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - inits++; - } - - // 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+1<mLevel[level].lSizex-1)) { - dcnt += dvec[0]; i++; - savedNodes++; - if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - if(ntype != CFInvalid) { - // rhomass are still inited from above - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - inits++; - } - } - } // distance>0 - - } - } - } // zmax - - D::freeGeoTree(); - myTime_t geotimeend = getTime(); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< ((geotimeend-geotimestart)/(double)1000.0)<<"s,"<<savedNodes<<") " , 10 ); - //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez)); - return true; -} - -/*****************************************************************************/ -/* init part for all freesurface testcases */ -template<class D> -void -LbmFsgrSolver<D>::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<mInitSurfaceSmoothing; s++) { - FSGR_FORIJK1(mMaxRefine) { - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { - LbmFloat mass = 0.0; - //LbmFloat nbdiv; - FORDF0 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFFluid ){ - mass += 1.0; - } - if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFInter ){ - mass += QCELL(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, dMass); - } - //nbdiv+=1.0; - } - - //errMsg(" I ", PRINT_IJK<<" m"<<mass ); - QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass) = (mass/19.0); - QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dFfrac) = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass); - } - } - - mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; - mLevel[mMaxRefine].setCurr ^= 1; - } - // copy back...? - -} - -/*****************************************************************************/ -/* init part for all freesurface testcases */ -template<class D> -void -LbmFsgrSolver<D>::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="<<gravIMin[0]<<" end="<<gravIMax[0]<<" dir="<<gravDir[0] ); \ - errMsg("Standing fp","Y start="<<gravIMin[1]<<" end="<<gravIMax[1]<<" dir="<<gravDir[1] ); \ - errMsg("Standing fp","Z start="<<gravIMin[2]<<" end="<<gravIMax[2]<<" dir="<<gravDir[2] ); - // _PRINTGDIRS; - - bool gravAbort = false; -#define GRAVLOOP \ - gravAbort=false; \ - for(gravIndex[2]= gravIMin[2]; (gravIndex[2]!=gravIMax[2])&&(!gravAbort); gravIndex[2] += gravDir[2]) \ - for(gravIndex[1]= gravIMin[1]; (gravIndex[1]!=gravIMax[1])&&(!gravAbort); gravIndex[1] += gravDir[1]) \ - for(gravIndex[0]= gravIMin[0]; (gravIndex[0]!=gravIMax[0])&&(!gravAbort); gravIndex[0] += gravDir[0]) - - GRAVLOOP { - int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; - //if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) {debMsgStd("Standing fluid preinit", DM_MSG, "fluidheightinit check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 ); } - //STANDFLAGCHECK(gravIndex[maxGravComp]); - if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || - ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ - int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp])); - if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] ); - //if(gravIndex[maxGravComp]>1) - if(fluidHeight>1) - { - haveStandingFluid = fluidHeight; //gravIndex[maxGravComp]; - gravIMax[maxGravComp] = gravIndex[maxGravComp] + gravDir[maxGravComp]; - } - gravAbort = true; continue; - } - } // GRAVLOOP - // _PRINTGDIRS; - - LbmFloat fluidHeight; - //if(gravDir>0) { fluidHeight = (LbmFloat)haveStandingFluid; - //} else { fluidHeight = (LbmFloat)haveStandingFluid; } - fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp])); - if(debugStandingPreinit) debMsgStd("Standing fluid preinit", DM_MSG, "fheight="<<fluidHeight<<" min="<<PRINT_VEC(gravIMin[0],gravIMin[1], gravIMin[2])<<" max="<<PRINT_VEC(gravIMax[0], gravIMax[1],gravIMax[2])<< - " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10); - - if(mDisableStandingFluidInit) { - debMsgStd("Standing fluid preinit", DM_MSG, "Should be performed - but skipped due to mDisableStandingFluidInit flag set!", 2); - haveStandingFluid=0; - } - - // copy flags and init , as no flags will be changed during grav init - // also important for corasening later on - const int lev = mMaxRefine; - CellFlagType nbflag[LBM_DFNUM], nbored; - for(int k=D::getForZMinBnd();k<D::getForZMaxBnd();++k) { - for(int j=0;j<mLevel[lev].lSizey-0;++j) { - for(int i=0;i<mLevel[lev].lSizex-0;++i) { - if( (RFLAG(lev, i,j,k,SRCS(lev)) & (CFFluid)) ) { - nbored = 0; - FORDF1 { - nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); - nbored |= nbflag[l]; - } - if(nbored&CFBnd) { - RFLAG(lev, i,j,k,SRCS(lev)) &= (~CFNoBndFluid); - } else { - RFLAG(lev, i,j,k,SRCS(lev)) |= CFNoBndFluid; - } - } - RFLAG(lev, i,j,k,TSET(lev)) = RFLAG(lev, i,j,k,SRCS(lev)); - } } } - - if(haveStandingFluid) { - int rhoworkSet = mLevel[lev].setCurr; - myTime_t timestart = getTime(); // FIXME use user time here? -#if OPT3D==true - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; -#endif // OPT3D==true - - GRAVLOOP { - int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; - //debMsgStd("Standing fluid preinit", DM_MSG, " init check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 ); - if( ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFInter)) ) || - ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFEmpty)) ) ){ - //gravAbort = true; - continue; - } - - LbmFloat rho = 1.0; - // 1/6 velocity from denisty gradient, 1/2 for delta of two cells - rho += 1.0* (fluidHeight-gravIndex[maxGravComp]) * - (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega); - if(debugStandingPreinit) - if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) { - errMsg("Standing fp","gi="<<gravIndex[maxGravComp]<<" rho="<<rho<<" at "<<PRINT_IJK); - } - - if( (RFLAG(lev, i,j,k, rhoworkSet) & CFFluid) || - (RFLAG(lev, i,j,k, rhoworkSet) & CFInter) ) { - FORDF0 { QCELL(lev, i,j,k, rhoworkSet, l) *= rho; } - QCELL(lev, i,j,k, rhoworkSet, dMass) *= rho; - } - - } // GRAVLOOP - debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited", 8); - - int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) ); - preinitSteps = (haveStandingFluid>>2); // not much use...? - //preinitSteps = 4; // DEBUG!!!! - //D::mInitDone = 1; // GRAVTEST - //preinitSteps = 0; - debMsgNnl("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10); - for(int s=0; s<preinitSteps; s++) { - int workSet = SRCS(lev); //mLevel[lev].setCurr; - int otherSet = TSET(lev); //mLevel[lev].setOther; - debMsgDirect("."); - if(debugStandingPreinit) debMsgStd("Standing fluid preinit", DM_MSG, "s="<<s<<" curset="<<workSet<<" srcs"<<SRCS(lev), 10); - LbmFloat *ccel; - LbmFloat *tcel; - LbmFloat m[LBM_DFNUM]; - - // grav loop not necessary here -#define NBFLAG(l) (nbflag[(l)]) - LbmFloat rho, ux,uy,uz, usqr; - int kstart=D::getForZMinBnd(), kend=D::getForZMaxBnd(); -#if COMPRESSGRIDS==0 - for(int k=kstart;k<kend;++k) { -#else // COMPRESSGRIDS==0 - int kdir = 1; // COMPRT ON - if(mLevel[lev].setCurr==1) { - kdir = -1; - int temp = kend; - kend = kstart-1; - kstart = temp-1; - } // COMPRT - for(int k=kstart;k!=kend;k+=kdir) { - - //errMsg("LbmFsgrSolver::mainLoop","k="<<k<<" ks="<<kstart<<" ke="<<kend<<" kdir="<<kdir ); // debug -#endif // COMPRESSGRIDS==0 - - for(int j=0;j<mLevel[lev].lSizey-0;++j) { - for(int i=0;i<mLevel[lev].lSizex-0;++i) { - const CellFlagType currFlag = RFLAG(lev, i,j,k,workSet); - if( (currFlag & (CFEmpty|CFBnd)) ) continue; - ccel = RACPNT(lev, i,j,k,workSet); - tcel = RACPNT(lev, i,j,k,otherSet); - - if( (currFlag & (CFInter)) ) { - // copy all values - for(int l=0; l<dTotalNum;l++) { RAC(tcel,l) = RAC(ccel,l); } - continue; - } - - if( (currFlag & CFNoBndFluid)) { - OPTIMIZED_STREAMCOLLIDE; - } else { - FORDF1 { - nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); - } - DEFAULT_STREAM; - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - DEFAULT_COLLIDE; - } - for(int l=LBM_DFNUM; l<dTotalNum;l++) { RAC(tcel,l) = RAC(ccel,l); } - } } } // GRAVLOOP - - mLevel[lev].setOther = mLevel[lev].setCurr; - mLevel[lev].setCurr ^= 1; - } - //D::mInitDone = 0; // GRAVTEST - // */ - - myTime_t timeend = getTime(); - debMsgDirect(" done, "<<((timeend-timestart)/(double)1000.0)<<"s \n"); -#undef NBFLAG - } -} - - - -/*****************************************************************************/ -/* init a given cell with flag, density, mass and equilibrium dist. funcs */ - -template<class D> -void LbmFsgrSolver<D>::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<class D> -void -LbmFsgrSolver<D>::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<class D> -void -LbmFsgrSolver<D>::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<class D> -bool -LbmFsgrSolver<D>::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<maxMsgs) { msgs++; - errMsg("EFLAG", PRINT_IJK<<"s"<<s<<" flag "<<RFLAG(lev, i,j,k,s)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" flag "<<RFLAG(lev, inb,j,k,s) ); - } - } - if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } - symm = false; - } - if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true; - if(D::cDimension==2) { - if(msgs<maxMsgs) { msgs++; - //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl); - errMsg("EMASS", PRINT_IJK<<"s"<<s<<" mass "<<QCELL(lev, i,j,k,s, dMass)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" mass "<<QCELL(lev, inb,j,k,s, dMass) ); - } - } - if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } - symm = false; - } - - LbmFloat nbrho = QCELL(lev, i,j,k, s, dC); - FORDF1 { nbrho += QCELL(lev, i,j,k, s, l); } - LbmFloat otrho = QCELL(lev, inb,j,k, s, dC); - FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); } - if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true; - if(D::cDimension==2) { - if(msgs<maxMsgs) { msgs++; - //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl); - errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho ); - } - } - if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } - symm = false; - } - } - } } - } // lev - LbmFloat maxdiv =0.0; - if(erro) { - errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv ); - //if(D::cDimension==2) D::mPanic = true; - //return false; - } else { - errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv ); - } - // all ok... - return symm; -}// */ - - -/*****************************************************************************/ -/*! debug object display */ -/*****************************************************************************/ -template<class D> -vector<ntlGeometryObject*> LbmFsgrSolver<D>::getDebugObjects() { - vector<ntlGeometryObject*> debo; - if(mOutputSurfacePreview) { - debo.push_back( mpPreviewSurface ); - } - return debo; -} - -/*****************************************************************************/ -/*! perform a single LBM step */ -/*****************************************************************************/ - -template<class D> -void -LbmFsgrSolver<D>::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 : "<<D::mStepCnt, 10); - if(!D::mSilent){ debMsgNnl("LbmFsgrSolver::step", DM_MSG, D::mName<<" cnt:"<<D::mStepCnt<<" ", 10); } - //debMsgDirect( "LbmFsgrSolver::step : "<<D::mStepCnt<<" "); - myTime_t timestart = getTime(); - //myTime_t timestart = 0; - //if(mStartSymm) { checkSymmetry("step1"); } // DEBUG - - // important - keep for tadap - mCurrentMass = D::mFixMass; // reset here for next step - mCurrentVolume = 0.0; - - //stats - mMaxVlen = mMxvz = mMxvy = mMxvx = 0.0; - - //change to single step advance! - int levsteps = 0; - int dsbits = D::mStepCnt ^ (D::mStepCnt-1); - //errMsg("S"," step:"<<D::mStepCnt<<" s-1:"<<(D::mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits)); - for(int lev=0; lev<=mMaxRefine; lev++) { - //if(! (D::mStepCnt&(1<<lev)) ) { - if( dsbits & (1<<(mMaxRefine-lev)) ) { - //errMsg("S"," l"<<lev); - - if(lev==mMaxRefine) { - // always advance fine level... - fineAdvance(); - } else { - performRefinement(lev); - performCoarsening(lev); - coarseRestrictFromFine(lev); - coarseAdvance(lev); - } -#if FSGR_OMEGA_DEBUG==1 - errMsg("LbmFsgrSolver::step","LES stats l="<<lev<<" omega="<<mLevel[lev].omega<<" avgOmega="<< (mLevel[lev].avgOmega/mLevel[lev].avgOmegaCnt) ); - mLevel[lev].avgOmega = 0.0; mLevel[lev].avgOmegaCnt = 0.0; -#endif // FSGR_OMEGA_DEBUG==1 - levsteps++; - } - mCurrentMass += mLevel[lev].lmass; - mCurrentVolume += mLevel[lev].lvolume; - } - - // prepare next step - D::mStepCnt++; - - - // some dbugging output follows - // calculate MLSUPS - myTime_t timeend = getTime(); - - D::mNumUsedCells += mNumInterdCells; // count both types for MLSUPS - mAvgNumUsedCells += D::mNumUsedCells; - D::mMLSUPS = (D::mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000); - if(D::mMLSUPS>10000){ D::mMLSUPS = -1; } - else { mAvgMLSUPS += D::mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups - - LbmFloat totMLSUPS = ( ((mLevel[mMaxRefine].lSizex-2)*(mLevel[mMaxRefine].lSizey-2)*(getForZMax1(mMaxRefine)-getForZMin1())) / ((timeend-timestart)/(double)1000.0) ) / (1000000); - if(totMLSUPS>10000) totMLSUPS = -1; - mNumInvIfTotal += mNumInvIfCells; // debug - - // do some formatting - if(!D::mSilent){ - string sepStr(""); // DEBUG -#ifndef USE_MSVC6FIXES - int avgcls = (int)(mAvgNumUsedCells/(long long int)D::mStepCnt); -#else - int avgcls = (int)(mAvgNumUsedCells/(_int64)D::mStepCnt); -#endif - debMsgDirect( - "mlsups(curr:"<<D::mMLSUPS<< - " avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<< sepStr<< - " totcls:"<<(D::mNumUsedCells)<< sepStr<< - " avgcls:"<< avgcls<< sepStr<< - " intd:"<<mNumInterdCells<< sepStr<< - " invif:"<<mNumInvIfCells<< sepStr<< - " invift:"<<mNumInvIfTotal<< sepStr<< - " fsgrcs:"<<mNumFsgrChanges<< sepStr<< - " filled:"<<D::mNumFilledCells<<", emptied:"<<D::mNumEmptiedCells<< sepStr<< - " mMxv:"<<mMxvx<<","<<mMxvy<<","<<mMxvz<<", tscnts:"<<mTimeSwitchCounts<< sepStr<< - " probs:"<<mNumProblems<< sepStr<< - " simt:"<<mSimulationTime<< sepStr<< - " for '"<<D::mName<<"' " ); - - debMsgDirect(std::endl); - debMsgDirect(D::mStepCnt<<": dccd="<< mCurrentMass<<"/"<<mCurrentVolume<<"(fix="<<D::mFixMass<<",ini="<<mInitialMass<<") "); - debMsgDirect(std::endl); - - // nicer output - debMsgDirect(std::endl); // - //debMsgStd(" ",DM_MSG," ",10); - } else { - debMsgDirect("."); - //if((mStepCnt%10)==9) debMsgDirect("\n"); - } - - if(D::mStepCnt==1) { - mMinNoCells = mMaxNoCells = D::mNumUsedCells; - } else { - if(D::mNumUsedCells>mMaxNoCells) mMaxNoCells = D::mNumUsedCells; - if(D::mNumUsedCells<mMinNoCells) mMinNoCells = D::mNumUsedCells; - } - - // mass scale test - if((mMaxRefine>0)&&(mInitialMass>0.0)) { - LbmFloat mscale = mInitialMass/mCurrentMass; - - mscale = 1.0; - const LbmFloat dchh = 0.001; - if(mCurrentMass<mInitialMass) mscale = 1.0+dchh; - if(mCurrentMass>mInitialMass) 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:"<<mInitialMass<<", cur:"<<mCurrentMass<<", f="<<ABS(mInitialMass/mCurrentMass) - <<" step:"<<D::mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" " - ); - errMsg("MDTDD","\n\n"); - - mscount++; - for(int lev=mMaxRefine; lev>=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: "<<mInitialMass, 2); - } - } - - // one of the last things to do - adapt timestep - // was in fineAdvance before... - if(mTimeAdap) { - adaptTimestep(); - } // time adaptivity - - // debug - raw dump of ffrac values - /*if((mStepCnt%200)==1){ - std::ostringstream name; - name <<"fill_" << mStepCnt <<".dump"; - FILE *file = fopen(name.str().c_str(),"w"); - for(int k= getForZMinBnd(mMaxRefine); k< getForZMaxBnd(mMaxRefine); ++k) - for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) - for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { - float val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); - fwrite( &val, sizeof(val), 1, file); - //errMsg("W", PRINT_IJK<<" val:"<<val); - } - fclose(file); - } // */ - - /* - if(1) { // DEBUG - const int lev = mMaxRefine; - int workSet = mLevel[lev].setCurr; - FSGR_FORIJK1(lev) { - 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<D::cDfNum; l++) { - LbmFloat m = QCELL(lev, i, j, k, workSet, l); - rho += m; - ux += (D::dfDvecX[l]*m); - uy += (D::dfDvecY[l]*m); - uz += (D::dfDvecZ[l]*m); - } - //errMsg("DEBUG"," "<<PRINT_IJK <<" rho="<<rho<<" vel="<<PRINT_VEC(ux,uy,uz) ); - errMsg(stdout,"D %d,%d rho=%+'.5f vel=[%+'.5f,%+'.5f] \n", i,j, rho, ux,uy ); - } - } // DEBUG */ - -} - -template<class D> -void -LbmFsgrSolver<D>::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 "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps) ); } - - // update other set - mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; - mLevel[mMaxRefine].setCurr ^= 1; - mLevel[mMaxRefine].lsteps++; - - // flag init... (work on current set, to simplify flag checks) - reinitFlags( mLevel[mMaxRefine].setCurr ); - //if((D::cDimension==2)&&(mStartSymm)) { checkSymmetry("step3"); } // DEBUG - if(!D::mSilent){ errMsg("fineAdvance"," flags reinit on set "<< mLevel[mMaxRefine].setCurr ); } -} - - -/*****************************************************************************/ -//! coarse/fine step functions -/*****************************************************************************/ - -// access to own dfs during step (may be changed to local array) -#define MYDF(l) RAC(ccel, l) - -template<class D> -void -LbmFsgrSolver<D>::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<mLevel[mMaxRefine].lSizex-1;++i) { - if(RFLAG(lev, i,j,k,SRCS(lev)) & CFFluid) { - RFLAG(lev, i,j,k,SRCS(lev)) = CFInter; - QCELL(lev, i,j,k,SRCS(lev), dMass) = 0.1; - QCELL(lev, i,j,k,SRCS(lev), dFfrac) = 0.1; - } - else if(RFLAG(lev, i,j,k,SRCS(lev)) & CFInter) { - QCELL(lev, i,j,k,SRCS(lev), dMass) = 0.1; - QCELL(lev, i,j,k,SRCS(lev), dFfrac) = 0.1; - } - } } } } - - - - // --- - // now stream etc. - - // use template functions for 2D/3D -#if COMPRESSGRIDS==0 - for(int k=kstart;k<kend;++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=0;i<mLevel[lev].lSizex-2; ) { -#else // COMPRESSGRIDS==0 - int kdir = 1; // COMPRT ON - if(mLevel[mMaxRefine].setCurr==1) { - kdir = -1; - int temp = kend; - kend = kstart-1; - kstart = temp-1; - } // COMPRT - -#if PARALLEL==0 - const int id = 0, Nthrds = 1; -#endif // PARALLEL==1 - const int Nj = mLevel[mMaxRefine].lSizey; - int jstart = 0+( id * (Nj / Nthrds) ); - int jend = 0+( (id+1) * (Nj / Nthrds) ); - if( ((Nj/Nthrds) *Nthrds) != Nj) { - errMsg("LbmFsgrSolver","Invalid domain size Nj="<<Nj<<" Nthrds="<<Nthrds); - } - // cutoff obstacle boundary - if(jstart<1) jstart = 1; - if(jend>mLevel[mMaxRefine].lSizey-1) jend = mLevel[mMaxRefine].lSizey-1; - -#if PARALLEL==1 - errMsg("LbmFsgrSolver::mainLoop","id="<<id<<" js="<<jstart<<" je="<<jend<<" jdir="<<(1) ); // debug -#endif // PARALLEL==1 - for(int k=kstart;k!=kend;k+=kdir) { - - //errMsg("LbmFsgrSolver::mainLoop","k="<<k<<" ks="<<kstart<<" ke="<<kend<<" kdir="<<kdir<<" x*y="<<mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum ); // debug - pFlagSrc = &RFLAG(lev, 0, jstart, k, SRCS(lev)); // omp test // COMPRT ON - pFlagDst = &RFLAG(lev, 0, jstart, k, TSET(lev)); // omp test - ccel = RACPNT(lev, 0, jstart, k, SRCS(lev)); // omp test - tcel = RACPNT(lev, 0, jstart, k, TSET(lev)); // omp test // COMPRT ON - - //for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int j=jstart;j!=jend;++j) { - for(int i=0;i<mLevel[lev].lSizex-2; ) { -#endif // COMPRESSGRIDS==0 - - ADVANCE_POINTERS(1); -#if FSGR_STRICT_DEBUG==1 - rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG - if( (&RFLAG(lev, i,j,k,mLevel[lev].setCurr) != pFlagSrc) || - (&RFLAG(lev, i,j,k,mLevel[lev].setOther) != pFlagDst) ) { - errMsg("LbmFsgrSolver::mainLoop","Err flagp "<<PRINT_IJK<<"="<< - RFLAG(lev, i,j,k,mLevel[lev].setCurr)<<","<<RFLAG(lev, i,j,k,mLevel[lev].setOther)<<" but is "<< - (*pFlagSrc)<<","<<(*pFlagDst) <<", pointers "<< - (int)(&RFLAG(lev, i,j,k,mLevel[lev].setCurr))<<","<<(int)(&RFLAG(lev, i,j,k,mLevel[lev].setOther))<<" but is "<< - (int)(pFlagSrc)<<","<<(int)(pFlagDst)<<" " - ); - D::mPanic=1; - } - if( (&QCELL(lev, i,j,k,mLevel[lev].setCurr,0) != ccel) || - (&QCELL(lev, i,j,k,mLevel[lev].setOther,0) != tcel) ) { - errMsg("LbmFsgrSolver::mainLoop","Err cellp "<<PRINT_IJK<<"="<< - (int)(&QCELL(lev, i,j,k,mLevel[lev].setCurr,0))<<","<<(int)(&QCELL(lev, i,j,k,mLevel[lev].setOther,0))<<" but is "<< - (int)(ccel)<<","<<(int)(tcel)<<" " - ); - D::mPanic=1; - } -#endif - oldFlag = *pFlagSrc; - // stream from current set to other, then collide and store - - // old INTCFCOARSETEST==1 - if( (oldFlag & (CFGrFromCoarse)) ) { // interpolateFineFromCoarse test! - if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } - } else { - interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); - calcNumUsedCells++; - } - continue; // interpolateFineFromCoarse test! - } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 - - if(oldFlag & (CFMbndInflow)) { - // fluid & if are ok, fill if later on - int isValid = oldFlag & (CFFluid|CFInter); - const LbmFloat iniRho = 1.0; - const int OId = oldFlag>>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 "<<PRINT_IJK ); - int isnotValid = oldFlag & (CFFluid); - if(isnotValid) { - // remove fluid cells, shouldnt be here anyway - //const int OId = oldFlag>>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<D::cDfNum; l++) { ofrho += RAC(ccel,l); } - calcCurrentMass += ofrho; - calcCurrentVolume += 1.0; - continue; - } - - newFlag = oldFlag; //cell(i,j,k, SRCS(lev)).flag; - // make sure: check which flags to really unset...! - newFlag = newFlag & (~( - CFNoNbFluid|CFNoNbEmpty| CFNoDelete - | CFNoInterpolSrc - | CFNoBndFluid - )); - // unnecessary for interface cells... !? - //if(nbored&CFBnd) { } else { newFlag |= CFNoBndFluid; } - - // store own dfs and mass - mass = RAC(ccel,dMass); - - // WARNING - only interface cells arrive here! - // read distribution funtions of adjacent cells = sweep step // FIXME after empty? - DEFAULT_STREAM; - - if((nbored & CFFluid)==0) { newFlag |= CFNoNbFluid; mNumInvIfCells++; } - if((nbored & CFEmpty)==0) { newFlag |= CFNoNbEmpty; mNumInvIfCells++; } - - // calculate mass exchange for interface cells - LbmFloat myfrac = RAC(ccel,dFfrac); -# define nbdf(l) m[ D::dfInv[(l)] ] - - // update mass - // only do boundaries for fluid cells, and interface cells without - // any fluid neighbors (assume that interface cells _with_ fluid - // neighbors are affected enough by these) - // which Df's have to be reconstructed? - // for fluid cells - just the f_i difference from streaming to empty cells ---- - numRecons = 0; - - FORDF1 { // dfl loop - recons[l] = 0; - // finally, "normal" interface cells ---- - if( NBFLAG(l)&CFFluid ) { - change = nbdf(l) - MYDF(l); - } - // interface cells - distuingish cells that shouldn't fill/empty - else if( NBFLAG(l) & CFInter ) { - - LbmFloat mynbfac = //numNbs[l] / numNbs[0]; - QCELL_NB(lev, i,j,k,SRCS(lev),l, dFlux) / QCELL(lev, i,j,k,SRCS(lev), dFlux); - LbmFloat nbnbfac = 1.0/mynbfac; - //mynbfac = nbnbfac = 1.0; // switch calc flux off - // OLD - if ((oldFlag|NBFLAG(l))&(CFNoNbFluid|CFNoNbEmpty)) { - switch (oldFlag&(CFNoNbFluid|CFNoNbEmpty)) { - case 0: - // we are a normal cell so... - switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { - case CFNoNbFluid: - // just fill current cell = empty neighbor - change = nbnbfac*nbdf(l) ; goto changeDone; - case CFNoNbEmpty: - // just empty current cell = fill neighbor - change = - mynbfac*MYDF(l) ; goto changeDone; - } - break; - - case CFNoNbFluid: - // we dont have fluid nb's so... - switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { - case 0: - case CFNoNbEmpty: - // we have no fluid nb's -> 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<D::cDfNum; l++) { - oldRho += RAC(ccel,l); - oldUx += (D::dfDvecX[l]*RAC(ccel,l)); - oldUy += (D::dfDvecY[l]*RAC(ccel,l)); - oldUz += (D::dfDvecZ[l]*RAC(ccel,l)); - } -#else // OPT3D==false - oldRho = + RAC(ccel,dC) + RAC(ccel,dN ) - + RAC(ccel,dS ) + RAC(ccel,dE ) - + RAC(ccel,dW ) + RAC(ccel,dT ) - + RAC(ccel,dB ) + RAC(ccel,dNE) - + RAC(ccel,dNW) + RAC(ccel,dSE) - + RAC(ccel,dSW) + RAC(ccel,dNT) - + RAC(ccel,dNB) + RAC(ccel,dST) - + RAC(ccel,dSB) + RAC(ccel,dET) - + RAC(ccel,dEB) + RAC(ccel,dWT) - + RAC(ccel,dWB); - - oldUx = + RAC(ccel,dE) - RAC(ccel,dW) - + RAC(ccel,dNE) - RAC(ccel,dNW) - + RAC(ccel,dSE) - RAC(ccel,dSW) - + RAC(ccel,dET) + RAC(ccel,dEB) - - RAC(ccel,dWT) - RAC(ccel,dWB); - - oldUy = + RAC(ccel,dN) - RAC(ccel,dS) - + RAC(ccel,dNE) + RAC(ccel,dNW) - - RAC(ccel,dSE) - RAC(ccel,dSW) - + RAC(ccel,dNT) + RAC(ccel,dNB) - - RAC(ccel,dST) - RAC(ccel,dSB); - - oldUz = + RAC(ccel,dT) - RAC(ccel,dB) - + RAC(ccel,dNT) - RAC(ccel,dNB) - + RAC(ccel,dST) - RAC(ccel,dSB) - + RAC(ccel,dET) - RAC(ccel,dEB) - + RAC(ccel,dWT) - RAC(ccel,dWB); -#endif - - // now reconstruction -#define REFERENCE_PRESSURE 1.0 // always atmosphere... -#if OPT3D==false - // NOW - construct dist funcs from empty cells - FORDF1 { - if(recons[ l ]) { - m[ D::dfInv[l] ] = - D::getCollideEq(l, REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + - D::getCollideEq(D::dfInv[l], REFERENCE_PRESSURE, oldUx,oldUy,oldUz) - - MYDF( l ); - /*errMsg("D", " "<<PRINT_IJK<<" l"<<l<<" eql"<<D::getCollideEq(l, REFERENCE_PRESSURE, oldUx,oldUy,oldUz)<< - " eqInvl"<<D::getCollideEq(D::dfInv[l], REFERENCE_PRESSURE, oldUx,oldUy,oldUz)<< - " mydfl"<< MYDF( l ) << - " newdf"<< m[ D::dfInv[l] ]<<" m"<<mass ); // MRT_FS_TEST */ - } // */ - } -#else - ux=oldUx, uy=oldUy, uz=oldUz; // no local vars, only for usqr - rho = REFERENCE_PRESSURE; - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); - if(recons[dN ]) { m[dS ] = EQN + EQS - MYDF(dN ); } - if(recons[dS ]) { m[dN ] = EQS + EQN - MYDF(dS ); } - if(recons[dE ]) { m[dW ] = EQE + EQW - MYDF(dE ); } - if(recons[dW ]) { m[dE ] = EQW + EQE - MYDF(dW ); } - if(recons[dT ]) { m[dB ] = EQT + EQB - MYDF(dT ); } - if(recons[dB ]) { m[dT ] = EQB + EQT - MYDF(dB ); } - if(recons[dNE]) { m[dSW] = EQNE + EQSW - MYDF(dNE); } - if(recons[dNW]) { m[dSE] = EQNW + EQSE - MYDF(dNW); } - if(recons[dSE]) { m[dNW] = EQSE + EQNW - MYDF(dSE); } - if(recons[dSW]) { m[dNE] = EQSW + EQNE - MYDF(dSW); } - if(recons[dNT]) { m[dSB] = EQNT + EQSB - MYDF(dNT); } - if(recons[dNB]) { m[dST] = EQNB + EQST - MYDF(dNB); } - if(recons[dST]) { m[dNB] = EQST + EQNB - MYDF(dST); } - if(recons[dSB]) { m[dNT] = EQSB + EQNT - MYDF(dSB); } - if(recons[dET]) { m[dWB] = EQET + EQWB - MYDF(dET); } - if(recons[dEB]) { m[dWT] = EQEB + EQWT - MYDF(dEB); } - if(recons[dWT]) { m[dEB] = EQWT + EQEB - MYDF(dWT); } - if(recons[dWB]) { m[dET] = EQWB + EQET - MYDF(dWB); } -#endif - - // mass streaming done... - // now collide new fluid or "old" if cells - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - DEFAULT_COLLIDE; - rho = m[dC]; - FORDF1 { rho+=m[l]; }; - // only with interface neighbors...? - PERFORM_USQRMAXCHECK; - - if(oldFlag & (CFMbndInflow)) { - // fill if cells in inflow region - if(myfrac<0.5) { - mass += 0.25; - mInitialMass += 0.25; - } - } - - // interface cell filled or emptied? - iffilled = ifemptied = 0; - // interface cells empty/full?, WARNING: to mark these cells, better do it at the end of reinitCellFlags - // interface cell if full? - if( (mass) >= (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 "<<PRINT_IJK); }; - iffilled = 1; - } - } - if(!ifemptied) { - if( (oldFlag & CFNoNbFluid)&&(newFlag & CFNoNbFluid)&& - ( (mass<(rho*FSGR_LISTTTHRESHEMPTY)) || ((nbored&CFInter)==0) ) - ) - { - //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","emptied "<<PRINT_IJK); }; - ifemptied = 1; - } - } // */ -#endif - - //iffilled = ifemptied = 0; // DEBUG!!!!!!!!!!!!!!! - - - // now that all dfs are known, handle last changes - if(iffilled) { - LbmPoint filledp; - filledp.x = i; filledp.y = j; filledp.z = k; -#if PARALLEL==1 - calcListFull[id].push_back( filledp ); -#else // PARALLEL==1 - mListFull.push_back( filledp ); -#endif // PARALLEL==1 - //D::mNumFilledCells++; // DEBUG - calcCellsFilled++; - } - else if(ifemptied) { - 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 - //D::mNumEmptiedCells++; // DEBUG - calcCellsEmptied++; - } else { - // ... - } - - // dont cutoff values -> 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; nn<D::cDfNum; nn++) { - if(RFLAG_NB(lev, i,j,k,SRCS(lev),nn) & (CFFluid|CFInter|CFBnd)) { - flux += D::dfLength[nn]; - } - } - //flux = FLUX_INIT; // calc flux off - QCELL(lev, i,j,k,TSET(lev), dFlux) = flux; // */ - - // perform mass exchange with streamed values - QCELL(lev, i,j,k,TSET(lev), dMass) = mass; // MASST - // set new flag - *pFlagDst = (CellFlagType)newFlag; - calcCurrentMass += mass; - calcCurrentVolume += RAC(tcel,dFfrac); - - // interface cell handling done... - } // i - int i=0; //dummy - ADVANCE_POINTERS(2); - } // j - -#if COMPRESSGRIDS==1 -#if PARALLEL==1 - //frintf(stderr," (id=%d k=%d) ",id,k); -# pragma omp barrier -#endif // PARALLEL==1 -#else // COMPRESSGRIDS==1 - int i=0; //dummy - ADVANCE_POINTERS(mLevel[lev].lSizex*2); -#endif // COMPRESSGRIDS==1 - } // all cell loop k,j,i - - } // main loop region - - // write vars from parallel computations to class - //errMsg("DFINI"," maxr l"<<mMaxRefine<<" cm="<<calcCurrentMass<<" cv="<<calcCurrentVolume ); - mLevel[lev].lmass = calcCurrentMass; - mLevel[lev].lvolume = calcCurrentVolume; - //mCurrentMass += calcCurrentMass; - //mCurrentVolume += calcCurrentVolume; - D::mNumFilledCells = calcCellsFilled; - D::mNumEmptiedCells = calcCellsEmptied; - D::mNumUsedCells = calcNumUsedCells; -#if PARALLEL==1 - //errMsg("PARALLELusqrcheck"," curr: "<<mMaxVlen<<"|"<<mMxvx<<","<<mMxvy<<","<<mMxvz); - for(int i=0; i<MAX_THREADS; i++) { - for(int j=0; j<calcListFull[i].size() ; j++) mListFull.push_back( calcListFull[i][j] ); - for(int j=0; j<calcListEmpty[i].size(); j++) mListEmpty.push_back( calcListEmpty[i][j] ); - if(calcMaxVlen[i]>mMaxVlen) { - mMxvx = calcMxvx[i]; - mMxvy = calcMxvy[i]; - mMxvz = calcMxvz[i]; - mMaxVlen = calcMaxVlen[i]; - } - errMsg("PARALLELusqrcheck"," curr: "<<mMaxVlen<<"|"<<mMxvx<<","<<mMxvy<<","<<mMxvz<< - " calc["<<i<<": "<<calcMaxVlen[i]<<"|"<<calcMxvx[i]<<","<<calcMxvy[i]<<","<<calcMxvz[i]<<"] " ); - } -#endif // PARALLEL==1 - - // check other vars...? -} - -template<class D> -void -LbmFsgrSolver<D>::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<mMaxRefine; lev++) { TEST DEBUG - FSGR_FORIJK_BOUNDS(lev) { - if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { - if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { - LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<D::cDirNum; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& - (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - ) { - totArea += mFsgrCellArea[l]; - } - } // l - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; - //continue; - } else - if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & (CFEmpty|CFUnused)) { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; - //continue; - } else { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; - } - //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); - } - } // } TEST DEBUG - if(!D::mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } -} - -template<class D> -void -LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { -#if FSGR_STRICT_DEBUG==1 - rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG -#endif - pFlagSrc++; - pFlagDst++; - ccel += QCELLSTEP; - tcel += QCELLSTEP; - - // from coarse cells without unused nbs are not necessary...! -> 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 "<<lev<<" "<<PRINT_IJK); -#endif // ELBEEM_BLENDER!=1 - // FIXME add debug check for these types of cells?, move to perform coarsening? - } - } // */ - - //*(pFlagSrc+pFlagTarOff) = *pFlagSrc; // always set other set... -#if FSGR_STRICT_DEBUG==1 - *pFlagDst = *pFlagSrc; // always set other set... -#else - *pFlagDst = (*pFlagSrc & (~CFGrCoarseInited)); // always set other set... , remove coarse inited flag -#endif - - // old INTCFCOARSETEST==1 - if((*pFlagSrc) & CFGrFromCoarse) { // interpolateFineFromCoarse test! - if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } - } else { - interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); - D::mNumUsedCells++; - } - continue; // interpolateFineFromCoarse test! - } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 - - if( ((*pFlagSrc) & (CFFluid)) ) { - ccel = RACPNT(lev, i,j,k ,SRCS(lev)); - tcel = RACPNT(lev, i,j,k ,TSET(lev)); - - if( ((*pFlagSrc) & (CFGrFromFine)) ) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? - continue; // comes from fine grid - } - // also ignore CFGrFromCoarse - else if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? - continue; - } - - OPTIMIZED_STREAMCOLLIDE; - *pFlagDst |= CFNoBndFluid; // test? - calcCurrentVolume += RAC(ccel,dFlux); - calcCurrentMass += RAC(ccel,dFlux)*rho; - //ebugMarkCell(lev+1, 2*i+1,2*j+1,2*k ); -#if FSGR_STRICT_DEBUG==1 - if(rho<-1.0){ debugMarkCell(lev, i,j,k ); - errMsg("INVRHOCELL_CHECK"," l"<<lev<<" "<< PRINT_IJK<<" rho:"<<rho ); - D::mPanic = 1; - } -#endif // FSGR_STRICT_DEBUG==1 - D::mNumUsedCells++; - - } - } - pFlagSrc+=2; // after x - pFlagDst+=2; // after x - ccel += (QCELLSTEP*2); - tcel += (QCELLSTEP*2); - } - pFlagSrc+= mLevel[lev].lSizex*2; // after y - pFlagDst+= mLevel[lev].lSizex*2; // after y - ccel += (QCELLSTEP*mLevel[lev].lSizex*2); - tcel += (QCELLSTEP*mLevel[lev].lSizex*2); - } // all cell loop k,j,i - - - //errMsg("coarseAdvance","level "<<lev<<" stepped from "<<mLevel[lev].setCurr<<" to "<<mLevel[lev].setOther); - if(!D::mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } - // */ - - // update other set - mLevel[lev].setOther = mLevel[lev].setCurr; - mLevel[lev].setCurr ^= 1; - mLevel[lev].lsteps++; - mLevel[lev].lmass = calcCurrentMass * mLevel[lev].lcellfactor; - mLevel[lev].lvolume = calcCurrentVolume * mLevel[lev].lcellfactor; -#ifndef ELBEEM_BLENDER - errMsg("DFINI", " m l"<<lev<<" m="<<mLevel[lev].lmass<<" c="<<calcCurrentMass<<" lcf="<< mLevel[lev].lcellfactor ); - errMsg("DFINI", " v l"<<lev<<" v="<<mLevel[lev].lvolume<<" c="<<calcCurrentVolume<<" lcf="<< mLevel[lev].lcellfactor ); -#endif // ELBEEM_BLENDER -} - -/*****************************************************************************/ -//! multi level functions -/*****************************************************************************/ - - -// get dfs from level (lev+1) to (lev) coarse border nodes -template<class D> -void -LbmFsgrSolver<D>::coarseRestrictFromFine(int lev) -{ - if((lev<0) || ((lev+1)>mMaxRefine)) return; -#if FSGR_STRICT_DEBUG==1 - // reset all unused cell values to invalid - int unuCnt = 0; - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,mLevel[lev].setCurr); - if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { - FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } - unuCnt++; - // set here - } else if( ((*pFlagSrc) & (CFFluid|CFGrNorm)) == (CFFluid|CFGrNorm) ) { - // simulated... - } else { - // reset in interpolation - //errMsg("coarseRestrictFromFine"," reset l"<<lev<<" "<<PRINT_IJK); - } - if( ((*pFlagSrc) & (CFEmpty|CFUnused)) ) { // test, also reset? - FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } - } // test - } } } - errMsg("coarseRestrictFromFine"," reset l"<<lev<<" fluid|coarseBorder cells: "<<unuCnt); -#endif // FSGR_STRICT_DEBUG==1 - const int srcSet = mLevel[lev+1].setCurr; - const int dstSet = mLevel[lev].setCurr; - - LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; - LbmFloat *ccel = NULL; - LbmFloat *tcel = NULL; -#if OPT3D==true - LbmFloat m[LBM_DFNUM]; - // for macro add - LbmFloat usqr; - //LbmFloat *addfcel, *dstcell; - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; - LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; -#else // OPT3D==true - LbmFloat df[LBM_DFNUM]; - LbmFloat omegaDst, omegaSrc; - LbmFloat feq[LBM_DFNUM]; - LbmFloat dfScale = mDfScaleUp; -#endif // OPT3D==true - - LbmFloat mGaussw[27]; - LbmFloat totGaussw = 0.0; - const LbmFloat alpha = 1.0; - const LbmFloat gw = sqrt(2.0*D::cDimension); -#ifndef ELBEEM_BLENDER - errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!"); -#endif - for(int n=0;(n<D::cDirNum); n++) { mGaussw[n] = 0.0; } - //for(int n=0;(n<D::cDirNum); n++) { - for(int n=0;(n<D::cDfNum); n++) { - const LbmFloat d = norm(LbmVec(D::dfVecX[n], D::dfVecY[n], D::dfVecZ[n])); - LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw ); - //errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 cell n"<<n<<" d"<<d<<" w"<<w); - mGaussw[n] = w; - totGaussw += w; - } - for(int n=0;(n<D::cDirNum); n++) { - mGaussw[n] = mGaussw[n]/totGaussw; - } - - //restrict - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,dstSet); - if((*pFlagSrc) & (CFFluid)) { - if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { - // TODO? optimize? - // do resctriction - mNumInterdCells++; - ccel = RACPNT(lev+1, 2*i,2*j,2*k,srcSet); - tcel = RACPNT(lev , i,j,k ,dstSet); - -# if OPT3D==false - // add up weighted dfs - FORDF0{ df[l] = 0.0;} - for(int n=0;(n<D::cDirNum); n++) { - int ni=2*i+1*D::dfVecX[n], nj=2*j+1*D::dfVecY[n], nk=2*k+1*D::dfVecZ[n]; - ccel = RACPNT(lev+1, ni,nj,nk,srcSet);// CFINTTEST - const LbmFloat weight = mGaussw[n]; - FORDF0{ - LbmFloat cdf = weight * RAC(ccel,l); -# if FSGR_STRICT_DEBUG==1 - if( cdf<-1.0 ){ errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]); } -# endif - //errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]<<" = "<<cdf<<" , w"<<weight); - df[l] += cdf; - } - } - - // calc rho etc. from weighted dfs - rho = ux = uy = uz = 0.0; - FORDF0{ - LbmFloat cdf = df[l]; - rho += cdf; - ux += (D::dfDvecX[l]*cdf); - uy += (D::dfDvecY[l]*cdf); - uz += (D::dfDvecZ[l]*cdf); - } - - FORDF0{ feq[l] = D::getCollideEq(l, rho,ux,uy,uz); } - if(mLevel[lev ].lcsmago>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<D::cDirNum); n++) { - ccel = RACPNT(lev+1, 2*i+1*D::dfVecX[n], 2*j+1*D::dfVecY[n], 2*k+1*D::dfVecZ[n] ,srcSet); - MSRC_C += CCELG_C(n) ; - MSRC_N += CCELG_N(n) ; - MSRC_S += CCELG_S(n) ; - MSRC_E += CCELG_E(n) ; - MSRC_W += CCELG_W(n) ; - MSRC_T += CCELG_T(n) ; - MSRC_B += CCELG_B(n) ; - MSRC_NE += CCELG_NE(n); - MSRC_NW += CCELG_NW(n); - MSRC_SE += CCELG_SE(n); - MSRC_SW += CCELG_SW(n); - MSRC_NT += CCELG_NT(n); - MSRC_NB += CCELG_NB(n); - MSRC_ST += CCELG_ST(n); - MSRC_SB += CCELG_SB(n); - MSRC_ET += CCELG_ET(n); - MSRC_EB += CCELG_EB(n); - MSRC_WT += CCELG_WT(n); - MSRC_WB += CCELG_WB(n); - } - rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T - + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT - + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; - ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW - + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB; - uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW - + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB; - uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB - + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB; - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - \ - lcsmeq[dC] = EQC ; \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev+0, MSRC_ )\ - COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ - COLL_CALCULATE_CSMOMEGAVAL(lev+1, lcsmSrcOmega); \ - \ - lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev+1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ - RAC(tcel, dC ) = (lcsmeq[dC ] + (MSRC_C -lcsmeq[dC ] )*lcsmdfscale); - RAC(tcel, dN ) = (lcsmeq[dN ] + (MSRC_N -lcsmeq[dN ] )*lcsmdfscale); - RAC(tcel, dS ) = (lcsmeq[dS ] + (MSRC_S -lcsmeq[dS ] )*lcsmdfscale); - RAC(tcel, dE ) = (lcsmeq[dE ] + (MSRC_E -lcsmeq[dE ] )*lcsmdfscale); - RAC(tcel, dW ) = (lcsmeq[dW ] + (MSRC_W -lcsmeq[dW ] )*lcsmdfscale); - RAC(tcel, dT ) = (lcsmeq[dT ] + (MSRC_T -lcsmeq[dT ] )*lcsmdfscale); - RAC(tcel, dB ) = (lcsmeq[dB ] + (MSRC_B -lcsmeq[dB ] )*lcsmdfscale); - RAC(tcel, dNE) = (lcsmeq[dNE] + (MSRC_NE-lcsmeq[dNE] )*lcsmdfscale); - RAC(tcel, dNW) = (lcsmeq[dNW] + (MSRC_NW-lcsmeq[dNW] )*lcsmdfscale); - RAC(tcel, dSE) = (lcsmeq[dSE] + (MSRC_SE-lcsmeq[dSE] )*lcsmdfscale); - RAC(tcel, dSW) = (lcsmeq[dSW] + (MSRC_SW-lcsmeq[dSW] )*lcsmdfscale); - RAC(tcel, dNT) = (lcsmeq[dNT] + (MSRC_NT-lcsmeq[dNT] )*lcsmdfscale); - RAC(tcel, dNB) = (lcsmeq[dNB] + (MSRC_NB-lcsmeq[dNB] )*lcsmdfscale); - RAC(tcel, dST) = (lcsmeq[dST] + (MSRC_ST-lcsmeq[dST] )*lcsmdfscale); - RAC(tcel, dSB) = (lcsmeq[dSB] + (MSRC_SB-lcsmeq[dSB] )*lcsmdfscale); - RAC(tcel, dET) = (lcsmeq[dET] + (MSRC_ET-lcsmeq[dET] )*lcsmdfscale); - RAC(tcel, dEB) = (lcsmeq[dEB] + (MSRC_EB-lcsmeq[dEB] )*lcsmdfscale); - RAC(tcel, dWT) = (lcsmeq[dWT] + (MSRC_WT-lcsmeq[dWT] )*lcsmdfscale); - RAC(tcel, dWB) = (lcsmeq[dWB] + (MSRC_WB-lcsmeq[dWB] )*lcsmdfscale); -# endif // OPT3D==false - - //? if((lev<mMaxRefine)&&(D::cDimension==2)) { debugMarkCell(lev,i,j,k); } -# if FSGR_STRICT_DEBUG==1 - //errMsg("coarseRestrictFromFine", "CRFF_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" " ); -# endif // FSGR_STRICT_DEBUG==1 - D::mNumUsedCells++; - } // from fine & fluid - else { - if(RFLAG(lev+1, 2*i,2*j,2*k,srcSet) & CFGrFromCoarse) { - RFLAG(lev, i,j,k,dstSet) |= CFGrToFine; - } else { - RFLAG(lev, i,j,k,dstSet) &= (~CFGrToFine); - } - } - } // & fluid - }}} - if(!D::mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } -} - -template<class D> -bool -LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - bool removeFromFine = 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), srcFineSet) & reqType) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & (notAllowed)) ) ){ // ok - } else { - removeFromFine=true; - } - /*if(strstr(D::getName().c_str(),"Debug")) - if(lev+1==mMaxRefine) { // mixborder - for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, srcFineSet)&CFBnd) { // NEWREFT - removeFromFine=true; - } - } - } // FARBORD */ -#elif REFINEMENTBORDER==2 // REFINEMENTBORDER==1 - FIX - for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { - int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT - removeFromFine=true; - } - } - /*for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT - removeFromFine=true; - } - } // FARBORD */ -#elif REFINEMENTBORDER==3 // REFINEMENTBORDER==1 - FIX - if(lev+1==mMaxRefine) { // mixborder - if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)¬SrcAllowed) { - removeFromFine=true; - } - } else { // mixborder - for(int l=0; l<D::cDirNum; l++) { - int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT - removeFromFine=true; - } - } - } // mixborder - // also remove from fine cells that are above from fine -#else // REFINEMENTBORDER==1 - ERROR -#endif // REFINEMENTBORDER==1 - - if(removeFromFine) { - // dont turn CFGrFromFine above interface cells into CFGrNorm - //errMsg("performRefinement","Removing CFGrFromFine on lev"<<lev<<" " <<PRINT_IJK<<" srcflag:"<<convertCellFlagType2String(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet)) <<" set:"<<dstSet ); - RFLAG(lev, i,j,k, dstSet) = CFEmpty; -#if FSGR_STRICT_DEBUG==1 - // for interpolation later on during fine grid fixing - // these cells are still correctly inited - RFLAG(lev, i,j,k, dstSet) |= CFGrCoarseInited; // remove later on? FIXME? -#endif // FSGR_STRICT_DEBUG==1 - //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFEmpty; // FLAGTEST - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); - change=true; - mNumFsgrChanges++; - for(int l=1; l<D::cDirNum; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - //errMsg("performRefinement","On lev:"<<lev<<" check: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet<<" = "<<convertCellFlagType2String(RFLAG(lev, ni,nj,nk, srcSet)) ); - if( ( RFLAG(lev, ni,nj,nk, srcSet)&CFFluid ) && - (!(RFLAG(lev, ni,nj,nk, srcSet)&CFGrFromFine)) ) { // dont change status of nb. from fine cells - // tag as inited for debugging, cell contains fluid DFs anyway - RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromFine|CFGrCoarseInited; - //errMsg("performRefinement","On lev:"<<lev<<" set to from fine: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet); - //if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - } - } // l - - // FIXME fix fine level? - } - - // recheck from fine flag - } - }}} // TEST - - - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST - for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST - for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST - - // test from coarseAdvance - // from coarse cells without unused nbs are not necessary...! -> 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 "<<lev<<" "<<PRINT_IJK); - } - } // */ - - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromCoarse) { - - // from coarse cells without unused nbs are not necessary...! -> remove - bool invNb = false; - bool fluidNb = false; - for(int l=1; l<D::cDirNum; l++) { - if(RFLAG_NB(lev, i, j, k, srcSet, l) & CFUnused) { invNb = true; } - if(RFLAG_NB(lev, i, j, k, srcSet, l) & (CFGrNorm)) { fluidNb = true; } - } - if(!invNb) { - // no unused cells around -> 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"<<lev<<" " <<PRINT_IJK<<" due to finer from coarse cell " ); - RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; - if(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<D::cDirNum; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if(RFLAG(lev, ni,nj,nk, srcSet)&(CFGrNorm)) { //ok - for(int m=1; m<D::cDirNum; m++) { - int mi= ni +D::dfVecX[m], mj= nj +D::dfVecY[m], mk= nk +D::dfVecZ[m]; - if(RFLAG(lev, mi, mj, mk, srcSet)&CFUnused) { - // norm cells in neighborhood with unused nbs have to be new border... - RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromCoarse; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - } - } - // these alreay have valid values... - } - else if(RFLAG(lev, ni,nj,nk, srcSet)&(CFUnused)) { //ok - // this should work because we have a valid neighborhood here for now - interpolateCellFromCoarse(lev, ni, nj, nk, dstSet /*mLevel[lev].setCurr*/, interTime, CFFluid|CFGrFromCoarse, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - mNumFsgrChanges++; - } - } // l - } // double transer - - } // from coarse - - } } } - - - // fix dstSet from fine cells here - // warning - checks CFGrFromFine on dstset changed before! - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST - for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST - for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST - - //if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - if(RFLAG(lev, i,j,k, dstSet) & CFGrFromFine) { - // modify finer level border - if((RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse))) { - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" from l"<<lev<<" " <<PRINT_IJK ); - CellFlagType setf = CFFluid; - if(lev+1 < mMaxRefine) setf = CFFluid|CFGrNorm; - RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; - change=true; - mNumFsgrChanges++; - for(int l=1; l<D::cDirNum; l++) { - int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; - if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFGrFromCoarse)) { - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); - RFLAG(lev+1, bi, bj, bk, srcFineSet) = setf; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); - } - else if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFUnused )) { - //errMsg("performRefinement","Removing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); - interpolateCellFromCoarse(lev+1, bi, bj, bk, srcFineSet, interTime, setf, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); - mNumFsgrChanges++; - } - } - for(int l=1; l<D::cDirNum; l++) { - int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; - if( (RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFFluid ) && - (!(RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFGrFromCoarse)) ) { - // all unused nbs now of coarse have to be from coarse - for(int m=1; m<D::cDirNum; m++) { - int mi= bi +D::dfVecX[m], mj= bj +D::dfVecY[m], mk= bk +D::dfVecZ[m]; - if(RFLAG(lev+1, mi, mj, mk, srcFineSet)&CFUnused) { - //errMsg("performRefinement","Changing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(mi,mj,mk) ); - interpolateCellFromCoarse(lev+1, mi, mj, mk, srcFineSet, interTime, CFFluid|CFGrFromCoarse, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); - mNumFsgrChanges++; - } - } - // nbs prepared... - } - } - } - - } // convert regions of from fine - }}} // TEST - - if(!D::mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } - return change; -} - - -// done after refinement -template<class D> -bool -LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - // from coarse cells without unused nbs are not necessary...! -> 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<D::cDirNum && nbsok; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; - if( (RFLAG(lev+1, ni,nj,nk, dstFineSet) & reqType) && - (!(RFLAG(lev+1, ni,nj,nk, dstFineSet) & (notAllowed)) ) ){ - // ok - } else { - nbsok=false; - } - /*if(strstr(D::getName().c_str(),"Debug")) - if((nbsok)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l<D::cDirNum) && (nbsok)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT - nbsok=false; - } - } - } // FARBORD */ - } - // dont turn CFGrFromFine above interface cells into CFGrNorm - // now check nbs on same level - for(int l=1; l<D::cDirNum && nbsok; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if(RFLAG(lev, ni,nj,nk, srcSet)&(CFFluid)) { //ok - } else { - nbsok = false; - } - } // l - - if(nbsok) { - // conversion to coarse fluid cell - change = true; - mNumFsgrChanges++; - RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrNorm; - // dfs are already ok... - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); - - // only check complete cubes - for(int dx=-1;dx<=1;dx+=2) { - for(int dy=-1;dy<=1;dy+=2) { - for(int dz=-1*(LBMDIM&1);dz<=1*(LBMDIM&1);dz+=2) { // 2d/3d - // check for norm and from coarse, as the coarse level might just have been refined... - /*if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subc check "<< "x"<<convertCellFlagType2String( RFLAG(lev, i+dx, j , k , srcSet))<<" " - "y"<<convertCellFlagType2String( RFLAG(lev, i , j+dy, k , srcSet))<<" " "z"<<convertCellFlagType2String( RFLAG(lev, i , j , k+dz, srcSet))<<" " - "xy"<<convertCellFlagType2String( RFLAG(lev, i+dx, j+dy, k , srcSet))<<" " "xz"<<convertCellFlagType2String( RFLAG(lev, i+dx, j , k+dz, srcSet))<<" " - "yz"<<convertCellFlagType2String( RFLAG(lev, i , j+dy, k+dz, srcSet))<<" " "xyz"<<convertCellFlagType2String( RFLAG(lev, i+dx, j+dy, k+dz, srcSet))<<" " ); // */ - if( - // we now the flag of the current cell! ( RFLAG(lev, i , j , k , srcSet)&(CFGrNorm)) && - ( RFLAG(lev, i+dx, j , k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - - ( RFLAG(lev, i+dx, j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i+dx, j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i+dx, j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) - ) { - // middle source node on higher level - int dstx = (2*i)+dx; - int dsty = (2*j)+dy; - int dstz = (2*k)+dz; - - mNumFsgrChanges++; - RFLAG(dstlev, dstx,dsty,dstz, dstFineSet) = CFUnused; - RFLAG(dstlev, dstx,dsty,dstz, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); - - for(int l=1; l<D::cDirNum; l++) { - int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; - if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFFluid)) { - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; - } - if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFInter)) { - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); - D::mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; - } - } // l - - // again check nb flags of all surrounding cells to see if any from coarse - // can be convted to unused - for(int l=1; l<D::cDirNum; l++) { - int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; - // have to be at least from coarse here... - //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" "<< convertCellFlagType2String(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)) ); - if(!(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFUnused) )) { - bool delok = true; - // careful long range here... check domain bounds? - for(int m=1; m<D::cDirNum; m++) { - int chkni=dstni+D::dfVecX[m], chknj=dstnj+D::dfVecY[m], chknk=dstnk+D::dfVecZ[m]; - if(RFLAG(dstlev, chkni,chknj,chknk, dstFineSet)&(CFUnused|CFGrFromCoarse)) { - // this nb cell is ok for deletion - } else { - delok=false; // keep it! - } - //errMsg("performCoarsening"," CHECK "<<PRINT_VEC(dstni,dstnj,dstnk)<<" to "<<PRINT_VEC( chkni,chknj,chknk )<<" f:"<< convertCellFlagType2String( RFLAG(dstlev, chkni,chknj,chknk, dstFineSet))<<" nbsok"<<delok ); - } - //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" ok"<<delok ); - if(delok) { - mNumFsgrChanges++; - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFUnused; - RFLAG(dstlev, dstni,dstnj,dstnk, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); - } - } - } // l - // treat subcube - //ebugMarkCell(lev,i+dx,j+dy,k+dz); - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); - } - } } } - - } // ? - } // convert regions of from fine - }}} // TEST! - - // reinit cell area value - /*if( RFLAG(lev, i,j,k,srcSet) & CFFluid) { - if( RFLAG(lev+1, i*2,j*2,k*2,dstFineSet) & CFGrFromCoarse) { - LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<D::cDirNum; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)& - (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - ) { - //LbmFloat area = 0.25; if(D::dfVecX[l]!=0) area *= 0.5; if(D::dfVecY[l]!=0) area *= 0.5; if(D::dfVecZ[l]!=0) area *= 0.5; - totArea += mFsgrCellArea[l]; - } - } // l - QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = - QCELL(lev, i,j,k,srcSet, dFlux) = totArea; - } else { - QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = - QCELL(lev, i,j,k,srcSet, dFlux) = 1.0; - } - //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,srcSet, dFlux) ); - } - // */ - - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - - if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { - // check empty -> 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<D::cDirNum) && (changeToFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT - changeToFromFine=false; - } - } - }// FARBORD */ -#elif REFINEMENTBORDER==2 // 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; - for(int l=0; ((l<D::cDirNum)&&(changeToFromFine)); l++) { - int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT - changeToFromFine=false; - } - } - /*for(int l=0; ((l<D::cDirNum)&&(changeToFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT - changeToFromFine=false; - } - } // FARBORD*/ - } -#elif REFINEMENTBORDER==3 // REFINEMENTBORDER==3 - FIX!!! - if(lev+1==mMaxRefine) { // mixborder - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (CFFluid|CFInter)) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ - changeToFromFine=true; - } - } else { - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (CFFluid)) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ - changeToFromFine=true; - for(int l=0; l<D::cDirNum; l++) { - int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT - changeToFromFine=false; - } - } - } } // mixborder -#else // REFINEMENTBORDER==3 - ERROR -#endif // REFINEMENTBORDER==1 - if(changeToFromFine) { - change = true; - mNumFsgrChanges++; - RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); - // same as restr from fine func! not necessary ?! - // coarseRestrictFromFine part */ - } - } // only check empty cells - - }}} // TEST! - - if(!D::mSilent){ errMsg("performCoarsening"," for l"<<lev<<" done " ); } - return change; -} - - -/*****************************************************************************/ -/*! perform a single LBM step */ -/*****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::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(nextmax<allowMax*fac) { - newdt = D::mpParam->getStepTime() / fac; - } - } // newtr - //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<fac<<" simmaxv="<< D::mpParam->getSimulationMaxSpeed() ); - - bool minCutoff = false; - LbmFloat desireddt = newdt; - if(newdt>D::mpParam->getMaxStepTime()){ newdt = D::mpParam->getMaxStepTime(); } - if(newdt<D::mpParam->getMinStepTime()){ - newdt = D::mpParam->getMinStepTime(); - if(nextmax>allowMax/fac){ minCutoff=true; } // only if really large vels... - } - - LbmFloat dtdiff = fabs(newdt - D::mpParam->getStepTime()); - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<D::mpParam->getMaxStepTime()<<" min"<<D::mpParam->getMinStepTime()<<" diff"<<dtdiff<< - " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxStepTime)<<" maxsteps:"<<(mSimulationTime/mMinStepTime) , 10); } - - // in range, and more than X% change? - //if( newdt < D::mpParam->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... "<<mTimestepReduceLock<<" ",10); - debMsgDirect("D"); - } else { - D::mpParam->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="<<newdt<<" old="<<D::mpParam->getStepTime()<<" maxSpeed:"<<D::mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<D::mStepCnt, 10 ); - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< - "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10); - } - } // really change dt - } - - if(mTimestepReduceLock>0) mTimestepReduceLock--; - - - /* - // forced back and forth switchting (for testing) - const int tadtogInter = 300; - const double tadtogSwitch = 0.66; - errMsg("TIMESWITCHTOGGLETEST","warning enabled "<< tadtogSwitch<<","<<tadtogSwitch<<" !!!!!!!!!!!!!!!!!!!"); - if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || - ((D::mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ - rescale = true; minCutoff = false; - newdt = tadtogSwitch * D::mpParam->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()<mMinStepTime) mMinStepTime = D::mpParam->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: "<<lev<<" Timestep change: "<< - " scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10); - } - if(lev!=mMaxRefine) coarseCalculateFluxareas(lev); - - int wss = 0, wse = 1; - // FIXME always currset!? - wss = wse = mLevel[lev].setCurr; - for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT - // warning - check sets for higher levels...? - FSGR_FORIJK1(lev) { - 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 rhoOld; - LbmVec velOld; - LbmFloat rho, ux,uy,uz; - rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l<D::cDfNum; l++) { - LbmFloat m = QCELL(lev, i, j, k, workSet, l); - rho += m; - ux += (D::dfDvecX[l]*m); - uy += (D::dfDvecY[l]*m); - uz += (D::dfDvecZ[l]*m); - } - rhoOld = rho; - velOld = LbmVec(ux,uy,uz); - - LbmFloat rhoNew = (rhoOld-rhoAvg)*scaleFac +rhoAvg; - LbmVec velNew = velOld * scaleFac; - - LbmFloat df[LBM_DFNUM]; - LbmFloat feqOld[LBM_DFNUM]; - LbmFloat feqNew[LBM_DFNUM]; - for(int l=0; l<D::cDfNum; l++) { - feqOld[l] = D::getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); - feqNew[l] = D::getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); - df[l] = QCELL(lev, i,j,k,workSet, l); - } - const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feqOld); - const LbmFloat oldOmega = D::getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); - const LbmFloat newOmega = D::getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); - //newOmega = mLevel[lev].omega; // FIXME debug test - - //LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); - const LbmFloat dfScale = (newSteptime/newOmega)/(levOldStepsize[lev]/oldOmega); - //dfScale = dfScaleFac/newOmega; - - for(int l=0; l<D::cDfNum; l++) { - // org scaling - //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important - // new scaling - LbmFloat dfn = feqNew[l] + (df[l]-feqOld[l])*dfScale*feqNew[l]/feqOld[l]; // non-eq. scaling, important - //df = eqNew + (df-eqOld)*dfScale; // modified ig scaling, no real difference? - QCELL(lev, i,j,k,workSet, l) = dfn; - } - - if(RFLAG(lev,i,j,k, workSet) & CFInter) { - //if(workSet==mLevel[lev].setCurr) - LbmFloat area = 1.0; - if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux); - massTOld += QCELL(lev, i,j,k,workSet, dMass) * area; - volTOld += QCELL(lev, i,j,k,workSet, dFfrac); - - // wrong... QCELL(i,j,k,workSet, dMass] = (QCELL(i,j,k,workSet, dFfrac]*rhoNew); - QCELL(lev, i,j,k,workSet, dMass) = (QCELL(lev, i,j,k,workSet, dMass)/rhoOld*rhoNew); - QCELL(lev, i,j,k,workSet, dFfrac) = (QCELL(lev, i,j,k,workSet, dMass)/rhoNew); - - //if(workSet==mLevel[lev].setCurr) - massTNew += QCELL(lev, i,j,k,workSet, dMass); - volTNew += QCELL(lev, i,j,k,workSet, dFfrac); - } - if(RFLAG(lev,i,j,k, workSet) & CFFluid) { // DEBUG - if(RFLAG(lev,i,j,k, workSet) & (CFGrFromFine|CFGrFromCoarse)) { // DEBUG - // dont include - } else { - LbmFloat area = 1.0; - if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux) * mLevel[lev].lcellfactor; - //if(workSet==mLevel[lev].setCurr) - massTOld += rhoOld*area; - //if(workSet==mLevel[lev].setCurr) - massTNew += rhoNew*area; - volTOld += area; - volTNew += area; - } - } - - } // IJK - } // workSet - - } // lev - - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<D::mStepCnt<< - " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxStepTime<< - " mindt"<<mMinStepTime<<" currdt"<<mLevel[mMaxRefine].stepsize, 10); - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE masst:"<<massTNew<<","<<massTOld<<" org:"<<mCurrentMass<<"; "<< - " volt:"<<volTNew<<","<<volTOld<<" org:"<<mCurrentVolume, 10); - } else { - debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep change by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt - <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<D::mOmega<<" gStar:"<<D::mpParam->getCurrentGStar() , 10); - } - } // rescale? - - //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG - if(minCutoff) { - errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<D::mName<<" step:"<<D::mStepCnt<<" newdt="<<desireddt<<" mindt="<<D::mpParam->getMinStepTime()<<") " ); - //brute force resacle all the time? - - for(int lev=mMaxRefine; lev>=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<D::cDfNum; l++) { - LbmFloat m = QCELL(lev, i, j, k, workSet, l); - rho += m; - ux += (D::dfDvecX[l]*m); - uy += (D::dfDvecY[l]*m); - uz += (D::dfDvecZ[l]*m); - } -#ifndef WIN32 - if (!finite(rho)) { - errMsg("adaptTimestep","Brute force non-finite rho at"<<PRINT_IJK); // DEBUG! - rho = 1.0; - ux = uy = uz = 0.0; - QCELL(lev, i, j, k, workSet, dMass) = 1.0; - QCELL(lev, i, j, k, workSet, dFfrac) = 1.0; - } -#endif // WIN32 - - if( (ux*ux+uy*uy+uz*uz)> (allowMax*allowMax) ) { - LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); - ux *= cfac; - uy *= cfac; - uz *= cfac; - for(int l=0; l<D::cDfNum; l++) { - QCELL(lev, i, j, k, workSet, l) = D::getCollideEq(l, rho, ux,uy,uz); } - rescs++; - debMsgDirect("B"); - } - - } } - //if(rescs>0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } - debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"<<lev<<" rescs:"<<rescs, 1); - //TTT mNumProblems += rescs; // add to problem display... - } // lev,set,ijk - - } // try brute force rescale? - - // time adap done... -} - - - - -/****************************************************************************** - * work on lists from updateCellMass to reinit cell flags - *****************************************************************************/ - -template<class D> -LbmFloat -LbmFsgrSolver<D>::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; - } else { - // backward for emptying - if(scal>-LBM_EPSILON) ret = 0.0; - else ret = scal * -1.0; - } - //errMsg("massd", PRINT_IJK<<" nv"<<nvel<<" : ret="<<ret ); //xit(1); //VECDEB - return ret; -} - -template<class D> -void LbmFsgrSolver<D>::addToNewInterList( int ni, int nj, int nk ) { -#if FSGR_STRICT_DEBUG==10 - // dangerous, this can change the simulation... - /*for( vector<LbmPoint>::iterator iter=mListNewInter.begin(); - iter != mListNewInter.end(); iter++ ) { - if(ni!=iter->x) continue; - if(nj!=iter->y) continue; - if(nk!=iter->z) continue; - // all 3 values match... skip point - return; - } */ -#endif // FSGR_STRICT_DEBUG==1 - // store point - LbmPoint newinter; - newinter.x = ni; newinter.y = nj; newinter.z = nk; - mListNewInter.push_back(newinter); -} - - -// 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)<<" "<<PRINT_VEC((ai),(aj),(ak))<<" fc:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )<<" fo:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )<<" dfl"<<l ); \ - debugMarkCell((alev), (ai),(aj),(ak));\ - D::mPanic = 1; \ - } - // end ADD_INT_DFSCHECK -#define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) \ - if( (((1.0-(at))>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)<<" "<<PRINT_VEC((ai),(aj),(ak))<<\ - " fc:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )) <<\ - " fold:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )) ); \ - debugMarkCell((alev), (ai),(aj),(ak));\ - D::mPanic = 1; \ - } - // end ADD_INT_DFSCHECK - - //if( !(RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) & CFUnused) ){ - //errMsg("INTFLAGUNU", PRINT_VEC(i,j,k)<<" child at "<<PRINT_VEC((ix),(iy),(iz)) ); - //if(iy==15) errMsg("IFFC", PRINT_VEC(i,j,k)<<" child interpolated at "<<PRINT_VEC((ix),(iy),(iz)) ); - //if(((ix)>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)<<" "<<PRINT_VEC((ix),(iy),(iz))<<" flag: "<< RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) ); \ - debugMarkCell((lev+1), (ix),(iy),(iz));\ - D::mPanic = 1; \ - }\ - RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) |= CFGrCoarseInited; \ - // INTUNUTCHECK -#define INTSTRICTCHECK(ix,iy,iz,caseId) \ - if( QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) <= 0.0 ){\ - errMsg("INVDFCCELLCHECK", "caseId:"<<caseId<<" "<<PRINT_VEC(i,j,k)<<" child inter at "<<PRINT_VEC((ix),(iy),(iz))<<" invalid df "<<l<<" = "<< QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) ); \ - debugMarkCell((lev+1), (ix),(iy),(iz));\ - D::mPanic = 1; \ - }\ - // INTSTRICTCHECK - -#else// FSGR_STRICT_DEBUG==1 -#define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) -#define ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l) -#define INTSTRICTCHECK(x,y,z,caseId) -#define INTUNUTCHECK(ix,iy,iz) -#endif// FSGR_STRICT_DEBUG==1 - - -#if FSGR_STRICT_DEBUG==1 -#define INTDEBOUT \ - { /*LbmFloat rho,ux,uy,uz;*/ \ - rho = ux=uy=uz=0.0; \ - FORDF0{ LbmFloat m = QCELL(lev,i,j,k, dstSet, l); \ - rho += m; ux += (D::dfDvecX[l]*m); uy += (D::dfDvecY[l]*m); uz += (D::dfDvecZ[l]*m); \ - if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m ); D::mPanic=1; }\ - /*errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" df"<<l<<":"<<m );*/ \ - } \ - /*if(D::mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \ - if(markNbs) errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); \ - /*errMsg("interpolateCellFromCoarse", "ICFC_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); */\ - } \ - /* both cases are ok to interpolate */ \ - if( (!(RFLAG(lev,i,j,k, dstSet) & CFGrFromCoarse)) && \ - (!(RFLAG(lev,i,j,k, dstSet) & CFUnused)) ) { \ - /* might also have CFGrCoarseInited (shouldnt be a problem here)*/ \ - errMsg("interpolateCellFromCoarse", "CHECK cell not CFGrFromCoarse? "<<PRINT_IJK<<" flag:"<< RFLAG(lev,i,j,k, dstSet)<<" fstr:"<<convertCellFlagType2String( RFLAG(lev,i,j,k, dstSet) )); \ - /* FIXME check this warning...? return; this can happen !? */ \ - /*D::mPanic = 1;*/ \ - } \ - // end INTDEBOUT -#else // FSGR_STRICT_DEBUG==1 -#define INTDEBOUT -#endif // FSGR_STRICT_DEBUG==1 - - -// t=0.0 -> 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"<<mDfScaleDown<<" n"<<dfScale<<" qc"<< QCELL(lev,i,j,k, dstSet, l)<<" idf"<<intDf[l]<<" eq"<<feq[l] ); */ \ - QCELL(lev,i,j,k, dstSet, l) = (feq[l]+ (intDf[l]-feq[l])*dfScale);\ - } \ - /* check that all values are ok */ \ - INTDEBOUT - -#else //OPT3D==false - -#define ADDALLVALS \ - addVal = addDfFacT * RAC(addfcel , dC ); \ - intDf[dC ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dN ); \ - uy+=addVal; intDf[dN ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dS ); \ - uy-=addVal; intDf[dS ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dE ); \ - ux+=addVal; intDf[dE ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dW ); \ - ux-=addVal; intDf[dW ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dT ); \ - uz+=addVal; intDf[dT ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dB ); \ - uz-=addVal; intDf[dB ] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dNE); \ - ux+=addVal; uy+=addVal; intDf[dNE] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dNW); \ - ux-=addVal; uy+=addVal; intDf[dNW] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dSE); \ - ux+=addVal; uy-=addVal; intDf[dSE] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dSW); \ - ux-=addVal; uy-=addVal; intDf[dSW] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dNT); \ - uy+=addVal; uz+=addVal; intDf[dNT] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dNB); \ - uy+=addVal; uz-=addVal; intDf[dNB] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dST); \ - uy-=addVal; uz+=addVal; intDf[dST] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dSB); \ - uy-=addVal; uz-=addVal; intDf[dSB] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dET); \ - ux+=addVal; uz+=addVal; intDf[dET] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dEB); \ - ux+=addVal; uz-=addVal; intDf[dEB] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dWT); \ - ux-=addVal; uz+=addVal; intDf[dWT] += addVal; rho += addVal; \ - addVal = addDfFacT * RAC(addfcel , dWB); \ - ux-=addVal; uz-=addVal; intDf[dWB] += addVal; rho += addVal; - -#define ADD_INT_DFS(alev, ai,aj,ak, at, afac) \ - addDfFacT = at*afac; \ - addfcel = RACPNT((alev), (ai),(aj),(ak),mLevel[(alev)].setOther); \ - ADDALLVALS\ - addDfFacT = (1.0-at)*afac; \ - addfcel = RACPNT((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr); \ - ADDALLVALS - -// also ugly... -#define INTDF_C intDf[dC ] -#define INTDF_N intDf[dN ] -#define INTDF_S intDf[dS ] -#define INTDF_E intDf[dE ] -#define INTDF_W intDf[dW ] -#define INTDF_T intDf[dT ] -#define INTDF_B intDf[dB ] -#define INTDF_NE intDf[dNE] -#define INTDF_NW intDf[dNW] -#define INTDF_SE intDf[dSE] -#define INTDF_SW intDf[dSW] -#define INTDF_NT intDf[dNT] -#define INTDF_NB intDf[dNB] -#define INTDF_ST intDf[dST] -#define INTDF_SB intDf[dSB] -#define INTDF_ET intDf[dET] -#define INTDF_EB intDf[dEB] -#define INTDF_WT intDf[dWT] -#define INTDF_WB intDf[dWB] - - -// write interpolated dfs back to cell (correct non-eq. parts) -#define IDF_WRITEBACK_LES \ - dstcell = RACPNT(lev, i,j,k,dstSet); \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - \ - lcsmeq[dC] = EQC ; \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev, INTDF_ )\ - COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ - COLL_CALCULATE_CSMOMEGAVAL(lev-1, lcsmSrcOmega); \ - \ - lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ - RAC(dstcell, dC ) = (lcsmeq[dC ] + (intDf[dC ]-lcsmeq[dC ] )*lcsmdfscale);\ - RAC(dstcell, dN ) = (lcsmeq[dN ] + (intDf[dN ]-lcsmeq[dN ] )*lcsmdfscale);\ - RAC(dstcell, dS ) = (lcsmeq[dS ] + (intDf[dS ]-lcsmeq[dS ] )*lcsmdfscale);\ - RAC(dstcell, dE ) = (lcsmeq[dE ] + (intDf[dE ]-lcsmeq[dE ] )*lcsmdfscale);\ - RAC(dstcell, dW ) = (lcsmeq[dW ] + (intDf[dW ]-lcsmeq[dW ] )*lcsmdfscale);\ - RAC(dstcell, dT ) = (lcsmeq[dT ] + (intDf[dT ]-lcsmeq[dT ] )*lcsmdfscale);\ - RAC(dstcell, dB ) = (lcsmeq[dB ] + (intDf[dB ]-lcsmeq[dB ] )*lcsmdfscale);\ - RAC(dstcell, dNE) = (lcsmeq[dNE] + (intDf[dNE]-lcsmeq[dNE] )*lcsmdfscale);\ - RAC(dstcell, dNW) = (lcsmeq[dNW] + (intDf[dNW]-lcsmeq[dNW] )*lcsmdfscale);\ - RAC(dstcell, dSE) = (lcsmeq[dSE] + (intDf[dSE]-lcsmeq[dSE] )*lcsmdfscale);\ - RAC(dstcell, dSW) = (lcsmeq[dSW] + (intDf[dSW]-lcsmeq[dSW] )*lcsmdfscale);\ - RAC(dstcell, dNT) = (lcsmeq[dNT] + (intDf[dNT]-lcsmeq[dNT] )*lcsmdfscale);\ - RAC(dstcell, dNB) = (lcsmeq[dNB] + (intDf[dNB]-lcsmeq[dNB] )*lcsmdfscale);\ - RAC(dstcell, dST) = (lcsmeq[dST] + (intDf[dST]-lcsmeq[dST] )*lcsmdfscale);\ - RAC(dstcell, dSB) = (lcsmeq[dSB] + (intDf[dSB]-lcsmeq[dSB] )*lcsmdfscale);\ - RAC(dstcell, dET) = (lcsmeq[dET] + (intDf[dET]-lcsmeq[dET] )*lcsmdfscale);\ - RAC(dstcell, dEB) = (lcsmeq[dEB] + (intDf[dEB]-lcsmeq[dEB] )*lcsmdfscale);\ - RAC(dstcell, dWT) = (lcsmeq[dWT] + (intDf[dWT]-lcsmeq[dWT] )*lcsmdfscale);\ - RAC(dstcell, dWB) = (lcsmeq[dWB] + (intDf[dWB]-lcsmeq[dWB] )*lcsmdfscale);\ - /* IDF_WRITEBACK optimized */ - -#define IDF_WRITEBACK_NOLES \ - dstcell = RACPNT(lev, i,j,k,dstSet); \ - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - \ - RAC(dstcell, dC ) = (EQC + (intDf[dC ]-EQC )*mDfScaleDown);\ - RAC(dstcell, dN ) = (EQN + (intDf[dN ]-EQN )*mDfScaleDown);\ - RAC(dstcell, dS ) = (EQS + (intDf[dS ]-EQS )*mDfScaleDown);\ - /*old*/ RAC(dstcell, dE ) = (EQE + (intDf[dE ]-EQE )*mDfScaleDown);\ - RAC(dstcell, dW ) = (EQW + (intDf[dW ]-EQW )*mDfScaleDown);\ - RAC(dstcell, dT ) = (EQT + (intDf[dT ]-EQT )*mDfScaleDown);\ - RAC(dstcell, dB ) = (EQB + (intDf[dB ]-EQB )*mDfScaleDown);\ - /*old*/ RAC(dstcell, dNE) = (EQNE + (intDf[dNE]-EQNE )*mDfScaleDown);\ - RAC(dstcell, dNW) = (EQNW + (intDf[dNW]-EQNW )*mDfScaleDown);\ - RAC(dstcell, dSE) = (EQSE + (intDf[dSE]-EQSE )*mDfScaleDown);\ - RAC(dstcell, dSW) = (EQSW + (intDf[dSW]-EQSW )*mDfScaleDown);\ - RAC(dstcell, dNT) = (EQNT + (intDf[dNT]-EQNT )*mDfScaleDown);\ - RAC(dstcell, dNB) = (EQNB + (intDf[dNB]-EQNB )*mDfScaleDown);\ - RAC(dstcell, dST) = (EQST + (intDf[dST]-EQST )*mDfScaleDown);\ - RAC(dstcell, dSB) = (EQSB + (intDf[dSB]-EQSB )*mDfScaleDown);\ - RAC(dstcell, dET) = (EQET + (intDf[dET]-EQET )*mDfScaleDown);\ - /*old*/ RAC(dstcell, dEB) = (EQEB + (intDf[dEB]-EQEB )*mDfScaleDown);\ - RAC(dstcell, dWT) = (EQWT + (intDf[dWT]-EQWT )*mDfScaleDown);\ - RAC(dstcell, dWB) = (EQWB + (intDf[dWB]-EQWB )*mDfScaleDown);\ - /* IDF_WRITEBACK optimized */ - -#if USE_LES==1 -#define IDF_WRITEBACK IDF_WRITEBACK_LES -#else -#define IDF_WRITEBACK IDF_WRITEBACK_NOLES -#endif - -#endif// OPT3D==false - -template<class D> -void LbmFsgrSolver<D>::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"<<lev<<" "<<PRINT_VEC(i,j,k)<<" s"<<dstSet<<" t"<<t); //xit(1); // DEBUG quit - - LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; - //LbmFloat intDf[LBM_DFNUM]; - // warning only q19 and below! - LbmFloat intDf[19] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; - -#if OPT3D==true - // for macro add - LbmFloat addDfFacT, addVal, usqr; - LbmFloat *addfcel, *dstcell; - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; - LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; -#endif // OPT3D==true - - // SET required nbs to from coarse (this might overwrite flag several times) - // this is not necessary for interpolateFineFromCoarse - if(markNbs) { - FORDF1{ - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if(RFLAG(lev,ni,nj,nk,dstSet)&CFUnused) { - // parents have to be inited! - interpolateCellFromCoarse(lev, ni, nj, nk, dstSet, t, CFFluid|CFGrFromCoarse, false); - } - } } - - // change flag of cell to be interpolated - RFLAG(lev,i,j,k, dstSet) = flagSet; - mNumInterdCells++; - - // interpolation lines... - int betx = i&1; - int bety = j&1; - int betz = k&1; - - if((!betx) && (!bety) && (!betz)) { - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2 , 0.0, 1.0); - - IDF_WRITEBACK; - return; - } - - if(( betx) && (!bety) && (!betz)) { - //if((i==19)&&(j==14)&&(D::cDimension==2)) { debugMarkCell(lev,i,j,k); debugMarkCell(lev-1, (i/2)-1, (j/2) , (k/2) ); debugMarkCell(lev-1, (i/2) , (j/2) , (k/2) ); debugMarkCell(lev-1, (i/2)+1, (j/2) , (k/2) ); debugMarkCell(lev-1, (i/2)+2, (j/2) , (k/2) ); } -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D1); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2) , t, WO2D1_1); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2) , t, WO2D1_9); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2) , t, WO2D1_9); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2) , t, WO2D1_1); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if((!betx) && ( bety) && (!betz)) { - //if((i==4)&&(j==9)&&(D::cDimension==2)) { debugMarkCell(lev,i,j,k); debugMarkCell(lev-1, (i/2), (j/2)-1 , (k/2) ); debugMarkCell(lev-1, (i/2), (j/2) , (k/2) ); debugMarkCell(lev-1, (i/2), (j/2)+1 , (k/2) ); debugMarkCell(lev-1, (i/2), (j/2)+2 , (k/2) ); } -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D1); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2), (j/2)-1 , (k/2) , t, WO2D1_1); - ADD_INT_DFS(lev-1, (i/2), (j/2) , (k/2) , t, WO2D1_9); - ADD_INT_DFS(lev-1, (i/2), (j/2)+1 , (k/2) , t, WO2D1_9); - ADD_INT_DFS(lev-1, (i/2), (j/2)+2 , (k/2) , t, WO2D1_1); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if((!betx) && (!bety) && ( betz)) { -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D1); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2-1, t, WO2D1_1); - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2 , t, WO2D1_9); - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2+1, t, WO2D1_9); - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2+2, t, WO2D1_1); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if(( betx) && ( bety) && (!betz)) { -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D2); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)-1 , (k/2) , t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+1 , (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+2 , (k/2) , t, WO2D2_11); - - ADD_INT_DFS(lev-1, (i/2) , (j/2)-1 , (k/2) , t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+1 , (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+2 , (k/2) , t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)-1 , (k/2) , t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+1 , (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+2 , (k/2) , t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)-1 , (k/2) , t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+1 , (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+2 , (k/2) , t, WO2D2_11); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if((!betx) && ( bety) && ( betz)) { -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D2); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2), (j/2)-1, (k/2)-1, t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2), (j/2)-1, (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2), (j/2)-1, (k/2)+1, t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2), (j/2)-1, (k/2)+2, t, WO2D2_11); - - ADD_INT_DFS(lev-1, (i/2), (j/2) , (k/2)-1, t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2), (j/2) , (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2), (j/2) , (k/2)+1, t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2), (j/2) , (k/2)+2, t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2), (j/2)+1, (k/2)-1, t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2), (j/2)+1, (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2), (j/2)+1, (k/2)+1, t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2), (j/2)+1, (k/2)+2, t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2), (j/2)+2, (k/2)-1, t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2), (j/2)+2, (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2), (j/2)+2, (k/2)+1, t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2), (j/2)+2, (k/2)+2, t, WO2D2_11); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if(( betx) && (!bety) && ( betz)) { -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D2); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2)-1, (j/2), (k/2)-1, t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2), (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2), (k/2)+1, t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2), (k/2)+2, t, WO2D2_11); - - ADD_INT_DFS(lev-1, (i/2) , (j/2), (k/2)-1, t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2) , (j/2), (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2) , (j/2), (k/2)+1, t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2) , (j/2), (k/2)+2, t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2), (k/2)-1, t, WO2D2_19); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2), (k/2) , t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2), (k/2)+1, t, WO2D2_99); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2), (k/2)+2, t, WO2D2_19); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2), (k/2)-1, t, WO2D2_11); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2), (k/2) , t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2), (k/2)+1, t, WO2D2_91); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2), (k/2)+2, t, WO2D2_11); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - if(( betx) && ( bety) && ( betz)) { -#if INTORDER==1 - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2)+1, t, WO1D3); -#else // INTORDER==1 - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)-1 , (k/2)-1, t, WO2D3_111); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2)-1, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+1 , (k/2)-1, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+2 , (k/2)-1, t, WO2D3_111); - - ADD_INT_DFS(lev-1, (i/2) , (j/2)-1 , (k/2)-1, t, WO2D3_191); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2)-1, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+1 , (k/2)-1, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+2 , (k/2)-1, t, WO2D3_191); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)-1 , (k/2)-1, t, WO2D3_191); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2)-1, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+1 , (k/2)-1, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+2 , (k/2)-1, t, WO2D3_191); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)-1 , (k/2)-1, t, WO2D3_111); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2)-1, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+1 , (k/2)-1, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+2 , (k/2)-1, t, WO2D3_111); - - - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)-1 , (k/2) , t, WO2D3_119); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2) , t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+1 , (k/2) , t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+2 , (k/2) , t, WO2D3_119); - - ADD_INT_DFS(lev-1, (i/2) , (j/2)-1 , (k/2) , t, WO2D3_199); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2) , t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+1 , (k/2) , t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+2 , (k/2) , t, WO2D3_199); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)-1 , (k/2) , t, WO2D3_199); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2) , t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+1 , (k/2) , t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+2 , (k/2) , t, WO2D3_199); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)-1 , (k/2) , t, WO2D3_119); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2) , t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+1 , (k/2) , t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+2 , (k/2) , t, WO2D3_119); - - - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)-1 , (k/2)+1, t, WO2D3_119); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2)+1, t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+1 , (k/2)+1, t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+2 , (k/2)+1, t, WO2D3_119); - - ADD_INT_DFS(lev-1, (i/2) , (j/2)-1 , (k/2)+1, t, WO2D3_199); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2)+1, t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+1 , (k/2)+1, t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+2 , (k/2)+1, t, WO2D3_199); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)-1 , (k/2)+1, t, WO2D3_199); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2)+1, t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+1 , (k/2)+1, t, WO2D3_999); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+2 , (k/2)+1, t, WO2D3_199); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)-1 , (k/2)+1, t, WO2D3_119); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2)+1, t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+1 , (k/2)+1, t, WO2D3_919); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+2 , (k/2)+1, t, WO2D3_119); - - - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)-1 , (k/2)+2, t, WO2D3_111); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2) , (k/2)+2, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+1 , (k/2)+2, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)-1, (j/2)+2 , (k/2)+2, t, WO2D3_111); - - ADD_INT_DFS(lev-1, (i/2) , (j/2)-1 , (k/2)+2, t, WO2D3_191); - ADD_INT_DFS(lev-1, (i/2) , (j/2) , (k/2)+2, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+1 , (k/2)+2, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2) , (j/2)+2 , (k/2)+2, t, WO2D3_191); - - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)-1 , (k/2)+2, t, WO2D3_191); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2) , (k/2)+2, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+1 , (k/2)+2, t, WO2D3_991); - ADD_INT_DFS(lev-1, (i/2)+1, (j/2)+2 , (k/2)+2, t, WO2D3_191); - - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)-1 , (k/2)+2, t, WO2D3_111); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2) , (k/2)+2, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+1 , (k/2)+2, t, WO2D3_911); - ADD_INT_DFS(lev-1, (i/2)+2, (j/2)+2 , (k/2)+2, t, WO2D3_111); -#endif // INTORDER==1 - IDF_WRITEBACK; - return; - } - - D::mPanic=1; - errFatal("interpolateCellFromCoarse","Invalid!?", SIMWORLD_GENERICERROR); -} - -template<class D> -void LbmFsgrSolver<D>::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<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); // DEBUG SYMM - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev, ni,nj,nk, workSet) & CFEmpty ){ - // new and empty interface cell, dont change old flag here! - addToNewInterList(ni,nj,nk); - - // preinit speed, get from average surrounding cells - // interpolate from non-workset to workset, sets are handled in function - { - // WARNING - other i,j,k than filling cell! - int ei=ni; int ej=nj; int ek=nk; - LbmFloat avgrho = 0.0; - LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; - LbmFloat cellcnt = 0.0; - LbmFloat avgnbdf[LBM_DFNUM]; - FORDF0M { avgnbdf[m]= 0.0; } - - for(int nbl=1; nbl< D::cDfNum ; ++nbl) { - if( (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFFluid) || - ((!(RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) && - (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFInter) )) { - cellcnt += 1.0; - for(int rl=0; rl< D::cDfNum ; ++rl) { - LbmFloat nbdf = QCELL_NB(workLev,ei,ej,ek, workSet,nbl, rl); - avgnbdf[rl] += nbdf; - avgux += (D::dfDvecX[rl]*nbdf); - avguy += (D::dfDvecY[rl]*nbdf); - avguz += (D::dfDvecZ[rl]*nbdf); - avgrho += nbdf; - } - } - } - - if(cellcnt<=0.0) { - // no nbs? just use eq. - //FORDF0 { QCELL(workLev,ei,ej,ek, workSet, l) = D::dfEquil[l]; } - avgrho = 1.0; - avgux = avguy = avguz = 0.0; - //TTT mNumProblems++; -#if ELBEEM_BLENDER!=1 - D::mPanic=1; errFatal("NYI2","cellcnt<=0.0",SIMWORLD_GENERICERROR); -#endif // ELBEEM_BLENDER - } else { - // init speed - avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; - avgrho /= cellcnt; - FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? - } - - // careful with l's... - FORDF0M { - QCELL(workLev,ei,ej,ek, workSet, m) = D::getCollideEq( m,avgrho, avgux, avguy, avguz ); - //QCELL(workLev,ei,ej,ek, workSet, l) = avgnbdf[l]; // CHECK FIXME test? - } - //errMsg("FNEW", PRINT_VEC(ei,ej,ek)<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<<avgrho<<" vel"<<PRINT_VEC(avgux,avguy,avguz) ); // DEBUG SYMM - QCELL(workLev,ei,ej,ek, workSet, dMass) = 0.0; //?? new - QCELL(workLev,ei,ej,ek, workSet, dFfrac) = 0.0; //?? new - //RFLAG(workLev,ei,ej,ek,workSet) = (CellFlagType)(CFInter|CFNoInterpolSrc); - changeFlag(workLev,ei,ej,ek,workSet, (CFInter|CFNoInterpolSrc)); - if(debugFlagreinit) errMsg("NEWE", PRINT_IJK<<" newif "<<PRINT_VEC(ei,ej,ek)<<" rho"<<avgrho<<" vel("<<avgux<<","<<avguy<<","<<avguz<<") " ); - } - } - /* prevent surrounding interface cells from getting removed as empty cells - * (also cells that are not newly inited) */ - if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { - //RFLAG(workLev,ni,nj,nk, workSet) = (CellFlagType)(RFLAG(workLev,ni,nj,nk, workSet) | CFNoDelete); - changeFlag(workLev,ni,nj,nk, workSet, (RFLAG(workLev,ni,nj,nk, workSet) | CFNoDelete)); - // also add to list... - addToNewInterList(ni,nj,nk); - } // NEW? - } - - // NEW? no extra loop... - //RFLAG(workLev,i,j,k, workSet) = CFFluid; - changeFlag(workLev,i,j,k, workSet,CFFluid); - } - - /* remove empty interface cells that are not allowed to be removed anyway - * this is important, otherwise the dreaded cell-type-flickering can occur! */ - for( vector<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); // DEBUG SYMM - iter = mListEmpty.erase(iter); - iter--; // and continue with next... - - // treat as "new inter" - addToNewInterList(i,j,k); - } - } - - - /* problems arise when adjacent cells empty&fill -> - let fill cells+surrounding interface cells have the higher importance */ - for( vector<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); - - /* set surrounding fluid cells to interface cells */ - FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(workLev,ni,nj,nk, workSet) & CFFluid){ - // init fluid->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<lbmFloatSet> vWeights; - vWeights.reserve( mListFull.size() + mListEmpty.size() ); - int weightIndex = 0; - int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - LbmFloat nbTotWeights = 0.0; - for( vector<LbmPoint>::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<<" "<<weightIndex<<" "<<nbTotWeights); - vWeights[weightIndex].val[0] = nbTotWeights; - FORDF1 { vWeights[weightIndex].val[l] = nbWeights[l]; } - vWeights[weightIndex].numNbs = (LbmFloat)nbCount; - } else { - vWeights[weightIndex].numNbs = 0.0; - } - weightIndex++; - } - for( vector<LbmPoint>::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<<" "<<weightIndex<<" "<<nbTotWeights); - vWeights[weightIndex].val[0] = nbTotWeights; - FORDF1 { vWeights[weightIndex].val[l] = nbWeights[l]; } - vWeights[weightIndex].numNbs = (LbmFloat)nbCount; - } else { - vWeights[weightIndex].numNbs = 0.0; - } - weightIndex++; - } - weightIndex = 0; - - - /* process full list entries, filled cells are done after this loop */ - for( vector<LbmPoint>::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"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM - if(vWeights[weightIndex].numNbs>0.0) { - const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; - //errMsg("FF I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); - 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) { - LbmFloat change = -1.0; - if(nbTotWeightsp>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<<" "<<D::mFixMass); - } - weightIndex++; - - // already done? RFLAG(workLev,i,j,k, workSet) = CFFluid; - QCELL(workLev,i,j,k, workSet, dMass) = myrho; // should be rho... but unused? - QCELL(workLev,i,j,k, workSet, dFfrac) = 1.0; // should be rho... but unused? - /*QCELL(workLev,i,j,k, otherSet, dMass) = myrho; // NEW? - QCELL(workLev,i,j,k, otherSet, dFfrac) = 1.0; // NEW? COMPRT */ - } // fulllist - - - /* now, finally handle the empty cells - order is important, has to be after - * full cell handling */ - for( vector<LbmPoint>::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"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM - //if(nbCount>0) { - if(vWeights[weightIndex].numNbs>0.0) { - const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; - //errMsg("EE I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); - 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) { - LbmFloat change = -1.0; - if(nbTotWeightsp>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<<" "<<D::mFixMass); - } - weightIndex++; - - // finally... make it empty - // already done? RFLAG(workLev,i,j,k, workSet) = CFEmpty; - QCELL(workLev,i,j,k, workSet, dMass) = 0.0; - QCELL(workLev,i,j,k, workSet, dFfrac) = 0.0; - } - for( vector<LbmPoint>::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<LbmPoint>::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<LbmPoint>::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("???"," "<<PRINT_IJK); - continue; - } - - QCELL(workLev,i,j,k, workSet, dMass) += (D::mFixMass * newIfFac); - - int nbored = 0; - FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); } - if((nbored & CFFluid)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbFluid; } - if((nbored & CFEmpty)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbEmpty; } - - if(!(RFLAG(workLev,i,j,k, otherSet)&CFInter)) { - RFLAG(workLev,i,j,k, workSet) = (CellFlagType)(RFLAG(workLev,i,j,k, workSet) | CFNoDelete); - } - if(debugFlagreinit) errMsg("NEWIF", PRINT_IJK<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" f"<< RFLAG(workLev,i,j,k, workSet)<<" wl"<<workLev ); - } - - // reinit fill fraction - for( vector<LbmPoint>::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:"<<D::mFixMass<<" nif:"<<mListNewInter.size() ); - D::mFixMass = 0.0; - } - - // empty lists for next step - mListFull.clear(); - mListEmpty.clear(); - mListNewInter.clear(); -} // reinitFlags - - - -//! for raytracing -template<class D> -void LbmFsgrSolver<D>::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;j<mLevel[lev].lSizey-0;j++) - for(int i=0;i<mLevel[lev].lSizex-0;i++) { - *D::mpIso->lbmGetData(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;j<mLevel[lev].lSizey-0;j++) - for(int i=0;i<mLevel[lev].lSizex-0;i++) { - *D::mpIso->lbmGetData(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;j<mLevel[lev].lSizey-1;j++) - for(int i=1;i<mLevel[lev].lSizex-1;i++) { - - //continue; // OFF DEBUG - if(RFLAG(lev, i,j,k,workSet)&(CFBnd|CFEmpty)) { - continue; - } else - if( (RFLAG(lev, i,j,k,workSet)&CFInter) && (!(RFLAG(lev, i,j,k,workSet)&CFNoNbEmpty)) ){ - // no empty nb interface cells are treated as full - val = (QCELL(lev, i,j,k,workSet, dFfrac)); - } else { - // fluid? - val = 1.0; ///27.0; - } // */ - - *D::mpIso->lbmGetData( 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;j<pvsy;j++) - for(int i=0;i<pvsx;i++) { - *mpPreviewSurface->lbmGetData(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<class D> -float LbmFsgrSolver<D>::getFillFrac(int i, int j, int k) { - return QCELL(mMaxRefine, i,j,k,mLevel[mMaxRefine].setOther, dFfrac); -} - -template<class D> -void LbmFsgrSolver<D>::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<class D> -void LbmFsgrSolver<D>::addDrop(bool active, float mx, float my) { - mDropping = active; - mDropX = mx; - mDropY = my; -} - -template<class D> -void LbmFsgrSolver<D>::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", " "<<rad); - - // check bounds - const int offset = 1; - const float forceFill = 1.0; - if( (px-rad)<=offset ) px = rad + offset; - if( (px+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"<<D::mStepCnt<<" \n\n\n"); - if(mDropMode==-1) { return; } - - if(mDropMode==0) { - // inflow - if((py-4)<=offset) py = 4+offset; - //errMsg(" ", " py"<<py<<" "<<mDropHeight ); - for(int k= pz-rad; k<= pz+rad; k++) { - for(int j= py-1; j<= py+1; j++) { - for(int i= px-rad; i<= px+rad; i++) { - float dz = pz-k; - //float dy = py-j; - float dx = px-i; - if( (dx*dx+dz*dz) > (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<class D> -void LbmFsgrSolver<D>::printCellStats() { - debMsgStd("CellStats", DM_NOTIFY, "Min:"<<mMinNoCells<<" Max:"<<mMaxNoCells<< - " Avg:"<< (int)(mAvgNumUsedCells/(long long int)D::mStepCnt) , 1); -} -template<class D> -int LbmFsgrSolver<D>::checkGfxEndTime() { - //errMsg("LbmFsgrSolver","GfxEndTime "<<mGfxEndTime<<" "<<mSimulationTime<<" steps:"<<D::mStepCnt); - //errMsg(" "," e"<<mGfxEndTime<<" s"<<mSimulationTime); - if((mGfxEndTime>0.0) && (mSimulationTime>mGfxEndTime)) { - errMsg("LbmFsgrSolver","GfxEndTime "<<mSimulationTime<<" steps:"<<D::mStepCnt); - return true; - } - return false; -} - - - - -/***************************************************************************** - * move the particles - * uses updated velocities from mSetOther - *****************************************************************************/ -template<class D> -void LbmFsgrSolver<D>::advanceParticles(ParticleTracer *partt ) { - partt = NULL; // remove warning -} - - -/****************************************************************************** - * reset particle positions to default - *****************************************************************************/ -/*! init particle positions */ -template<class D> -int LbmFsgrSolver<D>::initParticles(ParticleTracer *partt) { - partt = NULL; // remove warning - return 0; -} - - -/*! init particle positions */ -template<class D> -void LbmFsgrSolver<D>::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"<<i<<" set to "<< mObjectSpeeds[i]<<", unscaled:"<< (*D::mpGiObjects)[i]->getInitialVelocity() )); - } -} - -/*****************************************************************************/ -/*! internal quick print function (for debugging) */ -/*****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::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<D> >( this, newcid, D::mNodeInfoString, set ); - - delete newcid; -} -template<class D> -void -LbmFsgrSolver<D>::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<UniformFsgrCellIdentifier> 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<class D> -CellIdentifierInterface* -LbmFsgrSolver<D>::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<class D> -typename LbmFsgrSolver<D>::stdCellId* -LbmFsgrSolver<D>::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { - //stdCellId *cid = dynamic_cast<stdCellId*>( basecid ); - stdCellId *cid = (stdCellId*)( basecid ); - return cid; -} - -template<class D> -void -LbmFsgrSolver<D>::advanceCell( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - if(cid->getEnd()) return; - - //debugOut(" ADb "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->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 "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->getEnd(), 10); -} - -template<class D> -bool -LbmFsgrSolver<D>::noEndCell( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return (!cid->getEnd()); -} - -template<class D> -void -LbmFsgrSolver<D>::deleteCellIterator( CellIdentifierInterface** cid ) { - delete *cid; - *cid = NULL; -} - -template<class D> -CellIdentifierInterface* -LbmFsgrSolver<D>::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)) ) || - ( (level<mMaxRefine) && (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused|CFEmpty)) ) ) { - continue; - } // */ - - stdCellId *newcid = new stdCellId; - newcid->level = level; - newcid->x = x; - newcid->y = y; - newcid->z = z; - //errMsg("cellAt",D::mName<<" "<<pos<<" l"<<level<<":"<<x<<","<<y<<","<<z<<" "<<convertCellFlagType2String(RFLAG(level, x,y,z, mLevel[level].setCurr)) ); - - return newcid; - } - - return NULL; -} - - -// INFO functions - -template<class D> -int -LbmFsgrSolver<D>::getCellSet ( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return mLevel[cid->level].setCurr; - //return mLevel[cid->level].setOther; -} - -template<class D> -int -LbmFsgrSolver<D>::getCellLevel ( CellIdentifierInterface* basecid) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return cid->level; -} - -template<class D> -ntlVec3Gfx -LbmFsgrSolver<D>::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<class D> -ntlVec3Gfx -LbmFsgrSolver<D>::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<class D> -LbmFloat -LbmFsgrSolver<D>::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<class D> -LbmVec -LbmFsgrSolver<D>::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<class D> -LbmFloat -LbmFsgrSolver<D>::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); -} -template<class D> -LbmFloat -LbmFsgrSolver<D>::getCellMass( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); -} -template<class D> -LbmFloat -LbmFsgrSolver<D>::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<class D> -CellFlagType -LbmFsgrSolver<D>::getCellFlag( CellIdentifierInterface* basecid,int set) { - stdCellId *cid = convertBaseCidToStdCid(basecid); - return RFLAG(cid->level, cid->x,cid->y,cid->z, set); -} - -template<class D> -LbmFloat -LbmFsgrSolver<D>::getEquilDf( int l ) { - return D::dfEquil[l]; -} - -template<class D> -int -LbmFsgrSolver<D>::getDfNum( ) { - return D::cDfNum; -} - -#if LBM_USE_GUI==1 -//! show simulation info (implement SimulationObject pure virtual func) -template<class D> -void -LbmFsgrSolver<D>::debugDisplay(fluidDispSettings *set){ - lbmDebugDisplay< LbmFsgrSolver<D> >( set, this ); -} -#endif - -/*****************************************************************************/ -// strict debugging functions -/*****************************************************************************/ -#if FSGR_STRICT_DEBUG==1 -#define STRICT_EXIT *((int *)0)=0; - -template<class D> -int LbmFsgrSolver<D>::debLBMGI(int level, int ii,int ij,int ik, int is) { - if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(level > mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - - if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - return _LBMGI(level, ii,ij,ik, is); -}; - -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG(int level, int xx,int yy,int zz,int set){ - return _RFLAG(level, xx,yy,zz,set); -}; - -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - // warning might access all spatial nbs - if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - return _RFLAG_NB(level, xx,yy,zz,set, dir); -}; - -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - return _RFLAG_NBINV(level, xx,yy,zz,set, dir); -}; - -template<class D> -int LbmFsgrSolver<D>::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { - if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(level > mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - - if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } - if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } - if(l>D::cDfNum){ // dFfrac is an exception - if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } -#if COMPRESSGRIDS==1 - //if((!D::mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug -#endif // COMPRESSGRIDS==1 - return _LBMQI(level, ii,ij,ik, is, l); -}; - -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL(int level, int xx,int yy,int zz,int set,int l) { - //errMsg("LbmStrict","debQCELL debug: l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" l"<<l<<" index"<<LBMGI(level, xx,yy,zz,set)); - return _QCELL(level, xx,yy,zz,set,l); -}; - -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - return _QCELL_NB(level, xx,yy,zz,set, dir,l); -}; - -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { - if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - return _QCELL_NBINV(level, xx,yy,zz,set, dir,l); -}; - -template<class D> -LbmFloat* LbmFsgrSolver<D>::debRACPNT(int level, int ii,int ij,int ik, int is ) { - return _RACPNT(level, ii,ij,ik, is ); -}; - -template<class D> -LbmFloat& LbmFsgrSolver<D>::debRAC(LbmFloat* s,int l) { - if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } - if(l>dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } - //if(l>D::cDfNum){ // dFfrac is an exception - //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } - return _RAC(s,l); -}; - -#endif // FSGR_STRICT_DEBUG==1 - -#define LBMFSGRSOLVER_H -#endif - - diff --git a/intern/elbeem/intern/lbmfunctions.h b/intern/elbeem/intern/lbmfunctions.h deleted file mode 100644 index 4038c995f68..00000000000 --- a/intern/elbeem/intern/lbmfunctions.h +++ /dev/null @@ -1,320 +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 Solver templated helper functions - * - *****************************************************************************/ -#ifndef LBMFUNCTIONS_H - - - -#if LBM_USE_GUI==1 -#define USE_GLUTILITIES -#include "../gui/gui_utilities.h" - -//! display a single node -template<typename D> -void -debugDisplayNode(fluidDispSettings *dispset, D *lbm, typename D::CellIdentifier cell ) { - //debugOut(" DD: "<<cell->getAsString() , 10); - ntlVec3Gfx org = lbm->getCellOrigin( cell ); - ntlVec3Gfx halfsize = lbm->getCellSize( cell ); - int set = lbm->getCellSet( cell ); - //debugOut(" DD: "<<cell->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<typename D> -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<D>(dispset, lbm, cid ); -#endif - } - delete cid; - - glEnable( GL_LIGHTING ); // dont light lines -} - -//! debug display function -// D has to implement the CellIterator interface -template<typename D> -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<MarkedCellIdentifier *>( cid ); -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - //::debugDisplayNode<>(&dispset, lbm, mid->mpCell ); - ::debugDisplayNode<>(&dispset, lbm, cid ); -#else - //debugDisplayNode<D>(&dispset, lbm, mid->mpCell ); - debugDisplayNode<D>(&dispset, lbm, cid ); -#endif - cid = lbm->markedAdvanceCell(); - } - delete cid; - - glEnable( GL_LIGHTING ); // dont light lines -} - -#endif // LBM_USE_GUI - -//! display a single node -template<typename D> -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; i<printInfo.length()-0; i++) { - char what = printInfo[i]; - switch(what) { - case '+': // all on - printDF = true; printRho = true; printVel = true; printFlag = true; printGeom = true; printMass = true; - printBothSets = true; break; - case '-': // all off - printDF = false; printRho = false; printVel = false; printFlag = false; printGeom = false; printMass = false; - printBothSets = false; break; - case 'd': printDF = true; break; - case 'r': printRho = true; break; - case 'v': printVel = true; break; - case 'f': printFlag = true; break; - case 'g': printGeom = true; break; - case 'm': printMass = true; break; - case 's': printBothSets = true; break; - default: - errFatal("debugPrintNodeInfo","Invalid node info id "<<what,SIMWORLD_GENERICERROR); return; - } - } - - ntlVec3Gfx org = lbm->getCellOrigin( cell ); - ntlVec3Gfx halfsize = lbm->getCellSize( cell ); - int set = lbm->getCellSet( cell ); - debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<<printInfo<<"' for node: "<<cell->getAsString()<<" from "<<lbm->getName()<<" currSet:"<<set , 1); - if(printGeom) debMsgStd(" ",DM_MSG, "Org:"<<org<<" Halfsize:"<<halfsize<<" ", 1); - - int setmax = 2; - if(!printBothSets) setmax = 1; - if(forceSet>=0) setmax = 1; - - for(int s=0; s<setmax; s++) { - int workset = set; - if(s==1){ workset = (set^1); } - if(forceSet>=0) workset = forceSet; - debMsgStd(" ",DM_MSG, "Printing set:"<<workset<<" orgSet:"<<set, 1); - - if(printDF) { - for(int l=0; l<lbm->getDfNum(); l++) { // FIXME ?? - debMsgStd(" ",DM_MSG, " Df"<<l<<": "<<lbm->getCellDf(cell,workset,l), 1); - } - } - if(printRho) { - debMsgStd(" ",DM_MSG, " Rho: "<<lbm->getCellDensity(cell,workset), 1); - } - if(printVel) { - debMsgStd(" ",DM_MSG, " Vel: "<<lbm->getCellVelocity(cell,workset), 1); - } - if(printFlag) { - CellFlagType flag = lbm->getCellFlag(cell,workset); - debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<<convertFlags2String( flag ) <<" "<<convertCellFlagType2String( flag ), 1); - } - if(printMass) { - debMsgStd(" ",DM_MSG, " Mss: "<<lbm->getCellMass(cell,workset), 1); - } - } -} - -#define LBMFUNCTIONS_H -#endif - diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp index 9c7fbc70b16..d6ac0b84ed7 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.cpp +++ b/intern/elbeem/intern/ntl_blenderdumper.cpp @@ -24,7 +24,7 @@ * Constructor *****************************************************************************/ ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) : - ntlRaytracer(filename,commandlineMode), + ntlWorld(filename,commandlineMode), mpTrafo(NULL) { ntlRenderGlobals *glob = mpGlob; @@ -194,7 +194,7 @@ int ntlBlenderDumper::renderScene( void ) // still render for preview... if(debugOut) { debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1); - ntlRaytracer::renderScene(); } + ntlWorld::renderScene(); } else { // next frame glob->setAniCount( glob->getAniCount() +1 ); diff --git a/intern/elbeem/intern/ntl_blenderdumper.h b/intern/elbeem/intern/ntl_blenderdumper.h index 0178feff145..403531a10a4 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.h +++ b/intern/elbeem/intern/ntl_blenderdumper.h @@ -7,12 +7,12 @@ * *****************************************************************************/ #ifndef NTL_BLENDERDUMPER_H -#include "ntl_raytracer.h" +#include "ntl_world.h" template<class Scalar> 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 "<<t<<","<<mint<<" triangle: "<<PRINT_TRIANGLE( (*hit), (*mpVertices) ) ); - gfxReal u1=0.0,v1=0.0, t1=-1.0; - ray.intersectTriangle( mpVertices, hit, t1,u1,v1); - errorOut("Tree second test1 :"<<t1<<" u1:"<<u1<<" v1:"<<v1 ); - if(t==GFX_REAL_MAX) errorOut( "Tree MAX t " ); - //errorOut( mpVertices[ (*iter).getPoints()[0] ][0] ); - } - - //retnormal = -(e2-e0).crossProd(e1-e0); // DEBUG - } } diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index 80122c41146..b05b3d5ec9a 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -85,6 +85,7 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) mGeoInitId = -1; } mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false)); + mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false); debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<< " gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug diff --git a/intern/elbeem/intern/ntl_geometryobject.h b/intern/elbeem/intern/ntl_geometryobject.h index 31c786cb751..ca34b53b07b 100644 --- a/intern/elbeem/intern/ntl_geometryobject.h +++ b/intern/elbeem/intern/ntl_geometryobject.h @@ -72,6 +72,10 @@ class ntlGeometryObject : public ntlGeometryClass inline bool getGeoInitIntersect() const { return mGeoInitIntersect; } inline void setGeoInitIntersect(bool set) { mGeoInitIntersect=set; } + /*! Set/get the part slip value*/ + inline bool getGeoPartSlipValue() const { return mGeoPartSlipValue; } + inline void setGeoPartSlipValue(float set) { mGeoPartSlipValue=set; } + protected: /*! Point to a property object describing the surface of this object */ @@ -94,6 +98,8 @@ class ntlGeometryObject : public ntlGeometryClass ntlVec3Gfx mInitialVelocity; /*! perform more accurate intersecting geo init for this object? */ bool mGeoInitIntersect; + /*! part slip bc value */ + float mGeoPartSlipValue; public: diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp index 440144a0245..ed5f96a4541 100644 --- a/intern/elbeem/intern/ntl_ray.cpp +++ b/intern/elbeem/intern/ntl_ray.cpp @@ -466,7 +466,7 @@ const ntlColor ntlRay::shade() //const if (closest != NULL) { ntlVec3Gfx triangleNormal = tri->getNormal(); - if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) errorOut("ntlRaytracer warning: trinagle normal= 0 "); // DEBUG + if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) errorOut("ntlRay warning: trinagle normal= 0 "); // DEBUG /* intersection on inside faces? if yes invert normal afterwards */ gfxReal valDN; // = mDirection | normal; valDN = dot(mDirection, triangleNormal); diff --git a/intern/elbeem/intern/ntl_raytracer.cpp b/intern/elbeem/intern/ntl_world.cpp index ece36b1560a..bd7a6abeb6f 100644 --- a/intern/elbeem/intern/ntl_raytracer.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -11,7 +11,7 @@ #include <sys/stat.h> #include <sstream> #include "utilities.h" -#include "ntl_raytracer.h" +#include "ntl_world.h" #include "ntl_scene.h" #include "parametrizer.h" #include "globals.h" @@ -34,7 +34,7 @@ void setPointers( ntlRenderGlobals *setglob); /****************************************************************************** * Constructor *****************************************************************************/ -ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : +ntlWorld::ntlWorld(string filename, bool commandlineMode) : mpGlob(NULL), mpLightList(NULL), mpPropList(NULL), mpSims(NULL), mpOpenGLRenderer(NULL), @@ -71,7 +71,7 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : long sstartTime = getTime(); scene->buildScene(); long sstopTime = getTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); // TODO check simulations, run first steps mFirstSim = -1; @@ -89,31 +89,31 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : if(mFirstSim>=0) { if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) { mFirstSim = i; - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"First Sim changed: "<<i ,10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<<i ,10); } } // check any valid sim if(mFirstSim<0) { mFirstSim = i; - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"First Sim: "<<i ,10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim: "<<i ,10); } } if(mFirstSim>=0) { - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) { - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<<mSimulationTime ,10); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<<mSimulationTime ,10); advanceSims(); } long stopTime = getTime(); mSimulationTime += (*mpSims)[mFirstSim]->getStartTime(); - debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); #ifndef NOGUI guiResetSimulationTimeRange( mSimulationTime ); #endif } else { - if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlRaytracer::ntlRaytracer",DM_WARNING,"No active simulations!", 1); + if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); } } @@ -132,7 +132,7 @@ ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) : /****************************************************************************** * Destructor *****************************************************************************/ -ntlRaytracer::~ntlRaytracer() +ntlWorld::~ntlWorld() { delete mpGlob->getScene(); delete mpGlob; @@ -146,7 +146,7 @@ ntlRaytracer::~ntlRaytracer() /******************************************************************************/ /*! set single frame rendering to filename */ -void ntlRaytracer::setSingleFrameOut(string singleframeFilename) { +void ntlWorld::setSingleFrameOut(string singleframeFilename) { mpGlob->setSingleFrameMode(true); mpGlob->setSingleFrameFilename(singleframeFilename); } @@ -159,17 +159,17 @@ extern "C" { void simulateThreadIncreaseFrame(void); } #endif // ELBEEM_BLENDER==1 -int ntlRaytracer::renderAnimation( void ) +int ntlWorld::renderAnimation( void ) { // only single pic currently - //debMsgStd("ntlRaytracer::renderAnimation : Warning only simulating...",1); + //debMsgStd("ntlWorld::renderAnimation : Warning only simulating...",1); if(mpGlob->getAniFrames() < 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No frames to render... ",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No frames to render... ",1); return 1; } if(mFirstSim<0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No reference animation found...",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No reference animation found...",1); return 1; } @@ -184,7 +184,7 @@ int ntlRaytracer::renderAnimation( void ) #endif // ELBEEM_BLENDER==1 if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); return 1; } } @@ -198,7 +198,7 @@ int ntlRaytracer::renderAnimation( void ) * this function is run in another thread, and communicates * with the parent thread via a mutex *****************************************************************************/ -int ntlRaytracer::renderVisualization( bool multiThreaded ) +int ntlWorld::renderVisualization( bool multiThreaded ) { #ifndef NOGUI //gfxReal deltat = 0.0015; @@ -206,7 +206,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) while(!getStopRenderVisualization()) { if(mpSims->size() <= 0) { - debMsgStd("ntlRaytracer::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); + debMsgStd("ntlWorld::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); stopSimulationThread(); break; } @@ -216,7 +216,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) long startTime = getTime(); advanceSims(); long stopTime = getTime(); - debMsgStd("ntlRaytracer::renderVisualization",DM_MSG,"Time for "<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<"s ", 10); + debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for "<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<"s ", 10); } else { double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); singleStepSims(targetTime); @@ -227,11 +227,11 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) if(!(*mpSims)[i]->getPanic()) allPanic = false; } if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } if(!SIMWORLD_OK()) { - warnMsg("ntlRaytracer::advanceSims","World state error... stopping" ); + warnMsg("ntlWorld::advanceSims","World state error... stopping" ); setStopRenderVisualization( true ); } } @@ -254,7 +254,7 @@ int ntlRaytracer::renderVisualization( bool multiThreaded ) return 0; } /*! render a single step for viz mode */ -int ntlRaytracer::singleStepVisualization( void ) +int ntlWorld::singleStepVisualization( void ) { mThreadRunning = true; double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); @@ -279,12 +279,12 @@ int ntlRaytracer::singleStepVisualization( void ) /****************************************************************************** * advance simulations by time t *****************************************************************************/ -int ntlRaytracer::advanceSims() +int ntlWorld::advanceSims() { bool done = false; bool allPanic = true; double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(); - //debMsgStd("ntlRaytracer::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug + //debMsgStd("ntlWorld::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug while(!done) { double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime(); @@ -296,14 +296,14 @@ int ntlRaytracer::advanceSims() for(size_t i=0;i<mpSims->size();i++) { if(!(*mpSims)[i]->getVisible()) continue; if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? - //debMsgStd("ntlRaytracer::advanceSims",DM_MSG, " sim "<<i<<" c"<<(*mpSims)[i]->getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<<targetTime, 10); // debug // timedebug + //debMsgStd("ntlWorld::advanceSims",DM_MSG, " sim "<<i<<" c"<<(*mpSims)[i]->getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<<targetTime, 10); // debug // timedebug } if( (targetTime - (*mpSims)[mFirstSim]->getCurrentTime()) > LBM_TIME_EPSILON) done=false; if(allPanic) done = true; } if(allPanic) { - warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" ); + warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } for(size_t i=0;i<mpSims->size();i++) { @@ -318,10 +318,10 @@ int ntlRaytracer::advanceSims() /* advance simulations by a single step */ /* dont check target time, if *targetTime==NULL */ -void ntlRaytracer::singleStepSims(double targetTime) { +void ntlWorld::singleStepSims(double targetTime) { const bool debugTime = false; //double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Target time: "<<targetTime); + if(debugTime) errMsg("ntlWorld::singleStepSims","Target time: "<<targetTime); for(size_t i=0;i<mpSims->size();i++) { SimulationObject *sim = (*mpSims)[i]; @@ -330,9 +330,9 @@ void ntlRaytracer::singleStepSims(double targetTime) { bool done = false; while(!done) { // try to prevent round off errs - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getStepTime()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug + if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getStepTime()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug if( (targetTime - sim->getCurrentTime()) > LBM_TIME_EPSILON) { - if(debugTime) errMsg("ntlRaytracer::singleStepSims","Stepping sim "<<i<<" t:"<< sim->getCurrentTime()); // timedebug + if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping sim "<<i<<" t:"<< sim->getCurrentTime()); // timedebug sim->step(); } else { done = true; @@ -353,7 +353,7 @@ void ntlRaytracer::singleStepSims(double targetTime) { * Render the current scene * uses the global variables from the parser *****************************************************************************/ -int ntlRaytracer::renderScene( void ) +int ntlWorld::renderScene( void ) { #ifndef ELBEEM_BLENDER char nrStr[5]; /* nr conversion */ @@ -374,7 +374,7 @@ int ntlRaytracer::renderScene( void ) if(mpGlob->getFrameSkip()) { struct stat statBuf; if(stat(outfn_conv.str().c_str(),&statBuf) == 0) { - errorOut("ntlRaytracer::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); + errorOut("ntlWorld::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); glob->setAniCount( glob->getAniCount() +1 ); return(2); } @@ -472,7 +472,7 @@ int ntlRaytracer::renderScene( void ) glob->setCounterSceneInter(0); for (int scanline=Yres ; scanline > 0 ; --scanline) { - debugOutInter( "ntlRaytracer::renderScene: Line "<<scanline<< + debugOutInter( "ntlWorld::renderScene: Line "<<scanline<< " ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 ); screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres) - rightVec; @@ -679,7 +679,7 @@ int ntlRaytracer::renderScene( void ) #ifndef NOPNG writePng(outfn_conv.str().c_str(), rows, w, h); #else // NOPNG - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1); #endif // NOPNG } @@ -696,7 +696,7 @@ int ntlRaytracer::renderScene( void ) getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(), glob->getCounterShades(), glob->getCounterSceneInter() ); - debMsgStd("ntlRaytracer::renderScene",DM_MSG, resout, 1 ); + debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 ); /* clean stuff up */ delete [] aaCol; @@ -705,7 +705,7 @@ int ntlRaytracer::renderScene( void ) glob->getScene()->cleanupScene(); if(mpGlob->getSingleFrameMode() ) { - debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); + debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); return 1; } #endif // ELBEEM_BLENDER diff --git a/intern/elbeem/intern/ntl_raytracer.h b/intern/elbeem/intern/ntl_world.h index 3f36fabaf92..0da7171bad6 100644 --- a/intern/elbeem/intern/ntl_raytracer.h +++ b/intern/elbeem/intern/ntl_world.h @@ -18,13 +18,13 @@ #include "simulation_object.h" class ntlOpenGLRenderer; -class ntlRaytracer +class ntlWorld { public: /*! Constructor */ - ntlRaytracer(string filename, bool commandlineMode); + ntlWorld(string filename, bool commandlineMode); /*! Destructor */ - virtual ~ntlRaytracer( void ); + virtual ~ntlWorld( void ); /*! render a whole animation (command line mode) */ int renderAnimation( void ); diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp index 15fb79fa5f2..dfb92050af4 100644 --- a/intern/elbeem/intern/simulation_object.cpp +++ b/intern/elbeem/intern/simulation_object.cpp @@ -10,8 +10,6 @@ #include "simulation_object.h" #include "ntl_bsptree.h" #include "ntl_scene.h" -#include "factory_lbm.h" -#include "lbmfunctions.h" #ifdef _WIN32 #else @@ -19,6 +17,8 @@ #endif +//! lbm factory functions +LbmSolverInterface* createSolver(); /****************************************************************************** @@ -109,13 +109,8 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) //mDimension is deprecated mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); if(mSolverType == stnFsgr) { - mpLbm = createSolverLbmFsgr(); + mpLbm = createSolver(); } else if(mSolverType == stnOld) { -#ifdef LBM_INCLUDE_TESTSOLVERS - // old solver for gfx demo - mpLbm = createSolverOld(); -#endif // LBM_TESTSOLVER - } else { errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); return 1; } @@ -311,7 +306,8 @@ void SimulationObject::drawDebugDisplay() { //errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type ); mpLbm->debugDisplay( &mDebDispSet[ mDebugType ] ); - ::lbmMarkedCellDisplay<>( mpLbm ); + //::lbmMarkedCellDisplay<>( mpLbm ); + mpLbm->lbmMarkedCellDisplay(); #endif } @@ -322,7 +318,7 @@ void SimulationObject::drawInteractiveDisplay() if(!getVisible()) return; if(mSelectedCid) { // in debugDisplayNode if dispset is on is ignored... - ::debugDisplayNode<>( &mDebDispSet[ FLUIDDISPGrid ], mpLbm, mSelectedCid ); + mpLbm->debugDisplayNode( &mDebDispSet[ FLUIDDISPGrid ], mSelectedCid ); } #endif } @@ -351,7 +347,8 @@ void SimulationObject::setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir) void SimulationObject::setMouseClick() { if(mSelectedCid) { - ::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() ); + //::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() ); + mpLbm->debugPrintNodeInfo( mSelectedCid ); } } diff --git a/intern/elbeem/intern/simulation_object.h b/intern/elbeem/intern/simulation_object.h index 84a0fd8222a..ae9060db859 100644 --- a/intern/elbeem/intern/simulation_object.h +++ b/intern/elbeem/intern/simulation_object.h @@ -7,13 +7,13 @@ * *****************************************************************************/ -#ifndef ELBEEM_SIMINTERFACE -#define ELBEEM_SIMINTERFACE +#ifndef SIMULATION_OBJECT_H +#define SIMULATION_OBJECT_H #define USE_GLUTILITIES #include "ntl_geometryshader.h" -#include "lbmdimensions.h" +#include "solver_interface.h" #include "parametrizer.h" #include "particletracer.h" diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h new file mode 100644 index 00000000000..3e8d2c3e849 --- /dev/null +++ b/intern/elbeem/intern/solver_class.h @@ -0,0 +1,690 @@ +/****************************************************************************** + * + * El'Beem - the visual lattice boltzmann freesurface simulator + * All code distributed as part of El'Beem is covered by the version 2 of the + * GNU General Public License. See the file COPYING for details. + * Copyright 2003-2005 Nils Thuerey + * + * Combined 2D/3D Lattice Boltzmann standard solver classes + * + *****************************************************************************/ + + +#ifndef LBMFSGRSOLVER_H + +// blender interface +#if ELBEEM_BLENDER==1 +// warning - for MSVC this has to be included +// _before_ ntl_vector3dim +#include "SDL.h" +#include "SDL_thread.h" +#include "SDL_mutex.h" +extern "C" { + void simulateThreadIncreaseFrame(void); + extern SDL_mutex *globalBakeLock; + extern int globalBakeState; + extern int globalBakeFrame; +} +#endif // ELBEEM_BLENDER==1 + +#include "utilities.h" +#include "solver_interface.h" +#include "ntl_scene.h" +#include <stdio.h> + +#if PARALLEL==1 +#include <omp.h> +#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 <ieeefp.h> +#ifndef expf +#define expf exp +#endif +#endif + + +/*****************************************************************************/ +/*! cell access classes */ +template<typename D> +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"<<x<<",j"<<y; + if(D::cDimension>2) ret<<",k"<<z; + ret <<" }"; + return ret.str(); + } + + virtual bool equal(CellIdentifierInterface* other) { + //UniformFsgrCellIdentifier<D> *cid = dynamic_cast<UniformFsgrCellIdentifier<D> *>( other ); + UniformFsgrCellIdentifier<D> *cid = (UniformFsgrCellIdentifier<D> *)( 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 D> +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<ntlGeometryObject*>* /*objects*/ ); + +#if LBM_USE_GUI==1 + //! show simulation info (implement LbmSolverInterface pure virtual func) + virtual void debugDisplay(fluidDispSettings *set); +#endif + + + // implement CellIterator<UniformFsgrCellIdentifier> interface + typedef UniformFsgrCellIdentifier<typename D::LbmCellContents> 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<ntlGeometryObject*> 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<LbmPoint> mListEmpty; + //! list of the cells to make fluid at the end of the step + vector<LbmPoint> mListFull; + //! list of new interface cells to init + vector<LbmPoint> 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<LbmVec> mObjectSpeeds; + //! partslip bc. values for obstacle boundary conditions + vector<LbmFloat> 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: "<<D::mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \ + debugMarkCellCall((lev),(x),(y),(z)); +#else // FSGR_STRICT_DEBUG==1 +#define debugMarkCell(lev,x,y,z) \ + debugMarkCellCall((lev),(x),(y),(z)); +#endif // FSGR_STRICT_DEBUG==1 + + +// flag array defines ----------------------------------------------------------------------------------------------- + +// lbm testsolver get index define +#define _LBMGI(level, ii,ij,ik, is) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) + +//! flag array acces macro +#define _RFLAG(level,xx,yy,zz,set) mLevel[level].mprsFlags[set][ LBMGI((level),(xx),(yy),(zz),(set)) ] +#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set) ] +#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set) ] + +// array data layouts +// standard array layout ----------------------------------------------------------------------------------------------- +#define ALSTRING "Standard Array Layout" +//#define _LBMQI(level, ii,ij,ik, is, lunused) ( ((is)*mLevel[level].lOffsz) + (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) +#define _LBMQI(level, ii,ij,ik, is, lunused) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) +#define _QCELL(level,xx,yy,zz,set,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx),(yy),(zz),(set), l)*dTotalNum +(l)]) +#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set, l)*dTotalNum +(l)]) +#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set, l)*dTotalNum +(l)]) + +#define QCELLSTEP dTotalNum +#define _RACPNT(level, ii,ij,ik, is ) &QCELL(level,ii,ij,ik,is,0) +#define _RAC(s,l) (s)[(l)] + + +#if FSGR_STRICT_DEBUG==1 + +#define LBMGI(level,ii,ij,ik, is) debLBMGI(level,ii,ij,ik, is) +#define RFLAG(level,xx,yy,zz,set) debRFLAG(level,xx,yy,zz,set) +#define RFLAG_NB(level,xx,yy,zz,set, dir) debRFLAG_NB(level,xx,yy,zz,set, dir) +#define RFLAG_NBINV(level,xx,yy,zz,set, dir) debRFLAG_NBINV(level,xx,yy,zz,set, dir) + +#define LBMQI(level,ii,ij,ik, is, l) debLBMQI(level,ii,ij,ik, is, l) +#define QCELL(level,xx,yy,zz,set,l) debQCELL(level,xx,yy,zz,set,l) +#define QCELL_NB(level,xx,yy,zz,set, dir,l) debQCELL_NB(level,xx,yy,zz,set, dir,l) +#define QCELL_NBINV(level,xx,yy,zz,set, dir,l) debQCELL_NBINV(level,xx,yy,zz,set, dir,l) +#define RACPNT(level, ii,ij,ik, is ) debRACPNT(level, ii,ij,ik, is ) +#define RAC(s,l) debRAC(s,l) + +#else // FSGR_STRICT_DEBUG==1 + +#define LBMGI(level,ii,ij,ik, is) _LBMGI(level,ii,ij,ik, is) +#define RFLAG(level,xx,yy,zz,set) _RFLAG(level,xx,yy,zz,set) +#define RFLAG_NB(level,xx,yy,zz,set, dir) _RFLAG_NB(level,xx,yy,zz,set, dir) +#define RFLAG_NBINV(level,xx,yy,zz,set, dir) _RFLAG_NBINV(level,xx,yy,zz,set, dir) + +#define LBMQI(level,ii,ij,ik, is, l) _LBMQI(level,ii,ij,ik, is, l) +#define QCELL(level,xx,yy,zz,set,l) _QCELL(level,xx,yy,zz,set,l) +#define QCELL_NB(level,xx,yy,zz,set, dir,l) _QCELL_NB(level,xx,yy,zz,set, dir, l) +#define QCELL_NBINV(level,xx,yy,zz,set, dir,l) _QCELL_NBINV(level,xx,yy,zz,set, dir,l) +#define RACPNT(level, ii,ij,ik, is ) _RACPNT(level, ii,ij,ik, is ) +#define RAC(s,l) _RAC(s,l) + +#endif // FSGR_STRICT_DEBUG==1 + +// general defines ----------------------------------------------------------------------------------------------- + +#define TESTFLAG(flag, compflag) ((flag & compflag)==compflag) + +#if LBMDIM==2 +#define dC 0 +#define dN 1 +#define dS 2 +#define dE 3 +#define dW 4 +#define dNE 5 +#define dNW 6 +#define dSE 7 +#define dSW 8 +#define LBM_DFNUM 9 +#else +// direction indices +#define dC 0 +#define dN 1 +#define dS 2 +#define dE 3 +#define dW 4 +#define dT 5 +#define dB 6 +#define dNE 7 +#define dNW 8 +#define dSE 9 +#define dSW 10 +#define dNT 11 +#define dNB 12 +#define dST 13 +#define dSB 14 +#define dET 15 +#define dEB 16 +#define dWT 17 +#define dWB 18 +#define LBM_DFNUM 19 +#endif +//? #define dWB 18 + +// default init for dFlux values +#define FLUX_INIT 0.5f * (float)(D::cDfNum) + +// only for non DF dir handling! +#define dNET 19 +#define dNWT 20 +#define dSET 21 +#define dSWT 22 +#define dNEB 23 +#define dNWB 24 +#define dSEB 25 +#define dSWB 26 + +//! fill value for boundary cells +#define BND_FILL 0.0 + +#define DFL1 (1.0/ 3.0) +#define DFL2 (1.0/18.0) +#define DFL3 (1.0/36.0) + +// 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<mLevel[leveli].lSizey-0;++j) \ + for(int i=0;i<mLevel[leveli].lSizex-0;++i) \ + +// loops over _only inner_ cells +#define FSGR_FORIJK1(leveli) \ + for(int k= getForZMin1(); k< getForZMax1(leveli); ++k) \ + for(int j=1;j<mLevel[leveli].lSizey-1;++j) \ + for(int i=1;i<mLevel[leveli].lSizex-1;++i) \ + +// relaxation_macros end + + +/*****************************************************************************/ +/* init a given cell with flag, density, mass and equilibrium dist. funcs */ + +template<class D> +void LbmFsgrSolver<D>::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<class D> +void +LbmFsgrSolver<D>::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<class D> +void +LbmFsgrSolver<D>::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<class D> +LbmFsgrSolver<D>::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<D::cDimension; m++) { + for(int l=0; l<D::cDfNum; l++) { + D::lesCoeffDiag[m][l] = + D::lesCoeffOffdiag[m][l] = 0.0; + } + } + for(int m=0; m<D::cDimension; m++) { + for(int n=0; n<D::cDimension; n++) { + for(int l=1; l<D::cDfNum; l++) { + LbmFloat em; + switch(m) { + case 0: em = D::dfDvecX[l]; break; + case 1: em = D::dfDvecY[l]; break; + case 2: em = D::dfDvecZ[l]; break; + default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR); + } + LbmFloat en; + switch(n) { + case 0: en = D::dfDvecX[l]; break; + case 1: en = D::dfDvecY[l]; break; + case 2: en = D::dfDvecZ[l]; break; + default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR); + } + const LbmFloat coeff = em*en; + if(m==n) { + D::lesCoeffDiag[m][l] = coeff; + } else { + if(m>n) { + D::lesCoeffOffdiag[odm][l] = coeff; + } + } + } + + if(m==n) { + } else { + if(m>n) odm++; + } + } + } + + mDvecNrm[0] = LbmVec(0.0); + FORDF1 { + mDvecNrm[l] = getNormalized( + LbmVec(D::dfDvecX[D::dfInv[l]], D::dfDvecY[D::dfInv[l]], D::dfDvecZ[D::dfInv[l]] ) + ) * -1.0; + } + + //addDrop(false,0,0); +} + +/*****************************************************************************/ +/* Destructor */ +/*****************************************************************************/ +template<class D> +LbmFsgrSolver<D>::~LbmFsgrSolver() +{ + if(!D::mInitDone){ debugOut("LbmFsgrSolver::LbmFsgrSolver : not inited...",0); return; } + +#if COMPRESSGRIDS==1 + delete mLevel[mMaxRefine].mprsCells[1]; + mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL; +#endif // COMPRESSGRIDS==1 + + for(int i=0; i<=mMaxRefine; i++) { + for(int s=0; s<2; s++) { + if(mLevel[i].mprsCells[s]) delete [] mLevel[i].mprsCells[s]; + if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s]; + } + } + delete D::mpIso; + if(mpPreviewSurface) delete mpPreviewSurface; + + // always output performance estimate + debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5); + if(!D::mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10); +} + + + + +/****************************************************************************** + * initilize variables fom attribute list + *****************************************************************************/ +template<class D> +void +LbmFsgrSolver<D>::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<class D> +void +LbmFsgrSolver<D>::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 "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" offs:"<<mLevel[i].lOffsx<<","<<mLevel[i].lOffsy<<","<<mLevel[i].lOffsz + <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", " + <<" cmsagp:"<<mLevel[i].lcsmago<<", " + << " ss"<<mLevel[i].stepsize<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize ); + } else { + if(!D::mInitDone) { + debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" " + <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5); + } + } + } + if(mMaxRefine>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<class D> +bool +LbmFsgrSolver<D>::initialize( ntlTree* /*tree*/, vector<ntlGeometryObject*>* /*objects*/ ) +{ + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<<ALSTRING<<") ",1); + + // fix size inits to force cubic cells and mult4 level dimensions + const int debugGridsizeInit = 1; + mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)D::mSizex; + int maxGridSize = D::mSizex; // get max size + if(D::mSizey>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:"<<D::mvGeoStart<<" End:"<<D::mvGeoEnd<<" maxS:"<<maxGeoSize<<" maxG:"<<maxGridSize<<" cs:"<<cellSize, 10); + // force grid sizes according to geom. size, rounded + D::mSizex = (int) ((D::mvGeoEnd[0]-D::mvGeoStart[0]) / cellSize +0.5); + D::mSizey = (int) ((D::mvGeoEnd[1]-D::mvGeoStart[1]) / cellSize +0.5); + D::mSizez = (int) ((D::mvGeoEnd[2]-D::mvGeoStart[2]) / cellSize +0.5); + // match refinement sizes, round downwards to multiple of 4 + int sizeMask = 0; + int maskBits = mMaxRefine; + if(PARALLEL==1) maskBits+=2; + for(int i=0; i<maskBits; i++) { sizeMask |= (1<<i); } + sizeMask = ~sizeMask; + if(debugGridsizeInit) debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez<<" m"<<convertCellFlagType2String(sizeMask) ,10); + D::mSizex &= sizeMask; + D::mSizey &= sizeMask; + D::mSizez &= sizeMask; + // force geom size to match rounded grid sizes + D::mvGeoEnd[0] = D::mvGeoStart[0] + cellSize*(LbmFloat)D::mSizex; + D::mvGeoEnd[1] = D::mvGeoStart[1] + cellSize*(LbmFloat)D::mSizey; + D::mvGeoEnd[2] = D::mvGeoStart[2] + cellSize*(LbmFloat)D::mSizez; + + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Final domain size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez<< + ", Domain: "<<D::mvGeoStart<<":"<<D::mvGeoEnd<<", "<<(D::mvGeoEnd-D::mvGeoStart) ,2); + //debMsgStd("LbmFsgrSolver::initialize",DM_MSG, ,2); + D::mpParam->setSize(D::mSizex, D::mSizey, D::mSizez); + + //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez ,2); + +#if ELBEEM_BLENDER!=1 + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: " + <<"LBM_EPSILON="<<LBM_EPSILON <<" " + <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" " + <<"REFINEMENTBORDER="<<REFINEMENTBORDER <<" " + <<"OPT3D="<<OPT3D <<" " + <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" " + <<"LS_FLUIDTHRESHOLD="<<LS_FLUIDTHRESHOLD <<" " + <<"MASS_INVALID="<<MASS_INVALID <<" " + <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" " + <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" " + <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" " + <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" " + <<"USE_LES="<<USE_LES <<" " + ,10); +#endif // ELBEEM_BLENDER!=1 + + // perform 2D corrections... + if(D::cDimension == 2) D::mSizez = 1; + + D::mpParam->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 "<<mForceTadapRefine, 6); + } + + if(!D::mpParam->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 "<<i<<" "<<PRINT_VEC(mLevel[i].lSizex,mLevel[i].lSizey,mLevel[i].lSizez) ); + xit(1); + }// old QUAD handling */ + } + + // estimate memory usage + { + unsigned long int memCnt = 0; + unsigned long int rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); + memCnt += sizeof(CellFlagType) * (rcellSize/dTotalNum +4) *2; +#if COMPRESSGRIDS==0 + memCnt += sizeof(LbmFloat) * (rcellSize +4) *2; +#else // COMPRESSGRIDS==0 + unsigned long int compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); + memCnt += sizeof(LbmFloat) * (rcellSize+compressOffset +4); +#endif // COMPRESSGRIDS==0 + for(int i=mMaxRefine-1; i>=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:"<<sizeof(CellFlagType)<<", should be:"<<CellFlagTypeSize, SIMWORLD_GENERICERROR); + return false; + } + + mLevel[ mMaxRefine ].nodeSize = ((D::mvGeoEnd[0]-D::mvGeoStart[0]) / (LbmFloat)(D::mSizex)); + mLevel[ mMaxRefine ].simCellSize = D::mpParam->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:"<<rcellSize<<" cpff:"<<compressOffset<< " c0:"<<mLevel[ mMaxRefine ].mprsCells[0]<<" c1:"<<mLevel[ mMaxRefine ].mprsCells[1]<< " c0e:"<<(mLevel[ mMaxRefine ].mprsCells[0]+rcellSize)<<" c1:"<<(mLevel[ mMaxRefine ].mprsCells[1]+rcellSize)); // DEBUG +#endif // COMPRESSGRIDS==0 + + LbmFloat lcfdimFac = 8.0; + if(D::cDimension==2) lcfdimFac = 4.0; + for(int i=mMaxRefine-1; i>=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 ", " "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5)<<" "<<(LbmFloat)(D::mSizex+1.0)<<" " ); + D::mpIso->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;ak<D::mSizez+2+twodOff;ak++) + for(int aj=0;aj<D::mSizey+2;aj++) + for(int ai=0;ai<D::mSizex+2;ai++) { *D::mpIso->getData(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:"<<mDomainBound,10); + } else if(mDomainBound.find(string("part")) != string::npos) { + domainBoundType = CFBnd | CFBndPartslip; // part slip type + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10); + } else { + domainBoundType = CFBnd | CFBndNoslip; + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10); + } + + // use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips) + int domainobj = (int)(D::mpGiObjects->size()); + domainBoundType |= (domainobj<<24); + //for(int i=0; i<(int)(domainobj+0); i++) { + //errMsg("GEOIN","i"<<i<<" "<<(*D::mpGiObjects)[i]->getName()); + //if((*D::mpGiObjects)[i] == D::mpIso) { + //check... + //} + //} + //errMsg("GEOIN"," dm "<<(domainBoundType>>24)); + + for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) + for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { + initEmptyCell(mMaxRefine, i,0,k, domainBoundType, 0.0, BND_FILL); + initEmptyCell(mMaxRefine, i,mLevel[mMaxRefine].lSizey-1,k, domainBoundType, 0.0, BND_FILL); + } + + if(D::cDimension == 3) { + // only for 3D + for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) + for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { + initEmptyCell(mMaxRefine, i,j,0, domainBoundType, 0.0, BND_FILL); + initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-1, domainBoundType, 0.0, BND_FILL); + } + } + + for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) + for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { + initEmptyCell(mMaxRefine, 0,j,k, domainBoundType, 0.0, BND_FILL); + initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-1,j,k, domainBoundType, 0.0, BND_FILL); + // DEBUG BORDER! + //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL); + } + + // TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 + /*for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) + for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { + initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL); + } + for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) + for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { + initEmptyCell(mMaxRefine, i,1,k, domainBoundType, 0.0, BND_FILL); + } + // */ + + /*for(int ii=0; ii<(int)pow(2.0,mMaxRefine)-1; ii++) { + errMsg("BNDTESTSYMM","set "<<mLevel[mMaxRefine].lSizex-2-ii ); + for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) + for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { + initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2-ii,j,k, domainBoundType, 0.0, BND_FILL); // SYMM!? 2D? + } + for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) + for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { + initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-2-ii, domainBoundType, 0.0, BND_FILL); // SYMM!? 3D? + } + } + // Symmetry tests */ + + // prepare interface cells + initFreeSurfaces(); + initStandingFluidGradient(); + + // perform first step to init initial mass + mInitialMass = 0.0; + int inmCellCnt = 0; + FSGR_FORIJK1(mMaxRefine) { + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid) ) { + LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0); + FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); } + mInitialMass += fluidRho; + inmCellCnt ++; + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { + mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass); + inmCellCnt ++; + } + } + mCurrentVolume = mCurrentMass = mInitialMass; + + ParamVec cspv = D::mpParam->calculateCellSize(); + 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:"<<mInitialMass<<" normalized:"<<nrmMass, 3); + mInitialMass = 0.0; // reset, and use actual value after first step + + //mStartSymm = false; +#if ELBEEM_BLENDER!=1 + if((D::cDimension==2)&&(D::mSizex<200)) { + if(!checkSymmetry("init")) { + errMsg("LbmFsgrSolver::initialize","Unsymmetric init..."); + } else { + errMsg("LbmFsgrSolver::initialize","Symmetric init!"); + } + } +#endif // ELBEEM_BLENDER!=1 + + + // ---------------------------------------------------------------------- + // coarsen region + myTime_t fsgrtstart = getTime(); + for(int lev=mMaxRefine-1; lev>=0; lev--) { + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<<lev<<".",8); + performRefinement(lev); + performCoarsening(lev); + coarseRestrictFromFine(lev); + performRefinement(lev); + performCoarsening(lev); + coarseRestrictFromFine(lev); + } + D::markedClearList(); + myTime_t fsgrtend = getTime(); + if(!D::mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< ((fsgrtend-fsgrtstart)/(double)1000.0)<<"s), changes:"<<mNumFsgrChanges , 10 ); } + mNumFsgrChanges = 0; + + for(int l=0; l<D::cDirNum; l++) { + LbmFloat area = 0.5 * 0.5 *0.5; + if(D::cDimension==2) area = 0.5 * 0.5; + + if(D::dfVecX[l]!=0) area *= 0.5; + if(D::dfVecY[l]!=0) area *= 0.5; + if(D::dfVecZ[l]!=0) area *= 0.5; + mFsgrCellArea[l] = area; + } // l + /*for(int lev=0; lev<mMaxRefine; lev++) { + FSGR_FORIJK_BOUNDS(lev) { + if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { + if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { + LbmFloat totArea = mFsgrCellArea[0]; // for l=0 + for(int l=1; l<D::cDirNum; l++) { + int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& + (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + ) { + //LbmFloat area = 0.25; if(D::dfVecX[l]!=0) area *= 0.5; if(D::dfVecY[l]!=0) area *= 0.5; if(D::dfVecZ[l]!=0) area *= 0.5; + totArea += mFsgrCellArea[l]; + } + } // l + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; + } else if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFEmpty) { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; + } else { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; + } + errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); + } + } } // */ + + // now really done... + debugOut("LbmFsgrSolver::initialize : Init done ...",10); + D::mInitDone = 1; + + // make sure both sets are ok + // copy from other to curr + 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 */ + + + + if(D::cDimension==2) { + if(mOutputSurfacePreview) { + errMsg("LbmFsgrSolver::init","No preview in 2D allowed!"); + mOutputSurfacePreview = 0; } + } + if(mOutputSurfacePreview) { + + //int previewSize = mOutputSurfacePreview; + // same as normal one, but use reduced size + mpPreviewSurface = new IsoSurface( D::mIsoValue, false ); + mpPreviewSurface->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="<<PRINT_IJK); + for(int l=0; l<D::cDfNum; l++) { + debMsgDirect(" df="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, l) ); + } + debMsgDirect(" m="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dMass) ); + debMsgDirect(" f="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dFfrac) ); + debMsgDirect(" x="<< QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); + } } // COMPRT ON */ + return true; +} + + + +/*****************************************************************************/ +/*! perform geometry init (if switched on) */ +/*****************************************************************************/ +template<class D> +bool +LbmFsgrSolver<D>::initGeometryFlags() { + int level = mMaxRefine; + myTime_t geotimestart = getTime(); + ntlGeometryObject *pObj; + // getCellSize (due to forced cubes, use x values) + ntlVec3Gfx dvec( (D::mvGeoEnd[0]-D::mvGeoStart[0])/ ((LbmFloat)D::mSizex*2.0)); + bool thinHit = false; + // real cell size from now on... + dvec *= 2.0; + ntlVec3Gfx nodesize = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; + dvec = nodesize; + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< D::mGeoInitId <<") v"<<dvec,3); + + /* set interface cells */ + D::initGeoTree(D::mGeoInitId); + ntlVec3Gfx maxIniVel = vec2G( D::mpParam->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="<<allowMax ,5); + if(D::mpParam->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;j<mLevel[level].lSizey-1;j++) { + for(int i=1;i<mLevel[level].lSizex-1;i++) { + CellFlagType ntype = CFInvalid; + if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance)) { + //if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(1.0,0.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[0]*0.5, thinHit, true)) { + pObj = (*D::mpGiObjects)[OId]; + switch( pObj->getGeoInitType() ){ + 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<mLevel[level].lSizex-1)) { + dcnt += dvec[0]; i++; + savedNodes++; + if(ntype != CFInvalid) { + // rho,mass,OId are still inited from above + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + } + } + } + // * + + } + } + } // zmax + // */ + + /* + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + for(int i=1;i<mLevel[level].lSizex-1;i++) { + for(int j=1;j<mLevel[level].lSizey-1;j++) { + //errMsg("INIT0","at "<<PRINT_IJK<<" p="<<GETPOS(i,j,k)<<" j"<<j<<" "<<mLevel[level].lSizey); + //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + CellFlagType ntype = CFInvalid; + //errMsg("INIT1","at "<<PRINT_IJK<<" p="<<GETPOS(i,j,k)); + //if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,1.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[1]*0.5)) { + if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,1.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[1]*0.5, thinHit, true)) { + pObj = (*D::mpGiObjects)[OId]; + switch( pObj->getGeoInitType() ){ + 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] ); + } + //errMsg("INITT","at "<<PRINT_IJK<<" t="<<ntype<<" d="<<distance); + + // walk along x until hit for following inits + if(distance<=-1.0) { distance = 100.0; } + if(distance>=0.0) { + gfxReal dcnt=dvec[1]; + while(( dcnt< distance-dvec[1] )&&(j+1<mLevel[level].lSizey-1)) { + dcnt += dvec[1]; j++; + //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + savedNodes++; + if(ntype != CFInvalid) { + // rho,mass,OId are still inited from above + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + } + } + } + + } + } + } // zmax, j + // */ + + + /* + for(int j=1;j<mLevel[level].lSizey-1;j++) { + for(int i=1;i<mLevel[level].lSizex-1;i++) { + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + CellFlagType ntype = CFInvalid; + if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,0.0,1.0), FGI_ALLBOUNDS, OId, distance, dvec[2]*0.5, thinHit, true)) { + pObj = (*D::mpGiObjects)[OId]; + switch( pObj->getGeoInitType() ){ + 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] ); + } + errMsg("INITZ","at "<<PRINT_IJK<<" t="<<ntype<<" d="<<distance); + + // walk along x until hit for following inits + if(distance<=-1.0) { distance = 100.0; } + if(distance>=0.0) { + gfxReal dcnt=dvec[2]; + while(( dcnt< distance-dvec[2] )&&(k+1<mLevel[level].lSizez-1)) { + dcnt += dvec[2]; k++; + //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + savedNodes++; + if(ntype != CFInvalid) { + // rho,mass,OId are still inited from above + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + } + } + } // * + + } + } + } // zmax, k + // */ + + + // now init fluid layer + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + for(int j=1;j<mLevel[level].lSizey-1;j++) { + for(int i=1;i<mLevel[level].lSizex-1;i++) { + if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + + CellFlagType ntype = CFInvalid; + int inits = 0; + if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance)) { + ntype = CFFluid; + } + if(ntype != CFInvalid) { + // initDefaultCell + rhomass = 1.0; + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + inits++; + } + + // 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+1<mLevel[level].lSizex-1)) { + dcnt += dvec[0]; i++; + savedNodes++; + if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; + if(ntype != CFInvalid) { + // rhomass are still inited from above + initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); + inits++; + } + } + } // distance>0 + + } + } + } // zmax + + D::freeGeoTree(); + myTime_t geotimeend = getTime(); + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< ((geotimeend-geotimestart)/(double)1000.0)<<"s,"<<savedNodes<<") " , 10 ); + //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez)); + return true; +} + +/*****************************************************************************/ +/* init part for all freesurface testcases */ +template<class D> +void +LbmFsgrSolver<D>::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<mInitSurfaceSmoothing; s++) { + FSGR_FORIJK1(mMaxRefine) { + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { + LbmFloat mass = 0.0; + //LbmFloat nbdiv; + FORDF0 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFFluid ){ + mass += 1.0; + } + if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFInter ){ + mass += QCELL(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, dMass); + } + //nbdiv+=1.0; + } + + //errMsg(" I ", PRINT_IJK<<" m"<<mass ); + QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass) = (mass/19.0); + QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dFfrac) = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass); + } + } + + mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; + mLevel[mMaxRefine].setCurr ^= 1; + } + // copy back...? + +} + +/*****************************************************************************/ +/* init part for all freesurface testcases */ +template<class D> +void +LbmFsgrSolver<D>::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="<<gravIMin[0]<<" end="<<gravIMax[0]<<" dir="<<gravDir[0] ); \ + errMsg("Standing fp","Y start="<<gravIMin[1]<<" end="<<gravIMax[1]<<" dir="<<gravDir[1] ); \ + errMsg("Standing fp","Z start="<<gravIMin[2]<<" end="<<gravIMax[2]<<" dir="<<gravDir[2] ); + // _PRINTGDIRS; + + bool gravAbort = false; +#define GRAVLOOP \ + gravAbort=false; \ + for(gravIndex[2]= gravIMin[2]; (gravIndex[2]!=gravIMax[2])&&(!gravAbort); gravIndex[2] += gravDir[2]) \ + for(gravIndex[1]= gravIMin[1]; (gravIndex[1]!=gravIMax[1])&&(!gravAbort); gravIndex[1] += gravDir[1]) \ + for(gravIndex[0]= gravIMin[0]; (gravIndex[0]!=gravIMax[0])&&(!gravAbort); gravIndex[0] += gravDir[0]) + + GRAVLOOP { + int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; + //if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) {debMsgStd("Standing fluid preinit", DM_MSG, "fluidheightinit check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 ); } + //STANDFLAGCHECK(gravIndex[maxGravComp]); + if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || + ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ + int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp])); + if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] ); + //if(gravIndex[maxGravComp]>1) + if(fluidHeight>1) + { + haveStandingFluid = fluidHeight; //gravIndex[maxGravComp]; + gravIMax[maxGravComp] = gravIndex[maxGravComp] + gravDir[maxGravComp]; + } + gravAbort = true; continue; + } + } // GRAVLOOP + // _PRINTGDIRS; + + LbmFloat fluidHeight; + //if(gravDir>0) { fluidHeight = (LbmFloat)haveStandingFluid; + //} else { fluidHeight = (LbmFloat)haveStandingFluid; } + fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp])); + if(debugStandingPreinit) debMsgStd("Standing fluid preinit", DM_MSG, "fheight="<<fluidHeight<<" min="<<PRINT_VEC(gravIMin[0],gravIMin[1], gravIMin[2])<<" max="<<PRINT_VEC(gravIMax[0], gravIMax[1],gravIMax[2])<< + " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10); + + if(mDisableStandingFluidInit) { + debMsgStd("Standing fluid preinit", DM_MSG, "Should be performed - but skipped due to mDisableStandingFluidInit flag set!", 2); + haveStandingFluid=0; + } + + // copy flags and init , as no flags will be changed during grav init + // also important for corasening later on + const int lev = mMaxRefine; + CellFlagType nbflag[LBM_DFNUM], nbored; + for(int k=D::getForZMinBnd();k<D::getForZMaxBnd();++k) { + for(int j=0;j<mLevel[lev].lSizey-0;++j) { + for(int i=0;i<mLevel[lev].lSizex-0;++i) { + if( (RFLAG(lev, i,j,k,SRCS(lev)) & (CFFluid)) ) { + nbored = 0; + FORDF1 { + nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); + nbored |= nbflag[l]; + } + if(nbored&CFBnd) { + RFLAG(lev, i,j,k,SRCS(lev)) &= (~CFNoBndFluid); + } else { + RFLAG(lev, i,j,k,SRCS(lev)) |= CFNoBndFluid; + } + } + RFLAG(lev, i,j,k,TSET(lev)) = RFLAG(lev, i,j,k,SRCS(lev)); + } } } + + if(haveStandingFluid) { + int rhoworkSet = mLevel[lev].setCurr; + myTime_t timestart = getTime(); // FIXME use user time here? +#if OPT3D==1 + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM], lcsmomega; +#endif // OPT3D==true + + GRAVLOOP { + int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; + //debMsgStd("Standing fluid preinit", DM_MSG, " init check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 ); + if( ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFInter)) ) || + ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFEmpty)) ) ){ + //gravAbort = true; + continue; + } + + LbmFloat rho = 1.0; + // 1/6 velocity from denisty gradient, 1/2 for delta of two cells + rho += 1.0* (fluidHeight-gravIndex[maxGravComp]) * + (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega); + if(debugStandingPreinit) + if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) { + errMsg("Standing fp","gi="<<gravIndex[maxGravComp]<<" rho="<<rho<<" at "<<PRINT_IJK); + } + + if( (RFLAG(lev, i,j,k, rhoworkSet) & CFFluid) || + (RFLAG(lev, i,j,k, rhoworkSet) & CFInter) ) { + FORDF0 { QCELL(lev, i,j,k, rhoworkSet, l) *= rho; } + QCELL(lev, i,j,k, rhoworkSet, dMass) *= rho; + } + + } // GRAVLOOP + debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited", 8); + + int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) ); + preinitSteps = (haveStandingFluid>>2); // not much use...? + //preinitSteps = 4; // DEBUG!!!! + //D::mInitDone = 1; // GRAVTEST + //preinitSteps = 0; + debMsgNnl("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10); + for(int s=0; s<preinitSteps; s++) { + int workSet = SRCS(lev); //mLevel[lev].setCurr; + int otherSet = TSET(lev); //mLevel[lev].setOther; + debMsgDirect("."); + if(debugStandingPreinit) debMsgStd("Standing fluid preinit", DM_MSG, "s="<<s<<" curset="<<workSet<<" srcs"<<SRCS(lev), 10); + LbmFloat *ccel; + LbmFloat *tcel; + LbmFloat m[LBM_DFNUM]; + + // grav loop not necessary here +#define NBFLAG(l) (nbflag[(l)]) + LbmFloat rho, ux,uy,uz, usqr; + int kstart=D::getForZMinBnd(), kend=D::getForZMaxBnd(); +#if COMPRESSGRIDS==0 + for(int k=kstart;k<kend;++k) { +#else // COMPRESSGRIDS==0 + int kdir = 1; // COMPRT ON + if(mLevel[lev].setCurr==1) { + kdir = -1; + int temp = kend; + kend = kstart-1; + kstart = temp-1; + } // COMPRT + for(int k=kstart;k!=kend;k+=kdir) { + + //errMsg("LbmFsgrSolver::mainLoop","k="<<k<<" ks="<<kstart<<" ke="<<kend<<" kdir="<<kdir ); // debug +#endif // COMPRESSGRIDS==0 + + for(int j=0;j<mLevel[lev].lSizey-0;++j) { + for(int i=0;i<mLevel[lev].lSizex-0;++i) { + const CellFlagType currFlag = RFLAG(lev, i,j,k,workSet); + if( (currFlag & (CFEmpty|CFBnd)) ) continue; + ccel = RACPNT(lev, i,j,k,workSet); + tcel = RACPNT(lev, i,j,k,otherSet); + + if( (currFlag & (CFInter)) ) { + // copy all values + for(int l=0; l<dTotalNum;l++) { RAC(tcel,l) = RAC(ccel,l); } + continue; + } + + if( (currFlag & CFNoBndFluid)) { + OPTIMIZED_STREAMCOLLIDE; + } else { + FORDF1 { + nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); + } + DEFAULT_STREAM; + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + DEFAULT_COLLIDE; + } + for(int l=LBM_DFNUM; l<dTotalNum;l++) { RAC(tcel,l) = RAC(ccel,l); } + } } } // GRAVLOOP + + mLevel[lev].setOther = mLevel[lev].setCurr; + mLevel[lev].setCurr ^= 1; + } + //D::mInitDone = 0; // GRAVTEST + // */ + + myTime_t timeend = getTime(); + debMsgDirect(" done, "<<((timeend-timestart)/(double)1000.0)<<"s \n"); +#undef NBFLAG + } +} + + + +template<class D> +bool +LbmFsgrSolver<D>::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<maxMsgs) { msgs++; + errMsg("EFLAG", PRINT_IJK<<"s"<<s<<" flag "<<RFLAG(lev, i,j,k,s)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" flag "<<RFLAG(lev, inb,j,k,s) ); + } + } + if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } + symm = false; + } + if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true; + if(D::cDimension==2) { + if(msgs<maxMsgs) { msgs++; + //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl); + errMsg("EMASS", PRINT_IJK<<"s"<<s<<" mass "<<QCELL(lev, i,j,k,s, dMass)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" mass "<<QCELL(lev, inb,j,k,s, dMass) ); + } + } + if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } + symm = false; + } + + LbmFloat nbrho = QCELL(lev, i,j,k, s, dC); + FORDF1 { nbrho += QCELL(lev, i,j,k, s, l); } + LbmFloat otrho = QCELL(lev, inb,j,k, s, dC); + FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); } + if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true; + if(D::cDimension==2) { + if(msgs<maxMsgs) { msgs++; + //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl); + errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho ); + } + } + if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } + symm = false; + } + } + } } + } // lev + LbmFloat maxdiv =0.0; + if(erro) { + errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv ); + //if(D::cDimension==2) D::mPanic = true; + //return false; + } else { + errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv ); + } + // all ok... + return symm; +}// */ + + +#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/lbminterface.cpp b/intern/elbeem/intern/solver_interface.cpp index db7705de0a8..3d77e4a4968 100644 --- a/intern/elbeem/intern/lbminterface.cpp +++ b/intern/elbeem/intern/solver_interface.cpp @@ -11,12 +11,9 @@ *****************************************************************************/ /* LBM Files */ -#include "lbmdimensions.h" -#include "lbminterface.h" -#include "lbmfunctions.h" +#include "solver_interface.h" #include "ntl_scene.h" #include "ntl_ray.h" -#include "typeslbm.h" /*****************************************************************************/ @@ -401,6 +398,7 @@ void LbmSolverInterface::initGeoTree(int id) { mpGiObjects = scene->getObjects(); mGiObjInside.resize( mpGiObjects->size() ); mGiObjDistance.resize( mpGiObjects->size() ); + mGiObjSecondDist.resize( mpGiObjects->size() ); for(size_t i=0; i<mpGiObjects->size(); i++) { if((*mpGiObjects)[i]->getGeoInitIntersect()) mAccurateGeoinit=true; } @@ -436,6 +434,7 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int for(size_t i=0; i<mGiObjInside.size(); i++) { mGiObjInside[i] = 0; mGiObjDistance[i] = -1.0; + mGiObjSecondDist[i] = -1.0; } // if not inside, return distance to first hit gfxReal firstHit=-1.0; @@ -517,6 +516,142 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int 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; i<mGiObjInside.size(); i++) { + mGiObjInside[i] = 0; + mGiObjDistance[i] = -1.0; + mGiObjSecondDist[i] = -1.0; + } + // if not inside, return distance to first hit + gfxReal firstHit=-1.0; + int firstOId = -1; + thinHit = false; + + if(mAccurateGeoinit) { + while(!done) { + // find first inside intersection + ntlTriangle *triIns = NULL; + distance = -1.0; + ntlVec3Gfx normal(0.0); + mpGiTree->intersect(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:"<<OId<<" org"<<org<<" norg"<<norg); + } else { + // inside hit + //if(mGiObjDistance[OId]<0.0) mGiObjDistance[OId] = distance; + //errMsg("III"," oid:"<<OId<<" org"<<org<<" norg"<<norg); + if(mGiObjInside[OId]==1) { + // second inside hit + if(mGiObjSecondDist[OId]<0.0) mGiObjSecondDist[OId] = distance; + } + } + mGiObjInside[OId]++; + // always store first hit for thin obj init + if(mGiObjDistance[OId]<0.0) mGiObjDistance[OId] = distance; + + norg += normal * getVecEpsilon(); + ray = ntlRay(norg, dir, 0, 1.0, mpGlob); + // remember first hit distance, in case we're not + // inside anything + if(firstHit<0.0) { + firstHit = distance; + firstOId = OId; + } + } else { + // no more intersections... return false + done = true; + //if(insCnt%2) inside=true; + } + } + + distance = -1.0; + // standard inside check + for(size_t i=0; i<mGiObjInside.size(); i++) { + if(((mGiObjInside[i]%2)==1)&&(mGiObjDistance[i]>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<mGiObjInside.size(); i++) { + if((mGiObjInside[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(thisdist<halfCellsize) distance-=2.0*halfCellsize; + } // ? */ + } + //errMsg("CHIII","i"<<inside<<" fh"<<firstHit<<" fo"<<firstOId<<" - h"<<distance<<" o"<<OId); + + return inside; + } else { + + // find first inside intersection + ntlTriangle *triIns = NULL; + distance = -1.0; + ntlVec3Gfx normal(0.0); + mpGiTree->intersect(ray,distance,normal, triIns, flags, true); + if(triIns) { + // check outside intersect + LbmFloat orientation = dot(normal, dir); + if(orientation<=0.0) return false; + + OId = triIns->getObjectId(); + return true; + } + return false; + } +} /*****************************************************************************/ /*! get max. velocity of all objects to initialize as fluid regions */ diff --git a/intern/elbeem/intern/lbminterface.h b/intern/elbeem/intern/solver_interface.h index 073558e1309..55e5d61fe45 100644 --- a/intern/elbeem/intern/lbminterface.h +++ b/intern/elbeem/intern/solver_interface.h @@ -288,6 +288,8 @@ class LbmSolverInterface void freeGeoTree(); /*! check for a certain flag type at position org (needed for e.g. quadtree refinement) */ bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance); + bool geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir, int flags, int &OId, gfxReal &distance, + const gfxReal halfCellsize, bool &thinHit, bool recurse); /*! set render globals, for scene/tree access */ void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; }; /*! get max. velocity of all objects to initialize as fluid regions */ @@ -378,6 +380,13 @@ class LbmSolverInterface virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0; virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0; + // gui/output debugging functions +#if LBM_USE_GUI==1 + virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifier cell ) = 0; + virtual void lbmDebugDisplay(fluidDispSettings *dispset) = 0; + virtual void lbmMarkedCellDisplay() = 0; +#endif // LBM_USE_GUI==1 + virtual void debugPrintNodeInfo(CellIdentifier cell, int forceSet=-1) = 0; // debugging cell marker functions @@ -500,6 +509,7 @@ class LbmSolverInterface vector<int> mGiObjInside; /*! inside which objects? */ vector<gfxReal> mGiObjDistance; + vector<gfxReal> mGiObjSecondDist; /*! remember globals */ ntlRenderGlobals *mpGlob; @@ -509,6 +519,375 @@ class LbmSolverInterface }; +//! shorten static const definitions +#define STCON static const + + +/*****************************************************************************/ +/*! class for solver templating - 3D implementation */ +class LbmD3Q19 { + + public: + + // constructor, init interface + LbmD3Q19() {}; + // virtual destructor + virtual ~LbmD3Q19() {}; + //! id string of solver + string getIdString() { return string("3D"); } + + //! how many dimensions? + STCON int cDimension; + + // Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + //! direction vector contain vecs for all spatial dirs, even if not used for LBM model + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirT = 5, + cDirB = 6, + cDirNE = 7, + cDirNW = 8, + cDirSE = 9, + cDirSW = 10, + cDirNT = 11, + cDirNB = 12, + cDirST = 13, + cDirSB = 14, + cDirET = 15, + cDirEB = 16, + cDirWT = 17, + cDirWB = 18 + } dfDir; + + /* Vector Order 3D: + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + * 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 + * 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 + * 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 + */ + + /*! name of the dist. function + only for nicer output */ + STCON char* dfString[ 19 ]; + + /*! index of normal dist func, not used so far?... */ + STCON int dfNorm[ 19 ]; + + /*! index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 19 ]; + + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 19 ]; + + /*! dist func vectors */ + STCON int dfVecX[ 27 ]; + STCON int dfVecY[ 27 ]; + STCON int dfVecZ[ 27 ]; + + /*! arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 27 ]; + STCON LbmFloat dfDvecY[ 27 ]; + STCON LbmFloat dfDvecZ[ 27 ]; + + /*! principal directions */ + STCON int princDirX[ 2*3 ]; + STCON int princDirY[ 2*3 ]; + STCON int princDirZ[ 2*3 ]; + + /*! vector lengths */ + STCON LbmFloat dfLength[ 19 ]; + + /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 19 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ]; + static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ]; + +}; // LbmData3D + + + +/*****************************************************************************/ +//! class for solver templating - 2D implementation +class LbmD2Q9 { + + public: + + // constructor, init interface + LbmD2Q9() {}; + // virtual destructor + virtual ~LbmD2Q9() {}; + //! id string of solver + string getIdString() { return string("2D"); } + + //! how many dimensions? + STCON int cDimension; + + //! Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirNE = 5, + cDirNW = 6, + cDirSE = 7, + cDirSW = 8 + } dfDir; + + /* Vector Order 2D: + * 0 1 2 3 4 5 6 7 8 + * 0, 0,0, 1,-1, 1,-1,1,-1 + * 0, 1,-1, 0,0, 1,1,-1,-1 */ + + /* name of the dist. function + only for nicer output */ + STCON char* dfString[ 9 ]; + + /* index of normal dist func, not used so far?... */ + STCON int dfNorm[ 9 ]; + + /* index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 9 ]; + + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 9 ]; + + /* dist func vectors */ + STCON int dfVecX[ 9 ]; + STCON int dfVecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON int dfVecZ[ 9 ]; + + /* arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 9 ]; + STCON LbmFloat dfDvecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON LbmFloat dfDvecZ[ 9 ]; + + /*! principal directions */ + STCON int princDirX[ 2*2 ]; + STCON int princDirY[ 2*2 ]; + STCON int princDirZ[ 2*2 ]; + + /* vector lengths */ + STCON LbmFloat dfLength[ 9 ]; + + /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 9 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ]; + static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ]; + +}; // LbmData3D + + + +// lbmdimensions + +// not needed hereafter +#undef STCON + + + +/*****************************************************************************/ +//! class for solver templating - lbgk (srt) model implementation +template<class DQ> +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; l<DQ::cDfNum; l++) { + rho += df[l]; + ux += (DQ::dfDvecX[l]*df[l]); + uy += (DQ::dfDvecY[l]*df[l]); + uz += (DQ::dfDvecZ[l]*df[l]); + } + for(int l=0; l<DQ::cDfNum; l++) { + //LbmFloat tmp = (ux*DQ::dfDvecX[l]+uy*DQ::dfDvecY[l]+uz*DQ::dfDvecZ[l]); + df[l] = (1.0-omega ) * df[l] + omega * ( getCollideEq(l,rho,ux,uy,uz) ); + } + + mux = ux; + muy = uy; + muz = uz; + outrho = rho; + };*/ + + // LES functions + inline LbmFloat getLesNoneqTensorCoeff( + LbmFloat df[], + LbmFloat feq[] ) { + LbmFloat Qo = 0.0; + for(int m=0; m< ((DQ::cDimension*DQ::cDimension)-DQ::cDimension)/2 ; m++) { + LbmFloat qadd = 0.0; + for(int l=1; l<DQ::cDfNum; l++) { + if(DQ::lesCoeffOffdiag[m][l]==0.0) continue; + qadd += DQ::lesCoeffOffdiag[m][l]*(df[l]-feq[l]); + } + Qo += (qadd*qadd); + } + Qo *= 2.0; // off diag twice + for(int m=0; m<DQ::cDimension; m++) { + LbmFloat qadd = 0.0; + for(int l=1; l<DQ::cDfNum; l++) { + if(DQ::lesCoeffDiag[m][l]==0.0) continue; + qadd += DQ::lesCoeffDiag[m][l]*(df[l]-feq[l]); + } + Qo += (qadd*qadd); + } + Qo = sqrt(Qo); + return Qo; + } + inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) { + const LbmFloat tau = 1.0/omega; + const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0); + const LbmFloat C = csmago; + const LbmFloat Csqr = C*C; + LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr); + return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) ); + } + + // "normal" collision + inline void collideArrays(LbmFloat df[], + LbmFloat &outrho, // out only! + // velocity modifiers (returns actual velocity!) + LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, + LbmFloat omega, LbmFloat csmago, LbmFloat *newOmegaRet = NULL + ) { + LbmFloat rho=df[0]; + LbmFloat ux = mux; + LbmFloat uy = muy; + LbmFloat uz = muz; + for(int l=1; l<DQ::cDfNum; l++) { + rho += df[l]; + ux += (DQ::dfDvecX[l]*df[l]); + uy += (DQ::dfDvecY[l]*df[l]); + uz += (DQ::dfDvecZ[l]*df[l]); + } + LbmFloat feq[19]; + for(int l=0; l<DQ::cDfNum; l++) { + feq[l] = getCollideEq(l,rho,ux,uy,uz); + } + + LbmFloat omegaNew; + if(csmago>0.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<DQ::cDfNum; l++) { + df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l]; + } + + mux = ux; + muy = uy; + muz = uz; + outrho = rho; + }; + +}; // LBGK + +#ifdef LBMMODEL_DEFINED +// force compiler error! +ERROR - Dont include several LBM models at once... +#endif +#define LBMMODEL_DEFINED 1 + + +typedef LbmModelLBGK< LbmD2Q9 > LbmBGK2D; +typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D; + + //! helper function to convert flag to string (for debuggin) string convertCellFlagType2String( CellFlagType flag ); string convertSingleFlag2String(CellFlagType cflag); diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp new file mode 100644 index 00000000000..8b4a33e42f3 --- /dev/null +++ b/intern/elbeem/intern/solver_main.cpp @@ -0,0 +1,2684 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004,2005 Nils Thuerey + * + * Standard LBM Factory implementation + * + *****************************************************************************/ + +#include "solver_class.h" +#include "solver_relax.h" + +/*****************************************************************************/ +/*! debug object display */ +/*****************************************************************************/ +template<class D> +vector<ntlGeometryObject*> LbmFsgrSolver<D>::getDebugObjects() { + vector<ntlGeometryObject*> debo; + if(mOutputSurfacePreview) { + debo.push_back( mpPreviewSurface ); + } + return debo; +} + +/*****************************************************************************/ +/*! perform a single LBM step */ +/*****************************************************************************/ + +template<class D> +void +LbmFsgrSolver<D>::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 : "<<D::mStepCnt, 10); + if(!D::mSilent){ debMsgNnl("LbmFsgrSolver::step", DM_MSG, D::mName<<" cnt:"<<D::mStepCnt<<" ", 10); } + //debMsgDirect( "LbmFsgrSolver::step : "<<D::mStepCnt<<" "); + myTime_t timestart = getTime(); + //myTime_t timestart = 0; + //if(mStartSymm) { checkSymmetry("step1"); } // DEBUG + + // important - keep for tadap + mCurrentMass = D::mFixMass; // reset here for next step + mCurrentVolume = 0.0; + + //stats + mMaxVlen = mMxvz = mMxvy = mMxvx = 0.0; + + //change to single step advance! + int levsteps = 0; + int dsbits = D::mStepCnt ^ (D::mStepCnt-1); + //errMsg("S"," step:"<<D::mStepCnt<<" s-1:"<<(D::mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits)); + for(int lev=0; lev<=mMaxRefine; lev++) { + //if(! (D::mStepCnt&(1<<lev)) ) { + if( dsbits & (1<<(mMaxRefine-lev)) ) { + //errMsg("S"," l"<<lev); + + if(lev==mMaxRefine) { + // always advance fine level... + fineAdvance(); + } else { + performRefinement(lev); + performCoarsening(lev); + coarseRestrictFromFine(lev); + coarseAdvance(lev); + } +#if FSGR_OMEGA_DEBUG==1 + errMsg("LbmFsgrSolver::step","LES stats l="<<lev<<" omega="<<mLevel[lev].omega<<" avgOmega="<< (mLevel[lev].avgOmega/mLevel[lev].avgOmegaCnt) ); + mLevel[lev].avgOmega = 0.0; mLevel[lev].avgOmegaCnt = 0.0; +#endif // FSGR_OMEGA_DEBUG==1 + levsteps++; + } + mCurrentMass += mLevel[lev].lmass; + mCurrentVolume += mLevel[lev].lvolume; + } + + // prepare next step + D::mStepCnt++; + + + // some dbugging output follows + // calculate MLSUPS + myTime_t timeend = getTime(); + + D::mNumUsedCells += mNumInterdCells; // count both types for MLSUPS + mAvgNumUsedCells += D::mNumUsedCells; + D::mMLSUPS = (D::mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000); + if(D::mMLSUPS>10000){ D::mMLSUPS = -1; } + else { mAvgMLSUPS += D::mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups + + LbmFloat totMLSUPS = ( ((mLevel[mMaxRefine].lSizex-2)*(mLevel[mMaxRefine].lSizey-2)*(getForZMax1(mMaxRefine)-getForZMin1())) / ((timeend-timestart)/(double)1000.0) ) / (1000000); + if(totMLSUPS>10000) totMLSUPS = -1; + mNumInvIfTotal += mNumInvIfCells; // debug + + // do some formatting + if(!D::mSilent){ + string sepStr(""); // DEBUG +#ifndef USE_MSVC6FIXES + int avgcls = (int)(mAvgNumUsedCells/(long long int)D::mStepCnt); +#else + int avgcls = (int)(mAvgNumUsedCells/(_int64)D::mStepCnt); +#endif + debMsgDirect( + "mlsups(curr:"<<D::mMLSUPS<< + " avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<< sepStr<< + " totcls:"<<(D::mNumUsedCells)<< sepStr<< + " avgcls:"<< avgcls<< sepStr<< + " intd:"<<mNumInterdCells<< sepStr<< + " invif:"<<mNumInvIfCells<< sepStr<< + " invift:"<<mNumInvIfTotal<< sepStr<< + " fsgrcs:"<<mNumFsgrChanges<< sepStr<< + " filled:"<<D::mNumFilledCells<<", emptied:"<<D::mNumEmptiedCells<< sepStr<< + " mMxv:"<<mMxvx<<","<<mMxvy<<","<<mMxvz<<", tscnts:"<<mTimeSwitchCounts<< sepStr<< + " probs:"<<mNumProblems<< sepStr<< + " simt:"<<mSimulationTime<< sepStr<< + " for '"<<D::mName<<"' " ); + + debMsgDirect(std::endl); + debMsgDirect(D::mStepCnt<<": dccd="<< mCurrentMass<<"/"<<mCurrentVolume<<"(fix="<<D::mFixMass<<",ini="<<mInitialMass<<") "); + debMsgDirect(std::endl); + + // nicer output + debMsgDirect(std::endl); // + //debMsgStd(" ",DM_MSG," ",10); + } else { + debMsgDirect("."); + //if((mStepCnt%10)==9) debMsgDirect("\n"); + } + + if(D::mStepCnt==1) { + mMinNoCells = mMaxNoCells = D::mNumUsedCells; + } else { + if(D::mNumUsedCells>mMaxNoCells) mMaxNoCells = D::mNumUsedCells; + if(D::mNumUsedCells<mMinNoCells) mMinNoCells = D::mNumUsedCells; + } + + // mass scale test + if((mMaxRefine>0)&&(mInitialMass>0.0)) { + LbmFloat mscale = mInitialMass/mCurrentMass; + + mscale = 1.0; + const LbmFloat dchh = 0.001; + if(mCurrentMass<mInitialMass) mscale = 1.0+dchh; + if(mCurrentMass>mInitialMass) 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:"<<mInitialMass<<", cur:"<<mCurrentMass<<", f="<<ABS(mInitialMass/mCurrentMass) + <<" step:"<<D::mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" " + ); + errMsg("MDTDD","\n\n"); + + mscount++; + for(int lev=mMaxRefine; lev>=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: "<<mInitialMass, 2); + } + } + + // one of the last things to do - adapt timestep + // was in fineAdvance before... + if(mTimeAdap) { + adaptTimestep(); + } // time adaptivity + + // debug - raw dump of ffrac values + /*if((D::mStepCnt%100)==1){ + std::ostringstream name; + name <<"fill_" << D::mStepCnt <<".dump"; + FILE *file = fopen(name.str().c_str(),"w"); + for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { + for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) { + for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { + float val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); + //fwrite( &val, sizeof(val), 1, file); // binary + fprintf(file, "%f ",val); // text + //errMsg("W", PRINT_IJK<<" val:"<<val); + } + fprintf(file, "\n"); // text + } + fprintf(file, "\n"); // text + } + fclose(file); + } // */ + +} + +template<class D> +void +LbmFsgrSolver<D>::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 "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps) ); } + + // update other set + mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; + mLevel[mMaxRefine].setCurr ^= 1; + mLevel[mMaxRefine].lsteps++; + + // flag init... (work on current set, to simplify flag checks) + reinitFlags( mLevel[mMaxRefine].setCurr ); + if(!D::mSilent){ errMsg("fineAdvance"," flags reinit on set "<< mLevel[mMaxRefine].setCurr ); } +} + + +/*****************************************************************************/ +//! coarse/fine step functions +/*****************************************************************************/ + +// access to own dfs during step (may be changed to local array) +#define MYDF(l) RAC(ccel, l) + +template<class D> +void +LbmFsgrSolver<D>::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<kend;++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=0;i<mLevel[lev].lSizex-2; ) { +#else // COMPRESSGRIDS==0 + int kdir = 1; // COMPRT ON + if(mLevel[mMaxRefine].setCurr==1) { + kdir = -1; + int temp = kend; + kend = kstart-1; + kstart = temp-1; + } // COMPRT + +#if PARALLEL==0 + const int id = 0, Nthrds = 1; +#endif // PARALLEL==1 + const int Nj = mLevel[mMaxRefine].lSizey; + int jstart = 0+( id * (Nj / Nthrds) ); + int jend = 0+( (id+1) * (Nj / Nthrds) ); + if( ((Nj/Nthrds) *Nthrds) != Nj) { + errMsg("LbmFsgrSolver","Invalid domain size Nj="<<Nj<<" Nthrds="<<Nthrds); + } + // cutoff obstacle boundary + if(jstart<1) jstart = 1; + if(jend>mLevel[mMaxRefine].lSizey-1) jend = mLevel[mMaxRefine].lSizey-1; + +#if PARALLEL==1 + errMsg("LbmFsgrSolver::mainLoop","id="<<id<<" js="<<jstart<<" je="<<jend<<" jdir="<<(1) ); // debug +#endif // PARALLEL==1 + for(int k=kstart;k!=kend;k+=kdir) { + + //errMsg("LbmFsgrSolver::mainLoop","k="<<k<<" ks="<<kstart<<" ke="<<kend<<" kdir="<<kdir<<" x*y="<<mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum ); // debug + pFlagSrc = &RFLAG(lev, 0, jstart, k, SRCS(lev)); // omp test // COMPRT ON + pFlagDst = &RFLAG(lev, 0, jstart, k, TSET(lev)); // omp test + ccel = RACPNT(lev, 0, jstart, k, SRCS(lev)); // omp test + tcel = RACPNT(lev, 0, jstart, k, TSET(lev)); // omp test // COMPRT ON + + //for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int j=jstart;j!=jend;++j) { + for(int i=0;i<mLevel[lev].lSizex-2; ) { +#endif // COMPRESSGRIDS==0 + + ADVANCE_POINTERS(1); +#if FSGR_STRICT_DEBUG==1 + rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG + if( (&RFLAG(lev, i,j,k,mLevel[lev].setCurr) != pFlagSrc) || + (&RFLAG(lev, i,j,k,mLevel[lev].setOther) != pFlagDst) ) { + errMsg("LbmFsgrSolver::mainLoop","Err flagp "<<PRINT_IJK<<"="<< + RFLAG(lev, i,j,k,mLevel[lev].setCurr)<<","<<RFLAG(lev, i,j,k,mLevel[lev].setOther)<<" but is "<< + (*pFlagSrc)<<","<<(*pFlagDst) <<", pointers "<< + (int)(&RFLAG(lev, i,j,k,mLevel[lev].setCurr))<<","<<(int)(&RFLAG(lev, i,j,k,mLevel[lev].setOther))<<" but is "<< + (int)(pFlagSrc)<<","<<(int)(pFlagDst)<<" " + ); + D::mPanic=1; + } + if( (&QCELL(lev, i,j,k,mLevel[lev].setCurr,0) != ccel) || + (&QCELL(lev, i,j,k,mLevel[lev].setOther,0) != tcel) ) { + errMsg("LbmFsgrSolver::mainLoop","Err cellp "<<PRINT_IJK<<"="<< + (int)(&QCELL(lev, i,j,k,mLevel[lev].setCurr,0))<<","<<(int)(&QCELL(lev, i,j,k,mLevel[lev].setOther,0))<<" but is "<< + (int)(ccel)<<","<<(int)(tcel)<<" " + ); + D::mPanic=1; + } +#endif + oldFlag = *pFlagSrc; + // stream from current set to other, then collide and store + + // old INTCFCOARSETEST==1 + if( (oldFlag & (CFGrFromCoarse)) ) { // interpolateFineFromCoarse test! + if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } + } else { + interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); + calcNumUsedCells++; + } + continue; // interpolateFineFromCoarse test! + } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 + + if(oldFlag & (CFMbndInflow)) { + // fluid & if are ok, fill if later on + int isValid = oldFlag & (CFFluid|CFInter); + const LbmFloat iniRho = 1.0; + const int OId = oldFlag>>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<D::cDfNum; l++) { ofrho += RAC(ccel,l); } +//FST errMsg("TTTfl","at "<<PRINT_IJK<<", rho"<<rho ); + calcCurrentMass += rho; + calcCurrentVolume += 1.0; + continue; + } + + newFlag = oldFlag; + // make sure here: always check which flags to really unset...! + newFlag = newFlag & (~( + CFNoNbFluid|CFNoNbEmpty| CFNoDelete + | CFNoInterpolSrc + | CFNoBndFluid + )); + if(!(nbored&CFBnd)) { + newFlag |= CFNoBndFluid; + } + + // store own dfs and mass + mass = RAC(ccel,dMass); + + // WARNING - only interface cells arrive here! + // read distribution funtions of adjacent cells = stream step + DEFAULT_STREAM; + + if((nbored & CFFluid)==0) { newFlag |= CFNoNbFluid; mNumInvIfCells++; } + if((nbored & CFEmpty)==0) { newFlag |= CFNoNbEmpty; mNumInvIfCells++; } + + // calculate mass exchange for interface cells + LbmFloat myfrac = RAC(ccel,dFfrac); +# define nbdf(l) m[ D::dfInv[(l)] ] + + // update mass + // only do boundaries for fluid cells, and interface cells without + // any fluid neighbors (assume that interface cells _with_ fluid + // neighbors are affected enough by these) + // which Df's have to be reconstructed? + // for fluid cells - just the f_i difference from streaming to empty cells ---- + numRecons = 0; + + FORDF1 { // dfl loop + recons[l] = 0; + // finally, "normal" interface cells ---- + if( NBFLAG(l)&(CFFluid|CFBnd) ) { // NEWTEST! FIXME check!!!!!!!!!!!!!!!!!! + change = nbdf(l) - MYDF(l); + } + // interface cells - distuingish cells that shouldn't fill/empty + else if( NBFLAG(l) & CFInter ) { + + LbmFloat mynbfac = //numNbs[l] / numNbs[0]; + QCELL_NB(lev, i,j,k,SRCS(lev),l, dFlux) / QCELL(lev, i,j,k,SRCS(lev), dFlux); + LbmFloat nbnbfac = 1.0/mynbfac; + //mynbfac = nbnbfac = 1.0; // switch calc flux off + // OLD + if ((oldFlag|NBFLAG(l))&(CFNoNbFluid|CFNoNbEmpty)) { + switch (oldFlag&(CFNoNbFluid|CFNoNbEmpty)) { + case 0: + // we are a normal cell so... + switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { + case CFNoNbFluid: + // just fill current cell = empty neighbor + change = nbnbfac*nbdf(l) ; goto changeDone; + case CFNoNbEmpty: + // just empty current cell = fill neighbor + change = - mynbfac*MYDF(l) ; goto changeDone; + } + break; + + case CFNoNbFluid: + // we dont have fluid nb's so... + switch (NBFLAG(l)&(CFNoNbFluid|CFNoNbEmpty)) { + case 0: + case CFNoNbEmpty: + // we have no fluid nb's -> 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 "<<PRINT_IJK<<",l"<<l<<" m"<<mass<<",c"<<change<<" nbflag"<<convertCellFlagType2String(NBFLAG(l))<<" nbdf"<<nbdf(l)<<" mydf"<<MYDF(l)<<" isflix"<<((NBFLAG(l)&(CFFluid|CFBnd) )!=0) ); + // 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==0 + oldRho=RAC(ccel,0); + oldUx = oldUy = oldUz = 0.0; + for(int l=1; l<D::cDfNum; l++) { + oldRho += RAC(ccel,l); + oldUx += (D::dfDvecX[l]*RAC(ccel,l)); + oldUy += (D::dfDvecY[l]*RAC(ccel,l)); + oldUz += (D::dfDvecZ[l]*RAC(ccel,l)); + } +#else // OPT3D==0 + oldRho = + RAC(ccel,dC) + RAC(ccel,dN ) + + RAC(ccel,dS ) + RAC(ccel,dE ) + + RAC(ccel,dW ) + RAC(ccel,dT ) + + RAC(ccel,dB ) + RAC(ccel,dNE) + + RAC(ccel,dNW) + RAC(ccel,dSE) + + RAC(ccel,dSW) + RAC(ccel,dNT) + + RAC(ccel,dNB) + RAC(ccel,dST) + + RAC(ccel,dSB) + RAC(ccel,dET) + + RAC(ccel,dEB) + RAC(ccel,dWT) + + RAC(ccel,dWB); + + oldUx = + RAC(ccel,dE) - RAC(ccel,dW) + + RAC(ccel,dNE) - RAC(ccel,dNW) + + RAC(ccel,dSE) - RAC(ccel,dSW) + + RAC(ccel,dET) + RAC(ccel,dEB) + - RAC(ccel,dWT) - RAC(ccel,dWB); + + oldUy = + RAC(ccel,dN) - RAC(ccel,dS) + + RAC(ccel,dNE) + RAC(ccel,dNW) + - RAC(ccel,dSE) - RAC(ccel,dSW) + + RAC(ccel,dNT) + RAC(ccel,dNB) + - RAC(ccel,dST) - RAC(ccel,dSB); + + oldUz = + RAC(ccel,dT) - RAC(ccel,dB) + + RAC(ccel,dNT) - RAC(ccel,dNB) + + RAC(ccel,dST) - RAC(ccel,dSB) + + RAC(ccel,dET) - RAC(ccel,dEB) + + RAC(ccel,dWT) - RAC(ccel,dWB); +#endif + + // now reconstruction +#define REFERENCE_PRESSURE 1.0 // always atmosphere... +#if OPT3D==0 + // NOW - construct dist funcs from empty cells + FORDF1 { + if(recons[ l ]) { + m[ D::dfInv[l] ] = + D::getCollideEq(l, REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + + D::getCollideEq(D::dfInv[l], REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + - MYDF( l ); + } + } +#else + ux=oldUx, uy=oldUy, uz=oldUz; // no local vars, only for usqr + rho = REFERENCE_PRESSURE; + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); + if(recons[dN ]) { m[dS ] = EQN + EQS - MYDF(dN ); } + if(recons[dS ]) { m[dN ] = EQS + EQN - MYDF(dS ); } + if(recons[dE ]) { m[dW ] = EQE + EQW - MYDF(dE ); } + if(recons[dW ]) { m[dE ] = EQW + EQE - MYDF(dW ); } + if(recons[dT ]) { m[dB ] = EQT + EQB - MYDF(dT ); } + if(recons[dB ]) { m[dT ] = EQB + EQT - MYDF(dB ); } + if(recons[dNE]) { m[dSW] = EQNE + EQSW - MYDF(dNE); } + if(recons[dNW]) { m[dSE] = EQNW + EQSE - MYDF(dNW); } + if(recons[dSE]) { m[dNW] = EQSE + EQNW - MYDF(dSE); } + if(recons[dSW]) { m[dNE] = EQSW + EQNE - MYDF(dSW); } + if(recons[dNT]) { m[dSB] = EQNT + EQSB - MYDF(dNT); } + if(recons[dNB]) { m[dST] = EQNB + EQST - MYDF(dNB); } + if(recons[dST]) { m[dNB] = EQST + EQNB - MYDF(dST); } + if(recons[dSB]) { m[dNT] = EQSB + EQNT - MYDF(dSB); } + if(recons[dET]) { m[dWB] = EQET + EQWB - MYDF(dET); } + if(recons[dEB]) { m[dWT] = EQEB + EQWT - MYDF(dEB); } + if(recons[dWT]) { m[dEB] = EQWT + EQEB - MYDF(dWT); } + if(recons[dWB]) { m[dET] = EQWB + EQET - MYDF(dWB); } +#endif + + // mass streaming done... + // now collide new fluid or "old" if cells + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + DEFAULT_COLLIDE; + rho = m[dC]; + FORDF1 { rho+=m[l]; }; + // only with interface neighbors...? + PERFORM_USQRMAXCHECK; + + if(oldFlag & (CFMbndInflow)) { + // fill if cells in inflow region + if(myfrac<0.5) { + mass += 0.25; + mInitialMass += 0.25; + } + } + + // interface cell filled or emptied? + iffilled = ifemptied = 0; + // interface cells empty/full?, WARNING: to mark these cells, better do it at the end of reinitCellFlags + // interface cell if full? + if( (mass) >= (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 "<<PRINT_IJK); }; + iffilled = 1; + } + } + if(!ifemptied) { + if( (oldFlag & CFNoNbFluid)&&(newFlag & CFNoNbFluid)&& + ( (mass<(rho*FSGR_LISTTTHRESHEMPTY)) || ((nbored&CFInter)==0) ) + ) + { + //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","emptied "<<PRINT_IJK); }; + ifemptied = 1; + } + } // */ +#endif + + //iffilled = ifemptied = 0; // DEBUG!!!!!!!!!!!!!!! + + + // now that all dfs are known, handle last changes + if(iffilled) { + LbmPoint filledp; + filledp.x = i; filledp.y = j; filledp.z = k; +#if PARALLEL==1 + calcListFull[id].push_back( filledp ); +#else // PARALLEL==1 + mListFull.push_back( filledp ); +#endif // PARALLEL==1 + //D::mNumFilledCells++; // DEBUG + calcCellsFilled++; + } + else if(ifemptied) { + 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 + //D::mNumEmptiedCells++; // DEBUG + calcCellsEmptied++; + } else { + // ... + } + + // dont cutoff values -> 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; nn<D::cDfNum; nn++) { + if(RFLAG_NB(lev, i,j,k,SRCS(lev),nn) & (CFFluid|CFInter|CFBnd)) { + flux += D::dfLength[nn]; + } + } + //flux = FLUX_INIT; // calc flux off + QCELL(lev, i,j,k,TSET(lev), dFlux) = flux; // */ + + // perform mass exchange with streamed values + QCELL(lev, i,j,k,TSET(lev), dMass) = mass; // MASST + // set new flag + *pFlagDst = (CellFlagType)newFlag; +//FST errMsg("M","i "<<mass); + calcCurrentMass += mass; + calcCurrentVolume += RAC(tcel,dFfrac); + + // interface cell handling done... + } // i + int i=0; //dummy + ADVANCE_POINTERS(2); + } // j + +#if COMPRESSGRIDS==1 +#if PARALLEL==1 + //frintf(stderr," (id=%d k=%d) ",id,k); +# pragma omp barrier +#endif // PARALLEL==1 +#else // COMPRESSGRIDS==1 + int i=0; //dummy + ADVANCE_POINTERS(mLevel[lev].lSizex*2); +#endif // COMPRESSGRIDS==1 + } // all cell loop k,j,i + + } // main loop region + + // write vars from parallel computations to class + //errMsg("DFINI"," maxr l"<<mMaxRefine<<" cm="<<calcCurrentMass<<" cv="<<calcCurrentVolume ); + mLevel[lev].lmass = calcCurrentMass; + mLevel[lev].lvolume = calcCurrentVolume; + //mCurrentMass += calcCurrentMass; + //mCurrentVolume += calcCurrentVolume; + D::mNumFilledCells = calcCellsFilled; + D::mNumEmptiedCells = calcCellsEmptied; + D::mNumUsedCells = calcNumUsedCells; +#if PARALLEL==1 + //errMsg("PARALLELusqrcheck"," curr: "<<mMaxVlen<<"|"<<mMxvx<<","<<mMxvy<<","<<mMxvz); + for(int i=0; i<MAX_THREADS; i++) { + for(int j=0; j<calcListFull[i].size() ; j++) mListFull.push_back( calcListFull[i][j] ); + for(int j=0; j<calcListEmpty[i].size(); j++) mListEmpty.push_back( calcListEmpty[i][j] ); + if(calcMaxVlen[i]>mMaxVlen) { + mMxvx = calcMxvx[i]; + mMxvy = calcMxvy[i]; + mMxvz = calcMxvz[i]; + mMaxVlen = calcMaxVlen[i]; + } + errMsg("PARALLELusqrcheck"," curr: "<<mMaxVlen<<"|"<<mMxvx<<","<<mMxvy<<","<<mMxvz<< + " calc["<<i<<": "<<calcMaxVlen[i]<<"|"<<calcMxvx[i]<<","<<calcMxvy[i]<<","<<calcMxvz[i]<<"] " ); + } +#endif // PARALLEL==1 + + // check other vars...? +} + +template<class D> +void +LbmFsgrSolver<D>::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<mMaxRefine; lev++) { TEST DEBUG + FSGR_FORIJK_BOUNDS(lev) { + if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { + if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { + LbmFloat totArea = mFsgrCellArea[0]; // for l=0 + for(int l=1; l<D::cDirNum; l++) { + int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& + (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + ) { + totArea += mFsgrCellArea[l]; + } + } // l + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; + //continue; + } else + if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & (CFEmpty|CFUnused)) { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; + //continue; + } else { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; + } + //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); + } + } // } TEST DEBUG + if(!D::mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } +} + +template<class D> +void +LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { +#if FSGR_STRICT_DEBUG==1 + rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG +#endif + pFlagSrc++; + pFlagDst++; + ccel += QCELLSTEP; + tcel += QCELLSTEP; + + // from coarse cells without unused nbs are not necessary...! -> 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 "<<lev<<" "<<PRINT_IJK); +#endif // ELBEEM_BLENDER!=1 + // FIXME add debug check for these types of cells?, move to perform coarsening? + } + } // */ + + //*(pFlagSrc+pFlagTarOff) = *pFlagSrc; // always set other set... +#if FSGR_STRICT_DEBUG==1 + *pFlagDst = *pFlagSrc; // always set other set... +#else + *pFlagDst = (*pFlagSrc & (~CFGrCoarseInited)); // always set other set... , remove coarse inited flag +#endif + + // old INTCFCOARSETEST==1 + if((*pFlagSrc) & CFGrFromCoarse) { // interpolateFineFromCoarse test! + if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } + } else { + interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); + D::mNumUsedCells++; + } + continue; // interpolateFineFromCoarse test! + } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 + + if( ((*pFlagSrc) & (CFFluid)) ) { + ccel = RACPNT(lev, i,j,k ,SRCS(lev)); + tcel = RACPNT(lev, i,j,k ,TSET(lev)); + + if( ((*pFlagSrc) & (CFGrFromFine)) ) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? + continue; // comes from fine grid + } + // also ignore CFGrFromCoarse + else if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? + continue; + } + + OPTIMIZED_STREAMCOLLIDE; + *pFlagDst |= CFNoBndFluid; // test? + calcCurrentVolume += RAC(ccel,dFlux); + calcCurrentMass += RAC(ccel,dFlux)*rho; + //ebugMarkCell(lev+1, 2*i+1,2*j+1,2*k ); +#if FSGR_STRICT_DEBUG==1 + if(rho<-1.0){ debugMarkCell(lev, i,j,k ); + errMsg("INVRHOCELL_CHECK"," l"<<lev<<" "<< PRINT_IJK<<" rho:"<<rho ); + D::mPanic = 1; + } +#endif // FSGR_STRICT_DEBUG==1 + D::mNumUsedCells++; + + } + } + pFlagSrc+=2; // after x + pFlagDst+=2; // after x + ccel += (QCELLSTEP*2); + tcel += (QCELLSTEP*2); + } + pFlagSrc+= mLevel[lev].lSizex*2; // after y + pFlagDst+= mLevel[lev].lSizex*2; // after y + ccel += (QCELLSTEP*mLevel[lev].lSizex*2); + tcel += (QCELLSTEP*mLevel[lev].lSizex*2); + } // all cell loop k,j,i + + + //errMsg("coarseAdvance","level "<<lev<<" stepped from "<<mLevel[lev].setCurr<<" to "<<mLevel[lev].setOther); + if(!D::mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } + // */ + + // update other set + mLevel[lev].setOther = mLevel[lev].setCurr; + mLevel[lev].setCurr ^= 1; + mLevel[lev].lsteps++; + mLevel[lev].lmass = calcCurrentMass * mLevel[lev].lcellfactor; + mLevel[lev].lvolume = calcCurrentVolume * mLevel[lev].lcellfactor; +#ifndef ELBEEM_BLENDER + errMsg("DFINI", " m l"<<lev<<" m="<<mLevel[lev].lmass<<" c="<<calcCurrentMass<<" lcf="<< mLevel[lev].lcellfactor ); + errMsg("DFINI", " v l"<<lev<<" v="<<mLevel[lev].lvolume<<" c="<<calcCurrentVolume<<" lcf="<< mLevel[lev].lcellfactor ); +#endif // ELBEEM_BLENDER +} + +/*****************************************************************************/ +//! multi level functions +/*****************************************************************************/ + + +// get dfs from level (lev+1) to (lev) coarse border nodes +template<class D> +void +LbmFsgrSolver<D>::coarseRestrictFromFine(int lev) +{ + if((lev<0) || ((lev+1)>mMaxRefine)) return; +#if FSGR_STRICT_DEBUG==1 + // reset all unused cell values to invalid + int unuCnt = 0; + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,mLevel[lev].setCurr); + if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { + FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } + unuCnt++; + // set here + } else if( ((*pFlagSrc) & (CFFluid|CFGrNorm)) == (CFFluid|CFGrNorm) ) { + // simulated... + } else { + // reset in interpolation + //errMsg("coarseRestrictFromFine"," reset l"<<lev<<" "<<PRINT_IJK); + } + if( ((*pFlagSrc) & (CFEmpty|CFUnused)) ) { // test, also reset? + FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } + } // test + } } } + errMsg("coarseRestrictFromFine"," reset l"<<lev<<" fluid|coarseBorder cells: "<<unuCnt); +#endif // FSGR_STRICT_DEBUG==1 + const int srcSet = mLevel[lev+1].setCurr; + const int dstSet = mLevel[lev].setCurr; + + LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; + LbmFloat *ccel = NULL; + LbmFloat *tcel = NULL; +#if OPT3D==1 + LbmFloat m[LBM_DFNUM]; + // for macro add + LbmFloat usqr; + //LbmFloat *addfcel, *dstcell; + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; + LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; +#else // OPT3D==true + LbmFloat df[LBM_DFNUM]; + LbmFloat omegaDst, omegaSrc; + LbmFloat feq[LBM_DFNUM]; + LbmFloat dfScale = mDfScaleUp; +#endif // OPT3D==true + + LbmFloat mGaussw[27]; + LbmFloat totGaussw = 0.0; + const LbmFloat alpha = 1.0; + const LbmFloat gw = sqrt(2.0*D::cDimension); +#ifndef ELBEEM_BLENDER + errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!"); +#endif + for(int n=0;(n<D::cDirNum); n++) { mGaussw[n] = 0.0; } + //for(int n=0;(n<D::cDirNum); n++) { + for(int n=0;(n<D::cDfNum); n++) { + const LbmFloat d = norm(LbmVec(D::dfVecX[n], D::dfVecY[n], D::dfVecZ[n])); + LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw ); + //errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 cell n"<<n<<" d"<<d<<" w"<<w); + mGaussw[n] = w; + totGaussw += w; + } + for(int n=0;(n<D::cDirNum); n++) { + mGaussw[n] = mGaussw[n]/totGaussw; + } + + //restrict + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,dstSet); + if((*pFlagSrc) & (CFFluid)) { + if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { + // TODO? optimize? + // do resctriction + mNumInterdCells++; + ccel = RACPNT(lev+1, 2*i,2*j,2*k,srcSet); + tcel = RACPNT(lev , i,j,k ,dstSet); + +# if OPT3D==0 + // add up weighted dfs + FORDF0{ df[l] = 0.0;} + for(int n=0;(n<D::cDirNum); n++) { + int ni=2*i+1*D::dfVecX[n], nj=2*j+1*D::dfVecY[n], nk=2*k+1*D::dfVecZ[n]; + ccel = RACPNT(lev+1, ni,nj,nk,srcSet);// CFINTTEST + const LbmFloat weight = mGaussw[n]; + FORDF0{ + LbmFloat cdf = weight * RAC(ccel,l); +# if FSGR_STRICT_DEBUG==1 + if( cdf<-1.0 ){ errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]); } +# endif + //errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]<<" = "<<cdf<<" , w"<<weight); + df[l] += cdf; + } + } + + // calc rho etc. from weighted dfs + rho = ux = uy = uz = 0.0; + FORDF0{ + LbmFloat cdf = df[l]; + rho += cdf; + ux += (D::dfDvecX[l]*cdf); + uy += (D::dfDvecY[l]*cdf); + uz += (D::dfDvecZ[l]*cdf); + } + + FORDF0{ feq[l] = D::getCollideEq(l, rho,ux,uy,uz); } + if(mLevel[lev ].lcsmago>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<D::cDirNum); n++) { + ccel = RACPNT(lev+1, 2*i+1*D::dfVecX[n], 2*j+1*D::dfVecY[n], 2*k+1*D::dfVecZ[n] ,srcSet); + MSRC_C += CCELG_C(n) ; + MSRC_N += CCELG_N(n) ; + MSRC_S += CCELG_S(n) ; + MSRC_E += CCELG_E(n) ; + MSRC_W += CCELG_W(n) ; + MSRC_T += CCELG_T(n) ; + MSRC_B += CCELG_B(n) ; + MSRC_NE += CCELG_NE(n); + MSRC_NW += CCELG_NW(n); + MSRC_SE += CCELG_SE(n); + MSRC_SW += CCELG_SW(n); + MSRC_NT += CCELG_NT(n); + MSRC_NB += CCELG_NB(n); + MSRC_ST += CCELG_ST(n); + MSRC_SB += CCELG_SB(n); + MSRC_ET += CCELG_ET(n); + MSRC_EB += CCELG_EB(n); + MSRC_WT += CCELG_WT(n); + MSRC_WB += CCELG_WB(n); + } + rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T + + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT + + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; + ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW + + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB; + uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW + + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB; + uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB + + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB; + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + \ + lcsmeq[dC] = EQC ; \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev+0, MSRC_ )\ + COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ + COLL_CALCULATE_CSMOMEGAVAL(lev+1, lcsmSrcOmega); \ + \ + lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev+1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ + RAC(tcel, dC ) = (lcsmeq[dC ] + (MSRC_C -lcsmeq[dC ] )*lcsmdfscale); + RAC(tcel, dN ) = (lcsmeq[dN ] + (MSRC_N -lcsmeq[dN ] )*lcsmdfscale); + RAC(tcel, dS ) = (lcsmeq[dS ] + (MSRC_S -lcsmeq[dS ] )*lcsmdfscale); + RAC(tcel, dE ) = (lcsmeq[dE ] + (MSRC_E -lcsmeq[dE ] )*lcsmdfscale); + RAC(tcel, dW ) = (lcsmeq[dW ] + (MSRC_W -lcsmeq[dW ] )*lcsmdfscale); + RAC(tcel, dT ) = (lcsmeq[dT ] + (MSRC_T -lcsmeq[dT ] )*lcsmdfscale); + RAC(tcel, dB ) = (lcsmeq[dB ] + (MSRC_B -lcsmeq[dB ] )*lcsmdfscale); + RAC(tcel, dNE) = (lcsmeq[dNE] + (MSRC_NE-lcsmeq[dNE] )*lcsmdfscale); + RAC(tcel, dNW) = (lcsmeq[dNW] + (MSRC_NW-lcsmeq[dNW] )*lcsmdfscale); + RAC(tcel, dSE) = (lcsmeq[dSE] + (MSRC_SE-lcsmeq[dSE] )*lcsmdfscale); + RAC(tcel, dSW) = (lcsmeq[dSW] + (MSRC_SW-lcsmeq[dSW] )*lcsmdfscale); + RAC(tcel, dNT) = (lcsmeq[dNT] + (MSRC_NT-lcsmeq[dNT] )*lcsmdfscale); + RAC(tcel, dNB) = (lcsmeq[dNB] + (MSRC_NB-lcsmeq[dNB] )*lcsmdfscale); + RAC(tcel, dST) = (lcsmeq[dST] + (MSRC_ST-lcsmeq[dST] )*lcsmdfscale); + RAC(tcel, dSB) = (lcsmeq[dSB] + (MSRC_SB-lcsmeq[dSB] )*lcsmdfscale); + RAC(tcel, dET) = (lcsmeq[dET] + (MSRC_ET-lcsmeq[dET] )*lcsmdfscale); + RAC(tcel, dEB) = (lcsmeq[dEB] + (MSRC_EB-lcsmeq[dEB] )*lcsmdfscale); + RAC(tcel, dWT) = (lcsmeq[dWT] + (MSRC_WT-lcsmeq[dWT] )*lcsmdfscale); + RAC(tcel, dWB) = (lcsmeq[dWB] + (MSRC_WB-lcsmeq[dWB] )*lcsmdfscale); +# endif // OPT3D==0 + + //? if((lev<mMaxRefine)&&(D::cDimension==2)) { debugMarkCell(lev,i,j,k); } +# if FSGR_STRICT_DEBUG==1 + //errMsg("coarseRestrictFromFine", "CRFF_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" " ); +# endif // FSGR_STRICT_DEBUG==1 + D::mNumUsedCells++; + } // from fine & fluid + else { + if(RFLAG(lev+1, 2*i,2*j,2*k,srcSet) & CFGrFromCoarse) { + RFLAG(lev, i,j,k,dstSet) |= CFGrToFine; + } else { + RFLAG(lev, i,j,k,dstSet) &= (~CFGrToFine); + } + } + } // & fluid + }}} + if(!D::mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } +} + +template<class D> +bool +LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + bool removeFromFine = 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), srcFineSet) & reqType) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & (notAllowed)) ) ){ // ok + } else { + removeFromFine=true; + } + /*if(strstr(D::getName().c_str(),"Debug")) + if(lev+1==mMaxRefine) { // mixborder + for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { // FARBORD + int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, srcFineSet)&CFBnd) { // NEWREFT + removeFromFine=true; + } + } + } // FARBORD */ +#elif REFINEMENTBORDER==2 // REFINEMENTBORDER==1 + FIX + for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { + int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT + removeFromFine=true; + } + } + /*for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { // FARBORD + int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT + removeFromFine=true; + } + } // FARBORD */ +#elif REFINEMENTBORDER==3 // REFINEMENTBORDER==1 + FIX + if(lev+1==mMaxRefine) { // mixborder + if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)¬SrcAllowed) { + removeFromFine=true; + } + } else { // mixborder + for(int l=0; l<D::cDirNum; l++) { + int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, srcFineSet)¬SrcAllowed) { // NEWREFT + removeFromFine=true; + } + } + } // mixborder + // also remove from fine cells that are above from fine +#else // REFINEMENTBORDER==1 + ERROR +#endif // REFINEMENTBORDER==1 + + if(removeFromFine) { + // dont turn CFGrFromFine above interface cells into CFGrNorm + //errMsg("performRefinement","Removing CFGrFromFine on lev"<<lev<<" " <<PRINT_IJK<<" srcflag:"<<convertCellFlagType2String(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet)) <<" set:"<<dstSet ); + RFLAG(lev, i,j,k, dstSet) = CFEmpty; +#if FSGR_STRICT_DEBUG==1 + // for interpolation later on during fine grid fixing + // these cells are still correctly inited + RFLAG(lev, i,j,k, dstSet) |= CFGrCoarseInited; // remove later on? FIXME? +#endif // FSGR_STRICT_DEBUG==1 + //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFEmpty; // FLAGTEST + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); + change=true; + mNumFsgrChanges++; + for(int l=1; l<D::cDirNum; l++) { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + //errMsg("performRefinement","On lev:"<<lev<<" check: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet<<" = "<<convertCellFlagType2String(RFLAG(lev, ni,nj,nk, srcSet)) ); + if( ( RFLAG(lev, ni,nj,nk, srcSet)&CFFluid ) && + (!(RFLAG(lev, ni,nj,nk, srcSet)&CFGrFromFine)) ) { // dont change status of nb. from fine cells + // tag as inited for debugging, cell contains fluid DFs anyway + RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromFine|CFGrCoarseInited; + //errMsg("performRefinement","On lev:"<<lev<<" set to from fine: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet); + //if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + } + } // l + + // FIXME fix fine level? + } + + // recheck from fine flag + } + }}} // TEST + + + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST + for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST + for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST + + // test from coarseAdvance + // from coarse cells without unused nbs are not necessary...! -> 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 "<<lev<<" "<<PRINT_IJK); + } + } // */ + + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromCoarse) { + + // from coarse cells without unused nbs are not necessary...! -> remove + bool invNb = false; + bool fluidNb = false; + for(int l=1; l<D::cDirNum; l++) { + if(RFLAG_NB(lev, i, j, k, srcSet, l) & CFUnused) { invNb = true; } + if(RFLAG_NB(lev, i, j, k, srcSet, l) & (CFGrNorm)) { fluidNb = true; } + } + if(!invNb) { + // no unused cells around -> 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"<<lev<<" " <<PRINT_IJK<<" due to finer from coarse cell " ); + RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; + if(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<D::cDirNum; l++) { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if(RFLAG(lev, ni,nj,nk, srcSet)&(CFGrNorm)) { //ok + for(int m=1; m<D::cDirNum; m++) { + int mi= ni +D::dfVecX[m], mj= nj +D::dfVecY[m], mk= nk +D::dfVecZ[m]; + if(RFLAG(lev, mi, mj, mk, srcSet)&CFUnused) { + // norm cells in neighborhood with unused nbs have to be new border... + RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromCoarse; + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + } + } + // these alreay have valid values... + } + else if(RFLAG(lev, ni,nj,nk, srcSet)&(CFUnused)) { //ok + // this should work because we have a valid neighborhood here for now + interpolateCellFromCoarse(lev, ni, nj, nk, dstSet /*mLevel[lev].setCurr*/, interTime, CFFluid|CFGrFromCoarse, false); + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + mNumFsgrChanges++; + } + } // l + } // double transer + + } // from coarse + + } } } + + + // fix dstSet from fine cells here + // warning - checks CFGrFromFine on dstset changed before! + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST + for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST + for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST + + //if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + if(RFLAG(lev, i,j,k, dstSet) & CFGrFromFine) { + // modify finer level border + if((RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse))) { + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" from l"<<lev<<" " <<PRINT_IJK ); + CellFlagType setf = CFFluid; + if(lev+1 < mMaxRefine) setf = CFFluid|CFGrNorm; + RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; + change=true; + mNumFsgrChanges++; + for(int l=1; l<D::cDirNum; l++) { + int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; + if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFGrFromCoarse)) { + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); + RFLAG(lev+1, bi, bj, bk, srcFineSet) = setf; + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + } + else if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFUnused )) { + //errMsg("performRefinement","Removing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); + interpolateCellFromCoarse(lev+1, bi, bj, bk, srcFineSet, interTime, setf, false); + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + mNumFsgrChanges++; + } + } + for(int l=1; l<D::cDirNum; l++) { + int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; + if( (RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFFluid ) && + (!(RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFGrFromCoarse)) ) { + // all unused nbs now of coarse have to be from coarse + for(int m=1; m<D::cDirNum; m++) { + int mi= bi +D::dfVecX[m], mj= bj +D::dfVecY[m], mk= bk +D::dfVecZ[m]; + if(RFLAG(lev+1, mi, mj, mk, srcFineSet)&CFUnused) { + //errMsg("performRefinement","Changing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(mi,mj,mk) ); + interpolateCellFromCoarse(lev+1, mi, mj, mk, srcFineSet, interTime, CFFluid|CFGrFromCoarse, false); + if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); + mNumFsgrChanges++; + } + } + // nbs prepared... + } + } + } + + } // convert regions of from fine + }}} // TEST + + if(!D::mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } + return change; +} + + +// done after refinement +template<class D> +bool +LbmFsgrSolver<D>::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<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + // from coarse cells without unused nbs are not necessary...! -> 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<D::cDirNum && nbsok; l++) { + int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + if( (RFLAG(lev+1, ni,nj,nk, dstFineSet) & reqType) && + (!(RFLAG(lev+1, ni,nj,nk, dstFineSet) & (notAllowed)) ) ){ + // ok + } else { + nbsok=false; + } + /*if(strstr(D::getName().c_str(),"Debug")) + if((nbsok)&&(lev+1==mMaxRefine)) { // mixborder + for(int l=0;((l<D::cDirNum) && (nbsok)); l++) { // FARBORD + int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT + nbsok=false; + } + } + } // FARBORD */ + } + // dont turn CFGrFromFine above interface cells into CFGrNorm + // now check nbs on same level + for(int l=1; l<D::cDirNum && nbsok; l++) { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if(RFLAG(lev, ni,nj,nk, srcSet)&(CFFluid)) { //ok + } else { + nbsok = false; + } + } // l + + if(nbsok) { + // conversion to coarse fluid cell + change = true; + mNumFsgrChanges++; + RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrNorm; + // dfs are already ok... + //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); + if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + + // only check complete cubes + for(int dx=-1;dx<=1;dx+=2) { + for(int dy=-1;dy<=1;dy+=2) { + for(int dz=-1*(LBMDIM&1);dz<=1*(LBMDIM&1);dz+=2) { // 2d/3d + // check for norm and from coarse, as the coarse level might just have been refined... + /*if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subc check "<< "x"<<convertCellFlagType2String( RFLAG(lev, i+dx, j , k , srcSet))<<" " + "y"<<convertCellFlagType2String( RFLAG(lev, i , j+dy, k , srcSet))<<" " "z"<<convertCellFlagType2String( RFLAG(lev, i , j , k+dz, srcSet))<<" " + "xy"<<convertCellFlagType2String( RFLAG(lev, i+dx, j+dy, k , srcSet))<<" " "xz"<<convertCellFlagType2String( RFLAG(lev, i+dx, j , k+dz, srcSet))<<" " + "yz"<<convertCellFlagType2String( RFLAG(lev, i , j+dy, k+dz, srcSet))<<" " "xyz"<<convertCellFlagType2String( RFLAG(lev, i+dx, j+dy, k+dz, srcSet))<<" " ); // */ + if( + // we now the flag of the current cell! ( RFLAG(lev, i , j , k , srcSet)&(CFGrNorm)) && + ( RFLAG(lev, i+dx, j , k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + + ( RFLAG(lev, i+dx, j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i+dx, j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i+dx, j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) + ) { + // middle source node on higher level + int dstx = (2*i)+dx; + int dsty = (2*j)+dy; + int dstz = (2*k)+dz; + + mNumFsgrChanges++; + RFLAG(dstlev, dstx,dsty,dstz, dstFineSet) = CFUnused; + RFLAG(dstlev, dstx,dsty,dstz, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST + //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); + + for(int l=1; l<D::cDirNum; l++) { + int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; + if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFFluid)) { + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; + } + if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFInter)) { + //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); + D::mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; + } + } // l + + // again check nb flags of all surrounding cells to see if any from coarse + // can be convted to unused + for(int l=1; l<D::cDirNum; l++) { + int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; + // have to be at least from coarse here... + //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" "<< convertCellFlagType2String(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)) ); + if(!(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFUnused) )) { + bool delok = true; + // careful long range here... check domain bounds? + for(int m=1; m<D::cDirNum; m++) { + int chkni=dstni+D::dfVecX[m], chknj=dstnj+D::dfVecY[m], chknk=dstnk+D::dfVecZ[m]; + if(RFLAG(dstlev, chkni,chknj,chknk, dstFineSet)&(CFUnused|CFGrFromCoarse)) { + // this nb cell is ok for deletion + } else { + delok=false; // keep it! + } + //errMsg("performCoarsening"," CHECK "<<PRINT_VEC(dstni,dstnj,dstnk)<<" to "<<PRINT_VEC( chkni,chknj,chknk )<<" f:"<< convertCellFlagType2String( RFLAG(dstlev, chkni,chknj,chknk, dstFineSet))<<" nbsok"<<delok ); + } + //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" ok"<<delok ); + if(delok) { + mNumFsgrChanges++; + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFUnused; + RFLAG(dstlev, dstni,dstnj,dstnk, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST + if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); + } + } + } // l + // treat subcube + //ebugMarkCell(lev,i+dx,j+dy,k+dz); + //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); + } + } } } + + } // ? + } // convert regions of from fine + }}} // TEST! + + // reinit cell area value + /*if( RFLAG(lev, i,j,k,srcSet) & CFFluid) { + if( RFLAG(lev+1, i*2,j*2,k*2,dstFineSet) & CFGrFromCoarse) { + LbmFloat totArea = mFsgrCellArea[0]; // for l=0 + for(int l=1; l<D::cDirNum; l++) { + int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)& + (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + ) { + //LbmFloat area = 0.25; if(D::dfVecX[l]!=0) area *= 0.5; if(D::dfVecY[l]!=0) area *= 0.5; if(D::dfVecZ[l]!=0) area *= 0.5; + totArea += mFsgrCellArea[l]; + } + } // l + QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = + QCELL(lev, i,j,k,srcSet, dFlux) = totArea; + } else { + QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = + QCELL(lev, i,j,k,srcSet, dFlux) = 1.0; + } + //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,srcSet, dFlux) ); + } + // */ + + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + + if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { + // check empty -> 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<D::cDirNum) && (changeToFromFine)); l++) { // FARBORD + int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT + changeToFromFine=false; + } + } + }// FARBORD */ +#elif REFINEMENTBORDER==2 // 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; + for(int l=0; ((l<D::cDirNum)&&(changeToFromFine)); l++) { + int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT + changeToFromFine=false; + } + } + /*for(int l=0; ((l<D::cDirNum)&&(changeToFromFine)); l++) { // FARBORD + int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT + changeToFromFine=false; + } + } // FARBORD*/ + } +#elif REFINEMENTBORDER==3 // REFINEMENTBORDER==3 + FIX!!! + if(lev+1==mMaxRefine) { // mixborder + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (CFFluid|CFInter)) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ + changeToFromFine=true; + } + } else { + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (CFFluid)) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ + changeToFromFine=true; + for(int l=0; l<D::cDirNum; l++) { + int ni=2*i+D::dfVecX[l], nj=2*j+D::dfVecY[l], nk=2*k+D::dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&(notNbAllowed)) { // NEWREFT + changeToFromFine=false; + } + } + } } // mixborder +#else // REFINEMENTBORDER==3 + ERROR +#endif // REFINEMENTBORDER==1 + if(changeToFromFine) { + change = true; + mNumFsgrChanges++; + RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; + if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + // same as restr from fine func! not necessary ?! + // coarseRestrictFromFine part */ + } + } // only check empty cells + + }}} // TEST! + + if(!D::mSilent){ errMsg("performCoarsening"," for l"<<lev<<" done " ); } + return change; +} + + +/*****************************************************************************/ +/*! perform a single LBM step */ +/*****************************************************************************/ +template<class D> +void +LbmFsgrSolver<D>::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(nextmax<allowMax*fac) { + newdt = D::mpParam->getStepTime() / fac; + } + } // newtr + //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<fac<<" simmaxv="<< D::mpParam->getSimulationMaxSpeed() ); + + bool minCutoff = false; + LbmFloat desireddt = newdt; + if(newdt>D::mpParam->getMaxStepTime()){ newdt = D::mpParam->getMaxStepTime(); } + if(newdt<D::mpParam->getMinStepTime()){ + newdt = D::mpParam->getMinStepTime(); + if(nextmax>allowMax/fac){ minCutoff=true; } // only if really large vels... + } + + LbmFloat dtdiff = fabs(newdt - D::mpParam->getStepTime()); + if(!D::mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<D::mpParam->getMaxStepTime()<<" min"<<D::mpParam->getMinStepTime()<<" diff"<<dtdiff<< + " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxStepTime)<<" maxsteps:"<<(mSimulationTime/mMinStepTime) , 10); } + + // in range, and more than X% change? + //if( newdt < D::mpParam->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... "<<mTimestepReduceLock<<" ",10); + debMsgDirect("D"); + } else { + D::mpParam->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="<<newdt<<" old="<<D::mpParam->getStepTime()<<" maxSpeed:"<<D::mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<D::mStepCnt, 10 ); + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< + "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10); + } + } // really change dt + } + + if(mTimestepReduceLock>0) mTimestepReduceLock--; + + + /* + // forced back and forth switchting (for testing) + const int tadtogInter = 300; + const double tadtogSwitch = 0.66; + errMsg("TIMESWITCHTOGGLETEST","warning enabled "<< tadtogSwitch<<","<<tadtogSwitch<<" !!!!!!!!!!!!!!!!!!!"); + if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || + ((D::mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ + rescale = true; minCutoff = false; + newdt = tadtogSwitch * D::mpParam->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()<mMinStepTime) mMinStepTime = D::mpParam->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: "<<lev<<" Timestep change: "<< + " scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10); + } + if(lev!=mMaxRefine) coarseCalculateFluxareas(lev); + + int wss = 0, wse = 1; + // FIXME always currset!? + wss = wse = mLevel[lev].setCurr; + for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT + // warning - check sets for higher levels...? + FSGR_FORIJK1(lev) { + 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 rhoOld; + LbmVec velOld; + LbmFloat rho, ux,uy,uz; + rho=0.0; ux = uy = uz = 0.0; + for(int l=0; l<D::cDfNum; l++) { + LbmFloat m = QCELL(lev, i, j, k, workSet, l); + rho += m; + ux += (D::dfDvecX[l]*m); + uy += (D::dfDvecY[l]*m); + uz += (D::dfDvecZ[l]*m); + } + rhoOld = rho; + velOld = LbmVec(ux,uy,uz); + + LbmFloat rhoNew = (rhoOld-rhoAvg)*scaleFac +rhoAvg; + LbmVec velNew = velOld * scaleFac; + + LbmFloat df[LBM_DFNUM]; + LbmFloat feqOld[LBM_DFNUM]; + LbmFloat feqNew[LBM_DFNUM]; + for(int l=0; l<D::cDfNum; l++) { + feqOld[l] = D::getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); + feqNew[l] = D::getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); + df[l] = QCELL(lev, i,j,k,workSet, l); + } + const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feqOld); + const LbmFloat oldOmega = D::getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); + const LbmFloat newOmega = D::getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); + //newOmega = mLevel[lev].omega; // FIXME debug test + + //LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); + const LbmFloat dfScale = (newSteptime/newOmega)/(levOldStepsize[lev]/oldOmega); + //dfScale = dfScaleFac/newOmega; + + for(int l=0; l<D::cDfNum; l++) { + // org scaling + //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important + // new scaling + LbmFloat dfn = feqNew[l] + (df[l]-feqOld[l])*dfScale*feqNew[l]/feqOld[l]; // non-eq. scaling, important + //df = eqNew + (df-eqOld)*dfScale; // modified ig scaling, no real difference? + QCELL(lev, i,j,k,workSet, l) = dfn; + } + + if(RFLAG(lev,i,j,k, workSet) & CFInter) { + //if(workSet==mLevel[lev].setCurr) + LbmFloat area = 1.0; + if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux); + massTOld += QCELL(lev, i,j,k,workSet, dMass) * area; + volTOld += QCELL(lev, i,j,k,workSet, dFfrac); + + // wrong... QCELL(i,j,k,workSet, dMass] = (QCELL(i,j,k,workSet, dFfrac]*rhoNew); + QCELL(lev, i,j,k,workSet, dMass) = (QCELL(lev, i,j,k,workSet, dMass)/rhoOld*rhoNew); + QCELL(lev, i,j,k,workSet, dFfrac) = (QCELL(lev, i,j,k,workSet, dMass)/rhoNew); + + //if(workSet==mLevel[lev].setCurr) + massTNew += QCELL(lev, i,j,k,workSet, dMass); + volTNew += QCELL(lev, i,j,k,workSet, dFfrac); + } + if(RFLAG(lev,i,j,k, workSet) & CFFluid) { // DEBUG + if(RFLAG(lev,i,j,k, workSet) & (CFGrFromFine|CFGrFromCoarse)) { // DEBUG + // dont include + } else { + LbmFloat area = 1.0; + if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux) * mLevel[lev].lcellfactor; + //if(workSet==mLevel[lev].setCurr) + massTOld += rhoOld*area; + //if(workSet==mLevel[lev].setCurr) + massTNew += rhoNew*area; + volTOld += area; + volTNew += area; + } + } + + } // IJK + } // workSet + + } // lev + + if(!D::mSilent) { + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<D::mStepCnt<< + " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxStepTime<< + " mindt"<<mMinStepTime<<" currdt"<<mLevel[mMaxRefine].stepsize, 10); + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE masst:"<<massTNew<<","<<massTOld<<" org:"<<mCurrentMass<<"; "<< + " volt:"<<volTNew<<","<<volTOld<<" org:"<<mCurrentVolume, 10); + } else { + debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep change by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt + <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<D::mOmega<<" gStar:"<<D::mpParam->getCurrentGStar() , 10); + } + } // rescale? + + //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG + if(minCutoff) { + errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<D::mName<<" step:"<<D::mStepCnt<<" newdt="<<desireddt<<" mindt="<<D::mpParam->getMinStepTime()<<") " ); + //brute force resacle all the time? + + for(int lev=mMaxRefine; lev>=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<D::cDfNum; l++) { + LbmFloat m = QCELL(lev, i, j, k, workSet, l); + rho += m; + ux += (D::dfDvecX[l]*m); + uy += (D::dfDvecY[l]*m); + uz += (D::dfDvecZ[l]*m); + } +#ifndef WIN32 + if (!finite(rho)) { + errMsg("adaptTimestep","Brute force non-finite rho at"<<PRINT_IJK); // DEBUG! + rho = 1.0; + ux = uy = uz = 0.0; + QCELL(lev, i, j, k, workSet, dMass) = 1.0; + QCELL(lev, i, j, k, workSet, dFfrac) = 1.0; + } +#endif // WIN32 + + if( (ux*ux+uy*uy+uz*uz)> (allowMax*allowMax) ) { + LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); + ux *= cfac; + uy *= cfac; + uz *= cfac; + for(int l=0; l<D::cDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = D::getCollideEq(l, rho, ux,uy,uz); } + rescs++; + debMsgDirect("B"); + } + + } } + //if(rescs>0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } + debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"<<lev<<" rescs:"<<rescs, 1); + //TTT mNumProblems += rescs; // add to problem display... + } // lev,set,ijk + + } // try brute force rescale? + + // time adap done... +} + + + + +/****************************************************************************** + * work on lists from updateCellMass to reinit cell flags + *****************************************************************************/ + +template<class D> +LbmFloat +LbmFsgrSolver<D>::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; + } else { + // backward for emptying + if(scal>-LBM_EPSILON) ret = 0.0; + else ret = scal * -1.0; + } + //errMsg("massd", PRINT_IJK<<" nv"<<nvel<<" : ret="<<ret ); //xit(1); //VECDEB + return ret; +} + +template<class D> +void LbmFsgrSolver<D>::addToNewInterList( int ni, int nj, int nk ) { +#if FSGR_STRICT_DEBUG==10 + // dangerous, this can change the simulation... + /*for( vector<LbmPoint>::iterator iter=mListNewInter.begin(); + iter != mListNewInter.end(); iter++ ) { + if(ni!=iter->x) continue; + if(nj!=iter->y) continue; + if(nk!=iter->z) continue; + // all 3 values match... skip point + return; + } */ +#endif // FSGR_STRICT_DEBUG==1 + // store point + LbmPoint newinter; + newinter.x = ni; newinter.y = nj; newinter.z = nk; + mListNewInter.push_back(newinter); +} + +template<class D> +void LbmFsgrSolver<D>::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { + LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; + LbmFloat intDf[19] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + +#if OPT3D==1 + // for macro add + LbmFloat addDfFacT, addVal, usqr; + LbmFloat *addfcel, *dstcell; + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; + LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; +#endif // OPT3D==true + + // SET required nbs to from coarse (this might overwrite flag several times) + // this is not necessary for interpolateFineFromCoarse + if(markNbs) { + FORDF1{ + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if(RFLAG(lev,ni,nj,nk,dstSet)&CFUnused) { + // parents have to be inited! + interpolateCellFromCoarse(lev, ni, nj, nk, dstSet, t, CFFluid|CFGrFromCoarse, false); + } + } } + + // change flag of cell to be interpolated + RFLAG(lev,i,j,k, dstSet) = flagSet; + mNumInterdCells++; + + // interpolation lines... + int betx = i&1; + int bety = j&1; + int betz = k&1; + + if((!betx) && (!bety) && (!betz)) { + ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2 , 0.0, 1.0); + } + else if(( betx) && (!bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D1); + } + else if((!betx) && ( bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D1); + } + else if((!betx) && (!bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D1); + } + else if(( betx) && ( bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D2); + } + else if((!betx) && ( bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D2); + } + else if(( betx) && (!bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D2); + } + else if(( betx) && ( bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2)+1, t, WO1D3); + } + else { + D::mPanic=1; + errFatal("interpolateCellFromCoarse","Invalid!?", SIMWORLD_GENERICERROR); + } + + IDF_WRITEBACK; + return; +} + +template<class D> +void LbmFsgrSolver<D>::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<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); // DEBUG SYMM + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev, ni,nj,nk, workSet) & CFEmpty ){ + // new and empty interface cell, dont change old flag here! + addToNewInterList(ni,nj,nk); + + // preinit speed, get from average surrounding cells + // interpolate from non-workset to workset, sets are handled in function + { + // WARNING - other i,j,k than filling cell! + int ei=ni; int ej=nj; int ek=nk; + LbmFloat avgrho = 0.0; + LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; + LbmFloat cellcnt = 0.0; + LbmFloat avgnbdf[LBM_DFNUM]; + FORDF0M { avgnbdf[m]= 0.0; } + + for(int nbl=1; nbl< D::cDfNum ; ++nbl) { + if( (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFFluid) || + ((!(RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) && + (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFInter) )) { + cellcnt += 1.0; + for(int rl=0; rl< D::cDfNum ; ++rl) { + LbmFloat nbdf = QCELL_NB(workLev,ei,ej,ek, workSet,nbl, rl); + avgnbdf[rl] += nbdf; + avgux += (D::dfDvecX[rl]*nbdf); + avguy += (D::dfDvecY[rl]*nbdf); + avguz += (D::dfDvecZ[rl]*nbdf); + avgrho += nbdf; + } + } + } + + if(cellcnt<=0.0) { + // no nbs? just use eq. + //FORDF0 { QCELL(workLev,ei,ej,ek, workSet, l) = D::dfEquil[l]; } + avgrho = 1.0; + avgux = avguy = avguz = 0.0; + //TTT mNumProblems++; +#if ELBEEM_BLENDER!=1 + D::mPanic=1; errFatal("NYI2","cellcnt<=0.0",SIMWORLD_GENERICERROR); +#endif // ELBEEM_BLENDER + } else { + // init speed + avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; + avgrho /= cellcnt; + FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? + } + + // careful with l's... + FORDF0M { + QCELL(workLev,ei,ej,ek, workSet, m) = D::getCollideEq( m,avgrho, avgux, avguy, avguz ); + //QCELL(workLev,ei,ej,ek, workSet, l) = avgnbdf[l]; // CHECK FIXME test? + } + //errMsg("FNEW", PRINT_VEC(ei,ej,ek)<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<<avgrho<<" vel"<<PRINT_VEC(avgux,avguy,avguz) ); // DEBUG SYMM + QCELL(workLev,ei,ej,ek, workSet, dMass) = 0.0; //?? new + QCELL(workLev,ei,ej,ek, workSet, dFfrac) = 0.0; //?? new + //RFLAG(workLev,ei,ej,ek,workSet) = (CellFlagType)(CFInter|CFNoInterpolSrc); + changeFlag(workLev,ei,ej,ek,workSet, (CFInter|CFNoInterpolSrc)); + if(debugFlagreinit) errMsg("NEWE", PRINT_IJK<<" newif "<<PRINT_VEC(ei,ej,ek)<<" rho"<<avgrho<<" vel("<<avgux<<","<<avguy<<","<<avguz<<") " ); + } + } + /* prevent surrounding interface cells from getting removed as empty cells + * (also cells that are not newly inited) */ + if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { + //RFLAG(workLev,ni,nj,nk, workSet) = (CellFlagType)(RFLAG(workLev,ni,nj,nk, workSet) | CFNoDelete); + changeFlag(workLev,ni,nj,nk, workSet, (RFLAG(workLev,ni,nj,nk, workSet) | CFNoDelete)); + // also add to list... + addToNewInterList(ni,nj,nk); + } // NEW? + } + + // NEW? no extra loop... + //RFLAG(workLev,i,j,k, workSet) = CFFluid; + changeFlag(workLev,i,j,k, workSet,CFFluid); + } + + /* remove empty interface cells that are not allowed to be removed anyway + * this is important, otherwise the dreaded cell-type-flickering can occur! */ + for( vector<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); // DEBUG SYMM + iter = mListEmpty.erase(iter); + iter--; // and continue with next... + + // treat as "new inter" + addToNewInterList(i,j,k); + } + } + + + /* problems arise when adjacent cells empty&fill -> + let fill cells+surrounding interface cells have the higher importance */ + for( vector<LbmPoint>::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"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); + + /* set surrounding fluid cells to interface cells */ + FORDF1 { + int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + if( RFLAG(workLev,ni,nj,nk, workSet) & CFFluid){ + // init fluid->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<lbmFloatSet> vWeights; + vWeights.reserve( mListFull.size() + mListEmpty.size() ); + int weightIndex = 0; + int nbCount = 0; + LbmFloat nbWeights[LBM_DFNUM]; + LbmFloat nbTotWeights = 0.0; + for( vector<LbmPoint>::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<<" "<<weightIndex<<" "<<nbTotWeights); + vWeights[weightIndex].val[0] = nbTotWeights; + FORDF1 { vWeights[weightIndex].val[l] = nbWeights[l]; } + vWeights[weightIndex].numNbs = (LbmFloat)nbCount; + } else { + vWeights[weightIndex].numNbs = 0.0; + } + weightIndex++; + } + for( vector<LbmPoint>::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<<" "<<weightIndex<<" "<<nbTotWeights); + vWeights[weightIndex].val[0] = nbTotWeights; + FORDF1 { vWeights[weightIndex].val[l] = nbWeights[l]; } + vWeights[weightIndex].numNbs = (LbmFloat)nbCount; + } else { + vWeights[weightIndex].numNbs = 0.0; + } + weightIndex++; + } + weightIndex = 0; + + + /* process full list entries, filled cells are done after this loop */ + for( vector<LbmPoint>::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"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM + if(vWeights[weightIndex].numNbs>0.0) { + const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; + //errMsg("FF I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); + 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) { + LbmFloat change = -1.0; + if(nbTotWeightsp>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<<" "<<D::mFixMass); + } + weightIndex++; + + // already done? RFLAG(workLev,i,j,k, workSet) = CFFluid; + QCELL(workLev,i,j,k, workSet, dMass) = myrho; // should be rho... but unused? + QCELL(workLev,i,j,k, workSet, dFfrac) = 1.0; // should be rho... but unused? + /*QCELL(workLev,i,j,k, otherSet, dMass) = myrho; // NEW? + QCELL(workLev,i,j,k, otherSet, dFfrac) = 1.0; // NEW? COMPRT */ + } // fulllist + + + /* now, finally handle the empty cells - order is important, has to be after + * full cell handling */ + for( vector<LbmPoint>::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"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM + //if(nbCount>0) { + if(vWeights[weightIndex].numNbs>0.0) { + const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; + //errMsg("EE I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); + 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) { + LbmFloat change = -1.0; + if(nbTotWeightsp>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<<" "<<D::mFixMass); + } + weightIndex++; + + // finally... make it empty + // already done? RFLAG(workLev,i,j,k, workSet) = CFEmpty; + QCELL(workLev,i,j,k, workSet, dMass) = 0.0; + QCELL(workLev,i,j,k, workSet, dFfrac) = 0.0; + } + for( vector<LbmPoint>::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<LbmPoint>::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<LbmPoint>::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("???"," "<<PRINT_IJK); + continue; + } + + QCELL(workLev,i,j,k, workSet, dMass) += (D::mFixMass * newIfFac); + + int nbored = 0; + FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); } + if((nbored & CFFluid)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbFluid; } + if((nbored & CFEmpty)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbEmpty; } + + if(!(RFLAG(workLev,i,j,k, otherSet)&CFInter)) { + RFLAG(workLev,i,j,k, workSet) = (CellFlagType)(RFLAG(workLev,i,j,k, workSet) | CFNoDelete); + } + if(debugFlagreinit) errMsg("NEWIF", PRINT_IJK<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" f"<< RFLAG(workLev,i,j,k, workSet)<<" wl"<<workLev ); + } + + // reinit fill fraction + for( vector<LbmPoint>::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:"<<D::mFixMass<<" nif:"<<mListNewInter.size() ); + D::mFixMass = 0.0; + } + + // empty lists for next step + mListFull.clear(); + mListEmpty.clear(); + mListNewInter.clear(); +} // reinitFlags + + + +//! lbm factory functions +LbmSolverInterface* createSolver() { +#if LBMDIM==2 + return new LbmFsgrSolver< LbmBGK2D >(); +#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"<<l<<" value:"<<m[l]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\ + " nfc"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr)<<" nfo"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setOther) ); \ + MARKCELLCHECK; \ + } +#define COLLCHECK \ + if( (rho>2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\ + errMsg("COLLCHECK","Invalid collision values r:"<<rho<<" u:"PRINT_VEC(ux,uy,uz)<<" at? "<<PRINT_IJK ); \ + MARKCELLCHECK; \ + } +#else +#define STREAMCHECK(ni,nj,nk,nl) +#define COLLCHECK +#endif + +// careful ux,uy,uz need to be inited before! + +#define DEFAULT_STREAM \ + m[dC] = RAC(ccel,dC); \ + FORDF1 { \ + CellFlagType nbf = NBFLAG( D::dfInv[l] );\ + if(nbf & CFBnd) { \ + if(nbf & CFBndNoslip) { \ + /* no slip, default */ \ + m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \ + } else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \ + /* free slip */ \ + if(l<=LBMDIM*2) { \ + m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \ + } else { \ + const int inv_l = D::dfInv[l]; \ + DEFAULT_STREAM_FREESLIP(l,inv_l,nbf); \ + } /* l>2*dim free slip */ \ + \ + } /* type reflect */\ + else {\ + errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \ + } \ + } else { \ + m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ + STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + } \ + } + +#define _________________DEFAULT_STREAM \ + m[dC] = RAC(ccel,dC); \ + FORDF1 { \ + CellFlagType nbf = NBFLAG( D::dfInv[l] );\ + if(nbf & CFBnd) { \ + if(nbf & CFBndNoslip) { \ + /* no slip, default */ \ + m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \ + } else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \ + /* free slip */ \ + if(l<=LBMDIM*2) { \ + m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \ + } else { \ + const int inv_l = D::dfInv[l]; \ + int debug_srcl = -1; \ + 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[inv_l], dy = D::dfVecY[inv_l], dz = D::dfVecZ[inv_l]; \ + \ + if(dz==0) { \ + nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); /* FIXME add noslip|free|part here */ \ + 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]); \ + debug_srcl = D::dfRefX[l]; \ + } else \ + if((!nb1)&&(nb2)) { \ + /* y reflection */\ + newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ + debug_srcl = D::dfRefY[l]; \ + } else { \ + /* normal no slip in all other cases */\ + newval = QCELL(lev, i,j,k,SRCS(lev), inv_l); \ + debug_srcl = inv_l; \ + } \ + } 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), inv_l) ); \ + } \ + /* 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), inv_l) ); \ + } \ + } \ + if(nbf & CFBndPartslip) { /* part slip interpolation */ \ + const LbmFloat partv = mObjectPartslips[(int)(nbf>>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 "<<PRINT_IJK<<",l"<<l<<" nb1"<<nb1<<" nb2"<<nb2<<" dx"<<PRINT_VEC(dx,dy,dz)<<",srcl"<<debug_srcl<<" -> "<<newval );/**/ \ + } /* l>2*dim free slip */ \ + \ + } /* type reflect */\ + else {\ + errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \ + } \ + } else { \ + m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ + STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + } \ + } + +// careful ux,uy,uz need to be inited before! +#define DEFAULT_COLLIDE \ + D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet ); \ + CSMOMEGA_STATS(lev,mDebugOmegaRet); \ + FORDF0 { RAC(tcel,l) = m[l]; } \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLLCHECK; +#define OPTIMIZED_STREAMCOLLIDE \ + m[0] = RAC(ccel,0); \ + FORDF1 { /* df0 is set later on... */ \ + /* FIXME CHECK INV ? */\ + if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ + STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + } \ + rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ + CSMOMEGA_STATS(lev,mDebugOmegaRet); \ + FORDF0 { RAC(tcel,l) = m[l]; } \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLLCHECK; + +#else // 3D, opt OPT3D==true + + +#define DEFAULT_STREAM \ + m[dC] = RAC(ccel,dC); \ + /* explicit streaming */ \ + if((!nbored & CFBnd)) { \ + /* no boundary near?, no real speed diff.? */ \ + m[dN ] = CSRC_N ; m[dS ] = CSRC_S ; \ + m[dE ] = CSRC_E ; m[dW ] = CSRC_W ; \ + m[dT ] = CSRC_T ; m[dB ] = CSRC_B ; \ + m[dNE] = CSRC_NE; m[dNW] = CSRC_NW; m[dSE] = CSRC_SE; m[dSW] = CSRC_SW; \ + m[dNT] = CSRC_NT; m[dNB] = CSRC_NB; m[dST] = CSRC_ST; m[dSB] = CSRC_SB; \ + m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \ + } else { \ + /* explicit streaming, normal velocity always zero for obstacles */ \ + if(NBFLAG(dS )&CFBnd) { m[dN ] = RAC(ccel,dS ); } else { m[dN ] = CSRC_N ; } \ + if(NBFLAG(dN )&CFBnd) { m[dS ] = RAC(ccel,dN ); } else { m[dS ] = CSRC_S ; } \ + if(NBFLAG(dW )&CFBnd) { m[dE ] = RAC(ccel,dW ); } else { m[dE ] = CSRC_E ; } \ + if(NBFLAG(dE )&CFBnd) { m[dW ] = RAC(ccel,dE ); } else { m[dW ] = CSRC_W ; } \ + if(NBFLAG(dB )&CFBnd) { m[dT ] = RAC(ccel,dB ); } else { m[dT ] = CSRC_T ; } \ + if(NBFLAG(dT )&CFBnd) { m[dB ] = RAC(ccel,dT ); } else { m[dB ] = CSRC_B ; } \ + \ + /* also treat free slip here */ \ + if(NBFLAG(dSW)&CFBnd) { if(NBFLAG(dSW)&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,NBFLAG(dSW));} } else { m[dNE] = CSRC_NE; } \ + if(NBFLAG(dSE)&CFBnd) { if(NBFLAG(dSE)&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,NBFLAG(dSE));} } else { m[dNW] = CSRC_NW; } \ + if(NBFLAG(dNW)&CFBnd) { if(NBFLAG(dNW)&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,NBFLAG(dNW));} } else { m[dSE] = CSRC_SE; } \ + if(NBFLAG(dNE)&CFBnd) { if(NBFLAG(dNE)&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,NBFLAG(dNE));} } else { m[dSW] = CSRC_SW; } \ + if(NBFLAG(dSB)&CFBnd) { if(NBFLAG(dSB)&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,NBFLAG(dSB));} } else { m[dNT] = CSRC_NT; } \ + if(NBFLAG(dST)&CFBnd) { if(NBFLAG(dST)&CFBndNoslip){ m[dNB] = RAC(ccel,dST); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,NBFLAG(dST));} } else { m[dNB] = CSRC_NB; } \ + if(NBFLAG(dNB)&CFBnd) { if(NBFLAG(dNB)&CFBndNoslip){ m[dST] = RAC(ccel,dNB); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,NBFLAG(dNB));} } else { m[dST] = CSRC_ST; } \ + if(NBFLAG(dNT)&CFBnd) { if(NBFLAG(dNT)&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,NBFLAG(dNT));} } else { m[dSB] = CSRC_SB; } \ + if(NBFLAG(dWB)&CFBnd) { if(NBFLAG(dWB)&CFBndNoslip){ m[dET] = RAC(ccel,dWB); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,NBFLAG(dWB));} } else { m[dET] = CSRC_ET; } \ + if(NBFLAG(dWT)&CFBnd) { if(NBFLAG(dWT)&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,NBFLAG(dWT));} } else { m[dEB] = CSRC_EB; } \ + if(NBFLAG(dEB)&CFBnd) { if(NBFLAG(dEB)&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,NBFLAG(dEB));} } else { m[dWT] = CSRC_WT; } \ + if(NBFLAG(dET)&CFBnd) { if(NBFLAG(dET)&CFBndNoslip){ m[dWB] = RAC(ccel,dET); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,NBFLAG(dET));} } else { m[dWB] = CSRC_WB; } \ + } + + + +#define COLL_CALCULATE_DFEQ(dstarray) \ + dstarray[dN ] = EQN ; dstarray[dS ] = EQS ; \ + dstarray[dE ] = EQE ; dstarray[dW ] = EQW ; \ + dstarray[dT ] = EQT ; dstarray[dB ] = EQB ; \ + dstarray[dNE] = EQNE; dstarray[dNW] = EQNW; dstarray[dSE] = EQSE; dstarray[dSW] = EQSW; \ + dstarray[dNT] = EQNT; dstarray[dNB] = EQNB; dstarray[dST] = EQST; dstarray[dSB] = EQSB; \ + dstarray[dET] = EQET; dstarray[dEB] = EQEB; dstarray[dWT] = EQWT; dstarray[dWB] = EQWB; +#define COLL_CALCULATE_NONEQTENSOR(csolev, srcArray ) \ + lcsmqadd = (srcArray##NE - lcsmeq[ dNE ]); \ + lcsmqadd -= (srcArray##NW - lcsmeq[ dNW ]); \ + lcsmqadd -= (srcArray##SE - lcsmeq[ dSE ]); \ + lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ + lcsmqo = (lcsmqadd* lcsmqadd); \ + lcsmqadd = (srcArray##ET - lcsmeq[ dET ]); \ + lcsmqadd -= (srcArray##EB - lcsmeq[ dEB ]); \ + lcsmqadd -= (srcArray##WT - lcsmeq[ dWT ]); \ + lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ + lcsmqo += (lcsmqadd* lcsmqadd); \ + lcsmqadd = (srcArray##NT - lcsmeq[ dNT ]); \ + lcsmqadd -= (srcArray##NB - lcsmeq[ dNB ]); \ + lcsmqadd -= (srcArray##ST - lcsmeq[ dST ]); \ + lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ + lcsmqo += (lcsmqadd* lcsmqadd); \ + lcsmqo *= 2.0; \ + lcsmqadd = (srcArray##E - lcsmeq[ dE ]); \ + lcsmqadd += (srcArray##W - lcsmeq[ dW ]); \ + lcsmqadd += (srcArray##NE - lcsmeq[ dNE ]); \ + lcsmqadd += (srcArray##NW - lcsmeq[ dNW ]); \ + lcsmqadd += (srcArray##SE - lcsmeq[ dSE ]); \ + lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ + lcsmqadd += (srcArray##ET - lcsmeq[ dET ]); \ + lcsmqadd += (srcArray##EB - lcsmeq[ dEB ]); \ + lcsmqadd += (srcArray##WT - lcsmeq[ dWT ]); \ + lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ + lcsmqo += (lcsmqadd* lcsmqadd); \ + lcsmqadd = (srcArray##N - lcsmeq[ dN ]); \ + lcsmqadd += (srcArray##S - lcsmeq[ dS ]); \ + lcsmqadd += (srcArray##NE - lcsmeq[ dNE ]); \ + lcsmqadd += (srcArray##NW - lcsmeq[ dNW ]); \ + lcsmqadd += (srcArray##SE - lcsmeq[ dSE ]); \ + lcsmqadd += (srcArray##SW - lcsmeq[ dSW ]); \ + lcsmqadd += (srcArray##NT - lcsmeq[ dNT ]); \ + lcsmqadd += (srcArray##NB - lcsmeq[ dNB ]); \ + lcsmqadd += (srcArray##ST - lcsmeq[ dST ]); \ + lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ + lcsmqo += (lcsmqadd* lcsmqadd); \ + lcsmqadd = (srcArray##T - lcsmeq[ dT ]); \ + lcsmqadd += (srcArray##B - lcsmeq[ dB ]); \ + lcsmqadd += (srcArray##NT - lcsmeq[ dNT ]); \ + lcsmqadd += (srcArray##NB - lcsmeq[ dNB ]); \ + lcsmqadd += (srcArray##ST - lcsmeq[ dST ]); \ + lcsmqadd += (srcArray##SB - lcsmeq[ dSB ]); \ + lcsmqadd += (srcArray##ET - lcsmeq[ dET ]); \ + lcsmqadd += (srcArray##EB - lcsmeq[ dEB ]); \ + lcsmqadd += (srcArray##WT - lcsmeq[ dWT ]); \ + lcsmqadd += (srcArray##WB - lcsmeq[ dWB ]); \ + lcsmqo += (lcsmqadd* lcsmqadd); \ + lcsmqo = sqrt(lcsmqo); /* FIXME check effect of sqrt*/ \ + +// COLL_CALCULATE_CSMOMEGAVAL(csolev, lcsmomega); + +// careful - need lcsmqo +#define COLL_CALCULATE_CSMOMEGAVAL(csolev, dstomega ) \ + dstomega = 1.0/\ + ( 3.0*( mLevel[(csolev)].lcnu+mLevel[(csolev)].lcsmago_sqr*(\ + -mLevel[(csolev)].lcnu + sqrt( mLevel[(csolev)].lcnu*mLevel[(csolev)].lcnu + 18.0*mLevel[(csolev)].lcsmago_sqr* lcsmqo ) \ + / (6.0*mLevel[(csolev)].lcsmago_sqr)) \ + ) +0.5 ); + +#define DEFAULT_COLLIDE_LES \ + rho = + MSRC_C + MSRC_N \ + + MSRC_S + MSRC_E \ + + MSRC_W + MSRC_T \ + + MSRC_B + MSRC_NE \ + + MSRC_NW + MSRC_SE \ + + MSRC_SW + MSRC_NT \ + + MSRC_NB + MSRC_ST \ + + MSRC_SB + MSRC_ET \ + + MSRC_EB + MSRC_WT \ + + MSRC_WB; \ + \ + ux += MSRC_E - MSRC_W \ + + MSRC_NE - MSRC_NW \ + + MSRC_SE - MSRC_SW \ + + MSRC_ET + MSRC_EB \ + - MSRC_WT - MSRC_WB ; \ + \ + uy += MSRC_N - MSRC_S \ + + MSRC_NE + MSRC_NW \ + - MSRC_SE - MSRC_SW \ + + MSRC_NT + MSRC_NB \ + - MSRC_ST - MSRC_SB ; \ + \ + uz += MSRC_T - MSRC_B \ + + MSRC_NT - MSRC_NB \ + + MSRC_ST - MSRC_SB \ + + MSRC_ET - MSRC_EB \ + + MSRC_WT - MSRC_WB ; \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev, MSRC_)\ + COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ + CSMOMEGA_STATS(lev,lcsmomega); \ + \ + RAC(tcel,dC ) = (1.0-lcsmomega)*MSRC_C + lcsmomega*EQC ; \ + \ + RAC(tcel,dN ) = (1.0-lcsmomega)*MSRC_N + lcsmomega*lcsmeq[ dN ]; \ + RAC(tcel,dS ) = (1.0-lcsmomega)*MSRC_S + lcsmomega*lcsmeq[ dS ]; \ + RAC(tcel,dE ) = (1.0-lcsmomega)*MSRC_E + lcsmomega*lcsmeq[ dE ]; \ + RAC(tcel,dW ) = (1.0-lcsmomega)*MSRC_W + lcsmomega*lcsmeq[ dW ]; \ + RAC(tcel,dT ) = (1.0-lcsmomega)*MSRC_T + lcsmomega*lcsmeq[ dT ]; \ + RAC(tcel,dB ) = (1.0-lcsmomega)*MSRC_B + lcsmomega*lcsmeq[ dB ]; \ + \ + RAC(tcel,dNE) = (1.0-lcsmomega)*MSRC_NE + lcsmomega*lcsmeq[ dNE]; \ + RAC(tcel,dNW) = (1.0-lcsmomega)*MSRC_NW + lcsmomega*lcsmeq[ dNW]; \ + RAC(tcel,dSE) = (1.0-lcsmomega)*MSRC_SE + lcsmomega*lcsmeq[ dSE]; \ + RAC(tcel,dSW) = (1.0-lcsmomega)*MSRC_SW + lcsmomega*lcsmeq[ dSW]; \ + RAC(tcel,dNT) = (1.0-lcsmomega)*MSRC_NT + lcsmomega*lcsmeq[ dNT]; \ + RAC(tcel,dNB) = (1.0-lcsmomega)*MSRC_NB + lcsmomega*lcsmeq[ dNB]; \ + RAC(tcel,dST) = (1.0-lcsmomega)*MSRC_ST + lcsmomega*lcsmeq[ dST]; \ + RAC(tcel,dSB) = (1.0-lcsmomega)*MSRC_SB + lcsmomega*lcsmeq[ dSB]; \ + RAC(tcel,dET) = (1.0-lcsmomega)*MSRC_ET + lcsmomega*lcsmeq[ dET]; \ + RAC(tcel,dEB) = (1.0-lcsmomega)*MSRC_EB + lcsmomega*lcsmeq[ dEB]; \ + RAC(tcel,dWT) = (1.0-lcsmomega)*MSRC_WT + lcsmomega*lcsmeq[ dWT]; \ + RAC(tcel,dWB) = (1.0-lcsmomega)*MSRC_WB + lcsmomega*lcsmeq[ dWB]; + +#define DEFAULT_COLLIDE_NOLES \ + rho = + MSRC_C + MSRC_N \ + + MSRC_S + MSRC_E \ + + MSRC_W + MSRC_T \ + + MSRC_B + MSRC_NE \ + + MSRC_NW + MSRC_SE \ + + MSRC_SW + MSRC_NT \ + + MSRC_NB + MSRC_ST \ + + MSRC_SB + MSRC_ET \ + + MSRC_EB + MSRC_WT \ + + MSRC_WB; \ + \ + ux += MSRC_E - MSRC_W \ + + MSRC_NE - MSRC_NW \ + + MSRC_SE - MSRC_SW \ + + MSRC_ET + MSRC_EB \ + - MSRC_WT - MSRC_WB ; \ + \ + uy += MSRC_N - MSRC_S \ + + MSRC_NE + MSRC_NW \ + - MSRC_SE - MSRC_SW \ + + MSRC_NT + MSRC_NB \ + - MSRC_ST - MSRC_SB ; \ + \ + uz += MSRC_T - MSRC_B \ + + MSRC_NT - MSRC_NB \ + + MSRC_ST - MSRC_SB \ + + MSRC_ET - MSRC_EB \ + + MSRC_WT - MSRC_WB ; \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + \ + RAC(tcel,dC ) = (1.0-OMEGA(lev))*MSRC_C + OMEGA(lev)*EQC ; \ + \ + RAC(tcel,dN ) = (1.0-OMEGA(lev))*MSRC_N + OMEGA(lev)*EQN ; \ + RAC(tcel,dS ) = (1.0-OMEGA(lev))*MSRC_S + OMEGA(lev)*EQS ; \ + RAC(tcel,dE ) = (1.0-OMEGA(lev))*MSRC_E + OMEGA(lev)*EQE ; \ + RAC(tcel,dW ) = (1.0-OMEGA(lev))*MSRC_W + OMEGA(lev)*EQW ; \ + RAC(tcel,dT ) = (1.0-OMEGA(lev))*MSRC_T + OMEGA(lev)*EQT ; \ + RAC(tcel,dB ) = (1.0-OMEGA(lev))*MSRC_B + OMEGA(lev)*EQB ; \ + \ + RAC(tcel,dNE) = (1.0-OMEGA(lev))*MSRC_NE + OMEGA(lev)*EQNE; \ + RAC(tcel,dNW) = (1.0-OMEGA(lev))*MSRC_NW + OMEGA(lev)*EQNW; \ + RAC(tcel,dSE) = (1.0-OMEGA(lev))*MSRC_SE + OMEGA(lev)*EQSE; \ + RAC(tcel,dSW) = (1.0-OMEGA(lev))*MSRC_SW + OMEGA(lev)*EQSW; \ + RAC(tcel,dNT) = (1.0-OMEGA(lev))*MSRC_NT + OMEGA(lev)*EQNT; \ + RAC(tcel,dNB) = (1.0-OMEGA(lev))*MSRC_NB + OMEGA(lev)*EQNB; \ + RAC(tcel,dST) = (1.0-OMEGA(lev))*MSRC_ST + OMEGA(lev)*EQST; \ + RAC(tcel,dSB) = (1.0-OMEGA(lev))*MSRC_SB + OMEGA(lev)*EQSB; \ + RAC(tcel,dET) = (1.0-OMEGA(lev))*MSRC_ET + OMEGA(lev)*EQET; \ + RAC(tcel,dEB) = (1.0-OMEGA(lev))*MSRC_EB + OMEGA(lev)*EQEB; \ + RAC(tcel,dWT) = (1.0-OMEGA(lev))*MSRC_WT + OMEGA(lev)*EQWT; \ + RAC(tcel,dWB) = (1.0-OMEGA(lev))*MSRC_WB + OMEGA(lev)*EQWB; + + + +#define OPTIMIZED_STREAMCOLLIDE_LES \ + /* only surrounded by fluid cells...!, so safe streaming here... */ \ + m[dC ] = CSRC_C ; \ + m[dN ] = CSRC_N ; m[dS ] = CSRC_S ; \ + m[dE ] = CSRC_E ; m[dW ] = CSRC_W ; \ + m[dT ] = CSRC_T ; m[dB ] = CSRC_B ; \ + m[dNE] = CSRC_NE; m[dNW] = CSRC_NW; m[dSE] = CSRC_SE; m[dSW] = CSRC_SW; \ + m[dNT] = CSRC_NT; m[dNB] = CSRC_NB; m[dST] = CSRC_ST; m[dSB] = CSRC_SB; \ + m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \ + \ + rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T \ + + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT \ + + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; \ + ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW \ + + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB + mLevel[lev].gravity[0]; \ + uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW \ + + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB + mLevel[lev].gravity[1]; \ + uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB \ + + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB + mLevel[lev].gravity[2]; \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev, MSRC_) \ + COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ + CSMOMEGA_STATS(lev,lcsmomega); \ + \ + RAC(tcel,dC ) = (1.0-lcsmomega)*MSRC_C + lcsmomega*EQC ; \ + RAC(tcel,dN ) = (1.0-lcsmomega)*MSRC_N + lcsmomega*lcsmeq[ dN ]; \ + RAC(tcel,dS ) = (1.0-lcsmomega)*MSRC_S + lcsmomega*lcsmeq[ dS ]; \ + RAC(tcel,dE ) = (1.0-lcsmomega)*MSRC_E + lcsmomega*lcsmeq[ dE ]; \ + RAC(tcel,dW ) = (1.0-lcsmomega)*MSRC_W + lcsmomega*lcsmeq[ dW ]; \ + RAC(tcel,dT ) = (1.0-lcsmomega)*MSRC_T + lcsmomega*lcsmeq[ dT ]; \ + RAC(tcel,dB ) = (1.0-lcsmomega)*MSRC_B + lcsmomega*lcsmeq[ dB ]; \ + \ + RAC(tcel,dNE) = (1.0-lcsmomega)*MSRC_NE + lcsmomega*lcsmeq[ dNE]; \ + RAC(tcel,dNW) = (1.0-lcsmomega)*MSRC_NW + lcsmomega*lcsmeq[ dNW]; \ + RAC(tcel,dSE) = (1.0-lcsmomega)*MSRC_SE + lcsmomega*lcsmeq[ dSE]; \ + RAC(tcel,dSW) = (1.0-lcsmomega)*MSRC_SW + lcsmomega*lcsmeq[ dSW]; \ + \ + RAC(tcel,dNT) = (1.0-lcsmomega)*MSRC_NT + lcsmomega*lcsmeq[ dNT]; \ + RAC(tcel,dNB) = (1.0-lcsmomega)*MSRC_NB + lcsmomega*lcsmeq[ dNB]; \ + RAC(tcel,dST) = (1.0-lcsmomega)*MSRC_ST + lcsmomega*lcsmeq[ dST]; \ + RAC(tcel,dSB) = (1.0-lcsmomega)*MSRC_SB + lcsmomega*lcsmeq[ dSB]; \ + \ + RAC(tcel,dET) = (1.0-lcsmomega)*MSRC_ET + lcsmomega*lcsmeq[ dET]; \ + RAC(tcel,dEB) = (1.0-lcsmomega)*MSRC_EB + lcsmomega*lcsmeq[ dEB]; \ + RAC(tcel,dWT) = (1.0-lcsmomega)*MSRC_WT + lcsmomega*lcsmeq[ dWT]; \ + RAC(tcel,dWB) = (1.0-lcsmomega)*MSRC_WB + lcsmomega*lcsmeq[ dWB]; \ + +#define OPTIMIZED_STREAMCOLLIDE_UNUSED \ + /* only surrounded by fluid cells...!, so safe streaming here... */ \ + rho = CSRC_C + CSRC_N + CSRC_S + CSRC_E + CSRC_W + CSRC_T \ + + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ + + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ + ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ + + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ + uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ + + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ + uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ + + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev, CSRC_) \ + COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ + \ + RAC(tcel,dC ) = (1.0-lcsmomega)*CSRC_C + lcsmomega*EQC ; \ + RAC(tcel,dN ) = (1.0-lcsmomega)*CSRC_N + lcsmomega*lcsmeq[ dN ]; \ + RAC(tcel,dS ) = (1.0-lcsmomega)*CSRC_S + lcsmomega*lcsmeq[ dS ]; \ + RAC(tcel,dE ) = (1.0-lcsmomega)*CSRC_E + lcsmomega*lcsmeq[ dE ]; \ + RAC(tcel,dW ) = (1.0-lcsmomega)*CSRC_W + lcsmomega*lcsmeq[ dW ]; \ + RAC(tcel,dT ) = (1.0-lcsmomega)*CSRC_T + lcsmomega*lcsmeq[ dT ]; \ + RAC(tcel,dB ) = (1.0-lcsmomega)*CSRC_B + lcsmomega*lcsmeq[ dB ]; \ + \ + RAC(tcel,dNE) = (1.0-lcsmomega)*CSRC_NE + lcsmomega*lcsmeq[ dNE]; \ + RAC(tcel,dNW) = (1.0-lcsmomega)*CSRC_NW + lcsmomega*lcsmeq[ dNW]; \ + RAC(tcel,dSE) = (1.0-lcsmomega)*CSRC_SE + lcsmomega*lcsmeq[ dSE]; \ + RAC(tcel,dSW) = (1.0-lcsmomega)*CSRC_SW + lcsmomega*lcsmeq[ dSW]; \ + \ + RAC(tcel,dNT) = (1.0-lcsmomega)*CSRC_NT + lcsmomega*lcsmeq[ dNT]; \ + RAC(tcel,dNB) = (1.0-lcsmomega)*CSRC_NB + lcsmomega*lcsmeq[ dNB]; \ + RAC(tcel,dST) = (1.0-lcsmomega)*CSRC_ST + lcsmomega*lcsmeq[ dST]; \ + RAC(tcel,dSB) = (1.0-lcsmomega)*CSRC_SB + lcsmomega*lcsmeq[ dSB]; \ + \ + RAC(tcel,dET) = (1.0-lcsmomega)*CSRC_ET + lcsmomega*lcsmeq[ dET]; \ + RAC(tcel,dEB) = (1.0-lcsmomega)*CSRC_EB + lcsmomega*lcsmeq[ dEB]; \ + RAC(tcel,dWT) = (1.0-lcsmomega)*CSRC_WT + lcsmomega*lcsmeq[ dWT]; \ + RAC(tcel,dWB) = (1.0-lcsmomega)*CSRC_WB + lcsmomega*lcsmeq[ dWB]; \ + +#define OPTIMIZED_STREAMCOLLIDE_NOLES \ + /* only surrounded by fluid cells...!, so safe streaming here... */ \ + rho = CSRC_C + CSRC_N + CSRC_S + CSRC_E + CSRC_W + CSRC_T \ + + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ + + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ + ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ + + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ + uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ + + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ + uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ + + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + RAC(tcel,dC ) = (1.0-OMEGA(lev))*CSRC_C + OMEGA(lev)*EQC ; \ + RAC(tcel,dN ) = (1.0-OMEGA(lev))*CSRC_N + OMEGA(lev)*EQN ; \ + RAC(tcel,dS ) = (1.0-OMEGA(lev))*CSRC_S + OMEGA(lev)*EQS ; \ + RAC(tcel,dE ) = (1.0-OMEGA(lev))*CSRC_E + OMEGA(lev)*EQE ; \ + RAC(tcel,dW ) = (1.0-OMEGA(lev))*CSRC_W + OMEGA(lev)*EQW ; \ + RAC(tcel,dT ) = (1.0-OMEGA(lev))*CSRC_T + OMEGA(lev)*EQT ; \ + RAC(tcel,dB ) = (1.0-OMEGA(lev))*CSRC_B + OMEGA(lev)*EQB ; \ + \ + RAC(tcel,dNE) = (1.0-OMEGA(lev))*CSRC_NE + OMEGA(lev)*EQNE; \ + RAC(tcel,dNW) = (1.0-OMEGA(lev))*CSRC_NW + OMEGA(lev)*EQNW; \ + RAC(tcel,dSE) = (1.0-OMEGA(lev))*CSRC_SE + OMEGA(lev)*EQSE; \ + RAC(tcel,dSW) = (1.0-OMEGA(lev))*CSRC_SW + OMEGA(lev)*EQSW; \ + \ + RAC(tcel,dNT) = (1.0-OMEGA(lev))*CSRC_NT + OMEGA(lev)*EQNT; \ + RAC(tcel,dNB) = (1.0-OMEGA(lev))*CSRC_NB + OMEGA(lev)*EQNB; \ + RAC(tcel,dST) = (1.0-OMEGA(lev))*CSRC_ST + OMEGA(lev)*EQST; \ + RAC(tcel,dSB) = (1.0-OMEGA(lev))*CSRC_SB + OMEGA(lev)*EQSB; \ + \ + RAC(tcel,dET) = (1.0-OMEGA(lev))*CSRC_ET + OMEGA(lev)*EQET; \ + RAC(tcel,dEB) = (1.0-OMEGA(lev))*CSRC_EB + OMEGA(lev)*EQEB; \ + RAC(tcel,dWT) = (1.0-OMEGA(lev))*CSRC_WT + OMEGA(lev)*EQWT; \ + RAC(tcel,dWB) = (1.0-OMEGA(lev))*CSRC_WB + OMEGA(lev)*EQWB; \ + + +// debug version1 +#define STREAMCHECK(ni,nj,nk,nl) +#define COLLCHECK +#define OPTIMIZED_STREAMCOLLIDE_DEBUG \ + m[0] = RAC(ccel,0); \ + FORDF1 { /* df0 is set later on... */ \ + if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ + STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + } \ + rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ + CSMOMEGA_STATS(lev,mDebugOmegaRet); \ + FORDF0 { RAC(tcel,l) = m[l]; } \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + COLLCHECK; + + + +// more debugging +/*DEBUG \ + m[0] = RAC(ccel,0); \ + FORDF1 { \ + if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ + } \ +errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lcsmomega ); \ + rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet ); \ + CSMOMEGA_STATS(lev,mDebugOmegaRet); \ + */ +#if USE_LES==1 +#define DEFAULT_COLLIDE DEFAULT_COLLIDE_LES +#define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_LES +#else +#define DEFAULT_COLLIDE DEFAULT_COLLIDE_NOLES +#define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_NOLES +#endif + +#endif + +#define USQRMAXCHECK(Cusqr,Cux,Cuy,Cuz, CmMaxVlen,CmMxvx,CmMxvy,CmMxvz) \ + if(Cusqr>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)<<" "<<PRINT_VEC((ai),(aj),(ak))<<" fc:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )<<" fo:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )<<" dfl"<<l ); \ + debugMarkCell((alev), (ai),(aj),(ak));\ + D::mPanic = 1; \ + } + // end ADD_INT_DFSCHECK +#define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) \ + if( (((1.0-(at))>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)<<" "<<PRINT_VEC((ai),(aj),(ak))<<\ + " fc:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )) <<\ + " fold:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )) ); \ + debugMarkCell((alev), (ai),(aj),(ak));\ + D::mPanic = 1; \ + } + // end ADD_INT_DFSCHECK + + //if( !(RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) & CFUnused) ){ + //errMsg("INTFLAGUNU", PRINT_VEC(i,j,k)<<" child at "<<PRINT_VEC((ix),(iy),(iz)) ); + //if(iy==15) errMsg("IFFC", PRINT_VEC(i,j,k)<<" child interpolated at "<<PRINT_VEC((ix),(iy),(iz)) ); + //if(((ix)>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)<<" "<<PRINT_VEC((ix),(iy),(iz))<<" flag: "<< RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) ); \ + debugMarkCell((lev+1), (ix),(iy),(iz));\ + D::mPanic = 1; \ + }\ + RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) |= CFGrCoarseInited; \ + // INTUNUTCHECK +#define INTSTRICTCHECK(ix,iy,iz,caseId) \ + if( QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) <= 0.0 ){\ + errMsg("INVDFCCELLCHECK", "caseId:"<<caseId<<" "<<PRINT_VEC(i,j,k)<<" child inter at "<<PRINT_VEC((ix),(iy),(iz))<<" invalid df "<<l<<" = "<< QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) ); \ + debugMarkCell((lev+1), (ix),(iy),(iz));\ + D::mPanic = 1; \ + }\ + // INTSTRICTCHECK + +#else// FSGR_STRICT_DEBUG==1 +#define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) +#define ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l) +#define INTSTRICTCHECK(x,y,z,caseId) +#define INTUNUTCHECK(ix,iy,iz) +#endif// FSGR_STRICT_DEBUG==1 + + +#if FSGR_STRICT_DEBUG==1 +#define INTDEBOUT \ + { /*LbmFloat rho,ux,uy,uz;*/ \ + rho = ux=uy=uz=0.0; \ + FORDF0{ LbmFloat m = QCELL(lev,i,j,k, dstSet, l); \ + rho += m; ux += (D::dfDvecX[l]*m); uy += (D::dfDvecY[l]*m); uz += (D::dfDvecZ[l]*m); \ + if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m ); D::mPanic=1; }\ + /*errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" df"<<l<<":"<<m );*/ \ + } \ + /*if(D::mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \ + if(markNbs) errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); \ + /*errMsg("interpolateCellFromCoarse", "ICFC_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); */\ + } \ + /* both cases are ok to interpolate */ \ + if( (!(RFLAG(lev,i,j,k, dstSet) & CFGrFromCoarse)) && \ + (!(RFLAG(lev,i,j,k, dstSet) & CFUnused)) ) { \ + /* might also have CFGrCoarseInited (shouldnt be a problem here)*/ \ + errMsg("interpolateCellFromCoarse", "CHECK cell not CFGrFromCoarse? "<<PRINT_IJK<<" flag:"<< RFLAG(lev,i,j,k, dstSet)<<" fstr:"<<convertCellFlagType2String( RFLAG(lev,i,j,k, dstSet) )); \ + /* FIXME check this warning...? return; this can happen !? */ \ + /*D::mPanic = 1;*/ \ + } \ + // end INTDEBOUT +#else // FSGR_STRICT_DEBUG==1 +#define INTDEBOUT +#endif // FSGR_STRICT_DEBUG==1 + + +// t=0.0 -> 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"<<mDfScaleDown<<" n"<<dfScale<<" qc"<< QCELL(lev,i,j,k, dstSet, l)<<" idf"<<intDf[l]<<" eq"<<feq[l] ); */ \ + QCELL(lev,i,j,k, dstSet, l) = (feq[l]+ (intDf[l]-feq[l])*dfScale);\ + } \ + /* check that all values are ok */ \ + INTDEBOUT + +#else //OPT3D==0 + +#define ADDALLVALS \ + addVal = addDfFacT * RAC(addfcel , dC ); \ + intDf[dC ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dN ); \ + uy+=addVal; intDf[dN ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dS ); \ + uy-=addVal; intDf[dS ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dE ); \ + ux+=addVal; intDf[dE ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dW ); \ + ux-=addVal; intDf[dW ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dT ); \ + uz+=addVal; intDf[dT ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dB ); \ + uz-=addVal; intDf[dB ] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dNE); \ + ux+=addVal; uy+=addVal; intDf[dNE] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dNW); \ + ux-=addVal; uy+=addVal; intDf[dNW] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dSE); \ + ux+=addVal; uy-=addVal; intDf[dSE] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dSW); \ + ux-=addVal; uy-=addVal; intDf[dSW] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dNT); \ + uy+=addVal; uz+=addVal; intDf[dNT] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dNB); \ + uy+=addVal; uz-=addVal; intDf[dNB] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dST); \ + uy-=addVal; uz+=addVal; intDf[dST] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dSB); \ + uy-=addVal; uz-=addVal; intDf[dSB] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dET); \ + ux+=addVal; uz+=addVal; intDf[dET] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dEB); \ + ux+=addVal; uz-=addVal; intDf[dEB] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dWT); \ + ux-=addVal; uz+=addVal; intDf[dWT] += addVal; rho += addVal; \ + addVal = addDfFacT * RAC(addfcel , dWB); \ + ux-=addVal; uz-=addVal; intDf[dWB] += addVal; rho += addVal; + +#define ADD_INT_DFS(alev, ai,aj,ak, at, afac) \ + addDfFacT = at*afac; \ + addfcel = RACPNT((alev), (ai),(aj),(ak),mLevel[(alev)].setOther); \ + ADDALLVALS\ + addDfFacT = (1.0-at)*afac; \ + addfcel = RACPNT((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr); \ + ADDALLVALS + +// also ugly... +#define INTDF_C intDf[dC ] +#define INTDF_N intDf[dN ] +#define INTDF_S intDf[dS ] +#define INTDF_E intDf[dE ] +#define INTDF_W intDf[dW ] +#define INTDF_T intDf[dT ] +#define INTDF_B intDf[dB ] +#define INTDF_NE intDf[dNE] +#define INTDF_NW intDf[dNW] +#define INTDF_SE intDf[dSE] +#define INTDF_SW intDf[dSW] +#define INTDF_NT intDf[dNT] +#define INTDF_NB intDf[dNB] +#define INTDF_ST intDf[dST] +#define INTDF_SB intDf[dSB] +#define INTDF_ET intDf[dET] +#define INTDF_EB intDf[dEB] +#define INTDF_WT intDf[dWT] +#define INTDF_WB intDf[dWB] + + +// write interpolated dfs back to cell (correct non-eq. parts) +#define IDF_WRITEBACK_LES \ + dstcell = RACPNT(lev, i,j,k,dstSet); \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + \ + lcsmeq[dC] = EQC ; \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev, INTDF_ )\ + COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ + COLL_CALCULATE_CSMOMEGAVAL(lev-1, lcsmSrcOmega); \ + \ + lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ + RAC(dstcell, dC ) = (lcsmeq[dC ] + (intDf[dC ]-lcsmeq[dC ] )*lcsmdfscale);\ + RAC(dstcell, dN ) = (lcsmeq[dN ] + (intDf[dN ]-lcsmeq[dN ] )*lcsmdfscale);\ + RAC(dstcell, dS ) = (lcsmeq[dS ] + (intDf[dS ]-lcsmeq[dS ] )*lcsmdfscale);\ + RAC(dstcell, dE ) = (lcsmeq[dE ] + (intDf[dE ]-lcsmeq[dE ] )*lcsmdfscale);\ + RAC(dstcell, dW ) = (lcsmeq[dW ] + (intDf[dW ]-lcsmeq[dW ] )*lcsmdfscale);\ + RAC(dstcell, dT ) = (lcsmeq[dT ] + (intDf[dT ]-lcsmeq[dT ] )*lcsmdfscale);\ + RAC(dstcell, dB ) = (lcsmeq[dB ] + (intDf[dB ]-lcsmeq[dB ] )*lcsmdfscale);\ + RAC(dstcell, dNE) = (lcsmeq[dNE] + (intDf[dNE]-lcsmeq[dNE] )*lcsmdfscale);\ + RAC(dstcell, dNW) = (lcsmeq[dNW] + (intDf[dNW]-lcsmeq[dNW] )*lcsmdfscale);\ + RAC(dstcell, dSE) = (lcsmeq[dSE] + (intDf[dSE]-lcsmeq[dSE] )*lcsmdfscale);\ + RAC(dstcell, dSW) = (lcsmeq[dSW] + (intDf[dSW]-lcsmeq[dSW] )*lcsmdfscale);\ + RAC(dstcell, dNT) = (lcsmeq[dNT] + (intDf[dNT]-lcsmeq[dNT] )*lcsmdfscale);\ + RAC(dstcell, dNB) = (lcsmeq[dNB] + (intDf[dNB]-lcsmeq[dNB] )*lcsmdfscale);\ + RAC(dstcell, dST) = (lcsmeq[dST] + (intDf[dST]-lcsmeq[dST] )*lcsmdfscale);\ + RAC(dstcell, dSB) = (lcsmeq[dSB] + (intDf[dSB]-lcsmeq[dSB] )*lcsmdfscale);\ + RAC(dstcell, dET) = (lcsmeq[dET] + (intDf[dET]-lcsmeq[dET] )*lcsmdfscale);\ + RAC(dstcell, dEB) = (lcsmeq[dEB] + (intDf[dEB]-lcsmeq[dEB] )*lcsmdfscale);\ + RAC(dstcell, dWT) = (lcsmeq[dWT] + (intDf[dWT]-lcsmeq[dWT] )*lcsmdfscale);\ + RAC(dstcell, dWB) = (lcsmeq[dWB] + (intDf[dWB]-lcsmeq[dWB] )*lcsmdfscale);\ + /* IDF_WRITEBACK optimized */ + +#define IDF_WRITEBACK_NOLES \ + dstcell = RACPNT(lev, i,j,k,dstSet); \ + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + \ + RAC(dstcell, dC ) = (EQC + (intDf[dC ]-EQC )*mDfScaleDown);\ + RAC(dstcell, dN ) = (EQN + (intDf[dN ]-EQN )*mDfScaleDown);\ + RAC(dstcell, dS ) = (EQS + (intDf[dS ]-EQS )*mDfScaleDown);\ + /*old*/ RAC(dstcell, dE ) = (EQE + (intDf[dE ]-EQE )*mDfScaleDown);\ + RAC(dstcell, dW ) = (EQW + (intDf[dW ]-EQW )*mDfScaleDown);\ + RAC(dstcell, dT ) = (EQT + (intDf[dT ]-EQT )*mDfScaleDown);\ + RAC(dstcell, dB ) = (EQB + (intDf[dB ]-EQB )*mDfScaleDown);\ + /*old*/ RAC(dstcell, dNE) = (EQNE + (intDf[dNE]-EQNE )*mDfScaleDown);\ + RAC(dstcell, dNW) = (EQNW + (intDf[dNW]-EQNW )*mDfScaleDown);\ + RAC(dstcell, dSE) = (EQSE + (intDf[dSE]-EQSE )*mDfScaleDown);\ + RAC(dstcell, dSW) = (EQSW + (intDf[dSW]-EQSW )*mDfScaleDown);\ + RAC(dstcell, dNT) = (EQNT + (intDf[dNT]-EQNT )*mDfScaleDown);\ + RAC(dstcell, dNB) = (EQNB + (intDf[dNB]-EQNB )*mDfScaleDown);\ + RAC(dstcell, dST) = (EQST + (intDf[dST]-EQST )*mDfScaleDown);\ + RAC(dstcell, dSB) = (EQSB + (intDf[dSB]-EQSB )*mDfScaleDown);\ + RAC(dstcell, dET) = (EQET + (intDf[dET]-EQET )*mDfScaleDown);\ + /*old*/ RAC(dstcell, dEB) = (EQEB + (intDf[dEB]-EQEB )*mDfScaleDown);\ + RAC(dstcell, dWT) = (EQWT + (intDf[dWT]-EQWT )*mDfScaleDown);\ + RAC(dstcell, dWB) = (EQWB + (intDf[dWB]-EQWB )*mDfScaleDown);\ + /* IDF_WRITEBACK optimized */ + +#if USE_LES==1 +#define IDF_WRITEBACK IDF_WRITEBACK_LES +#else +#define IDF_WRITEBACK IDF_WRITEBACK_NOLES +#endif + +#endif// OPT3D==0 + diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp new file mode 100644 index 00000000000..1d25bcd3dd8 --- /dev/null +++ b/intern/elbeem/intern/solver_util.cpp @@ -0,0 +1,861 @@ +/****************************************************************************** + * + * 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" + +//! for raytracing +template<class D> +void LbmFsgrSolver<D>::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;j<mLevel[lev].lSizey-0;j++) + for(int i=0;i<mLevel[lev].lSizex-0;i++) { + *D::mpIso->lbmGetData(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;j<mLevel[lev].lSizey-0;j++) + for(int i=0;i<mLevel[lev].lSizex-0;i++) { + *D::mpIso->lbmGetData(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;j<mLevel[lev].lSizey-1;j++) + for(int i=1;i<mLevel[lev].lSizex-1;i++) { + + //continue; // OFF DEBUG + if(RFLAG(lev, i,j,k,workSet)&(CFBnd|CFEmpty)) { + continue; + } else + if( (RFLAG(lev, i,j,k,workSet)&CFInter) && (!(RFLAG(lev, i,j,k,workSet)&CFNoNbEmpty)) ){ + // no empty nb interface cells are treated as full + val = (QCELL(lev, i,j,k,workSet, dFfrac)); + //if( (!(RFLAG(lev, i,j,k,workSet)&CFNoBndFluid)) &&(RFLAG(lev, i,j,k,workSet)&CFNoNbFluid)){ val += D::mIsoValue; } + } else { + // fluid? + val = 1.0; ///27.0; + } // */ + + *D::mpIso->lbmGetData( 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;j<pvsy;j++) + for(int i=0;i<pvsx;i++) { + *mpPreviewSurface->lbmGetData(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<class D> +void LbmFsgrSolver<D>::advanceParticles(ParticleTracer *partt ) { + partt = NULL; // remove warning +} + + +/****************************************************************************** + * reset particle positions to default + *****************************************************************************/ +/*! init particle positions */ +template<class D> +int LbmFsgrSolver<D>::initParticles(ParticleTracer *partt) { + partt = NULL; // remove warning + return 0; +} + + +/*! init particle positions */ +template<class D> +void LbmFsgrSolver<D>::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"<<i<<" set to "<< mObjectSpeeds[i]<<", unscaled:"<< (*D::mpGiObjects)[i]->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 "<<mDomainPartSlipValue); + mObjectPartslips[numobjs] = mDomainPartSlipValue; +} + +/*****************************************************************************/ +/*! internal quick print function (for debugging) */ +/*****************************************************************************/ +template<class D> +void +LbmFsgrSolver<D>::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<class D> +void +LbmFsgrSolver<D>::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<UniformFsgrCellIdentifier> 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<class D> +CellIdentifierInterface* +LbmFsgrSolver<D>::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<class D> +typename LbmFsgrSolver<D>::stdCellId* +LbmFsgrSolver<D>::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { + //stdCellId *cid = dynamic_cast<stdCellId*>( basecid ); + stdCellId *cid = (stdCellId*)( basecid ); + return cid; +} + +template<class D> +void +LbmFsgrSolver<D>::advanceCell( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + if(cid->getEnd()) return; + + //debugOut(" ADb "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->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 "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->getEnd(), 10); +} + +template<class D> +bool +LbmFsgrSolver<D>::noEndCell( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return (!cid->getEnd()); +} + +template<class D> +void +LbmFsgrSolver<D>::deleteCellIterator( CellIdentifierInterface** cid ) { + delete *cid; + *cid = NULL; +} + +template<class D> +CellIdentifierInterface* +LbmFsgrSolver<D>::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)) ) || + ( (level<mMaxRefine) && (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused|CFEmpty)) ) ) { + continue; + } // */ + + stdCellId *newcid = new stdCellId; + newcid->level = level; + newcid->x = x; + newcid->y = y; + newcid->z = z; + //errMsg("cellAt",D::mName<<" "<<pos<<" l"<<level<<":"<<x<<","<<y<<","<<z<<" "<<convertCellFlagType2String(RFLAG(level, x,y,z, mLevel[level].setCurr)) ); + return newcid; + } + + return NULL; +} + + +// INFO functions + +template<class D> +int +LbmFsgrSolver<D>::getCellSet ( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return mLevel[cid->level].setCurr; + //return mLevel[cid->level].setOther; +} + +template<class D> +int +LbmFsgrSolver<D>::getCellLevel ( CellIdentifierInterface* basecid) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return cid->level; +} + +template<class D> +ntlVec3Gfx +LbmFsgrSolver<D>::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<class D> +ntlVec3Gfx +LbmFsgrSolver<D>::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<class D> +LbmFloat +LbmFsgrSolver<D>::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<class D> +LbmVec +LbmFsgrSolver<D>::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<class D> +LbmFloat +LbmFsgrSolver<D>::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); +} +template<class D> +LbmFloat +LbmFsgrSolver<D>::getCellMass( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); +} +template<class D> +LbmFloat +LbmFsgrSolver<D>::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<class D> +CellFlagType +LbmFsgrSolver<D>::getCellFlag( CellIdentifierInterface* basecid,int set) { + stdCellId *cid = convertBaseCidToStdCid(basecid); + return RFLAG(cid->level, cid->x,cid->y,cid->z, set); +} + +template<class D> +LbmFloat +LbmFsgrSolver<D>::getEquilDf( int l ) { + return D::dfEquil[l]; +} + +template<class D> +int +LbmFsgrSolver<D>::getDfNum( ) { + return D::cDfNum; +} + +#if LBM_USE_GUI==1 +//! show simulation info (implement SimulationObject pure virtual func) +template<class D> +void +LbmFsgrSolver<D>::debugDisplay(fluidDispSettings *set){ + //lbmDebugDisplay< LbmFsgrSolver<D> >( set, this ); + lbmDebugDisplay( set ); +} +#endif + +/*****************************************************************************/ +// strict debugging functions +/*****************************************************************************/ +#if FSGR_STRICT_DEBUG==1 +#define STRICT_EXIT *((int *)0)=0; + +template<class D> +int LbmFsgrSolver<D>::debLBMGI(int level, int ii,int ij,int ik, int is) { + if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(level > mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + + if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + return _LBMGI(level, ii,ij,ik, is); +}; + +template<class D> +CellFlagType& LbmFsgrSolver<D>::debRFLAG(int level, int xx,int yy,int zz,int set){ + return _RFLAG(level, xx,yy,zz,set); +}; + +template<class D> +CellFlagType& LbmFsgrSolver<D>::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + // warning might access all spatial nbs + if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + return _RFLAG_NB(level, xx,yy,zz,set, dir); +}; + +template<class D> +CellFlagType& LbmFsgrSolver<D>::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + return _RFLAG_NBINV(level, xx,yy,zz,set, dir); +}; + +template<class D> +int LbmFsgrSolver<D>::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { + if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(level > mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + + if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } + if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } + if(l>D::cDfNum){ // dFfrac is an exception + if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } +#if COMPRESSGRIDS==1 + //if((!D::mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug +#endif // COMPRESSGRIDS==1 + return _LBMQI(level, ii,ij,ik, is, l); +}; + +template<class D> +LbmFloat& LbmFsgrSolver<D>::debQCELL(int level, int xx,int yy,int zz,int set,int l) { + //errMsg("LbmStrict","debQCELL debug: l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" l"<<l<<" index"<<LBMGI(level, xx,yy,zz,set)); + return _QCELL(level, xx,yy,zz,set,l); +}; + +template<class D> +LbmFloat& LbmFsgrSolver<D>::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + return _QCELL_NB(level, xx,yy,zz,set, dir,l); +}; + +template<class D> +LbmFloat& LbmFsgrSolver<D>::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { + if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + return _QCELL_NBINV(level, xx,yy,zz,set, dir,l); +}; + +template<class D> +LbmFloat* LbmFsgrSolver<D>::debRACPNT(int level, int ii,int ij,int ik, int is ) { + return _RACPNT(level, ii,ij,ik, is ); +}; + +template<class D> +LbmFloat& LbmFsgrSolver<D>::debRAC(LbmFloat* s,int l) { + if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } + if(l>dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } + //if(l>D::cDfNum){ // dFfrac is an exception + //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } + return _RAC(s,l); +}; + +#endif // FSGR_STRICT_DEBUG==1 + + + +#if LBM_USE_GUI==1 +#define USE_GLUTILITIES +#include "../gui/gui_utilities.h" + +//! display a single node +template<class D> +void LbmFsgrSolver<D>::debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ) { + //debugOut(" DD: "<<cell->getAsString() , 10); + ntlVec3Gfx org = this->getCellOrigin( cell ); + ntlVec3Gfx halfsize = this->getCellSize( cell ); + int set = this->getCellSet( cell ); + //debugOut(" DD: "<<cell->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<class D> +void LbmFsgrSolver<D>::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<class D> +void LbmFsgrSolver<D>::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<class D> +void LbmFsgrSolver<D>::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; i<printInfo.length()-0; i++) { + char what = printInfo[i]; + switch(what) { + case '+': // all on + printDF = true; printRho = true; printVel = true; printFlag = true; printGeom = true; printMass = true ; + printBothSets = true; break; + case '-': // all off + printDF = false; printRho = false; printVel = false; printFlag = false; printGeom = false; printMass = false; + printBothSets = false; break; + case 'd': printDF = true; break; + case 'r': printRho = true; break; + case 'v': printVel = true; break; + case 'f': printFlag = true; break; + case 'g': printGeom = true; break; + case 'm': printMass = true; break; + case 's': printBothSets = true; break; + default: + errFatal("debugPrintNodeInfo","Invalid node info id "<<what,SIMWORLD_GENERICERROR); return; + } + } + + ntlVec3Gfx org = this->getCellOrigin( cell ); + ntlVec3Gfx halfsize = this->getCellSize( cell ); + int set = this->getCellSet( cell ); + debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<<printInfo<<"' for node: "<<cell->getAsString()<<" from "<<this->getName()<<" currSet:"<<set , 1); + if(printGeom) debMsgStd(" ",DM_MSG, "Org:"<<org<<" Halfsize:"<<halfsize<<" ", 1); + + int setmax = 2; + if(!printBothSets) setmax = 1; + if(forceSet>=0) setmax = 1; + + for(int s=0; s<setmax; s++) { + int workset = set; + if(s==1){ workset = (set^1); } + if(forceSet>=0) workset = forceSet; + debMsgStd(" ",DM_MSG, "Printing set:"<<workset<<" orgSet:"<<set, 1); + + if(printDF) { + for(int l=0; l<this->getDfNum(); l++) { // FIXME ?? + debMsgStd(" ",DM_MSG, " Df"<<l<<": "<<this->getCellDf(cell,workset,l), 1); + } + } + if(printRho) { + debMsgStd(" ",DM_MSG, " Rho: "<<this->getCellDensity(cell,workset), 1); + } + if(printVel) { + debMsgStd(" ",DM_MSG, " Vel: "<<this->getCellVelocity(cell,workset), 1); + } + if(printFlag) { + CellFlagType flag = this->getCellFlag(cell,workset); + debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<<convertFlags2String( flag ) <<" "<<convertCellFlagType2String( flag ), 1); + } + if(printMass) { + debMsgStd(" ",DM_MSG, " Mss: "<<this->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 - |