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 // always output performance estimate
446 debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5);
447 if(!mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10);
453 /******************************************************************************
454 * initilize variables fom attribute list
455 *****************************************************************************/
456 void LbmFsgrSolver::parseAttrList()
458 LbmSolverInterface::parseStdAttrList();
460 string matIso("default");
461 matIso = mpSifAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false );
462 mpIso->setMaterialName( matIso );
463 mOutputSurfacePreview = mpSifAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false );
464 mTimeAdap = mpSifAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false );
465 mDomainBound = mpSifAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false );
466 mDomainPartSlipValue = mpSifAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false );
468 mIsoWeightMethod= mpSifAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false );
469 mInitSurfaceSmoothing = mpSifAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false );
470 mSmoothSurface = mpSifAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false );
471 mSmoothNormals = mpSifAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false );
472 mFsSurfGenSetting = mpSifAttrs->readInt("fssurfgen", mFsSurfGenSetting, "SimulationLbm","mFsSurfGenSetting", false );
475 mMaxRefine = mRefinementDesired;
476 mMaxRefine = mpSifAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false);
477 if(mMaxRefine<0) mMaxRefine=0;
478 if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1;
479 mDisableStandingFluidInit = mpSifAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false);
480 mInit2dYZ = mpSifAttrs->readBool("init2dyz", mInit2dYZ,"LbmFsgrSolver", "mInit2dYZ", false);
481 mForceTadapRefine = mpSifAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false);
483 // demo mode settings
484 mFVHeight = mpSifAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false );
485 // FIXME check needed?
486 mFVArea = mpSifAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false );
488 // debugging - skip some time...
489 double starttimeskip = 0.;
490 starttimeskip = mpSifAttrs->readFloat("forcestarttimeskip", starttimeskip, "LbmFsgrSolver","starttimeskip", false );
491 mSimulationTime += starttimeskip;
492 if(starttimeskip>0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<<starttimeskip<<", t="<<mSimulationTime, 1);
494 #if LBM_INCLUDE_CONTROL==1
495 mpControl->parseControldataAttrList(mpSifAttrs);
498 #if LBM_INCLUDE_TESTSOLVERS==1
500 mUseTestdata = mpSifAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false);
501 mpTest->parseTestdataAttrList(mpSifAttrs);
503 mUseTestdata=1; // DEBUG
504 #endif // ELBEEM_PLUGIN
506 mMpNum = mpSifAttrs->readInt("mpnum", mMpNum ,"LbmFsgrSolver", "mMpNum", false);
507 mMpIndex = mpSifAttrs->readInt("mpindex", mMpIndex ,"LbmFsgrSolver", "mMpIndex", false);
511 mMpIndex = glob_mpindex;
516 errMsg("LbmFsgrSolver::parseAttrList"," mpactive:"<<glob_mpactive<<", "<<glob_mpindex<<"/"<<glob_mpnum);
518 mUseTestdata=1; // needed in this case...
521 errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" ");
522 #else // LBM_INCLUDE_TESTSOLVERS!=1
523 // not testsolvers, off by default
525 if(mFarFieldSize>=2.) mUseTestdata=1; // equiv. to test solver check
526 #endif // LBM_INCLUDE_TESTSOLVERS!=1
528 mInitialCsmago = mpSifAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false );
530 float mInitialCsmagoCoarse = 0.0;
531 mInitialCsmagoCoarse = mpSifAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false );
534 debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2);
535 mInitialCsmago = 0.0;
540 /******************************************************************************
541 * Initialize omegas and forces on all levels (for init/timestep change)
542 *****************************************************************************/
543 void LbmFsgrSolver::initLevelOmegas()
545 // no explicit settings
546 mOmega = mpParam->calculateOmega(mSimulationTime);
547 mGravity = vec2L( mpParam->calculateGravity(mSimulationTime) );
548 mSurfaceTension = 0.; //mpParam->calculateSurfaceTension(); // unused
549 if(mInit2dYZ) { SWAPYZ(mGravity); }
551 // check if last init was ok
552 LbmFloat gravDelta = norm(mGravity-mLastGravity);
553 //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<mOmega<<" - lom:"<<mLastOmega<<" gv:"<<mGravity<<" - "<<mLastGravity<<" , "<<gravDelta );
554 if((mOmega == mLastOmega) && (gravDelta<=0.0)) return;
556 if(mInitialCsmago<=0.0) {
558 errFatal("LbmFsgrSolver::initLevelOmegas","Csmago-LES = 0 not supported for optimized 3D version...",SIMWORLD_INITERROR);
563 LbmFloat fineCsmago = mInitialCsmago;
564 LbmFloat coarseCsmago = mInitialCsmago;
565 LbmFloat maxFineCsmago1 = 0.026;
566 LbmFloat maxCoarseCsmago1 = 0.029; // try stabilizing
567 LbmFloat maxFineCsmago2 = 0.028;
568 LbmFloat maxCoarseCsmago2 = 0.032; // try stabilizing some more
569 if((mMaxRefine==1)&&(mInitialCsmago<maxFineCsmago1)) {
570 fineCsmago = maxFineCsmago1;
571 coarseCsmago = maxCoarseCsmago1;
573 if((mMaxRefine>1)&&(mInitialCsmago<maxFineCsmago2)) {
574 fineCsmago = maxFineCsmago2;
575 coarseCsmago = maxCoarseCsmago2;
579 // use Tau instead of Omega for calculations
582 mLevel[i].omega = mOmega;
583 mLevel[i].timestep = mpParam->getTimestep();
584 mLevel[i].lcsmago = fineCsmago; //CSMAGO_INITIAL;
585 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
586 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
589 // init all sub levels
590 for(int i=mMaxRefine-1; i>=0; i--) {
591 //mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5;
592 double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5;
594 mLevel[i].omega = (LbmFloat)nomega;
595 mLevel[i].timestep = 2.0 * mLevel[i+1].timestep;
596 mLevel[i].lcsmago = coarseCsmago;
597 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
598 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
602 mLevel[ mMaxRefine ].gravity = mGravity / mLevel[ mMaxRefine ].omega;
603 for(int i=mMaxRefine-1; i>=0; i--) {
604 // should be the same on all levels...
606 mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega;
610 mLastGravity = mGravity;
611 // debug? invalidate old values...
615 for(int i=0; i<=mMaxRefine; i++) {
617 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
618 <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", "
619 <<" cmsagp:"<<mLevel[i].lcsmago<<", "
620 << " ss"<<mLevel[i].timestep<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize );
623 debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" "
624 <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5);
629 mDfScaleUp = (mLevel[0 ].timestep/mLevel[0+1].timestep)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu
630 mDfScaleDown = (mLevel[0+1].timestep/mLevel[0 ].timestep)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu
635 /******************************************************************************
636 * Init Solver (values should be read from config file)
637 *****************************************************************************/
639 /*! finish the init with config file values (allocate arrays...) */
640 bool LbmFsgrSolver::initializeSolverMemory()
642 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<mInitDone<<" "<<(void*)this,1);
646 mSizex *= mCppfStage;
647 mSizey *= mCppfStage;
648 mSizez *= mCppfStage;
650 if(mFsSurfGenSetting==-1) {
653 fssgNormal | fssgNoNorth | fssgNoSouth | fssgNoEast |
654 fssgNoWest | fssgNoTop | fssgNoBottom | fssgNoObs ;
657 // size inits to force cubic cells and mult4 level dimensions
658 // and make sure we dont allocate too much...
663 double sizeReduction = 1.0;
664 double memEstFromFunc = -1.0;
665 double memEstFine = -1.0;
666 string memreqStr("");
667 bool firstMInit = true;
671 initGridSizes( mSizex, mSizey, mSizez,
672 mvGeoStart, mvGeoEnd, mMaxRefine, PARALLEL);
675 #if LBM_INCLUDE_TESTSOLVERS==1
679 #endif // LBM_INCLUDE_TESTSOLVERS==1
682 calculateMemreqEstimate( mSizex, mSizey, mSizez,
683 mMaxRefine, mFarFieldSize, &memEstFromFunc, &memEstFine, &memreqStr );
686 string memLimStr("-");
687 if(sizeof(void*)==4) {
688 // 32bit system, limit to 2GB
689 memLimit = 2.0* 1024.0*1024.0*1024.0;
690 memLimStr = string("2GB");
692 // 64bit, just take 16GB as limit for now...
693 memLimit = 16.0* 1024.0*1024.0*1024.0;
694 memLimStr = string("16GB");
697 // restrict max. chunk of 1 mem block to 1GB for windos
698 bool memBlockAllocProblem = false;
699 double maxDefaultMemChunk = 2.*1024.*1024.*1024.;
700 //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG
702 double maxWinMemChunk = 1100.*1024.*1024.;
703 if(memEstFine> maxWinMemChunk) {
704 memBlockAllocProblem = true;
708 double maxMacMemChunk = 1200.*1024.*1024.;
709 if(memEstFine> maxMacMemChunk) {
710 memBlockAllocProblem = true;
713 if(sizeof(void*)==4 && memEstFine>maxDefaultMemChunk) {
714 // max memory chunk for 32bit systems 2gig
715 memBlockAllocProblem = true;
718 if(memEstFromFunc>memLimit || memBlockAllocProblem) {
719 sizeReduction *= 0.9;
720 mSizex = (int)(orgSx * sizeReduction);
721 mSizey = (int)(orgSy * sizeReduction);
722 mSizez = (int)(orgSz * sizeReduction);
723 debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<
724 //memEstFromFunc<<"/"<<memLimit<<", "<<
725 //memEstFine<<"/"<<maxWinMemChunk<<", "<<
726 memreqStr<<"/"<<memLimStr<<", "<<
727 "retrying: "<<PRINT_VEC(mSizex,mSizey,mSizez)<<" org:"<<PRINT_VEC(orgSx,orgSy,orgSz)
734 mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)mSizex;
735 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<mSizex<<" Y:"<<mSizey<<" Z:"<<mSizez<<
736 ", Domain: "<<mvGeoStart<<":"<<mvGeoEnd<<", "<<(mvGeoEnd-mvGeoStart)<<
737 ", PointerSize: "<< sizeof(void*) << ", IntSize: "<< sizeof(int) <<
738 ", est. Mem.Req.: "<<memreqStr ,2);
739 mpParam->setSize(mSizex, mSizey, mSizez);
740 if((minitTries>1)&&(glob_mpnum)) { errMsg("LbmFsgrSolver::initialize","Warning!!!!!!!!!!!!!!! Original gridsize changed........."); }
742 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: "
743 <<"LBM_EPSILON="<<LBM_EPSILON <<" "
744 <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" "
745 <<"OPT3D="<<OPT3D <<" "
746 <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" "
747 <<"MASS_INVALID="<<MASS_INVALID <<" "
748 <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" "
749 <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" "
750 <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" "
751 <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" "
752 <<"USE_LES="<<USE_LES <<" "
755 // perform 2D corrections...
756 if(LBMDIM == 2) mSizez = 1;
758 mpParam->setSimulationMaxSpeed(0.0);
759 if(mFVHeight>0.0) mpParam->setFluidVolumeHeight(mFVHeight);
760 mpParam->setTadapLevels( mMaxRefine+1 );
762 if(mForceTadapRefine>mMaxRefine) {
763 mpParam->setTadapLevels( mForceTadapRefine+1 );
764 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<<mForceTadapRefine, 6);
767 if(!mpParam->calculateAllMissingValues(mSimulationTime, false)) {
768 errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR);
774 for(int i=0; i<=mMaxRefine; i++) {
776 mLevel[i].nodeSize = 0.0;
777 mLevel[i].simCellSize = 0.0;
778 mLevel[i].omega = 0.0;
779 mLevel[i].time = 0.0;
780 mLevel[i].timestep = 1.0;
781 mLevel[i].gravity = LbmVec(0.0);
782 mLevel[i].mprsCells[0] = NULL;
783 mLevel[i].mprsCells[1] = NULL;
784 mLevel[i].mprsFlags[0] = NULL;
785 mLevel[i].mprsFlags[1] = NULL;
787 mLevel[i].avgOmega = 0.0;
788 mLevel[i].avgOmegaCnt = 0.0;
792 mLevel[mMaxRefine].lSizex = mSizex;
793 mLevel[mMaxRefine].lSizey = mSizey;
794 mLevel[mMaxRefine].lSizez = mSizez;
795 for(int i=mMaxRefine-1; i>=0; i--) {
796 mLevel[i].lSizex = mLevel[i+1].lSizex/2;
797 mLevel[i].lSizey = mLevel[i+1].lSizey/2;
798 mLevel[i].lSizez = mLevel[i+1].lSizez/2;
802 if(sizeof(CellFlagType) != CellFlagTypeSize) {
803 errFatal("LbmFsgrSolver::initialize","Fatal Error: CellFlagType has wrong size! Is:"<<sizeof(CellFlagType)<<", should be:"<<CellFlagTypeSize, SIMWORLD_GENERICERROR);
807 double ownMemCheck = 0.0;
808 mLevel[ mMaxRefine ].nodeSize = ((mvGeoEnd[0]-mvGeoStart[0]) / (LbmFloat)(mSizex));
809 mLevel[ mMaxRefine ].simCellSize = mpParam->getCellSize();
810 mLevel[ mMaxRefine ].lcellfactor = 1.0;
811 LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum);
814 mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ];
815 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ];
816 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
817 #else // COMPRESSGRIDS==0
818 LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2);
819 // D int tmp = ( (rcellSize +compressOffset +4)/(1024*1024) )*4;
820 // D printf("Debug MEMMMM excee: %d\n", tmp);
821 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ];
822 mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset;
823 ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4);
824 #endif // COMPRESSGRIDS==0
826 if(!mLevel[ mMaxRefine ].mprsCells[1] || !mLevel[ mMaxRefine ].mprsCells[0]) {
827 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (1)! Aborting...",SIMWORLD_INITERROR);
832 mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
833 mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
834 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
835 if(!mLevel[ mMaxRefine ].mprsFlags[1] || !mLevel[ mMaxRefine ].mprsFlags[0]) {
836 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (2)! Aborting...",SIMWORLD_INITERROR);
839 delete[] mLevel[ mMaxRefine ].mprsCells[0];
840 delete[] mLevel[ mMaxRefine ].mprsCells[1];
841 #else // COMPRESSGRIDS==0
842 delete[] mLevel[ mMaxRefine ].mprsCells[1];
843 #endif // COMPRESSGRIDS==0
847 LbmFloat lcfdimFac = 8.0;
848 if(LBMDIM==2) lcfdimFac = 4.0;
849 for(int i=mMaxRefine-1; i>=0; i--) {
850 mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize;
851 mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize;
852 mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac;
854 if(LBMDIM==2){ mLevel[i].lSizez = 1; } // 2D
855 rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum);
856 mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ];
857 mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ];
858 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4);
859 mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ];
860 mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ];
861 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
864 // isosurface memory, use orig res values
865 if(mFarFieldSize>0.) {
866 ownMemCheck += (double)( (3*sizeof(int)+sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
868 // ignore 3 int slices...
869 ownMemCheck += (double)( ( sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
874 if(ABS(1.0-ownMemCheck/memEstFromFunc)>0.01) {
875 errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off! real:"<<ownMemCheck<<" vs. estimate:"<<memEstFromFunc );
877 #endif // ELBEEM_PLUGIN!=1
879 // init sizes for _all_ levels
880 for(int i=mMaxRefine; i>=0; i--) {
881 mLevel[i].lOffsx = mLevel[i].lSizex;
882 mLevel[i].lOffsy = mLevel[i].lOffsx*mLevel[i].lSizey;
883 mLevel[i].lOffsz = mLevel[i].lOffsy*mLevel[i].lSizez;
884 mLevel[i].setCurr = 0;
885 mLevel[i].setOther = 1;
886 mLevel[i].lsteps = 0;
887 mLevel[i].lmass = 0.0;
888 mLevel[i].lvolume = 0.0;
891 // calc omega, force for all levels
893 mMinTimestep = mpParam->getTimestep();
894 mMaxTimestep = mpParam->getTimestep();
897 mpIso->setIsolevel( mIsoValue );
898 #if LBM_INCLUDE_TESTSOLVERS==1
900 mpTest->setMaterialName( mpIso->getMaterialName() );
903 if(mpTest->mFarfMode>0) { // 3d off
904 mpTest->setIsolevel(-100.0);
906 mpTest->setIsolevel( mIsoValue );
909 #endif // LBM_INCLUDE_TESTSOLVERS!=1
910 // approximate feature size with mesh resolution
911 float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5;
912 // smooth vars defined in solver_interface, set by simulation object
913 // reset for invalid values...
914 if((mSmoothSurface<0.)||(mSmoothSurface>50.)) mSmoothSurface = 1.;
915 if((mSmoothNormals<0.)||(mSmoothNormals>50.)) mSmoothNormals = 1.;
916 mpIso->setSmoothSurface( mSmoothSurface * featureSize );
917 mpIso->setSmoothNormals( mSmoothNormals * featureSize );
919 // init iso weight values mIsoWeightMethod
922 for(int ak=-1;ak<=1;ak++)
923 for(int aj=-1;aj<=1;aj++)
924 for(int ai=-1;ai<=1;ai++) {
925 switch(mIsoWeightMethod) {
926 case 1: // light smoothing
927 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) );
929 case 2: // very light smoothing
930 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) );
931 mIsoWeight[wcnt] *= mIsoWeight[wcnt];
933 case 3: // no smoothing
934 if(ai==0 && aj==0 && ak==0) mIsoWeight[wcnt] = 1.0;
935 else mIsoWeight[wcnt] = 0.0;
937 default: // strong smoothing (=0)
938 mIsoWeight[wcnt] = 1.0;
941 totw += mIsoWeight[wcnt];
944 for(int i=0; i<27; i++) mIsoWeight[i] /= totw;
946 LbmVec isostart = vec2L(mvGeoStart);
947 LbmVec isoend = vec2L(mvGeoEnd);
948 int twodOff = 0; // 2d slices
951 sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
952 se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
957 int isosx = mSizex+2;
958 int isosy = mSizey+2;
959 int isosz = mSizez+2+twodOff;
962 #if LBM_INCLUDE_TESTSOLVERS==1
963 //if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) {
964 if( (mMpNum>0) && (mMpIndex==0) ) {
966 // restore original value for node0
967 isosx = mOrgSizeX + 2;
968 isostart[0] = mOrgStartX;
969 isoend[0] = mOrgEndX;
971 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMin.mSrcx,mpTest->mGCMin.mSrcy,mpTest->mGCMin.mSrcz)<<" dst"
972 << PRINT_VEC(mpTest->mGCMin.mDstx,mpTest->mGCMin.mDsty,mpTest->mGCMin.mDstz)<<" consize"
973 << PRINT_VEC(mpTest->mGCMin.mConSizex,mpTest->mGCMin.mConSizey,mpTest->mGCMin.mConSizez)<<" ");
974 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMax.mSrcx,mpTest->mGCMax.mSrcy,mpTest->mGCMax.mSrcz)<<" dst"
975 << PRINT_VEC(mpTest->mGCMax.mDstx,mpTest->mGCMax.mDsty,mpTest->mGCMax.mDstz)<<" consize"
976 << PRINT_VEC(mpTest->mGCMax.mConSizex,mpTest->mGCMax.mConSizey,mpTest->mGCMax.mConSizez)<<" ");
977 #endif // LBM_INCLUDE_TESTSOLVERS==1
979 errMsg(" SETISO ", "iso "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5)<<" "<<(LbmFloat)(mSizex+1.0) );
980 errMsg("LbmFsgrSolver::initialize", "MPT: geo "<< mvGeoStart<<","<<mvGeoEnd<<
981 " grid:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<",iso:"<< PRINT_VEC(isosx,isosy,isosz) );
982 mpIso->setStart( vec2G(isostart) );
983 mpIso->setEnd( vec2G(isoend) );
984 LbmVec isodist = isoend-isostart;
986 int isosubs = mIsoSubdivs;
987 if(mFarFieldSize>1.) {
988 errMsg("LbmFsgrSolver::initialize","Warning - resetting isosubdivs, using fulledge!");
990 mpIso->setUseFulledgeArrays(true);
992 mpIso->setSubdivs(isosubs);
994 mpIso->initializeIsosurface( isosx,isosy,isosz, vec2G(isodist) );
997 for(int ak=0;ak<isosz;ak++)
998 for(int aj=0;aj<isosy;aj++)
999 for(int ai=0;ai<isosx;ai++) { *mpIso->getData(ai,aj,ak) = 0.0; }
1002 /* init array (set all invalid first) */
1004 for(int lev=0; lev<=mMaxRefine; lev++) {
1005 FSGR_FORIJK_BOUNDS(lev) {
1006 RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage
1008 initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0);
1010 initEmptyCell(lev, i,j,k, CFFluid, 1.0, 1.0);
1017 if(mOutputSurfacePreview) {
1018 errMsg("LbmFsgrSolver::init","No preview in 2D allowed!");
1019 mOutputSurfacePreview = 0; }
1021 if((glob_mpactive) && (glob_mpindex>0)) {
1022 mOutputSurfacePreview = 0;
1026 if(mOutputSurfacePreview) {
1027 errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0");
1028 mOutputSurfacePreview = 0; }
1029 #endif // LBM_USE_GUI==1
1030 if(mOutputSurfacePreview) {
1031 // same as normal one, but use reduced size
1032 mpPreviewSurface = new IsoSurface( mIsoValue );
1033 mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() );
1034 mpPreviewSurface->setIsolevel( mIsoValue );
1035 // usually dont display for rendering
1036 mpPreviewSurface->setVisible( false );
1038 mpPreviewSurface->setStart( vec2G(isostart) );
1039 mpPreviewSurface->setEnd( vec2G(isoend) );
1040 LbmVec pisodist = isoend-isostart;
1041 LbmFloat pfac = mPreviewFactor;
1042 mpPreviewSurface->initializeIsosurface( (int)(pfac*mSizex)+2, (int)(pfac*mSizey)+2, (int)(pfac*mSizez)+2, vec2G(pisodist) );
1043 //mpPreviewSurface->setName( getName() + "preview" );
1044 mpPreviewSurface->setName( "preview" );
1046 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*mSizex)<<","<<(pfac*mSizey)<<","<<(pfac*mSizez)<<" enabled",10);
1050 mAvgNumUsedCells = 0;
1055 /*! init solver arrays */
1056 bool LbmFsgrSolver::initializeSolverGrids() {
1057 /* init boundaries */
1058 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10);
1059 // init obstacles, and reinit time step size
1060 initGeometryFlags();
1061 mLastSimTime = -1.0;
1062 // TODO check for invalid cells? nitGenericTestCases();
1064 // new - init noslip 1 everywhere...
1065 // half fill boundary cells?
1067 CellFlagType domainBoundType = CFInvalid;
1068 // TODO use normal object types instad...
1069 if(mDomainBound.find(string("free")) != string::npos) {
1070 domainBoundType = CFBnd | CFBndFreeslip;
1071 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<mDomainBound,10);
1072 } else if(mDomainBound.find(string("part")) != string::npos) {
1073 domainBoundType = CFBnd | CFBndPartslip; // part slip type
1074 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10);
1076 domainBoundType = CFBnd | CFBndNoslip;
1077 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10);
1080 // use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips)
1081 int domainobj = (int)(mpGiObjects->size());
1082 domainBoundType |= (domainobj<<24);
1083 //for(int i=0; i<(int)(domainobj+0); i++) {
1084 //errMsg("GEOIN","i"<<i<<" "<<(*mpGiObjects)[i]->getName());
1085 //if((*mpGiObjects)[i] == mpIso) { //check...
1088 //errMsg("GEOIN"," dm "<<(domainBoundType>>24));
1090 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1091 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1092 initEmptyCell(mMaxRefine, i,0,k, domainBoundType, 0.0, BND_FILL);
1093 initEmptyCell(mMaxRefine, i,mLevel[mMaxRefine].lSizey-1,k, domainBoundType, 0.0, BND_FILL);
1096 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1097 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1098 initEmptyCell(mMaxRefine, 0,j,k, domainBoundType, 0.0, BND_FILL);
1099 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-1,j,k, domainBoundType, 0.0, BND_FILL);
1101 //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL);
1106 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++)
1107 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1108 initEmptyCell(mMaxRefine, i,j,0, domainBoundType, 0.0, BND_FILL);
1109 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-1, domainBoundType, 0.0, BND_FILL);
1113 // TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
1114 /*for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1115 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1116 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL);
1118 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1119 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1120 initEmptyCell(mMaxRefine, i,1,k, domainBoundType, 0.0, BND_FILL);
1124 /*for(int ii=0; ii<(int)po w_change?(2.0,mMaxRefine)-1; ii++) {
1125 errMsg("BNDTESTSYMM","set "<<mLevel[mMaxRefine].lSizex-2-ii );
1126 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++)
1127 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
1128 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2-ii,j,k, domainBoundType, 0.0, BND_FILL); // SYMM!? 2D?
1130 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++)
1131 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
1132 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-2-ii, domainBoundType, 0.0, BND_FILL); // SYMM!? 3D?
1135 // Symmetry tests */
1137 #if LBM_INCLUDE_TESTSOLVERS==1
1138 if(( strstr( this->getName().c_str(), "vorttfluid" ) != NULL) && (LBMDIM==2)) {
1139 errMsg("VORTT","init");
1140 int level=mMaxRefine;
1141 int cx = mLevel[level].lSizex/2;
1142 int cyo = mLevel[level].lSizey/2;
1143 int sx = mLevel[level].lSizex/8;
1144 int sy = mLevel[level].lSizey/8;
1146 LbmFloat rhomass = 1.;
1147 LbmFloat uFactor = 0.15;
1148 LbmFloat vdist = 1.0;
1150 int cy1=cyo-(int)(vdist*sy);
1151 int cy2=cyo+(int)(vdist*sy);
1153 //for(int j=cy-sy;j<cy+sy;j++) for(int i=cx-sx;i<cx+sx;i++) {
1154 for(int j=1;j<mLevel[level].lSizey-1;j++)
1155 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1156 LbmFloat d1 = norm(LbmVec(cx,cy1,0.)-LbmVec(i,j,0));
1157 LbmFloat d2 = norm(LbmVec(cx,cy2,0.)-LbmVec(i,j,0));
1158 bool in1 = (d1<=(LbmFloat)(sx));
1159 bool in2 = (d2<=(LbmFloat)(sx));
1161 LbmVec v1 = getNormalized( cross( LbmVec(cx,cy1,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor;
1162 LbmVec v2 = getNormalized( cross( LbmVec(cx,cy2,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor;
1163 LbmFloat w1=1., w2=1.;
1164 if(!in1) w1=(LbmFloat)(sx)/(1.5*d1);
1165 if(!in2) w2=(LbmFloat)(sx)/(1.5*d2);
1166 if(!in1) w1=0.; if(!in2) w2=0.; // sharp falloff
1169 initVelocityCell(level, i,j,0, CFFluid, rho, rhomass, uvec );
1170 //errMsg("VORTT","init uvec"<<uvec);
1174 #endif // LBM_INCLUDE_TESTSOLVERS==1
1176 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal1, causing panic, aborting..."); return false; }
1178 // prepare interface cells
1180 initStandingFluidGradient();
1182 // perform first step to init initial mass
1185 FSGR_FORIJK1(mMaxRefine) {
1186 if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid) {
1187 LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0);
1188 FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); }
1189 mInitialMass += fluidRho;
1191 } else if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) {
1192 mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass);
1196 mCurrentVolume = mCurrentMass = mInitialMass;
1198 ParamVec cspv = mpParam->calculateCellSize();
1199 if(LBMDIM==2) cspv[2] = 1.0;
1201 double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0;
1202 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<<mInitialMass<<" normalized:"<<nrmMass, 3);
1203 mInitialMass = 0.0; // reset, and use actual value after first step
1205 //mStartSymm = false;
1206 #if ELBEEM_PLUGIN!=1
1207 if((LBMDIM==2)&&(mSizex<200)) {
1208 if(!checkSymmetry("init")) {
1209 errMsg("LbmFsgrSolver::initialize","Unsymmetric init...");
1211 errMsg("LbmFsgrSolver::initialize","Symmetric init!");
1214 #endif // ELBEEM_PLUGIN!=1
1219 /*! prepare actual simulation start, setup viz etc */
1220 bool LbmFsgrSolver::initializeSolverPostinit() {
1222 myTime_t fsgrtstart = getTime();
1223 for(int lev=mMaxRefine-1; lev>=0; lev--) {
1224 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<<lev<<".",8);
1226 coarseRestrictFromFine(lev);
1228 coarseRestrictFromFine(lev);
1231 myTime_t fsgrtend = getTime();
1232 if(!mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); }
1233 mNumFsgrChanges = 0;
1235 for(int l=0; l<cDirNum; l++) {
1236 LbmFloat area = 0.5 * 0.5 *0.5;
1237 if(LBMDIM==2) area = 0.5 * 0.5;
1239 if(dfVecX[l]!=0) area *= 0.5;
1240 if(dfVecY[l]!=0) area *= 0.5;
1241 if(dfVecZ[l]!=0) area *= 0.5;
1242 mFsgrCellArea[l] = area;
1245 // make sure both sets are ok
1246 // copy from other to curr
1247 for(int lev=0; lev<=mMaxRefine; lev++) {
1248 FSGR_FORIJK_BOUNDS(lev) {
1249 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr);
1250 } } // first copy flags */
1253 // old mpPreviewSurface init
1254 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal2, causing panic, aborting..."); return false; }
1255 // make sure fill fracs are right for first surface generation
1259 mpIso->setParticles(mpParticles, mPartDropMassSub);
1260 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Iso Settings, subdivs="<<mpIso->getSubdivs()<<", partsize="<<mPartDropMassSub, 9);
1261 prepareVisualization();
1262 // copy again for stats counting
1263 for(int lev=0; lev<=mMaxRefine; lev++) {
1264 FSGR_FORIJK_BOUNDS(lev) {
1265 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr);
1266 } } // first copy flags */
1269 // now really done...
1270 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"SurfaceGen: SmsOrg("<<mSmoothSurface<<","<<mSmoothNormals<< /*","<<featureSize<<*/ "), Iso("<<mpIso->getSmoothSurface()<<","<<mpIso->getSmoothNormals()<<") ",10);
1271 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init done ... ",10);
1274 #if LBM_INCLUDE_CONTROL==1
1276 #endif // LBM_INCLUDE_CONTROL==1
1278 #if LBM_INCLUDE_TESTSOLVERS==1
1280 #endif // ELBEEM_PLUGIN!=1
1281 // not inited? dont use...
1282 if(mCutoff<0) mCutoff=0;
1290 // macros for mov obj init
1293 #define POS2GRID_CHECK(vec,n) \
1295 int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \
1296 if(k!=0) continue; \
1297 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \
1298 if(i<=0) continue; \
1299 if(i>=mLevel[level].lSizex-1) continue; \
1300 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \
1301 if(j<=0) continue; \
1302 if(j>=mLevel[level].lSizey-1) continue; \
1304 #else // LBMDIM -> 3
1305 #define POS2GRID_CHECK(vec,n) \
1307 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \
1308 if(i<=0) continue; \
1309 if(i>=mLevel[level].lSizex-1) continue; \
1310 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \
1311 if(j<=0) continue; \
1312 if(j>=mLevel[level].lSizey-1) continue; \
1313 const int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \
1314 if(k<=0) continue; \
1315 if(k>=mLevel[level].lSizez-1) continue; \
1319 // calculate object velocity from vert arrays in objvel vec
1320 #define OBJVEL_CALC \
1321 LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { \
1322 const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; \
1323 USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); \
1324 if(usqr>maxusqr) { \
1325 /* cutoff at maxVelVal */ \
1326 for(int jj=0; jj<3; jj++) { \
1327 if(objvel[jj]>0.) objvel[jj] = maxVelVal; \
1328 if(objvel[jj]<0.) objvel[jj] = -maxVelVal; \
1331 if(ntype&(CFBndFreeslip)) { \
1332 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \
1333 const LbmVec oldov=objvel; /*DEBUG*/ \
1334 objvel = vec2L((*pNormals)[n]) *dp; \
1335 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \
1337 else if(ntype&(CFBndPartslip)) { \
1338 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \
1339 const LbmVec oldov=objvel; /*DEBUG*/ \
1340 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \
1341 const LbmFloat partv = mObjectPartslips[OId]; \
1342 /*errMsg("PARTSLIP_DEBUG","l="<<l<<" ccel="<<RAC(ccel, dfInv[l] )<<" partv="<<partv<<",id="<<(int)(mnbf>>24)<<" newval="<<newval ); / part slip debug */ \
1343 /* m[l] = (RAC(ccel, dfInv[l] ) ) * partv + newval * (1.-partv); part slip */ \
1344 objvel = objvel*partv + vec2L((*pNormals)[n]) *dp*(1.-partv); \
1350 /*****************************************************************************/
1351 //! init moving obstacles for next sim step sim
1352 /*****************************************************************************/
1353 void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
1354 myTime_t monstart = getTime();
1357 const int level = mMaxRefine;
1358 const int workSet = mLevel[level].setCurr;
1359 const int otherSet = mLevel[level].setOther;
1360 LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime!
1361 // for debugging - check targetTime check during DEFAULT STREAM
1362 LbmFloat targetTime = mSimulationTime + mpParam->getTimestep();
1363 if(mLastSimTime == targetTime) {
1364 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"Called for same time! (t="<<mSimulationTime<<" , targett="<<targetTime<<")", 1);
1367 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime,10);
1368 //if(mSimulationTime!=mLastSimTime) errMsg("LbmFsgrSolver::initMovingObstacles","time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime);
1370 const LbmFloat maxVelVal = 0.1666;
1371 const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
1373 LbmFloat rhomass = 0.0;
1374 CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs!
1375 CellFlagType ntype = CFInvalid;
1376 // WARNING - copied from geo init!
1377 int numobjs = (int)(mpGiObjects->size());
1378 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
1379 // 2d display as rectangles
1380 ntlVec3Gfx iniPos(0.0);
1383 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))-(dvec*0.0);
1385 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0);
1388 if( (int)mObjectMassMovnd.size() < numobjs) {
1389 for(int i=mObjectMassMovnd.size(); i<numobjs; i++) {
1390 mObjectMassMovnd.push_back(0.);
1395 int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0;
1397 for(int OId=0; OId<numobjs; OId++) {
1398 ntlGeometryObject *obj = (*mpGiObjects)[OId];
1400 if(obj->getGeoInitId() != mLbmInitId) skip=true;
1401 if( (!staticInit) && (!obj->getIsAnimated()) ) skip=true;
1402 if( ( staticInit) && ( obj->getIsAnimated()) ) skip=true;
1404 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" skip:"<<skip<<", static:"<<staticInit<<" anim:"<<obj->getIsAnimated()<<" gid:"<<obj->getGeoInitId()<<" simgid:"<<mLbmInitId, 10);
1406 if( (obj->getGeoInitType()&FGI_ALLBOUNDS) ||
1407 (obj->getGeoInitType()&FGI_FLUID) && staticInit ) {
1409 otype = ntype = CFInvalid;
1410 switch(obj->getGeoInitType()) {
1411 /* case FGI_BNDPART: // old, use noslip for moving part/free objs
1414 errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() );
1415 otype = ntype = CFBnd|CFBndNoslip;
1417 if(obj->getGeoInitType()==FGI_BNDPART) otype = ntype = CFBnd|CFBndPartslip;
1418 if(obj->getGeoInitType()==FGI_BNDFREE) otype = ntype = CFBnd|CFBndFreeslip;
1422 case FGI_BNDPART: rhomass = BND_FILL;
1423 otype = ntype = CFBnd|CFBndPartslip|(OId<<24);
1425 case FGI_BNDFREE: rhomass = BND_FILL;
1426 otype = ntype = CFBnd|CFBndFreeslip|(OId<<24);
1429 case FGI_BNDNO: rhomass = BND_FILL;
1430 otype = ntype = CFBnd|CFBndNoslip|(OId<<24);
1433 otype = ntype = CFFluid;
1435 case FGI_MBNDINFLOW:
1436 otype = ntype = CFMbndInflow;
1438 case FGI_MBNDOUTFLOW:
1439 otype = ntype = CFMbndOutflow;
1442 int wasActive = ((obj->getGeoActive(sourceTime)>0.)? 1:0);
1443 int active = ((obj->getGeoActive(targetTime)>0.)? 1:0);
1444 //errMsg("GEOACTT"," obj "<<obj->getName()<<" a:"<<active<<","<<wasActive<<" s"<<sourceTime<<" t"<<targetTime <<" v"<<mObjectSpeeds[OId] );
1445 // skip inactive in/out flows
1446 if(ntype==CFInvalid){ errMsg("LbmFsgrSolver::initMovingObstacles","Invalid obj type "<<obj->getGeoInitType()); continue; }
1447 if((!active) && (otype&(CFMbndOutflow|CFMbndInflow)) ) continue;
1449 // copied from recalculateObjectSpeeds
1450 mObjectSpeeds[OId] = vec2L(mpParam->calculateLattVelocityFromRw( vec2P( (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) )));
1451 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 );
1453 //vector<ntlVec3Gfx> tNormals;
1454 vector<ntlVec3Gfx> *pNormals = NULL;
1455 mMOINormals.clear();
1456 if(ntype&(CFBndFreeslip|CFBndPartslip)) { pNormals = &mMOINormals; }
1458 mMOIVertices.clear();
1459 if(obj->getMeshAnimated()) {
1460 // do two full update
1461 // TODO tNormals handling!?
1462 mMOIVerticesOld.clear();
1463 obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, pNormals, mLevel[mMaxRefine].nodeSize, mvGeoStart, mvGeoEnd);
1464 monTrafo += mMOIVerticesOld.size();
1465 obj->applyTransformation(sourceTime, &mMOIVerticesOld,pNormals, 0, mMOIVerticesOld.size(), false );
1466 monTrafo += mMOIVertices.size();
1467 obj->applyTransformation(targetTime, &mMOIVertices,NULL /* no old normals needed */, 0, mMOIVertices.size(), false );
1469 // only do transform update
1470 obj->getMovingPoints(mMOIVertices,pNormals);
1471 mMOIVerticesOld = mMOIVertices;
1472 // WARNING - assumes mSimulationTime is global!?
1473 obj->applyTransformation(targetTime, &mMOIVertices,pNormals, 0, mMOIVertices.size(), false );
1474 monTrafo += mMOIVertices.size();
1476 // correct flags from last position, but extrapolate
1477 // velocity to next timestep
1478 obj->applyTransformation(sourceTime, &mMOIVerticesOld, NULL /* no old normals needed */, 0, mMOIVerticesOld.size(), false );
1479 monTrafo += mMOIVerticesOld.size();
1485 // check if object is moving at all
1486 if(obj->getIsAnimated()) {
1487 ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime);
1489 if(normNoSqrt(objMaxVel)>0.0) { ntype |= CFBndMoving; }
1490 // get old type - CHECK FIXME , timestep could have changed - cause trouble?
1491 ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - mpParam->getTimestep(),sourceTime);
1492 if(normNoSqrt(oldobjMaxVel)>0.0) { otype |= CFBndMoving; }
1494 if(obj->getMeshAnimated()) { ntype |= CFBndMoving; otype |= CFBndMoving; }
1495 CellFlagType rflagnb[27];
1496 LbmFloat massCheck = 0.;
1498 bool fillCells = (mObjectMassMovnd[OId]<=-1.);
1499 LbmFloat impactCorrFactor = obj->getGeoImpactFactor(targetTime);
1502 // first pass - set new obs. cells
1504 for(size_t n=0; n<mMOIVertices.size(); n++) {
1505 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK);
1506 POS2GRID_CHECK(mMOIVertices,n);
1507 //{ errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<", t="<<targetTime); }
1508 if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue;
1512 if(RFLAG(level, i,j,k, workSet)&(CFFluid)) {
1513 FORDF0 { massCheck -= QCELL(level, i,j,k, workSet, l); }
1516 else if(RFLAG(level, i,j,k, workSet)&(CFInter)) {
1517 massCheck -= QCELL(level, i,j,k, workSet, dMass);
1521 RFLAG(level, i,j,k, workSet) = ntype;
1523 //CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l);
1524 rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l);
1525 if(rflagnb[l]&(CFFluid|CFInter)) {
1526 rflagnb[l] &= (~CFNoBndFluid); // remove CFNoBndFluid flag
1527 RFLAG_NB(level, i,j,k,workSet,l) &= rflagnb[l];
1530 LbmFloat *dstCell = RACPNT(level, i,j,k,workSet);
1531 RAC(dstCell,0) = 0.0;
1532 if(ntype&CFBndMoving) {
1535 // compute fluid acceleration
1537 if(rflagnb[l]&(CFFluid|CFInter)) {
1538 const LbmFloat ux = dfDvecX[l]*objvel[0];
1539 const LbmFloat uy = dfDvecY[l]*objvel[1];
1540 const LbmFloat uz = dfDvecZ[l]*objvel[2];
1542 LbmFloat factor = 2. * dfLength[l] * 3.0 * (ux+uy+uz); //
1543 if(ntype&(CFBndFreeslip|CFBndPartslip)) {
1544 // missing, diag mass checks...
1545 //if(l<=LBMDIM*2) factor *= 1.4142;
1546 factor *= 2.0; // TODO, optimize
1548 factor *= 1.2; // TODO, optimize
1550 factor *= impactCorrFactor; // use manual tweaking channel
1551 RAC(dstCell,l) = factor;
1552 massCheck += factor;
1554 RAC(dstCell,l) = 0.;
1558 #if NEWDIRVELMOTEST==1
1559 FORDF1 { RAC(dstCell,l) = 0.; }
1560 RAC(dstCell,dMass) = objvel[0];
1561 RAC(dstCell,dFfrac) = objvel[1];
1562 RAC(dstCell,dC) = objvel[2];
1563 #endif // NEWDIRVELMOTEST==1
1565 FORDF1 { RAC(dstCell,l) = 0.0; }
1567 RAC(dstCell, dFlux) = targetTime;
1568 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" dflt="<<RAC(dstCell, dFlux) );
1571 } // bnd, is active?
1573 // second pass, remove old ones
1574 // warning - initEmptyCell et. al dont overwrite OId or persist flags...
1576 for(size_t n=0; n<mMOIVerticesOld.size(); n++) {
1577 POS2GRID_CHECK(mMOIVerticesOld,n);
1579 if((RFLAG(level, i,j,k, workSet) == otype) &&
1580 (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) {
1583 // TODO: optimize for OPT3D==0
1585 //rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l);
1586 rflagnb[l] = RFLAG_NB(level, i,j,k,otherSet,l); // test use other set to not have loop dependance
1587 nbored |= rflagnb[l];
1589 CellFlagType settype = CFInvalid;
1590 if(nbored&CFFluid) {
1591 settype = CFInter|CFNoInterpolSrc;
1593 if(!fillCells) rhomass = 0.;
1596 if(!(nbored&CFEmpty)) { settype=CFFluid|CFNoInterpolSrc; rhomass=1.; }
1598 // new interpolate values
1599 LbmFloat avgrho = 0.0;
1600 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
1601 interpolateCellValues(level,i,j,k,workSet, avgrho,avgux,avguy,avguz);
1602 initVelocityCell(level, i,j,k, settype, avgrho, rhomass, LbmVec(avgux,avguy,avguz) );
1603 //errMsg("NMOCIT"," at "<<PRINT_IJK<<" "<<avgrho<<" "<<norm(LbmVec(avgux,avguy,avguz))<<" "<<LbmVec(avgux,avguy,avguz) );
1604 massCheck += rhomass;
1606 settype = CFEmpty; rhomass = 0.0;
1607 initEmptyCell(level, i,j,k, settype, 1., rhomass );
1615 // only compute mass transfer when init is done
1617 errMsg("initMov","dccd\n\nMassd test "<<obj->getName()<<" dccd massCheck="<<massCheck<<" massReinits"<<massReinits<<
1618 " fillCells"<<fillCells<<" massmovbnd:"<<mObjectMassMovnd[OId]<<" inim:"<<mInitialMass );
1619 mObjectMassMovnd[OId] += massCheck;
1623 else if(ntype&CFFluid){
1624 // second static init pass
1626 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" verts"<<mMOIVertices.size() ,9);
1627 CellFlagType setflflag = CFFluid; //|(OId<<24);
1628 for(size_t n=0; n<mMOIVertices.size(); n++) {
1629 POS2GRID_CHECK(mMOIVertices,n);
1630 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1631 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1632 //changeFlag(level, i,j,k, workSet, setflflag);
1633 initVelocityCell(level, i,j,k, setflflag, 1., 1., mObjectSpeeds[OId] );
1635 //else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); }
1637 } // second static inflow pass
1640 else if(ntype&CFMbndInflow){
1641 // inflow pass - add new fluid cells
1642 // this is slightly different for standing inflows,
1643 // as the fluid is forced to the desired velocity inside as
1645 const LbmFloat iniRho = 1.0;
1646 const LbmVec vel(mObjectSpeeds[OId]);
1647 const LbmFloat usqr = (vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])*1.5;
1648 USQRMAXCHECK(usqr,vel[0],vel[1],vel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
1649 //errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<mMOIVertices.size() );
1651 for(size_t n=0; n<mMOIVertices.size(); n++) {
1652 POS2GRID_CHECK(mMOIVertices,n);
1653 // TODO - also reinit interface cells !?
1654 if(RFLAG(level, i,j,k, workSet)!=CFEmpty) {
1655 // test prevent particle gen for inflow inter cells
1656 if(RFLAG(level, i,j,k, workSet)&(CFInter)) { RFLAG(level, i,j,k, workSet) &= (~CFNoBndFluid); } // remove CFNoBndFluid flag
1660 // TODO add OPT3D treatment
1661 LbmFloat *tcel = RACPNT(level, i,j,k,workSet);
1662 FORDF0 { RAC(tcel, l) = this->getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); }
1663 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho;
1664 RAC(tcel, dFlux) = FLUX_INIT;
1665 CellFlagType setFlag = CFInter;
1666 changeFlag(level, i,j,k, workSet, setFlag);
1667 mInitialMass += iniRho;
1669 // second static init pass
1671 CellFlagType set2Flag = CFMbndInflow|(OId<<24);
1672 for(size_t n=0; n<mMOIVertices.size(); n++) {
1673 POS2GRID_CHECK(mMOIVertices,n);
1674 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1675 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1676 forceChangeFlag(level, i,j,k, workSet, set2Flag);
1677 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) {
1678 forceChangeFlag(level, i,j,k, workSet,
1679 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag);
1682 } // second static inflow pass
1686 else if(ntype&CFMbndOutflow){
1687 const LbmFloat iniRho = 0.0;
1688 for(size_t n=0; n<mMOIVertices.size(); n++) {
1689 POS2GRID_CHECK(mMOIVertices,n);
1690 // FIXME check fluid/inter cells for non-static!?
1691 if(!(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter))) {
1692 if((staticInit)&&(RFLAG(level, i,j,k, workSet)==CFEmpty)) {
1693 forceChangeFlag(level, i,j,k, workSet, CFMbndOutflow); }
1697 // interface cell - might be double empty? FIXME check?
1699 // remove fluid cells, shouldnt be here anyway
1700 LbmFloat *tcel = RACPNT(level, i,j,k,workSet);
1701 LbmFloat fluidRho = RAC(tcel,0); FORDF1 { fluidRho += RAC(tcel,l); }
1702 mInitialMass -= fluidRho;
1703 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho;
1704 RAC(tcel, dFlux) = FLUX_INIT;
1705 CellFlagType setFlag = CFInter;
1706 changeFlag(level, i,j,k, workSet, setFlag);
1708 // same as ifemptied for if below
1710 emptyp.x = i; emptyp.y = j; emptyp.z = k;
1711 mListEmpty.push_back( emptyp );
1712 //calcCellsEmptied++;
1714 // second static init pass
1716 CellFlagType set2Flag = CFMbndOutflow|(OId<<24);
1717 for(size_t n=0; n<mMOIVertices.size(); n++) {
1718 POS2GRID_CHECK(mMOIVertices,n);
1719 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; }
1720 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) {
1721 forceChangeFlag(level, i,j,k, workSet, set2Flag);
1722 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) {
1723 forceChangeFlag(level, i,j,k, workSet,
1724 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag);
1727 } // second static outflow pass
1735 int workSet = mLevel[level].setCurr;
1736 FSGR_FORIJK1(level) {
1737 if( (RFLAG(level,i,j,k, workSet) & CFBndMoving) ) {
1738 if(QCELL(level, i,j,k, workSet, dFlux)!=targetTime) {
1739 errMsg("lastt"," old val!? at "<<PRINT_IJK<<" t="<<QCELL(level, i,j,k, workSet, dFlux)<<" target="<<targetTime);
1745 #undef POS2GRID_CHECK
1746 myTime_t monend = getTime();
1747 if(monend-monstart>0) debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7);
1748 mLastSimTime = targetTime;
1754 #define GETPOS(i,j,k) \
1755 ntlVec3Gfx ggpos = \
1756 ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \
1757 iniPos[1]+ dvec[1]*(gfxReal)(j), \
1758 iniPos[2]+ dvec[2]*(gfxReal)(k) ); \
1759 if((LBMDIM==2)&&(mInit2dYZ)) { SWAPYZ(ggpos); }
1761 /*****************************************************************************/
1762 /*! perform geometry init (if switched on) */
1763 /*****************************************************************************/
1764 extern int globGeoInitDebug; //solver_interface
1765 bool LbmFsgrSolver::initGeometryFlags() {
1766 int level = mMaxRefine;
1767 myTime_t geotimestart = getTime();
1768 ntlGeometryObject *pObj;
1769 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
1770 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< mLbmInitId <<") v"<<dvec,3);
1771 // WARNING - copied to movobj init!
1773 /* init object velocities, this has always to be called for init */
1779 // make sure moving obstacles are inited correctly
1780 // preinit moving obj points
1781 int numobjs = (int)(mpGiObjects->size());
1782 for(int o=0; o<numobjs; o++) {
1783 ntlGeometryObject *obj = (*mpGiObjects)[o];
1784 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9);
1786 ((obj->getGeoInitType()&FGI_ALLBOUNDS) && (obj->getIsAnimated())) ||
1787 (obj->getVolumeInit()&VOLUMEINIT_SHELL) ) {
1788 if(!obj->getMeshAnimated()) {
1789 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9);
1790 obj->initMovingPoints(mSimulationTime, mLevel[mMaxRefine].nodeSize);
1796 ntlVec3Gfx maxMovobjVelRw = getGeoMaxMovementVelocity( mSimulationTime, mpParam->getTimestep() );
1797 ntlVec3Gfx maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) );
1798 mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) );
1799 LbmFloat allowMax = mpParam->getTadapMaxSpeed(); // maximum allowed velocity
1800 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxMovobjVel <<" from mov. obj.="<<maxMovobjVelRw<<" , allowed Max="<<allowMax ,5);
1801 if(mpParam->getSimulationMaxSpeed() > allowMax) {
1802 // similar to adaptTimestep();
1803 LbmFloat nextmax = mpParam->getSimulationMaxSpeed();
1804 LbmFloat newdt = mpParam->getTimestep() * (allowMax / nextmax); // newtr
1805 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< mpParam->getTimestep() <<" ",5);
1806 mpParam->setDesiredTimestep( newdt );
1807 mpParam->calculateAllMissingValues( mSimulationTime, mSilent );
1808 maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P(getGeoMaxMovementVelocity(
1809 mSimulationTime, mpParam->getTimestep() )) ));
1810 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxMovobjVel,5);
1812 recalculateObjectSpeeds();
1815 // init obstacles for first time step (requires obj speeds)
1816 initMovingObstacles(true);
1818 /* set interface cells */
1819 ntlVec3Gfx pos,iniPos; // position of current cell
1820 LbmFloat rhomass = 0.0;
1821 CellFlagType ntype = CFInvalid;
1826 // 2d display as rectangles
1829 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))+(dvec*0.5);
1830 //if(mInit2dYZ) { SWAPYZ(mGravity); for(int lev=0; lev<=mMaxRefine; lev++){ SWAPYZ( mLevel[lev].gravity ); } }
1832 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5);
1836 // first init boundary conditions
1837 // invalid cells are set to empty afterwards
1838 // TODO use floop macros!?
1839 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1840 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1841 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1845 const bool inside = geoInitCheckPointInside( ggpos, FGI_ALLBOUNDS, OId, distance);
1847 pObj = (*mpGiObjects)[OId];
1848 switch( pObj->getGeoInitType() ){
1849 case FGI_MBNDINFLOW:
1850 if(! pObj->getIsAnimated() ) {
1852 ntype = CFFluid | CFMbndInflow;
1857 case FGI_MBNDOUTFLOW:
1858 if(! pObj->getIsAnimated() ) {
1860 ntype = CFEmpty|CFMbndOutflow;
1867 ntype = CFBnd|CFBndNoslip;
1871 ntype = CFBnd|CFBndPartslip; break;
1874 ntype = CFBnd|CFBndFreeslip; break;
1875 default: // warn here?
1877 ntype = CFBnd|CFBndNoslip; break;
1880 if(ntype != CFInvalid) {
1882 if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { }
1883 ntype |= (OId<<24); // NEWTEST2
1884 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1887 // walk along x until hit for following inits
1888 if(distance<=-1.0) { distance = 100.0; } // FIXME dangerous
1890 gfxReal dcnt=dvec[0];
1891 while(( dcnt< distance-dvec[0] )&&(i+1<mLevel[level].lSizex-1)) {
1892 dcnt += dvec[0]; i++;
1894 if(ntype != CFInvalid) {
1895 // rho,mass,OId are still inited from above
1896 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1907 // now init fluid layer
1908 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1909 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1910 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1911 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue;
1915 const bool inside = geoInitCheckPointInside( ggpos, FGI_FLUID, OId, distance);
1919 if(ntype != CFInvalid) {
1922 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1926 // walk along x until hit for following inits
1927 if(distance<=-1.0) { distance = 100.0; }
1929 gfxReal dcnt=dvec[0];
1930 while((dcnt< distance )&&(i+1<mLevel[level].lSizex-1)) {
1931 dcnt += dvec[0]; i++;
1933 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue;
1934 if(ntype != CFInvalid) {
1935 // rhomass are still inited from above
1936 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] );
1946 // reset invalid to empty again
1947 for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
1948 for(int j=1;j<mLevel[level].lSizey-1;j++) {
1949 for(int i=1;i<mLevel[level].lSizex-1;i++) {
1950 if(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFInvalid) {
1951 RFLAG(level, i,j,k, mLevel[level].setOther) =
1952 RFLAG(level, i,j,k, mLevel[level].setCurr) = CFEmpty;
1959 myTime_t geotimeend = getTime();
1960 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< getTimeString(geotimeend-geotimestart)<<","<<savedNodes<<") " , 10 );
1961 //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez));
1967 /*****************************************************************************/
1968 /* init part for all freesurface testcases */
1969 void LbmFsgrSolver::initFreeSurfaces() {
1970 double interfaceFill = 0.45; // filling level of interface cells
1971 //interfaceFill = 1.0; // DEUG!! GEOMTEST!!!!!!!!!!!!
1973 // set interface cells
1974 FSGR_FORIJK1(mMaxRefine) {
1975 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid )) {
1977 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
1978 if( ( RFLAG(mMaxRefine, ni, nj, nk, mLevel[mMaxRefine].setCurr)& CFEmpty ) ) {
1979 LbmFloat arho=0., aux=0., auy=0., auz=0.;
1980 interpolateCellValues(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz);
1981 //errMsg("TINI"," "<<PRINT_VEC(ni,nj,nk)<<" v"<<LbmVec(aux,auy,auz) );
1982 // unnecessary? initEmptyCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill);
1983 initVelocityCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill, LbmVec(aux,auy,auz) );
1989 // remove invalid interface cells
1990 FSGR_FORIJK1(mMaxRefine) {
1991 // remove invalid interface cells
1992 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) ) {
1994 int NBs = 0; // neighbor flags or'ed
1998 if( ( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l )& CFEmpty ) ) {
2001 NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l);
2003 // remove cells with no fluid or interface neighbors
2004 if((NBs & CFFluid)==0) { delit = 1; }
2005 if((NBs & CFInter)==0) { delit = 1; }
2006 // remove cells with no empty neighbors
2007 if(noEmptyNB) { delit = 2; }
2009 // now we can remove the cell
2011 initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0);
2014 //initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0);
2015 LbmFloat arho=0., aux=0., auy=0., auz=0.;
2016 interpolateCellValues(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz);
2017 initVelocityCell(mMaxRefine, i,j,k, CFFluid, arho,1., LbmVec(aux,auy,auz) );
2022 // another brute force init, make sure the fill values are right...
2023 // and make sure both sets are equal
2024 for(int lev=0; lev<=mMaxRefine; lev++) {
2025 FSGR_FORIJK_BOUNDS(lev) {
2026 if( (RFLAG(lev, i,j,k,0) & (CFBnd)) ) {
2027 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = BND_FILL;
2030 if( (RFLAG(lev, i,j,k,0) & (CFEmpty)) ) {
2031 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = 0.0;
2036 // ----------------------------------------------------------------------
2037 // smoother surface...
2038 if(mInitSurfaceSmoothing>0) {
2039 debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing timestep ",10);
2040 #if COMPRESSGRIDS==1
2041 //errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return;
2042 #endif // COMPRESSGRIDS==0
2044 for(int s=0; s<mInitSurfaceSmoothing; s++) {
2045 //SGR_FORIJK1(mMaxRefine) {
2047 int kstart=getForZMin1(), kend=getForZMax1(mMaxRefine);
2048 int lev = mMaxRefine;
2049 #if COMPRESSGRIDS==0
2050 for(int k=kstart;k<kend;++k) {
2051 #else // COMPRESSGRIDS==0
2052 int kdir = 1; // COMPRT ON
2053 if(mLevel[lev].setCurr==1) {
2059 for(int k=kstart;k!=kend;k+=kdir) {
2060 #endif // COMPRESSGRIDS==0
2061 for(int j=1;j<mLevel[lev].lSizey-1;++j) {
2062 for(int i=1;i<mLevel[lev].lSizex-1;++i) {
2063 if( ( RFLAG(lev, i,j,k, mLevel[lev].setCurr)& CFInter) ) {
2064 LbmFloat mass = 0.0;
2067 for(int l=0;(l<cDirNum); l++) {
2068 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
2069 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFFluid ){
2072 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFInter ){
2073 mass += QCELL(lev, ni,nj,nk, mLevel[lev].setCurr, dMass);
2078 //errMsg(" I ", PRINT_IJK<<" m"<<mass );
2079 QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)cDirNum) );
2080 QCELL(lev, i,j,k, mLevel[lev].setOther, dFfrac) = QCELL(lev, i,j,k, mLevel[lev].setOther, dMass);
2084 mLevel[lev].setOther = mLevel[lev].setCurr;
2085 mLevel[lev].setCurr ^= 1;
2090 /*****************************************************************************/
2091 /* init part for all freesurface testcases */
2092 void LbmFsgrSolver::initStandingFluidGradient() {
2093 // ----------------------------------------------------------------------
2094 // standing fluid preinit
2095 const int debugStandingPreinit = 0;
2096 int haveStandingFluid = 0;
2098 #define STANDFLAGCHECK(iindex) \
2099 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || \
2100 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ \
2101 if((iindex)>1) { haveStandingFluid=(iindex); } \
2102 j = mLevel[mMaxRefine].lSizey; i=mLevel[mMaxRefine].lSizex; k=getForZMaxBnd(); \
2105 int gravIndex[3] = {0,0,0};
2106 int gravDir[3] = {1,1,1};
2107 int maxGravComp = 1; // by default y
2108 int gravComp1 = 0; // by default y
2109 int gravComp2 = 2; // by default y
2110 if( ABS(mLevel[mMaxRefine].gravity[0]) > ABS(mLevel[mMaxRefine].gravity[1]) ){ maxGravComp = 0; gravComp1=1; gravComp2=2; }
2111 if( ABS(mLevel[mMaxRefine].gravity[2]) > ABS(mLevel[mMaxRefine].gravity[0]) ){ maxGravComp = 2; gravComp1=0; gravComp2=1; }
2113 int gravIMin[3] = { 0 , 0 , 0 };
2115 mLevel[mMaxRefine].lSizex + 0,
2116 mLevel[mMaxRefine].lSizey + 0,
2117 mLevel[mMaxRefine].lSizez + 0 };
2118 if(LBMDIM==2) gravIMax[2] = 1;
2121 if( mLevel[mMaxRefine].gravity[maxGravComp] > 0.0 ) {
2124 int tmp = gravIMin[i];
2125 gravIMin[i] = gravIMax[i] - 1;
2126 gravIMax[i] = tmp - 1;
2129 #define PRINTGDIRS \
2130 errMsg("Standing fp","X start="<<gravIMin[0]<<" end="<<gravIMax[0]<<" dir="<<gravDir[0] ); \
2131 errMsg("Standing fp","Y start="<<gravIMin[1]<<" end="<<gravIMax[1]<<" dir="<<gravDir[1] ); \
2132 errMsg("Standing fp","Z start="<<gravIMin[2]<<" end="<<gravIMax[2]<<" dir="<<gravDir[2] );
2135 bool gravAbort = false;
2138 for(gravIndex[2]= gravIMin[2]; (gravIndex[2]!=gravIMax[2])&&(!gravAbort); gravIndex[2] += gravDir[2]) \
2139 for(gravIndex[1]= gravIMin[1]; (gravIndex[1]!=gravIMax[1])&&(!gravAbort); gravIndex[1] += gravDir[1]) \
2140 for(gravIndex[0]= gravIMin[0]; (gravIndex[0]!=gravIMax[0])&&(!gravAbort); gravIndex[0] += gravDir[0])
2143 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2];
2144 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) ||
2145 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFBndMoving)) ) ||
2146 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ) {
2147 int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp]));
2148 if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] );
2150 haveStandingFluid = fluidHeight; //gravIndex[maxGravComp];
2151 gravIMax[maxGravComp] = gravIndex[maxGravComp] + gravDir[maxGravComp];
2153 gravAbort = true; continue;
2158 LbmFloat fluidHeight;
2159 fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp]));
2160 #if LBM_INCLUDE_TESTSOLVERS==1
2161 if(mUseTestdata) mpTest->mFluidHeight = (int)fluidHeight;
2162 #endif // ELBEEM_PLUGIN!=1
2163 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])<<
2164 " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10);
2166 if(mDisableStandingFluidInit) {
2167 debMsgStd("Standing fluid preinit", DM_MSG, "Should be performed - but skipped due to mDisableStandingFluidInit flag set!", 2);
2168 haveStandingFluid=0;
2171 // copy flags and init , as no flags will be changed during grav init
2172 // also important for corasening later on
2173 const int lev = mMaxRefine;
2174 CellFlagType nbflag[LBM_DFNUM], nbored;
2175 for(int k=getForZMinBnd();k<getForZMaxBnd(mMaxRefine);++k) {
2176 for(int j=0;j<mLevel[lev].lSizey-0;++j) {
2177 for(int i=0;i<mLevel[lev].lSizex-0;++i) {
2178 if( (RFLAG(lev, i,j,k,SRCS(lev)) & (CFFluid)) ) {
2181 nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l);
2182 nbored |= nbflag[l];
2185 RFLAG(lev, i,j,k,SRCS(lev)) &= (~CFNoBndFluid);
2187 RFLAG(lev, i,j,k,SRCS(lev)) |= CFNoBndFluid;
2190 RFLAG(lev, i,j,k,TSET(lev)) = RFLAG(lev, i,j,k,SRCS(lev));
2193 if(haveStandingFluid) {
2194 int rhoworkSet = mLevel[lev].setCurr;
2195 myTime_t timestart = getTime(); // FIXME use user time here?
2198 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2];
2199 //debMsgStd("Standing fluid preinit", DM_MSG, " init check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 );
2200 if( ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFInter)) ) ||
2201 ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFEmpty)) ) ){
2207 // 1/6 velocity from denisty gradient, 1/2 for delta of two cells
2208 rho += 1.0* (fluidHeight-gravIndex[maxGravComp]) *
2209 (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega);
2210 if(debugStandingPreinit)
2211 if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) {
2212 errMsg("Standing fp","gi="<<gravIndex[maxGravComp]<<" rho="<<rho<<" at "<<PRINT_IJK);
2215 if( (RFLAG(lev, i,j,k, rhoworkSet) & CFFluid) ||
2216 (RFLAG(lev, i,j,k, rhoworkSet) & CFInter) ) {
2217 FORDF0 { QCELL(lev, i,j,k, rhoworkSet, l) *= rho; }
2218 QCELL(lev, i,j,k, rhoworkSet, dMass) *= rho;
2223 debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited (max-rho:"<<
2224 (1.0+ (fluidHeight) * (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega)) <<", h:"<< fluidHeight<<") ", 8);
2226 int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) );
2227 preinitSteps = (haveStandingFluid>>2); // not much use...?
2229 debMsgStd("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10);
2230 for(int s=0; s<preinitSteps; s++) {
2231 // in solver main cpp
2232 standingFluidPreinit();
2235 myTime_t timeend = getTime();
2236 debMsgStd("Standing fluid preinit", DM_MSG, " done, "<<getTimeString(timeend-timestart), 9);
2243 bool LbmFsgrSolver::checkSymmetry(string idstring)
2248 const int maxMsgs = 10;
2249 const bool markCells = false;
2251 //for(int lev=0; lev<=mMaxRefine; lev++) {
2252 { int lev = mMaxRefine;
2254 // no point if not symm.
2255 if( (mLevel[lev].lSizex==mLevel[lev].lSizey) && (mLevel[lev].lSizex==mLevel[lev].lSizez)) {
2261 for(int s=0; s<2; s++) {
2263 if(i<(mLevel[lev].lSizex/2)) {
2264 int inb = (mLevel[lev].lSizey-1-i);
2266 if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T
2268 if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true;
2270 if(msgs<maxMsgs) { msgs++;
2271 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) );
2274 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2277 if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true;
2279 if(msgs<maxMsgs) { msgs++;
2280 //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl);
2281 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) );
2284 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2288 LbmFloat nbrho = QCELL(lev, i,j,k, s, dC);
2289 FORDF1 { nbrho += QCELL(lev, i,j,k, s, l); }
2290 LbmFloat otrho = QCELL(lev, inb,j,k, s, dC);
2291 FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); }
2292 if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true;
2294 if(msgs<maxMsgs) { msgs++;
2295 //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl);
2296 errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho );
2299 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); }
2305 LbmFloat maxdiv =0.0;
2307 errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv );
2308 //if(LBMDIM==2) mPanic = true;
2311 errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv );
2319 LbmFsgrSolver::interpolateCellValues(
2320 int level,int ei,int ej,int ek,int workSet,
2321 LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz)
2323 LbmFloat avgrho = 0.0;
2324 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
2325 LbmFloat cellcnt = 0.0;
2327 for(int nbl=1; nbl< cDfNum ; ++nbl) {
2328 if(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) continue;
2329 if( (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & (CFFluid|CFInter)) ){
2330 //((!(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) &&
2331 //(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFInter) ) {
2333 for(int rl=0; rl< cDfNum ; ++rl) {
2334 LbmFloat nbdf = QCELL_NB(level,ei,ej,ek, workSet,nbl, rl);
2335 avgux += (dfDvecX[rl]*nbdf);
2336 avguy += (dfDvecY[rl]*nbdf);
2337 avguz += (dfDvecZ[rl]*nbdf);
2344 // no nbs? just use eq.
2346 avgux = avguy = avguz = 0.0;
2347 //TTT mNumProblems++;
2348 #if ELBEEM_PLUGIN!=1
2350 // this can happen for worst case moving obj scenarios...
2351 errMsg("LbmFsgrSolver::interpolateCellValues","Cellcnt<=0.0 at "<<PRINT_VEC(ei,ej,ek));
2352 #endif // ELBEEM_PLUGIN
2355 avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt;
2363 } // interpolateCellValues
2366 /******************************************************************************
2368 *****************************************************************************/
2370 //! lbm factory functions
2371 LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); }