1 /******************************************************************************
3 * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
4 * Copyright 2003-2006 Nils Thuerey
6 * Standard LBM Factory implementation
8 *****************************************************************************/
11 #include "solver_class.h"
12 #include "solver_relax.h"
13 // for geo init FGI_ defines
17 #define SWAPYZ(vec) { \
18 const LbmFloat tmp = (vec)[2]; \
19 (vec)[2] = (vec)[1]; (vec)[1] = tmp; }
22 /*****************************************************************************/
25 /*****************************************************************************/
26 /*! 3D implementation D3Q19 */
29 //! how many dimensions?
30 const int LbmFsgrSolver::cDimension = 3;
32 // Wi factors for collide step
33 const LbmFloat LbmFsgrSolver::cCollenZero = (1.0/3.0);
34 const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/18.0);
35 const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0);
37 //! threshold value for filled/emptied cells
38 const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005;
39 const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005;
40 const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001;
41 const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001;
43 //! size of a single set of distribution functions
44 const int LbmFsgrSolver::cDfNum = 19;
45 //! direction vector contain vecs for all spatial dirs, even if not used for LBM model
46 const int LbmFsgrSolver::cDirNum = 27;
48 //const string LbmFsgrSolver::dfString[ cDfNum ] = {
49 const char* LbmFsgrSolver::dfString[ cDfNum ] = {
50 " C", " N"," S"," E"," W"," T"," B",
56 const int LbmFsgrSolver::dfNorm[ cDfNum ] = {
57 cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB,
58 cDirNE, cDirNW, cDirSE, cDirSW,
59 cDirNT, cDirNB, cDirST, cDirSB,
60 cDirET, cDirEB, cDirWT, cDirWB
63 const int LbmFsgrSolver::dfInv[ cDfNum ] = {
64 cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT,
65 cDirSW, cDirSE, cDirNW, cDirNE,
66 cDirSB, cDirST, cDirNB, cDirNT,
67 cDirWB, cDirWT, cDirEB, cDirET
70 const int LbmFsgrSolver::dfRefX[ cDfNum ] = {
72 cDirSE, cDirSW, cDirNE, cDirNW,
74 cDirEB, cDirET, cDirWB, cDirWT
77 const int LbmFsgrSolver::dfRefY[ cDfNum ] = {
79 cDirNW, cDirNE, cDirSW, cDirSE,
80 cDirNB, cDirNT, cDirSB, cDirST,
84 const int LbmFsgrSolver::dfRefZ[ cDfNum ] = {
87 cDirST, cDirSB, cDirNT, cDirNB,
88 cDirWT, cDirWB, cDirET, cDirEB
92 // 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
93 // 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
94 // 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
95 // 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
97 const int LbmFsgrSolver::dfVecX[ cDirNum ] = {
105 const int LbmFsgrSolver::dfVecY[ cDirNum ] = {
113 const int LbmFsgrSolver::dfVecZ[ cDirNum ] = {
122 const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = {
130 const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = {
138 const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = {
147 /* principal directions */
148 const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = {
151 const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = {
154 const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = {
158 /*! arrays for les model coefficients, inited in lbmsolver constructor */
159 LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
160 LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ];
163 const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= {
165 cCollenOne, cCollenOne, cCollenOne,
166 cCollenOne, cCollenOne, cCollenOne,
167 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
168 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
169 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
172 /* precalculated equilibrium dfs, inited in lbmsolver constructor */
173 LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ];
175 #else // end LBMDIM==3 , LBMDIM==2
177 /*****************************************************************************/
178 /*! 2D implementation D2Q9 */
180 //! how many dimensions?
181 const int LbmFsgrSolver::cDimension = 2;
183 //! Wi factors for collide step
184 const LbmFloat LbmFsgrSolver::cCollenZero = (4.0/9.0);
185 const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/9.0);
186 const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0);
188 //! threshold value for filled/emptied cells
189 const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005;
190 const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005;
191 const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001;
192 const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001;
194 //! size of a single set of distribution functions
195 const int LbmFsgrSolver::cDfNum = 9;
196 const int LbmFsgrSolver::cDirNum = 9;
198 //const string LbmFsgrSolver::dfString[ cDfNum ] = {
199 const char* LbmFsgrSolver::dfString[ cDfNum ] = {
201 " N", " S", " E", " W",
202 "NE", "NW", "SE","SW"
205 const int LbmFsgrSolver::dfNorm[ cDfNum ] = {
207 cDirN, cDirS, cDirE, cDirW,
208 cDirNE, cDirNW, cDirSE, cDirSW
211 const int LbmFsgrSolver::dfInv[ cDfNum ] = {
213 cDirS, cDirN, cDirW, cDirE,
214 cDirSW, cDirSE, cDirNW, cDirNE
217 const int LbmFsgrSolver::dfRefX[ cDfNum ] = {
220 cDirSE, cDirSW, cDirNE, cDirNW
223 const int LbmFsgrSolver::dfRefY[ cDfNum ] = {
226 cDirNW, cDirNE, cDirSW, cDirSE
229 const int LbmFsgrSolver::dfRefZ[ cDfNum ] = {
236 // 0, 0,0, 1,-1, 1,-1,1,-1
237 // 0, 1,-1, 0,0, 1,1,-1,-1
239 const int LbmFsgrSolver::dfVecX[ cDirNum ] = {
244 const int LbmFsgrSolver::dfVecY[ cDirNum ] = {
249 const int LbmFsgrSolver::dfVecZ[ cDirNum ] = {
253 const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = {
258 const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = {
263 const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = {
267 const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = {
270 const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = {
273 const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = {
278 /*! arrays for les model coefficients, inited in lbmsolver constructor */
279 LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
280 LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ];
283 const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= {
285 cCollenOne, cCollenOne, cCollenOne, cCollenOne,
286 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
289 /* precalculated equilibrium dfs, inited in lbmsolver constructor */
290 LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ];
297 extern bool glob_mpactive;
298 extern int glob_mpnum, glob_mpindex;
301 /******************************************************************************
303 *****************************************************************************/
304 LbmFsgrSolver::LbmFsgrSolver() :
306 mCurrentMass(0.0), mCurrentVolume(0.0),
308 mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0),
309 mpPreviewSurface(NULL),
310 mTimeAdap(true), mForceTimeStepReduce(false),
311 mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false),
312 mInitSurfaceSmoothing(0), mFsSurfGenSetting(0),
313 mTimestepReduceLock(0),
314 mTimeSwitchCounts(0), mTimeMaxvelStepCnt(0),
315 mSimulationTime(0.0), mLastSimTime(0.0),
316 mMinTimestep(0.0), mMaxTimestep(0.0),
317 mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0),
318 mObjectSpeeds(), mObjectPartslips(), mObjectMassMovnd(),
319 mMOIVertices(), mMOIVerticesOld(), mMOINormals(),
322 mDfScaleUp(-1.0), mDfScaleDown(-1.0),
323 mInitialCsmago(0.02), // set to 0.02 for mMaxRefine==0 below and default for fine level, coarser ones are 0.03
325 mLastOmega(1e10), mLastGravity(1e10),
326 mNumInvIfTotal(0), mNumFsgrChanges(0),
327 mDisableStandingFluidInit(0),
329 mForceTadapRefine(-1), mCutoff(-1)
331 #if LBM_INCLUDE_CONTROL==1
332 mpControl = new LbmControlData();
335 #if LBM_INCLUDE_TESTSOLVERS==1
336 mpTest = new LbmTestdata();
337 mMpNum = mMpIndex = 0;
341 #endif // LBM_INCLUDE_TESTSOLVERS!=1
342 mpIso = new IsoSurface( mIsoValue );
344 // init equilibrium dist. func
347 dfEquil[l] = this->getCollideEq( l,rho, 0.0, 0.0, 0.0);
350 dfEquil[dFfrac] = 1.;
351 dfEquil[dFlux] = FLUX_INIT;
355 for(int m=0; m<LBMDIM; m++) {
356 for(int l=0; l<cDfNum; l++) {
357 this->lesCoeffDiag[m][l] =
358 this->lesCoeffOffdiag[m][l] = 0.0;
361 for(int m=0; m<LBMDIM; m++) {
362 for(int n=0; n<LBMDIM; n++) {
363 for(int l=1; l<cDfNum; l++) {
366 case 0: em = dfDvecX[l]; break;
367 case 1: em = dfDvecY[l]; break;
368 case 2: em = dfDvecZ[l]; break;
369 default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR);
373 case 0: en = dfDvecX[l]; break;
374 case 1: en = dfDvecY[l]; break;
375 case 2: en = dfDvecZ[l]; break;
376 default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR);
378 const LbmFloat coeff = em*en;
380 this->lesCoeffDiag[m][l] = coeff;
383 this->lesCoeffOffdiag[odm][l] = coeff;
395 mDvecNrm[0] = LbmVec(0.0);
397 mDvecNrm[l] = getNormalized(
398 LbmVec(dfDvecX[dfInv[l]], dfDvecY[dfInv[l]], dfDvecZ[dfInv[l]] )
402 // calculate gauss weights for restriction
403 //LbmFloat mGaussw[27];
404 LbmFloat totGaussw = 0.0;
405 const LbmFloat alpha = 1.0;
406 const LbmFloat gw = sqrt(2.0*LBMDIM);
408 errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!");
410 for(int n=0;(n<cDirNum); n++) { mGaussw[n] = 0.0; }
411 //for(int n=0;(n<cDirNum); n++) {
412 for(int n=0;(n<cDfNum); n++) {
413 const LbmFloat d = norm(LbmVec(dfVecX[n], dfVecY[n], dfVecZ[n]));
414 LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw );
418 for(int n=0;(n<cDirNum); n++) {
419 mGaussw[n] = mGaussw[n]/totGaussw;
424 /*****************************************************************************/
426 /*****************************************************************************/
427 LbmFsgrSolver::~LbmFsgrSolver()
429 if(!mInitDone){ debMsgStd("LbmFsgrSolver::LbmFsgrSolver",DM_MSG,"not inited...",0); return; }
431 delete [] mLevel[mMaxRefine].mprsCells[1];
432 mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL;
433 #endif // COMPRESSGRIDS==1
435 for(int i=0; i<=mMaxRefine; i++) {
436 for(int s=0; s<2; s++) {
437 if(mLevel[i].mprsCells[s]) delete [] mLevel[i].mprsCells[s];
438 if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s];
442 if(mpPreviewSurface) delete mpPreviewSurface;
443 // cleanup done during scene deletion...
445 #if LBM_INCLUDE_CONTROL==1
446 if(mpControl) delete mpControl;
449 // always output performance estimate
450 debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5);
451 if(!mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10);
457 /******************************************************************************
458 * initilize variables fom attribute list
459 *****************************************************************************/
460 void LbmFsgrSolver::parseAttrList()
462 LbmSolverInterface::parseStdAttrList();
464 string matIso("default");
465 matIso = mpSifAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false );
466 mpIso->setMaterialName( matIso );
467 mOutputSurfacePreview = mpSifAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false );
468 mTimeAdap = mpSifAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false );
469 mDomainBound = mpSifAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false );
470 mDomainPartSlipValue = mpSifAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false );
472 mIsoWeightMethod= mpSifAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false );
473 mInitSurfaceSmoothing = mpSifAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false );
474 mSmoothSurface = mpSifAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false );
475 mSmoothNormals = mpSifAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false );
476 mFsSurfGenSetting = mpSifAttrs->readInt("fssurfgen", mFsSurfGenSetting, "SimulationLbm","mFsSurfGenSetting", false );
479 mMaxRefine = mRefinementDesired;
480 mMaxRefine = mpSifAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false);
481 if(mMaxRefine<0) mMaxRefine=0;
482 if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1;
483 mDisableStandingFluidInit = mpSifAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false);
484 mInit2dYZ = mpSifAttrs->readBool("init2dyz", mInit2dYZ,"LbmFsgrSolver", "mInit2dYZ", false);
485 mForceTadapRefine = mpSifAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false);
487 // demo mode settings
488 mFVHeight = mpSifAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false );
489 // FIXME check needed?
490 mFVArea = mpSifAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false );
492 // debugging - skip some time...
493 double starttimeskip = 0.;
494 starttimeskip = mpSifAttrs->readFloat("forcestarttimeskip", starttimeskip, "LbmFsgrSolver","starttimeskip", false );
495 mSimulationTime += starttimeskip;
496 if(starttimeskip>0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<<starttimeskip<<", t="<<mSimulationTime, 1);
498 #if LBM_INCLUDE_CONTROL==1
499 mpControl->parseControldataAttrList(mpSifAttrs);
502 #if LBM_INCLUDE_TESTSOLVERS==1
504 mUseTestdata = mpSifAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false);
505 mpTest->parseTestdataAttrList(mpSifAttrs);
507 mUseTestdata=1; // DEBUG
508 #endif // ELBEEM_PLUGIN
510 mMpNum = mpSifAttrs->readInt("mpnum", mMpNum ,"LbmFsgrSolver", "mMpNum", false);
511 mMpIndex = mpSifAttrs->readInt("mpindex", mMpIndex ,"LbmFsgrSolver", "mMpIndex", false);
515 mMpIndex = glob_mpindex;
520 errMsg("LbmFsgrSolver::parseAttrList"," mpactive:"<<glob_mpactive<<", "<<glob_mpindex<<"/"<<glob_mpnum);
522 mUseTestdata=1; // needed in this case...
525 errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" ");
526 #else // LBM_INCLUDE_TESTSOLVERS!=1
527 // not testsolvers, off by default
529 if(mFarFieldSize>=2.) mUseTestdata=1; // equiv. to test solver check
530 #endif // LBM_INCLUDE_TESTSOLVERS!=1
532 mInitialCsmago = mpSifAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false );
534 float mInitialCsmagoCoarse = 0.0;
535 mInitialCsmagoCoarse = mpSifAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false );
538 debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2);
539 mInitialCsmago = 0.0;
544 /******************************************************************************
545 * Initialize omegas and forces on all levels (for init/timestep change)
546 *****************************************************************************/
547 void LbmFsgrSolver::initLevelOmegas()
549 // no explicit settings
550 mOmega = mpParam->calculateOmega(mSimulationTime);
551 mGravity = vec2L( mpParam->calculateGravity(mSimulationTime) );
552 mSurfaceTension = 0.; //mpParam->calculateSurfaceTension(); // unused
553 if(mInit2dYZ) { SWAPYZ(mGravity); }
555 // check if last init was ok
556 LbmFloat gravDelta = norm(mGravity-mLastGravity);
557 //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<mOmega<<" - lom:"<<mLastOmega<<" gv:"<<mGravity<<" - "<<mLastGravity<<" , "<<gravDelta );
558 if((mOmega == mLastOmega) && (gravDelta<=0.0)) return;
560 if(mInitialCsmago<=0.0) {
562 errFatal("LbmFsgrSolver::initLevelOmegas","Csmago-LES = 0 not supported for optimized 3D version...",SIMWORLD_INITERROR);
567 LbmFloat fineCsmago = mInitialCsmago;
568 LbmFloat coarseCsmago = mInitialCsmago;
569 LbmFloat maxFineCsmago1 = 0.026;
570 LbmFloat maxCoarseCsmago1 = 0.029; // try stabilizing
571 LbmFloat maxFineCsmago2 = 0.028;
572 LbmFloat maxCoarseCsmago2 = 0.032; // try stabilizing some more
573 if((mMaxRefine==1)&&(mInitialCsmago<maxFineCsmago1)) {
574 fineCsmago = maxFineCsmago1;
575 coarseCsmago = maxCoarseCsmago1;
577 if((mMaxRefine>1)&&(mInitialCsmago<maxFineCsmago2)) {
578 fineCsmago = maxFineCsmago2;
579 coarseCsmago = maxCoarseCsmago2;
583 // use Tau instead of Omega for calculations
586 mLevel[i].omega = mOmega;
587 mLevel[i].timestep = mpParam->getTimestep();
588 mLevel[i].lcsmago = fineCsmago; //CSMAGO_INITIAL;
589 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
590 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
593 // init all sub levels
594 for(int i=mMaxRefine-1; i>=0; i--) {
595 //mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5;
596 double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5;
598 mLevel[i].omega = (LbmFloat)nomega;
599 mLevel[i].timestep = 2.0 * mLevel[i+1].timestep;
600 mLevel[i].lcsmago = coarseCsmago;
601 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
602 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
606 mLevel[ mMaxRefine ].gravity = mGravity / mLevel[ mMaxRefine ].omega;
607 for(int i=mMaxRefine-1; i>=0; i--) {
608 // should be the same on all levels...
610 mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega;
614 mLastGravity = mGravity;
615 // debug? invalidate old values...
619 for(int i=0; i<=mMaxRefine; i++) {
621 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
622 <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", "
623 <<" cmsagp:"<<mLevel[i].lcsmago<<", "
624 << " ss"<<mLevel[i].timestep<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize );
627 debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" "
628 <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5);
633 mDfScaleUp = (mLevel[0 ].timestep/mLevel[0+1].timestep)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu
634 mDfScaleDown = (mLevel[0+1].timestep/mLevel[0 ].timestep)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu
639 /******************************************************************************
640 * Init Solver (values should be read from config file)
641 *****************************************************************************/
643 /*! finish the init with config file values (allocate arrays...) */
644 bool LbmFsgrSolver::initializeSolverMemory()
646 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<mInitDone<<" "<<(void*)this,1);
650 mSizex *= mCppfStage;
651 mSizey *= mCppfStage;
652 mSizez *= mCppfStage;
654 if(mFsSurfGenSetting==-1) {
657 fssgNormal | fssgNoNorth | fssgNoSouth | fssgNoEast |
658 fssgNoWest | fssgNoTop | fssgNoBottom | fssgNoObs ;
661 // size inits to force cubic cells and mult4 level dimensions
662 // and make sure we dont allocate too much...
667 double sizeReduction = 1.0;
668 double memEstFromFunc = -1.0;
669 double memEstFine = -1.0;
670 string memreqStr("");
671 bool firstMInit = true;
675 initGridSizes( mSizex, mSizey, mSizez,
676 mvGeoStart, mvGeoEnd, mMaxRefine, PARALLEL);
679 #if LBM_INCLUDE_TESTSOLVERS==1
683 #endif // LBM_INCLUDE_TESTSOLVERS==1
686 calculateMemreqEstimate( mSizex, mSizey, mSizez,
687 mMaxRefine, mFarFieldSize, &memEstFromFunc, &memEstFine, &memreqStr );
690 string memLimStr("-");
691 if(sizeof(void*)==4) {
692 // 32bit system, limit to 2GB
693 memLimit = 2.0* 1024.0*1024.0*1024.0;
694 memLimStr = string("2GB");
696 // 64bit, just take 16GB as limit for now...
697 memLimit = 16.0* 1024.0*1024.0*1024.0;
698 memLimStr = string("16GB");
701 // restrict max. chunk of 1 mem block to 1GB for windos
702 bool memBlockAllocProblem = false;
703 double maxDefaultMemChunk = 2.*1024.*1024.*1024.;
704 //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG
706 double maxWinMemChunk = 1100.*1024.*1024.;
707 if(sizeof(void *)==4 && memEstFine>maxWinMemChunk) {
708 memBlockAllocProblem = true;
712 double maxMacMemChunk = 1200.*1024.*1024.;
713 if(memEstFine> maxMacMemChunk) {
714 memBlockAllocProblem = true;
717 if(sizeof(void*)==4 && memEstFine>maxDefaultMemChunk) {
718 // max memory chunk for 32bit systems 2gig
719 memBlockAllocProblem = true;
722 if(memEstFromFunc>memLimit || memBlockAllocProblem) {
723 sizeReduction *= 0.9;
724 mSizex = (int)(orgSx * sizeReduction);
725 mSizey = (int)(orgSy * sizeReduction);
726 mSizez = (int)(orgSz * sizeReduction);
727 debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<
728 //memEstFromFunc<<"/"<<memLimit<<", "<<
729 //memEstFine<<"/"<<maxWinMemChunk<<", "<<
730 memreqStr<<"/"<<memLimStr<<", "<<
731 "retrying: "<<PRINT_VEC(mSizex,mSizey,mSizez)<<" org:"<<PRINT_VEC(orgSx,orgSy,orgSz)
738 mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)mSizex;
739 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<mSizex<<" Y:"<<mSizey<<" Z:"<<mSizez<<
740 ", Domain: "<<mvGeoStart<<":"<<mvGeoEnd<<", "<<(mvGeoEnd-mvGeoStart)<<
741 ", PointerSize: "<< sizeof(void*) << ", IntSize: "<< sizeof(int) <<
742 ", est. Mem.Req.: "<<memreqStr ,2);
743 mpParam->setSize(mSizex, mSizey, mSizez);
744 if((minitTries>1)&&(glob_mpnum)) { errMsg("LbmFsgrSolver::initialize","Warning!!!!!!!!!!!!!!! Original gridsize changed........."); }
746 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: "
747 <<"LBM_EPSILON="<<LBM_EPSILON <<" "
748 <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" "
749 <<"OPT3D="<<OPT3D <<" "
750 <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" "
751 <<"MASS_INVALID="<<MASS_INVALID <<" "
752 <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" "
753 <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" "
754 <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" "
755 <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" "
756 <<"USE_LES="<<USE_LES <<" "
759 // perform 2D corrections...
760 if(LBMDIM == 2) mSizez = 1;
762 mpParam->setSimulationMaxSpeed(0.0);
763 if(mFVHeight>0.0) mpParam->setFluidVolumeHeight(mFVHeight);
764 mpParam->setTadapLevels( mMaxRefine+1 );
766 if(mForceTadapRefine>mMaxRefine) {
767 mpParam->setTadapLevels( mForceTadapRefine+1 );
768 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<<mForceTadapRefine, 6);
771 if(!mpParam->calculateAllMissingValues(mSimulationTime, false)) {
772 errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR);
778 for(int i=0; i<=mMaxRefine; i++) {
780 mLevel[i].nodeSize = 0.0;
781 mLevel[i].simCellSize = 0.0;
782 mLevel[i].omega = 0.0;
783 mLevel[i].time = 0.0;
784 mLevel[i].timestep = 1.0;
785 mLevel[i].gravity = LbmVec(0.0);
786 mLevel[i].mprsCells[0] = NULL;
787 mLevel[i].mprsCells[1] = NULL;
788 mLevel[i].mprsFlags[0] = NULL;
789 mLevel[i].mprsFlags[1] = NULL;
791 mLevel[i].avgOmega = 0.0;
792 mLevel[i].avgOmegaCnt = 0.0;
796 mLevel[mMaxRefine].lSizex = mSizex;
797 mLevel[mMaxRefine].lSizey = mSizey;
798 mLevel[mMaxRefine].lSizez = mSizez;
799 for(int i=mMaxRefine-1; i>=0; i--) {
800 mLevel[i].lSizex = mLevel[i+1].lSizex/2;
801 mLevel[i].lSizey = mLevel[i+1].lSizey/2;
802 mLevel[i].lSizez = mLevel[i+1].lSizez/2;
806 if(sizeof(CellFlagType) != CellFlagTypeSize) {
807 errFatal("LbmFsgrSolver::initialize","Fatal Error: CellFlagType has wrong size! Is:"<<sizeof(CellFlagType)<<", should be:"<<CellFlagTypeSize, SIMWORLD_GENERICERROR);
811 double ownMemCheck = 0.0;
812 mLevel[ mMaxRefine ].nodeSize = ((mvGeoEnd[0]-mvGeoStart[0]) / (LbmFloat)(mSizex));
813 mLevel[ mMaxRefine ].simCellSize = mpParam->getCellSize();
814 mLevel[ mMaxRefine ].lcellfactor = 1.0;
815 LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum);
818 mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ];
819 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ];
820 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
821 #else // COMPRESSGRIDS==0
822 LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2);
823 // D int tmp = ( (rcellSize +compressOffset +4)/(1024*1024) )*4;
824 // D printf("Debug MEMMMM excee: %d\n", tmp);
825 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ];
826 mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset;
827 ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4);
828 #endif // COMPRESSGRIDS==0
830 if(!mLevel[ mMaxRefine ].mprsCells[1] || !mLevel[ mMaxRefine ].mprsCells[0]) {
831 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (1)! Aborting...",SIMWORLD_INITERROR);
836 mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
837 mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
838 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
839 if(!mLevel[ mMaxRefine ].mprsFlags[1] || !mLevel[ mMaxRefine ].mprsFlags[0]) {
840 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (2)! Aborting...",SIMWORLD_INITERROR);
843 delete[] mLevel[ mMaxRefine ].mprsCells[0];
844 delete[] mLevel[ mMaxRefine ].mprsCells[1];
845 #else // COMPRESSGRIDS==0
846 delete[] mLevel[ mMaxRefine ].mprsCells[1];
847 #endif // COMPRESSGRIDS==0
851 LbmFloat lcfdimFac = 8.0;
852 if(LBMDIM==2) lcfdimFac = 4.0;
853 for(int i=mMaxRefine-1; i>=0; i--) {
854 mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize;
855 mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize;
856 mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac;
858 if(LBMDIM==2){ mLevel[i].lSizez = 1; } // 2D
859 rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum);
860 mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
861 mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
862 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
863 mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ];
864 mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ];
865 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
868 // isosurface memory, use orig res values
869 if(mFarFieldSize>0.) {
870 ownMemCheck += (double)( (3*sizeof(int)+sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
872 // ignore 3 int slices...
873 ownMemCheck += (double)( ( sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
878 if(ABS(1.0-ownMemCheck/memEstFromFunc)>0.01) {
879 errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off! real:"<<ownMemCheck<<" vs. estimate:"<<memEstFromFunc );
881 #endif // ELBEEM_PLUGIN!=1
883 // init sizes for _all_ levels
884 for(int i=mMaxRefine; i>=0; i--) {
885 mLevel[i].lOffsx = mLevel[i].lSizex;
886 mLevel[i].lOffsy = mLevel[i].lOffsx*mLevel[i].lSizey;
887 mLevel[i].lOffsz = mLevel[i].lOffsy*mLevel[i].lSizez;
888 mLevel[i].setCurr = 0;
889 mLevel[i].setOther = 1;
890 mLevel[i].lsteps = 0;
891 mLevel[i].lmass = 0.0;
892 mLevel[i].lvolume = 0.0;
895 // calc omega, force for all levels
897 mMinTimestep = mpParam->getTimestep();
898 mMaxTimestep = mpParam->getTimestep();
901 mpIso->setIsolevel( mIsoValue );
902 #if LBM_INCLUDE_TESTSOLVERS==1
904 mpTest->setMaterialName( mpIso->getMaterialName() );
907 if(mpTest->mFarfMode>0) { // 3d off
908 mpTest->setIsolevel(-100.0);
910 mpTest->setIsolevel( mIsoValue );
913 #endif // LBM_INCLUDE_TESTSOLVERS!=1
914 // approximate feature size with mesh resolution
915 float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5;
916 // smooth vars defined in solver_interface, set by simulation object
917 // reset for invalid values...
918 if((mSmoothSurface<0.)||(mSmoothSurface>50.)) mSmoothSurface = 1.;
919 if((mSmoothNormals<0.)||(mSmoothNormals>50.)) mSmoothNormals = 1.;
920 mpIso->setSmoothSurface( mSmoothSurface * featureSize );
921 mpIso->setSmoothNormals( mSmoothNormals * featureSize );
923 // init iso weight values mIsoWeightMethod
926 for(int ak=-1;ak<=1;ak++)
927 for(int aj=-1;aj<=1;aj++)
928 for(int ai=-1;ai<=1;ai++) {
929 switch(mIsoWeightMethod) {
930 case 1: // light smoothing
931 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) );
933 case 2: // very light smoothing
934 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) );
935 mIsoWeight[wcnt] *= mIsoWeight[wcnt];
937 case 3: // no smoothing
938 if(ai==0 && aj==0 && ak==0) mIsoWeight[wcnt] = 1.0;
939 else mIsoWeight[wcnt] = 0.0;
941 default: // strong smoothing (=0)
942 mIsoWeight[wcnt] = 1.0;
945 totw += mIsoWeight[wcnt];
948 for(int i=0; i<27; i++) mIsoWeight[i] /= totw;
950 LbmVec isostart = vec2L(mvGeoStart);
951 LbmVec isoend = vec2L(mvGeoEnd);
952 int twodOff = 0; // 2d slices
955 sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
956 se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
961 int isosx = mSizex+2;
962 int isosy = mSizey+2;
963 int isosz = mSizez+2+twodOff;
966 #if LBM_INCLUDE_TESTSOLVERS==1
967 //if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) {
968 if( (mMpNum>0) && (mMpIndex==0) ) {
970 // restore original value for node0
971 isosx = mOrgSizeX + 2;
972 isostart[0] = mOrgStartX;
973 isoend[0] = mOrgEndX;
975 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMin.mSrcx,mpTest->mGCMin.mSrcy,mpTest->mGCMin.mSrcz)<<" dst"
976 << PRINT_VEC(mpTest->mGCMin.mDstx,mpTest->mGCMin.mDsty,mpTest->mGCMin.mDstz)<<" consize"
977 << PRINT_VEC(mpTest->mGCMin.mConSizex,mpTest->mGCMin.mConSizey,mpTest->mGCMin.mConSizez)<<" ");
978 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMax.mSrcx,mpTest->mGCMax.mSrcy,mpTest->mGCMax.mSrcz)<<" dst"
979 << PRINT_VEC(mpTest->mGCMax.mDstx,mpTest->mGCMax.mDsty,mpTest->mGCMax.mDstz)<<" consize"
980 << PRINT_VEC(mpTest->mGCMax.mConSizex,mpTest->mGCMax.mConSizey,mpTest->mGCMax.mConSizez)<<" ");
981 #endif // LBM_INCLUDE_TESTSOLVERS==1
983 errMsg(" SETISO ", "iso "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5)<<" "<<(LbmFloat)(mSizex+1.0) );
984 errMsg("LbmFsgrSolver::initialize", "MPT: geo "<< mvGeoStart<<","<<mvGeoEnd<<
985 " grid:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<",iso:"<< PRINT_VEC(isosx,isosy,isosz) );
986 mpIso->setStart( vec2G(isostart) );
987 mpIso->setEnd( vec2G(isoend) );
988 LbmVec isodist = isoend-isostart;
990 int isosubs = mIsoSubdivs;
991 if(mFarFieldSize>1.) {
992 errMsg("LbmFsgrSolver::initialize","Warning - resetting isosubdivs, using fulledge!");
994 mpIso->setUseFulledgeArrays(true);
996 mpIso->setSubdivs(isosubs);
998 mpIso->initializeIsosurface( isosx,isosy,isosz, vec2G(isodist) );
1001 for(int ak=0;ak<isosz;ak++)
1002 for(int aj=0;aj<isosy;aj++)
1003 for(int ai=0;ai<isosx;ai++) { *mpIso->getData(ai,aj,ak) = 0.0; }
1006 /* init array (set all invalid first) */
1008 for(int lev=0; lev<=mMaxRefine; lev++) {
1009 FSGR_FORIJK_BOUNDS(lev) {
1010 RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage
1012 initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0);
1014 initEmptyCell(lev, i,j,k, CFFluid, 1.0, 1.0);
1021 if(mOutputSurfacePreview) {
1022 errMsg("LbmFsgrSolver::init","No preview in 2D allowed!");
1023 mOutputSurfacePreview = 0; }
1025 if((glob_mpactive) && (glob_mpindex>0)) {
1026 mOutputSurfacePreview = 0;
1030 if(mOutputSurfacePreview) {
1031 errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0");
1032 mOutputSurfacePreview = 0; }
1033 #endif // LBM_USE_GUI==1
1034 if(mOutputSurfacePreview) {
1035 // same as normal one, but use reduced size
1036 mpPreviewSurface = new IsoSurface( mIsoValue );
1037 mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() );
1038 mpPreviewSurface->setIsolevel( mIsoValue );
1039 // usually dont display for rendering
1040 mpPreviewSurface->setVisible( false );
1042 mpPreviewSurface->setStart( vec2G(isostart) );
1043 mpPreviewSurface->setEnd( vec2G(isoend) );
1044 LbmVec pisodist = isoend-isostart;
1045 LbmFloat pfac = mPreviewFactor;
1046 mpPreviewSurface->initializeIsosurface( (int)(pfac*mSizex)+2, (int)(pfac*mSizey)+2, (int)(pfac*mSizez)+2, vec2G(pisodist) );
1047 //mpPreviewSurface->setName( getName() + "preview" );
1048 mpPreviewSurface->setName( "preview" );
1050 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*mSizex)<<","<<(pfac*mSizey)<<","<<(pfac*mSizez)<<" enabled",10);
1054 mAvgNumUsedCells = 0;
1059 /*! init solver arrays */
1060 bool LbmFsgrSolver::initializeSolverGrids() {
1061 /* init boundaries */
1062 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10);
1063 // init obstacles, and reinit time step size
1064 initGeometryFlags();
1065 mLastSimTime = -1.0;
1066 // TODO check for invalid cells? nitGenericTestCases();
1068 // new - init noslip 1 everywhere...
1069 // half fill boundary cells?
1071 CellFlagType domainBoundType = CFInvalid;
1072 // TODO use normal object types instad...
1073 if(mDomainBound.find(string("free")) != string::npos) {
1074 domainBoundType = CFBnd | CFBndFreeslip;
1075 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<mDomainBound,10);
1076 } else if(mDomainBound.find(string("part")) != string::npos) {
1077 domainBoundType = CFBnd | CFBndPartslip; // part slip type
1078 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10);
1080 domainBoundType = CFBnd | CFBndNoslip;
1081 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10);
1084 // use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips)
1085 int domainobj = (int)(mpGiObjects->size());
1086 domainBoundType |= (domainobj<<24);
1087 //for(int i=0; i<(int)(domainobj+0); i++) {
1088 //errMsg("GEOIN","i"<<i<<" "<<(*mpGiObjects)[i]->getName());
1089 //if((*mpGiObjects)[i] == mpIso) { //check...
1092 //errMsg("GEOIN"," dm "<<(domainBoundType>>24));
1094 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1095 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1096 initEmptyCell(mMaxRefine, i,0,k, domainBoundType, 0.0, BND_FILL);
1097 initEmptyCell(mMaxRefine, i,mLevel[mMaxRefine].lSizey-1,k, domainBoundType, 0.0, BND_FILL);
1100 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1101 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1102 initEmptyCell(mMaxRefine, 0,j,k, domainBoundType, 0.0, BND_FILL);
1103 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-1,j,k, domainBoundType, 0.0, BND_FILL);
1105 //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL);
1110 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++)
1111 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1112 initEmptyCell(mMaxRefine, i,j,0, domainBoundType, 0.0, BND_FILL);
1113 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-1, domainBoundType, 0.0, BND_FILL);
1117 // TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
1118 /*for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1119 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1120 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL);
1122 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1123 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1124 initEmptyCell(mMaxRefine, i,1,k, domainBoundType, 0.0, BND_FILL);
1128 /*for(int ii=0; ii<(int)po w_change?(2.0,mMaxRefine)-1; ii++) {
1129 errMsg("BNDTESTSYMM","set "<<mLevel[mMaxRefine].lSizex-2-ii );
1130 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1131 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1132 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2-ii,j,k, domainBoundType, 0.0, BND_FILL); // SYMM!? 2D?
1134 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++)
1135 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1136 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-2-ii, domainBoundType, 0.0, BND_FILL); // SYMM!? 3D?
1139 // Symmetry tests */
1141 #if LBM_INCLUDE_TESTSOLVERS==1
1142 if(( strstr( this->getName().c_str(), "vorttfluid" ) != NULL) && (LBMDIM==2)) {
1143 errMsg("VORTT","init");
1144 int level=mMaxRefine;
1145 int cx = mLevel[level].lSizex/2;
1146 int cyo = mLevel[level].lSizey/2;
1147 int sx = mLevel[level].lSizex/8;
1148 int sy = mLevel[level].lSizey/8;
1150 LbmFloat rhomass = 1.;
1151 LbmFloat uFactor = 0.15;
1152 LbmFloat vdist = 1.0;
1154 int cy1=cyo-(int)(vdist*sy);
1155 int cy2=cyo+(int)(vdist*sy);
1157 //for(int j=cy-sy;j<cy+sy;j++) for(int i=cx-sx;i<cx+sx;i++) {
1158 for(int j=1;j<mLevel[level].lSizey-1;j++)
1159 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1160 LbmFloat d1 = norm(LbmVec(cx,cy1,0.)-LbmVec(i,j,0));
1161 LbmFloat d2 = norm(LbmVec(cx,cy2,0.)-LbmVec(i,j,0));
1162 bool in1 = (d1<=(LbmFloat)(sx));
1163 bool in2 = (d2<=(LbmFloat)(sx));
1165 LbmVec v1 = getNormalized( cross( LbmVec(cx,cy1,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor;
1166 LbmVec v2 = getNormalized( cross( LbmVec(cx,cy2,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor;
1167 LbmFloat w1=1., w2=1.;
1168 if(!in1) w1=(LbmFloat)(sx)/(1.5*d1);
1169 if(!in2) w2=(LbmFloat)(sx)/(1.5*d2);
1170 if(!in1) w1=0.; if(!in2) w2=0.; // sharp falloff
1173 initVelocityCell(level, i,j,0, CFFluid, rho, rhomass, uvec );
1174 //errMsg("VORTT","init uvec"<<uvec);
1178 #endif // LBM_INCLUDE_TESTSOLVERS==1
1180 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal1, causing panic, aborting..."); return false; }
1182 // prepare interface cells
1184 initStandingFluidGradient();
1186 // perform first step to init initial mass
1189 FSGR_FORIJK1(mMaxRefine) {
1190 if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid) {
1191 LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0);
1192 FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); }
1193 mInitialMass += fluidRho;
1195 } else if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) {
1196 mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass);
1200 mCurrentVolume = mCurrentMass = mInitialMass;
1202 ParamVec cspv = mpParam->calculateCellSize();
1203 if(LBMDIM==2) cspv[2] = 1.0;
1205 double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0;
1206 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<<mInitialMass<<" normalized:"<<nrmMass, 3);
1207 mInitialMass = 0.0; // reset, and use actual value after first step
1209 //mStartSymm = false;
1210 #if ELBEEM_PLUGIN!=1
1211 if((LBMDIM==2)&&(mSizex<200)) {
1212 if(!checkSymmetry("init")) {
1213 errMsg("LbmFsgrSolver::initialize","Unsymmetric init...");
1215 errMsg("LbmFsgrSolver::initialize","Symmetric init!");
1218 #endif // ELBEEM_PLUGIN!=1
1223 /*! prepare actual simulation start, setup viz etc */
1224 bool LbmFsgrSolver::initializeSolverPostinit() {
1226 myTime_t fsgrtstart = getTime();
1227 for(int lev=mMaxRefine-1; lev>=0; lev--) {
1228 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<<lev<<".",8);
1230 coarseRestrictFromFine(lev);
1232 coarseRestrictFromFine(lev);
1235 myTime_t fsgrtend = getTime();
1236 if(!mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); }
1237 mNumFsgrChanges = 0;
1239 for(int l=0; l<cDirNum; l++) {
1240 LbmFloat area = 0.5 * 0.5 *0.5;
1241 if(LBMDIM==2) area = 0.5 * 0.5;
1243 if(dfVecX[l]!=0) area *= 0.5;
1244 if(dfVecY[l]!=0) area *= 0.5;
1245 if(dfVecZ[l]!=0) area *= 0.5;
1246 mFsgrCellArea[l] = area;
1249 // make sure both sets are ok
1250 // copy from other to curr
1251 for(int lev=0; lev<=mMaxRefine; lev++) {
1252 FSGR_FORIJK_BOUNDS(lev) {
1253 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr);
1254 } } // first copy flags */
1257 // old mpPreviewSurface init
1258 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal2, causing panic, aborting..."); return false; }
1259 // make sure fill fracs are right for first surface generation
1263 mpIso->setParticles(mpParticles, mPartDropMassSub);
1264 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Iso Settings, subdivs="<<mpIso->getSubdivs()<<", partsize="<<mPartDropMassSub, 9);
1265 prepareVisualization();
1266 // copy again for stats counting
1267 for(int lev=0; lev<=mMaxRefine; lev++) {
1268 FSGR_FORIJK_BOUNDS(lev) {
1269 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr);
1270 } } // first copy flags */
1273 // now really done...
1274 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"SurfaceGen: SmsOrg("<<mSmoothSurface<<","<<mSmoothNormals<< /*","<<featureSize<<*/ "), Iso("<<mpIso->getSmoothSurface()<<","<<mpIso->getSmoothNormals()<<") ",10);
1275 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init done ... ",10);
1278 #if LBM_INCLUDE_CONTROL==1
1280 #endif // LBM_INCLUDE_CONTROL==1
1282 #if LBM_INCLUDE_TESTSOLVERS==1
1284 #endif // ELBEEM_PLUGIN!=1
1285 // not inited? dont use...
1286 if(mCutoff<0) mCutoff=0;
1294 // macros for mov obj init
1297 #define POS2GRID_CHECK(vec,n) \
1299 int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \
1300 if(k!=0) continue; \
1301 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \
1302 if(i<=0) continue; \
1303 if(i>=mLevel[level].lSizex-1) continue; \
1304 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \
1305 if(j<=0) continue; \
1306 if(j>=mLevel[level].lSizey-1) continue; \
1308 #else // LBMDIM -> 3
1309 #define POS2GRID_CHECK(vec,n) \
1311 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \
1312 if(i<=0) continue; \
1313 if(i>=mLevel[level].lSizex-1) continue; \
1314 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \
1315 if(j<=0) continue; \
1316 if(j>=mLevel[level].lSizey-1) continue; \
1317 const int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \
1318 if(k<=0) continue; \
1319 if(k>=mLevel[level].lSizez-1) continue; \
1323 // calculate object velocity from vert arrays in objvel vec
1324 #define OBJVEL_CALC \
1325 LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { \
1326 const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; \
1327 USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); \
1328 if(usqr>maxusqr) { \
1329 /* cutoff at maxVelVal */ \
1330 for(int jj=0; jj<3; jj++) { \
1331 if(objvel[jj]>0.) objvel[jj] = maxVelVal; \
1332 if(objvel[jj]<0.) objvel[jj] = -maxVelVal; \
1335 if(ntype&(CFBndFreeslip)) { \
1336 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \
1337 const LbmVec oldov=objvel; /*DEBUG*/ \
1338 objvel = vec2L((*pNormals)[n]) *dp; \
1339 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \
1341 else if(ntype&(CFBndPartslip)) { \
1342 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \
1343 const LbmVec oldov=objvel; /*DEBUG*/ \
1344 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \
1345 const LbmFloat partv = mObjectPartslips[OId]; \
1346 /*errMsg("PARTSLIP_DEBUG","l="<<l<<" ccel="<<RAC(ccel, dfInv[l] )<<" partv="<<partv<<",id="<<(int)(mnbf>>24)<<" newval="<<newval ); / part slip debug */ \
1347 /* m[l] = (RAC(ccel, dfInv[l] ) ) * partv + newval * (1.-partv); part slip */ \
1348 objvel = objvel*partv + vec2L((*pNormals)[n]) *dp*(1.-partv); \
1354 /*****************************************************************************/
1355 //! init moving obstacles for next sim step sim
1356 /*****************************************************************************/
1357 void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
1358 myTime_t monstart = getTime();
1361 const int level = mMaxRefine;
1362 const int workSet = mLevel[level].setCurr;
1363 const int otherSet = mLevel[level].setOther;
1364 LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime!
1365 // for debugging - check targetTime check during DEFAULT STREAM
1366 LbmFloat targetTime = mSimulationTime + mpParam->getTimestep();
1367 if(mLastSimTime == targetTime) {
1368 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"Called for same time! (t="<<mSimulationTime<<" , targett="<<targetTime<<")", 1);
1371 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime,10);
1372 //if(mSimulationTime!=mLastSimTime) errMsg("LbmFsgrSolver::initMovingObstacles","time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime);
1374 const LbmFloat maxVelVal = 0.1666;
1375 const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
1377 LbmFloat rhomass = 0.0;
1378 CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs!
1379 CellFlagType ntype = CFInvalid;
1380 // WARNING - copied from geo init!
1381 int numobjs = (int)(mpGiObjects->size());
1382 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
1383 // 2d display as rectangles
1384 ntlVec3Gfx iniPos(0.0);
1387 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))-(dvec*0.0);
1389 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0);
1392 if( (int)mObjectMassMovnd.size() < numobjs) {
1393 for(int i=mObjectMassMovnd.size(); i<numobjs; i++) {
1394 mObjectMassMovnd.push_back(0.);
1399 int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0;
1401 for(int OId=0; OId<numobjs; OId++) {
1402 ntlGeometryObject *obj = (*mpGiObjects)[OId];
1404 if(obj->getGeoInitId() != mLbmInitId) skip=true;
1405 if( (!staticInit) && (!obj->getIsAnimated()) ) skip=true;
1406 if( ( staticInit) && ( obj->getIsAnimated()) ) skip=true;
1408 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" skip:"<<skip<<", static:"<<staticInit<<" anim:"<<obj->getIsAnimated()<<" gid:"<<obj->getGeoInitId()<<" simgid:"<<mLbmInitId, 10);
1410 if( (obj->getGeoInitType()&FGI_ALLBOUNDS) ||
1411 (obj->getGeoInitType()&FGI_FLUID) && staticInit ) {
1413 otype = ntype = CFInvalid;
1414 switch(obj->getGeoInitType()) {
1415 /* case FGI_BNDPART: // old, use noslip for moving part/free objs
1418 errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() );
1419 otype = ntype = CFBnd|CFBndNoslip;
1421 if(obj->getGeoInitType()==FGI_BNDPART) otype = ntype = CFBnd|CFBndPartslip;
1422 if(obj->getGeoInitType()==FGI_BNDFREE) otype = ntype = CFBnd|CFBndFreeslip;
1426 case FGI_BNDPART: rhomass = BND_FILL;
1427 otype = ntype = CFBnd|CFBndPartslip|(OId<<24);
1429 case FGI_BNDFREE: rhomass = BND_FILL;
1430 otype = ntype = CFBnd|CFBndFreeslip|(OId<<24);
1433 case FGI_BNDNO: rhomass = BND_FILL;
1434 otype = ntype = CFBnd|CFBndNoslip|(OId<<24);
1437 otype = ntype = CFFluid;
1439 case FGI_MBNDINFLOW:
1440 otype = ntype = CFMbndInflow;
1442 case FGI_MBNDOUTFLOW:
1443 otype = ntype = CFMbndOutflow;
1446 int wasActive = ((obj->getGeoActive(sourceTime)>0.)? 1:0);
1447 int active = ((obj->getGeoActive(targetTime)>0.)? 1:0);
1448 //errMsg("GEOACTT"," obj "<<obj->getName()<<" a:"<<active<<","<<wasActive<<" s"<<sourceTime<<" t"<<targetTime <<" v"<<mObjectSpeeds[OId] );
1449 // skip inactive in/out flows
1450 if(ntype==CFInvalid){ errMsg("LbmFsgrSolver::initMovingObstacles","Invalid obj type "<<obj->getGeoInitType()); continue; }
1451 if((!active) && (otype&(CFMbndOutflow|CFMbndInflow)) ) continue;
1453 // copied from recalculateObjectSpeeds
1454 mObjectSpeeds[OId] = vec2L(mpParam->calculateLattVelocityFromRw( vec2P( (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) )));
1455 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 );
1457 //vector<ntlVec3Gfx> tNormals;
1458 vector<ntlVec3Gfx> *pNormals = NULL;
1459 mMOINormals.clear();
1460 if(ntype&(CFBndFreeslip|CFBndPartslip)) { pNormals = &mMOINormals; }
1462 mMOIVertices.clear();
1463 if(obj->getMeshAnimated()) {
1464 // do two full update
1465 // TODO tNormals handling!?
1466 mMOIVerticesOld.clear();
1467 obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, pNormals, mLevel[mMaxRefine].nodeSize, mvGeoStart, mvGeoEnd);
1468 monTrafo += mMOIVerticesOld.size();
1469 obj->applyTransformation(sourceTime, &mMOIVerticesOld,pNormals, 0, mMOIVerticesOld.size(), false );
1470 monTrafo += mMOIVertices.size();
1471 obj->applyTransformation(targetTime, &mMOIVertices,NULL /* no old normals needed */, 0, mMOIVertices.size(), false );
1473 // only do transform update
1474 obj->getMovingPoints(mMOIVertices,pNormals);
1475 mMOIVerticesOld = mMOIVertices;
1476 // WARNING - assumes mSimulationTime is global!?
1477 obj->applyTransformation(targetTime, &mMOIVertices,pNormals, 0, mMOIVertices.size(), false );
1478 monTrafo += mMOIVertices.size();
1480 // correct flags from last position, but extrapolate
1481 // velocity to next timestep
1482 obj->applyTransformation(sourceTime, &mMOIVerticesOld, NULL /* no old normals needed */, 0, mMOIVerticesOld.size(), false );
1483 monTrafo += mMOIVerticesOld.size();
1489 // check if object is moving at all
1490 if(obj->getIsAnimated()) {
1491 ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime);
1493 if(normNoSqrt(objMaxVel)>0.0) { ntype |= CFBndMoving; }
1494 // get old type - CHECK FIXME , timestep could have changed - cause trouble?
1495 ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - mpParam->getTimestep(),sourceTime);
1496 if(normNoSqrt(oldobjMaxVel)>0.0) { otype |= CFBndMoving; }
1498 if(obj->getMeshAnimated()) { ntype |= CFBndMoving; otype |= CFBndMoving; }
1499 CellFlagType rflagnb[27];
1500 LbmFloat massCheck = 0.;
1502 bool fillCells = (mObjectMassMovnd[OId]<=-1.);
1503 LbmFloat impactCorrFactor = obj->getGeoImpactFactor(targetTime);
1506 // first pass - set new obs. cells
1508 for(size_t n=0; n<mMOIVertices.size(); n++) {
1509 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK);
1510 POS2GRID_CHECK(mMOIVertices,n);
1511 //{ errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<", t="<<targetTime); }
1512 if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue;
1516 if(RFLAG(level, i,j,k, workSet)&(CFFluid)) {
1517 FORDF0 { massCheck -= QCELL(level, i,j,k, workSet, l); }
1520 else if(RFLAG(level, i,j,k, workSet)&(CFInter)) {
1521 massCheck -= QCELL(level, i,j,k, workSet, dMass);
1525 RFLAG(level, i,j,k, workSet) = ntype;
1527 //CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l);
1528 rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l);
1529 if(rflagnb[l]&(CFFluid|CFInter)) {
1530 rflagnb[l] &= (~CFNoBndFluid); // remove CFNoBndFluid flag
1531 RFLAG_NB(level, i,j,k,workSet,l) &= rflagnb[l];
1534 LbmFloat *dstCell = RACPNT(level, i,j,k,workSet);
1535 RAC(dstCell,0) = 0.0;
1536 if(ntype&CFBndMoving) {
1539 // compute fluid acceleration
1541 if(rflagnb[l]&(CFFluid|CFInter)) {
1542 const LbmFloat ux = dfDvecX[l]*objvel[0];
1543 const LbmFloat uy = dfDvecY[l]*objvel[1];
1544 const LbmFloat uz = dfDvecZ[l]*objvel[2];
1546 LbmFloat factor = 2. * dfLength[l] * 3.0 * (ux+uy+uz); //
1547 if(ntype&(CFBndFreeslip|CFBndPartslip)) {
1548 // missing, diag mass checks...
1549 //if(l<=LBMDIM*2) factor *= 1.4142;
1550 factor *= 2.0; // TODO, optimize
1552 factor *= 1.2; // TODO, optimize
1554 factor *= impactCorrFactor; // use manual tweaking channel
1555 RAC(dstCell,l) = factor;
1556 massCheck += factor;
1558 RAC(dstCell,l) = 0.;
1562 #if NEWDIRVELMOTEST==1
1563 FORDF1 { RAC(dstCell,l) = 0.; }
1564 RAC(dstCell,dMass) = objvel[0];
1565 RAC(dstCell,dFfrac) = objvel[1];
1566 RAC(dstCell,dC) = objvel[2];
1567 #endif // NEWDIRVELMOTEST==1
1569 FORDF1 { RAC(dstCell,l) = 0.0; }
1571 RAC(dstCell, dFlux) = targetTime;
1572 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" dflt="<<RAC(dstCell, dFlux) );
1575 } // bnd, is active?
1577 // second pass, remove old ones
1578 // warning - initEmptyCell et. al dont overwrite OId or persist flags...
1580 for(size_t n=0; n<mMOIVerticesOld.size(); n++) {
1581 POS2GRID_CHECK(mMOIVerticesOld,n);
1583 if((RFLAG(level, i,j,k, workSet) == otype) &&
1584 (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) {
1587 // TODO: optimize for OPT3D==0
1589 //rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l);
1590 rflagnb[l] = RFLAG_NB(level, i,j,k,otherSet,l); // test use other set to not have loop dependance
1591 nbored |= rflagnb[l];
1593 CellFlagType settype = CFInvalid;
1594 if(nbored&CFFluid) {
1595 settype = CFInter|CFNoInterpolSrc;
1597 if(!fillCells) rhomass = 0.;
1600 if(!(nbored&CFEmpty)) { settype=CFFluid|CFNoInterpolSrc; rhomass=1.; }
1602 // new interpolate values
1603 LbmFloat avgrho = 0.0;
1604 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
1605 interpolateCellValues(level,i,j,k,workSet, avgrho,avgux,avguy,avguz);
1606 initVelocityCell(level, i,j,k, settype, avgrho, rhomass, LbmVec(avgux,avguy,avguz) );
1607 //errMsg("NMOCIT"," at "<<PRINT_IJK<<" "<<avgrho<<" "<<norm(LbmVec(avgux,avguy,avguz))<<" "<<LbmVec(avgux,avguy,avguz) );
1608 massCheck += rhomass;
1610 settype = CFEmpty; rhomass = 0.0;
1611 initEmptyCell(level, i,j,k, settype, 1., rhomass );
1619 // only compute mass transfer when init is done
1621 errMsg("initMov","dccd\n\nMassd test "<<obj->getName()<<" dccd massCheck="<<massCheck<<" massReinits"<<massReinits<<
1622 " fillCells"<<fillCells<<" massmovbnd:"<<mObjectMassMovnd[OId]<<" inim:"<<mInitialMass );
1623 mObjectMassMovnd[OId] += massCheck;
1627 else if(ntype&CFFluid){
1628 // second static init pass
1630 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" verts"<<mMOIVertices.size() ,9);
1631 CellFlagType setflflag = CFFluid; //|(OId<<24);
1632 for(size_t n=0; n<mMOIVertices.size(); n++) {
1633 POS2GRID_CHECK(mMOIVertices,n);
1634 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1635 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1636 //changeFlag(level, i,j,k, workSet, setflflag);
1637 initVelocityCell(level, i,j,k, setflflag, 1., 1., mObjectSpeeds[OId] );
1639 //else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); }
1641 } // second static inflow pass
1644 else if(ntype&CFMbndInflow){
1645 // inflow pass - add new fluid cells
1646 // this is slightly different for standing inflows,
1647 // as the fluid is forced to the desired velocity inside as
1649 const LbmFloat iniRho = 1.0;
1650 const LbmVec vel(mObjectSpeeds[OId]);
1651 const LbmFloat usqr = (vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])*1.5;
1652 USQRMAXCHECK(usqr,vel[0],vel[1],vel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
1653 //errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<mMOIVertices.size() );
1655 for(size_t n=0; n<mMOIVertices.size(); n++) {
1656 POS2GRID_CHECK(mMOIVertices,n);
1657 // TODO - also reinit interface cells !?
1658 if(RFLAG(level, i,j,k, workSet)!=CFEmpty) {
1659 // test prevent particle gen for inflow inter cells
1660 if(RFLAG(level, i,j,k, workSet)&(CFInter)) { RFLAG(level, i,j,k, workSet) &= (~CFNoBndFluid); } // remove CFNoBndFluid flag
1664 // TODO add OPT3D treatment
1665 LbmFloat *tcel = RACPNT(level, i,j,k,workSet);
1666 FORDF0 { RAC(tcel, l) = this->getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); }
1667 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho;
1668 RAC(tcel, dFlux) = FLUX_INIT;
1669 CellFlagType setFlag = CFInter;
1670 changeFlag(level, i,j,k, workSet, setFlag);
1671 mInitialMass += iniRho;
1673 // second static init pass
1675 CellFlagType set2Flag = CFMbndInflow|(OId<<24);
1676 for(size_t n=0; n<mMOIVertices.size(); n++) {
1677 POS2GRID_CHECK(mMOIVertices,n);
1678 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1679 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1680 forceChangeFlag(level, i,j,k, workSet, set2Flag);
1681 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) {
1682 forceChangeFlag(level, i,j,k, workSet,
1683 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag);
1686 } // second static inflow pass
1690 else if(ntype&CFMbndOutflow){
1691 const LbmFloat iniRho = 0.0;
1692 for(size_t n=0; n<mMOIVertices.size(); n++) {
1693 POS2GRID_CHECK(mMOIVertices,n);
1694 // FIXME check fluid/inter cells for non-static!?
1695 if(!(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter))) {
1696 if((staticInit)&&(RFLAG(level, i,j,k, workSet)==CFEmpty)) {
1697 forceChangeFlag(level, i,j,k, workSet, CFMbndOutflow); }
1701 // interface cell - might be double empty? FIXME check?
1703 // remove fluid cells, shouldnt be here anyway
1704 LbmFloat *tcel = RACPNT(level, i,j,k,workSet);
1705 LbmFloat fluidRho = RAC(tcel,0); FORDF1 { fluidRho += RAC(tcel,l); }
1706 mInitialMass -= fluidRho;
1707 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho;
1708 RAC(tcel, dFlux) = FLUX_INIT;
1709 CellFlagType setFlag = CFInter;
1710 changeFlag(level, i,j,k, workSet, setFlag);
1712 // same as ifemptied for if below
1714 emptyp.x = i; emptyp.y = j; emptyp.z = k;
1715 mListEmpty.push_back( emptyp );
1716 //calcCellsEmptied++;
1718 // second static init pass
1720 CellFlagType set2Flag = CFMbndOutflow|(OId<<24);
1721 for(size_t n=0; n<mMOIVertices.size(); n++) {
1722 POS2GRID_CHECK(mMOIVertices,n);
1723 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1724 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1725 forceChangeFlag(level, i,j,k, workSet, set2Flag);
1726 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) {
1727 forceChangeFlag(level, i,j,k, workSet,
1728 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag);
1731 } // second static outflow pass
1739 int workSet = mLevel[level].setCurr;
1740 FSGR_FORIJK1(level) {
1741 if( (RFLAG(level,i,j,k, workSet) & CFBndMoving) ) {
1742 if(QCELL(level, i,j,k, workSet, dFlux)!=targetTime) {
1743 errMsg("lastt"," old val!? at "<<PRINT_IJK<<" t="<<QCELL(level, i,j,k, workSet, dFlux)<<" target="<<targetTime);
1749 #undef POS2GRID_CHECK
1750 myTime_t monend = getTime();
1751 if(monend-monstart>0) debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7);
1752 mLastSimTime = targetTime;
1758 #define GETPOS(i,j,k) \
1759 ntlVec3Gfx ggpos = \
1760 ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \
1761 iniPos[1]+ dvec[1]*(gfxReal)(j), \
1762 iniPos[2]+ dvec[2]*(gfxReal)(k) ); \
1763 if((LBMDIM==2)&&(mInit2dYZ)) { SWAPYZ(ggpos); }
1765 /*****************************************************************************/
1766 /*! perform geometry init (if switched on) */
1767 /*****************************************************************************/
1768 extern int globGeoInitDebug; //solver_interface
1769 bool LbmFsgrSolver::initGeometryFlags() {
1770 int level = mMaxRefine;
1771 myTime_t geotimestart = getTime();
1772 ntlGeometryObject *pObj;
1773 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
1774 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< mLbmInitId <<") v"<<dvec,3);
1775 // WARNING - copied to movobj init!
1777 /* init object velocities, this has always to be called for init */
1783 // make sure moving obstacles are inited correctly
1784 // preinit moving obj points
1785 int numobjs = (int)(mpGiObjects->size());
1786 for(int o=0; o<numobjs; o++) {
1787 ntlGeometryObject *obj = (*mpGiObjects)[o];
1788 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9);
1790 ((obj->getGeoInitType()&FGI_ALLBOUNDS) && (obj->getIsAnimated())) ||
1791 (obj->getVolumeInit()&VOLUMEINIT_SHELL) ) {
1792 if(!obj->getMeshAnimated()) {
1793 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9);
1794 obj->initMovingPoints(mSimulationTime, mLevel[mMaxRefine].nodeSize);
1800 ntlVec3Gfx maxMovobjVelRw = getGeoMaxMovementVelocity( mSimulationTime, mpParam->getTimestep() );
1801 ntlVec3Gfx maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) );
1802 mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) );
1803 LbmFloat allowMax = mpParam->getTadapMaxSpeed(); // maximum allowed velocity
1804 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxMovobjVel <<" from mov. obj.="<<maxMovobjVelRw<<" , allowed Max="<<allowMax ,5);
1805 if(mpParam->getSimulationMaxSpeed() > allowMax) {
1806 // similar to adaptTimestep();
1807 LbmFloat nextmax = mpParam->getSimulationMaxSpeed();
1808 LbmFloat newdt = mpParam->getTimestep() * (allowMax / nextmax); // newtr
1809 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< mpParam->getTimestep() <<" ",5);
1810 mpParam->setDesiredTimestep( newdt );
1811 mpParam->calculateAllMissingValues( mSimulationTime, mSilent );
1812 maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P(getGeoMaxMovementVelocity(
1813 mSimulationTime, mpParam->getTimestep() )) ));
1814 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxMovobjVel,5);
1816 recalculateObjectSpeeds();
1819 // init obstacles for first time step (requires obj speeds)
1820 initMovingObstacles(true);
1822 /* set interface cells */
1823 ntlVec3Gfx pos,iniPos; // position of current cell
1824 LbmFloat rhomass = 0.0;
1825 CellFlagType ntype = CFInvalid;
1830 // 2d display as rectangles
1833 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))+(dvec*0.5);
1834 //if(mInit2dYZ) { SWAPYZ(mGravity); for(int lev=0; lev<=mMaxRefine; lev++){ SWAPYZ( mLevel[lev].gravity ); } }
1836 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5);
1840 // first init boundary conditions
1841 // invalid cells are set to empty afterwards
1842 // TODO use floop macros!?
1843 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1844 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1845 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1849 const bool inside = geoInitCheckPointInside( ggpos, FGI_ALLBOUNDS, OId, distance);
1851 pObj = (*mpGiObjects)[OId];
1852 switch( pObj->getGeoInitType() ){
1853 case FGI_MBNDINFLOW:
1854 if(! pObj->getIsAnimated() ) {
1856 ntype = CFFluid | CFMbndInflow;
1861 case FGI_MBNDOUTFLOW:
1862 if(! pObj->getIsAnimated() ) {
1864 ntype = CFEmpty|CFMbndOutflow;
1871 ntype = CFBnd|CFBndNoslip;
1875 ntype = CFBnd|CFBndPartslip; break;
1878 ntype = CFBnd|CFBndFreeslip; break;
1879 default: // warn here?
1881 ntype = CFBnd|CFBndNoslip; break;
1884 if(ntype != CFInvalid) {
1886 if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { }
1887 ntype |= (OId<<24); // NEWTEST2
1888 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1891 // walk along x until hit for following inits
1892 if(distance<=-1.0) { distance = 100.0; } // FIXME dangerous
1894 gfxReal dcnt=dvec[0];
1895 while(( dcnt< distance-dvec[0] )&&(i+1<mLevel[level].lSizex-1)) {
1896 dcnt += dvec[0]; i++;
1898 if(ntype != CFInvalid) {
1899 // rho,mass,OId are still inited from above
1900 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1911 // now init fluid layer
1912 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1913 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1914 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1915 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue;
1919 const bool inside = geoInitCheckPointInside( ggpos, FGI_FLUID, OId, distance);
1923 if(ntype != CFInvalid) {
1926 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1930 // walk along x until hit for following inits
1931 if(distance<=-1.0) { distance = 100.0; }
1933 gfxReal dcnt=dvec[0];
1934 while((dcnt< distance )&&(i+1<mLevel[level].lSizex-1)) {
1935 dcnt += dvec[0]; i++;
1937 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue;
1938 if(ntype != CFInvalid) {
1939 // rhomass are still inited from above
1940 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1950 // reset invalid to empty again
1951 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1952 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1953 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1954 if(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFInvalid) {
1955 RFLAG(level, i,j,k, mLevel[level].setOther) =
1956 RFLAG(level, i,j,k, mLevel[level].setCurr) = CFEmpty;
1963 myTime_t geotimeend = getTime();
1964 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< getTimeString(geotimeend-geotimestart)<<","<<savedNodes<<") " , 10 );
1965 //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez));
1971 /*****************************************************************************/
1972 /* init part for all freesurface testcases */
1973 void LbmFsgrSolver::initFreeSurfaces() {
1974 double interfaceFill = 0.45; // filling level of interface cells
1975 //interfaceFill = 1.0; // DEUG!! GEOMTEST!!!!!!!!!!!!
1977 // set interface cells
1978 FSGR_FORIJK1(mMaxRefine) {
1979 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid )) {
1981 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
1982 if( ( RFLAG(mMaxRefine, ni, nj, nk, mLevel[mMaxRefine].setCurr)& CFEmpty ) ) {
1983 LbmFloat arho=0., aux=0., auy=0., auz=0.;
1984 interpolateCellValues(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz);
1985 //errMsg("TINI"," "<<PRINT_VEC(ni,nj,nk)<<" v"<<LbmVec(aux,auy,auz) );
1986 // unnecessary? initEmptyCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill);
1987 initVelocityCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill, LbmVec(aux,auy,auz) );
1993 // remove invalid interface cells
1994 FSGR_FORIJK1(mMaxRefine) {
1995 // remove invalid interface cells
1996 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) ) {
1998 int NBs = 0; // neighbor flags or'ed
2002 if( ( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l )& CFEmpty ) ) {
2005 NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l);
2007 // remove cells with no fluid or interface neighbors
2008 if((NBs & CFFluid)==0) { delit = 1; }
2009 if((NBs & CFInter)==0) { delit = 1; }
2010 // remove cells with no empty neighbors
2011 if(noEmptyNB) { delit = 2; }
2013 // now we can remove the cell
2015 initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0);
2018 //initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0);
2019 LbmFloat arho=0., aux=0., auy=0., auz=0.;
2020 interpolateCellValues(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz);
2021 initVelocityCell(mMaxRefine, i,j,k, CFFluid, arho,1., LbmVec(aux,auy,auz) );
2026 // another brute force init, make sure the fill values are right...
2027 // and make sure both sets are equal
2028 for(int lev=0; lev<=mMaxRefine; lev++) {
2029 FSGR_FORIJK_BOUNDS(lev) {
2030 if( (RFLAG(lev, i,j,k,0) & (CFBnd)) ) {
2031 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = BND_FILL;
2034 if( (RFLAG(lev, i,j,k,0) & (CFEmpty)) ) {
2035 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = 0.0;
2040 // ----------------------------------------------------------------------
2041 // smoother surface...
2042 if(mInitSurfaceSmoothing>0) {
2043 debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing timestep ",10);
2044 #if COMPRESSGRIDS==1
2045 //errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return;
2046 #endif // COMPRESSGRIDS==0
2048 for(int s=0; s<mInitSurfaceSmoothing; s++) {
2049 //SGR_FORIJK1(mMaxRefine) {
2051 int kstart=getForZMin1(), kend=getForZMax1(mMaxRefine);
2052 int lev = mMaxRefine;
2053 #if COMPRESSGRIDS==0
2054 for(int k=kstart;k<kend;++k) {
2055 #else // COMPRESSGRIDS==0
2056 int kdir = 1; // COMPRT ON
2057 if(mLevel[lev].setCurr==1) {
2063 for(int k=kstart;k!=kend;k+=kdir) {
2064 #endif // COMPRESSGRIDS==0
2065 for(int j=1;j<mLevel[lev].lSizey-1;++j) {
2066 for(int i=1;i<mLevel[lev].lSizex-1;++i) {
2067 if( ( RFLAG(lev, i,j,k, mLevel[lev].setCurr)& CFInter) ) {
2068 LbmFloat mass = 0.0;
2071 for(int l=0;(l<cDirNum); l++) {
2072 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
2073 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFFluid ){
2076 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFInter ){
2077 mass += QCELL(lev, ni,nj,nk, mLevel[lev].setCurr, dMass);
2082 //errMsg(" I ", PRINT_IJK<<" m"<<mass );
2083 QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)cDirNum) );
2084 QCELL(lev, i,j,k, mLevel[lev].setOther, dFfrac) = QCELL(lev, i,j,k, mLevel[lev].setOther, dMass);
2088 mLevel[lev].setOther = mLevel[lev].setCurr;
2089 mLevel[lev].setCurr ^= 1;
2094 /*****************************************************************************/
2095 /* init part for all freesurface testcases */
2096 void LbmFsgrSolver::initStandingFluidGradient() {
2097 // ----------------------------------------------------------------------
2098 // standing fluid preinit
2099 const int debugStandingPreinit = 0;
2100 int haveStandingFluid = 0;
2102 #define STANDFLAGCHECK(iindex) \
2103 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || \
2104 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ \
2105 if((iindex)>1) { haveStandingFluid=(iindex); } \
2106 j = mLevel[mMaxRefine].lSizey; i=mLevel[mMaxRefine].lSizex; k=getForZMaxBnd(); \
2109 int gravIndex[3] = {0,0,0};
2110 int gravDir[3] = {1,1,1};
2111 int maxGravComp = 1; // by default y
2112 int gravComp1 = 0; // by default y
2113 int gravComp2 = 2; // by default y
2114 if( ABS(mLevel[mMaxRefine].gravity[0]) > ABS(mLevel[mMaxRefine].gravity[1]) ){ maxGravComp = 0; gravComp1=1; gravComp2=2; }
2115 if( ABS(mLevel[mMaxRefine].gravity[2]) > ABS(mLevel[mMaxRefine].gravity[0]) ){ maxGravComp = 2; gravComp1=0; gravComp2=1; }
2117 int gravIMin[3] = { 0 , 0 , 0 };
2119 mLevel[mMaxRefine].lSizex + 0,
2120 mLevel[mMaxRefine].lSizey + 0,
2121 mLevel[mMaxRefine].lSizez + 0 };
2122 if(LBMDIM==2) gravIMax[2] = 1;
2125 if( mLevel[mMaxRefine].gravity[maxGravComp] > 0.0 ) {
2128 int tmp = gravIMin[i];
2129 gravIMin[i] = gravIMax[i] - 1;
2130 gravIMax[i] = tmp - 1;
2133 #define PRINTGDIRS \
2134 errMsg("Standing fp","X start="<<gravIMin[0]<<" end="<<gravIMax[0]<<" dir="<<gravDir[0] ); \
2135 errMsg("Standing fp","Y start="<<gravIMin[1]<<" end="<<gravIMax[1]<<" dir="<<gravDir[1] ); \
2136 errMsg("Standing fp","Z start="<<gravIMin[2]<<" end="<<gravIMax[2]<<" dir="<<gravDir[2] );
2139 bool gravAbort = false;
2142 for(gravIndex[2]= gravIMin[2]; (gravIndex[2]!=gravIMax[2])&&(!gravAbort); gravIndex[2] += gravDir[2]) \
2143 for(gravIndex[1]= gravIMin[1]; (gravIndex[1]!=gravIMax[1])&&(!gravAbort); gravIndex[1] += gravDir[1]) \
2144 for(gravIndex[0]= gravIMin[0]; (gravIndex[0]!=gravIMax[0])&&(!gravAbort); gravIndex[0] += gravDir[0])
2147 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2];
2148 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) ||
2149 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFBndMoving)) ) ||
2150 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ) {
2151 int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp]));
2152 if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] );
2154 haveStandingFluid = fluidHeight; //gravIndex[maxGravComp];
2155 gravIMax[maxGravComp] = gravIndex[maxGravComp] + gravDir[maxGravComp];
2157 gravAbort = true; continue;
2162 LbmFloat fluidHeight;
2163 fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp]));
2164 #if LBM_INCLUDE_TESTSOLVERS==1
2165 if(mUseTestdata) mpTest->mFluidHeight = (int)fluidHeight;
2166 #endif // ELBEEM_PLUGIN!=1
2167 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])<<
2168 " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10);
2170 if(mDisableStandingFluidInit) {
2171 debMsgStd("Standing fluid preinit", DM_MSG, "Should be performed - but skipped due to mDisableStandingFluidInit flag set!", 2);
2172 haveStandingFluid=0;
2175 // copy flags and init , as no flags will be changed during grav init
2176 // also important for corasening later on
2177 const int lev = mMaxRefine;
2178 CellFlagType nbflag[LBM_DFNUM], nbored;
2179 for(int k=getForZMinBnd();k<getForZMaxBnd(mMaxRefine);++k) {
2180 for(int j=0;j<mLevel[lev].lSizey-0;++j) {
2181 for(int i=0;i<mLevel[lev].lSizex-0;++i) {
2182 if( (RFLAG(lev, i,j,k,SRCS(lev)) & (CFFluid)) ) {
2185 nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l);
2186 nbored |= nbflag[l];
2189 RFLAG(lev, i,j,k,SRCS(lev)) &= (~CFNoBndFluid);
2191 RFLAG(lev, i,j,k,SRCS(lev)) |= CFNoBndFluid;
2194 RFLAG(lev, i,j,k,TSET(lev)) = RFLAG(lev, i,j,k,SRCS(lev));
2197 if(haveStandingFluid) {
2198 int rhoworkSet = mLevel[lev].setCurr;
2199 myTime_t timestart = getTime(); // FIXME use user time here?
2202 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2];
2203 //debMsgStd("Standing fluid preinit", DM_MSG, " init check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 );
2204 if( ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFInter)) ) ||
2205 ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFEmpty)) ) ){
2211 // 1/6 velocity from denisty gradient, 1/2 for delta of two cells
2212 rho += 1.0* (fluidHeight-gravIndex[maxGravComp]) *
2213 (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega);
2214 if(debugStandingPreinit)
2215 if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) {
2216 errMsg("Standing fp","gi="<<gravIndex[maxGravComp]<<" rho="<<rho<<" at "<<PRINT_IJK);
2219 if( (RFLAG(lev, i,j,k, rhoworkSet) & CFFluid) ||
2220 (RFLAG(lev, i,j,k, rhoworkSet) & CFInter) ) {
2221 FORDF0 { QCELL(lev, i,j,k, rhoworkSet, l) *= rho; }
2222 QCELL(lev, i,j,k, rhoworkSet, dMass) *= rho;
2227 debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited (max-rho:"<<
2228 (1.0+ (fluidHeight) * (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega)) <<", h:"<< fluidHeight<<") ", 8);
2230 int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) );
2231 preinitSteps = (haveStandingFluid>>2); // not much use...?
2233 debMsgStd("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10);
2234 for(int s=0; s<preinitSteps; s++) {
2235 // in solver main cpp
2236 standingFluidPreinit();
2239 myTime_t timeend = getTime();
2240 debMsgStd("Standing fluid preinit", DM_MSG, " done, "<<getTimeString(timeend-timestart), 9);
2247 bool LbmFsgrSolver::checkSymmetry(string idstring)
2252 const int maxMsgs = 10;
2253 const bool markCells = false;
2255 //for(int lev=0; lev<=mMaxRefine; lev++) {
2256 { int lev = mMaxRefine;
2258 // no point if not symm.
2259 if( (mLevel[lev].lSizex==mLevel[lev].lSizey) && (mLevel[lev].lSizex==mLevel[lev].lSizez)) {
2265 for(int s=0; s<2; s++) {
2267 if(i<(mLevel[lev].lSizex/2)) {
2268 int inb = (mLevel[lev].lSizey-1-i);
2270 if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T
2272 if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true;
2274 if(msgs<maxMsgs) { msgs++;
2275 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) );
2278 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2281 if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true;
2283 if(msgs<maxMsgs) { msgs++;
2284 //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl);
2285 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) );
2288 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2292 LbmFloat nbrho = QCELL(lev, i,j,k, s, dC);
2293 FORDF1 { nbrho += QCELL(lev, i,j,k, s, l); }
2294 LbmFloat otrho = QCELL(lev, inb,j,k, s, dC);
2295 FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); }
2296 if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true;
2298 if(msgs<maxMsgs) { msgs++;
2299 //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl);
2300 errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho );
2303 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2309 LbmFloat maxdiv =0.0;
2311 errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv );
2312 //if(LBMDIM==2) mPanic = true;
2315 errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv );
2323 LbmFsgrSolver::interpolateCellValues(
2324 int level,int ei,int ej,int ek,int workSet,
2325 LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz)
2327 LbmFloat avgrho = 0.0;
2328 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
2329 LbmFloat cellcnt = 0.0;
2331 for(int nbl=1; nbl< cDfNum ; ++nbl) {
2332 if(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) continue;
2333 if( (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & (CFFluid|CFInter)) ){
2334 //((!(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) &&
2335 //(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFInter) ) {
2337 for(int rl=0; rl< cDfNum ; ++rl) {
2338 LbmFloat nbdf = QCELL_NB(level,ei,ej,ek, workSet,nbl, rl);
2339 avgux += (dfDvecX[rl]*nbdf);
2340 avguy += (dfDvecY[rl]*nbdf);
2341 avguz += (dfDvecZ[rl]*nbdf);
2348 // no nbs? just use eq.
2350 avgux = avguy = avguz = 0.0;
2351 //TTT mNumProblems++;
2352 #if ELBEEM_PLUGIN!=1
2354 // this can happen for worst case moving obj scenarios...
2355 errMsg("LbmFsgrSolver::interpolateCellValues","Cellcnt<=0.0 at "<<PRINT_VEC(ei,ej,ek));
2356 #endif // ELBEEM_PLUGIN
2359 avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt;
2367 } // interpolateCellValues
2370 /******************************************************************************
2372 *****************************************************************************/
2374 //! lbm factory functions
2375 LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); }