1 /******************************************************************************
3 * El'Beem - the visual lattice boltzmann freesurface simulator
4 * All code distributed as part of El'Beem is covered by the version 2 of the
5 * GNU General Public License. See the file COPYING for details.
6 * Copyright 2003-2006 Nils Thuerey
8 * Combined 2D/3D Lattice Boltzmann standard solver classes
10 *****************************************************************************/
13 #ifndef LBM_SOLVERCLASS_H
14 #define LBM_SOLVERCLASS_H
16 #include "utilities.h"
17 #include "solver_interface.h"
29 // general solver setting defines
31 //! debug coordinate accesses and the like? (much slower)
32 // might be enabled by compilation
33 #ifndef FSGR_STRICT_DEBUG
34 #define FSGR_STRICT_DEBUG 0
35 #endif // FSGR_STRICT_DEBUG
37 //! debug coordinate accesses and the like? (much slower)
38 #define FSGR_OMEGA_DEBUG 0
40 //! OPT3D quick LES on/off, only debug/benchmarking
43 //! order of interpolation (0=always current/1=interpolate/2=always other)
44 //#define TIMEINTORDER 0
45 // TODO remove interpol t param, also interTime
47 // use optimized 3D code?
51 // determine with debugging...
52 # if FSGR_STRICT_DEBUG==1
54 # else // FSGR_STRICT_DEBUG==1
55 // usually switch optimizations for 3d on, when not debugging
59 # endif // FSGR_STRICT_DEBUG==1
62 //! invalid mass value for unused mass data
63 #define MASS_INVALID -1000.0
65 // empty/fill cells without fluid/empty NB's by inserting them into the full/empty lists?
66 #define FSGR_LISTTRICK 1
67 #define FSGR_LISTTTHRESHEMPTY 0.10
68 #define FSGR_LISTTTHRESHFULL 0.90
69 #define FSGR_MAGICNR 0.025
72 //! maxmimum no. of grid levels
73 #define FSGR_MAXNOOFLEVELS 5
75 // enable/disable fine grid compression for finest level
76 // make sure this is same as useGridComp in calculateMemreqEstimate
78 #define COMPRESSGRIDS 1
80 #define COMPRESSGRIDS 0
83 // helper for comparing floats with epsilon
84 #define GFX_FLOATNEQ(x,y) ( ABS((x)-(y)) > (VECTOR_EPSILON) )
85 #define LBM_FLOATNEQ(x,y) ( ABS((x)-(y)) > (10.0*LBM_EPSILON) )
88 // macros for loops over all DFs
89 #define FORDF0 for(int l= 0; l< LBM_DFNUM; ++l)
90 #define FORDF1 for(int l= 1; l< LBM_DFNUM; ++l)
91 // and with different loop var to prevent shadowing
92 #define FORDF0M for(int m= 0; m< LBM_DFNUM; ++m)
93 #define FORDF1M for(int m= 1; m< LBM_DFNUM; ++m)
96 // border for marching cubes
99 #define LBM_INLINED inline
101 // sirdude fix for solaris
102 #if !defined(linux) && defined(sun)
104 #define expf(x) exp((double)(x))
108 #include "solver_control.h"
110 #if LBM_INCLUDE_TESTSOLVERS==1
111 #include "solver_test.h"
112 #endif // LBM_INCLUDE_TESTSOLVERS==1
114 /*****************************************************************************/
115 /*! cell access classes */
116 class UniformFsgrCellIdentifier :
117 public CellIdentifierInterface , public LbmCellContents
120 //! which grid level?
125 //! reset constructor
126 UniformFsgrCellIdentifier() :
127 x(0), y(0), z(0) { };
129 // implement CellIdentifierInterface
130 virtual string getAsString() {
131 std::ostringstream ret;
132 ret <<"{ i"<<x<<",j"<<y;
133 if(LBMDIM>2) ret<<",k"<<z;
138 virtual bool equal(CellIdentifierInterface* other) {
139 UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( other );
140 if(!cid) return false;
141 if( x==cid->x && y==cid->y && z==cid->z && level==cid->level ) return true;
146 //! information needed for each level in the simulation
147 class FsgrLevelData {
149 int id; // level number
151 //! node size on this level (geometric, in world coordinates, not simulation units!)
153 //! node size on this level in simulation units
154 LbmFloat simCellSize;
155 //! quadtree node relaxation parameter
157 //! size this level was advanced to
159 //! size of a single lbm step in time units on this level
163 //! gravity force for this level
166 LbmFloat *mprsCells[2];
167 CellFlagType *mprsFlags[2];
169 //! smago params and precalculated values
171 LbmFloat lcsmago_sqr;
174 // LES statistics per level
178 //! current set of dist funcs
180 //! target/other set of dist funcs
183 //! mass&volume for this level
186 LbmFloat lcellfactor;
188 //! local storage of mSizes
189 int lSizex, lSizey, lSizez;
190 int lOffsx, lOffsy, lOffsz;
196 /*****************************************************************************/
197 /*! class for solving a LBM problem */
198 class LbmFsgrSolver :
199 public LbmSolverInterface // this means, the solver is a lbmData object and implements the lbmInterface
206 virtual ~LbmFsgrSolver();
208 //! initilize variables fom attribute list
209 virtual void parseAttrList();
210 //! Initialize omegas and forces on all levels (for init/timestep change)
211 void initLevelOmegas();
213 // multi step solver init
214 /*! finish the init with config file values (allocate arrays...) */
215 virtual bool initializeSolverMemory();
216 /*! init solver arrays */
217 virtual bool initializeSolverGrids();
218 /*! prepare actual simulation start, setup viz etc */
219 virtual bool initializeSolverPostinit();
221 //! notify object that dump is in progress (e.g. for field dump)
222 virtual void notifySolverOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename);
225 //! show simulation info (implement LbmSolverInterface pure virtual func)
226 virtual void debugDisplay(int set);
229 // implement CellIterator<UniformFsgrCellIdentifier> interface
230 typedef UniformFsgrCellIdentifier stdCellId;
231 virtual CellIdentifierInterface* getFirstCell( );
232 virtual void advanceCell( CellIdentifierInterface* );
233 virtual bool noEndCell( CellIdentifierInterface* );
234 virtual void deleteCellIterator( CellIdentifierInterface** );
235 virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos );
236 virtual int getCellSet ( CellIdentifierInterface* );
237 virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* );
238 virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* );
239 virtual int getCellLevel ( CellIdentifierInterface* );
240 virtual LbmFloat getCellDensity ( CellIdentifierInterface* ,int set);
241 virtual LbmVec getCellVelocity ( CellIdentifierInterface* ,int set);
242 virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir);
243 virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set);
244 virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set);
245 virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set);
246 virtual LbmFloat getEquilDf ( int );
247 virtual ntlVec3Gfx getVelocityAt (float x, float y, float z);
249 stdCellId* convertBaseCidToStdCid( CellIdentifierInterface* basecid);
251 //! perform geometry init (if switched on)
252 bool initGeometryFlags();
253 //! init part for all freesurface testcases
254 void initFreeSurfaces();
255 //! init density gradient if enabled
256 void initStandingFluidGradient();
258 /*! init a given cell with flag, density, mass and equilibrium dist. funcs */
259 LBM_INLINED void initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass);
260 LBM_INLINED void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel);
261 LBM_INLINED void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag);
262 LBM_INLINED void forceChangeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag);
263 LBM_INLINED void initInterfaceVars(int level, int i,int j,int k,int workSet, bool initMass);
264 //! interpolate velocity and density at a given position
265 void interpolateCellValues(int level,int ei,int ej,int ek,int workSet, LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz);
267 /*! perform a single LBM step */
269 //! advance fine grid
271 //! advance coarse grid
272 void coarseAdvance(int lev);
273 //! update flux area values on coarse grids
274 void coarseCalculateFluxareas(int lev);
275 // adaptively coarsen grid
276 bool adaptGrid(int lev);
277 // restrict fine grid DFs to coarse grid
278 void coarseRestrictFromFine(int lev);
280 /* simulation object interface, just calls stepMain */
282 /*! init particle positions */
283 virtual int initParticles();
284 /*! move all particles */
285 virtual void advanceParticles();
286 /*! move a particle at a boundary */
287 void handleObstacleParticle(ParticleObject *p);
288 /*! check whether to add particle
289 bool checkAddParticle();
290 void performAddParticle();*/
293 /*! debug object display (used e.g. for preview surface) */
294 virtual vector<ntlGeometryObject*> getDebugObjects();
296 // gui/output debugging functions
298 virtual void debugDisplayNode(int dispset, CellIdentifierInterface* cell );
299 virtual void lbmDebugDisplay(int dispset);
300 virtual void lbmMarkedCellDisplay();
301 # endif // LBM_USE_GUI==1
302 virtual void debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet=-1);
304 //! for raytracing, preprocess
305 void prepareVisualization( void );
309 //! internal quick print function (for debugging)
310 void printLbmCell(int level, int i, int j, int k,int set);
311 // debugging use CellIterator interface to mark cell
312 void debugMarkCellCall(int level, int vi,int vj,int vk);
314 // loop over grid, stream&collide update
315 void mainLoop(int lev);
316 // change time step size
317 void adaptTimestep();
318 //! init mObjectSpeeds for current parametrization
319 void recalculateObjectSpeeds();
320 //! init moving obstacles for next sim step sim
321 void initMovingObstacles(bool staticInit);
322 //! flag reinit step - always works on finest grid!
323 void reinitFlags( int workSet );
324 //! mass dist weights
325 LbmFloat getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l);
326 //! compute surface normals: fluid, fluid more accurate, and for obstacles
327 void computeFluidSurfaceNormal(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
328 void computeFluidSurfaceNormalAcc(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
329 void computeObstacleSurfaceNormal(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
330 void computeObstacleSurfaceNormalAcc(int i,int j,int k, LbmFloat *snret);
331 //! add point to mListNewInter list
332 LBM_INLINED void addToNewInterList( int ni, int nj, int nk );
333 //! cell is interpolated from coarse level (inited into set, source sets are determined by t)
334 void interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet,bool markNbs);
335 void coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int dstSet);
337 //! minimal and maximal z-coords (for 2D/3D loops)
338 LBM_INLINED int getForZMinBnd();
339 LBM_INLINED int getForZMin1();
340 LBM_INLINED int getForZMaxBnd(int lev);
341 LBM_INLINED int getForZMax1(int lev);
342 LBM_INLINED bool checkDomainBounds(int lev,int i,int j,int k);
343 LBM_INLINED bool checkDomainBoundsPos(int lev,LbmVec pos);
345 // touch grid and flags once
347 // one relaxation step for standing fluid
348 void standingFluidPreinit();
353 //! mass calculated during streaming step
354 LbmFloat mCurrentMass;
355 LbmFloat mCurrentVolume;
356 LbmFloat mInitialMass;
358 //! count problematic cases, that occured so far...
361 // average mlsups, count how many so far...
363 double mAvgMLSUPSCnt;
365 //! Mcubes object for surface reconstruction
366 IsoSurface *mpPreviewSurface;
368 //! use time adaptivity?
370 //! force smaller timestep for next LBM step? (eg for mov obj)
371 bool mForceTimeStepReduce;
376 bool mUpdateFVHeight;
378 //! force quit for gfx
379 LbmFloat mGfxEndTime;
380 //! smoother surface initialization?
381 int mInitSurfaceSmoothing;
382 //! surface generation settings, default is all off (=0)
383 // each flag switches side on off, fssgNoObs is for obstacle sides
395 int mFsSurfGenSetting;
397 //! lock time step down switching
398 int mTimestepReduceLock;
399 //! count no. of switches
400 int mTimeSwitchCounts;
401 // only switch of maxvel is higher for several steps...
402 int mTimeMaxvelStepCnt;
404 //! total simulation time so far
405 LbmFloat mSimulationTime, mLastSimTime;
406 //! smallest and largest step size so far
407 LbmFloat mMinTimestep, mMaxTimestep;
408 //! track max. velocity
409 LbmFloat mMxvx, mMxvy, mMxvz, mMaxVlen;
411 //! list of the cells to empty at the end of the step
412 vector<LbmPoint> mListEmpty;
413 //! list of the cells to make fluid at the end of the step
414 vector<LbmPoint> mListFull;
415 //! list of new interface cells to init
416 vector<LbmPoint> mListNewInter;
417 //! class for handling redist weights in reinit flag function
420 LbmFloat val[dTotalNum];
423 //! normalized vectors for all neighboring cell directions (for e.g. massdweight calc)
428 bool checkSymmetry(string idstring);
429 //! kepp track of max/min no. of filled cells
430 int mMaxNoCells, mMinNoCells;
431 LONGINT mAvgNumUsedCells;
433 //! precalculated objects speeds for current parametrization
434 vector<LbmVec> mObjectSpeeds;
435 //! partslip bc. values for obstacle boundary conditions
436 vector<LbmFloat> mObjectPartslips;
437 //! moving object mass boundary condition values
438 vector<LbmFloat> mObjectMassMovnd;
440 //! permanent movobj vert storage
441 vector<ntlVec3Gfx> mMOIVertices;
442 vector<ntlVec3Gfx> mMOIVerticesOld;
443 vector<ntlVec3Gfx> mMOINormals;
445 //! get isofield weights
446 int mIsoWeightMethod;
447 float mIsoWeight[27];
449 // grid coarsening vars
451 /*! vector for the data for each level */
452 FsgrLevelData mLevel[FSGR_MAXNOOFLEVELS];
454 /*! minimal and maximal refinement levels */
457 /*! df scale factors for level up/down */
458 LbmFloat mDfScaleUp, mDfScaleDown;
460 /*! precomputed cell area values */
461 LbmFloat mFsgrCellArea[27];
462 /*! restriction interpolation weights */
463 LbmFloat mGaussw[27];
465 /*! LES C_smago paramter for finest grid */
466 float mInitialCsmago;
467 /*! LES stats for non OPT3D */
468 LbmFloat mDebugOmegaRet;
469 /*! remember last init for animated params */
479 //! debug function to disable standing f init
480 int mDisableStandingFluidInit;
481 //! init 2d with skipped Y/Z coords
483 //! debug function to force tadap syncing
484 int mForceTadapRefine;
485 //! border cutoff value
488 // strict debug interface
489 # if FSGR_STRICT_DEBUG==1
490 int debLBMGI(int level, int ii,int ij,int ik, int is);
491 CellFlagType& debRFLAG(int level, int xx,int yy,int zz,int set);
492 CellFlagType& debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir);
493 CellFlagType& debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir);
494 int debLBMQI(int level, int ii,int ij,int ik, int is, int l);
495 LbmFloat& debQCELL(int level, int xx,int yy,int zz,int set,int l);
496 LbmFloat& debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l);
497 LbmFloat& debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l);
498 LbmFloat* debRACPNT(int level, int ii,int ij,int ik, int is );
499 LbmFloat& debRAC(LbmFloat* s,int l);
500 # endif // FSGR_STRICT_DEBUG==1
502 LbmControlData *mpControl;
506 void cpDebugDisplay(int dispset);
509 # if LBM_INCLUDE_TESTSOLVERS==1
513 void destroyTestdata();
514 void handleTestdata();
515 void set3dHeight(int ,int );
523 void mrIsoExchange();
524 LbmFloat mrInitTadap(LbmFloat max);
525 void gcFillBuffer( LbmGridConnector *gc, int *retSizeCnt, const int *bdfs);
526 void gcUnpackBuffer(LbmGridConnector *gc, int *retSizeCnt, const int *bdfs);
528 // needed for testdata
529 void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat *retux, LbmFloat *retuy, LbmFloat *retuz);
531 int getMpIndex() { return mMpIndex; };
532 # endif // LBM_INCLUDE_TESTSOLVERS==1
534 // former LbmModelLBGK functions
535 // relaxation funtions - implemented together with relax macros
536 static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz);
537 static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz);
538 inline LbmFloat getLesNoneqTensorCoeff( LbmFloat df[], LbmFloat feq[] );
539 inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo);
540 inline void collideArrays( int lev, int i, int j, int k, // position - more for debugging
541 LbmFloat df[], LbmFloat &outrho, // out only!
542 // velocity modifiers (returns actual velocity!)
543 LbmFloat &mux, LbmFloat &muy, LbmFloat &muz,
544 LbmFloat omega, LbmVec gravity, LbmFloat csmago,
545 LbmFloat *newOmegaRet, LbmFloat *newQoRet);
549 //! shorten static const definitions
550 # define STCON static const
554 //! id string of solver
555 virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D3Q19]"); }
557 //! how many dimensions? UNUSED? replace by LBMDIM?
558 STCON int cDimension;
560 // Wi factors for collide step
561 STCON LbmFloat cCollenZero;
562 STCON LbmFloat cCollenOne;
563 STCON LbmFloat cCollenSqrtTwo;
565 //! threshold value for filled/emptied cells
566 STCON LbmFloat cMagicNr2;
567 STCON LbmFloat cMagicNr2Neg;
568 STCON LbmFloat cMagicNr;
569 STCON LbmFloat cMagicNrNeg;
571 //! size of a single set of distribution functions
573 //! direction vector contain vecs for all spatial dirs, even if not used for LBM model
576 //! distribution functions directions
601 * 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
602 * 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
603 * 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
604 * 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
607 /*! name of the dist. function
608 only for nicer output */
609 STCON char* dfString[ 19 ];
611 /*! index of normal dist func, not used so far?... */
612 STCON int dfNorm[ 19 ];
614 /*! index of inverse dist func, not fast, but useful... */
615 STCON int dfInv[ 19 ];
617 /*! index of x reflected dist func for free slip, not valid for all DFs... */
618 STCON int dfRefX[ 19 ];
619 /*! index of x reflected dist func for free slip, not valid for all DFs... */
620 STCON int dfRefY[ 19 ];
621 /*! index of x reflected dist func for free slip, not valid for all DFs... */
622 STCON int dfRefZ[ 19 ];
624 /*! dist func vectors */
625 STCON int dfVecX[ 27 ];
626 STCON int dfVecY[ 27 ];
627 STCON int dfVecZ[ 27 ];
629 /*! arrays as before with doubles */
630 STCON LbmFloat dfDvecX[ 27 ];
631 STCON LbmFloat dfDvecY[ 27 ];
632 STCON LbmFloat dfDvecZ[ 27 ];
634 /*! principal directions */
635 STCON int princDirX[ 2*3 ];
636 STCON int princDirY[ 2*3 ];
637 STCON int princDirZ[ 2*3 ];
639 /*! vector lengths */
640 STCON LbmFloat dfLength[ 19 ];
642 /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
643 static LbmFloat dfEquil[ dTotalNum ];
645 /*! arrays for les model coefficients */
646 static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ];
647 static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ];
649 # else // end LBMDIM==3 , LBMDIM==2
651 //! id string of solver
652 virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D2Q9]"); }
654 //! how many dimensions?
655 STCON int cDimension;
657 //! Wi factors for collide step
658 STCON LbmFloat cCollenZero;
659 STCON LbmFloat cCollenOne;
660 STCON LbmFloat cCollenSqrtTwo;
662 //! threshold value for filled/emptied cells
663 STCON LbmFloat cMagicNr2;
664 STCON LbmFloat cMagicNr2Neg;
665 STCON LbmFloat cMagicNr;
666 STCON LbmFloat cMagicNrNeg;
668 //! size of a single set of distribution functions
672 //! distribution functions directions
688 * 0, 0,0, 1,-1, 1,-1,1,-1
689 * 0, 1,-1, 0,0, 1,1,-1,-1 */
691 /* name of the dist. function
692 only for nicer output */
693 STCON char* dfString[ 9 ];
695 /* index of normal dist func, not used so far?... */
696 STCON int dfNorm[ 9 ];
698 /* index of inverse dist func, not fast, but useful... */
699 STCON int dfInv[ 9 ];
701 /* index of x reflected dist func for free slip, not valid for all DFs... */
702 STCON int dfRefX[ 9 ];
703 /* index of x reflected dist func for free slip, not valid for all DFs... */
704 STCON int dfRefY[ 9 ];
705 /* index of x reflected dist func for free slip, not valid for all DFs... */
706 STCON int dfRefZ[ 9 ];
708 /* dist func vectors */
709 STCON int dfVecX[ 9 ];
710 STCON int dfVecY[ 9 ];
711 /* Z, 2D values are all 0! */
712 STCON int dfVecZ[ 9 ];
714 /* arrays as before with doubles */
715 STCON LbmFloat dfDvecX[ 9 ];
716 STCON LbmFloat dfDvecY[ 9 ];
717 /* Z, 2D values are all 0! */
718 STCON LbmFloat dfDvecZ[ 9 ];
720 /*! principal directions */
721 STCON int princDirX[ 2*2 ];
722 STCON int princDirY[ 2*2 ];
723 STCON int princDirZ[ 2*2 ];
726 STCON LbmFloat dfLength[ 9 ];
728 /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
729 static LbmFloat dfEquil[ dTotalNum ];
731 /*! arrays for les model coefficients */
732 static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ];
733 static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ];
741 /*****************************************************************************/
746 // cell mark debugging
747 #if FSGR_STRICT_DEBUG==10
748 #define debugMarkCell(lev,x,y,z) \
749 errMsg("debugMarkCell",this->mName<<" step: "<<this->mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \
750 debugMarkCellCall((lev),(x),(y),(z));
751 #else // FSGR_STRICT_DEBUG==1
752 #define debugMarkCell(lev,x,y,z) \
753 debugMarkCellCall((lev),(x),(y),(z));
754 #endif // FSGR_STRICT_DEBUG==1
757 // flag array defines -----------------------------------------------------------------------------------------------
759 // lbm testsolver get index define, note - ignores is (set) as flag
760 // array is only a single entry
761 #define _LBMGI(level, ii,ij,ik, is) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) )
763 //! flag array acces macro
764 #define _RFLAG(level,xx,yy,zz,set) mLevel[level].mprsFlags[set][ LBMGI((level),(xx),(yy),(zz),(set)) ]
765 #define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set) ]
766 #define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set) ]
768 // array handling -----------------------------------------------------------------------------------------------
770 #define _LBMQI(level, ii,ij,ik, is, lunused) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) )
771 #define _QCELL(level,xx,yy,zz,set,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx),(yy),(zz),(set), l)*dTotalNum +(l)])
772 #define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set, l)*dTotalNum +(l)])
773 #define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set, l)*dTotalNum +(l)])
775 #define QCELLSTEP dTotalNum
776 #define _RACPNT(level, ii,ij,ik, is ) &QCELL(level,ii,ij,ik,is,0)
777 #define _RAC(s,l) (s)[(l)]
780 #if FSGR_STRICT_DEBUG==1
782 #define LBMGI(level,ii,ij,ik, is) debLBMGI(level,ii,ij,ik, is)
783 #define RFLAG(level,xx,yy,zz,set) debRFLAG(level,xx,yy,zz,set)
784 #define RFLAG_NB(level,xx,yy,zz,set, dir) debRFLAG_NB(level,xx,yy,zz,set, dir)
785 #define RFLAG_NBINV(level,xx,yy,zz,set, dir) debRFLAG_NBINV(level,xx,yy,zz,set, dir)
787 #define LBMQI(level,ii,ij,ik, is, l) debLBMQI(level,ii,ij,ik, is, l)
788 #define QCELL(level,xx,yy,zz,set,l) debQCELL(level,xx,yy,zz,set,l)
789 #define QCELL_NB(level,xx,yy,zz,set, dir,l) debQCELL_NB(level,xx,yy,zz,set, dir,l)
790 #define QCELL_NBINV(level,xx,yy,zz,set, dir,l) debQCELL_NBINV(level,xx,yy,zz,set, dir,l)
791 #define RACPNT(level, ii,ij,ik, is ) debRACPNT(level, ii,ij,ik, is )
792 #define RAC(s,l) debRAC(s,l)
794 #else // FSGR_STRICT_DEBUG==1
796 #define LBMGI(level,ii,ij,ik, is) _LBMGI(level,ii,ij,ik, is)
797 #define RFLAG(level,xx,yy,zz,set) _RFLAG(level,xx,yy,zz,set)
798 #define RFLAG_NB(level,xx,yy,zz,set, dir) _RFLAG_NB(level,xx,yy,zz,set, dir)
799 #define RFLAG_NBINV(level,xx,yy,zz,set, dir) _RFLAG_NBINV(level,xx,yy,zz,set, dir)
801 #define LBMQI(level,ii,ij,ik, is, l) _LBMQI(level,ii,ij,ik, is, l)
802 #define QCELL(level,xx,yy,zz,set,l) _QCELL(level,xx,yy,zz,set,l)
803 #define QCELL_NB(level,xx,yy,zz,set, dir,l) _QCELL_NB(level,xx,yy,zz,set, dir, l)
804 #define QCELL_NBINV(level,xx,yy,zz,set, dir,l) _QCELL_NBINV(level,xx,yy,zz,set, dir,l)
805 #define RACPNT(level, ii,ij,ik, is ) _RACPNT(level, ii,ij,ik, is )
806 #define RAC(s,l) _RAC(s,l)
808 #endif // FSGR_STRICT_DEBUG==1
810 // general defines -----------------------------------------------------------------------------------------------
813 #define FLAGISEXACT(flag, compflag) ((flag & compflag)==compflag)
849 // default init for dFlux values
850 #define FLUX_INIT 0.5f * (float)(this->cDfNum)
852 // only for non DF dir handling!
862 //! fill value for boundary cells
865 #define DFL1 (1.0/ 3.0)
866 #define DFL2 (1.0/18.0)
867 #define DFL3 (1.0/36.0)
869 // loops over _all_ cells (including boundary layer)
870 #define FSGR_FORIJK_BOUNDS(leveli) \
871 for(int k= getForZMinBnd(); k< getForZMaxBnd(leveli); ++k) \
872 for(int j=0;j<mLevel[leveli].lSizey-0;++j) \
873 for(int i=0;i<mLevel[leveli].lSizex-0;++i) \
875 // loops over _only inner_ cells
876 #define FSGR_FORIJK1(leveli) \
877 for(int k= getForZMin1(); k< getForZMax1(leveli); ++k) \
878 for(int j=1;j<mLevel[leveli].lSizey-1;++j) \
879 for(int i=1;i<mLevel[leveli].lSizex-1;++i) \
881 // relaxation_macros end
885 /******************************************************************************/
886 /*! equilibrium functions */
887 /******************************************************************************/
889 /*! calculate length of velocity vector */
890 inline LbmFloat LbmFsgrSolver::getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) {
891 return ((ux)*dfDvecX[l]+(uy)*dfDvecY[l]+(uz)*dfDvecZ[l]);
894 /*! calculate equilibrium DF for given values */
895 inline LbmFloat LbmFsgrSolver::getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) {
896 #if FSGR_STRICT_DEBUG==1
897 if((l<0)||(l>LBM_DFNUM)) { errFatal("LbmFsgrSolver::getCollideEq","Invalid DFEQ call "<<l, SIMWORLD_PANIC ); /* no access to mPanic here */ }
898 #endif // FSGR_STRICT_DEBUG==1
899 LbmFloat tmp = getVelVecLen(l,ux,uy,uz);
900 return( dfLength[l] *(
901 + rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz))
903 + 9.0/2.0 *(tmp*tmp) )
907 /*****************************************************************************/
908 /* init a given cell with flag, density, mass and equilibrium dist. funcs */
910 void LbmFsgrSolver::forceChangeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) {
911 // also overwrite persisting flags
912 // function is useful for tracking accesses...
913 RFLAG(level,xx,yy,zz,set) = newflag;
915 void LbmFsgrSolver::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) {
916 CellFlagType pers = RFLAG(level,xx,yy,zz,set) & CFPersistMask;
917 RFLAG(level,xx,yy,zz,set) = newflag | pers;
921 LbmFsgrSolver::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) {
922 /* init eq. dist funcs */
924 int workSet = mLevel[level].setCurr;
926 ecel = RACPNT(level, i,j,k, workSet);
927 FORDF0 { RAC(ecel, l) = this->dfEquil[l] * rho; }
928 RAC(ecel, dMass) = mass;
929 RAC(ecel, dFfrac) = mass/rho;
930 RAC(ecel, dFlux) = FLUX_INIT;
931 changeFlag(level, i,j,k, workSet, flag);
934 changeFlag(level, i,j,k, workSet, flag);
939 LbmFsgrSolver::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) {
941 int workSet = mLevel[level].setCurr;
943 ecel = RACPNT(level, i,j,k, workSet);
944 FORDF0 { RAC(ecel, l) = getCollideEq(l, rho,vel[0],vel[1],vel[2]); }
945 RAC(ecel, dMass) = mass;
946 RAC(ecel, dFfrac) = mass/rho;
947 RAC(ecel, dFlux) = FLUX_INIT;
948 changeFlag(level, i,j,k, workSet, flag);
951 changeFlag(level, i,j,k, workSet, flag);
955 int LbmFsgrSolver::getForZMinBnd() {
958 int LbmFsgrSolver::getForZMin1() {
959 if(LBMDIM==2) return 0;
963 int LbmFsgrSolver::getForZMaxBnd(int lev) {
964 if(LBMDIM==2) return 1;
965 return mLevel[lev].lSizez -0;
967 int LbmFsgrSolver::getForZMax1(int lev) {
968 if(LBMDIM==2) return 1;
969 return mLevel[lev].lSizez -1;
972 bool LbmFsgrSolver::checkDomainBounds(int lev,int i,int j,int k) {
973 if(i<0) return false;
974 if(j<0) return false;
975 if(k<0) return false;
976 if(i>mLevel[lev].lSizex-1) return false;
977 if(j>mLevel[lev].lSizey-1) return false;
978 if(k>mLevel[lev].lSizez-1) return false;
981 bool LbmFsgrSolver::checkDomainBoundsPos(int lev,LbmVec pos) {
982 const int i= (int)pos[0];
983 if(i<0) return false;
984 if(i>mLevel[lev].lSizex-1) return false;
985 const int j= (int)pos[1];
986 if(j<0) return false;
987 if(j>mLevel[lev].lSizey-1) return false;
988 const int k= (int)pos[2];
989 if(k<0) return false;
990 if(k>mLevel[lev].lSizez-1) return false;
994 void LbmFsgrSolver::initInterfaceVars(int level, int i,int j,int k,int workSet, bool initMass) {
995 LbmFloat *ccel = &QCELL(level ,i,j,k, workSet,0);
997 FORDF0 { nrho += RAC(ccel,l); }
999 RAC(ccel,dMass) = nrho;
1000 RAC(ccel, dFfrac) = 1.;
1002 // preinited, e.g. from reinitFlags
1003 RAC(ccel, dFfrac) = RAC(ccel, dMass)/nrho;
1004 RAC(ccel, dFlux) = FLUX_INIT;