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 #include "solver_class.h" 00014 #include "solver_relax.h" 00015 #include "particletracer.h" 00016 00017 // MPT 00018 #include "ntl_world.h" 00019 #include "simulation_object.h" 00020 00021 #include <stdlib.h> 00022 #include <zlib.h> 00023 #ifndef sqrtf 00024 #define sqrtf sqrt 00025 #endif 00026 00027 /****************************************************************************** 00028 * helper functions 00029 *****************************************************************************/ 00030 00031 // try to enhance surface? 00032 #define SURFACE_ENH 2 00033 00034 extern bool glob_mpactive; 00035 extern bool glob_mpnum; 00036 extern bool glob_mpindex; 00037 00039 void LbmFsgrSolver::prepareVisualization( void ) { 00040 int lev = mMaxRefine; 00041 int workSet = mLevel[lev].setCurr; 00042 00043 int mainGravDir=6; // if normalizing fails, we asume z-direction gravity 00044 LbmFloat mainGravLen = 0.; 00045 FORDF1{ 00046 LbmFloat thisGravLen = dot(LbmVec(dfVecX[l],dfVecY[l],dfVecZ[l]), mLevel[mMaxRefine].gravity ); 00047 if(thisGravLen>mainGravLen) { 00048 mainGravLen = thisGravLen; 00049 mainGravDir = l; 00050 } 00051 } 00052 00053 #if LBMDIM==2 00054 // 2d, place in the middle of isofield slice (k=2) 00055 # define ZKD1 0 00056 // 2d z offset = 2, lbmGetData adds 1, so use one here 00057 # define ZKOFF 1 00058 // reset all values... 00059 for(int k= 0; k< 5; ++k) 00060 for(int j=0;j<mLevel[lev].lSizey-0;j++) 00061 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00062 *mpIso->lbmGetData(i,j,ZKOFF)=0.0; 00063 } 00064 #else // LBMDIM==2 00065 // 3d, use normal bounds 00066 # define ZKD1 1 00067 # define ZKOFF k 00068 // reset all values... 00069 for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) 00070 for(int j=0;j<mLevel[lev].lSizey-0;j++) 00071 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00072 *mpIso->lbmGetData(i,j,ZKOFF)=0.0; 00073 } 00074 #endif // LBMDIM==2 00075 00076 // MPT, ignore 00077 if((glob_mpactive) && (glob_mpnum>1) && (glob_mpindex==0)) { 00078 mpIso->resetAll(0.); 00079 } 00080 00081 00082 LbmFloat minval = mIsoValue*1.05; // / mIsoWeight[13]; 00083 // add up... 00084 float val = 0.0; 00085 for(int k= getForZMin1(); k< getForZMax1(lev); ++k) 00086 for(int j=1;j<mLevel[lev].lSizey-1;j++) 00087 for(int i=1;i<mLevel[lev].lSizex-1;i++) { 00088 const CellFlagType cflag = RFLAG(lev, i,j,k,workSet); 00089 //if(cflag&(CFBnd|CFEmpty)) { 00090 00091 #if SURFACE_ENH==0 00092 00093 // no enhancements... 00094 if( (cflag&(CFFluid|CFUnused)) ) { 00095 val = 1.; 00096 } else if( (cflag&CFInter) ) { 00097 val = (QCELL(lev, i,j,k,workSet, dFfrac)); 00098 } else { 00099 continue; 00100 } 00101 00102 #else // SURFACE_ENH!=1 00103 if(cflag&CFBnd) { 00104 // treated in second loop 00105 continue; 00106 } else if(cflag&CFUnused) { 00107 val = 1.; 00108 } else if( (cflag&CFFluid) && (cflag&CFNoBndFluid)) { 00109 // optimized fluid 00110 val = 1.; 00111 } else if( (cflag&(CFEmpty|CFInter|CFFluid)) ) { 00112 int noslipbnd = 0; 00113 int intercnt = 0; 00114 FORDF1 { 00115 const CellFlagType nbflag = RFLAG_NB(lev, i,j,k, workSet,l); 00116 if(nbflag&CFInter){ intercnt++; } 00117 00118 // check all directions otherwise we get bugs with splashes on obstacles 00119 if(l!=mainGravDir) continue; // only check bnd along main grav. dir 00120 //if((nbflag&CFBnd)&&(nbflag&CFBndNoslip)){ noslipbnd=1; } 00121 if((nbflag&CFBnd)){ noslipbnd=1; } 00122 } 00123 00124 if(cflag&CFEmpty) { 00125 // special empty treatment 00126 if((noslipbnd)&&(intercnt>6)) { 00127 *mpIso->lbmGetData(i,j,ZKOFF) += minval; 00128 } else if((noslipbnd)&&(intercnt>0)) { 00129 // necessary? 00130 *mpIso->lbmGetData(i,j,ZKOFF) += mIsoValue*0.9; 00131 } else { 00132 // nothing to do... 00133 } 00134 00135 continue; 00136 } else if(cflag&(CFNoNbEmpty|CFFluid)) { 00137 // no empty nb interface cells are treated as full 00138 val=1.0; 00139 } else { 00140 val = (QCELL(lev, i,j,k,workSet, dFfrac)); 00141 } 00142 00143 if(noslipbnd) { 00144 if(val<minval) val = minval; 00145 *mpIso->lbmGetData(i,j,ZKOFF) += minval-( val * mIsoWeight[13] ); 00146 } 00147 } else { // all others, unused? 00148 continue; 00149 } 00150 #endif // SURFACE_ENH>0 00151 00152 *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] ); 00153 *mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] ); 00154 *mpIso->lbmGetData( i+1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[2] ); 00155 00156 *mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] ); 00157 *mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] ); 00158 *mpIso->lbmGetData( i+1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[5] ); 00159 00160 *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] ); 00161 *mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] ); 00162 *mpIso->lbmGetData( i+1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[8] ); 00163 00164 00165 *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] ); 00166 *mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] ); 00167 *mpIso->lbmGetData( i+1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[11] ); 00168 00169 *mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] ); 00170 *mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] ); 00171 *mpIso->lbmGetData( i+1 , j ,ZKOFF ) += ( val * mIsoWeight[14] ); 00172 00173 *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] ); 00174 *mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] ); 00175 *mpIso->lbmGetData( i+1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[17] ); 00176 00177 00178 *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] ); 00179 *mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] ); 00180 *mpIso->lbmGetData( i+1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[20] ); 00181 00182 *mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] ); 00183 *mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] ); 00184 *mpIso->lbmGetData( i+1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[23] ); 00185 00186 *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] ); 00187 *mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] ); 00188 *mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] ); 00189 } 00190 00191 // TEST!? 00192 #if SURFACE_ENH>=2 00193 00194 if(mFsSurfGenSetting&fssgNoObs) { 00195 for(int k= getForZMin1(); k< getForZMax1(lev); ++k) 00196 for(int j=1;j<mLevel[lev].lSizey-1;j++) 00197 for(int i=1;i<mLevel[lev].lSizex-1;i++) { 00198 const CellFlagType cflag = RFLAG(lev, i,j,k,workSet); 00199 if(cflag&(CFBnd)) { 00200 CellFlagType nbored=0; 00201 LbmFloat avgfill=0.,avgfcnt=0.; 00202 FORDF1 { 00203 const int ni = i+dfVecX[l]; 00204 const int nj = j+dfVecY[l]; 00205 const int nk = ZKOFF+dfVecZ[l]; 00206 00207 const CellFlagType nbflag = RFLAG(lev, ni,nj,nk, workSet); 00208 nbored |= nbflag; 00209 if(nbflag&CFInter) { 00210 avgfill += QCELL(lev, ni,nj,nk, workSet,dFfrac); avgfcnt += 1.; 00211 } else if(nbflag&CFFluid) { 00212 avgfill += 1.; avgfcnt += 1.; 00213 } else if(nbflag&CFEmpty) { 00214 avgfill += 0.; avgfcnt += 1.; 00215 } 00216 00217 //if( (ni<0) || (nj<0) || (nk<0) 00218 //|| (ni>=mLevel[mMaxRefine].lSizex) 00219 //|| (nj>=mLevel[mMaxRefine].lSizey) 00220 //|| (nk>=mLevel[mMaxRefine].lSizez) ) continue; 00221 } 00222 00223 if(nbored&CFInter) { 00224 if(avgfcnt>0.) avgfill/=avgfcnt; 00225 *mpIso->lbmGetData(i,j,ZKOFF) = avgfill; continue; 00226 } 00227 else if(nbored&CFFluid) { 00228 *mpIso->lbmGetData(i,j,ZKOFF) = 1.; continue; 00229 } 00230 00231 } 00232 } 00233 00234 // move surface towards inner "row" of obstacle 00235 // cells if necessary (all obs cells without fluid/inter 00236 // nbs (=iso==0) next to obstacles...) 00237 for(int k= getForZMin1(); k< getForZMax1(lev); ++k) 00238 for(int j=1;j<mLevel[lev].lSizey-1;j++) 00239 for(int i=1;i<mLevel[lev].lSizex-1;i++) { 00240 const CellFlagType cflag = RFLAG(lev, i,j,k,workSet); 00241 if( (cflag&(CFBnd)) && (*mpIso->lbmGetData(i,j,ZKOFF)==0.)) { 00242 int bndnbcnt=0; 00243 FORDF1 { 00244 const int ni = i+dfVecX[l]; 00245 const int nj = j+dfVecY[l]; 00246 const int nk = ZKOFF+dfVecZ[l]; 00247 const CellFlagType nbflag = RFLAG(lev, ni,nj,nk, workSet); 00248 if(nbflag&CFBnd) bndnbcnt++; 00249 } 00250 if(bndnbcnt>0) *mpIso->lbmGetData(i,j,ZKOFF)=mIsoValue*0.95; 00251 } 00252 } 00253 } 00254 // */ 00255 00256 if(mFsSurfGenSetting&fssgNoNorth) 00257 for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) 00258 for(int j=0;j<mLevel[lev].lSizey-0;j++) { 00259 *mpIso->lbmGetData(0, j,ZKOFF) = *mpIso->lbmGetData(1, j,ZKOFF); 00260 } 00261 if(mFsSurfGenSetting&fssgNoEast) 00262 for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) 00263 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00264 *mpIso->lbmGetData(i,0, ZKOFF) = *mpIso->lbmGetData(i,1, ZKOFF); 00265 } 00266 if(mFsSurfGenSetting&fssgNoSouth) 00267 for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) 00268 for(int j=0;j<mLevel[lev].lSizey-0;j++) { 00269 *mpIso->lbmGetData(mLevel[lev].lSizex-1,j,ZKOFF) = *mpIso->lbmGetData(mLevel[lev].lSizex-2,j,ZKOFF); 00270 } 00271 if(mFsSurfGenSetting&fssgNoWest) 00272 for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) 00273 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00274 *mpIso->lbmGetData(i,mLevel[lev].lSizey-1,ZKOFF) = *mpIso->lbmGetData(i,mLevel[lev].lSizey-2,ZKOFF); 00275 } 00276 if(LBMDIM>2) { 00277 if(mFsSurfGenSetting&fssgNoBottom) 00278 for(int j=0;j<mLevel[lev].lSizey-0;j++) 00279 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00280 *mpIso->lbmGetData(i,j,0 ) = *mpIso->lbmGetData(i,j,1 ); 00281 } 00282 if(mFsSurfGenSetting&fssgNoTop) 00283 for(int j=0;j<mLevel[lev].lSizey-0;j++) 00284 for(int i=0;i<mLevel[lev].lSizex-0;i++) { 00285 *mpIso->lbmGetData(i,j,mLevel[lev].lSizez-1) = *mpIso->lbmGetData(i,j,mLevel[lev].lSizez-2); 00286 } 00287 } 00288 #endif // SURFACE_ENH>=2 00289 00290 00291 // update preview, remove 2d? 00292 if((mOutputSurfacePreview)&&(LBMDIM==3)) { 00293 int pvsx = (int)(mPreviewFactor*mSizex); 00294 int pvsy = (int)(mPreviewFactor*mSizey); 00295 int pvsz = (int)(mPreviewFactor*mSizez); 00296 //float scale = (float)mSizex / previewSize; 00297 LbmFloat scalex = (LbmFloat)mSizex/(LbmFloat)pvsx; 00298 LbmFloat scaley = (LbmFloat)mSizey/(LbmFloat)pvsy; 00299 LbmFloat scalez = (LbmFloat)mSizez/(LbmFloat)pvsz; 00300 for(int k= 0; k< (pvsz-1); ++k) 00301 for(int j=0;j< pvsy;j++) 00302 for(int i=0;i< pvsx;i++) { 00303 *mpPreviewSurface->lbmGetData(i,j,k) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) ); 00304 } 00305 // set borders again... 00306 for(int k= 0; k< (pvsz-1); ++k) { 00307 for(int j=0;j< pvsy;j++) { 00308 *mpPreviewSurface->lbmGetData(0,j,k) = *mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) ); 00309 *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *mpIso->lbmGetData( mSizex-1, (int)(j*scaley), (int)(k*scalez) ); 00310 } 00311 for(int i=0;i< pvsx;i++) { 00312 *mpPreviewSurface->lbmGetData(i,0,k) = *mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) ); 00313 *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *mpIso->lbmGetData( (int)(i*scalex), mSizey-1, (int)(k*scalez) ); 00314 } 00315 } 00316 for(int j=0;j<pvsy;j++) 00317 for(int i=0;i<pvsx;i++) { 00318 *mpPreviewSurface->lbmGetData(i,j,0) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0); 00319 *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , mSizez-1); 00320 } 00321 00322 if(mFarFieldSize>=1.2) { 00323 // also remove preview border 00324 for(int k= 0; k< (pvsz-1); ++k) { 00325 for(int j=0;j< pvsy;j++) { 00326 *mpPreviewSurface->lbmGetData(0,j,k) = 00327 *mpPreviewSurface->lbmGetData(1,j,k) = 00328 *mpPreviewSurface->lbmGetData(2,j,k); 00329 *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = 00330 *mpPreviewSurface->lbmGetData(pvsx-2,j,k) = 00331 *mpPreviewSurface->lbmGetData(pvsx-3,j,k); 00332 //0.0; 00333 } 00334 for(int i=0;i< pvsx;i++) { 00335 *mpPreviewSurface->lbmGetData(i,0,k) = 00336 *mpPreviewSurface->lbmGetData(i,1,k) = 00337 *mpPreviewSurface->lbmGetData(i,2,k); 00338 *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = 00339 *mpPreviewSurface->lbmGetData(i,pvsy-2,k) = 00340 *mpPreviewSurface->lbmGetData(i,pvsy-3,k); 00341 //0.0; 00342 } 00343 } 00344 for(int j=0;j<pvsy;j++) 00345 for(int i=0;i<pvsx;i++) { 00346 *mpPreviewSurface->lbmGetData(i,j,0) = 00347 *mpPreviewSurface->lbmGetData(i,j,1) = 00348 *mpPreviewSurface->lbmGetData(i,j,2); 00349 *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = 00350 *mpPreviewSurface->lbmGetData(i,j,pvsz-2) = 00351 *mpPreviewSurface->lbmGetData(i,j,pvsz-3); 00352 //0.0; 00353 } 00354 } 00355 } 00356 00357 // MPT 00358 #if LBM_INCLUDE_TESTSOLVERS==1 00359 mrIsoExchange(); 00360 #endif // LBM_INCLUDE_TESTSOLVERS==1 00361 00362 return; 00363 } 00364 00366 void LbmFsgrSolver::recalculateObjectSpeeds() { 00367 const bool debugRecalc = false; 00368 int numobjs = (int)(this->mpGiObjects->size()); 00369 // note - (numobjs + 1) is entry for domain settings 00370 00371 if(debugRecalc) errMsg("recalculateObjectSpeeds","start, #obj:"<<numobjs); 00372 if(numobjs>255-1) { 00373 errFatal("LbmFsgrSolver::recalculateObjectSpeeds","More than 256 objects currently not supported...",SIMWORLD_INITERROR); 00374 return; 00375 } 00376 mObjectSpeeds.resize(numobjs+1); 00377 for(int i=0; i<(int)(numobjs+0); i++) { 00378 mObjectSpeeds[i] = vec2L(this->mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[i]->getInitialVelocity(mSimulationTime) ))); 00379 if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<<i<<" set to "<< mObjectSpeeds[i]<<", unscaled:"<< (*this->mpGiObjects)[i]->getInitialVelocity(mSimulationTime) ); 00380 } 00381 00382 // also reinit part slip values here 00383 mObjectPartslips.resize(numobjs+1); 00384 for(int i=0; i<=(int)(numobjs+0); i++) { 00385 if(i<numobjs) { 00386 mObjectPartslips[i] = (LbmFloat)(*this->mpGiObjects)[i]->getGeoPartSlipValue(); 00387 } else { 00388 // domain setting 00389 mObjectPartslips[i] = this->mDomainPartSlipValue; 00390 } 00391 LbmFloat set = mObjectPartslips[i]; 00392 00393 // as in setInfluenceVelocity 00394 const LbmFloat dt = mLevel[mMaxRefine].timestep; 00395 const LbmFloat dtInter = 0.01; 00396 //LbmFloat facFv = 1.-set; 00397 // mLevel[mMaxRefine].timestep 00398 LbmFloat facNv = (LbmFloat)( 1.-pow( (double)(set), (double)(dt/dtInter)) ); 00399 errMsg("mObjectPartslips","id:"<<i<<"/"<<numobjs<<" ts:"<<dt<< " its:"<<(dt/dtInter) <<" set"<<set<<" nv"<<facNv<<" test:"<< 00400 pow( (double)(1.-facNv),(double)(dtInter/dt)) ); 00401 mObjectPartslips[i] = facNv; 00402 00403 if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<<i<<" parts "<< mObjectPartslips[i] ); 00404 } 00405 00406 if(debugRecalc) errMsg("recalculateObjectSpeeds","done, domain:"<<mObjectPartslips[numobjs]<<" n"<<numobjs); 00407 } 00408 00409 00410 00411 /*****************************************************************************/ 00413 /*****************************************************************************/ 00414 vector<ntlGeometryObject*> LbmFsgrSolver::getDebugObjects() { 00415 vector<ntlGeometryObject*> debo; 00416 if(this->mOutputSurfacePreview) { 00417 debo.push_back( mpPreviewSurface ); 00418 } 00419 #if LBM_INCLUDE_TESTSOLVERS==1 00420 if(mUseTestdata) { 00421 vector<ntlGeometryObject*> tdebo; 00422 tdebo = mpTest->getDebugObjects(); 00423 for(size_t i=0; i<tdebo.size(); i++) debo.push_back( tdebo[i] ); 00424 } 00425 #endif // ELBEEM_PLUGIN 00426 return debo; 00427 } 00428 00429 /****************************************************************************** 00430 * particle handling 00431 *****************************************************************************/ 00432 00434 int LbmFsgrSolver::initParticles() { 00435 int workSet = mLevel[mMaxRefine].setCurr; 00436 int tries = 0; 00437 int num = 0; 00438 ParticleTracer *partt = mpParticles; 00439 00440 partt->setStart( this->mvGeoStart + ntlVec3Gfx(mLevel[mMaxRefine].nodeSize*0.5) ); 00441 partt->setEnd ( this->mvGeoEnd + ntlVec3Gfx(mLevel[mMaxRefine].nodeSize*0.5) ); 00442 00443 partt->setSimStart( ntlVec3Gfx(0.0) ); 00444 partt->setSimEnd ( ntlVec3Gfx(mSizex, mSizey, getForZMaxBnd(mMaxRefine)) ); 00445 00446 while( (num<partt->getNumInitialParticles()) && (tries<100*partt->getNumInitialParticles()) ) { 00447 LbmFloat x,y,z,t; 00448 x = 1.0+(( (LbmFloat)(mSizex-3.) ) * (rand()/(RAND_MAX+1.0)) ); 00449 y = 1.0+(( (LbmFloat)(mSizey-3.) ) * (rand()/(RAND_MAX+1.0)) ); 00450 z = 1.0+(( (LbmFloat) getForZMax1(mMaxRefine)-2. )* (rand()/(RAND_MAX+1.0)) ); 00451 int i = (int)(x+0.5); 00452 int j = (int)(y+0.5); 00453 int k = (int)(z+0.5); 00454 if(LBMDIM==2) { 00455 k = 0; z = 0.5; // place in the middle of domain 00456 } 00457 00458 //if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFFluid) ) 00459 //&& ( RFLAG(mMaxRefine, i,j,k, workSet)& CFNoNbFluid ) 00460 //if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFInter|CFMbndInflow) ) { 00461 if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFNoBndFluid|CFUnused) ) { 00462 bool cellOk = true; 00463 //? FORDF1 { if(!(RFLAG_NB(mMaxRefine,i,j,k,workSet, l) & CFFluid)) cellOk = false; } 00464 if(!cellOk) continue; 00465 // in fluid... 00466 partt->addParticle(x,y,z); 00467 partt->getLast()->setStatus(PART_IN); 00468 partt->getLast()->setType(PART_TRACER); 00469 00470 partt->getLast()->setSize(1.); 00471 // randomize size 00472 partt->getLast()->setSize(0.5 + (rand()/(RAND_MAX+1.0))); 00473 00474 if( ( partt->getInitStart()>0.) 00475 && ( partt->getInitEnd()>0.) 00476 && ( partt->getInitEnd()>partt->getInitStart() )) { 00477 t = partt->getInitStart()+ (partt->getInitEnd()-partt->getInitStart())*(rand()/(RAND_MAX+1.0)); 00478 partt->getLast()->setLifeTime( -t ); 00479 } 00480 num++; 00481 } 00482 tries++; 00483 } // */ 00484 00485 /*FSGR_FORIJK1(mMaxRefine) { 00486 if( (RFLAG(mMaxRefine,i,j,k, workSet) & (CFNoBndFluid)) ) { 00487 LbmFloat rndn = (rand()/(RAND_MAX+1.0)); 00488 if(rndn>0.0) { 00489 ntlVec3Gfx pos( (LbmFloat)(i)-0.5, (LbmFloat)(j)-0.5, (LbmFloat)(k)-0.5 ); 00490 if(LBMDIM==2) { pos[2]=0.5; } 00491 partt->addParticle( pos[0],pos[1],pos[2] ); 00492 partt->getLast()->setStatus(PART_IN); 00493 partt->getLast()->setType(PART_TRACER); 00494 partt->getLast()->setSize(1.0); 00495 } 00496 } 00497 } // */ 00498 00499 00500 // DEBUG TEST 00501 #if LBM_INCLUDE_TESTSOLVERS==1 00502 if(mUseTestdata) { 00503 const bool partDebug=false; 00504 if(mpTest->mPartTestcase==0){ errMsg("LbmTestdata"," part init "<<mpTest->mPartTestcase); } 00505 if(mpTest->mPartTestcase==-12){ 00506 const int lev = mMaxRefine; 00507 for(int i=5;i<15;i++) { 00508 LbmFloat x,y,z; 00509 y = 0.5+(LbmFloat)(i); 00510 x = mLevel[lev].lSizex/20.0*10.0; 00511 z = mLevel[lev].lSizez/20.0*2.0; 00512 partt->addParticle(x,y,z); 00513 partt->getLast()->setStatus(PART_IN); 00514 partt->getLast()->setType(PART_BUBBLE); 00515 partt->getLast()->setSize( (-4.0+(LbmFloat)i)/1.0 ); 00516 if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); 00517 } 00518 } 00519 if(mpTest->mPartTestcase==-11){ 00520 const int lev = mMaxRefine; 00521 for(int i=5;i<15;i++) { 00522 LbmFloat x,y,z; 00523 y = 10.5+(LbmFloat)(i); 00524 x = mLevel[lev].lSizex/20.0*10.0; 00525 z = mLevel[lev].lSizez/20.0*40.0; 00526 partt->addParticle(x,y,z); 00527 partt->getLast()->setStatus(PART_IN); 00528 partt->getLast()->setType(PART_DROP); 00529 partt->getLast()->setSize( (-4.0+(LbmFloat)i)/1.0 ); 00530 if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); 00531 } 00532 } 00533 // place floats on rectangular region FLOAT_JITTER_BND 00534 if(mpTest->mPartTestcase==-10){ 00535 const int lev = mMaxRefine; 00536 const int sx = mLevel[lev].lSizex; 00537 const int sy = mLevel[lev].lSizey; 00538 //for(int j=-(int)(sy*0.25);j<-(int)(sy*0.25)+2;++j) { for(int i=-(int)(sx*0.25);i<-(int)(sy*0.25)+2;++i) { 00539 //for(int j=-(int)(sy*1.25);j<(int)(2.25*sy);++j) { for(int i=-(int)(sx*1.25);i<(int)(2.25*sx);++i) { 00540 for(int j=-(int)(sy*0.3);j<(int)(1.3*sy);++j) { for(int i=-(int)(sx*0.3);i<(int)(1.3*sx);++i) { 00541 //for(int j=-(int)(sy*0.2);j<(int)(0.2*sy);++j) { for(int i= (int)(sx*0.5);i<= (int)(0.51*sx);++i) { 00542 LbmFloat x,y,z; 00543 x = 0.0+(LbmFloat)(i); 00544 y = 0.0+(LbmFloat)(j); 00545 //z = mLevel[lev].lSizez/10.0*2.5 - 1.0; 00546 z = mLevel[lev].lSizez/20.0*9.5 - 1.0; 00547 //z = mLevel[lev].lSizez/20.0*4.5 - 1.0; 00548 partt->addParticle(x,y,z); 00549 //if( (i>0)&&(i<sx) && (j>0)&&(j<sy) ) { partt->getLast()->setStatus(PART_IN); } else { partt->getLast()->setStatus(PART_OUT); } 00550 partt->getLast()->setStatus(PART_IN); 00551 partt->getLast()->setType(PART_FLOAT); 00552 partt->getLast()->setSize( 15.0 ); 00553 if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); 00554 } 00555 } } 00556 } 00557 // DEBUG TEST 00558 #endif // LBM_INCLUDE_TESTSOLVERS 00559 00560 00561 debMsgStd("LbmFsgrSolver::initParticles",DM_MSG,"Added "<<num<<" particles, genProb:"<<this->mPartGenProb<<", tries:"<<tries, 10); 00562 if(num != partt->getNumParticles()) return 1; 00563 00564 return 0; 00565 } 00566 00567 // helper function for particle debugging 00568 /*static string getParticleStatusString(int state) { 00569 std::ostringstream out; 00570 if(state&PART_DROP) out << "dropp "; 00571 if(state&PART_TRACER) out << "tracr "; 00572 if(state&PART_BUBBLE) out << "bubbl "; 00573 if(state&PART_FLOAT) out << "float "; 00574 if(state&PART_INTER) out << "inter "; 00575 00576 if(state&PART_IN) out << "inn "; 00577 if(state&PART_OUT) out << "out "; 00578 if(state&PART_INACTIVE) out << "INACT "; 00579 if(state&PART_OUTFLUID) out << "outfluid "; 00580 return out.str(); 00581 } // */ 00582 00583 #define P_CHANGETYPE(p, newtype) \ 00584 p->setLifeTime(0.); \ 00585 /* errMsg("PIT","U pit"<<(p)->getId()<<" pos:"<< (p)->getPos()<<" status:"<<convertFlags2String((p)->getFlags())<<" to "<< (newtype) ); */ \ 00586 p->setType(newtype); 00587 00588 // tracer defines 00589 #define TRACE_JITTER 0.025 00590 #define TRACE_RAND (rand()/(RAND_MAX+1.0))*TRACE_JITTER-(TRACE_JITTER*0.5) 00591 #define FFGET_NORM(var,dl) \ 00592 if(RFLAG_NB(lev,i,j,k,workSet, dl) &(CFInter)){ (var) = QCELL_NB(lev,i,j,k,workSet,dl,dFfrac); } \ 00593 else if(RFLAG_NB(lev,i,j,k,workSet, dl) &(CFFluid|CFUnused)){ (var) = 1.; } else (var) = 0.0; 00594 00595 // float jitter 00596 #define FLOAT_JITTER_BND (FLOAT_JITTER*2.0) 00597 #define FLOAT_JITTBNDRAND(x) ((rand()/(RAND_MAX+1.0))*FLOAT_JITTER_BND*(1.-(x/(LbmFloat)maxdw))-(FLOAT_JITTER_BND*(1.-(x)/(LbmFloat)maxdw)*0.5)) 00598 00599 #define DEL_PART { \ 00600 /*errMsg("PIT","DEL AT "<< __LINE__<<" type:"<<p->getType()<<" "); */ \ 00601 p->setActive( false ); \ 00602 continue; } 00603 00604 void LbmFsgrSolver::advanceParticles() { 00605 const int level = mMaxRefine; 00606 const int workSet = mLevel[level].setCurr; 00607 LbmFloat vx=0.0,vy=0.0,vz=0.0; 00608 //int debugOutCounter=0; // debug output counter 00609 00610 myTime_t parttstart = getTime(); 00611 const LbmFloat cellsize = this->mpParam->getCellSize(); 00612 const LbmFloat timestep = this->mpParam->getTimestep(); 00613 //const LbmFloat viscAir = 1.79 * 1e-5; // RW2L kin. viscosity, mu 00614 //const LbmFloat viscWater = 1.0 * 1e-6; // RW2L kin. viscosity, mu 00615 const LbmFloat rhoAir = 1.2; // [kg m^-3] RW2L 00616 const LbmFloat rhoWater = 1000.0; // RW2L 00617 const LbmFloat minDropSize = 0.0005; // [m], = 2mm RW2L 00618 const LbmVec velAir(0.); // [m / s] 00619 00620 const LbmFloat r1 = 0.005; // r max 00621 const LbmFloat r2 = 0.0005; // r min 00622 const LbmFloat v1 = 9.0; // v max 00623 const LbmFloat v2 = 2.0; // v min 00624 const LbmVec rwgrav = vec2L( this->mpParam->getGravity(mSimulationTime) ); 00625 const bool useff = (mFarFieldSize>1.2); // if(mpTest->mFarfMode>0){ 00626 00627 // TODO scale bubble/part damping dep. on timestep, also drop bnd rev damping 00628 const int cutval = mCutoff; // use full border!? 00629 if(this->mStepCnt%50==49) { mpParticles->cleanup(); } 00630 for(vector<ParticleObject>::iterator pit= mpParticles->getParticlesBegin(); 00631 pit!= mpParticles->getParticlesEnd(); pit++) { 00632 //if((*pit).getPos()[2]>10.) errMsg("PIT"," pit"<<(*pit).getId()<<" pos:"<< (*pit).getPos()<<" status:["<<getParticleStatusString((*pit).getFlags())<<"] vel:"<< (*pit).getVel() ); 00633 if( (*pit).getActive()==false ) continue; 00634 // skip until reached 00635 ParticleObject *p = &(*pit); 00636 if(p->getLifeTime()<0.){ 00637 if(p->getLifeTime() < -mSimulationTime) continue; 00638 else p->setLifeTime(-mLevel[level].timestep); // zero for following update 00639 } 00640 int i,j,k; 00641 p->setLifeTime(p->getLifeTime()+mLevel[level].timestep); 00642 00643 // nearest neighbor, particle positions don't include empty bounds 00644 ntlVec3Gfx pos = p->getPos(); 00645 i= (int)pos[0]; j= (int)pos[1]; k= (int)pos[2];// no offset necessary 00646 if(LBMDIM==2) { k = 0; } 00647 00648 // only testdata handling, all for sws 00649 #if LBM_INCLUDE_TESTSOLVERS==1 00650 if(useff && (mpTest->mFarfMode>0)) { 00651 p->setStatus(PART_OUT); 00652 mpTest->handleParticle(p, i,j,k); continue; 00653 } 00654 #endif // LBM_INCLUDE_TESTSOLVERS==1 00655 00656 // in out tests 00657 if(p->getStatus()&PART_IN) { // IN 00658 if( (i<cutval)||(i>mSizex-1-cutval)|| 00659 (j<cutval)||(j>mSizey-1-cutval) 00660 //||(k<cutval)||(k>mSizez-1-cutval) 00661 ) { 00662 if(!useff) { DEL_PART; 00663 } else { 00664 p->setStatus(PART_OUT); 00665 } 00666 } 00667 } else { // OUT rough check 00668 // check in again? 00669 if( (i>=cutval)&&(i<=mSizex-1-cutval)&& 00670 (j>=cutval)&&(j<=mSizey-1-cutval) 00671 ) { 00672 p->setStatus(PART_IN); 00673 } 00674 } 00675 00676 if( (p->getType()==PART_BUBBLE) || 00677 (p->getType()==PART_TRACER) ) { 00678 00679 // no interpol 00680 vx = vy = vz = 0.0; 00681 if(p->getStatus()&PART_IN) { // IN 00682 if(k>=cutval) { 00683 if(k>mSizez-1-cutval) DEL_PART; 00684 00685 if( RFLAG(level, i,j,k, workSet)&(CFFluid|CFUnused) ) { 00686 // still ok 00687 int partLev = level; 00688 int si=i, sj=j, sk=k; 00689 while(partLev>0 && RFLAG(partLev, si,sj,sk, workSet)&(CFUnused)) { 00690 partLev--; 00691 si/=2; 00692 sj/=2; 00693 sk/=2; 00694 } 00695 // get velocity from fluid cell 00696 if( RFLAG(partLev, si,sj,sk, workSet)&(CFFluid) ) { 00697 LbmFloat *ccel = RACPNT(partLev, si,sj,sk, workSet); 00698 FORDF1{ 00699 LbmFloat cdf = RAC(ccel, l); 00700 // TODO update below 00701 vx += (this->dfDvecX[l]*cdf); 00702 vy += (this->dfDvecY[l]*cdf); 00703 vz += (this->dfDvecZ[l]*cdf); 00704 } 00705 // remove gravity influence 00706 const LbmFloat lesomega = mLevel[level].omega; // no les 00707 vx -= mLevel[level].gravity[0] * lesomega*0.5; 00708 vy -= mLevel[level].gravity[1] * lesomega*0.5; 00709 vz -= mLevel[level].gravity[2] * lesomega*0.5; 00710 } // fluid vel 00711 00712 } else { // OUT 00713 // out of bounds, deactivate... 00714 // FIXME make fsgr treatment 00715 if(p->getType()==PART_BUBBLE) { P_CHANGETYPE(p, PART_FLOAT ); continue; } 00716 } 00717 } else { 00718 // below 3d region, just rise 00719 } 00720 } else { // OUT 00721 # if LBM_INCLUDE_TESTSOLVERS==1 00722 if(useff) { mpTest->handleParticle(p, i,j,k); } 00723 else DEL_PART; 00724 # else // LBM_INCLUDE_TESTSOLVERS==1 00725 DEL_PART; 00726 # endif // LBM_INCLUDE_TESTSOLVERS==1 00727 // TODO use x,y vel...? 00728 } 00729 00730 ntlVec3Gfx v = p->getVel(); // dampen... 00731 if( (useff)&& (p->getType()==PART_BUBBLE) ) { 00732 // test rise 00733 00734 if(mPartUsePhysModel) { 00735 LbmFloat radius = p->getSize() * minDropSize; 00736 LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity 00737 LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity 00738 LbmVec velRel = velWater - velPart; 00739 //LbmFloat velRelNorm = norm(velRel); 00740 LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3 00741 00742 LbmVec fb = -rwgrav* pvolume *rhoWater; 00743 LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater; 00744 LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize); 00745 /*if(debugOutCounter<0) { 00746 errMsg("PIT","BTEST1 vol="<<pvolume<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel); 00747 errMsg("PIT","BTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscW="<<viscWater<<" ss/mb="<<(timestep/(pvolume*rhoAir))); 00748 errMsg("PIT","BTEST2 grav="<<rwgrav<<" " ); 00749 errMsg("PIT","BTEST2 change="<<(change)<<" fb="<<(fb)<<" fd="<<(fd)<<" "); 00750 errMsg("PIT","BTEST2 change="<<norm(change)<<" fb="<<norm(fb)<<" fd="<<norm(fd)<<" "); 00751 } // DEBUG */ 00752 00753 LbmVec fd2 = (LbmVec(vx,vy,vz)-vec2L(p->getVel())) * 6.0*M_PI*radius* (1e-3); //viscWater; 00754 LbmFloat w = 0.99; 00755 vz = (1.0-w)*vz + w*(p->getVel()[2]-0.5*(p->getSize()/5.0)*mLevel[level].gravity[2]); 00756 v = ntlVec3Gfx(vx,vy,vz)+vec2G(fd2); 00757 p->setVel( v ); 00758 } else { 00759 // non phys, half old, half fluid, use slightly slower acc 00760 v = v*0.5 + ntlVec3Gfx(vx,vy,vz)* 0.5-vec2G(mLevel[level].gravity)*0.5; 00761 p->setVel( v * 0.99 ); 00762 } 00763 p->advanceVel(); 00764 00765 } else if(p->getType()==PART_TRACER) { 00766 v = ntlVec3Gfx(vx,vy,vz); 00767 CellFlagType fflag = RFLAG(level, i,j,k, workSet); 00768 00769 if(fflag&(CFFluid|CFInter) ) { p->setInFluid(true); 00770 } else { p->setInFluid(false); } 00771 00772 if( (( fflag&CFFluid ) && ( fflag&CFNoBndFluid )) || 00773 (( fflag&CFInter ) && (!(fflag&CFNoNbFluid)) ) ) { 00774 // only real fluid 00775 # if LBMDIM==3 00776 p->advance( TRACE_RAND,TRACE_RAND,TRACE_RAND); 00777 # else 00778 p->advance( TRACE_RAND,TRACE_RAND, 0.); 00779 # endif 00780 00781 } else { 00782 // move inwards along normal, make sure normal is valid first 00783 // todo use class funcs! 00784 const int lev = level; 00785 LbmFloat nx=0.,ny=0.,nz=0., nv1,nv2; 00786 bool nonorm = false; 00787 if(i<=0) { nx = -1.; nonorm = true; } 00788 if(i>=mSizex-1) { nx = 1.; nonorm = true; } 00789 if(j<=0) { ny = -1.; nonorm = true; } 00790 if(j>=mSizey-1) { ny = 1.; nonorm = true; } 00791 # if LBMDIM==3 00792 if(k<=0) { nz = -1.; nonorm = true; } 00793 if(k>=mSizez-1) { nz = 1.; nonorm = true; } 00794 # endif // LBMDIM==3 00795 if(!nonorm) { 00796 FFGET_NORM(nv1,dE); FFGET_NORM(nv2,dW); 00797 nx = 0.5* (nv2-nv1); 00798 FFGET_NORM(nv1,dN); FFGET_NORM(nv2,dS); 00799 ny = 0.5* (nv2-nv1); 00800 # if LBMDIM==3 00801 FFGET_NORM(nv1,dT); FFGET_NORM(nv2,dB); 00802 nz = 0.5* (nv2-nv1); 00803 # else // LBMDIM==3 00804 nz = 0.; 00805 # endif // LBMDIM==3 00806 } else { 00807 v = p->getVel() + vec2G(mLevel[level].gravity); 00808 } 00809 p->advanceVec( (ntlVec3Gfx(nx,ny,nz)) * -0.1 ); // + vec2G(mLevel[level].gravity); 00810 } 00811 } 00812 00813 p->setVel( v ); 00814 p->advanceVel(); 00815 } 00816 00817 // drop handling 00818 else if(p->getType()==PART_DROP) { 00819 ntlVec3Gfx v = p->getVel(); // dampen... 00820 00821 if(mPartUsePhysModel) { 00822 LbmFloat radius = p->getSize() * minDropSize; 00823 LbmVec velPart = vec2L(p->getVel()) *cellsize /timestep; // * cellsize / timestep; // L2RW, lattice velocity 00824 LbmVec velRel = velAir - velPart; 00825 //LbmVec velRelLat = velRel /cellsize*timestep; // L2RW 00826 LbmFloat velRelNorm = norm(velRel); 00827 // TODO calculate values in lattice units, compute CD?!??! 00828 LbmFloat mb = rhoWater * 4.0/3.0 * M_PI* radius*radius*radius; // mass: 4/3 pi r^3 rho 00829 const LbmFloat rw = (r1-radius)/(r1-r2); 00830 const LbmFloat rmax = (0.5 + 0.5*rw); 00831 const LbmFloat vmax = (v2 + (v1-v2)* (1.0-rw) ); 00832 const LbmFloat cd = (rmax) * (velRelNorm)/(vmax); 00833 00834 LbmVec fg = rwgrav * mb;// * (1.0-rhoAir/rhoWater); 00835 LbmVec fd = velRel* velRelNorm* cd*M_PI *rhoAir *0.5 *radius*radius; 00836 LbmVec change = (fg+ fd ) *timestep / mb *(timestep/cellsize); 00837 //if(k>0) { errMsg("\nPIT","NTEST1 mb="<<mb<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel<<" pgetVel="<<p->getVel() ); } 00838 00839 v += vec2G(change); 00840 p->setVel(v); 00841 // NEW 00842 } else { 00843 p->setVel( v ); 00844 int gravk = (int)(p->getPos()[2]+mLevel[level].gravity[2]); 00845 if(gravk>=0 && gravk<mSizez && RFLAG(level, i,j,gravk, workSet)&CFBnd) { 00846 // dont add for "resting" parts 00847 v[2] = 0.; 00848 p->setVel( v*0.9 ); // restdamping 00849 } else { 00850 p->addToVel( vec2G(mLevel[level].gravity) ); 00851 } 00852 } // OLD 00853 p->advanceVel(); 00854 00855 if(p->getStatus()&PART_IN) { // IN 00856 if(k<cutval) { DEL_PART; continue; } 00857 if(k<=mSizez-1-cutval){ 00858 CellFlagType pflag = RFLAG(level, i,j,k, workSet); 00859 //errMsg("PIT move"," at "<<PRINT_IJK<<" flag"<<convertCellFlagType2String(pflag) ); 00860 if(pflag & (CFBnd)) { 00861 handleObstacleParticle(p); 00862 continue; 00863 } else if(pflag & (CFEmpty)) { 00864 // still ok 00865 } else if((pflag & CFInter) 00866 //&&(!(RFLAG(level, i,j,k, workSet)& CFNoNbFluid)) 00867 ) { 00868 // add to no nb fluid i.f.'s, so skip if interface with fluid nb 00869 } else if(pflag & (CFFluid|CFUnused|CFInter) ){ // interface cells ignored here due to previous check! 00870 // add dropmass again, (these are only interf. with nonbfl.) 00871 int oi= (int)(pos[0]-1.25*v[0]+0.5); 00872 int oj= (int)(pos[1]-1.25*v[1]+0.5); 00873 int ok= (int)(pos[2]-1.25*v[2]+0.5); 00874 const LbmFloat size = p->getSize(); 00875 const LbmFloat dropmass = ParticleObject::getMass(mPartDropMassSub*size); 00876 bool orgcellok = false; 00877 if( (oi<0)||(oi>mSizex-1)|| 00878 (oj<0)||(oj>mSizey-1)|| 00879 (ok<0)||(ok>mSizez-1) ) { 00880 // org cell not ok! 00881 } else if( RFLAG(level, oi,oj,ok, workSet) & (CFInter) ){ 00882 orgcellok = true; 00883 } else { 00884 // search upward for interface 00885 oi=i; oj=j; ok=k; 00886 for(int kk=0; kk<5 && ok<=mSizez-2; kk++) { 00887 ok++; // check sizez-2 due to this increment! 00888 if( RFLAG(level, oi,oj,ok, workSet) & (CFInter) ){ 00889 kk = 5; orgcellok = true; 00890 } 00891 } 00892 } 00893 00894 //errMsg("PTIMPULSE"," new v"<<v<<" at "<<PRINT_VEC(oi,oj,ok)<<" , was "<<PRINT_VEC(i,j,k)<<" ok "<<orgcellok ); 00895 if(orgcellok) { 00896 QCELL(level, oi,oj,ok, workSet, dMass) += dropmass; 00897 QCELL(level, oi,oj,ok, workSet, dFfrac) += dropmass; // assume rho=1? 00898 00899 if(RFLAG(level, oi,oj,ok, workSet) & CFNoBndFluid){ 00900 // check speed, perhaps normalize 00901 gfxReal vlensqr = normNoSqrt(v); 00902 if(vlensqr > 0.166*0.166) { 00903 v *= 1./sqrtf((float)vlensqr)*0.166; 00904 } 00905 // compute cell velocity 00906 LbmFloat *tcel = RACPNT(level, oi,oj,ok, workSet); 00907 LbmFloat velUx=0., velUy=0., velUz=0.; 00908 FORDF0 { 00909 velUx += (this->dfDvecX[l]*RAC(tcel,l)); 00910 velUy += (this->dfDvecY[l]*RAC(tcel,l)); 00911 velUz += (this->dfDvecZ[l]*RAC(tcel,l)); 00912 } 00913 // add impulse 00914 /* 00915 LbmFloat cellVelSqr = velUx*velUx+ velUy*velUy+ velUz*velUz; 00916 //errMsg("PTIMPULSE"," new v"<<v<<" cvs"<<cellVelSqr<<"="<<sqrt(cellVelSqr)); 00917 if(cellVelSqr< 0.166*0.166) { 00918 FORDF1 { 00919 const LbmFloat add = 3. * dropmass * this->dfLength[l]*(v[0]*this->dfDvecX[l]+v[1]*this->dfDvecY[l]+v[2]*this->dfDvecZ[l]); 00920 RAC(tcel,l) += add; 00921 } } // */ 00922 } // only add impulse away from obstacles! 00923 } // orgcellok 00924 00925 // FIXME make fsgr treatment 00926 P_CHANGETYPE(p, PART_FLOAT ); continue; 00927 // jitter in cell to prevent stacking when hitting a steep surface 00928 ntlVec3Gfx cpos = p->getPos(); 00929 cpos[0] += (rand()/(RAND_MAX+1.0))-0.5; 00930 cpos[1] += (rand()/(RAND_MAX+1.0))-0.5; 00931 cpos[2] += (rand()/(RAND_MAX+1.0))-0.5; 00932 p->setPos(cpos); 00933 } else { 00934 DEL_PART; 00935 this->mNumParticlesLost++; 00936 } 00937 } 00938 } else { // OUT 00939 # if LBM_INCLUDE_TESTSOLVERS==1 00940 if(useff) { mpTest->handleParticle(p, i,j,k); } 00941 else{ DEL_PART; } 00942 # else // LBM_INCLUDE_TESTSOLVERS==1 00943 DEL_PART; 00944 # endif // LBM_INCLUDE_TESTSOLVERS==1 00945 } 00946 00947 } // air particle 00948 00949 // inter particle 00950 else if(p->getType()==PART_INTER) { 00951 // unused!? 00952 if(p->getStatus()&PART_IN) { // IN 00953 if((k<cutval)||(k>mSizez-1-cutval)) { 00954 // undecided particle above or below... remove? 00955 DEL_PART; 00956 } 00957 00958 CellFlagType pflag = RFLAG(level, i,j,k, workSet); 00959 if(pflag& CFInter ) { 00960 // still ok 00961 } else if(pflag& (CFFluid|CFUnused) ) { 00962 P_CHANGETYPE(p, PART_FLOAT ); continue; 00963 } else if(pflag& CFEmpty ) { 00964 P_CHANGETYPE(p, PART_DROP ); continue; 00965 } else if(pflag& CFBnd ) { 00966 P_CHANGETYPE(p, PART_FLOAT ); continue; 00967 } 00968 } else { // OUT 00969 // undecided particle outside... remove? 00970 DEL_PART; 00971 } 00972 } 00973 00974 // float particle 00975 else if(p->getType()==PART_FLOAT) { 00976 00977 if(p->getStatus()&PART_IN) { // IN 00978 if(k<cutval) DEL_PART; 00979 // not valid for mass... 00980 vx = vy = vz = 0.0; 00981 00982 // define from particletracer.h 00983 #if MOVE_FLOATS==1 00984 const int DEPTH_AVG=3; // only average interface vels 00985 int ccnt=0; 00986 for(int kk=0;kk<DEPTH_AVG;kk+=1) { 00987 if((k-kk)<1) continue; 00988 if(RFLAG(level, i,j,k, workSet)&(CFInter)) {} else continue; 00989 ccnt++; 00990 FORDF1{ 00991 LbmFloat cdf = QCELL(level, i,j,k-kk, workSet, l); 00992 vx += (this->dfDvecX[l]*cdf); 00993 vy += (this->dfDvecY[l]*cdf); 00994 vz += (this->dfDvecZ[l]*cdf); 00995 } 00996 } 00997 if(ccnt) { 00998 // use halved surface velocity (todo, use omega instead) 00999 vx /=(LbmFloat)(ccnt * 2.0); // half xy speed! value2 01000 vy /=(LbmFloat)(ccnt * 2.0); 01001 vz /=(LbmFloat)(ccnt); } 01002 #else // MOVE_FLOATS==1 01003 vx=vy=0.; //p->setVel(ntlVec3Gfx(0.) ); // static_float 01004 #endif // MOVE_FLOATS==1 01005 vx += (rand()/(RAND_MAX+1.0))*(FLOAT_JITTER*0.2)-(FLOAT_JITTER*0.2*0.5); 01006 vy += (rand()/(RAND_MAX+1.0))*(FLOAT_JITTER*0.2)-(FLOAT_JITTER*0.2*0.5); 01007 01008 //bool delfloat = false; 01009 if( ( RFLAG(level, i,j,k, workSet)& (CFFluid|CFUnused) ) ) { 01010 // in fluid cell 01011 vz = p->getVel()[2]-1.0*mLevel[level].gravity[2]; // simply rise... 01012 if(vz<0.) vz=0.; 01013 } else if( ( RFLAG(level, i,j,k, workSet)& CFBnd ) ) { 01014 // force downwards movement, move below obstacle... 01015 //vz = p->getVel()[2]+1.0*mLevel[level].gravity[2]; // fall... 01016 //if(vz>0.) vz=0.; 01017 DEL_PART; 01018 } else if( ( RFLAG(level, i,j,k, workSet)& CFInter ) ) { 01019 // keep in interface , one grid cell offset is added in part. gen 01020 } else { // all else... 01021 if( ( RFLAG(level, i,j,k-1, workSet)& (CFFluid|CFInter) ) ) { 01022 vz = p->getVel()[2]+2.0*mLevel[level].gravity[2]; // fall... 01023 if(vz>0.) vz=0.; } 01024 else { DEL_PART; } 01025 } 01026 01027 p->setVel( vec2G( ntlVec3Gfx(vx,vy,vz) ) ); //? 01028 p->advanceVel(); 01029 } else { 01030 #if LBM_INCLUDE_TESTSOLVERS==1 01031 if(useff) { mpTest->handleParticle(p, i,j,k); } 01032 else DEL_PART; 01033 #else // LBM_INCLUDE_TESTSOLVERS==1 01034 DEL_PART; 01035 #endif // LBM_INCLUDE_TESTSOLVERS==1 01036 } 01037 01038 // additional bnd jitter 01039 if((0) && (useff) && (p->getLifeTime()<3.*mLevel[level].timestep)) { 01040 // use half butoff border 1/8 01041 int maxdw = (int)(mLevel[level].lSizex*0.125*0.5); 01042 if(maxdw<3) maxdw=3; 01043 if((j>=0)&&(j<=mSizey-1)) { 01044 if(ABS(i-( cutval))<maxdw) { p->advance( FLOAT_JITTBNDRAND( ABS(i-( cutval))), 0.,0.); } 01045 if(ABS(i-(mSizex-1-cutval))<maxdw) { p->advance( FLOAT_JITTBNDRAND( ABS(i-(mSizex-1-cutval))), 0.,0.); } 01046 } 01047 } 01048 } // PART_FLOAT 01049 01050 // unknown particle type 01051 else { 01052 errMsg("LbmFsgrSolver::advanceParticles","PIT pit invalid type!? "<<p->getStatus() ); 01053 } 01054 } 01055 myTime_t parttend = getTime(); 01056 debMsgStd("LbmFsgrSolver::advanceParticles",DM_MSG,"Time for particle update:"<< getTimeString(parttend-parttstart)<<", #particles:"<<mpParticles->getNumParticles() , 10 ); 01057 } 01058 01059 void LbmFsgrSolver::notifySolverOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) { 01060 int workSet = mLevel[mMaxRefine].setCurr; 01061 std::ostringstream name; 01062 01063 // debug - raw dump of ffrac values, as text! 01064 if(mDumpRawText) { 01065 name << outfilename<< frameNrStr <<".dump"; 01066 FILE *file = fopen(name.str().c_str(),"w"); 01067 if(file) { 01068 01069 for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { 01070 for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) { 01071 for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { 01072 float val = 0.; 01073 if(RFLAG(mMaxRefine, i,j,k, workSet) & CFInter) { 01074 val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); 01075 if(val<0.) val=0.; 01076 if(val>1.) val=1.; 01077 } 01078 if(RFLAG(mMaxRefine, i,j,k, workSet) & CFFluid) val = 1.; 01079 fprintf(file, "%f ",val); // text 01080 //errMsg("W", PRINT_IJK<<" val:"<<val); 01081 } 01082 fprintf(file, "\n"); // text 01083 } 01084 fprintf(file, "\n"); // text 01085 } 01086 fclose(file); 01087 01088 } // file 01089 } // */ 01090 01091 if(mDumpRawBinary) { 01092 if(!mDumpRawBinaryZip) { 01093 // unzipped, only fill 01094 name << outfilename<< frameNrStr <<".bdump"; 01095 FILE *file = fopen(name.str().c_str(),"w"); 01096 if(file) { 01097 for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { 01098 for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) { 01099 for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { 01100 float val = 0.; 01101 if(RFLAG(mMaxRefine, i,j,k, workSet) & CFInter) { 01102 val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); 01103 if(val<0.) val=0.; 01104 if(val>1.) val=1.; 01105 } 01106 if(RFLAG(mMaxRefine, i,j,k, workSet) & CFFluid) val = 1.; 01107 fwrite( &val, sizeof(val), 1, file); // binary 01108 } 01109 } 01110 } 01111 fclose(file); 01112 } // file 01113 } // unzipped 01114 else { 01115 // zipped, use iso values 01116 prepareVisualization(); 01117 name << outfilename<< frameNrStr <<".bdump.gz"; 01118 gzFile gzf = gzopen(name.str().c_str(),"wb9"); 01119 if(gzf) { 01120 // write size 01121 int s; 01122 s=mSizex; gzwrite(gzf, &s, sizeof(s)); 01123 s=mSizey; gzwrite(gzf, &s, sizeof(s)); 01124 s=mSizez; gzwrite(gzf, &s, sizeof(s)); 01125 01126 // write isovalues 01127 for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { 01128 for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) { 01129 for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { 01130 float val = 0.; 01131 val = *mpIso->lbmGetData( i,j,k ); 01132 gzwrite(gzf, &val, sizeof(val)); 01133 } 01134 } 01135 } 01136 gzclose(gzf); 01137 } // gzf 01138 } // zip 01139 } // bin dump 01140 01141 dumptype = 0; frameNr = 0; // get rid of warning 01142 } 01143 01145 void LbmFsgrSolver::handleObstacleParticle(ParticleObject *p) { 01146 //if(normNoSqrt(v)<=0.) continue; // skip stuck 01147 /* 01148 p->setVel( v * -1. ); // revert 01149 p->advanceVel(); // move back twice... 01150 if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFBndNoslip)) { 01151 p->setVel( v * -0.5 ); // revert & dampen 01152 } 01153 p->advanceVel(); 01154 // */ 01155 // TODO mark/remove stuck parts!? 01156 01157 const int level = mMaxRefine; 01158 const int workSet = mLevel[level].setCurr; 01159 LbmVec v = vec2L( p->getVel() ); 01160 if(normNoSqrt(v)<=0.) { 01161 p->setVel(vec2G(mLevel[level].gravity)); 01162 } 01163 01164 CellFlagType pflag = CFBnd; 01165 ntlVec3Gfx posOrg(p->getPos()); 01166 ntlVec3Gfx npos(0.); 01167 int ni=1,nj=1,nk=1; 01168 int tries = 0; 01169 01170 // try to undo movement 01171 p->advanceVec( (p->getVel()-vec2G(mLevel[level].gravity)) * -2.); 01172 01173 npos = p->getPos(); ni= (int)npos[0]; 01174 nj= (int)npos[1]; nk= (int)npos[2]; 01175 if(LBMDIM==2) { nk = 0; } 01176 //errMsg("BOUNDCPAR"," t"<<PRINT_VEC(ni,nj,nk)<<" v"<<v<<" p"<<npos); 01177 01178 // delete out of domain 01179 if(!checkDomainBounds(level,ni,nj,nk)) { 01180 //errMsg("BOUNDCPAR"," DEL! "); 01181 p->setActive( false ); 01182 return; 01183 } 01184 pflag = RFLAG(level, ni,nj,nk, workSet); 01185 01186 // try to force particle out of boundary 01187 bool haveNorm = false; 01188 LbmVec bnormal; 01189 if(pflag&CFBnd) { 01190 npos = posOrg; ni= (int)npos[0]; 01191 nj= (int)npos[1]; nk= (int)npos[2]; 01192 if(LBMDIM==2) { nk = 0; } 01193 01194 computeObstacleSurfaceNormalAcc(ni,nj,nk, &bnormal[0]); 01195 haveNorm = true; 01196 normalize(bnormal); 01197 bnormal *= 0.25; 01198 01199 tries = 1; 01200 while(pflag&CFBnd && tries<=5) { 01201 // use increasing step sizes 01202 p->advanceVec( vec2G( bnormal *0.5 *(gfxReal)tries ) ); 01203 npos = p->getPos(); 01204 ni= (int)npos[0]; 01205 nj= (int)npos[1]; 01206 nk= (int)npos[2]; 01207 01208 // delete out of domain 01209 if(!checkDomainBounds(level,ni,nj,nk)) { 01210 //errMsg("BOUNDCPAR"," DEL! "); 01211 p->setActive( false ); 01212 return; 01213 } 01214 pflag = RFLAG(level, ni,nj,nk, workSet); 01215 tries++; 01216 } 01217 01218 // really stuck, delete... 01219 if(pflag&CFBnd) { 01220 p->setActive( false ); 01221 return; 01222 } 01223 } 01224 01225 // not in bound anymore! 01226 if(!haveNorm) { 01227 CellFlagType *bflag = &RFLAG(level, ni,nj,nk, workSet); 01228 LbmFloat *bcell = RACPNT(level, ni,nj,nk, workSet); 01229 computeObstacleSurfaceNormal(bcell,bflag, &bnormal[0]); 01230 } 01231 normalize(bnormal); 01232 LbmVec normComp = bnormal * dot(vec2L(v),bnormal); 01233 //errMsg("BOUNDCPAR","bnormal"<<bnormal<<" normComp"<<normComp<<" newv"<<(v-normComp) ); 01234 v = (v-normComp)*0.9; // only move tangential 01235 v *= 0.9; // restdamping , todo use timestep 01236 p->setVel(vec2G(v)); 01237 p->advanceVel(); 01238 } 01239 01240 /*****************************************************************************/ 01242 /*****************************************************************************/ 01243 void 01244 LbmFsgrSolver::printLbmCell(int level, int i, int j, int k, int set) { 01245 stdCellId *newcid = new stdCellId; 01246 newcid->level = level; 01247 newcid->x = i; 01248 newcid->y = j; 01249 newcid->z = k; 01250 01251 // this function is not called upon clicking, then its from setMouseClick 01252 debugPrintNodeInfo( newcid, set ); 01253 delete newcid; 01254 } 01255 void 01256 LbmFsgrSolver::debugMarkCellCall(int level, int vi,int vj,int vk) { 01257 stdCellId *newcid = new stdCellId; 01258 newcid->level = level; 01259 newcid->x = vi; 01260 newcid->y = vj; 01261 newcid->z = vk; 01262 this->addCellToMarkedList( newcid ); 01263 } 01264 01265 01266 /*****************************************************************************/ 01267 // implement CellIterator<UniformFsgrCellIdentifier> interface 01268 /*****************************************************************************/ 01269 01270 01271 01272 // values from guiflkt.cpp 01273 extern double guiRoiSX, guiRoiSY, guiRoiSZ, guiRoiEX, guiRoiEY, guiRoiEZ; 01274 extern int guiRoiMaxLev, guiRoiMinLev; 01275 #define CID_SX (int)( (mLevel[cid->level].lSizex-1) * guiRoiSX ) 01276 #define CID_SY (int)( (mLevel[cid->level].lSizey-1) * guiRoiSY ) 01277 #define CID_SZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiSZ ) 01278 01279 #define CID_EX (int)( (mLevel[cid->level].lSizex-1) * guiRoiEX ) 01280 #define CID_EY (int)( (mLevel[cid->level].lSizey-1) * guiRoiEY ) 01281 #define CID_EZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiEZ ) 01282 01283 CellIdentifierInterface* 01284 LbmFsgrSolver::getFirstCell( ) { 01285 int level = mMaxRefine; 01286 01287 #if LBMDIM==3 01288 if(mMaxRefine>0) { level = mMaxRefine-1; } // NO1HIGHESTLEV DEBUG 01289 #endif 01290 level = guiRoiMaxLev; 01291 if(level>mMaxRefine) level = mMaxRefine; 01292 01293 //errMsg("LbmFsgrSolver::getFirstCell","Celliteration started..."); 01294 stdCellId *cid = new stdCellId; 01295 cid->level = level; 01296 cid->x = CID_SX; 01297 cid->y = CID_SY; 01298 cid->z = CID_SZ; 01299 return cid; 01300 } 01301 01302 LbmFsgrSolver::stdCellId* 01303 LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { 01304 //stdCellId *cid = dynamic_cast<stdCellId*>( basecid ); 01305 stdCellId *cid = (stdCellId*)( basecid ); 01306 return cid; 01307 } 01308 01309 void LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { 01310 stdCellId *cid = convertBaseCidToStdCid(basecid); 01311 if(cid->getEnd()) return; 01312 01313 //debugOut(" ADb "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->getEnd(), 10); 01314 cid->x++; 01315 if(cid->x > CID_EX){ cid->x = CID_SX; cid->y++; 01316 if(cid->y > CID_EY){ cid->y = CID_SY; cid->z++; 01317 if(cid->z > CID_EZ){ 01318 cid->level--; 01319 cid->x = CID_SX; 01320 cid->y = CID_SY; 01321 cid->z = CID_SZ; 01322 if(cid->level < guiRoiMinLev) { 01323 cid->level = guiRoiMaxLev; 01324 cid->setEnd( true ); 01325 } 01326 } 01327 } 01328 } 01329 //debugOut(" ADa "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->getEnd(), 10); 01330 } 01331 01332 bool LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { 01333 stdCellId *cid = convertBaseCidToStdCid(basecid); 01334 return (!cid->getEnd()); 01335 } 01336 01337 void LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { 01338 delete *cid; 01339 *cid = NULL; 01340 } 01341 01342 CellIdentifierInterface* LbmFsgrSolver::getCellAt( ntlVec3Gfx pos ) { 01343 //int cellok = false; 01344 pos -= (this->mvGeoStart); 01345 01346 LbmFloat mmaxsize = mLevel[mMaxRefine].nodeSize; 01347 for(int level=mMaxRefine; level>=0; level--) { // finest first 01348 //for(int level=0; level<=mMaxRefine; level++) { // coarsest first 01349 LbmFloat nsize = mLevel[level].nodeSize; 01350 int x,y,z; 01351 // CHECK +- maxsize? 01352 x = (int)((pos[0]+0.5*mmaxsize) / nsize ); 01353 y = (int)((pos[1]+0.5*mmaxsize) / nsize ); 01354 z = (int)((pos[2]+0.5*mmaxsize) / nsize ); 01355 if(LBMDIM==2) z = 0; 01356 01357 // double check... 01358 if(x<0) continue; 01359 if(y<0) continue; 01360 if(z<0) continue; 01361 if(x>=mLevel[level].lSizex) continue; 01362 if(y>=mLevel[level].lSizey) continue; 01363 if(z>=mLevel[level].lSizez) continue; 01364 01365 // return fluid/if/border cells 01366 if( ( (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused)) ) || 01367 ( (level<mMaxRefine) && (RFLAG(level, x,y,z, mLevel[level].setCurr)&(CFUnused|CFEmpty)) ) ) { 01368 continue; 01369 } // */ 01370 01371 stdCellId *newcid = new stdCellId; 01372 newcid->level = level; 01373 newcid->x = x; 01374 newcid->y = y; 01375 newcid->z = z; 01376 //errMsg("cellAt",this->mName<<" "<<pos<<" l"<<level<<":"<<x<<","<<y<<","<<z<<" "<<convertCellFlagType2String(RFLAG(level, x,y,z, mLevel[level].setCurr)) ); 01377 return newcid; 01378 } 01379 01380 return NULL; 01381 } 01382 01383 01384 // INFO functions 01385 01386 int LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { 01387 stdCellId *cid = convertBaseCidToStdCid(basecid); 01388 return mLevel[cid->level].setCurr; 01389 //return mLevel[cid->level].setOther; 01390 } 01391 01392 int LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { 01393 stdCellId *cid = convertBaseCidToStdCid(basecid); 01394 return cid->level; 01395 } 01396 01397 ntlVec3Gfx LbmFsgrSolver::getCellOrigin ( CellIdentifierInterface* basecid) { 01398 ntlVec3Gfx ret; 01399 01400 stdCellId *cid = convertBaseCidToStdCid(basecid); 01401 ntlVec3Gfx cs( mLevel[cid->level].nodeSize ); 01402 if(LBMDIM==2) { cs[2] = 0.0; } 01403 01404 if(LBMDIM==2) { 01405 ret =(this->mvGeoStart + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ) 01406 + ntlVec3Gfx(0.0,0.0,cs[1]*-0.25)*cid->level ) 01407 +getCellSize(basecid); 01408 } else { 01409 ret =(this->mvGeoStart + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], cid->z *cs[2] )) 01410 +getCellSize(basecid); 01411 } 01412 return (ret); 01413 } 01414 01415 ntlVec3Gfx LbmFsgrSolver::getCellSize ( CellIdentifierInterface* basecid) { 01416 // return half size 01417 stdCellId *cid = convertBaseCidToStdCid(basecid); 01418 ntlVec3Gfx retvec( mLevel[cid->level].nodeSize * 0.5 ); 01419 // 2d display as rectangles 01420 if(LBMDIM==2) { retvec[2] = 0.0; } 01421 return (retvec); 01422 } 01423 01424 LbmFloat LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int set) { 01425 stdCellId *cid = convertBaseCidToStdCid(basecid); 01426 01427 // skip non-fluid cells 01428 if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&(CFFluid|CFInter)) { 01429 // ok go on... 01430 } else { 01431 return 0.; 01432 } 01433 01434 LbmFloat rho = 0.0; 01435 FORDF0 { rho += QCELL(cid->level, cid->x,cid->y,cid->z, set, l); } // ORG 01436 return ((rho-1.0) * mLevel[cid->level].simCellSize / mLevel[cid->level].timestep) +1.0; // ORG 01437 /*if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) { // test 01438 LbmFloat ux,uy,uz; 01439 ux=uy=uz= 0.0; 01440 int lev = cid->level; 01441 LbmFloat df[27], feqOld[27]; 01442 FORDF0 { 01443 rho += QCELL(lev, cid->x,cid->y,cid->z, set, l); 01444 ux += this->dfDvecX[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); 01445 uy += this->dfDvecY[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); 01446 uz += this->dfDvecZ[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); 01447 df[l] = QCELL(lev, cid->x,cid->y,cid->z, set, l); 01448 } 01449 FORDF0 { 01450 feqOld[l] = getCollideEq(l, rho,ux,uy,uz); 01451 } 01452 // debugging mods 01453 //const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feqOld); 01454 //const LbmFloat modOmega = this->getLesOmega(mLevel[lev].omega, mLevel[lev].lcsmago,Qo); 01455 //rho = (2.0-modOmega) *25.0; 01456 //rho = Qo*100.0; 01457 //if(cid->x==24){ errMsg("MODOMT"," at "<<PRINT_VEC(cid->x,cid->y,cid->z)<<" = "<<rho<<" "<<Qo); } 01458 //else{ rho=0.0; } 01459 } // test 01460 return rho; // test */ 01461 } 01462 01463 LbmVec LbmFsgrSolver::getCellVelocity ( CellIdentifierInterface* basecid,int set) { 01464 stdCellId *cid = convertBaseCidToStdCid(basecid); 01465 01466 // skip non-fluid cells 01467 if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&(CFFluid|CFInter)) { 01468 // ok go on... 01469 } else { 01470 return LbmVec(0.0); 01471 } 01472 01473 LbmFloat ux,uy,uz; 01474 ux=uy=uz= 0.0; 01475 FORDF0 { 01476 ux += this->dfDvecX[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); 01477 uy += this->dfDvecY[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); 01478 uz += this->dfDvecZ[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); 01479 } 01480 LbmVec vel(ux,uy,uz); 01481 // TODO fix... 01482 return (vel * mLevel[cid->level].simCellSize / mLevel[cid->level].timestep * this->mDebugVelScale); // normal 01483 } 01484 01485 LbmFloat LbmFsgrSolver::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { 01486 stdCellId *cid = convertBaseCidToStdCid(basecid); 01487 return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); 01488 } 01489 LbmFloat LbmFsgrSolver::getCellMass( CellIdentifierInterface* basecid,int set) { 01490 stdCellId *cid = convertBaseCidToStdCid(basecid); 01491 return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); 01492 } 01493 LbmFloat LbmFsgrSolver::getCellFill( CellIdentifierInterface* basecid,int set) { 01494 stdCellId *cid = convertBaseCidToStdCid(basecid); 01495 if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); 01496 if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFFluid) return 1.0; 01497 return 0.0; 01498 //return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); 01499 } 01500 CellFlagType LbmFsgrSolver::getCellFlag( CellIdentifierInterface* basecid,int set) { 01501 stdCellId *cid = convertBaseCidToStdCid(basecid); 01502 return RFLAG(cid->level, cid->x,cid->y,cid->z, set); 01503 } 01504 01505 LbmFloat LbmFsgrSolver::getEquilDf( int l ) { 01506 return this->dfEquil[l]; 01507 } 01508 01509 01510 ntlVec3Gfx LbmFsgrSolver::getVelocityAt (float xp, float yp, float zp) { 01511 ntlVec3Gfx avgvel(0.0); 01512 LbmFloat avgnum = 0.; 01513 01514 // taken from getCellAt! 01515 const int level = mMaxRefine; 01516 const int workSet = mLevel[level].setCurr; 01517 const LbmFloat nsize = mLevel[level].nodeSize; 01518 const int x = (int)((-this->mvGeoStart[0]+xp-0.5*nsize) / nsize ); 01519 const int y = (int)((-this->mvGeoStart[1]+yp-0.5*nsize) / nsize ); 01520 int z = (int)((-this->mvGeoStart[2]+zp-0.5*nsize) / nsize ); 01521 if(LBMDIM==2) z=0; 01522 //errMsg("DUMPVEL","p"<<PRINT_VEC(xp,yp,zp)<<" at "<<PRINT_VEC(x,y,z)<<" max"<<PRINT_VEC(mLevel[level].lSizex,mLevel[level].lSizey,mLevel[level].lSizez) ); 01523 01524 // return fluid/if/border cells 01525 // search neighborhood, do smoothing 01526 FORDF0{ 01527 const int i = x+this->dfVecX[l]; 01528 const int j = y+this->dfVecY[l]; 01529 const int k = z+this->dfVecZ[l]; 01530 01531 if( (i<0) || (j<0) || (k<0) 01532 || (i>=mLevel[level].lSizex) 01533 || (j>=mLevel[level].lSizey) 01534 || (k>=mLevel[level].lSizez) ) continue; 01535 01536 if( (RFLAG(level, i,j,k, mLevel[level].setCurr)&(CFFluid|CFInter)) ) { 01537 ntlVec3Gfx vel(0.0); 01538 LbmFloat *ccel = RACPNT(level, i,j,k ,workSet); // omp 01539 for(int n=1; n<this->cDfNum; n++) { 01540 vel[0] += (this->dfDvecX[n]*RAC(ccel,n)); 01541 vel[1] += (this->dfDvecY[n]*RAC(ccel,n)); 01542 vel[2] += (this->dfDvecZ[n]*RAC(ccel,n)); 01543 } 01544 01545 avgvel += vel; 01546 avgnum += 1.0; 01547 if(l==0) { // center slightly more weight 01548 avgvel += vel; avgnum += 1.0; 01549 } 01550 } // */ 01551 } 01552 01553 if(avgnum>0.) { 01554 ntlVec3Gfx retv = avgvel / avgnum; 01555 retv *= nsize/mLevel[level].timestep; 01556 // scale for current animation settings (frame time) 01557 retv *= mpParam->getCurrentAniFrameTime(); 01558 //errMsg("DUMPVEL","t"<<mSimulationTime<<" at "<<PRINT_VEC(xp,yp,zp)<<" ret:"<<retv<<", avgv:"<<avgvel<<" n"<<avgnum<<" nsize"<<nsize<<" ts"<<mLevel[level].timestep<<" fr"<<mpParam->getCurrentAniFrameTime() ); 01559 return retv; 01560 } 01561 // no cells here...? 01562 //errMsg("DUMPVEL"," at "<<PRINT_VEC(xp,yp,zp)<<" v"<<avgvel<<" n"<<avgnum<<" no vel !?"); 01563 return ntlVec3Gfx(0.); 01564 } 01565 01566 #if LBM_USE_GUI==1 01567 01568 void 01569 LbmFsgrSolver::debugDisplay(int set){ 01570 //lbmDebugDisplay< LbmFsgrSolver >( set, this ); 01571 lbmDebugDisplay( set ); 01572 } 01573 #endif 01574 01575 /*****************************************************************************/ 01576 // strict debugging functions 01577 /*****************************************************************************/ 01578 #if FSGR_STRICT_DEBUG==1 01579 #define STRICT_EXIT *((int *)0)=0; 01580 01581 int LbmFsgrSolver::debLBMGI(int level, int ii,int ij,int ik, int is) { 01582 if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01583 if(level > mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01584 01585 if((ii==-1)&&(ij==0)) { 01586 // special case for main loop, ok 01587 } else { 01588 if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01589 if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01590 if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01591 if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01592 } 01593 if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01594 if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01595 if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01596 if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01597 return _LBMGI(level, ii,ij,ik, is); 01598 }; 01599 01600 CellFlagType& LbmFsgrSolver::debRFLAG(int level, int xx,int yy,int zz,int set){ 01601 return _RFLAG(level, xx,yy,zz,set); 01602 }; 01603 01604 CellFlagType& LbmFsgrSolver::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { 01605 if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01606 // warning might access all spatial nbs 01607 if(dir>this->cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01608 return _RFLAG_NB(level, xx,yy,zz,set, dir); 01609 }; 01610 01611 CellFlagType& LbmFsgrSolver::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { 01612 if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01613 if(dir>this->cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01614 return _RFLAG_NBINV(level, xx,yy,zz,set, dir); 01615 }; 01616 01617 int LbmFsgrSolver::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { 01618 if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01619 if(level > mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01620 01621 if((ii==-1)&&(ij==0)) { 01622 // special case for main loop, ok 01623 } else { 01624 if(ii<0){ errMsg("LbmStrict"," invX- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01625 if(ij<0){ errMsg("LbmStrict"," invY- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01626 if(ii>mLevel[level].lSizex-1){ errMsg("LbmStrict"," invX+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01627 if(ij>mLevel[level].lSizey-1){ errMsg("LbmStrict"," invY+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01628 } 01629 if(ik<0){ errMsg("LbmStrict"," invZ- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01630 if(ik>mLevel[level].lSizez-1){ errMsg("LbmStrict"," invZ+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01631 if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01632 if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } 01633 if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } 01634 if(l>this->cDfNum){ // dFfrac is an exception 01635 if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } 01636 #if COMPRESSGRIDS==1 01637 //if((!this->mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug 01638 #endif // COMPRESSGRIDS==1 01639 return _LBMQI(level, ii,ij,ik, is, l); 01640 }; 01641 01642 LbmFloat& LbmFsgrSolver::debQCELL(int level, int xx,int yy,int zz,int set,int l) { 01643 //errMsg("LbmStrict","debQCELL debug: l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" l"<<l<<" index"<<LBMGI(level, xx,yy,zz,set)); 01644 return _QCELL(level, xx,yy,zz,set,l); 01645 }; 01646 01647 LbmFloat& LbmFsgrSolver::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { 01648 if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01649 if(dir>this->cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01650 return _QCELL_NB(level, xx,yy,zz,set, dir,l); 01651 }; 01652 01653 LbmFloat& LbmFsgrSolver::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { 01654 if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01655 if(dir>this->cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } 01656 return _QCELL_NBINV(level, xx,yy,zz,set, dir,l); 01657 }; 01658 01659 LbmFloat* LbmFsgrSolver::debRACPNT(int level, int ii,int ij,int ik, int is ) { 01660 return _RACPNT(level, ii,ij,ik, is ); 01661 }; 01662 01663 LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { 01664 if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } 01665 if(l>dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } 01666 //if(l>this->cDfNum){ // dFfrac is an exception 01667 //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } 01668 return _RAC(s,l); 01669 }; 01670 01671 #endif // FSGR_STRICT_DEBUG==1 01672 01673 01674 /****************************************************************************** 01675 * GUI&debugging functions 01676 *****************************************************************************/ 01677 01678 01679 #if LBM_USE_GUI==1 01680 #define USE_GLUTILITIES 01681 #include "../gui/gui_utilities.h" 01682 01684 void LbmFsgrSolver::debugDisplayNode(int dispset, CellIdentifierInterface* cell ) { 01685 //debugOut(" DD: "<<cell->getAsString() , 10); 01686 ntlVec3Gfx org = this->getCellOrigin( cell ); 01687 ntlVec3Gfx halfsize = this->getCellSize( cell ); 01688 int set = this->getCellSet( cell ); 01689 //debugOut(" DD: "<<cell->getAsString()<<" "<< (dispset->type) , 10); 01690 01691 bool showcell = true; 01692 int linewidth = 1; 01693 ntlColor col(0.5); 01694 LbmFloat cscale = 1.0; //dispset->scale; 01695 01696 #define DRAWDISPCUBE(col,scale) \ 01697 { glLineWidth( linewidth ); \ 01698 glColor3f( (col)[0], (col)[1], (col)[2]); \ 01699 ntlVec3Gfx s = org-(halfsize * (scale)); \ 01700 ntlVec3Gfx e = org+(halfsize * (scale)); \ 01701 drawCubeWire( s,e ); } 01702 01703 CellFlagType flag = this->getCellFlag(cell, set ); 01704 // always check types 01705 if(flag& CFInvalid ) { if(!guiShowInvalid ) return; } 01706 if(flag& CFUnused ) { if(!guiShowInvalid ) return; } 01707 if(flag& CFEmpty ) { if(!guiShowEmpty ) return; } 01708 if(flag& CFInter ) { if(!guiShowInterface) return; } 01709 if(flag& CFNoDelete ) { if(!guiShowNoDelete ) return; } 01710 if(flag& CFBnd ) { if(!guiShowBnd ) return; } 01711 01712 // only dismiss one of these types 01713 if(flag& CFGrFromCoarse) { if(!guiShowCoarseInner ) return; } // inner not really interesting 01714 else 01715 if(flag& CFGrFromFine) { if(!guiShowCoarseBorder ) return; } 01716 else 01717 if(flag& CFFluid ) { if(!guiShowFluid ) return; } 01718 01719 switch(dispset) { 01720 case FLUIDDISPNothing: { 01721 showcell = false; 01722 } break; 01723 case FLUIDDISPCelltypes: { 01724 cscale = 0.5; 01725 01726 if(flag& CFNoDelete) { // debug, mark nodel cells 01727 ntlColor ccol(0.7,0.0,0.0); 01728 DRAWDISPCUBE(ccol, 0.1); 01729 } 01730 if(flag& CFPersistMask) { // mark persistent flags 01731 ntlColor ccol(0.5); 01732 DRAWDISPCUBE(ccol, 0.125); 01733 } 01734 if(flag& CFNoBndFluid) { // mark persistent flags 01735 ntlColor ccol(0,0,1); 01736 DRAWDISPCUBE(ccol, 0.075); 01737 } 01738 01739 if(flag& CFInvalid) { 01740 cscale = 0.50; 01741 col = ntlColor(0.0,0,0.0); 01742 } 01743 else if(flag& CFBnd) { 01744 cscale = 0.59; 01745 col = ntlColor(0.4); 01746 } 01747 01748 else if(flag& CFInter) { 01749 cscale = 0.55; 01750 col = ntlColor(0,1,1); 01751 01752 } else if(flag& CFGrFromCoarse) { 01753 // draw as - with marker 01754 ntlColor col2(0.0,1.0,0.3); 01755 DRAWDISPCUBE(col2, 0.1); 01756 cscale = 0.5; 01757 showcell=false; // DEBUG 01758 } 01759 else if(flag& CFFluid) { 01760 cscale = 0.5; 01761 if(flag& CFGrToFine) { 01762 ntlColor col2(0.5,0.0,0.5); 01763 DRAWDISPCUBE(col2, 0.1); 01764 col = ntlColor(0,0,1); 01765 } 01766 if(flag& CFGrFromFine) { 01767 ntlColor col2(1.0,1.0,0.0); 01768 DRAWDISPCUBE(col2, 0.1); 01769 col = ntlColor(0,0,1); 01770 } else if(flag& CFGrFromCoarse) { 01771 // draw as fluid with marker 01772 ntlColor col2(0.0,1.0,0.3); 01773 DRAWDISPCUBE(col2, 0.1); 01774 col = ntlColor(0,0,1); 01775 } else { 01776 col = ntlColor(0,0,1); 01777 } 01778 } 01779 else if(flag& CFEmpty) { 01780 showcell=false; 01781 } 01782 01783 } break; 01784 case FLUIDDISPVelocities: { 01785 // dont use cube display 01786 LbmVec vel = this->getCellVelocity( cell, set ); 01787 glBegin(GL_LINES); 01788 glColor3f( 0.0,0.0,0.0 ); 01789 glVertex3f( org[0], org[1], org[2] ); 01790 org += vec2G(vel * 10.0 * cscale); 01791 glColor3f( 1.0,1.0,1.0 ); 01792 glVertex3f( org[0], org[1], org[2] ); 01793 glEnd(); 01794 showcell = false; 01795 } break; 01796 case FLUIDDISPCellfills: { 01797 cscale = 0.5; 01798 if(flag& CFFluid) { 01799 cscale = 0.75; 01800 col = ntlColor(0,0,0.5); 01801 } 01802 else if(flag& CFInter) { 01803 cscale = 0.75 * this->getCellMass(cell,set); 01804 col = ntlColor(0,1,1); 01805 } 01806 else { 01807 showcell=false; 01808 } 01809 01810 if( ABS(this->getCellMass(cell,set)) < 10.0 ) { 01811 cscale = 0.75 * this->getCellMass(cell,set); 01812 } else { 01813 showcell = false; 01814 } 01815 if(cscale>0.0) { 01816 col = ntlColor(0,1,1); 01817 } else { 01818 col = ntlColor(1,1,0); 01819 } 01820 // TODO 01821 } break; 01822 case FLUIDDISPDensity: { 01823 LbmFloat rho = this->getCellDensity(cell,set); 01824 cscale = rho*rho * 0.25; 01825 col = ntlColor( MIN(0.5+cscale,1.0) , MIN(0.0+cscale,1.0), MIN(0.0+cscale,1.0) ); 01826 cscale *= 2.0; 01827 } break; 01828 case FLUIDDISPGrid: { 01829 cscale = 0.59; 01830 col = ntlColor(1.0); 01831 } break; 01832 default: { 01833 cscale = 0.5; 01834 col = ntlColor(1.0,0.0,0.0); 01835 } break; 01836 } 01837 01838 if(!showcell) return; 01839 if(cscale==0.0) return; // dont draw zero values 01840 DRAWDISPCUBE(col, cscale); 01841 } 01842 01844 // D has to implement the CellIterator interface 01845 void LbmFsgrSolver::lbmDebugDisplay(int dispset) { 01846 // DEBUG always display testdata 01847 #if LBM_INCLUDE_TESTSOLVERS==1 01848 if(mUseTestdata){ 01849 cpDebugDisplay(dispset); 01850 mpTest->testDebugDisplay(dispset); 01851 } 01852 #endif // LBM_INCLUDE_TESTSOLVERS==1 01853 if(dispset<=FLUIDDISPNothing) return; 01854 //if(!dispset->on) return; 01855 glDisable( GL_LIGHTING ); // dont light lines 01856 01857 #if LBM_INCLUDE_TESTSOLVERS==1 01858 if((!mUseTestdata)|| (mUseTestdata)&&(mpTest->mFarfMode<=0)) { 01859 #endif // LBM_INCLUDE_TESTSOLVERS==1 01860 01861 LbmFsgrSolver::CellIdentifier cid = this->getFirstCell(); 01862 for(; this->noEndCell( cid ); 01863 this->advanceCell( cid ) ) { 01864 this->debugDisplayNode(dispset, cid ); 01865 } 01866 delete cid; 01867 01868 #if LBM_INCLUDE_TESTSOLVERS==1 01869 } // 3d check 01870 #endif // LBM_INCLUDE_TESTSOLVERS==1 01871 01872 glEnable( GL_LIGHTING ); // dont light lines 01873 } 01874 01876 // D has to implement the CellIterator interface 01877 void LbmFsgrSolver::lbmMarkedCellDisplay() { 01878 //fluidDispSettings dispset; 01879 // trick - display marked cells as grid displa -> white, big 01880 int dispset = FLUIDDISPGrid; 01881 glDisable( GL_LIGHTING ); // dont light lines 01882 01883 LbmFsgrSolver::CellIdentifier cid = this->markedGetFirstCell(); 01884 while(cid) { 01885 this->debugDisplayNode(dispset, cid ); 01886 cid = this->markedAdvanceCell(); 01887 } 01888 delete cid; 01889 01890 glEnable( GL_LIGHTING ); // dont light lines 01891 } 01892 01893 #endif // LBM_USE_GUI==1 01894 01896 void LbmFsgrSolver::debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet) { 01897 //string printInfo, 01898 // force printing of one set? default = -1 = off 01899 bool printDF = false; 01900 bool printRho = false; 01901 bool printVel = false; 01902 bool printFlag = false; 01903 bool printGeom = false; 01904 bool printMass=false; 01905 bool printBothSets = false; 01906 string printInfo = this->getNodeInfoString(); 01907 01908 for(size_t i=0; i<printInfo.length()-0; i++) { 01909 char what = printInfo[i]; 01910 switch(what) { 01911 case '+': // all on 01912 printDF = true; printRho = true; printVel = true; printFlag = true; printGeom = true; printMass = true ; 01913 printBothSets = true; break; 01914 case '-': // all off 01915 printDF = false; printRho = false; printVel = false; printFlag = false; printGeom = false; printMass = false; 01916 printBothSets = false; break; 01917 case 'd': printDF = true; break; 01918 case 'r': printRho = true; break; 01919 case 'v': printVel = true; break; 01920 case 'f': printFlag = true; break; 01921 case 'g': printGeom = true; break; 01922 case 'm': printMass = true; break; 01923 case 's': printBothSets = true; break; 01924 default: 01925 errFatal("debugPrintNodeInfo","Invalid node info id "<<what,SIMWORLD_GENERICERROR); return; 01926 } 01927 } 01928 01929 ntlVec3Gfx org = this->getCellOrigin( cell ); 01930 ntlVec3Gfx halfsize = this->getCellSize( cell ); 01931 int set = this->getCellSet( cell ); 01932 debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<<printInfo<<"' for node: "<<cell->getAsString()<<" from "<<this->getName()<<" currSet:"<<set , 1); 01933 if(printGeom) debMsgStd(" ",DM_MSG, "Org:"<<org<<" Halfsize:"<<halfsize<<" ", 1); 01934 01935 int setmax = 2; 01936 if(!printBothSets) setmax = 1; 01937 if(forceSet>=0) setmax = 1; 01938 01939 for(int s=0; s<setmax; s++) { 01940 int workset = set; 01941 if(s==1){ workset = (set^1); } 01942 if(forceSet>=0) workset = forceSet; 01943 debMsgStd(" ",DM_MSG, "Printing set:"<<workset<<" orgSet:"<<set, 1); 01944 01945 if(printDF) { 01946 for(int l=0; l<LBM_DFNUM; l++) { // FIXME ?? 01947 debMsgStd(" ",DM_MSG, " Df"<<l<<": "<<this->getCellDf(cell,workset,l), 1); 01948 } 01949 } 01950 if(printRho) { 01951 debMsgStd(" ",DM_MSG, " Rho: "<<this->getCellDensity(cell,workset), 1); 01952 } 01953 if(printVel) { 01954 debMsgStd(" ",DM_MSG, " Vel: "<<this->getCellVelocity(cell,workset), 1); 01955 } 01956 if(printFlag) { 01957 CellFlagType flag = this->getCellFlag(cell,workset); 01958 debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<<convertFlags2String( flag ) <<" "<<convertCellFlagType2String( flag ), 1); 01959 } 01960 if(printMass) { 01961 debMsgStd(" ",DM_MSG, " Mss: "<<this->getCellMass(cell,workset), 1); 01962 } 01963 // dirty... TODO fixme 01964 debMsgStd(" ",DM_MSG, " Flx: "<<this->getCellDf(cell,workset,dFlux), 1); 01965 } 01966 } 01967 01968