/****************************************************************************** * render a whole animation (visualization mode) * this function is run in another thread, and communicates * with the parent thread via a mutex *****************************************************************************/ int ntlWorld::renderVisualization( bool multiThreaded ) { #ifndef NOGUI if(getElbeemState() != SIMWORLD_INITED) { return 0; } if(multiThreaded) mThreadRunning = true; // TODO, check global state? while(!getStopRenderVisualization()) { if(mpSims->size() <= 0) { debMsgStd("ntlWorld::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1); stopSimulationThread(); break; } // determine stepsize if(!mSingleStepDebug) { long startTime = getTime(); advanceSims(mFrameCnt); mFrameCnt++; long stopTime = getTime(); debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for t="<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<" ", 10); } else { double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(targetTime); // check paniced sims (normally done by advanceSims bool allPanic = true; for(size_t i=0;i<mpSims->size();i++) { if(!(*mpSims)[i]->getPanic()) allPanic = false; } if(allPanic) { warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } if(! isSimworldOk() ) { warnMsg("ntlWorld::advanceSims","World state error... stopping" ); setStopRenderVisualization( true ); } } // save frame if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime ); // for non-threaded check events if(!multiThreaded) { Fl::check(); gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw(); } } mThreadRunning = false; stopSimulationRestoreGui(); #else multiThreaded = false; // remove warning #endif return 0; }
/*! check status (e.g. stop/abort) from calling program, returns !=0 if sth. happened... */ int SimulationObject::checkCallerStatus(int status, int frame) { //return 0; // DEBUG int ret = 0; if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) { ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, status,frame); if(ret!=FLUIDSIM_CBRET_CONTINUE) { if(ret==FLUIDSIM_CBRET_STOP) { debMsgStd("SimulationObject::notifySolverOfDump",DM_NOTIFY,"Got stop signal from caller",1); setElbeemState( SIMWORLD_STOP ); } else if(ret==FLUIDSIM_CBRET_ABORT) { errFatal("SimulationObject::notifySolverOfDump","Got abort signal from caller, aborting...", SIMWORLD_GENERICERROR ); mPanic = 1; } else { errMsg("SimulationObject::notifySolverOfDump","Invalid callback return value: "<<ret<<", ignoring... "); } } } //debMsgStd("SimulationObject::checkCallerStatus",DM_MSG, "s="<<status<<",f="<<frame<<" "<<this->getName()<<" ret="<<ret); if(isSimworldOk()) return 0; return 1; }
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) { if(! isSimworldOk() ) return 1; // already inited? if(mpLbm) return 0; mpGlob = glob; if(!getVisible()) { mpAttrs->setAllUsed(); return 0; } mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); //mDimension, mSolverType are deprecated string mSolverType(""); mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); mpLbm = createSolver(); /* check lbm pointer */ if(mpLbm == NULL) { errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR); return 2; } debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2); mpParts = new ParticleTracer(); // for non-param simulations mpLbm->setParametrizer( mpParam ); mpParam->setAttrList( getAttributeList() ); // not needed.. done in solver_init: mpParam->setSize ... in solver_interface mpParam->parseAttrList(); mpLbm->setAttrList( getAttributeList() ); mpLbm->setSwsAttrList( getSwsAttributeList() ); mpLbm->parseAttrList(); mpParts->parseAttrList( getAttributeList() ); if(! isSimworldOk() ) return 3; mpParts->setName( getName() + "_part" ); mpParts->initialize( glob ); if(! isSimworldOk() ) return 4; // init material settings string matMc("default"); matMc = mpAttrs->readString("material_surf", matMc, "SimulationObject","matMc", false ); mShowSurface = mpAttrs->readInt("showsurface", mShowSurface, "SimulationObject","mShowSurface", false ); mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false ); checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" ); mpLbm->setLbmInitId( mGeoInitId ); mpLbm->setGeoStart( mGeoStart ); mpLbm->setGeoEnd( mGeoEnd ); mpLbm->setRenderGlobals( mpGlob ); mpLbm->setName( getName() + "_lbm" ); mpLbm->setParticleTracer( mpParts ); if(mpElbeemSettings) { // set further settings from API struct init if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath); mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo ); mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing); mpLbm->setIsoSubdivs(mpElbeemSettings->surfaceSubdivs); mpLbm->setSizeX(mpElbeemSettings->resolutionxyz); mpLbm->setSizeY(mpElbeemSettings->resolutionxyz); mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz); mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz); mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine); mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles); // set initial particles mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles); // surface generation flag mpLbm->setSurfGenSettings(mpElbeemSettings->mFsSurfGenSetting); string dinitType = string("no"); if (mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part"); else if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free"); else /*if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no"); mpLbm->setDomainBound(dinitType); mpLbm->setDomainPartSlip(mpElbeemSettings->domainobsPartslip); mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors); mpLbm->setFarFieldSize(mpElbeemSettings->farFieldSize); debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->domainobsPartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 ); debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10); } if(! mpLbm->initializeSolverMemory() ) { errMsg("SimulationObject::initialize","initializeSolverMemory failed"); mPanic=true; return 10; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverMemory status"); mPanic=true; return 11; } if(! mpLbm->initializeSolverGrids() ) { errMsg("SimulationObject::initialize","initializeSolverGrids failed"); mPanic=true; return 12; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverGrids status"); mPanic=true; return 13; } if(! mpLbm->initializeSolverPostinit() ) { errMsg("SimulationObject::initialize","initializeSolverPostin failed"); mPanic=true; return 14; } if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverPostin status"); mPanic=true; return 15; } // print cell type stats bool printStats = true; if(glob_mpnum>0) printStats=false; // skip in this case if(printStats) { const int jmax = sizeof(CellFlagType)*8; int totalCells = 0; int flagCount[jmax]; for(int j=0; j<jmax ; j++) flagCount[j] = 0; int diffInits = 0; LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell(); for(; mpLbm->noEndCell( cid ); mpLbm->advanceCell( cid ) ) { int flag = mpLbm->getCellFlag(cid,0); int flag2 = mpLbm->getCellFlag(cid,1); if(flag != flag2) { diffInits++; } for(int j=0; j<jmax ; j++) { if( flag&(1<<j) ) flagCount[j]++; } totalCells++; } mpLbm->deleteCellIterator( &cid ); char charNl = '\n'; debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5); debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5); for(int j=0; j<jmax ; j++) { std::ostringstream out; if(flagCount[j]>0) { out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl; debugOutNnl(out.str(), 5); } } // compute dist. of empty/bnd - fluid - if // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11), if(1){ std::ostringstream out; out.precision(2); out.width(4); int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8]; double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum; double flFrac = (double)(flagCount[7]) / totNum; double ifFrac = (double)(flagCount[8]) / totNum; //??? out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl; if(diffInits > 0) { debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5); } debugOutNnl(out.str(), 5); } } // cellstats // might be modified by mpLbm //mpParts->setStart( mGeoStart );? mpParts->setEnd( mGeoEnd );? mpParts->setStart( mpLbm->getGeoStart() ); mpParts->setEnd( mpLbm->getGeoEnd() ); mpParts->setCastShadows( false ); mpParts->setReceiveShadows( false ); mpParts->searchMaterial( glob->getMaterials() ); // this has to be inited here - before, the values might be unknown IsoSurface *surf = mpLbm->getSurfaceGeoObj(); if(surf) { surf->setName( "final" ); // final surface mesh // warning - this might cause overwriting effects for multiple sims and geom dump... surf->setCastShadows( true ); surf->setReceiveShadows( false ); surf->searchMaterial( glob->getMaterials() ); if(mShowSurface) mObjects.push_back( surf ); } #ifdef ELBEEM_PLUGIN mShowParticles=1; // for e.g. dumping #endif // ELBEEM_PLUGIN if((mpLbm->getGenerateParticles()>0.0)||(mpParts->getNumInitialParticles()>0)) { mShowParticles=1; mpParts->setDumpParts(true); } //debMsgStd("SimulationObject::init",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mShowParticles, DEBUG!",1); //} // DEBUG ENABLE!!!!!!!!!! if(mShowParticles) { mObjects.push_back(mpParts); } // add objects to display for debugging (e.g. levelset particles) vector<ntlGeometryObject *> debugObjs = mpLbm->getDebugObjects(); for(size_t i=0;i<debugObjs.size(); i++) { debugObjs[i]->setCastShadows( false ); debugObjs[i]->setReceiveShadows( false ); debugObjs[i]->searchMaterial( glob->getMaterials() ); mObjects.push_back( debugObjs[i] ); debMsgStd("SimulationObject::init",DM_NOTIFY,"Added debug obj "<<debugObjs[i]->getName(), 10 ); } return 0; }
void ntlWorld::finishWorldInit() { if(! isSimworldOk() ) return; // init the scene for the first time long sstartTime = getTime(); // first init sim scene for geo setup mpGlob->getSimScene()->buildScene(0.0, true); if(! isSimworldOk() ) return; mpGlob->getRenderScene()->buildScene(0.0, true); if(! isSimworldOk() ) return; long sstopTime = getTime(); debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); // TODO check simulations, run first steps mFirstSim = -1; if(mpSims->size() > 0) { // use values from first simulation as master time scale long startTime = getTime(); // remember first active sim for(size_t i=0;i<mpSims->size();i++) { if(!(*mpSims)[i]->getVisible()) continue; if((*mpSims)[i]->getPanic()) continue; // check largest timestep if(mFirstSim>=0) { if( (*mpSims)[i]->getTimestep() > (*mpSims)[mFirstSim]->getTimestep() ) { mFirstSim = i; debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<<i ,10); } } // check any valid sim if(mFirstSim<0) { mFirstSim = i; debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim: "<<i ,10); } } if(mFirstSim>=0) { debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10); while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) { debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<<mSimulationTime ,10); advanceSims(-1); } long stopTime = getTime(); mSimulationTime += (*mpSims)[mFirstSim]->getStartTime(); debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start-sims:"<< getTimeString(stopTime-startTime) , 1); #ifndef NOGUI guiResetSimulationTimeRange( mSimulationTime ); #endif } else { if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); } } if(! isSimworldOk() ) return; setElbeemState( SIMWORLD_INITED ); }
/****************************************************************************** * advance simulations by time t *****************************************************************************/ int ntlWorld::advanceSims(int framenum) { bool done = false; bool allPanic = true; // stop/quit (abort), dont display/render if(!isSimworldOk()) { return 1; } for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); } // time stopped? nothing else to do... if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ done=true; allPanic=false; /* DG: Need to check for user cancel here (fix for [#30298]) */ (*mpSims)[mFirstSim]->checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); } // Prevent bug [#29186] Object contribute to fluid sim animation start earlier than keyframe // Was: double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); - DG double totalTime = 0.0, targetTime = 0.0; for(size_t i = 0; i < mSimFrameCnt; i++) { /* We need an intermediate array "mSimFrameValue" because otherwise if we don't start with starttime = 0, the sim gets out of sync - DG */ totalTime += (*mpSims)[mFirstSim]->getFrameTime(mSimFrameValue[i]); } targetTime = totalTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); int gstate = 0; myTime_t advsstart = getTime(); // step all the sims, and check for panic debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic<<" gstate:"<<gstate, 10); // debug // timedebug while(!done) { double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(nextTargetTime); // check target times done = true; allPanic = false; if((*mpSims)[mFirstSim]->getTimestep() <1e-9 ) { // safety check, avoid timesteps that are too small errMsg("ntlWorld::advanceSims","Invalid time step, causing panic! curr:"<<(*mpSims)[mFirstSim]->getCurrentTime()<<" next:"<<nextTargetTime<<", stept:"<< (*mpSims)[mFirstSim]->getTimestep() ); allPanic = true; } else { for(size_t i=0;i<mpSims->size();i++) { if(!(*mpSims)[i]->getVisible()) continue; if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? debMsgStd("ntlWorld::advanceSims",DM_MSG, "Sim "<<i<<", currt:"<<(*mpSims)[i]->getCurrentTime()<<", nt:"<<nextTargetTime<<", panic:"<<(*mpSims)[i]->getPanic()<<", targett:"<<targetTime, 10); // debug // timedebug } } if( (targetTime - (*mpSims)[mFirstSim]->getCurrentTime()) > LBM_TIME_EPSILON) done=false; if(allPanic) done = true; } if(allPanic) { warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); return 1; } myTime_t advsend = getTime(); debMsgStd("ntlWorld::advanceSims",DM_MSG,"Overall steps so far took:"<< getTimeString(advsend-advsstart)<<" for sim time "<<targetTime, 4); // finish step for(size_t i=0;i<mpSims->size();i++) { SimulationObject *sim = (*mpSims)[i]; if(!sim->getVisible()) continue; if(sim->getPanic()) continue; sim->prepareVisualization(); } mSimFrameValue.push_back(framenum); mSimFrameCnt++; return 0; }