Blender  V2.59
solver_util.cpp
Go to the documentation of this file.
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