Blender V2.61 - r43446
|
00001 00004 /****************************************************************************** 00005 * 00006 * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method 00007 * Copyright 2003-2006 Nils Thuerey 00008 * 00009 * Basic interface for all simulation modules 00010 * 00011 *****************************************************************************/ 00012 00013 #include "simulation_object.h" 00014 #include "solver_interface.h" 00015 #include "ntl_bsptree.h" 00016 #include "ntl_ray.h" 00017 #include "ntl_world.h" 00018 #include "solver_interface.h" 00019 #include "particletracer.h" 00020 #include "elbeem.h" 00021 00022 #ifdef _WIN32 00023 #else 00024 #include <sys/time.h> 00025 #endif 00026 00027 00029 LbmSolverInterface* createSolver(); 00030 00031 00032 /****************************************************************************** 00033 * Constructor 00034 *****************************************************************************/ 00035 SimulationObject::SimulationObject() : 00036 ntlGeometryShader(), 00037 mGeoStart(-100.0), mGeoEnd(100.0), 00038 mpGiTree(NULL), mpGiObjects(NULL), 00039 mpGlob(NULL), 00040 mPanic( false ), 00041 mDebugType( 1 /* =FLUIDDISPNothing*/ ), 00042 mpLbm(NULL), mpParam( NULL ), 00043 mShowSurface(true), mShowParticles(false), 00044 mSelectedCid( NULL ), 00045 mpElbeemSettings( NULL ) 00046 00047 { 00048 mpParam = new Parametrizer(); 00049 //for(int i=0; i<MAX_DEBDISPSET; i++) { mDebDispSet[i].type = (i); mDebDispSet[i].on = false; mDebDispSet[i].scale = 1.0; } 00050 00051 // reset time 00052 mTime = 0.0; 00053 } 00054 00055 00056 /****************************************************************************** 00057 * Destructor 00058 *****************************************************************************/ 00059 SimulationObject::~SimulationObject() 00060 { 00061 if(mpGiTree) delete mpGiTree; 00062 if(mpElbeemSettings) delete mpElbeemSettings; 00063 if(mpLbm) delete mpLbm; 00064 if(mpParam) delete mpParam; 00065 if(mpParts) delete mpParts; 00066 debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10); 00067 } 00068 00069 00070 00071 /*****************************************************************************/ 00073 /*****************************************************************************/ 00074 void SimulationObject::initGeoTree() { 00075 // unused!! overriden by solver interface 00076 if(mpGlob == NULL) { 00077 errFatal("SimulationObject::initGeoTree error","Requires globals!", SIMWORLD_INITERROR); 00078 return; 00079 } 00080 ntlScene *scene = mpGlob->getSimScene(); 00081 mpGiObjects = scene->getObjects(); 00082 00083 if(mpGiTree != NULL) delete mpGiTree; 00084 char treeFlag = (1<<(mGeoInitId+4)); 00085 mpGiTree = new ntlTree( 20, 4, // warning - fixed values for depth & maxtriangles here... 00086 scene, treeFlag ); 00087 // unused!! overriden by solver interface 00088 } 00089 00090 /*****************************************************************************/ 00092 /*****************************************************************************/ 00093 void SimulationObject::freeGeoTree() { 00094 if(mpGiTree != NULL) delete mpGiTree; 00095 } 00096 00097 00098 00099 // copy & remember settings for later use 00100 void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) { 00101 mpElbeemSettings = new elbeemSimulationSettings; 00102 *mpElbeemSettings = *settings; 00103 00104 mGeoInitId = settings->domainId+1; 00105 debMsgStd("SimulationObject",DM_MSG,"mGeoInitId="<<mGeoInitId<<", domainId="<<settings->domainId, 8); 00106 } 00107 00108 /****************************************************************************** 00109 * simluation interface: initialize simulation using the given configuration file 00110 *****************************************************************************/ 00111 extern int glob_mpnum; 00112 int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) 00113 { 00114 if(! isSimworldOk() ) return 1; 00115 00116 // already inited? 00117 if(mpLbm) return 0; 00118 00119 mpGlob = glob; 00120 if(!getVisible()) { 00121 mpAttrs->setAllUsed(); 00122 return 0; 00123 } 00124 00125 00126 mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); 00127 //mDimension, mSolverType are deprecated 00128 string mSolverType(""); 00129 mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); 00130 00131 mpLbm = createSolver(); 00132 /* check lbm pointer */ 00133 if(mpLbm == NULL) { 00134 errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR); 00135 return 2; 00136 } 00137 debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2); 00138 00139 mpParts = new ParticleTracer(); 00140 00141 // for non-param simulations 00142 mpLbm->setParametrizer( mpParam ); 00143 mpParam->setAttrList( getAttributeList() ); 00144 // not needed.. done in solver_init: mpParam->setSize ... in solver_interface 00145 mpParam->parseAttrList(); 00146 00147 mpLbm->setAttrList( getAttributeList() ); 00148 mpLbm->setSwsAttrList( getSwsAttributeList() ); 00149 mpLbm->parseAttrList(); 00150 mpParts->parseAttrList( getAttributeList() ); 00151 00152 if(! isSimworldOk() ) return 3; 00153 mpParts->setName( getName() + "_part" ); 00154 mpParts->initialize( glob ); 00155 if(! isSimworldOk() ) return 4; 00156 00157 // init material settings 00158 string matMc("default"); 00159 matMc = mpAttrs->readString("material_surf", matMc, "SimulationObject","matMc", false ); 00160 mShowSurface = mpAttrs->readInt("showsurface", mShowSurface, "SimulationObject","mShowSurface", false ); 00161 mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false ); 00162 00163 checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" ); 00164 mpLbm->setLbmInitId( mGeoInitId ); 00165 mpLbm->setGeoStart( mGeoStart ); 00166 mpLbm->setGeoEnd( mGeoEnd ); 00167 mpLbm->setRenderGlobals( mpGlob ); 00168 mpLbm->setName( getName() + "_lbm" ); 00169 mpLbm->setParticleTracer( mpParts ); 00170 if(mpElbeemSettings) { 00171 // set further settings from API struct init 00172 if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath); 00173 mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo ); 00174 mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing); 00175 mpLbm->setIsoSubdivs(mpElbeemSettings->surfaceSubdivs); 00176 mpLbm->setSizeX(mpElbeemSettings->resolutionxyz); 00177 mpLbm->setSizeY(mpElbeemSettings->resolutionxyz); 00178 mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz); 00179 mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz); 00180 mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine); 00181 mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles); 00182 // set initial particles 00183 mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles); 00184 00185 // surface generation flag 00186 mpLbm->setSurfGenSettings(mpElbeemSettings->mFsSurfGenSetting); 00187 00188 string dinitType = string("no"); 00189 if (mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part"); 00190 else if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free"); 00191 else /*if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no"); 00192 mpLbm->setDomainBound(dinitType); 00193 mpLbm->setDomainPartSlip(mpElbeemSettings->domainobsPartslip); 00194 mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors); 00195 mpLbm->setFarFieldSize(mpElbeemSettings->farFieldSize); 00196 debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->domainobsPartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 ); 00197 00198 debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10); 00199 } 00200 00201 if(! mpLbm->initializeSolverMemory() ) { errMsg("SimulationObject::initialize","initializeSolverMemory failed"); mPanic=true; return 10; } 00202 if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverMemory status"); mPanic=true; return 11; } 00203 if(! mpLbm->initializeSolverGrids() ) { errMsg("SimulationObject::initialize","initializeSolverGrids failed"); mPanic=true; return 12; } 00204 if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverGrids status"); mPanic=true; return 13; } 00205 if(! mpLbm->initializeSolverPostinit() ) { errMsg("SimulationObject::initialize","initializeSolverPostin failed"); mPanic=true; return 14; } 00206 if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverPostin status"); mPanic=true; return 15; } 00207 00208 // print cell type stats 00209 bool printStats = true; 00210 if(glob_mpnum>0) printStats=false; // skip in this case 00211 if(printStats) { 00212 const int jmax = sizeof(CellFlagType)*8; 00213 int totalCells = 0; 00214 int flagCount[jmax]; 00215 for(int j=0; j<jmax ; j++) flagCount[j] = 0; 00216 int diffInits = 0; 00217 LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell(); 00218 for(; mpLbm->noEndCell( cid ); 00219 mpLbm->advanceCell( cid ) ) { 00220 int flag = mpLbm->getCellFlag(cid,0); 00221 int flag2 = mpLbm->getCellFlag(cid,1); 00222 if(flag != flag2) { 00223 diffInits++; 00224 } 00225 for(int j=0; j<jmax ; j++) { 00226 if( flag&(1<<j) ) flagCount[j]++; 00227 } 00228 totalCells++; 00229 } 00230 mpLbm->deleteCellIterator( &cid ); 00231 00232 char charNl = '\n'; 00233 debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5); 00234 debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5); 00235 for(int j=0; j<jmax ; j++) { 00236 std::ostringstream out; 00237 if(flagCount[j]>0) { 00238 out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl; 00239 debugOutNnl(out.str(), 5); 00240 } 00241 } 00242 // compute dist. of empty/bnd - fluid - if 00243 // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11), 00244 if(1){ 00245 std::ostringstream out; 00246 out.precision(2); out.width(4); 00247 int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8]; 00248 double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum; 00249 double flFrac = (double)(flagCount[7]) / totNum; 00250 double ifFrac = (double)(flagCount[8]) / totNum; 00251 //??? 00252 out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl; 00253 00254 if(diffInits > 0) { 00255 debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5); 00256 } 00257 debugOutNnl(out.str(), 5); 00258 } 00259 } // cellstats 00260 00261 // might be modified by mpLbm 00262 //mpParts->setStart( mGeoStart );? mpParts->setEnd( mGeoEnd );? 00263 mpParts->setStart( mpLbm->getGeoStart() ); 00264 mpParts->setEnd( mpLbm->getGeoEnd() ); 00265 mpParts->setCastShadows( false ); 00266 mpParts->setReceiveShadows( false ); 00267 mpParts->searchMaterial( glob->getMaterials() ); 00268 00269 // this has to be inited here - before, the values might be unknown 00270 IsoSurface *surf = mpLbm->getSurfaceGeoObj(); 00271 if(surf) { 00272 surf->setName( "final" ); // final surface mesh 00273 // warning - this might cause overwriting effects for multiple sims and geom dump... 00274 surf->setCastShadows( true ); 00275 surf->setReceiveShadows( false ); 00276 surf->searchMaterial( glob->getMaterials() ); 00277 if(mShowSurface) mObjects.push_back( surf ); 00278 } 00279 00280 #ifdef ELBEEM_PLUGIN 00281 mShowParticles=1; // for e.g. dumping 00282 #endif // ELBEEM_PLUGIN 00283 if((mpLbm->getGenerateParticles()>0.0)||(mpParts->getNumInitialParticles()>0)) { 00284 mShowParticles=1; 00285 mpParts->setDumpParts(true); 00286 } 00287 //debMsgStd("SimulationObject::init",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mShowParticles, DEBUG!",1); 00288 //} // DEBUG ENABLE!!!!!!!!!! 00289 if(mShowParticles) { 00290 mObjects.push_back(mpParts); 00291 } 00292 00293 // add objects to display for debugging (e.g. levelset particles) 00294 vector<ntlGeometryObject *> debugObjs = mpLbm->getDebugObjects(); 00295 for(size_t i=0;i<debugObjs.size(); i++) { 00296 debugObjs[i]->setCastShadows( false ); 00297 debugObjs[i]->setReceiveShadows( false ); 00298 debugObjs[i]->searchMaterial( glob->getMaterials() ); 00299 mObjects.push_back( debugObjs[i] ); 00300 debMsgStd("SimulationObject::init",DM_NOTIFY,"Added debug obj "<<debugObjs[i]->getName(), 10 ); 00301 } 00302 return 0; 00303 } 00304 00306 void SimulationObject::setFrameNum(int num) { 00307 // advance parametrizer 00308 mpParam->setFrameNum(num); 00309 } 00310 00311 /****************************************************************************** 00312 * simluation interface: advance simulation another step (whatever delta time that might be) 00313 *****************************************************************************/ 00314 void SimulationObject::step( void ) 00315 { 00316 if(mpParam->getCurrentAniFrameTime()>0.0) { 00317 // dont advance for stopped time 00318 mpLbm->step(); 00319 mTime += mpParam->getTimestep(); 00320 //if(mTime>0.001) { errMsg("DEBUG!!!!!!!!","quit mlsu..."); xit(1); } // PROFILE DEBUG TEST! 00321 } 00322 if(mpLbm->getPanic()) mPanic = true; 00323 00324 checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); 00325 //if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) { 00326 //int ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, FLUIDSIM_CBSTATUS_STEP, 0); 00327 //errMsg("runSimulationCallback cbtest1"," "<<this->getName()<<" ret="<<ret); 00328 //} 00329 //debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getTimestep())<<", framet="<<getFrameTime()<<") ", 10); 00330 } 00332 void SimulationObject::prepareVisualization( void ) { 00333 if(mPanic) return; 00334 mpLbm->prepareVisualization(); 00335 } 00336 00337 00338 /******************************************************************************/ 00339 /* get current start simulation time */ 00340 double SimulationObject::getStartTime( void ) { 00341 //return mpParam->calculateAniStart(); 00342 return mpParam->getAniStart(); 00343 } 00344 /* get time for a single animation frame */ 00345 double SimulationObject::getFrameTime( int frame ) { 00346 return mpParam->getAniFrameTime(frame); 00347 } 00348 /* get time for a single time step */ 00349 double SimulationObject::getTimestep( void ) { 00350 return mpParam->getTimestep(); 00351 } 00352 00353 00354 /****************************************************************************** 00355 * return a pointer to the geometry object of this simulation 00356 *****************************************************************************/ 00357 //ntlGeometryObject *SimulationObject::getGeometry() { return mpMC; } 00358 vector<ntlGeometryObject *>::iterator 00359 SimulationObject::getObjectsBegin() 00360 { 00361 return mObjects.begin(); 00362 } 00363 vector<ntlGeometryObject *>::iterator 00364 SimulationObject::getObjectsEnd() 00365 { 00366 return mObjects.end(); 00367 } 00368 00369 00370 00371 00372 00373 /****************************************************************************** 00374 * GUI - display debug info 00375 *****************************************************************************/ 00376 00377 void SimulationObject::drawDebugDisplay() { 00378 #ifndef NOGUI 00379 if(!getVisible()) return; 00380 00381 //if( mDebugType > (MAX_DEBDISPSET-1) ){ errFatal("SimulationObject::drawDebugDisplay","Invalid debug type!", SIMWORLD_GENERICERROR); return; } 00382 //mDebDispSet[ mDebugType ].on = true; 00383 //errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type ); 00384 mpLbm->debugDisplay( mDebugType ); 00385 00386 //::lbmMarkedCellDisplay<>( mpLbm ); 00387 mpLbm->lbmMarkedCellDisplay(); 00388 #endif 00389 } 00390 00391 /* GUI - display interactive info */ 00392 void SimulationObject::drawInteractiveDisplay() 00393 { 00394 #ifndef NOGUI 00395 if(!getVisible()) return; 00396 if(mSelectedCid) { 00397 // in debugDisplayNode if dispset is on is ignored... 00398 mpLbm->debugDisplayNode( FLUIDDISPGrid, mSelectedCid ); 00399 } 00400 #endif 00401 } 00402 00403 00404 /*******************************************************************************/ 00405 // GUI - handle mouse movement for selection 00406 /*******************************************************************************/ 00407 void SimulationObject::setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir) 00408 { 00409 normalize( dir ); 00410 // assume 2D sim is in XY plane... 00411 00412 double zplane = (mGeoEnd[2]-mGeoStart[2])*0.5; 00413 double zt = (zplane-org[2]) / dir[2]; 00414 ntlVec3Gfx pos( 00415 org[0]+ dir[0] * zt, 00416 org[1]+ dir[1] * zt, 0.0); 00417 00418 mSelectedCid = mpLbm->getCellAt( pos ); 00419 //errMsg("SMP ", mName<< x<<" "<<y<<" - "<<dir ); 00420 x = y = 0; // remove warning 00421 } 00422 00423 00424 void SimulationObject::setMouseClick() 00425 { 00426 if(mSelectedCid) { 00427 //::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() ); 00428 mpLbm->debugPrintNodeInfo( mSelectedCid ); 00429 } 00430 } 00431 00433 void SimulationObject::notifyShaderOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) { 00434 if(!mpLbm) return; 00435 00436 mpLbm->notifySolverOfDump(dumptype, frameNr,frameNrStr,outfilename); 00437 checkCallerStatus(FLUIDSIM_CBSTATUS_NEWFRAME, frameNr); 00438 } 00439 00441 int SimulationObject::checkCallerStatus(int status, int frame) { 00442 //return 0; // DEBUG 00443 int ret = 0; 00444 if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) { 00445 ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, status,frame); 00446 if(ret!=FLUIDSIM_CBRET_CONTINUE) { 00447 if(ret==FLUIDSIM_CBRET_STOP) { 00448 debMsgStd("SimulationObject::notifySolverOfDump",DM_NOTIFY,"Got stop signal from caller",1); 00449 setElbeemState( SIMWORLD_STOP ); 00450 } 00451 else if(ret==FLUIDSIM_CBRET_ABORT) { 00452 errFatal("SimulationObject::notifySolverOfDump","Got abort signal from caller, aborting...", SIMWORLD_GENERICERROR ); 00453 mPanic = 1; 00454 } 00455 else { 00456 errMsg("SimulationObject::notifySolverOfDump","Invalid callback return value: "<<ret<<", ignoring... "); 00457 } 00458 } 00459 } 00460 00461 //debMsgStd("SimulationObject::checkCallerStatus",DM_MSG, "s="<<status<<",f="<<frame<<" "<<this->getName()<<" ret="<<ret); 00462 if(isSimworldOk()) return 0; 00463 return 1; 00464 } 00465