/** \file elbeem/intern/parametrizer.cpp * \ingroup elbeem */ /****************************************************************************** * * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method * Copyright 2003-2006 Nils Thuerey * * Parameter calculator for the LBM Solver class * *****************************************************************************/ #include #include "parametrizer.h" // debug output flag, has to be off for win32 for some reason... #define DEBUG_PARAMCHANNELS 0 /*! param seen debug string array */ const char *ParamStrings[] = { "RelaxTime", "Reynolds", "Viscosity", "SoundSpeed", "DomainSize", "GravityForce", "TimeLength", "Timestep", "Size", "TimeFactor", "AniFrames", "AniFrameTime", "AniStart", "SurfaceTension", "Density", "CellSize", "GStar", "MaxSpeed", "SimMaxSpeed", "FluidVolHeight", "NormalizedGStar", "PSERR", "PSERR", "PSERR", "PSERR" }; /****************************************************************************** * Default constructor *****************************************************************************/ Parametrizer::Parametrizer( void ) : mcViscosity( 8.94e-7 ), mSoundSpeed( 1500 ), mDomainSize( 0.1 ), mCellSize( 0.01 ), mcGravity( ParamVec(0.0) ), mTimestep(0.0001), mDesiredTimestep(-1.0), mMaxTimestep(-1.0), mMinTimestep(-1.0), mSizex(50), mSizey(50), mSizez(50), mTimeFactor( 1.0 ), mcAniFrameTime(0.0001), mTimeStepScale(1.0), mAniStart(0.0), //mExtent(1.0, 1.0, 1.0), //mSurfaceTension( 0.0 ), mDensity(1000.0), mGStar(0.0001), mFluidVolumeHeight(0.0), mSimulationMaxSpeed(0.0), mTadapMaxOmega(2.0), mTadapMaxSpeed(0.1), mTadapLevels(1), mFrameNum(0), mSeenValues( 0 ), mCalculatedValues( 0 ) { } /****************************************************************************** * Destructor *****************************************************************************/ Parametrizer::~Parametrizer() { /* not much to do... */ } /****************************************************************************** * Init from attr list *****************************************************************************/ void Parametrizer::parseAttrList() { if(!mpAttrs) { errFatal("Parametrizer::parseAttrList", "mpAttrs pointer not initialized!", SIMWORLD_INITERROR); return; } // unused string mSetupType = ""; mSetupType = mpAttrs->readString("p_setup",mSetupType, "Parametrizer","mSetupType", false); // real params if(getAttributeList()->exists("p_viscosity")) { mcViscosity = mpAttrs->readChannelFloat("p_viscosity"); seenThis( PARAM_VISCOSITY ); } mSoundSpeed = mpAttrs->readFloat("p_soundspeed",mSoundSpeed, "Parametrizer","mSoundSpeed", false); if(getAttributeList()->exists("p_soundspeed")) seenThis( PARAM_SOUNDSPEED ); mDomainSize = mpAttrs->readFloat("p_domainsize",mDomainSize, "Parametrizer","mDomainSize", false); if(getAttributeList()->exists("p_domainsize")) seenThis( PARAM_DOMAINSIZE ); if(mDomainSize<=0.0) { errMsg("Parametrizer::parseAttrList","Invalid real world domain size:"<exists("p_gravity")) { // || (!mcGravity.isInited()) ) { mcGravity = mpAttrs->readChannelVec3d("p_gravity"); seenThis( PARAM_GRAVITY ); } mTimestep = mpAttrs->readFloat("p_steptime",mTimestep, "Parametrizer","mTimestep", false); if(getAttributeList()->exists("p_steptime")) seenThis( PARAM_STEPTIME ); mTimeFactor = mpAttrs->readFloat("p_timefactor",mTimeFactor, "Parametrizer","mTimeFactor", false); if(getAttributeList()->exists("p_timefactor")) seenThis( PARAM_TIMEFACTOR ); if(getAttributeList()->exists("p_aniframetime")) { //|| (!mcAniFrameTime.isInited()) ) { mcAniFrameTime = mpAttrs->readChannelFloat("p_aniframetime");seenThis( PARAM_ANIFRAMETIME ); } mTimeStepScale = mpAttrs->readFloat("p_timestepscale",mTimeStepScale, "Parametrizer","mTimeStepScale", false); mAniStart = mpAttrs->readFloat("p_anistart",mAniStart, "Parametrizer","mAniStart", false); if(getAttributeList()->exists("p_anistart")) seenThis( PARAM_ANISTART ); if(mAniStart<0.0) { errMsg("Parametrizer::parseAttrList","Invalid start time:"<readFloat("p_surfacetension",mSurfaceTension, "Parametrizer","mSurfaceTension", false); //if(getAttributeList()->exists("p_surfacetension")) seenThis( PARAM_SURFACETENSION ); mDensity = mpAttrs->readFloat("p_density",mDensity, "Parametrizer","mDensity", false); if(getAttributeList()->exists("p_density")) seenThis( PARAM_DENSITY ); ParamFloat cellSize = 0.0; // unused, deprecated cellSize = mpAttrs->readFloat("p_cellsize",cellSize, "Parametrizer","cellSize", false); mGStar = mpAttrs->readFloat("p_gstar",mGStar, "Parametrizer","mGStar", false); if(getAttributeList()->exists("p_gstar")) seenThis( PARAM_GSTAR ); mNormalizedGStar = mpAttrs->readFloat("p_normgstar",mNormalizedGStar, "Parametrizer","mNormalizedGStar", false); if(getAttributeList()->exists("p_normgstar")) seenThis( PARAM_NORMALIZEDGSTAR ); mTadapMaxOmega = mpAttrs->readFloat("p_tadapmaxomega",mTadapMaxOmega, "Parametrizer","mTadapMaxOmega", false); mTadapMaxSpeed = mpAttrs->readFloat("p_tadapmaxspeed",mTadapMaxSpeed, "Parametrizer","mTadapMaxSpeed", false); } /****************************************************************************** *! advance to next render/output frame *****************************************************************************/ void Parametrizer::setFrameNum(int frame) { mFrameNum = frame; #if DEBUG_PARAMCHANNELS>0 errMsg("DEBUG_PARAMCHANNELS","setFrameNum frame-num="<0 } /*! get time of an animation frame (renderer) */ // also used by: mpParam->getCurrentAniFrameTime() , e.g. for velocity dump ParamFloat Parametrizer::getAniFrameTime( int frame ) { double frametime = (double)frame; ParamFloat anift = mcAniFrameTime.get(frametime); if(anift<0.0) { ParamFloat resetv = 0.; errMsg("Parametrizer::setFrameNum","Invalid frame time:"<0 if((0)|| (DEBUG_PARAMCHANNELS)) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<0 return anift; } /****************************************************************************** * scale a given speed vector in m/s to lattice values *****************************************************************************/ ParamVec Parametrizer::calculateAddForce(ParamVec vec, string usage) { ParamVec ret = vec * (mTimestep*mTimestep) /mCellSize; debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<0 errMsg("DEBUG_PARAMCHANNELS","calculateLatticeViscosity viscStar="<0 return viscStar; } /*! get no of steps for the given length in seconds */ int Parametrizer::calculateStepsForSecs( ParamFloat s ) { return (int)(s/mTimestep); } /*! get start time of animation */ int Parametrizer::calculateAniStart( void ) { return (int)(mAniStart/mTimestep); } /*! get no of steps for a single animation frame */ int Parametrizer::calculateAniStepsPerFrame(int frame) { if(!checkSeenValues(PARAM_ANIFRAMETIME)) { errFatal("Parametrizer::calculateAniStepsPerFrame", "Missing ani frame time argument!", SIMWORLD_INITERROR); return 1; } int value = (int)(getAniFrameTime(frame)/mTimestep); if((value<0) || (value>1000000)) { errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="< ani-frame-time ("<0.0) { gStar = mGStar/mFluidVolumeHeight; } return gStar; } /****************************************************************************** * function that tries to calculate all the missing values from the given ones * prints errors and returns false if thats not possible *****************************************************************************/ bool Parametrizer::calculateAllMissingValues( double time, bool silent ) { bool init = false; // did we init correctly? int valuesChecked = 0; int reqValues; // we always need the sizes reqValues = PARAM_SIZE; valuesChecked |= reqValues; if(!checkSeenValues(reqValues)) { errMsg("Parametrizer::calculateAllMissingValues"," Missing size argument!"); return false; } if(!checkSeenValues(PARAM_DOMAINSIZE)) { errMsg("Parametrizer::calculateAllMissingValues"," Missing domain size argument!"); return false; } int maxsize = mSizex; // get max size if(mSizey>maxsize) maxsize = mSizey; if(mSizez>maxsize) maxsize = mSizez; maxsize = mSizez; // take along gravity dir for now! mCellSize = ( mDomainSize * calculateCellSize() ); // sets mCellSize if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," max domain resolution="<<(maxsize)<<" cells , cellsize="<0.0) { debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," height"<0.0) { // explicitly set step time according to max velocity in sim setDeltaT = mDesiredTimestep; if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," desired step time = "<0)) { if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<(set); seenThis( PARAM_VISCOSITY ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcViscosity set = "<< mcViscosity.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } void Parametrizer::initViscosityChannel(vector val, vector time) { mcViscosity = AnimChannel(val,time); seenThis( PARAM_VISCOSITY ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcViscosity initc = "<< mcViscosity.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } /*! set the external force */ void Parametrizer::setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mcGravity = AnimChannel(ParamVec(setx,sety,setz)); seenThis( PARAM_GRAVITY ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcGravity set = "<< mcGravity.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } void Parametrizer::setGravity(ParamVec set) { mcGravity = AnimChannel(set); seenThis( PARAM_GRAVITY ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcGravity set = "<< mcGravity.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } void Parametrizer::initGravityChannel(vector val, vector time) { mcGravity = AnimChannel(val,time); seenThis( PARAM_GRAVITY ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcGravity initc = "<< mcGravity.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } /*! set time of an animation frame (renderer) */ void Parametrizer::setAniFrameTimeChannel(ParamFloat set) { mcAniFrameTime = AnimChannel(set); seenThis( PARAM_ANIFRAMETIME ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcAniFrameTime set = "<< mcAniFrameTime.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } void Parametrizer::initAniFrameTimeChannel(vector val, vector time) { mcAniFrameTime = AnimChannel(val,time); seenThis( PARAM_ANIFRAMETIME ); #if DEBUG_PARAMCHANNELS>0 { errMsg("DebugChannels","Parametrizer::mcAniFrameTime initc = "<< mcAniFrameTime.printChannel() ); } #endif // DEBUG_PARAMCHANNELS>0 } // OLD interface stuff // reactivate at some point? /*! surface tension, [kg/s^2] */ //ParamFloat mSurfaceTension; /*! set starting time of the animation (renderer) */ //void setSurfaceTension(ParamFloat set) { mSurfaceTension = set; seenThis( PARAM_SURFACETENSION ); } /*! get starting time of the animation (renderer) */ //ParamFloat getSurfaceTension( void ) { return mSurfaceTension; } /*if((checkSeenValues(PARAM_SURFACETENSION))&&(mSurfaceTension>0.0)) { ParamFloat massDelta = 1.0; ParamFloat densityStar = 1.0; massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize; if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<0.0) { ParamFloat maxSpeed = 1.0/6.0; // for rough reynolds approx ParamFloat reynoldsApprox = -1.0; ParamFloat gridSpeed = (maxSpeed*mCellSize/mTimestep); reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity; if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<readFloat("p_relaxtime",mRelaxTime, "Parametrizer","mRelaxTime", false); //if(getAttributeList()->exists("p_relaxtime")) seenThis( PARAM_RELAXTIME ); //? mReynolds = mpAttrs->readFloat("p_reynolds",mReynolds, "Parametrizer","mReynolds", false); //if(getAttributeList()->exists("p_reynolds")) seenThis( PARAM_REYNOLDS ); //mViscosity = mpAttrs->readFloat("p_viscosity",mViscosity, "Parametrizer","mViscosity", false); //if(getAttributeList()->exists("p_viscosity") || (!mcViscosity.isInited()) ) { } //if(getAttributeList()->exists("p_viscosity")) //ParamFloat viscStar = calculateLatticeViscosity(time); //RelaxTime = (6.0 * viscStar + 1) * 0.5;