Blender V2.61 - r43446
|
00001 00004 /****************************************************************************** 00005 * 00006 * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method 00007 * Copyright 2003-2006 Nils Thuerey 00008 * 00009 * Standard LBM Factory implementation 00010 * 00011 *****************************************************************************/ 00012 00013 00014 #include "solver_class.h" 00015 #include "solver_relax.h" 00016 // for geo init FGI_ defines 00017 #include "elbeem.h" 00018 00019 // helper for 2d init 00020 #define SWAPYZ(vec) { \ 00021 const LbmFloat tmp = (vec)[2]; \ 00022 (vec)[2] = (vec)[1]; (vec)[1] = tmp; } 00023 00024 00025 /*****************************************************************************/ 00027 00028 /*****************************************************************************/ 00030 #if LBMDIM==3 00031 00033 const int LbmFsgrSolver::cDimension = 3; 00034 00035 // Wi factors for collide step 00036 const LbmFloat LbmFsgrSolver::cCollenZero = (1.0/3.0); 00037 const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/18.0); 00038 const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0); 00039 00041 const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005; 00042 const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005; 00043 const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001; 00044 const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001; 00045 00047 const int LbmFsgrSolver::cDfNum = 19; 00049 const int LbmFsgrSolver::cDirNum = 27; 00050 00051 //const string LbmFsgrSolver::dfString[ cDfNum ] = { 00052 const char* LbmFsgrSolver::dfString[ cDfNum ] = { 00053 " C", " N"," S"," E"," W"," T"," B", 00054 "NE","NW","SE","SW", 00055 "NT","NB","ST","SB", 00056 "ET","EB","WT","WB" 00057 }; 00058 00059 const int LbmFsgrSolver::dfNorm[ cDfNum ] = { 00060 cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB, 00061 cDirNE, cDirNW, cDirSE, cDirSW, 00062 cDirNT, cDirNB, cDirST, cDirSB, 00063 cDirET, cDirEB, cDirWT, cDirWB 00064 }; 00065 00066 const int LbmFsgrSolver::dfInv[ cDfNum ] = { 00067 cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT, 00068 cDirSW, cDirSE, cDirNW, cDirNE, 00069 cDirSB, cDirST, cDirNB, cDirNT, 00070 cDirWB, cDirWT, cDirEB, cDirET 00071 }; 00072 00073 const int LbmFsgrSolver::dfRefX[ cDfNum ] = { 00074 0, 0, 0, 0, 0, 0, 0, 00075 cDirSE, cDirSW, cDirNE, cDirNW, 00076 0, 0, 0, 0, 00077 cDirEB, cDirET, cDirWB, cDirWT 00078 }; 00079 00080 const int LbmFsgrSolver::dfRefY[ cDfNum ] = { 00081 0, 0, 0, 0, 0, 0, 0, 00082 cDirNW, cDirNE, cDirSW, cDirSE, 00083 cDirNB, cDirNT, cDirSB, cDirST, 00084 0, 0, 0, 0 00085 }; 00086 00087 const int LbmFsgrSolver::dfRefZ[ cDfNum ] = { 00088 0, 0, 0, 0, 0, 0, 0, 00089 0, 0, 0, 0, 00090 cDirST, cDirSB, cDirNT, cDirNB, 00091 cDirWT, cDirWB, cDirET, cDirEB 00092 }; 00093 00094 // Vector Order 3D: 00095 // 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 00096 // 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 00097 // 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 00098 // 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 00099 00100 const int LbmFsgrSolver::dfVecX[ cDirNum ] = { 00101 0, 0,0, 1,-1, 0,0, 00102 1,-1,1,-1, 00103 0,0,0,0, 00104 1,1,-1,-1, 00105 1,-1, 1,-1, 00106 1,-1, 1,-1, 00107 }; 00108 const int LbmFsgrSolver::dfVecY[ cDirNum ] = { 00109 0, 1,-1, 0,0,0,0, 00110 1,1,-1,-1, 00111 1,1,-1,-1, 00112 0,0,0,0, 00113 1, 1,-1,-1, 00114 1, 1,-1,-1 00115 }; 00116 const int LbmFsgrSolver::dfVecZ[ cDirNum ] = { 00117 0, 0,0,0,0,1,-1, 00118 0,0,0,0, 00119 1,-1,1,-1, 00120 1,-1,1,-1, 00121 1, 1, 1, 1, 00122 -1,-1,-1,-1 00123 }; 00124 00125 const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = { 00126 0, 0,0, 1,-1, 0,0, 00127 1,-1,1,-1, 00128 0,0,0,0, 00129 1,1,-1,-1, 00130 1,-1, 1,-1, 00131 1,-1, 1,-1 00132 }; 00133 const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = { 00134 0, 1,-1, 0,0,0,0, 00135 1,1,-1,-1, 00136 1,1,-1,-1, 00137 0,0,0,0, 00138 1, 1,-1,-1, 00139 1, 1,-1,-1 00140 }; 00141 const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = { 00142 0, 0,0,0,0,1,-1, 00143 0,0,0,0, 00144 1,-1,1,-1, 00145 1,-1,1,-1, 00146 1, 1, 1, 1, 00147 -1,-1,-1,-1 00148 }; 00149 00150 /* principal directions */ 00151 const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = { 00152 1,-1, 0,0, 0,0 00153 }; 00154 const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = { 00155 0,0, 1,-1, 0,0 00156 }; 00157 const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = { 00158 0,0, 0,0, 1,-1 00159 }; 00160 00162 LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; 00163 LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ]; 00164 00165 00166 const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= { 00167 cCollenZero, 00168 cCollenOne, cCollenOne, cCollenOne, 00169 cCollenOne, cCollenOne, cCollenOne, 00170 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, 00171 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, 00172 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo 00173 }; 00174 00175 /* precalculated equilibrium dfs, inited in lbmsolver constructor */ 00176 LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ]; 00177 00178 #else // end LBMDIM==3 , LBMDIM==2 00179 00180 /*****************************************************************************/ 00183 00184 const int LbmFsgrSolver::cDimension = 2; 00185 00187 const LbmFloat LbmFsgrSolver::cCollenZero = (4.0/9.0); 00188 const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/9.0); 00189 const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0); 00190 00192 const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005; 00193 const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005; 00194 const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001; 00195 const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001; 00196 00198 const int LbmFsgrSolver::cDfNum = 9; 00199 const int LbmFsgrSolver::cDirNum = 9; 00200 00201 //const string LbmFsgrSolver::dfString[ cDfNum ] = { 00202 const char* LbmFsgrSolver::dfString[ cDfNum ] = { 00203 " C", 00204 " N", " S", " E", " W", 00205 "NE", "NW", "SE","SW" 00206 }; 00207 00208 const int LbmFsgrSolver::dfNorm[ cDfNum ] = { 00209 cDirC, 00210 cDirN, cDirS, cDirE, cDirW, 00211 cDirNE, cDirNW, cDirSE, cDirSW 00212 }; 00213 00214 const int LbmFsgrSolver::dfInv[ cDfNum ] = { 00215 cDirC, 00216 cDirS, cDirN, cDirW, cDirE, 00217 cDirSW, cDirSE, cDirNW, cDirNE 00218 }; 00219 00220 const int LbmFsgrSolver::dfRefX[ cDfNum ] = { 00221 0, 00222 0, 0, 0, 0, 00223 cDirSE, cDirSW, cDirNE, cDirNW 00224 }; 00225 00226 const int LbmFsgrSolver::dfRefY[ cDfNum ] = { 00227 0, 00228 0, 0, 0, 0, 00229 cDirNW, cDirNE, cDirSW, cDirSE 00230 }; 00231 00232 const int LbmFsgrSolver::dfRefZ[ cDfNum ] = { 00233 0, 0, 0, 0, 0, 00234 0, 0, 0, 0 00235 }; 00236 00237 // Vector Order 2D: 00238 // 0 1 2 3 4 5 6 7 8 00239 // 0, 0,0, 1,-1, 1,-1,1,-1 00240 // 0, 1,-1, 0,0, 1,1,-1,-1 00241 00242 const int LbmFsgrSolver::dfVecX[ cDirNum ] = { 00243 0, 00244 0,0, 1,-1, 00245 1,-1,1,-1 00246 }; 00247 const int LbmFsgrSolver::dfVecY[ cDirNum ] = { 00248 0, 00249 1,-1, 0,0, 00250 1,1,-1,-1 00251 }; 00252 const int LbmFsgrSolver::dfVecZ[ cDirNum ] = { 00253 0, 0,0,0,0, 0,0,0,0 00254 }; 00255 00256 const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = { 00257 0, 00258 0,0, 1,-1, 00259 1,-1,1,-1 00260 }; 00261 const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = { 00262 0, 00263 1,-1, 0,0, 00264 1,1,-1,-1 00265 }; 00266 const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = { 00267 0, 0,0,0,0, 0,0,0,0 00268 }; 00269 00270 const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = { 00271 1,-1, 0,0 00272 }; 00273 const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = { 00274 0,0, 1,-1 00275 }; 00276 const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = { 00277 0,0, 0,0 00278 }; 00279 00280 00282 LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; 00283 LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ]; 00284 00285 00286 const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= { 00287 cCollenZero, 00288 cCollenOne, cCollenOne, cCollenOne, cCollenOne, 00289 cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo 00290 }; 00291 00292 /* precalculated equilibrium dfs, inited in lbmsolver constructor */ 00293 LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ]; 00294 00295 // D2Q9 end 00296 #endif // LBMDIM==2 00297 00298 00299 // required globals 00300 extern bool glob_mpactive; 00301 extern int glob_mpnum, glob_mpindex; 00302 00303 00304 /****************************************************************************** 00305 * Lbm Constructor 00306 *****************************************************************************/ 00307 LbmFsgrSolver::LbmFsgrSolver() : 00308 //D(), 00309 mCurrentMass(0.0), mCurrentVolume(0.0), 00310 mNumProblems(0), 00311 mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0), 00312 mpPreviewSurface(NULL), 00313 mTimeAdap(true), mForceTimeStepReduce(false), 00314 mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false), 00315 mInitSurfaceSmoothing(0), mFsSurfGenSetting(0), 00316 mTimestepReduceLock(0), 00317 mTimeSwitchCounts(0), mTimeMaxvelStepCnt(0), 00318 mSimulationTime(0.0), mLastSimTime(0.0), 00319 mMinTimestep(0.0), mMaxTimestep(0.0), 00320 mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0), 00321 mObjectSpeeds(), mObjectPartslips(), mObjectMassMovnd(), 00322 mMOIVertices(), mMOIVerticesOld(), mMOINormals(), 00323 mIsoWeightMethod(1), 00324 mMaxRefine(1), 00325 mDfScaleUp(-1.0), mDfScaleDown(-1.0), 00326 mInitialCsmago(0.02), // set to 0.02 for mMaxRefine==0 below and default for fine level, coarser ones are 0.03 00327 mDebugOmegaRet(0.0), 00328 mLastOmega(1e10), mLastGravity(1e10), 00329 mNumInvIfTotal(0), mNumFsgrChanges(0), 00330 mDisableStandingFluidInit(0), 00331 mInit2dYZ(false), 00332 mForceTadapRefine(-1), mCutoff(-1) 00333 { 00334 mpControl = new LbmControlData(); 00335 00336 #if LBM_INCLUDE_TESTSOLVERS==1 00337 mpTest = new LbmTestdata(); 00338 mMpNum = mMpIndex = 0; 00339 mOrgSizeX = 0; 00340 mOrgStartX = 0.; 00341 mOrgEndX = 0.; 00342 #endif // LBM_INCLUDE_TESTSOLVERS!=1 00343 mpIso = new IsoSurface( mIsoValue ); 00344 00345 // init equilibrium dist. func 00346 LbmFloat rho=1.0; 00347 FORDF0 { 00348 dfEquil[l] = this->getCollideEq( l,rho, 0.0, 0.0, 0.0); 00349 } 00350 dfEquil[dMass] = 1.; 00351 dfEquil[dFfrac] = 1.; 00352 dfEquil[dFlux] = FLUX_INIT; 00353 00354 // init LES 00355 int odm = 0; 00356 for(int m=0; m<LBMDIM; m++) { 00357 for(int l=0; l<cDfNum; l++) { 00358 this->lesCoeffDiag[m][l] = 00359 this->lesCoeffOffdiag[m][l] = 0.0; 00360 } 00361 } 00362 for(int m=0; m<LBMDIM; m++) { 00363 for(int n=0; n<LBMDIM; n++) { 00364 for(int l=1; l<cDfNum; l++) { 00365 LbmFloat em; 00366 switch(m) { 00367 case 0: em = dfDvecX[l]; break; 00368 case 1: em = dfDvecY[l]; break; 00369 case 2: em = dfDvecZ[l]; break; 00370 default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR); 00371 } 00372 LbmFloat en; 00373 switch(n) { 00374 case 0: en = dfDvecX[l]; break; 00375 case 1: en = dfDvecY[l]; break; 00376 case 2: en = dfDvecZ[l]; break; 00377 default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR); 00378 } 00379 const LbmFloat coeff = em*en; 00380 if(m==n) { 00381 this->lesCoeffDiag[m][l] = coeff; 00382 } else { 00383 if(m>n) { 00384 this->lesCoeffOffdiag[odm][l] = coeff; 00385 } 00386 } 00387 } 00388 00389 if(m==n) { 00390 } else { 00391 if(m>n) odm++; 00392 } 00393 } 00394 } 00395 00396 mDvecNrm[0] = LbmVec(0.0); 00397 FORDF1 { 00398 mDvecNrm[l] = getNormalized( 00399 LbmVec(dfDvecX[dfInv[l]], dfDvecY[dfInv[l]], dfDvecZ[dfInv[l]] ) 00400 ) * -1.0; 00401 } 00402 00403 // calculate gauss weights for restriction 00404 //LbmFloat mGaussw[27]; 00405 LbmFloat totGaussw = 0.0; 00406 const LbmFloat alpha = 1.0; 00407 const LbmFloat gw = sqrt(2.0*LBMDIM); 00408 #if ELBEEM_PLUGIN!=1 00409 errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!"); 00410 #endif 00411 for(int n=0;(n<cDirNum); n++) { mGaussw[n] = 0.0; } 00412 //for(int n=0;(n<cDirNum); n++) { 00413 for(int n=0;(n<cDfNum); n++) { 00414 const LbmFloat d = norm(LbmVec(dfVecX[n], dfVecY[n], dfVecZ[n])); 00415 LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw ); 00416 mGaussw[n] = w; 00417 totGaussw += w; 00418 } 00419 for(int n=0;(n<cDirNum); n++) { 00420 mGaussw[n] = mGaussw[n]/totGaussw; 00421 } 00422 00423 } 00424 00425 /*****************************************************************************/ 00426 /* Destructor */ 00427 /*****************************************************************************/ 00428 LbmFsgrSolver::~LbmFsgrSolver() 00429 { 00430 if(!mInitDone){ debMsgStd("LbmFsgrSolver::LbmFsgrSolver",DM_MSG,"not inited...",0); return; } 00431 #if COMPRESSGRIDS==1 00432 delete [] mLevel[mMaxRefine].mprsCells[1]; 00433 mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL; 00434 #endif // COMPRESSGRIDS==1 00435 00436 for(int i=0; i<=mMaxRefine; i++) { 00437 for(int s=0; s<2; s++) { 00438 if(mLevel[i].mprsCells[s]) delete [] mLevel[i].mprsCells[s]; 00439 if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s]; 00440 } 00441 } 00442 delete mpIso; 00443 if(mpPreviewSurface) delete mpPreviewSurface; 00444 // cleanup done during scene deletion... 00445 00446 if(mpControl) delete mpControl; 00447 00448 // always output performance estimate 00449 debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5); 00450 if(!mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10); 00451 } 00452 00453 00454 00455 00456 /****************************************************************************** 00457 * initilize variables fom attribute list 00458 *****************************************************************************/ 00459 void LbmFsgrSolver::parseAttrList() 00460 { 00461 LbmSolverInterface::parseStdAttrList(); 00462 00463 string matIso("default"); 00464 matIso = mpSifAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false ); 00465 mpIso->setMaterialName( matIso ); 00466 mOutputSurfacePreview = mpSifAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false ); 00467 mTimeAdap = mpSifAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false ); 00468 mDomainBound = mpSifAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false ); 00469 mDomainPartSlipValue = mpSifAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false ); 00470 00471 mIsoWeightMethod= mpSifAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false ); 00472 mInitSurfaceSmoothing = mpSifAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false ); 00473 mSmoothSurface = mpSifAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); 00474 mSmoothNormals = mpSifAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); 00475 mFsSurfGenSetting = mpSifAttrs->readInt("fssurfgen", mFsSurfGenSetting, "SimulationLbm","mFsSurfGenSetting", false ); 00476 00477 // refinement 00478 mMaxRefine = mRefinementDesired; 00479 mMaxRefine = mpSifAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false); 00480 if(mMaxRefine<0) mMaxRefine=0; 00481 if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1; 00482 mDisableStandingFluidInit = mpSifAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false); 00483 mInit2dYZ = mpSifAttrs->readBool("init2dyz", mInit2dYZ,"LbmFsgrSolver", "mInit2dYZ", false); 00484 mForceTadapRefine = mpSifAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false); 00485 00486 // demo mode settings 00487 mFVHeight = mpSifAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false ); 00488 // FIXME check needed? 00489 mFVArea = mpSifAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false ); 00490 00491 // debugging - skip some time... 00492 double starttimeskip = 0.; 00493 starttimeskip = mpSifAttrs->readFloat("forcestarttimeskip", starttimeskip, "LbmFsgrSolver","starttimeskip", false ); 00494 mSimulationTime += starttimeskip; 00495 if(starttimeskip>0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<<starttimeskip<<", t="<<mSimulationTime, 1); 00496 00497 mpControl->parseControldataAttrList(mpSifAttrs); 00498 00499 #if LBM_INCLUDE_TESTSOLVERS==1 00500 mUseTestdata = 0; 00501 mUseTestdata = mpSifAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false); 00502 mpTest->parseTestdataAttrList(mpSifAttrs); 00503 #ifdef ELBEEM_PLUGIN 00504 mUseTestdata=1; // DEBUG 00505 #endif // ELBEEM_PLUGIN 00506 00507 mMpNum = mpSifAttrs->readInt("mpnum", mMpNum ,"LbmFsgrSolver", "mMpNum", false); 00508 mMpIndex = mpSifAttrs->readInt("mpindex", mMpIndex ,"LbmFsgrSolver", "mMpIndex", false); 00509 if(glob_mpactive) { 00510 // used instead... 00511 mMpNum = glob_mpnum; 00512 mMpIndex = glob_mpindex; 00513 } else { 00514 glob_mpnum = mMpNum; 00515 glob_mpindex = 0; 00516 } 00517 errMsg("LbmFsgrSolver::parseAttrList"," mpactive:"<<glob_mpactive<<", "<<glob_mpindex<<"/"<<glob_mpnum); 00518 if(mMpNum>0) { 00519 mUseTestdata=1; // needed in this case... 00520 } 00521 00522 errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" "); 00523 #else // LBM_INCLUDE_TESTSOLVERS!=1 00524 // not testsolvers, off by default 00525 mUseTestdata = 0; 00526 if(mFarFieldSize>=2.) mUseTestdata=1; // equiv. to test solver check 00527 #endif // LBM_INCLUDE_TESTSOLVERS!=1 00528 00529 mInitialCsmago = mpSifAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); 00530 // deprecated! 00531 float mInitialCsmagoCoarse = 0.0; 00532 mInitialCsmagoCoarse = mpSifAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false ); 00533 #if USE_LES==1 00534 #else // USE_LES==1 00535 debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2); 00536 mInitialCsmago = 0.0; 00537 #endif // USE_LES==1 00538 } 00539 00540 00541 /****************************************************************************** 00542 * (part of enabling chapter 6 of "Free Surface Flows with Moving and Deforming Objects for LBM") 00543 *****************************************************************************/ 00544 void LbmFsgrSolver::setSurfGenSettings(short value) 00545 { 00546 mFsSurfGenSetting = value; 00547 } 00548 00549 00550 /****************************************************************************** 00551 * Initialize omegas and forces on all levels (for init/timestep change) 00552 *****************************************************************************/ 00553 void LbmFsgrSolver::initLevelOmegas() 00554 { 00555 // no explicit settings 00556 mOmega = mpParam->calculateOmega(mSimulationTime); 00557 mGravity = vec2L( mpParam->calculateGravity(mSimulationTime) ); 00558 mSurfaceTension = 0.; //mpParam->calculateSurfaceTension(); // unused 00559 if(mInit2dYZ) { SWAPYZ(mGravity); } 00560 00561 // check if last init was ok 00562 LbmFloat gravDelta = norm(mGravity-mLastGravity); 00563 //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<mOmega<<" - lom:"<<mLastOmega<<" gv:"<<mGravity<<" - "<<mLastGravity<<" , "<<gravDelta ); 00564 if((mOmega == mLastOmega) && (gravDelta<=0.0)) return; 00565 00566 if(mInitialCsmago<=0.0) { 00567 if(OPT3D==1) { 00568 errFatal("LbmFsgrSolver::initLevelOmegas","Csmago-LES = 0 not supported for optimized 3D version...",SIMWORLD_INITERROR); 00569 return; 00570 } 00571 } 00572 00573 LbmFloat fineCsmago = mInitialCsmago; 00574 LbmFloat coarseCsmago = mInitialCsmago; 00575 LbmFloat maxFineCsmago1 = 0.026; 00576 LbmFloat maxCoarseCsmago1 = 0.029; // try stabilizing 00577 LbmFloat maxFineCsmago2 = 0.028; 00578 LbmFloat maxCoarseCsmago2 = 0.032; // try stabilizing some more 00579 if((mMaxRefine==1)&&(mInitialCsmago<maxFineCsmago1)) { 00580 fineCsmago = maxFineCsmago1; 00581 coarseCsmago = maxCoarseCsmago1; 00582 } 00583 if((mMaxRefine>1)&&(mInitialCsmago<maxFineCsmago2)) { 00584 fineCsmago = maxFineCsmago2; 00585 coarseCsmago = maxCoarseCsmago2; 00586 } 00587 00588 00589 // use Tau instead of Omega for calculations 00590 { // init base level 00591 int i = mMaxRefine; 00592 mLevel[i].omega = mOmega; 00593 mLevel[i].timestep = mpParam->getTimestep(); 00594 mLevel[i].lcsmago = fineCsmago; //CSMAGO_INITIAL; 00595 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; 00596 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); 00597 } 00598 00599 // init all sub levels 00600 for(int i=mMaxRefine-1; i>=0; i--) { 00601 //mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5; 00602 double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5; 00603 nomega = 1.0/nomega; 00604 mLevel[i].omega = (LbmFloat)nomega; 00605 mLevel[i].timestep = 2.0 * mLevel[i+1].timestep; 00606 mLevel[i].lcsmago = coarseCsmago; 00607 mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; 00608 mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); 00609 } 00610 00611 // for lbgk 00612 mLevel[ mMaxRefine ].gravity = mGravity / mLevel[ mMaxRefine ].omega; 00613 for(int i=mMaxRefine-1; i>=0; i--) { 00614 // should be the same on all levels... 00615 // for lbgk 00616 mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega; 00617 } 00618 00619 mLastOmega = mOmega; 00620 mLastGravity = mGravity; 00621 // debug? invalidate old values... 00622 mGravity = -100.0; 00623 mOmega = -100.0; 00624 00625 for(int i=0; i<=mMaxRefine; i++) { 00626 if(!mSilent) { 00627 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 00628 <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", " 00629 <<" cmsagp:"<<mLevel[i].lcsmago<<", " 00630 << " ss"<<mLevel[i].timestep<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize ); 00631 } else { 00632 if(!mInitDone) { 00633 debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" " 00634 <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5); 00635 } 00636 } 00637 } 00638 if(mMaxRefine>0) { 00639 mDfScaleUp = (mLevel[0 ].timestep/mLevel[0+1].timestep)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu 00640 mDfScaleDown = (mLevel[0+1].timestep/mLevel[0 ].timestep)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu 00641 } 00642 } 00643 00644 00645 /****************************************************************************** 00646 * Init Solver (values should be read from config file) 00647 *****************************************************************************/ 00648 00650 bool LbmFsgrSolver::initializeSolverMemory() 00651 { 00652 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<mInitDone<<" "<<(void*)this,1); 00653 00654 // init cppf stage 00655 if(mCppfStage>0) { 00656 mSizex *= mCppfStage; 00657 mSizey *= mCppfStage; 00658 mSizez *= mCppfStage; 00659 } 00660 if(mFsSurfGenSetting==-1) { 00661 // all on 00662 mFsSurfGenSetting = 00663 fssgNormal | fssgNoNorth | fssgNoSouth | fssgNoEast | 00664 fssgNoWest | fssgNoTop | fssgNoBottom | fssgNoObs ; 00665 } 00666 00667 // size inits to force cubic cells and mult4 level dimensions 00668 // and make sure we dont allocate too much... 00669 bool memOk = false; 00670 int orgSx = mSizex; 00671 int orgSy = mSizey; 00672 int orgSz = mSizez; 00673 double sizeReduction = 1.0; 00674 double memEstFromFunc = -1.0; 00675 double memEstFine = -1.0; 00676 string memreqStr(""); 00677 bool firstMInit = true; 00678 int minitTries=0; 00679 while(!memOk) { 00680 minitTries++; 00681 initGridSizes( mSizex, mSizey, mSizez, 00682 mvGeoStart, mvGeoEnd, mMaxRefine, PARALLEL); 00683 00684 // MPT 00685 #if LBM_INCLUDE_TESTSOLVERS==1 00686 if(firstMInit) { 00687 mrSetup(); 00688 } 00689 #endif // LBM_INCLUDE_TESTSOLVERS==1 00690 firstMInit=false; 00691 00692 calculateMemreqEstimate( mSizex, mSizey, mSizez, 00693 mMaxRefine, mFarFieldSize, &memEstFromFunc, &memEstFine, &memreqStr ); 00694 00695 double memLimit; 00696 string memLimStr("-"); 00697 if(sizeof(void*)==4) { 00698 // 32bit system, limit to 2GB 00699 memLimit = 2.0* 1024.0*1024.0*1024.0; 00700 memLimStr = string("2GB"); 00701 } else { 00702 // 64bit, just take 16GB as limit for now... 00703 memLimit = 16.0* 1024.0*1024.0*1024.0; 00704 memLimStr = string("16GB"); 00705 } 00706 00707 // restrict max. chunk of 1 mem block to 1GB for windos 00708 bool memBlockAllocProblem = false; 00709 double maxDefaultMemChunk = 2.*1024.*1024.*1024.; 00710 //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" <<maxWinMemChunk <<" maxMac:" <<maxMacMemChunk ; // DEBUG 00711 #ifdef WIN32 00712 double maxWinMemChunk = 1100.*1024.*1024.; 00713 if(sizeof(void *)==4 && memEstFine>maxWinMemChunk) { 00714 memBlockAllocProblem = true; 00715 } 00716 #endif // WIN32 00717 #ifdef __APPLE__ 00718 double maxMacMemChunk = 1200.*1024.*1024.; 00719 if(memEstFine> maxMacMemChunk) { 00720 memBlockAllocProblem = true; 00721 } 00722 #endif // Mac 00723 if(sizeof(void*)==4 && memEstFine>maxDefaultMemChunk) { 00724 // max memory chunk for 32bit systems 2gig 00725 memBlockAllocProblem = true; 00726 } 00727 00728 if(memEstFromFunc>memLimit || memBlockAllocProblem) { 00729 sizeReduction *= 0.9; 00730 mSizex = (int)(orgSx * sizeReduction); 00731 mSizey = (int)(orgSy * sizeReduction); 00732 mSizez = (int)(orgSz * sizeReduction); 00733 debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<< 00734 //memEstFromFunc<<"/"<<memLimit<<", "<< 00735 //memEstFine<<"/"<<maxWinMemChunk<<", "<< 00736 memreqStr<<"/"<<memLimStr<<", "<< 00737 "retrying: "<<PRINT_VEC(mSizex,mSizey,mSizez)<<" org:"<<PRINT_VEC(orgSx,orgSy,orgSz) 00738 , 3 ); 00739 } else { 00740 memOk = true; 00741 } 00742 } 00743 00744 mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)mSizex; 00745 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<mSizex<<" Y:"<<mSizey<<" Z:"<<mSizez<< 00746 ", Domain: "<<mvGeoStart<<":"<<mvGeoEnd<<", "<<(mvGeoEnd-mvGeoStart)<< 00747 ", PointerSize: "<< sizeof(void*) << ", IntSize: "<< sizeof(int) << 00748 ", est. Mem.Req.: "<<memreqStr ,2); 00749 mpParam->setSize(mSizex, mSizey, mSizez); 00750 if((minitTries>1)&&(glob_mpnum)) { errMsg("LbmFsgrSolver::initialize","Warning!!!!!!!!!!!!!!! Original gridsize changed........."); } 00751 00752 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: " 00753 <<"LBM_EPSILON="<<LBM_EPSILON <<" " 00754 <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" " 00755 <<"OPT3D="<<OPT3D <<" " 00756 <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" " 00757 <<"MASS_INVALID="<<MASS_INVALID <<" " 00758 <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" " 00759 <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" " 00760 <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" " 00761 <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" " 00762 <<"USE_LES="<<USE_LES <<" " 00763 ,10); 00764 00765 // perform 2D corrections... 00766 if(LBMDIM == 2) mSizez = 1; 00767 00768 mpParam->setSimulationMaxSpeed(0.0); 00769 if(mFVHeight>0.0) mpParam->setFluidVolumeHeight(mFVHeight); 00770 mpParam->setTadapLevels( mMaxRefine+1 ); 00771 00772 if(mForceTadapRefine>mMaxRefine) { 00773 mpParam->setTadapLevels( mForceTadapRefine+1 ); 00774 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<<mForceTadapRefine, 6); 00775 } 00776 00777 if(!mpParam->calculateAllMissingValues(mSimulationTime, false)) { 00778 errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR); 00779 return false; 00780 } 00781 00782 00783 // init vectors 00784 for(int i=0; i<=mMaxRefine; i++) { 00785 mLevel[i].id = i; 00786 mLevel[i].nodeSize = 0.0; 00787 mLevel[i].simCellSize = 0.0; 00788 mLevel[i].omega = 0.0; 00789 mLevel[i].time = 0.0; 00790 mLevel[i].timestep = 1.0; 00791 mLevel[i].gravity = LbmVec(0.0); 00792 mLevel[i].mprsCells[0] = NULL; 00793 mLevel[i].mprsCells[1] = NULL; 00794 mLevel[i].mprsFlags[0] = NULL; 00795 mLevel[i].mprsFlags[1] = NULL; 00796 00797 mLevel[i].avgOmega = 0.0; 00798 mLevel[i].avgOmegaCnt = 0.0; 00799 } 00800 00801 // init sizes 00802 mLevel[mMaxRefine].lSizex = mSizex; 00803 mLevel[mMaxRefine].lSizey = mSizey; 00804 mLevel[mMaxRefine].lSizez = mSizez; 00805 for(int i=mMaxRefine-1; i>=0; i--) { 00806 mLevel[i].lSizex = mLevel[i+1].lSizex/2; 00807 mLevel[i].lSizey = mLevel[i+1].lSizey/2; 00808 mLevel[i].lSizez = mLevel[i+1].lSizez/2; 00809 } 00810 00811 // safety check 00812 if(sizeof(CellFlagType) != CellFlagTypeSize) { 00813 errFatal("LbmFsgrSolver::initialize","Fatal Error: CellFlagType has wrong size! Is:"<<sizeof(CellFlagType)<<", should be:"<<CellFlagTypeSize, SIMWORLD_GENERICERROR); 00814 return false; 00815 } 00816 00817 double ownMemCheck = 0.0; 00818 mLevel[ mMaxRefine ].nodeSize = ((mvGeoEnd[0]-mvGeoStart[0]) / (LbmFloat)(mSizex)); 00819 mLevel[ mMaxRefine ].simCellSize = mpParam->getCellSize(); 00820 mLevel[ mMaxRefine ].lcellfactor = 1.0; 00821 LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); 00822 00823 #if COMPRESSGRIDS==0 00824 mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; 00825 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; 00826 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); 00827 #else // COMPRESSGRIDS==0 00828 LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); 00829 // D int tmp = ( (rcellSize +compressOffset +4)/(1024*1024) )*4; 00830 // D printf("Debug MEMMMM excee: %d\n", tmp); 00831 mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ]; 00832 mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset; 00833 ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4); 00834 #endif // COMPRESSGRIDS==0 00835 00836 if(!mLevel[ mMaxRefine ].mprsCells[1] || !mLevel[ mMaxRefine ].mprsCells[0]) { 00837 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (1)! Aborting...",SIMWORLD_INITERROR); 00838 return false; 00839 } 00840 00841 // +4 for safety ? 00842 mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; 00843 mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; 00844 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); 00845 if(!mLevel[ mMaxRefine ].mprsFlags[1] || !mLevel[ mMaxRefine ].mprsFlags[0]) { 00846 errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (2)! Aborting...",SIMWORLD_INITERROR); 00847 00848 #if COMPRESSGRIDS==0 00849 delete[] mLevel[ mMaxRefine ].mprsCells[0]; 00850 delete[] mLevel[ mMaxRefine ].mprsCells[1]; 00851 #else // COMPRESSGRIDS==0 00852 delete[] mLevel[ mMaxRefine ].mprsCells[1]; 00853 #endif // COMPRESSGRIDS==0 00854 return false; 00855 } 00856 00857 LbmFloat lcfdimFac = 8.0; 00858 if(LBMDIM==2) lcfdimFac = 4.0; 00859 for(int i=mMaxRefine-1; i>=0; i--) { 00860 mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize; 00861 mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize; 00862 mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac; 00863 00864 if(LBMDIM==2){ mLevel[i].lSizez = 1; } // 2D 00865 rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); 00866 mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; 00867 mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; 00868 ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); 00869 mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; 00870 mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; 00871 ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); 00872 } 00873 00874 // isosurface memory, use orig res values 00875 if(mFarFieldSize>0.) { 00876 ownMemCheck += (double)( (3*sizeof(int)+sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) ); 00877 } else { 00878 // ignore 3 int slices... 00879 ownMemCheck += (double)( ( sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) ); 00880 } 00881 00882 // sanity check 00883 #if ELBEEM_PLUGIN!=1 00884 if(ABS(1.0-ownMemCheck/memEstFromFunc)>0.01) { 00885 errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off! real:"<<ownMemCheck<<" vs. estimate:"<<memEstFromFunc ); 00886 } 00887 #endif // ELBEEM_PLUGIN!=1 00888 00889 // init sizes for _all_ levels 00890 for(int i=mMaxRefine; i>=0; i--) { 00891 mLevel[i].lOffsx = mLevel[i].lSizex; 00892 mLevel[i].lOffsy = mLevel[i].lOffsx*mLevel[i].lSizey; 00893 mLevel[i].lOffsz = mLevel[i].lOffsy*mLevel[i].lSizez; 00894 mLevel[i].setCurr = 0; 00895 mLevel[i].setOther = 1; 00896 mLevel[i].lsteps = 0; 00897 mLevel[i].lmass = 0.0; 00898 mLevel[i].lvolume = 0.0; 00899 } 00900 00901 // calc omega, force for all levels 00902 initLevelOmegas(); 00903 mMinTimestep = mpParam->getTimestep(); 00904 mMaxTimestep = mpParam->getTimestep(); 00905 00906 // init isosurf 00907 mpIso->setIsolevel( mIsoValue ); 00908 #if LBM_INCLUDE_TESTSOLVERS==1 00909 if(mUseTestdata) { 00910 mpTest->setMaterialName( mpIso->getMaterialName() ); 00911 delete mpIso; 00912 mpIso = mpTest; 00913 if(mpTest->mFarfMode>0) { // 3d off 00914 mpTest->setIsolevel(-100.0); 00915 } else { 00916 mpTest->setIsolevel( mIsoValue ); 00917 } 00918 } 00919 #endif // LBM_INCLUDE_TESTSOLVERS!=1 00920 // approximate feature size with mesh resolution 00921 float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5; 00922 // smooth vars defined in solver_interface, set by simulation object 00923 // reset for invalid values... 00924 if((mSmoothSurface<0.)||(mSmoothSurface>50.)) mSmoothSurface = 1.; 00925 if((mSmoothNormals<0.)||(mSmoothNormals>50.)) mSmoothNormals = 1.; 00926 mpIso->setSmoothSurface( mSmoothSurface * featureSize ); 00927 mpIso->setSmoothNormals( mSmoothNormals * featureSize ); 00928 00929 // init iso weight values mIsoWeightMethod 00930 int wcnt = 0; 00931 float totw = 0.0; 00932 for(int ak=-1;ak<=1;ak++) 00933 for(int aj=-1;aj<=1;aj++) 00934 for(int ai=-1;ai<=1;ai++) { 00935 switch(mIsoWeightMethod) { 00936 case 1: // light smoothing 00937 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); 00938 break; 00939 case 2: // very light smoothing 00940 mIsoWeight[wcnt] = sqrt(3.0) - sqrt( (LbmFloat)(ak*ak + aj*aj + ai*ai) ); 00941 mIsoWeight[wcnt] *= mIsoWeight[wcnt]; 00942 break; 00943 case 3: // no smoothing 00944 if(ai==0 && aj==0 && ak==0) mIsoWeight[wcnt] = 1.0; 00945 else mIsoWeight[wcnt] = 0.0; 00946 break; 00947 default: // strong smoothing (=0) 00948 mIsoWeight[wcnt] = 1.0; 00949 break; 00950 } 00951 totw += mIsoWeight[wcnt]; 00952 wcnt++; 00953 } 00954 for(int i=0; i<27; i++) mIsoWeight[i] /= totw; 00955 00956 LbmVec isostart = vec2L(mvGeoStart); 00957 LbmVec isoend = vec2L(mvGeoEnd); 00958 int twodOff = 0; // 2d slices 00959 if(LBMDIM==2) { 00960 LbmFloat sn,se; 00961 sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5; 00962 se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5; 00963 isostart[2] = sn; 00964 isoend[2] = se; 00965 twodOff = 2; 00966 } 00967 int isosx = mSizex+2; 00968 int isosy = mSizey+2; 00969 int isosz = mSizez+2+twodOff; 00970 00971 // MPT 00972 #if LBM_INCLUDE_TESTSOLVERS==1 00973 //if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) { 00974 if( (mMpNum>0) && (mMpIndex==0) ) { 00975 //? mpindex==0 00976 // restore original value for node0 00977 isosx = mOrgSizeX + 2; 00978 isostart[0] = mOrgStartX; 00979 isoend[0] = mOrgEndX; 00980 } 00981 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMin.mSrcx,mpTest->mGCMin.mSrcy,mpTest->mGCMin.mSrcz)<<" dst" 00982 << PRINT_VEC(mpTest->mGCMin.mDstx,mpTest->mGCMin.mDsty,mpTest->mGCMin.mDstz)<<" consize" 00983 << PRINT_VEC(mpTest->mGCMin.mConSizex,mpTest->mGCMin.mConSizey,mpTest->mGCMin.mConSizez)<<" "); 00984 errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMax.mSrcx,mpTest->mGCMax.mSrcy,mpTest->mGCMax.mSrcz)<<" dst" 00985 << PRINT_VEC(mpTest->mGCMax.mDstx,mpTest->mGCMax.mDsty,mpTest->mGCMax.mDstz)<<" consize" 00986 << PRINT_VEC(mpTest->mGCMax.mConSizex,mpTest->mGCMax.mConSizey,mpTest->mGCMax.mConSizez)<<" "); 00987 #endif // LBM_INCLUDE_TESTSOLVERS==1 00988 00989 errMsg(" SETISO ", "iso "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5)<<" "<<(LbmFloat)(mSizex+1.0) ); 00990 errMsg("LbmFsgrSolver::initialize", "MPT: geo "<< mvGeoStart<<","<<mvGeoEnd<< 00991 " grid:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<",iso:"<< PRINT_VEC(isosx,isosy,isosz) ); 00992 mpIso->setStart( vec2G(isostart) ); 00993 mpIso->setEnd( vec2G(isoend) ); 00994 LbmVec isodist = isoend-isostart; 00995 00996 int isosubs = mIsoSubdivs; 00997 if(mFarFieldSize>1.) { 00998 errMsg("LbmFsgrSolver::initialize","Warning - resetting isosubdivs, using fulledge!"); 00999 isosubs = 1; 01000 mpIso->setUseFulledgeArrays(true); 01001 } 01002 mpIso->setSubdivs(isosubs); 01003 01004 mpIso->initializeIsosurface( isosx,isosy,isosz, vec2G(isodist) ); 01005 01006 // reset iso field 01007 for(int ak=0;ak<isosz;ak++) 01008 for(int aj=0;aj<isosy;aj++) 01009 for(int ai=0;ai<isosx;ai++) { *mpIso->getData(ai,aj,ak) = 0.0; } 01010 01011 01012 /* init array (set all invalid first) */ 01013 preinitGrids(); 01014 for(int lev=0; lev<=mMaxRefine; lev++) { 01015 FSGR_FORIJK_BOUNDS(lev) { 01016 RFLAG(lev,i,j,k,0) = 0, RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage 01017 if(!mAllfluid) { 01018 initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0); 01019 } else { 01020 initEmptyCell(lev, i,j,k, CFFluid, 1.0, 1.0); 01021 } 01022 } 01023 } 01024 01025 01026 if(LBMDIM==2) { 01027 if(mOutputSurfacePreview) { 01028 errMsg("LbmFsgrSolver::init","No preview in 2D allowed!"); 01029 mOutputSurfacePreview = 0; } 01030 } 01031 if((glob_mpactive) && (glob_mpindex>0)) { 01032 mOutputSurfacePreview = 0; 01033 } 01034 01035 #if LBM_USE_GUI==1 01036 if(mOutputSurfacePreview) { 01037 errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0"); 01038 mOutputSurfacePreview = 0; } 01039 #endif // LBM_USE_GUI==1 01040 if(mOutputSurfacePreview) { 01041 // same as normal one, but use reduced size 01042 mpPreviewSurface = new IsoSurface( mIsoValue ); 01043 mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() ); 01044 mpPreviewSurface->setIsolevel( mIsoValue ); 01045 // usually dont display for rendering 01046 mpPreviewSurface->setVisible( false ); 01047 01048 mpPreviewSurface->setStart( vec2G(isostart) ); 01049 mpPreviewSurface->setEnd( vec2G(isoend) ); 01050 LbmVec pisodist = isoend-isostart; 01051 LbmFloat pfac = mPreviewFactor; 01052 mpPreviewSurface->initializeIsosurface( (int)(pfac*mSizex)+2, (int)(pfac*mSizey)+2, (int)(pfac*mSizez)+2, vec2G(pisodist) ); 01053 //mpPreviewSurface->setName( getName() + "preview" ); 01054 mpPreviewSurface->setName( "preview" ); 01055 01056 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*mSizex)<<","<<(pfac*mSizey)<<","<<(pfac*mSizez)<<" enabled",10); 01057 } 01058 01059 // init defaults 01060 mAvgNumUsedCells = 0; 01061 mFixMass= 0.0; 01062 return true; 01063 } 01064 01066 bool LbmFsgrSolver::initializeSolverGrids() { 01067 /* init boundaries */ 01068 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10); 01069 // init obstacles, and reinit time step size 01070 initGeometryFlags(); 01071 mLastSimTime = -1.0; 01072 // TODO check for invalid cells? nitGenericTestCases(); 01073 01074 // new - init noslip 1 everywhere... 01075 // half fill boundary cells? 01076 01077 CellFlagType domainBoundType = CFInvalid; 01078 // TODO use normal object types instad... 01079 if(mDomainBound.find(string("free")) != string::npos) { 01080 domainBoundType = CFBnd | CFBndFreeslip; 01081 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<mDomainBound,10); 01082 } else if(mDomainBound.find(string("part")) != string::npos) { 01083 domainBoundType = CFBnd | CFBndPartslip; // part slip type 01084 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10); 01085 } else { 01086 domainBoundType = CFBnd | CFBndNoslip; 01087 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10); 01088 } 01089 01090 // use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips) 01091 int domainobj = (int)(mpGiObjects->size()); 01092 domainBoundType |= (domainobj<<24); 01093 //for(int i=0; i<(int)(domainobj+0); i++) { 01094 //errMsg("GEOIN","i"<<i<<" "<<(*mpGiObjects)[i]->getName()); 01095 //if((*mpGiObjects)[i] == mpIso) { //check... 01096 //} 01097 //} 01098 //errMsg("GEOIN"," dm "<<(domainBoundType>>24)); 01099 01100 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) 01101 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { 01102 initEmptyCell(mMaxRefine, i,0,k, domainBoundType, 0.0, BND_FILL); 01103 initEmptyCell(mMaxRefine, i,mLevel[mMaxRefine].lSizey-1,k, domainBoundType, 0.0, BND_FILL); 01104 } 01105 01106 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) 01107 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { 01108 initEmptyCell(mMaxRefine, 0,j,k, domainBoundType, 0.0, BND_FILL); 01109 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-1,j,k, domainBoundType, 0.0, BND_FILL); 01110 // DEBUG BORDER! 01111 //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL); 01112 } 01113 01114 if(LBMDIM == 3) { 01115 // only for 3D 01116 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) 01117 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { 01118 initEmptyCell(mMaxRefine, i,j,0, domainBoundType, 0.0, BND_FILL); 01119 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-1, domainBoundType, 0.0, BND_FILL); 01120 } 01121 } 01122 01123 // TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 01124 /*for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) 01125 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { 01126 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL); 01127 } 01128 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) 01129 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { 01130 initEmptyCell(mMaxRefine, i,1,k, domainBoundType, 0.0, BND_FILL); 01131 } 01132 // */ 01133 01134 /*for(int ii=0; ii<(int)po w_change?(2.0,mMaxRefine)-1; ii++) { 01135 errMsg("BNDTESTSYMM","set "<<mLevel[mMaxRefine].lSizex-2-ii ); 01136 for(int k=0;k<mLevel[mMaxRefine].lSizez;k++) 01137 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { 01138 initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2-ii,j,k, domainBoundType, 0.0, BND_FILL); // SYMM!? 2D? 01139 } 01140 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) 01141 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { 01142 initEmptyCell(mMaxRefine, i,j,mLevel[mMaxRefine].lSizez-2-ii, domainBoundType, 0.0, BND_FILL); // SYMM!? 3D? 01143 } 01144 } 01145 // Symmetry tests */ 01146 // vortt 01147 #if LBM_INCLUDE_TESTSOLVERS==1 01148 if(( strstr( this->getName().c_str(), "vorttfluid" ) != NULL) && (LBMDIM==2)) { 01149 errMsg("VORTT","init"); 01150 int level=mMaxRefine; 01151 int cx = mLevel[level].lSizex/2; 01152 int cyo = mLevel[level].lSizey/2; 01153 int sx = mLevel[level].lSizex/8; 01154 int sy = mLevel[level].lSizey/8; 01155 LbmFloat rho = 1.; 01156 LbmFloat rhomass = 1.; 01157 LbmFloat uFactor = 0.15; 01158 LbmFloat vdist = 1.0; 01159 01160 int cy1=cyo-(int)(vdist*sy); 01161 int cy2=cyo+(int)(vdist*sy); 01162 01163 //for(int j=cy-sy;j<cy+sy;j++) for(int i=cx-sx;i<cx+sx;i++) { 01164 for(int j=1;j<mLevel[level].lSizey-1;j++) 01165 for(int i=1;i<mLevel[level].lSizex-1;i++) { 01166 LbmFloat d1 = norm(LbmVec(cx,cy1,0.)-LbmVec(i,j,0)); 01167 LbmFloat d2 = norm(LbmVec(cx,cy2,0.)-LbmVec(i,j,0)); 01168 bool in1 = (d1<=(LbmFloat)(sx)); 01169 bool in2 = (d2<=(LbmFloat)(sx)); 01170 LbmVec uvec(0.); 01171 LbmVec v1 = getNormalized( cross( LbmVec(cx,cy1,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor; 01172 LbmVec v2 = getNormalized( cross( LbmVec(cx,cy2,0.)-LbmVec(i,j,0), LbmVec(0.,0.,1.)) )* uFactor; 01173 LbmFloat w1=1., w2=1.; 01174 if(!in1) w1=(LbmFloat)(sx)/(1.5*d1); 01175 if(!in2) w2=(LbmFloat)(sx)/(1.5*d2); 01176 if(!in1) w1=0.; if(!in2) w2=0.; // sharp falloff 01177 uvec += v1*w1; 01178 uvec += v2*w2; 01179 initVelocityCell(level, i,j,0, CFFluid, rho, rhomass, uvec ); 01180 //errMsg("VORTT","init uvec"<<uvec); 01181 } 01182 01183 } 01184 #endif // LBM_INCLUDE_TESTSOLVERS==1 01185 01186 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal1, causing panic, aborting..."); return false; } 01187 01188 // prepare interface cells 01189 initFreeSurfaces(); 01190 initStandingFluidGradient(); 01191 01192 // perform first step to init initial mass 01193 mInitialMass = 0.0; 01194 int inmCellCnt = 0; 01195 FSGR_FORIJK1(mMaxRefine) { 01196 if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid) { 01197 LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0); 01198 FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); } 01199 mInitialMass += fluidRho; 01200 inmCellCnt ++; 01201 } else if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) { 01202 mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass); 01203 inmCellCnt ++; 01204 } 01205 } 01206 mCurrentVolume = mCurrentMass = mInitialMass; 01207 01208 ParamVec cspv = mpParam->calculateCellSize(); 01209 if(LBMDIM==2) cspv[2] = 1.0; 01210 inmCellCnt = 1; 01211 double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0; 01212 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<<mInitialMass<<" normalized:"<<nrmMass, 3); 01213 mInitialMass = 0.0; // reset, and use actual value after first step 01214 01215 //mStartSymm = false; 01216 #if ELBEEM_PLUGIN!=1 01217 if((LBMDIM==2)&&(mSizex<200)) { 01218 if(!checkSymmetry("init")) { 01219 errMsg("LbmFsgrSolver::initialize","Unsymmetric init..."); 01220 } else { 01221 errMsg("LbmFsgrSolver::initialize","Symmetric init!"); 01222 } 01223 } 01224 #endif // ELBEEM_PLUGIN!=1 01225 return true; 01226 } 01227 01228 01230 bool LbmFsgrSolver::initializeSolverPostinit() { 01231 // coarsen region 01232 myTime_t fsgrtstart = getTime(); 01233 for(int lev=mMaxRefine-1; lev>=0; lev--) { 01234 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Coarsening level "<<lev<<".",8); 01235 adaptGrid(lev); 01236 coarseRestrictFromFine(lev); 01237 adaptGrid(lev); 01238 coarseRestrictFromFine(lev); 01239 } 01240 markedClearList(); 01241 myTime_t fsgrtend = getTime(); 01242 if(!mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); } 01243 mNumFsgrChanges = 0; 01244 01245 for(int l=0; l<cDirNum; l++) { 01246 LbmFloat area = 0.5 * 0.5 *0.5; 01247 if(LBMDIM==2) area = 0.5 * 0.5; 01248 01249 if(dfVecX[l]!=0) area *= 0.5; 01250 if(dfVecY[l]!=0) area *= 0.5; 01251 if(dfVecZ[l]!=0) area *= 0.5; 01252 mFsgrCellArea[l] = area; 01253 } // l 01254 01255 // make sure both sets are ok 01256 // copy from other to curr 01257 for(int lev=0; lev<=mMaxRefine; lev++) { 01258 FSGR_FORIJK_BOUNDS(lev) { 01259 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr); 01260 } } // first copy flags */ 01261 01262 01263 // old mpPreviewSurface init 01264 //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal2, causing panic, aborting..."); return false; } 01265 // make sure fill fracs are right for first surface generation 01266 stepMain(); 01267 01268 // prepare once... 01269 mpIso->setParticles(mpParticles, mPartDropMassSub); 01270 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Iso Settings, subdivs="<<mpIso->getSubdivs()<<", partsize="<<mPartDropMassSub, 9); 01271 prepareVisualization(); 01272 // copy again for stats counting 01273 for(int lev=0; lev<=mMaxRefine; lev++) { 01274 FSGR_FORIJK_BOUNDS(lev) { 01275 RFLAG(lev, i,j,k,mLevel[lev].setOther) = RFLAG(lev, i,j,k,mLevel[lev].setCurr); 01276 } } // first copy flags */ 01277 01278 01279 // now really done... 01280 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"SurfaceGen: SmsOrg("<<mSmoothSurface<<","<<mSmoothNormals<< /*","<<featureSize<<*/ "), Iso("<<mpIso->getSmoothSurface()<<","<<mpIso->getSmoothNormals()<<") ",10); 01281 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init done ... ",10); 01282 mInitDone = 1; 01283 01284 // init fluid control 01285 initCpdata(); 01286 01287 #if LBM_INCLUDE_TESTSOLVERS==1 01288 initTestdata(); 01289 #endif // ELBEEM_PLUGIN!=1 01290 // not inited? dont use... 01291 if(mCutoff<0) mCutoff=0; 01292 01293 initParticles(); 01294 return true; 01295 } 01296 01297 01298 01299 // macros for mov obj init 01300 #if LBMDIM==2 01301 01302 #define POS2GRID_CHECK(vec,n) \ 01303 monTotal++;\ 01304 int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \ 01305 if(k!=0) continue; \ 01306 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ 01307 if(i<=0) continue; \ 01308 if(i>=mLevel[level].lSizex-1) continue; \ 01309 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ 01310 if(j<=0) continue; \ 01311 if(j>=mLevel[level].lSizey-1) continue; \ 01312 01313 #else // LBMDIM -> 3 01314 #define POS2GRID_CHECK(vec,n) \ 01315 monTotal++;\ 01316 const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ 01317 if(i<=0) continue; \ 01318 if(i>=mLevel[level].lSizex-1) continue; \ 01319 const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ 01320 if(j<=0) continue; \ 01321 if(j>=mLevel[level].lSizey-1) continue; \ 01322 const int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \ 01323 if(k<=0) continue; \ 01324 if(k>=mLevel[level].lSizez-1) continue; \ 01325 01326 #endif // LBMDIM 01327 01328 // calculate object velocity from vert arrays in objvel vec 01329 #define OBJVEL_CALC \ 01330 LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { \ 01331 const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; \ 01332 USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); \ 01333 if(usqr>maxusqr) { \ 01334 /* cutoff at maxVelVal */ \ 01335 for(int jj=0; jj<3; jj++) { \ 01336 if(objvel[jj]>0.) objvel[jj] = maxVelVal; \ 01337 if(objvel[jj]<0.) objvel[jj] = -maxVelVal; \ 01338 } \ 01339 } } \ 01340 if(ntype&(CFBndFreeslip)) { \ 01341 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \ 01342 const LbmVec oldov=objvel; /*DEBUG*/ \ 01343 objvel = vec2L((*pNormals)[n]) *dp; \ 01344 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \ 01345 } \ 01346 else if(ntype&(CFBndPartslip)) { \ 01347 const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); \ 01348 const LbmVec oldov=objvel; /*DEBUG*/ \ 01349 /* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \ 01350 const LbmFloat partv = mObjectPartslips[OId]; \ 01351 /*errMsg("PARTSLIP_DEBUG","l="<<l<<" ccel="<<RAC(ccel, dfInv[l] )<<" partv="<<partv<<",id="<<(int)(mnbf>>24)<<" newval="<<newval ); / part slip debug */ \ 01352 /* m[l] = (RAC(ccel, dfInv[l] ) ) * partv + newval * (1.-partv); part slip */ \ 01353 objvel = objvel*partv + vec2L((*pNormals)[n]) *dp*(1.-partv); \ 01354 } 01355 01356 #define TTT \ 01357 01358 01359 /*****************************************************************************/ 01361 /*****************************************************************************/ 01362 void LbmFsgrSolver::initMovingObstacles(bool staticInit) { 01363 myTime_t monstart = getTime(); 01364 01365 // movobj init 01366 const int level = mMaxRefine; 01367 const int workSet = mLevel[level].setCurr; 01368 const int otherSet = mLevel[level].setOther; 01369 LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime! 01370 // for debugging - check targetTime check during DEFAULT STREAM 01371 LbmFloat targetTime = mSimulationTime + mpParam->getTimestep(); 01372 if(mLastSimTime == targetTime) { 01373 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"Called for same time! (t="<<mSimulationTime<<" , targett="<<targetTime<<")", 1); 01374 return; 01375 } 01376 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime,10); 01377 //if(mSimulationTime!=mLastSimTime) errMsg("LbmFsgrSolver::initMovingObstacles","time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime); 01378 01379 const LbmFloat maxVelVal = 0.1666; 01380 const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; 01381 01382 LbmFloat rhomass = 0.0; 01383 CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs! 01384 CellFlagType ntype = CFInvalid; 01385 // WARNING - copied from geo init! 01386 int numobjs = (int)(mpGiObjects->size()); 01387 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; 01388 // 2d display as rectangles 01389 ntlVec3Gfx iniPos(0.0); 01390 if(LBMDIM==2) { 01391 dvec[2] = 1.0; 01392 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))-(dvec*0.0); 01393 } else { 01394 iniPos = (mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0); 01395 } 01396 01397 if( (int)mObjectMassMovnd.size() < numobjs) { 01398 for(int i=mObjectMassMovnd.size(); i<numobjs; i++) { 01399 mObjectMassMovnd.push_back(0.); 01400 } 01401 } 01402 01403 // stats 01404 int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0; 01405 int nbored; 01406 for(int OId=0; OId<numobjs; OId++) { 01407 ntlGeometryObject *obj = (*mpGiObjects)[OId]; 01408 bool skip = false; 01409 if(obj->getGeoInitId() != mLbmInitId) skip=true; 01410 if( (!staticInit) && (!obj->getIsAnimated()) ) skip=true; 01411 if( ( staticInit) && ( obj->getIsAnimated()) ) skip=true; 01412 if(skip) continue; 01413 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" skip:"<<skip<<", static:"<<staticInit<<" anim:"<<obj->getIsAnimated()<<" gid:"<<obj->getGeoInitId()<<" simgid:"<<mLbmInitId, 10); 01414 01415 if( (obj->getGeoInitType()&FGI_ALLBOUNDS) || 01416 ((obj->getGeoInitType()&FGI_FLUID) && staticInit) ) { 01417 01418 otype = ntype = CFInvalid; 01419 switch(obj->getGeoInitType()) { 01420 /* case FGI_BNDPART: // old, use noslip for moving part/free objs 01421 case FGI_BNDFREE: 01422 if(!staticInit) { 01423 errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() ); 01424 otype = ntype = CFBnd|CFBndNoslip; 01425 } else { 01426 if(obj->getGeoInitType()==FGI_BNDPART) otype = ntype = CFBnd|CFBndPartslip; 01427 if(obj->getGeoInitType()==FGI_BNDFREE) otype = ntype = CFBnd|CFBndFreeslip; 01428 } 01429 break; 01430 // off */ 01431 case FGI_BNDPART: rhomass = BND_FILL; 01432 otype = ntype = CFBnd|CFBndPartslip|(OId<<24); 01433 break; 01434 case FGI_BNDFREE: rhomass = BND_FILL; 01435 otype = ntype = CFBnd|CFBndFreeslip|(OId<<24); 01436 break; 01437 // off */ 01438 case FGI_BNDNO: rhomass = BND_FILL; 01439 otype = ntype = CFBnd|CFBndNoslip|(OId<<24); 01440 break; 01441 case FGI_FLUID: 01442 otype = ntype = CFFluid; 01443 break; 01444 case FGI_MBNDINFLOW: 01445 otype = ntype = CFMbndInflow; 01446 break; 01447 case FGI_MBNDOUTFLOW: 01448 otype = ntype = CFMbndOutflow; 01449 break; 01450 } 01451 int wasActive = ((obj->getGeoActive(sourceTime)>0.)? 1:0); 01452 int active = ((obj->getGeoActive(targetTime)>0.)? 1:0); 01453 //errMsg("GEOACTT"," obj "<<obj->getName()<<" a:"<<active<<","<<wasActive<<" s"<<sourceTime<<" t"<<targetTime <<" v"<<mObjectSpeeds[OId] ); 01454 // skip inactive in/out flows 01455 if(ntype==CFInvalid){ errMsg("LbmFsgrSolver::initMovingObstacles","Invalid obj type "<<obj->getGeoInitType()); continue; } 01456 if((!active) && (otype&(CFMbndOutflow|CFMbndInflow)) ) continue; 01457 01458 // copied from recalculateObjectSpeeds 01459 mObjectSpeeds[OId] = vec2L(mpParam->calculateLattVelocityFromRw( vec2P( (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ))); 01460 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 ); 01461 01462 //vector<ntlVec3Gfx> tNormals; 01463 vector<ntlVec3Gfx> *pNormals = NULL; 01464 mMOINormals.clear(); 01465 if(ntype&(CFBndFreeslip|CFBndPartslip)) { pNormals = &mMOINormals; } 01466 01467 mMOIVertices.clear(); 01468 if(obj->getMeshAnimated()) { 01469 // do two full update 01470 // TODO tNormals handling!? 01471 mMOIVerticesOld.clear(); 01472 obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, pNormals, mLevel[mMaxRefine].nodeSize, mvGeoStart, mvGeoEnd); 01473 monTrafo += mMOIVerticesOld.size(); 01474 obj->applyTransformation(sourceTime, &mMOIVerticesOld,pNormals, 0, mMOIVerticesOld.size(), false ); 01475 monTrafo += mMOIVertices.size(); 01476 obj->applyTransformation(targetTime, &mMOIVertices,NULL /* no old normals needed */, 0, mMOIVertices.size(), false ); 01477 } else { 01478 // only do transform update 01479 obj->getMovingPoints(mMOIVertices,pNormals); // mMOIVertices = mCachedMovPoints 01480 mMOIVerticesOld = mMOIVertices; 01481 // WARNING - assumes mSimulationTime is global!? 01482 obj->applyTransformation(targetTime, &mMOIVertices,pNormals, 0, mMOIVertices.size(), false ); 01483 monTrafo += mMOIVertices.size(); 01484 01485 // correct flags from last position, but extrapolate 01486 // velocity to next timestep 01487 obj->applyTransformation(sourceTime, &mMOIVerticesOld, NULL /* no old normals needed */, 0, mMOIVerticesOld.size(), false ); 01488 monTrafo += mMOIVerticesOld.size(); 01489 } 01490 01491 // object types 01492 if(ntype&CFBnd){ 01493 01494 // check if object is moving at all 01495 if(obj->getIsAnimated()) { 01496 ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime); 01497 // FIXME? 01498 if(normNoSqrt(objMaxVel)>0.0) { ntype |= CFBndMoving; } 01499 // get old type - CHECK FIXME , timestep could have changed - cause trouble? 01500 ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - mpParam->getTimestep(),sourceTime); 01501 if(normNoSqrt(oldobjMaxVel)>0.0) { otype |= CFBndMoving; } 01502 } 01503 if(obj->getMeshAnimated()) { ntype |= CFBndMoving; otype |= CFBndMoving; } 01504 CellFlagType rflagnb[27]; 01505 LbmFloat massCheck = 0.; 01506 int massReinits=0; 01507 bool fillCells = (mObjectMassMovnd[OId]<=-1.); 01508 LbmFloat impactCorrFactor = obj->getGeoImpactFactor(targetTime); 01509 01510 01511 // first pass - set new obs. cells 01512 if(active) { 01513 for(size_t n=0; n<mMOIVertices.size(); n++) { 01514 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK); 01515 POS2GRID_CHECK(mMOIVertices,n); 01516 //{ errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<", t="<<targetTime); } 01517 if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue; 01518 monPoints++; 01519 01520 // check mass 01521 if(RFLAG(level, i,j,k, workSet)&(CFFluid)) { 01522 FORDF0 { massCheck -= QCELL(level, i,j,k, workSet, l); } 01523 massReinits++; 01524 } 01525 else if(RFLAG(level, i,j,k, workSet)&(CFInter)) { 01526 massCheck -= QCELL(level, i,j,k, workSet, dMass); 01527 massReinits++; 01528 } 01529 01530 RFLAG(level, i,j,k, workSet) = ntype; 01531 FORDF1 { 01532 //CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l); 01533 rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l); 01534 if(rflagnb[l]&(CFFluid|CFInter)) { 01535 rflagnb[l] &= (~CFNoBndFluid); // remove CFNoBndFluid flag 01536 RFLAG_NB(level, i,j,k,workSet,l) &= rflagnb[l]; 01537 } 01538 } 01539 LbmFloat *dstCell = RACPNT(level, i,j,k,workSet); 01540 RAC(dstCell,0) = 0.0; 01541 if(ntype&CFBndMoving) { 01542 OBJVEL_CALC; 01543 01544 // compute fluid acceleration 01545 FORDF1 { 01546 if(rflagnb[l]&(CFFluid|CFInter)) { 01547 const LbmFloat ux = dfDvecX[l]*objvel[0]; 01548 const LbmFloat uy = dfDvecY[l]*objvel[1]; 01549 const LbmFloat uz = dfDvecZ[l]*objvel[2]; 01550 01551 LbmFloat factor = 2. * dfLength[l] * 3.0 * (ux+uy+uz); // 01552 if(ntype&(CFBndFreeslip|CFBndPartslip)) { 01553 // missing, diag mass checks... 01554 //if(l<=LBMDIM*2) factor *= 1.4142; 01555 factor *= 2.0; // TODO, optimize 01556 } else { 01557 factor *= 1.2; // TODO, optimize 01558 } 01559 factor *= impactCorrFactor; // use manual tweaking channel 01560 RAC(dstCell,l) = factor; 01561 massCheck += factor; 01562 } else { 01563 RAC(dstCell,l) = 0.; 01564 } 01565 } 01566 01567 #if NEWDIRVELMOTEST==1 01568 FORDF1 { RAC(dstCell,l) = 0.; } 01569 RAC(dstCell,dMass) = objvel[0]; 01570 RAC(dstCell,dFfrac) = objvel[1]; 01571 RAC(dstCell,dC) = objvel[2]; 01572 #endif // NEWDIRVELMOTEST==1 01573 } else { 01574 FORDF1 { RAC(dstCell,l) = 0.0; } 01575 } 01576 RAC(dstCell, dFlux) = targetTime; 01577 //errMsg("initMovingObstacles_Debug","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" dflt="<<RAC(dstCell, dFlux) ); 01578 monObsts++; 01579 } // points 01580 } // bnd, is active? 01581 01582 // second pass, remove old ones 01583 // warning - initEmptyCell et. al dont overwrite OId or persist flags... 01584 if(wasActive) { 01585 for(size_t n=0; n<mMOIVerticesOld.size(); n++) { 01586 POS2GRID_CHECK(mMOIVerticesOld,n); 01587 monPoints++; 01588 if((RFLAG(level, i,j,k, workSet) == otype) && 01589 (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) { 01590 // from mainloop 01591 nbored = 0; 01592 // TODO: optimize for OPT3D==0 01593 FORDF1 { 01594 //rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l); 01595 rflagnb[l] = RFLAG_NB(level, i,j,k,otherSet,l); // test use other set to not have loop dependance 01596 nbored |= rflagnb[l]; 01597 } 01598 CellFlagType settype = CFInvalid; 01599 if(nbored&CFFluid) { 01600 settype = CFInter|CFNoInterpolSrc; 01601 rhomass = 1.5; 01602 if(!fillCells) rhomass = 0.; 01603 01604 OBJVEL_CALC; 01605 if(!(nbored&CFEmpty)) { settype=CFFluid|CFNoInterpolSrc; rhomass=1.; } 01606 01607 // new interpolate values 01608 LbmFloat avgrho = 0.0; 01609 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; 01610 interpolateCellValues(level,i,j,k,workSet, avgrho,avgux,avguy,avguz); 01611 initVelocityCell(level, i,j,k, settype, avgrho, rhomass, LbmVec(avgux,avguy,avguz) ); 01612 //errMsg("NMOCIT"," at "<<PRINT_IJK<<" "<<avgrho<<" "<<norm(LbmVec(avgux,avguy,avguz))<<" "<<LbmVec(avgux,avguy,avguz) ); 01613 massCheck += rhomass; 01614 } else { 01615 settype = CFEmpty; rhomass = 0.0; 01616 initEmptyCell(level, i,j,k, settype, 1., rhomass ); 01617 } 01618 monFluids++; 01619 massReinits++; 01620 } // flag & simtime 01621 } 01622 } // wasactive 01623 01624 // only compute mass transfer when init is done 01625 if(mInitDone) { 01626 errMsg("initMov","dccd\n\nMassd test "<<obj->getName()<<" dccd massCheck="<<massCheck<<" massReinits"<<massReinits<< 01627 " fillCells"<<fillCells<<" massmovbnd:"<<mObjectMassMovnd[OId]<<" inim:"<<mInitialMass ); 01628 mObjectMassMovnd[OId] += massCheck; 01629 } 01630 } // bnd, active 01631 01632 else if(ntype&CFFluid){ 01633 // second static init pass 01634 if(staticInit) { 01635 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" verts"<<mMOIVertices.size() ,9); 01636 CellFlagType setflflag = CFFluid; //|(OId<<24); 01637 for(size_t n=0; n<mMOIVertices.size(); n++) { 01638 POS2GRID_CHECK(mMOIVertices,n); 01639 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } 01640 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { 01641 //changeFlag(level, i,j,k, workSet, setflflag); 01642 initVelocityCell(level, i,j,k, setflflag, 1., 1., mObjectSpeeds[OId] ); 01643 } 01644 //else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); } 01645 } 01646 } // second static inflow pass 01647 } // fluid 01648 01649 else if(ntype&CFMbndInflow){ 01650 // inflow pass - add new fluid cells 01651 // this is slightly different for standing inflows, 01652 // as the fluid is forced to the desired velocity inside as 01653 // well... 01654 const LbmFloat iniRho = 1.0; 01655 const LbmVec vel(mObjectSpeeds[OId]); 01656 const LbmFloat usqr = (vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])*1.5; 01657 USQRMAXCHECK(usqr,vel[0],vel[1],vel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); 01658 //errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<mMOIVertices.size() ); 01659 01660 for(size_t n=0; n<mMOIVertices.size(); n++) { 01661 POS2GRID_CHECK(mMOIVertices,n); 01662 // TODO - also reinit interface cells !? 01663 if(RFLAG(level, i,j,k, workSet)!=CFEmpty) { 01664 // test prevent particle gen for inflow inter cells 01665 if(RFLAG(level, i,j,k, workSet)&(CFInter)) { RFLAG(level, i,j,k, workSet) &= (~CFNoBndFluid); } // remove CFNoBndFluid flag 01666 continue; } 01667 monFluids++; 01668 01669 // TODO add OPT3D treatment 01670 LbmFloat *tcel = RACPNT(level, i,j,k,workSet); 01671 FORDF0 { RAC(tcel, l) = this->getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } 01672 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; 01673 RAC(tcel, dFlux) = FLUX_INIT; 01674 CellFlagType setFlag = CFInter; 01675 changeFlag(level, i,j,k, workSet, setFlag); 01676 mInitialMass += iniRho; 01677 } 01678 // second static init pass 01679 if(staticInit) { 01680 CellFlagType set2Flag = CFMbndInflow|(OId<<24); 01681 for(size_t n=0; n<mMOIVertices.size(); n++) { 01682 POS2GRID_CHECK(mMOIVertices,n); 01683 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } 01684 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { 01685 forceChangeFlag(level, i,j,k, workSet, set2Flag); 01686 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { 01687 forceChangeFlag(level, i,j,k, workSet, 01688 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag); 01689 } 01690 } 01691 } // second static inflow pass 01692 01693 } // inflow 01694 01695 else if(ntype&CFMbndOutflow){ 01696 const LbmFloat iniRho = 0.0; 01697 for(size_t n=0; n<mMOIVertices.size(); n++) { 01698 POS2GRID_CHECK(mMOIVertices,n); 01699 // FIXME check fluid/inter cells for non-static!? 01700 if(!(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter))) { 01701 if((staticInit)&&(RFLAG(level, i,j,k, workSet)==CFEmpty)) { 01702 forceChangeFlag(level, i,j,k, workSet, CFMbndOutflow); } 01703 continue; 01704 } 01705 monFluids++; 01706 // interface cell - might be double empty? FIXME check? 01707 01708 // remove fluid cells, shouldnt be here anyway 01709 LbmFloat *tcel = RACPNT(level, i,j,k,workSet); 01710 LbmFloat fluidRho = RAC(tcel,0); FORDF1 { fluidRho += RAC(tcel,l); } 01711 mInitialMass -= fluidRho; 01712 RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; 01713 RAC(tcel, dFlux) = FLUX_INIT; 01714 CellFlagType setFlag = CFInter; 01715 changeFlag(level, i,j,k, workSet, setFlag); 01716 01717 // same as ifemptied for if below 01718 LbmPoint emptyp; 01719 emptyp.x = i; emptyp.y = j; emptyp.z = k; 01720 mListEmpty.push_back( emptyp ); 01721 //calcCellsEmptied++; 01722 } // points 01723 // second static init pass 01724 if(staticInit) { 01725 CellFlagType set2Flag = CFMbndOutflow|(OId<<24); 01726 for(size_t n=0; n<mMOIVertices.size(); n++) { 01727 POS2GRID_CHECK(mMOIVertices,n); 01728 if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } 01729 if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { 01730 forceChangeFlag(level, i,j,k, workSet, set2Flag); 01731 } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { 01732 forceChangeFlag(level, i,j,k, workSet, 01733 (RFLAG(level, i,j,k, workSet)&CFNoPersistMask)|set2Flag); 01734 } 01735 } 01736 } // second static outflow pass 01737 } // outflow 01738 01739 } // allbound check 01740 } // OId 01741 01742 01743 /* { // DEBUG check 01744 int workSet = mLevel[level].setCurr; 01745 FSGR_FORIJK1(level) { 01746 if( (RFLAG(level,i,j,k, workSet) & CFBndMoving) ) { 01747 if(QCELL(level, i,j,k, workSet, dFlux)!=targetTime) { 01748 errMsg("lastt"," old val!? at "<<PRINT_IJK<<" t="<<QCELL(level, i,j,k, workSet, dFlux)<<" target="<<targetTime); 01749 } 01750 } 01751 } 01752 } // DEBUG */ 01753 01754 #undef POS2GRID_CHECK 01755 myTime_t monend = getTime(); 01756 if(monend-monstart>0) debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7); 01757 mLastSimTime = targetTime; 01758 } 01759 01760 01761 // geoinit position 01762 01763 #define GETPOS(i,j,k) \ 01764 ntlVec3Gfx ggpos = \ 01765 ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \ 01766 iniPos[1]+ dvec[1]*(gfxReal)(j), \ 01767 iniPos[2]+ dvec[2]*(gfxReal)(k) ); \ 01768 if((LBMDIM==2)&&(mInit2dYZ)) { SWAPYZ(ggpos); } 01769 01770 /*****************************************************************************/ 01772 /*****************************************************************************/ 01773 extern int globGeoInitDebug; //solver_interface 01774 bool LbmFsgrSolver::initGeometryFlags() { 01775 int level = mMaxRefine; 01776 myTime_t geotimestart = getTime(); 01777 ntlGeometryObject *pObj; 01778 ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; 01779 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< mLbmInitId <<") v"<<dvec,3); 01780 // WARNING - copied to movobj init! 01781 01782 /* init object velocities, this has always to be called for init */ 01783 initGeoTree(); 01784 if(mAllfluid) { 01785 freeGeoTree(); 01786 return true; } 01787 01788 // make sure moving obstacles are inited correctly 01789 // preinit moving obj points 01790 int numobjs = (int)(mpGiObjects->size()); 01791 for(int o=0; o<numobjs; o++) { 01792 ntlGeometryObject *obj = (*mpGiObjects)[o]; 01793 //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9); 01794 if( 01795 ((obj->getGeoInitType()&FGI_ALLBOUNDS) && (obj->getIsAnimated())) || 01796 (obj->getVolumeInit()&VOLUMEINIT_SHELL) ) { 01797 if(!obj->getMeshAnimated()) { 01798 debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9); 01799 obj->initMovingPoints(mSimulationTime, mLevel[mMaxRefine].nodeSize); 01800 } 01801 } 01802 } 01803 01804 // max speed init 01805 ntlVec3Gfx maxMovobjVelRw = getGeoMaxMovementVelocity( mSimulationTime, mpParam->getTimestep() ); 01806 ntlVec3Gfx maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) ); 01807 mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) ); 01808 LbmFloat allowMax = mpParam->getTadapMaxSpeed(); // maximum allowed velocity 01809 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxMovobjVel <<" from mov. obj.="<<maxMovobjVelRw<<" , allowed Max="<<allowMax ,5); 01810 if(mpParam->getSimulationMaxSpeed() > allowMax) { 01811 // similar to adaptTimestep(); 01812 LbmFloat nextmax = mpParam->getSimulationMaxSpeed(); 01813 LbmFloat newdt = mpParam->getTimestep() * (allowMax / nextmax); // newtr 01814 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< mpParam->getTimestep() <<" ",5); 01815 mpParam->setDesiredTimestep( newdt ); 01816 mpParam->calculateAllMissingValues( mSimulationTime, mSilent ); 01817 maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P(getGeoMaxMovementVelocity( 01818 mSimulationTime, mpParam->getTimestep() )) )); 01819 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxMovobjVel,5); 01820 } 01821 recalculateObjectSpeeds(); 01822 // */ 01823 01824 // init obstacles for first time step (requires obj speeds) 01825 initMovingObstacles(true); 01826 01827 /* set interface cells */ 01828 ntlVec3Gfx pos,iniPos; // position of current cell 01829 LbmFloat rhomass = 0.0; 01830 CellFlagType ntype = CFInvalid; 01831 int savedNodes = 0; 01832 int OId = -1; 01833 gfxReal distance; 01834 01835 // 2d display as rectangles 01836 if(LBMDIM==2) { 01837 dvec[2] = 0.0; 01838 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))+(dvec*0.5); 01839 //if(mInit2dYZ) { SWAPYZ(mGravity); for(int lev=0; lev<=mMaxRefine; lev++){ SWAPYZ( mLevel[lev].gravity ); } } 01840 } else { 01841 iniPos =(mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5); 01842 } 01843 01844 01845 // first init boundary conditions 01846 // invalid cells are set to empty afterwards 01847 // TODO use floop macros!? 01848 for(int k= getForZMin1(); k< getForZMax1(level); ++k) { 01849 for(int j=1;j<mLevel[level].lSizey-1;j++) { 01850 for(int i=1;i<mLevel[level].lSizex-1;i++) { 01851 ntype = CFInvalid; 01852 01853 GETPOS(i,j,k); 01854 const bool inside = geoInitCheckPointInside( ggpos, FGI_ALLBOUNDS, OId, distance); 01855 if(inside) { 01856 pObj = (*mpGiObjects)[OId]; 01857 switch( pObj->getGeoInitType() ){ 01858 case FGI_MBNDINFLOW: 01859 if(! pObj->getIsAnimated() ) { 01860 rhomass = 1.0; 01861 ntype = CFFluid | CFMbndInflow; 01862 } else { 01863 ntype = CFInvalid; 01864 } 01865 break; 01866 case FGI_MBNDOUTFLOW: 01867 if(! pObj->getIsAnimated() ) { 01868 rhomass = 0.0; 01869 ntype = CFEmpty|CFMbndOutflow; 01870 } else { 01871 ntype = CFInvalid; 01872 } 01873 break; 01874 case FGI_BNDNO: 01875 rhomass = BND_FILL; 01876 ntype = CFBnd|CFBndNoslip; 01877 break; 01878 case FGI_BNDPART: 01879 rhomass = BND_FILL; 01880 ntype = CFBnd|CFBndPartslip; break; 01881 case FGI_BNDFREE: 01882 rhomass = BND_FILL; 01883 ntype = CFBnd|CFBndFreeslip; break; 01884 default: // warn here? 01885 rhomass = BND_FILL; 01886 ntype = CFBnd|CFBndNoslip; break; 01887 } 01888 } 01889 if(ntype != CFInvalid) { 01890 // initDefaultCell 01891 if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { } 01892 ntype |= (OId<<24); // NEWTEST2 01893 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); 01894 } 01895 01896 // walk along x until hit for following inits 01897 if(distance<=-1.0) { distance = 100.0; } // FIXME dangerous 01898 if(distance>=0.0) { 01899 gfxReal dcnt=dvec[0]; 01900 while(( dcnt< distance-dvec[0] )&&(i+1<mLevel[level].lSizex-1)) { 01901 dcnt += dvec[0]; i++; 01902 savedNodes++; 01903 if(ntype != CFInvalid) { 01904 // rho,mass,OId are still inited from above 01905 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); 01906 } 01907 } 01908 } 01909 // */ 01910 01911 } 01912 } 01913 } // zmax 01914 // */ 01915 01916 // now init fluid layer 01917 for(int k= getForZMin1(); k< getForZMax1(level); ++k) { 01918 for(int j=1;j<mLevel[level].lSizey-1;j++) { 01919 for(int i=1;i<mLevel[level].lSizex-1;i++) { 01920 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; 01921 ntype = CFInvalid; 01922 int inits = 0; 01923 GETPOS(i,j,k); 01924 const bool inside = geoInitCheckPointInside( ggpos, FGI_FLUID, OId, distance); 01925 if(inside) { 01926 ntype = CFFluid; 01927 } 01928 if(ntype != CFInvalid) { 01929 // initDefaultCell 01930 rhomass = 1.0; 01931 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); 01932 inits++; 01933 } 01934 01935 // walk along x until hit for following inits 01936 if(distance<=-1.0) { distance = 100.0; } 01937 if(distance>=0.0) { 01938 gfxReal dcnt=dvec[0]; 01939 while((dcnt< distance )&&(i+1<mLevel[level].lSizex-1)) { 01940 dcnt += dvec[0]; i++; 01941 savedNodes++; 01942 if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; 01943 if(ntype != CFInvalid) { 01944 // rhomass are still inited from above 01945 initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); 01946 inits++; 01947 } 01948 } 01949 } // distance>0 01950 01951 } 01952 } 01953 } // zmax 01954 01955 // reset invalid to empty again 01956 for(int k= getForZMin1(); k< getForZMax1(level); ++k) { 01957 for(int j=1;j<mLevel[level].lSizey-1;j++) { 01958 for(int i=1;i<mLevel[level].lSizex-1;i++) { 01959 if(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFInvalid) { 01960 RFLAG(level, i,j,k, mLevel[level].setOther) = 01961 RFLAG(level, i,j,k, mLevel[level].setCurr) = CFEmpty; 01962 } 01963 } 01964 } 01965 } 01966 01967 freeGeoTree(); 01968 myTime_t geotimeend = getTime(); 01969 debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< getTimeString(geotimeend-geotimestart)<<","<<savedNodes<<") " , 10 ); 01970 //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez)); 01971 return true; 01972 } 01973 01974 #undef GETPOS 01975 01976 /*****************************************************************************/ 01977 /* init part for all freesurface testcases */ 01978 void LbmFsgrSolver::initFreeSurfaces() { 01979 double interfaceFill = 0.45; // filling level of interface cells 01980 //interfaceFill = 1.0; // DEUG!! GEOMTEST!!!!!!!!!!!! 01981 01982 // set interface cells 01983 FSGR_FORIJK1(mMaxRefine) { 01984 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid )) { 01985 FORDF1 { 01986 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l]; 01987 if( ( RFLAG(mMaxRefine, ni, nj, nk, mLevel[mMaxRefine].setCurr)& CFEmpty ) ) { 01988 LbmFloat arho=0., aux=0., auy=0., auz=0.; 01989 interpolateCellValues(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz); 01990 //errMsg("TINI"," "<<PRINT_VEC(ni,nj,nk)<<" v"<<LbmVec(aux,auy,auz) ); 01991 // unnecessary? initEmptyCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill); 01992 initVelocityCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill, LbmVec(aux,auy,auz) ); 01993 } 01994 } 01995 } 01996 } 01997 01998 // remove invalid interface cells 01999 FSGR_FORIJK1(mMaxRefine) { 02000 // remove invalid interface cells 02001 if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) ) { 02002 int delit = 0; 02003 int NBs = 0; // neighbor flags or'ed 02004 int noEmptyNB = 1; 02005 02006 FORDF1 { 02007 if( ( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l )& CFEmpty ) ) { 02008 noEmptyNB = 0; 02009 } 02010 NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l); 02011 } 02012 // remove cells with no fluid or interface neighbors 02013 if((NBs & CFFluid)==0) { delit = 1; } 02014 if((NBs & CFInter)==0) { delit = 1; } 02015 // remove cells with no empty neighbors 02016 if(noEmptyNB) { delit = 2; } 02017 02018 // now we can remove the cell 02019 if(delit==1) { 02020 initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0); 02021 } 02022 if(delit==2) { 02023 //initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); 02024 LbmFloat arho=0., aux=0., auy=0., auz=0.; 02025 interpolateCellValues(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz); 02026 initVelocityCell(mMaxRefine, i,j,k, CFFluid, arho,1., LbmVec(aux,auy,auz) ); 02027 } 02028 } // interface 02029 } // */ 02030 02031 // another brute force init, make sure the fill values are right... 02032 // and make sure both sets are equal 02033 for(int lev=0; lev<=mMaxRefine; lev++) { 02034 FSGR_FORIJK_BOUNDS(lev) { 02035 if( (RFLAG(lev, i,j,k,0) & (CFBnd)) ) { 02036 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = BND_FILL; 02037 continue; 02038 } 02039 if( (RFLAG(lev, i,j,k,0) & (CFEmpty)) ) { 02040 QCELL(lev, i,j,k,mLevel[mMaxRefine].setCurr, dFfrac) = 0.0; 02041 continue; 02042 } 02043 } } 02044 02045 // ---------------------------------------------------------------------- 02046 // smoother surface... 02047 if(mInitSurfaceSmoothing>0) { 02048 debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing timestep ",10); 02049 #if COMPRESSGRIDS==1 02050 //errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return; 02051 #endif // COMPRESSGRIDS==0 02052 } 02053 for(int s=0; s<mInitSurfaceSmoothing; s++) { 02054 //SGR_FORIJK1(mMaxRefine) { 02055 02056 int kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); 02057 int lev = mMaxRefine; 02058 #if COMPRESSGRIDS==0 02059 for(int k=kstart;k<kend;++k) { 02060 #else // COMPRESSGRIDS==0 02061 int kdir = 1; // COMPRT ON 02062 if(mLevel[lev].setCurr==1) { 02063 kdir = -1; 02064 int temp = kend; 02065 kend = kstart-1; 02066 kstart = temp-1; 02067 } // COMPRT 02068 for(int k=kstart;k!=kend;k+=kdir) { 02069 #endif // COMPRESSGRIDS==0 02070 for(int j=1;j<mLevel[lev].lSizey-1;++j) { 02071 for(int i=1;i<mLevel[lev].lSizex-1;++i) { 02072 if( ( RFLAG(lev, i,j,k, mLevel[lev].setCurr)& CFInter) ) { 02073 LbmFloat mass = 0.0; 02074 //LbmFloat nbdiv; 02075 //FORDF0 { 02076 for(int l=0;(l<cDirNum); l++) { 02077 int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l]; 02078 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFFluid ){ 02079 mass += 1.0; 02080 } 02081 if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFInter ){ 02082 mass += QCELL(lev, ni,nj,nk, mLevel[lev].setCurr, dMass); 02083 } 02084 //nbdiv+=1.0; 02085 } 02086 02087 //errMsg(" I ", PRINT_IJK<<" m"<<mass ); 02088 QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)cDirNum) ); 02089 QCELL(lev, i,j,k, mLevel[lev].setOther, dFfrac) = QCELL(lev, i,j,k, mLevel[lev].setOther, dMass); 02090 } 02091 }}} 02092 02093 mLevel[lev].setOther = mLevel[lev].setCurr; 02094 mLevel[lev].setCurr ^= 1; 02095 } 02096 // copy back...? 02097 } 02098 02099 /*****************************************************************************/ 02100 /* init part for all freesurface testcases */ 02101 void LbmFsgrSolver::initStandingFluidGradient() { 02102 // ---------------------------------------------------------------------- 02103 // standing fluid preinit 02104 const int debugStandingPreinit = 0; 02105 int haveStandingFluid = 0; 02106 02107 #define STANDFLAGCHECK(iindex) \ 02108 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || \ 02109 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ \ 02110 if((iindex)>1) { haveStandingFluid=(iindex); } \ 02111 j = mLevel[mMaxRefine].lSizey; i=mLevel[mMaxRefine].lSizex; k=getForZMaxBnd(); \ 02112 continue; \ 02113 } 02114 int gravIndex[3] = {0,0,0}; 02115 int gravDir[3] = {1,1,1}; 02116 int maxGravComp = 1; // by default y 02117 int gravComp1 = 0; // by default y 02118 int gravComp2 = 2; // by default y 02119 if( ABS(mLevel[mMaxRefine].gravity[0]) > ABS(mLevel[mMaxRefine].gravity[1]) ){ maxGravComp = 0; gravComp1=1; gravComp2=2; } 02120 if( ABS(mLevel[mMaxRefine].gravity[2]) > ABS(mLevel[mMaxRefine].gravity[0]) ){ maxGravComp = 2; gravComp1=0; gravComp2=1; } 02121 02122 int gravIMin[3] = { 0 , 0 , 0 }; 02123 int gravIMax[3] = { 02124 mLevel[mMaxRefine].lSizex + 0, 02125 mLevel[mMaxRefine].lSizey + 0, 02126 mLevel[mMaxRefine].lSizez + 0 }; 02127 if(LBMDIM==2) gravIMax[2] = 1; 02128 02129 //int gravDir = 1; 02130 if( mLevel[mMaxRefine].gravity[maxGravComp] > 0.0 ) { 02131 // swap directions 02132 int i=maxGravComp; 02133 int tmp = gravIMin[i]; 02134 gravIMin[i] = gravIMax[i] - 1; 02135 gravIMax[i] = tmp - 1; 02136 gravDir[i] = -1; 02137 } 02138 #define PRINTGDIRS \ 02139 errMsg("Standing fp","X start="<<gravIMin[0]<<" end="<<gravIMax[0]<<" dir="<<gravDir[0] ); \ 02140 errMsg("Standing fp","Y start="<<gravIMin[1]<<" end="<<gravIMax[1]<<" dir="<<gravDir[1] ); \ 02141 errMsg("Standing fp","Z start="<<gravIMin[2]<<" end="<<gravIMax[2]<<" dir="<<gravDir[2] ); 02142 // _PRINTGDIRS; 02143 02144 bool gravAbort = false; 02145 #define GRAVLOOP \ 02146 gravAbort=false; \ 02147 for(gravIndex[2]= gravIMin[2]; (gravIndex[2]!=gravIMax[2])&&(!gravAbort); gravIndex[2] += gravDir[2]) \ 02148 for(gravIndex[1]= gravIMin[1]; (gravIndex[1]!=gravIMax[1])&&(!gravAbort); gravIndex[1] += gravDir[1]) \ 02149 for(gravIndex[0]= gravIMin[0]; (gravIndex[0]!=gravIMax[0])&&(!gravAbort); gravIndex[0] += gravDir[0]) 02150 02151 GRAVLOOP { 02152 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; 02153 if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || 02154 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFBndMoving)) ) || 02155 ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ) { 02156 int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp])); 02157 if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] ); 02158 if(fluidHeight>1) { 02159 haveStandingFluid = fluidHeight; //gravIndex[maxGravComp]; 02160 gravIMax[maxGravComp] = gravIndex[maxGravComp] + gravDir[maxGravComp]; 02161 } 02162 gravAbort = true; continue; 02163 } 02164 } // GRAVLOOP 02165 // _PRINTGDIRS; 02166 02167 LbmFloat fluidHeight; 02168 fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp])); 02169 #if LBM_INCLUDE_TESTSOLVERS==1 02170 if(mUseTestdata) mpTest->mFluidHeight = (int)fluidHeight; 02171 #endif // ELBEEM_PLUGIN!=1 02172 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])<< 02173 " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10); 02174 02175 if(mDisableStandingFluidInit) { 02176 debMsgStd("Standing fluid preinit", DM_MSG, "Should be performed - but skipped due to mDisableStandingFluidInit flag set!", 2); 02177 haveStandingFluid=0; 02178 } 02179 02180 // copy flags and init , as no flags will be changed during grav init 02181 // also important for corasening later on 02182 const int lev = mMaxRefine; 02183 CellFlagType nbflag[LBM_DFNUM], nbored; 02184 for(int k=getForZMinBnd();k<getForZMaxBnd(mMaxRefine);++k) { 02185 for(int j=0;j<mLevel[lev].lSizey-0;++j) { 02186 for(int i=0;i<mLevel[lev].lSizex-0;++i) { 02187 if( (RFLAG(lev, i,j,k,SRCS(lev)) & (CFFluid)) ) { 02188 nbored = 0; 02189 FORDF1 { 02190 nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); 02191 nbored |= nbflag[l]; 02192 } 02193 if(nbored&CFBnd) { 02194 RFLAG(lev, i,j,k,SRCS(lev)) &= (~CFNoBndFluid); 02195 } else { 02196 RFLAG(lev, i,j,k,SRCS(lev)) |= CFNoBndFluid; 02197 } 02198 } 02199 RFLAG(lev, i,j,k,TSET(lev)) = RFLAG(lev, i,j,k,SRCS(lev)); 02200 } } } 02201 02202 if(haveStandingFluid) { 02203 int rhoworkSet = mLevel[lev].setCurr; 02204 myTime_t timestart = getTime(); // FIXME use user time here? 02205 02206 GRAVLOOP { 02207 int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; 02208 //debMsgStd("Standing fluid preinit", DM_MSG, " init check "<<PRINT_IJK<<" "<< haveStandingFluid, 1 ); 02209 if( ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFInter)) ) || 02210 ( (RFLAG(lev, i,j,k,rhoworkSet) & (CFEmpty)) ) ){ 02211 //gravAbort = true; 02212 continue; 02213 } 02214 02215 LbmFloat rho = 1.0; 02216 // 1/6 velocity from denisty gradient, 1/2 for delta of two cells 02217 rho += 1.0* (fluidHeight-gravIndex[maxGravComp]) * 02218 (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega); 02219 if(debugStandingPreinit) 02220 if((gravIndex[gravComp1]==gravIMin[gravComp1]) && (gravIndex[gravComp2]==gravIMin[gravComp2])) { 02221 errMsg("Standing fp","gi="<<gravIndex[maxGravComp]<<" rho="<<rho<<" at "<<PRINT_IJK); 02222 } 02223 02224 if( (RFLAG(lev, i,j,k, rhoworkSet) & CFFluid) || 02225 (RFLAG(lev, i,j,k, rhoworkSet) & CFInter) ) { 02226 FORDF0 { QCELL(lev, i,j,k, rhoworkSet, l) *= rho; } 02227 QCELL(lev, i,j,k, rhoworkSet, dMass) *= rho; 02228 } 02229 02230 } // GRAVLOOP 02231 02232 debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited (max-rho:"<< 02233 (1.0+ (fluidHeight) * (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega)) <<", h:"<< fluidHeight<<") ", 8); 02234 02235 int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) ); 02236 preinitSteps = (haveStandingFluid>>2); // not much use...? 02237 //preinitSteps = 0; 02238 debMsgStd("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10); 02239 for(int s=0; s<preinitSteps; s++) { 02240 // in solver main cpp 02241 standingFluidPreinit(); 02242 } 02243 02244 myTime_t timeend = getTime(); 02245 debMsgStd("Standing fluid preinit", DM_MSG, " done, "<<getTimeString(timeend-timestart), 9); 02246 #undef NBFLAG 02247 } 02248 } 02249 02250 02251 02252 bool LbmFsgrSolver::checkSymmetry(string idstring) 02253 { 02254 bool erro = false; 02255 bool symm = true; 02256 int msgs = 0; 02257 const int maxMsgs = 10; 02258 const bool markCells = false; 02259 02260 //for(int lev=0; lev<=mMaxRefine; lev++) { 02261 { int lev = mMaxRefine; 02262 02263 // no point if not symm. 02264 if( (mLevel[lev].lSizex==mLevel[lev].lSizey) && (mLevel[lev].lSizex==mLevel[lev].lSizez)) { 02265 // ok 02266 } else { 02267 return false; 02268 } 02269 02270 for(int s=0; s<2; s++) { 02271 FSGR_FORIJK1(lev) { 02272 if(i<(mLevel[lev].lSizex/2)) { 02273 int inb = (mLevel[lev].lSizey-1-i); 02274 02275 if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T 02276 02277 if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true; 02278 if(LBMDIM==2) { 02279 if(msgs<maxMsgs) { msgs++; 02280 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) ); 02281 } 02282 } 02283 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } 02284 symm = false; 02285 } 02286 if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true; 02287 if(LBMDIM==2) { 02288 if(msgs<maxMsgs) { msgs++; 02289 //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl); 02290 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) ); 02291 } 02292 } 02293 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } 02294 symm = false; 02295 } 02296 02297 LbmFloat nbrho = QCELL(lev, i,j,k, s, dC); 02298 FORDF1 { nbrho += QCELL(lev, i,j,k, s, l); } 02299 LbmFloat otrho = QCELL(lev, inb,j,k, s, dC); 02300 FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); } 02301 if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true; 02302 if(LBMDIM==2) { 02303 if(msgs<maxMsgs) { msgs++; 02304 //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl); 02305 errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho ); 02306 } 02307 } 02308 if(markCells){ debugMarkCell(lev, i,j,k); debugMarkCell(lev, inb,j,k); } 02309 symm = false; 02310 } 02311 } 02312 } } 02313 } // lev 02314 LbmFloat maxdiv =0.0; 02315 if(erro) { 02316 errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv ); 02317 //if(LBMDIM==2) mPanic = true; 02318 //return false; 02319 } else { 02320 errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv ); 02321 } 02322 // all ok... 02323 return symm; 02324 }// */ 02325 02326 02327 void 02328 LbmFsgrSolver::interpolateCellValues( 02329 int level,int ei,int ej,int ek,int workSet, 02330 LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz) 02331 { 02332 LbmFloat avgrho = 0.0; 02333 LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; 02334 LbmFloat cellcnt = 0.0; 02335 02336 for(int nbl=1; nbl< cDfNum ; ++nbl) { 02337 if(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) continue; 02338 if( (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & (CFFluid|CFInter)) ){ 02339 //((!(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) && 02340 //(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFInter) ) { 02341 cellcnt += 1.0; 02342 for(int rl=0; rl< cDfNum ; ++rl) { 02343 LbmFloat nbdf = QCELL_NB(level,ei,ej,ek, workSet,nbl, rl); 02344 avgux += (dfDvecX[rl]*nbdf); 02345 avguy += (dfDvecY[rl]*nbdf); 02346 avguz += (dfDvecZ[rl]*nbdf); 02347 avgrho += nbdf; 02348 } 02349 } 02350 } 02351 02352 if(cellcnt<=0.0) { 02353 // no nbs? just use eq. 02354 avgrho = 1.0; 02355 avgux = avguy = avguz = 0.0; 02356 //TTT mNumProblems++; 02357 #if ELBEEM_PLUGIN!=1 02358 //mPanic=1; 02359 // this can happen for worst case moving obj scenarios... 02360 errMsg("LbmFsgrSolver::interpolateCellValues","Cellcnt<=0.0 at "<<PRINT_VEC(ei,ej,ek)); 02361 #endif // ELBEEM_PLUGIN 02362 } else { 02363 // init speed 02364 avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; 02365 avgrho /= cellcnt; 02366 } 02367 02368 retrho = avgrho; 02369 retux = avgux; 02370 retuy = avguy; 02371 retuz = avguz; 02372 } // interpolateCellValues 02373 02374 02375 /****************************************************************************** 02376 * instantiation 02377 *****************************************************************************/ 02378 02380 LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); } 02381 02382