diff options
70 files changed, 8149 insertions, 5469 deletions
diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript index 8c1aa59170c..3044ecff0b7 100644 --- a/intern/elbeem/SConscript +++ b/intern/elbeem/SConscript @@ -1,21 +1,9 @@ #!/usr/bin/python import sys import os -Import('env') - -#if use_fluidsim=='false': -# # print "El'Beem Fluid Simulation Disabled..." # debug -# elbeem_env.Append (CPPPATH = user_options_dict['PNG_INCLUDE']) -# elbeem_env.Append (CPPPATH = user_options_dict['SDL_INCLUDE']) -# elbeem_env.Append(CPPDEFINES= 'ELBEEM_DUMMIES'); -# # dummy interface build -# Sources = [ -# "intern/utilities.cpp", -# "intern/blenderdummy.cpp" -# ]; # sources +import('env') sources = env.Glob('intern/*.cpp') -sources.remove('intern'+os.sep+'blenderdummy.cpp') defs = 'NOGUI ELBEEM_BLENDER=1' if env['OURPLATFORM']=='win32-vc': diff --git a/intern/elbeem/extern/LBM_fluidsim.h b/intern/elbeem/extern/LBM_fluidsim.h index ff0b0a465dd..b879dd41396 100644 --- a/intern/elbeem/extern/LBM_fluidsim.h +++ b/intern/elbeem/extern/LBM_fluidsim.h @@ -53,7 +53,7 @@ void fluidsimBake(struct Object* ob); /* read & write bobj / bobj.gz files (e.g. for fluid sim surface meshes) */ void writeBobjgz(char *filename, struct Object *ob); -struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh); +struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh, float* bbstart, float *bbsize); /* create derived mesh for fluid sim objects */ // WARNING - currently implemented in DerivedMesh.c! @@ -66,7 +66,7 @@ int performElbeemSimulation(char *cfgfilename); /* init axis aligned BB for mesh object */ // implemented in source/blender/blenkernel/intern/DerivedMesh.c void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4], - /*RET*/ float start[3], /*RET*/ float size[3] ); + /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh ); // implemented in intern/elbeem/utilities.cpp /* set elbeem debug output level (0=off to 10=full on) */ diff --git a/intern/elbeem/intern/attributes.cpp b/intern/elbeem/intern/attributes.cpp index 8689a3fe98e..abdd931a4bf 100644 --- a/intern/elbeem/intern/attributes.cpp +++ b/intern/elbeem/intern/attributes.cpp @@ -8,12 +8,17 @@ *****************************************************************************/ #include "attributes.h" +#include "ntl_matrices.h" +#include "elbeem.h" #include <sstream> //! output attribute values? on=1/off=0 #define DEBUG_ATTRIBUTES 0 +//! output channel values? on=1/off=0 +#define DEBUG_CHANNELS 0 + /****************************************************************************** * attribute conversion functions @@ -70,20 +75,19 @@ bool Attribute::initChannel(int elemSize) { mValue = newvalue; mChannelInited = elemSize; - print(); + if(DEBUG_CHANNELS) print(); return true; } // get value as string -string Attribute::getAsString() +string Attribute::getAsString(bool debug) { - if(mIsChannel) { + if(mIsChannel && (!debug)) { errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string is a channel! Not allowed..."); print(); return string(""); } if(mValue.size()!=1) { - //errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string has invalid value '"<< getCompleteString() <<"' "); // for directories etc. , this might be valid! cutoff "..." first string comp = getCompleteString(); if(comp.size()<2) return string(""); @@ -215,7 +219,7 @@ ntlVec3d Attribute::getAsVec3d() } // get value as 4x4 matrix -ntlMat4Gfx Attribute::getAsMat4Gfx() +void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat) { bool success = true; ntlMat4Gfx ret(0.0); @@ -265,9 +269,10 @@ ntlMat4Gfx Attribute::getAsMat4Gfx() #if ELBEEM_PLUGIN!=1 gElbeemState = -4; // parse error #endif - return ntlMat4Gfx(0.0); + *mat = ntlMat4Gfx(0.0); + return; } - return ret; + *mat = ret; } @@ -355,7 +360,7 @@ bool AttributeList::checkUnusedParams() i != mAttrs.end(); i++) { if((*i).second) { if(!(*i).second->getUsed()) { - errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString() <<"' "); + errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString(true) <<"' "); found = true; } } @@ -409,7 +414,7 @@ string AttributeList::readString(string name, string defaultValue, string source } if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); } find(name)->setUsed(true); - return find(name)->getAsString(); + return find(name)->getAsString(false); } ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) { if(!exists(name)) { @@ -421,14 +426,16 @@ ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string sou return find(name)->getAsVec3d(); } -ntlMat4Gfx AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed) { +void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed, ntlMat4Gfx *mat) { if(!exists(name)) { if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); } - return defaultValue; + *mat = defaultValue; + return; } if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); } find(name)->setUsed(true); - return find(name)->getAsMat4Gfx(); + find(name)->getAsMat4Gfx( mat ); + return; } // set that a parameter can be given, and will be ignored... @@ -442,15 +449,39 @@ bool AttributeList::ignoreParameter(string name, string source) { // read channels AnimChannel<double> AttributeList::readChannelFloat(string name) { if(!exists(name)) { return AnimChannel<double>(0.0); } - return find(name)->getChannelFloat(); + AnimChannel<double> ret = find(name)->getChannelFloat(); + find(name)->setUsed(true); + channelSimplifyd(ret); + return ret; } AnimChannel<int> AttributeList::readChannelInt(string name) { if(!exists(name)) { return AnimChannel<int>(0); } - return find(name)->getChannelInt(); + AnimChannel<int> ret = find(name)->getChannelInt(); + find(name)->setUsed(true); + channelSimplifyi(ret); + return ret; } AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name) { if(!exists(name)) { return AnimChannel<ntlVec3d>(0.0); } - return find(name)->getChannelVec3d(); + AnimChannel<ntlVec3d> ret = find(name)->getChannelVec3d(); + find(name)->setUsed(true); + channelSimplifyVd(ret); + return ret; +} +AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name) { + if(!exists(name)) { return AnimChannel<ntlVec3f>(0.0); } + + AnimChannel<ntlVec3d> convert = find(name)->getChannelVec3d(); + // convert to float + vector<ntlVec3f> vals; + for(size_t i=0; i<convert.accessValues().size(); i++) { + vals.push_back( vec2F(convert.accessValues()[i]) ); + } + vector<double> times = convert.accessTimes(); + AnimChannel<ntlVec3f> ret(vals, times); + find(name)->setUsed(true); + channelSimplifyVf(ret); + return ret; } /****************************************************************************** @@ -509,7 +540,6 @@ void AttributeList::print() } - /****************************************************************************** * import attributes from other attribute list *****************************************************************************/ @@ -526,5 +556,133 @@ void AttributeList::import(AttributeList *oal) } +/****************************************************************************** + * channel max finding + *****************************************************************************/ +ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel) { + ntlVec3f ret(0.0); + float maxLen = 0.0; + for(size_t i=0; i<channel.accessValues().size(); i++) { + float nlen = normNoSqrt(channel.accessValues()[i]); + if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +ntlVec3d channelFindMaxVd (AnimChannel<ntlVec3d> channel) { + ntlVec3d ret(0.0); + float maxLen = 0.0; + for(size_t i=0; i<channel.accessValues().size(); i++) { + float nlen = normNoSqrt(channel.accessValues()[i]); + if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +int channelFindMaxi (AnimChannel<float > channel) { + int ret = 0; + float maxLen = 0.0; + for(size_t i=0; i<channel.accessValues().size(); i++) { + float nlen = ABS(channel.accessValues()[i]); + if(nlen>maxLen) { ret= (int)channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +float channelFindMaxf (AnimChannel<float > channel) { + float ret = 0.0; + float maxLen = 0.0; + for(size_t i=0; i<channel.accessValues().size(); i++) { + float nlen = ABS(channel.accessValues()[i]); + if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +double channelFindMaxd (AnimChannel<double > channel) { + double ret = 0.0; + float maxLen = 0.0; + for(size_t i=0; i<channel.accessValues().size(); i++) { + float nlen = ABS(channel.accessValues()[i]); + if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} + +/****************************************************************************** + // unoptimized channel simplification functions, use elbeem.cpp functions + // warning - currently only with single precision + *****************************************************************************/ + +template<class SCALAR> +static bool channelSimplifyScalarT(AnimChannel<SCALAR> &channel) { + int size = channel.getSize(); + if(size<=1) return false; + float *nchannel = new float[2*size]; + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() ); + // convert to array + for(size_t i=0; i<channel.accessValues().size(); i++) { + nchannel[i*2 + 0] = (float)channel.accessValues()[i]; + nchannel[i*2 + 1] = (float)channel.accessTimes()[i]; + } + bool ret = elbeemSimplifyChannelFloat(nchannel, &size); + if(ret) { + vector<SCALAR> vals; + vector<double> times; + for(int i=0; i<size; i++) { + vals.push_back( (SCALAR)(nchannel[i*2 + 0]) ); + times.push_back( (double)(nchannel[i*2 + 1]) ); + } + channel = AnimChannel<SCALAR>(vals, times); + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() ); + } + delete [] nchannel; + return ret; +} +bool channelSimplifyi (AnimChannel<int > &channel) { return channelSimplifyScalarT<int>(channel); } +bool channelSimplifyf (AnimChannel<float> &channel) { return channelSimplifyScalarT<float>(channel); } +bool channelSimplifyd (AnimChannel<double > &channel) { return channelSimplifyScalarT<double>(channel); } +template<class VEC> +static bool channelSimplifyVecT(AnimChannel<VEC> &channel) { + int size = channel.getSize(); + if(size<=1) return false; + float *nchannel = new float[4*size]; + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() ); + // convert to array + for(size_t i=0; i<channel.accessValues().size(); i++) { + nchannel[i*4 + 0] = (float)channel.accessValues()[i][0]; + nchannel[i*4 + 1] = (float)channel.accessValues()[i][1]; + nchannel[i*4 + 2] = (float)channel.accessValues()[i][2]; + nchannel[i*4 + 3] = (float)channel.accessTimes()[i]; + } + bool ret = elbeemSimplifyChannelVec3(nchannel, &size); + if(ret) { + vector<VEC> vals; + vector<double> times; + for(int i=0; i<size; i++) { + vals.push_back( VEC(nchannel[i*4 + 0], nchannel[i*4 + 1], nchannel[i*4 + 2] ) ); + times.push_back( (double)(nchannel[i*4 + 3]) ); + } + channel = AnimChannel<VEC>(vals, times); + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() ); + } + delete [] nchannel; + return ret; +} +bool channelSimplifyVf (AnimChannel<ntlVec3f> &channel) { + return channelSimplifyVecT<ntlVec3f>(channel); +} +bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel) { + return channelSimplifyVecT<ntlVec3d>(channel); +} + +template<class Scalar> +string AnimChannel<Scalar>::printChannel() { + std::ostringstream ostr; + ostr << " CHANNEL #"<< mValue.size() <<" = { "; + for(size_t i=0;i<mValue.size();i++) { + ostr <<"'"<< mValue[i]<<"' "; + ostr << "@"<<mTimes[i]<<"; "; + } + ostr << " } "; + return ostr.str(); +} // */ + diff --git a/intern/elbeem/intern/attributes.h b/intern/elbeem/intern/attributes.h index f9f44e2eb52..730e136f962 100644 --- a/intern/elbeem/intern/attributes.h +++ b/intern/elbeem/intern/attributes.h @@ -11,7 +11,7 @@ #ifndef NTL_ATTRIBUTES_H #include "utilities.h" -#include "ntl_matrices.h" +template<class T> class ntlMatrix4x4; //! An animated attribute channel @@ -19,19 +19,24 @@ template<class Scalar> class AnimChannel { public: + // default constructor + AnimChannel() : + mValue(), mTimes() { mInited = false; } + // null init constructor AnimChannel(Scalar null) : - mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; }; + mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; mInited = true; } // proper init AnimChannel(vector<Scalar> v, vector<double> t) : - mValue(v), mTimes(t) { }; + mValue(v), mTimes(t) { mInited = true; } // desctructor, nothing to do ~AnimChannel() { }; // get interpolated value at time t Scalar get(double t) { + if(!mInited) { Scalar null; null=(Scalar)(0.0); return null; } if(t<=mTimes[0]) { return mValue[0]; } if(t>=mTimes[mTimes.size()-1]) { return mValue[mTimes.size()-1]; } for(size_t i=0; i<mTimes.size()-1; i++) { @@ -40,7 +45,7 @@ class AnimChannel // interpolate double d = mTimes[i+1]-mTimes[i]; double f = (t-mTimes[i])/d; - return mValue[i] * (1.0-f) + mValue[i+1] * f; + return (Scalar)(mValue[i] * (1.0-f) + mValue[i+1] * f); } } // whats this...? @@ -50,6 +55,7 @@ class AnimChannel // get uninterpolated value at time t Scalar getConstant(double t) { //errMsg("DEBB","getc"<<t<<" "); + if(!mInited) { Scalar null; null=(Scalar)0.0; return null; } if(t<=mTimes[0]) { return mValue[0]; } if(t>=mTimes[mTimes.size()-1]) { return mValue[mTimes.size()-1]; } for(size_t i=0; i<mTimes.size()-1; i++) { @@ -69,14 +75,29 @@ class AnimChannel mTimes.push_back(0.0); } + //! debug function, prints channel as string + string printChannel(); + //! valid init? + bool isInited() { return mInited; } + + //! get number of entries (value and time sizes have to be equal) + int getSize() { return mValue.size(); }; + //! raw access of value vector + vector<Scalar> &accessValues() { return mValue; } + //! raw access of time vector + vector<double> &accessTimes() { return mTimes; } + protected: + /*! inited at least once? */ + bool mInited; /*! anim channel attribute values */ vector<Scalar> mValue; /*! anim channel attr times */ vector<double> mTimes; }; + //! A single attribute class Attribute { @@ -106,7 +127,7 @@ class Attribute bool getIsChannel() { return mIsChannel; } //! get value as string - string getAsString(); + string getAsString(bool debug=false); //! get value as integer value int getAsInt(); //! get value as boolean @@ -116,13 +137,13 @@ class Attribute //! get value as 3d vector ntlVec3d getAsVec3d(); //! get value as 4x4 matrix - ntlMat4Gfx getAsMat4Gfx(); + void getAsMat4Gfx(ntlMatrix4x4<gfxReal> *mat); //! get channel as integer value AnimChannel<int> getChannelInt(); //! get channel as double value AnimChannel<double> getChannelFloat(); - //! get channel as double value + //! get channel as double vector AnimChannel<ntlVec3d> getChannelVec3d(); //! get the concatenated string of all value string @@ -207,11 +228,12 @@ class AttributeList double readFloat(string name, double defaultValue, string source,string target, bool needed); string readString(string name, string defaultValue, string source,string target, bool needed); ntlVec3d readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed); - ntlMat4Gfx readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed); + void readMat4Gfx(string name, ntlMatrix4x4<gfxReal> defaultValue, string source,string target, bool needed, ntlMatrix4x4<gfxReal> *mat); //! read attributes channels (attribute should be inited before) AnimChannel<int> readChannelInt(string name); AnimChannel<double> readChannelFloat(string name); AnimChannel<ntlVec3d> readChannelVec3d(string name); + AnimChannel<ntlVec3f> readChannelVec3f(string name); //! set that a parameter can be given, and will be ignored... bool ignoreParameter(string name, string source); @@ -229,6 +251,19 @@ class AttributeList }; +ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel); +ntlVec3d channelFindMaxVd (AnimChannel<ntlVec3d> channel); +int channelFindMaxi (AnimChannel<int > channel); +float channelFindMaxf (AnimChannel<float > channel); +double channelFindMaxd (AnimChannel<double > channel); + +// unoptimized channel simplification functions, use elbeem.cpp functions +bool channelSimplifyVf (AnimChannel<ntlVec3f> &channel); +bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel); +bool channelSimplifyi (AnimChannel<int > &channel); +bool channelSimplifyf (AnimChannel<float > &channel); +bool channelSimplifyd (AnimChannel<double > &channel); + #define NTL_ATTRIBUTES_H #endif diff --git a/intern/elbeem/intern/blendercall.cpp b/intern/elbeem/intern/blendercall.cpp deleted file mode 100644 index f1617da8296..00000000000 --- a/intern/elbeem/intern/blendercall.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * All code distributed as part of El'Beem is covered by the version 2 of the - * GNU General Public License. See the file COPYING for details. - * Copyright 2003-2005 Nils Thuerey - * - * Blender call interface - * - *****************************************************************************/ - -#include "globals.h" -#include "utilities.h" -#include "ntl_blenderdumper.h" -#include <stdlib.h> - -// ELBEEM_BLENDER always =1 here -extern "C" void elbeemCheckDebugEnv(void); - -extern "C" -int performElbeemSimulation(char *cfgfilename) { - gElbeemState = SIMWORLD_INVALID; - strcpy(gElbeemErrorString,"[none]"); - - //if(gDebugLevel>0) { - elbeemCheckDebugEnv(); - debMsgStd("performElbeemSimulation",DM_NOTIFY,"Running El'Beem from Blender with file '"<< cfgfilename <<"', debugLevel:"<<gDebugLevel<<" ...\n", 2); - //} - // load given file in command line mode - ntlBlenderDumper elbeem(cfgfilename, true); - if(SIMWORLD_OK()) { - gElbeemState = SIMWORLD_INITED; - myTime_t timestart = getTime(); - elbeem.renderAnimation(); - myTime_t timeend = getTime(); - debMsgStd("performElbeemSimulation",DM_NOTIFY, "El'Beem simulation done, time: "<<((timeend-timestart)/(double)1000.0) <<" seconds.\n", 2 ); - } else { - // signal there was an initialization problem - setGlobalBakeState( -2 ); - } - return 1; -}; - - diff --git a/intern/elbeem/intern/blenderdummy.cpp b/intern/elbeem/intern/blenderdummy.cpp deleted file mode 100644 index 4d672dee528..00000000000 --- a/intern/elbeem/intern/blenderdummy.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * All code distributed as part of El'Beem is covered by the version 2 of the - * GNU General Public License. See the file COPYING for details. - * Copyright 2003-2005 Nils Thuerey - * - * Blender call for disabled fluidsim - * - *****************************************************************************/ - -#include <stdlib.h> - -extern "C" -int performElbeemSimulation(char *cfgfilename) { - return 1; -}; - - diff --git a/intern/elbeem/intern/cfglexer.cpp b/intern/elbeem/intern/cfglexer.cpp index 472c6929451..0bc9d96b5b2 100644 --- a/intern/elbeem/intern/cfglexer.cpp +++ b/intern/elbeem/intern/cfglexer.cpp @@ -430,16 +430,16 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 6, 1, 1, 1, 1, 1, - 1, 7, 1, 1, 8, 9, 10, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 12, 13, 1, - 14, 1, 1, 1, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 33, - 1, 15, 1, 1, 16, 1, 17, 18, 19, 20, - - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 33, 42, 1, 43, 1, 1, 1, 1, 1, + 1, 7, 8, 1, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 14, 1, + 15, 1, 1, 1, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 34, + 1, 16, 1, 1, 17, 1, 18, 19, 20, 21, + + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 34, 43, 1, 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -456,103 +456,103 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[44] = +static yyconst flex_int32_t yy_meta[45] = { 0, - 1, 2, 3, 4, 1, 1, 1, 5, 6, 5, - 6, 5, 2, 1, 5, 6, 6, 6, 6, 6, + 1, 2, 3, 4, 1, 1, 1, 5, 5, 6, + 5, 6, 5, 2, 1, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 1, 1 + 6, 6, 1, 1 } ; -static yyconst flex_int16_t yy_base[576] = +static yyconst flex_int16_t yy_base[575] = { 0, - 0, 0, 43, 86, 128, 170, 704, 705, 60, 705, - 63, 0, 0, 43, 692, 53, 50, 47, 53, 78, - 47, 39, 87, 681, 43, 82, 54, 80, 117, 92, - 93, 112, 116, 669, 99, 123, 138, 149, 152, 0, - 141, 0, 695, 156, 101, 705, 157, 160, 163, 175, - 180, 694, 0, 687, 176, 686, 705, 0, 177, 660, - 677, 153, 662, 657, 673, 101, 651, 161, 46, 175, - 178, 670, 668, 660, 659, 649, 647, 186, 653, 645, - 651, 658, 649, 168, 645, 649, 648, 650, 653, 644, - 705, 652, 641, 174, 630, 192, 653, 131, 652, 633, - - 198, 635, 628, 631, 629, 214, 219, 222, 226, 0, - 227, 0, 658, 657, 230, 0, 235, 705, 0, 636, - 635, 146, 634, 637, 623, 629, 625, 624, 705, 617, - 617, 620, 618, 612, 623, 619, 624, 705, 613, 609, - 622, 617, 600, 611, 604, 609, 616, 601, 611, 607, - 612, 598, 597, 609, 206, 600, 705, 603, 597, 596, - 584, 599, 587, 601, 587, 600, 588, 598, 598, 595, - 581, 578, 583, 591, 590, 589, 588, 572, 582, 238, - 568, 584, 570, 567, 585, 582, 575, 576, 578, 567, - 561, 559, 183, 577, 570, 562, 570, 553, 558, 567, - - 216, 567, 705, 565, 555, 563, 549, 545, 545, 563, - 545, 561, 546, 705, 545, 554, 543, 705, 550, 549, - 548, 534, 535, 543, 550, 545, 537, 533, 526, 528, - 525, 531, 524, 529, 705, 705, 538, 535, 537, 533, - 523, 535, 534, 522, 513, 530, 513, 525, 705, 521, - 519, 705, 509, 508, 221, 520, 521, 504, 513, 705, - 506, 519, 507, 499, 512, 496, 495, 496, 705, 493, - 503, 486, 492, 497, 490, 503, 494, 705, 490, 495, - 502, 480, 498, 482, 478, 475, 485, 491, 705, 480, - 193, 493, 705, 469, 480, 705, 471, 477, 471, 479, - - 705, 466, 471, 467, 483, 480, 705, 477, 476, 465, - 470, 478, 457, 471, 461, 470, 460, 470, 460, 458, - 451, 705, 462, 705, 466, 462, 705, 440, 444, 458, - 461, 447, 445, 456, 453, 448, 453, 435, 441, 452, - 705, 448, 221, 450, 426, 705, 444, 436, 442, 426, - 444, 424, 422, 441, 437, 227, 428, 417, 434, 413, - 435, 417, 705, 414, 428, 427, 418, 421, 705, 404, - 427, 415, 421, 418, 415, 411, 402, 705, 407, 411, - 400, 404, 416, 407, 414, 396, 408, 408, 391, 392, - 227, 705, 400, 219, 705, 389, 402, 392, 385, 389, - - 385, 394, 231, 399, 395, 394, 393, 377, 387, 705, - 705, 705, 705, 379, 705, 391, 705, 377, 377, 388, - 705, 370, 705, 375, 380, 383, 365, 370, 368, 705, - 705, 374, 379, 376, 375, 361, 371, 705, 368, 705, - 357, 371, 354, 350, 354, 356, 369, 351, 355, 355, - 705, 354, 345, 361, 705, 358, 342, 347, 355, 341, - 351, 356, 351, 336, 340, 351, 332, 336, 336, 333, - 339, 339, 333, 705, 705, 327, 325, 342, 322, 325, - 335, 705, 705, 705, 321, 705, 705, 330, 318, 317, - 705, 705, 331, 310, 313, 705, 323, 322, 318, 326, - - 308, 326, 306, 320, 705, 705, 320, 308, 705, 308, - 312, 705, 705, 705, 305, 705, 310, 317, 295, 705, - 311, 307, 300, 705, 705, 236, 299, 305, 309, 287, - 306, 289, 302, 705, 705, 299, 296, 296, 281, 274, - 267, 264, 263, 705, 705, 269, 258, 261, 705, 267, - 250, 705, 705, 245, 225, 222, 705, 212, 166, 705, - 705, 155, 705, 705, 705, 268, 274, 277, 283, 113, - 289, 295, 301, 307, 313 + 0, 0, 44, 0, 87, 130, 713, 714, 95, 714, + 102, 0, 0, 84, 700, 96, 90, 85, 91, 92, + 86, 83, 122, 689, 82, 85, 101, 111, 133, 118, + 137, 128, 125, 677, 136, 124, 166, 167, 173, 0, + 174, 0, 704, 177, 173, 714, 181, 185, 188, 191, + 192, 703, 0, 695, 187, 694, 714, 0, 188, 668, + 685, 175, 670, 665, 681, 180, 659, 167, 178, 190, + 192, 678, 676, 668, 667, 657, 655, 200, 661, 653, + 659, 666, 657, 182, 653, 657, 656, 658, 661, 652, + 714, 660, 649, 191, 638, 205, 661, 199, 660, 641, + + 208, 643, 636, 639, 637, 231, 235, 236, 240, 0, + 241, 0, 667, 666, 245, 0, 246, 714, 0, 644, + 643, 229, 642, 645, 631, 637, 633, 632, 714, 625, + 625, 628, 626, 620, 631, 627, 632, 714, 621, 617, + 630, 625, 608, 619, 612, 617, 624, 609, 619, 615, + 620, 606, 605, 617, 222, 608, 714, 611, 605, 604, + 592, 607, 595, 609, 595, 608, 596, 606, 606, 603, + 589, 586, 591, 599, 598, 597, 596, 580, 590, 252, + 576, 592, 578, 575, 593, 590, 583, 584, 586, 575, + 569, 567, 229, 585, 578, 570, 578, 561, 566, 575, + + 227, 575, 714, 573, 563, 571, 557, 553, 553, 571, + 553, 569, 554, 714, 553, 562, 551, 714, 558, 557, + 556, 542, 543, 551, 558, 553, 545, 541, 534, 536, + 533, 539, 532, 537, 714, 714, 546, 543, 545, 541, + 531, 543, 542, 530, 521, 538, 521, 533, 714, 529, + 527, 714, 517, 516, 239, 528, 529, 512, 521, 714, + 514, 527, 515, 507, 520, 504, 503, 504, 714, 501, + 511, 494, 500, 505, 498, 511, 502, 714, 498, 503, + 510, 488, 506, 490, 486, 483, 493, 499, 714, 488, + 244, 501, 714, 477, 488, 714, 479, 485, 479, 487, + + 714, 474, 479, 475, 491, 488, 714, 485, 484, 473, + 478, 486, 465, 479, 469, 478, 468, 478, 468, 466, + 459, 714, 470, 714, 474, 470, 714, 448, 452, 466, + 469, 455, 453, 464, 461, 456, 461, 443, 449, 460, + 714, 456, 249, 458, 434, 714, 452, 444, 450, 434, + 452, 432, 430, 449, 445, 245, 436, 425, 442, 421, + 443, 425, 714, 422, 436, 435, 426, 429, 714, 412, + 435, 423, 429, 426, 423, 419, 410, 714, 415, 419, + 408, 412, 424, 415, 422, 404, 416, 416, 399, 400, + 252, 714, 408, 238, 714, 397, 410, 400, 393, 397, + + 393, 402, 246, 407, 403, 402, 401, 385, 395, 714, + 714, 714, 714, 387, 714, 399, 714, 385, 385, 396, + 714, 378, 714, 383, 388, 391, 373, 378, 376, 714, + 714, 382, 387, 384, 383, 369, 379, 714, 376, 714, + 365, 379, 362, 358, 362, 364, 377, 359, 363, 363, + 714, 362, 353, 369, 714, 366, 350, 355, 363, 349, + 359, 364, 359, 344, 348, 359, 340, 344, 344, 341, + 347, 347, 341, 714, 714, 335, 333, 350, 330, 333, + 343, 714, 714, 714, 329, 714, 714, 338, 326, 325, + 714, 714, 339, 318, 321, 714, 331, 330, 326, 334, + + 316, 334, 314, 328, 714, 714, 328, 316, 714, 316, + 320, 714, 714, 714, 313, 714, 318, 325, 303, 714, + 319, 315, 305, 714, 714, 261, 299, 300, 300, 278, + 297, 277, 290, 714, 714, 287, 280, 268, 256, 254, + 252, 252, 251, 714, 714, 256, 248, 231, 714, 228, + 197, 714, 714, 207, 167, 149, 714, 150, 106, 714, + 714, 101, 714, 714, 714, 294, 297, 303, 89, 309, + 315, 321, 327, 333 } ; -static yyconst flex_int16_t yy_def[576] = +static yyconst flex_int16_t yy_def[575] = { 0, - 565, 1, 566, 566, 567, 567, 565, 565, 565, 565, - 565, 568, 569, 565, 565, 565, 565, 565, 565, 565, + 565, 1, 565, 3, 566, 566, 565, 565, 565, 565, + 565, 567, 568, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, - 565, 565, 565, 565, 565, 565, 565, 565, 565, 570, - 565, 571, 572, 573, 571, 565, 571, 571, 565, 565, - 565, 568, 569, 565, 565, 565, 565, 574, 565, 565, + 565, 565, 565, 565, 565, 565, 565, 565, 565, 569, + 565, 570, 571, 572, 570, 565, 570, 570, 565, 565, + 565, 567, 568, 565, 565, 565, 565, 573, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, - 565, 565, 565, 565, 565, 565, 565, 565, 565, 570, - 565, 571, 572, 572, 573, 571, 575, 565, 574, 565, + 565, 565, 565, 565, 565, 565, 565, 565, 565, 569, + 565, 570, 571, 571, 572, 570, 574, 565, 573, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, - 565, 565, 565, 565, 565, 565, 565, 565, 565, 575, + 565, 565, 565, 565, 565, 565, 565, 565, 565, 574, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, @@ -596,175 +596,177 @@ static yyconst flex_int16_t yy_def[576] = 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 0, 565, 565, 565, 565, 565, - 565, 565, 565, 565, 565 + 565, 565, 565, 565 } ; -static yyconst flex_int16_t yy_nxt[749] = +static yyconst flex_int16_t yy_nxt[759] = { 0, - 8, 9, 10, 11, 12, 13, 8, 14, 15, 16, - 17, 8, 8, 8, 8, 8, 18, 19, 20, 21, - 22, 23, 24, 8, 25, 8, 8, 26, 27, 28, - 29, 30, 8, 31, 32, 33, 34, 35, 8, 8, - 8, 36, 37, 8, 38, 10, 39, 8, 13, 8, - 8, 54, 16, 55, 8, 8, 41, 8, 54, 57, - 59, 49, 58, 49, 49, 60, 49, 70, 72, 65, - 84, 71, 80, 132, 133, 61, 62, 81, 85, 73, - 66, 63, 64, 67, 36, 37, 8, 38, 10, 39, - 8, 13, 8, 8, 68, 16, 86, 8, 8, 41, - - 8, 50, 51, 74, 50, 51, 82, 116, 69, 95, - 117, 75, 83, 96, 76, 93, 87, 77, 110, 104, - 78, 127, 94, 105, 106, 128, 106, 36, 37, 9, - 10, 11, 43, 44, 88, 97, 100, 45, 89, 107, - 46, 107, 111, 98, 111, 90, 91, 99, 92, 101, - 108, 169, 108, 108, 170, 108, 102, 53, 106, 53, - 106, 107, 109, 107, 49, 109, 49, 183, 53, 47, - 48, 9, 10, 11, 43, 44, 106, 122, 106, 45, - 184, 107, 46, 107, 54, 54, 55, 59, 123, 564, - 50, 51, 134, 50, 51, 130, 135, 131, 136, 137, - - 563, 161, 144, 151, 50, 51, 145, 152, 162, 343, - 164, 47, 48, 165, 173, 106, 252, 106, 174, 253, - 107, 166, 107, 108, 344, 108, 167, 111, 111, 111, - 111, 53, 562, 53, 175, 109, 119, 215, 119, 119, - 388, 119, 53, 216, 261, 262, 435, 119, 309, 310, - 119, 401, 311, 438, 439, 537, 389, 561, 402, 447, - 560, 403, 436, 50, 51, 559, 448, 538, 40, 40, - 40, 40, 40, 40, 42, 42, 42, 42, 42, 42, - 52, 52, 52, 53, 53, 558, 53, 53, 53, 112, - 557, 556, 555, 112, 112, 113, 554, 553, 552, 113, - - 113, 115, 115, 551, 115, 115, 115, 119, 119, 550, - 119, 119, 119, 180, 180, 549, 180, 180, 180, 548, - 547, 546, 545, 544, 543, 542, 541, 540, 539, 536, - 535, 534, 533, 532, 531, 530, 529, 528, 527, 526, - 525, 524, 523, 522, 521, 520, 519, 518, 517, 516, - 515, 514, 513, 512, 511, 510, 509, 508, 507, 506, - 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, - 495, 494, 493, 492, 491, 490, 489, 488, 487, 486, - 485, 484, 483, 482, 481, 480, 479, 478, 477, 476, - 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, - - 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, - 455, 454, 453, 452, 451, 450, 449, 446, 445, 444, - 443, 442, 441, 440, 437, 434, 433, 432, 431, 430, - 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, - 419, 418, 417, 416, 415, 414, 413, 412, 411, 410, - 409, 408, 407, 406, 405, 404, 400, 399, 398, 397, - 396, 395, 394, 393, 392, 391, 390, 387, 386, 385, - 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, - 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, - 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, - - 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, - 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, - 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, - 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, - 312, 308, 307, 306, 305, 304, 303, 302, 301, 300, - 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, - 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, - 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, - 269, 268, 267, 266, 265, 264, 263, 260, 259, 258, - 257, 256, 255, 254, 251, 250, 249, 248, 247, 246, - - 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, - 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, - 225, 224, 223, 222, 221, 220, 219, 218, 217, 214, - 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, - 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, - 193, 192, 191, 190, 189, 188, 187, 186, 185, 182, - 181, 114, 114, 179, 178, 177, 176, 172, 171, 168, - 163, 160, 159, 158, 157, 156, 155, 154, 153, 150, - 149, 148, 147, 146, 143, 142, 141, 140, 139, 138, - 129, 126, 125, 124, 121, 120, 56, 56, 118, 114, - - 103, 79, 56, 565, 7, 565, 565, 565, 565, 565, + 8, 9, 10, 11, 12, 13, 8, 8, 14, 15, + 16, 17, 8, 8, 8, 8, 8, 18, 19, 20, + 21, 22, 23, 24, 8, 25, 8, 8, 26, 27, + 28, 29, 30, 8, 31, 32, 33, 34, 35, 8, + 8, 8, 36, 37, 8, 38, 10, 39, 8, 13, + 8, 8, 8, 40, 16, 40, 8, 8, 41, 8, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 36, 37, 9, 10, + 11, 43, 44, 54, 110, 55, 49, 45, 49, 54, + + 46, 59, 57, 49, 60, 49, 58, 70, 65, 68, + 82, 71, 80, 72, 61, 62, 83, 81, 84, 66, + 63, 64, 67, 69, 73, 106, 85, 106, 86, 47, + 48, 9, 10, 11, 43, 44, 564, 50, 51, 74, + 45, 563, 93, 46, 50, 51, 100, 75, 87, 94, + 76, 88, 97, 77, 95, 89, 78, 104, 96, 101, + 98, 105, 90, 91, 99, 92, 102, 107, 108, 107, + 108, 562, 47, 48, 108, 111, 108, 111, 53, 116, + 53, 109, 106, 117, 106, 561, 107, 109, 107, 49, + 53, 49, 106, 107, 106, 107, 54, 54, 55, 59, + + 122, 127, 130, 560, 131, 128, 132, 133, 134, 50, + 51, 123, 135, 136, 137, 50, 51, 144, 151, 161, + 169, 145, 152, 170, 164, 173, 162, 165, 559, 174, + 50, 51, 106, 558, 106, 166, 107, 108, 107, 108, + 167, 111, 111, 111, 111, 175, 53, 119, 53, 119, + 109, 183, 557, 119, 215, 119, 261, 262, 53, 119, + 216, 343, 556, 252, 184, 119, 253, 309, 310, 388, + 401, 311, 435, 438, 439, 447, 344, 402, 50, 51, + 403, 537, 448, 555, 554, 389, 553, 552, 436, 551, + 550, 549, 548, 538, 42, 42, 42, 42, 42, 42, + + 52, 52, 52, 53, 53, 547, 53, 53, 53, 112, + 546, 545, 544, 112, 112, 113, 543, 542, 541, 113, + 113, 115, 115, 540, 115, 115, 115, 119, 119, 539, + 119, 119, 119, 180, 180, 536, 180, 180, 180, 535, + 534, 533, 532, 531, 530, 529, 528, 527, 526, 525, + 524, 523, 522, 521, 520, 519, 518, 517, 516, 515, + 514, 513, 512, 511, 510, 509, 508, 507, 506, 505, + 504, 503, 502, 501, 500, 499, 498, 497, 496, 495, + 494, 493, 492, 491, 490, 489, 488, 487, 486, 485, + 484, 483, 482, 481, 480, 479, 478, 477, 476, 475, + + 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, + 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, + 454, 453, 452, 451, 450, 449, 446, 445, 444, 443, + 442, 441, 440, 437, 434, 433, 432, 431, 430, 429, + 428, 427, 426, 425, 424, 423, 422, 421, 420, 419, + 418, 417, 416, 415, 414, 413, 412, 411, 410, 409, + 408, 407, 406, 405, 404, 400, 399, 398, 397, 396, + 395, 394, 393, 392, 391, 390, 387, 386, 385, 384, + 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, + 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, + + 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, + 353, 352, 351, 350, 349, 348, 347, 346, 345, 342, + 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, + 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, + 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, + 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, + 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, + 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, + 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, + 268, 267, 266, 265, 264, 263, 260, 259, 258, 257, + + 256, 255, 254, 251, 250, 249, 248, 247, 246, 245, + 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, + 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, + 224, 223, 222, 221, 220, 219, 218, 217, 214, 213, + 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, + 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, + 192, 191, 190, 189, 188, 187, 186, 185, 182, 181, + 114, 114, 179, 178, 177, 176, 172, 171, 168, 163, + 160, 159, 158, 157, 156, 155, 154, 153, 150, 149, + 148, 147, 146, 143, 142, 141, 140, 139, 138, 129, + + 126, 125, 124, 121, 120, 56, 56, 118, 114, 103, + 79, 56, 565, 7, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565 } ; -static yyconst flex_int16_t yy_chk[749] = +static yyconst flex_int16_t yy_chk[759] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, - 3, 14, 3, 14, 3, 3, 3, 3, 17, 16, - 17, 9, 16, 9, 11, 18, 11, 21, 22, 19, - 27, 21, 25, 69, 69, 18, 18, 25, 27, 22, - 19, 18, 18, 19, 3, 3, 4, 4, 4, 4, - 4, 4, 4, 4, 20, 4, 28, 4, 4, 4, - - 4, 9, 9, 23, 11, 11, 26, 45, 20, 31, - 45, 23, 26, 31, 23, 30, 28, 23, 570, 35, - 23, 66, 30, 35, 36, 66, 36, 4, 4, 5, - 5, 5, 5, 5, 29, 32, 33, 5, 29, 37, - 5, 37, 41, 32, 41, 29, 29, 32, 29, 33, - 38, 98, 38, 39, 98, 39, 33, 44, 47, 44, - 47, 48, 38, 48, 49, 39, 49, 122, 44, 5, - 5, 6, 6, 6, 6, 6, 50, 62, 50, 6, - 122, 51, 6, 51, 55, 59, 55, 59, 62, 562, - 38, 38, 70, 39, 39, 68, 70, 68, 71, 71, - - 559, 94, 78, 84, 49, 49, 78, 84, 94, 291, - 96, 6, 6, 96, 101, 106, 193, 106, 101, 193, - 107, 96, 107, 108, 291, 108, 96, 109, 111, 109, - 111, 115, 558, 115, 101, 108, 117, 155, 117, 180, - 343, 180, 115, 155, 201, 201, 391, 117, 255, 255, - 180, 356, 255, 394, 394, 526, 343, 556, 356, 403, - 555, 356, 391, 108, 108, 554, 403, 526, 566, 566, - 566, 566, 566, 566, 567, 567, 567, 567, 567, 567, - 568, 568, 568, 569, 569, 551, 569, 569, 569, 571, - 550, 548, 547, 571, 571, 572, 546, 543, 542, 572, - - 572, 573, 573, 541, 573, 573, 573, 574, 574, 540, - 574, 574, 574, 575, 575, 539, 575, 575, 575, 538, - 537, 536, 533, 532, 531, 530, 529, 528, 527, 523, - 522, 521, 519, 518, 517, 515, 511, 510, 508, 507, - 504, 503, 502, 501, 500, 499, 498, 497, 495, 494, - 493, 490, 489, 488, 485, 481, 480, 479, 478, 477, - 476, 473, 472, 471, 470, 469, 468, 467, 466, 465, - 464, 463, 462, 461, 460, 459, 458, 457, 456, 454, - 453, 452, 450, 449, 448, 447, 446, 445, 444, 443, - 442, 441, 439, 437, 436, 435, 434, 433, 432, 429, - - 428, 427, 426, 425, 424, 422, 420, 419, 418, 416, - 414, 409, 408, 407, 406, 405, 404, 402, 401, 400, - 399, 398, 397, 396, 393, 390, 389, 388, 387, 386, - 385, 384, 383, 382, 381, 380, 379, 377, 376, 375, - 374, 373, 372, 371, 370, 368, 367, 366, 365, 364, - 362, 361, 360, 359, 358, 357, 355, 354, 353, 352, - 351, 350, 349, 348, 347, 345, 344, 342, 340, 339, - 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, - 328, 326, 325, 323, 321, 320, 319, 318, 317, 316, - 315, 314, 313, 312, 311, 310, 309, 308, 306, 305, - - 304, 303, 302, 300, 299, 298, 297, 295, 294, 292, - 290, 288, 287, 286, 285, 284, 283, 282, 281, 280, - 279, 277, 276, 275, 274, 273, 272, 271, 270, 268, - 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, - 256, 254, 253, 251, 250, 248, 247, 246, 245, 244, - 243, 242, 241, 240, 239, 238, 237, 234, 233, 232, - 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, - 221, 220, 219, 217, 216, 215, 213, 212, 211, 210, - 209, 208, 207, 206, 205, 204, 202, 200, 199, 198, - 197, 196, 195, 194, 192, 191, 190, 189, 188, 187, - - 186, 185, 184, 183, 182, 181, 179, 178, 177, 176, - 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, - 165, 164, 163, 162, 161, 160, 159, 158, 156, 154, - 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, - 143, 142, 141, 140, 139, 137, 136, 135, 134, 133, - 132, 131, 130, 128, 127, 126, 125, 124, 123, 121, - 120, 114, 113, 105, 104, 103, 102, 100, 99, 97, - 95, 93, 92, 90, 89, 88, 87, 86, 85, 83, - 82, 81, 80, 79, 77, 76, 75, 74, 73, 72, - 67, 65, 64, 63, 61, 60, 56, 54, 52, 43, - - 34, 24, 15, 7, 565, 565, 565, 565, 565, 565, + 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, + 5, 5, 5, 14, 569, 14, 9, 5, 9, 17, + + 5, 17, 16, 11, 18, 11, 16, 21, 19, 20, + 26, 21, 25, 22, 18, 18, 26, 25, 27, 19, + 18, 18, 19, 20, 22, 36, 27, 36, 28, 5, + 5, 6, 6, 6, 6, 6, 562, 9, 9, 23, + 6, 559, 30, 6, 11, 11, 33, 23, 28, 30, + 23, 29, 32, 23, 31, 29, 23, 35, 31, 33, + 32, 35, 29, 29, 32, 29, 33, 37, 38, 37, + 38, 558, 6, 6, 39, 41, 39, 41, 44, 45, + 44, 38, 47, 45, 47, 556, 48, 39, 48, 49, + 44, 49, 50, 51, 50, 51, 55, 59, 55, 59, + + 62, 66, 68, 555, 68, 66, 69, 69, 70, 38, + 38, 62, 70, 71, 71, 39, 39, 78, 84, 94, + 98, 78, 84, 98, 96, 101, 94, 96, 554, 101, + 49, 49, 106, 551, 106, 96, 107, 108, 107, 108, + 96, 109, 111, 109, 111, 101, 115, 117, 115, 117, + 108, 122, 550, 180, 155, 180, 201, 201, 115, 117, + 155, 291, 548, 193, 122, 180, 193, 255, 255, 343, + 356, 255, 391, 394, 394, 403, 291, 356, 108, 108, + 356, 526, 403, 547, 546, 343, 543, 542, 391, 541, + 540, 539, 538, 526, 566, 566, 566, 566, 566, 566, + + 567, 567, 567, 568, 568, 537, 568, 568, 568, 570, + 536, 533, 532, 570, 570, 571, 531, 530, 529, 571, + 571, 572, 572, 528, 572, 572, 572, 573, 573, 527, + 573, 573, 573, 574, 574, 523, 574, 574, 574, 522, + 521, 519, 518, 517, 515, 511, 510, 508, 507, 504, + 503, 502, 501, 500, 499, 498, 497, 495, 494, 493, + 490, 489, 488, 485, 481, 480, 479, 478, 477, 476, + 473, 472, 471, 470, 469, 468, 467, 466, 465, 464, + 463, 462, 461, 460, 459, 458, 457, 456, 454, 453, + 452, 450, 449, 448, 447, 446, 445, 444, 443, 442, + + 441, 439, 437, 436, 435, 434, 433, 432, 429, 428, + 427, 426, 425, 424, 422, 420, 419, 418, 416, 414, + 409, 408, 407, 406, 405, 404, 402, 401, 400, 399, + 398, 397, 396, 393, 390, 389, 388, 387, 386, 385, + 384, 383, 382, 381, 380, 379, 377, 376, 375, 374, + 373, 372, 371, 370, 368, 367, 366, 365, 364, 362, + 361, 360, 359, 358, 357, 355, 354, 353, 352, 351, + 350, 349, 348, 347, 345, 344, 342, 340, 339, 338, + 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, + 326, 325, 323, 321, 320, 319, 318, 317, 316, 315, + + 314, 313, 312, 311, 310, 309, 308, 306, 305, 304, + 303, 302, 300, 299, 298, 297, 295, 294, 292, 290, + 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, + 277, 276, 275, 274, 273, 272, 271, 270, 268, 267, + 266, 265, 264, 263, 262, 261, 259, 258, 257, 256, + 254, 253, 251, 250, 248, 247, 246, 245, 244, 243, + 242, 241, 240, 239, 238, 237, 234, 233, 232, 231, + 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, + 220, 219, 217, 216, 215, 213, 212, 211, 210, 209, + 208, 207, 206, 205, 204, 202, 200, 199, 198, 197, + + 196, 195, 194, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 179, 178, 177, 176, 175, + 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, + 164, 163, 162, 161, 160, 159, 158, 156, 154, 153, + 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, + 142, 141, 140, 139, 137, 136, 135, 134, 133, 132, + 131, 130, 128, 127, 126, 125, 124, 123, 121, 120, + 114, 113, 105, 104, 103, 102, 100, 99, 97, 95, + 93, 92, 90, 89, 88, 87, 86, 85, 83, 82, + 81, 80, 79, 77, 76, 75, 74, 73, 72, 67, + + 65, 64, 63, 61, 60, 56, 54, 52, 43, 34, + 24, 15, 7, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, 565, @@ -800,10 +802,11 @@ char *yy_text; /* this header file is automatically generated by bison * and includes all token definitions, as well as yy_lval */ #if ELBEEM_BLENDER==1 +// for blender the headers have to be .h #include "cfgparser.h" -#else // ELBEEM_BLENDER==1 +#else #include "cfgparser.hpp" -#endif // ELBEEM_BLENDER==1 +#endif #include "utilities.h" #include <string.h> @@ -825,7 +828,7 @@ extern "C" int yy_wrap (void ) { return 1; } * rules start */ /*----------------------------------------------------------------------------*/ -#line 829 "<stdout>" +#line 832 "<stdout>" #define INITIAL 0 #define ATTR 1 @@ -978,11 +981,11 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 54 "src/cfglexer.ll" +#line 55 "src/cfglexer.ll" -#line 986 "<stdout>" +#line 989 "<stdout>" if ( (yy_init) ) { @@ -1063,25 +1066,25 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 57 "src/cfglexer.ll" +#line 58 "src/cfglexer.ll" { return KW_PAROPEN; } YY_BREAK case 2: YY_RULE_SETUP -#line 58 "src/cfglexer.ll" +#line 59 "src/cfglexer.ll" { BEGIN(INITIAL); // '}' always closes scopes return KW_PARCLOSE; } YY_BREAK case 3: YY_RULE_SETUP -#line 61 "src/cfglexer.ll" +#line 62 "src/cfglexer.ll" { BEGIN(ATTRVALUE); return KW_EQUALS; } YY_BREAK case 4: YY_RULE_SETUP -#line 64 "src/cfglexer.ll" +#line 65 "src/cfglexer.ll" { /* attribute name = normal string */ strncpy( charBuffer, yy_text, CHAR_BUFFER_SIZE-2 ); yy_lval.charValue = charBuffer; @@ -1091,7 +1094,7 @@ YY_RULE_SETUP YY_BREAK case 5: YY_RULE_SETUP -#line 70 "src/cfglexer.ll" +#line 71 "src/cfglexer.ll" { /* quoted string! attribute name = normal string */ strncpy( charBuffer, yy_text, CHAR_BUFFER_SIZE-2 ); /* get rid of " " */ @@ -1102,7 +1105,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 77 "src/cfglexer.ll" +#line 78 "src/cfglexer.ll" { /* ends at newline or ';' */ strncpy( charBuffer, yy_text, CHAR_BUFFER_SIZE-2 ); yy_lval.charValue = charBuffer; @@ -1110,433 +1113,433 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 81 "src/cfglexer.ll" +#line 82 "src/cfglexer.ll" { /* return end token... */ BEGIN(ATTR); return KW_ATTREND; } YY_BREAK case 8: YY_RULE_SETUP -#line 86 "src/cfglexer.ll" +#line 87 "src/cfglexer.ll" { return KW_LBMSIM; } YY_BREAK case 9: YY_RULE_SETUP -#line 87 "src/cfglexer.ll" +#line 88 "src/cfglexer.ll" { return KW_COMPARELBM; } YY_BREAK case 10: YY_RULE_SETUP -#line 88 "src/cfglexer.ll" +#line 89 "src/cfglexer.ll" { return KW_DEBUGMODE; } YY_BREAK case 11: YY_RULE_SETUP -#line 89 "src/cfglexer.ll" +#line 90 "src/cfglexer.ll" { return KW_DEBUGLEVEL; } YY_BREAK case 12: YY_RULE_SETUP -#line 90 "src/cfglexer.ll" +#line 91 "src/cfglexer.ll" { return KW_RAYTRACING; } YY_BREAK case 13: YY_RULE_SETUP -#line 93 "src/cfglexer.ll" +#line 94 "src/cfglexer.ll" { return KW_RESOLUTION; } YY_BREAK case 14: YY_RULE_SETUP -#line 94 "src/cfglexer.ll" +#line 95 "src/cfglexer.ll" { return KW_ANTIALIAS; } YY_BREAK case 15: YY_RULE_SETUP -#line 95 "src/cfglexer.ll" +#line 96 "src/cfglexer.ll" { return KW_EYEPOINT; } YY_BREAK case 16: YY_RULE_SETUP -#line 96 "src/cfglexer.ll" +#line 97 "src/cfglexer.ll" { return KW_LOOKAT ; } YY_BREAK case 17: YY_RULE_SETUP -#line 97 "src/cfglexer.ll" +#line 98 "src/cfglexer.ll" { return KW_UPVEC ; } YY_BREAK case 18: YY_RULE_SETUP -#line 98 "src/cfglexer.ll" +#line 99 "src/cfglexer.ll" { return KW_FOVY; } YY_BREAK case 19: YY_RULE_SETUP -#line 99 "src/cfglexer.ll" +#line 100 "src/cfglexer.ll" { return KW_ASPECT ; } YY_BREAK case 20: YY_RULE_SETUP -#line 100 "src/cfglexer.ll" +#line 101 "src/cfglexer.ll" { return KW_AMBIENCE; } YY_BREAK case 21: YY_RULE_SETUP -#line 101 "src/cfglexer.ll" +#line 102 "src/cfglexer.ll" { return KW_BACKGROUND; } YY_BREAK case 22: YY_RULE_SETUP -#line 102 "src/cfglexer.ll" +#line 103 "src/cfglexer.ll" { return KW_ANISTART; } YY_BREAK case 23: YY_RULE_SETUP -#line 103 "src/cfglexer.ll" +#line 104 "src/cfglexer.ll" { return KW_ANIFRAMES; } YY_BREAK case 24: YY_RULE_SETUP -#line 104 "src/cfglexer.ll" +#line 105 "src/cfglexer.ll" { return KW_ANIFRAMETIME; } YY_BREAK case 25: YY_RULE_SETUP -#line 105 "src/cfglexer.ll" +#line 106 "src/cfglexer.ll" { return KW_FRAMESKIP; } YY_BREAK case 26: YY_RULE_SETUP -#line 106 "src/cfglexer.ll" +#line 107 "src/cfglexer.ll" { return KW_FILENAME; } YY_BREAK case 27: YY_RULE_SETUP -#line 107 "src/cfglexer.ll" +#line 108 "src/cfglexer.ll" { return KW_PMCAUSTICS; } YY_BREAK case 28: YY_RULE_SETUP -#line 108 "src/cfglexer.ll" +#line 109 "src/cfglexer.ll" { return KW_CAUSTICDIST; } YY_BREAK case 29: YY_RULE_SETUP -#line 109 "src/cfglexer.ll" +#line 110 "src/cfglexer.ll" { return KW_CAUSTICPHOT; } YY_BREAK case 30: YY_RULE_SETUP -#line 110 "src/cfglexer.ll" +#line 111 "src/cfglexer.ll" { return KW_SHADOWMAPBIAS; } YY_BREAK case 31: YY_RULE_SETUP -#line 111 "src/cfglexer.ll" +#line 112 "src/cfglexer.ll" { return KW_MAXRAYDEPTH; } YY_BREAK case 32: YY_RULE_SETUP -#line 112 "src/cfglexer.ll" +#line 113 "src/cfglexer.ll" { return KW_TREEMAXDEPTH; } YY_BREAK case 33: YY_RULE_SETUP -#line 113 "src/cfglexer.ll" +#line 114 "src/cfglexer.ll" { return KW_TREEMAXTRIANGLES; } YY_BREAK case 34: YY_RULE_SETUP -#line 114 "src/cfglexer.ll" +#line 115 "src/cfglexer.ll" { return KW_DEBUGPIXEL; } YY_BREAK case 35: YY_RULE_SETUP -#line 115 "src/cfglexer.ll" +#line 116 "src/cfglexer.ll" { return KW_TESTMODE; } YY_BREAK case 36: YY_RULE_SETUP -#line 116 "src/cfglexer.ll" +#line 117 "src/cfglexer.ll" { return KW_OPENGLATTR; } YY_BREAK case 37: YY_RULE_SETUP -#line 117 "src/cfglexer.ll" +#line 118 "src/cfglexer.ll" { return KW_BLENDERATTR; } YY_BREAK case 38: YY_RULE_SETUP -#line 119 "src/cfglexer.ll" +#line 120 "src/cfglexer.ll" { return KW_OBJATTR; /* assign attr to obj */ } YY_BREAK case 39: YY_RULE_SETUP -#line 120 "src/cfglexer.ll" +#line 121 "src/cfglexer.ll" { BEGIN(ATTR); return KW_ATTRIBUTE; /* global attr list */ } YY_BREAK case 40: YY_RULE_SETUP -#line 121 "src/cfglexer.ll" +#line 122 "src/cfglexer.ll" { BEGIN(ATTR); return KW_DEFINEATTR; /* obj defines new attrs */ } YY_BREAK case 41: YY_RULE_SETUP -#line 122 "src/cfglexer.ll" +#line 123 "src/cfglexer.ll" { BEGIN(ATTR); return KW_DEFINEATTR; } YY_BREAK case 42: YY_RULE_SETUP -#line 123 "src/cfglexer.ll" +#line 124 "src/cfglexer.ll" { BEGIN(ATTR); return KW_DEFINEATTR; } YY_BREAK case 43: YY_RULE_SETUP -#line 125 "src/cfglexer.ll" +#line 126 "src/cfglexer.ll" { return KW_GEOMETRY; } YY_BREAK case 44: YY_RULE_SETUP -#line 126 "src/cfglexer.ll" +#line 127 "src/cfglexer.ll" { return KW_TYPE; } YY_BREAK case 45: YY_RULE_SETUP -#line 127 "src/cfglexer.ll" +#line 128 "src/cfglexer.ll" { return KW_GEOTYPE_BOX; } YY_BREAK case 46: YY_RULE_SETUP -#line 128 "src/cfglexer.ll" +#line 129 "src/cfglexer.ll" { return KW_GEOTYPE_SPHERE; } YY_BREAK case 47: YY_RULE_SETUP -#line 129 "src/cfglexer.ll" +#line 130 "src/cfglexer.ll" { return KW_GEOTYPE_OBJMODEL; } YY_BREAK case 48: YY_RULE_SETUP -#line 130 "src/cfglexer.ll" +#line 131 "src/cfglexer.ll" { return KW_CASTSHADOWS; } YY_BREAK case 49: YY_RULE_SETUP -#line 131 "src/cfglexer.ll" +#line 132 "src/cfglexer.ll" { return KW_RECEIVESHADOWS ; } YY_BREAK case 50: YY_RULE_SETUP -#line 132 "src/cfglexer.ll" +#line 133 "src/cfglexer.ll" { return KW_VISIBLE; } YY_BREAK case 51: YY_RULE_SETUP -#line 133 "src/cfglexer.ll" +#line 134 "src/cfglexer.ll" { return KW_BOX_START; } YY_BREAK case 52: YY_RULE_SETUP -#line 134 "src/cfglexer.ll" +#line 135 "src/cfglexer.ll" { return KW_BOX_END; } YY_BREAK case 53: YY_RULE_SETUP -#line 135 "src/cfglexer.ll" +#line 136 "src/cfglexer.ll" { return KW_POLY ; } YY_BREAK case 54: YY_RULE_SETUP -#line 136 "src/cfglexer.ll" +#line 137 "src/cfglexer.ll" { return KW_POLY ; } YY_BREAK case 55: YY_RULE_SETUP -#line 137 "src/cfglexer.ll" +#line 138 "src/cfglexer.ll" { return KW_NUMVERTICES; } YY_BREAK case 56: YY_RULE_SETUP -#line 138 "src/cfglexer.ll" +#line 139 "src/cfglexer.ll" { return KW_VERTEX; } YY_BREAK case 57: YY_RULE_SETUP -#line 139 "src/cfglexer.ll" +#line 140 "src/cfglexer.ll" { return KW_NUMPOLYGONS; } YY_BREAK case 58: YY_RULE_SETUP -#line 140 "src/cfglexer.ll" +#line 141 "src/cfglexer.ll" { return KW_ISOSURF; } YY_BREAK case 59: YY_RULE_SETUP -#line 141 "src/cfglexer.ll" +#line 142 "src/cfglexer.ll" { return KW_FILEMODE; } YY_BREAK case 60: YY_RULE_SETUP -#line 142 "src/cfglexer.ll" +#line 143 "src/cfglexer.ll" { return KW_INVERT; } YY_BREAK case 61: YY_RULE_SETUP -#line 144 "src/cfglexer.ll" +#line 145 "src/cfglexer.ll" { return KW_MATERIAL; } YY_BREAK case 62: YY_RULE_SETUP -#line 145 "src/cfglexer.ll" +#line 146 "src/cfglexer.ll" { return KW_MATTYPE_PHONG; } YY_BREAK case 63: YY_RULE_SETUP -#line 146 "src/cfglexer.ll" +#line 147 "src/cfglexer.ll" { return KW_MATTYPE_BLINN; } YY_BREAK case 64: YY_RULE_SETUP -#line 147 "src/cfglexer.ll" +#line 148 "src/cfglexer.ll" { return KW_NAME; } YY_BREAK case 65: YY_RULE_SETUP -#line 148 "src/cfglexer.ll" +#line 149 "src/cfglexer.ll" { return KW_AMBIENT; } YY_BREAK case 66: YY_RULE_SETUP -#line 149 "src/cfglexer.ll" +#line 150 "src/cfglexer.ll" { return KW_DIFFUSE; } YY_BREAK case 67: YY_RULE_SETUP -#line 150 "src/cfglexer.ll" +#line 151 "src/cfglexer.ll" { return KW_SPECULAR; } YY_BREAK case 68: YY_RULE_SETUP -#line 151 "src/cfglexer.ll" +#line 152 "src/cfglexer.ll" { return KW_MIRROR; } YY_BREAK case 69: YY_RULE_SETUP -#line 152 "src/cfglexer.ll" +#line 153 "src/cfglexer.ll" { return KW_TRANSPARENCE; } YY_BREAK case 70: YY_RULE_SETUP -#line 153 "src/cfglexer.ll" +#line 154 "src/cfglexer.ll" { return KW_REFRACINDEX; } YY_BREAK case 71: YY_RULE_SETUP -#line 154 "src/cfglexer.ll" +#line 155 "src/cfglexer.ll" { return KW_TRANSADDITIVE; } YY_BREAK case 72: YY_RULE_SETUP -#line 155 "src/cfglexer.ll" +#line 156 "src/cfglexer.ll" { return KW_TRANSATTCOL; } YY_BREAK case 73: YY_RULE_SETUP -#line 156 "src/cfglexer.ll" +#line 157 "src/cfglexer.ll" { return KW_FRESNEL; } YY_BREAK case 74: YY_RULE_SETUP -#line 157 "src/cfglexer.ll" +#line 158 "src/cfglexer.ll" { return KW_FRESNEL; } YY_BREAK case 75: YY_RULE_SETUP -#line 159 "src/cfglexer.ll" +#line 160 "src/cfglexer.ll" { return KW_LIGHT; } YY_BREAK case 76: YY_RULE_SETUP -#line 160 "src/cfglexer.ll" +#line 161 "src/cfglexer.ll" { return KW_LIGHT_OMNI; } YY_BREAK case 77: YY_RULE_SETUP -#line 161 "src/cfglexer.ll" +#line 162 "src/cfglexer.ll" { return KW_ACTIVE; } YY_BREAK case 78: YY_RULE_SETUP -#line 162 "src/cfglexer.ll" +#line 163 "src/cfglexer.ll" { return KW_COLOUR; } YY_BREAK case 79: YY_RULE_SETUP -#line 163 "src/cfglexer.ll" +#line 164 "src/cfglexer.ll" { return KW_COLOUR; } YY_BREAK case 80: YY_RULE_SETUP -#line 164 "src/cfglexer.ll" +#line 165 "src/cfglexer.ll" { return KW_POSITION; } YY_BREAK case 81: YY_RULE_SETUP -#line 165 "src/cfglexer.ll" +#line 166 "src/cfglexer.ll" { return KW_CAUSTICPHOTONS; } YY_BREAK case 82: YY_RULE_SETUP -#line 166 "src/cfglexer.ll" +#line 167 "src/cfglexer.ll" { return KW_CAUSTICSTRENGTH; } YY_BREAK case 83: YY_RULE_SETUP -#line 167 "src/cfglexer.ll" +#line 168 "src/cfglexer.ll" { return KW_SHADOWMAP; } YY_BREAK case 84: YY_RULE_SETUP -#line 168 "src/cfglexer.ll" +#line 169 "src/cfglexer.ll" { return KW_CAUSTICSMAP; } YY_BREAK case 85: YY_RULE_SETUP -#line 170 "src/cfglexer.ll" +#line 171 "src/cfglexer.ll" { yy_lval.intValue = 1; return DT_INTEGER; } YY_BREAK case 86: YY_RULE_SETUP -#line 171 "src/cfglexer.ll" +#line 172 "src/cfglexer.ll" { yy_lval.intValue = 0; return DT_INTEGER; } YY_BREAK case 87: YY_RULE_SETUP -#line 172 "src/cfglexer.ll" +#line 173 "src/cfglexer.ll" { yy_lval.intValue = 1; return DT_INTEGER; } YY_BREAK case 88: YY_RULE_SETUP -#line 173 "src/cfglexer.ll" +#line 174 "src/cfglexer.ll" { yy_lval.intValue = 0; return DT_INTEGER; } YY_BREAK case 89: YY_RULE_SETUP -#line 176 "src/cfglexer.ll" +#line 177 "src/cfglexer.ll" { // integer number yy_lval.intValue = atoi( yy_text ); return DT_INTEGER; } YY_BREAK case 90: YY_RULE_SETUP -#line 180 "src/cfglexer.ll" +#line 181 "src/cfglexer.ll" { // floating point number yy_lval.floatValue = atof( yy_text ); return DT_FLOAT; } YY_BREAK case 91: YY_RULE_SETUP -#line 184 "src/cfglexer.ll" +#line 185 "src/cfglexer.ll" { /* normal character strings, now also for paths/filenames */ strncpy( charBuffer, yy_text, CHAR_BUFFER_SIZE-2 ); /* get rid of " " */ @@ -1547,17 +1550,17 @@ YY_RULE_SETUP YY_BREAK case 92: YY_RULE_SETUP -#line 192 "src/cfglexer.ll" +#line 193 "src/cfglexer.ll" { /* one line comment */ } YY_BREAK case 93: YY_RULE_SETUP -#line 193 "src/cfglexer.ll" +#line 194 "src/cfglexer.ll" { /* one line comment */ } YY_BREAK case 94: YY_RULE_SETUP -#line 194 "src/cfglexer.ll" +#line 195 "src/cfglexer.ll" { /* multiline comment */ register int c; for ( ; ; ) { @@ -1583,26 +1586,26 @@ YY_RULE_SETUP case 95: /* rule 95 can match eol */ YY_RULE_SETUP -#line 218 "src/cfglexer.ll" +#line 219 "src/cfglexer.ll" { // count line numbers lineCount++; } YY_BREAK case 96: YY_RULE_SETUP -#line 221 "src/cfglexer.ll" +#line 222 "src/cfglexer.ll" { /* do nothing by default... */ } YY_BREAK case 97: YY_RULE_SETUP -#line 223 "src/cfglexer.ll" +#line 224 "src/cfglexer.ll" { /*errorOut( "cfgLexer, Line "<<lineCount<<" : Unknown character '"<<(char)yyinput()<<"' " ); xit(1); */ } YY_BREAK case 98: YY_RULE_SETUP -#line 226 "src/cfglexer.ll" +#line 227 "src/cfglexer.ll" ECHO; YY_BREAK -#line 1606 "<stdout>" +#line 1609 "<stdout>" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(ATTR): case YY_STATE_EOF(ATTRVALUE): @@ -2567,4 +2570,4 @@ void yy_free (void * ptr ) #undef YY_DECL_IS_OURS #undef YY_DECL #endif -#line 226 "src/cfglexer.ll" +#line 227 "src/cfglexer.ll" diff --git a/intern/elbeem/intern/cfgparser.cpp b/intern/elbeem/intern/cfgparser.cpp index 16a8772ff72..6ca309f77a5 100644 --- a/intern/elbeem/intern/cfgparser.cpp +++ b/intern/elbeem/intern/cfgparser.cpp @@ -299,19 +299,17 @@ int yy_parse( void ); // local variables to access objects +#include "solver_interface.h" #include "simulation_object.h" #ifdef LBM_INCLUDE_TESTSOLVERS #include "simulation_complbm.h" #endif // LBM_INCLUDE_TESTSOLVERS #include "parametrizer.h" -#include "ntl_renderglobals.h" -#include "ntl_scene.h" - -#include "ntl_lightobject.h" -#include "ntl_material.h" +#include "ntl_world.h" +#include "ntl_ray.h" +#include "ntl_lighting.h" #include "ntl_geometrymodel.h" -#include "globals.h" /* global variables */ static map<string,AttributeList*> attrs; /* global attribute storage */ @@ -333,11 +331,11 @@ AttributeList *currentAttrib; string currentAttrName, currentAttribAddName; -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN #include "ntl_geometrybox.h" #include "ntl_geometrysphere.h" ntlGeometryBox *currentGeometryBox; -#endif //ELBEEM_BLENDER +#endif //ELBEEM_PLUGIN /* material init checks */ ntlMaterial *currentMaterial; @@ -358,14 +356,14 @@ #endif #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 87 "src/cfgparser.yy" +#line 85 "src/cfgparser.yy" typedef union YYSTYPE { int intValue; float floatValue; char *charValue; } YYSTYPE; /* Line 190 of yacc.c. */ -#line 369 "bld-std-gcc/src/cfgparser.cpp" +#line 367 "bld-std-gcc/src/cfgparser.cpp" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -377,7 +375,7 @@ typedef union YYSTYPE { /* Line 213 of yacc.c. */ -#line 381 "bld-std-gcc/src/cfgparser.cpp" +#line 379 "bld-std-gcc/src/cfgparser.cpp" #if ! defined (yyoverflow) || YYERROR_VERBOSE @@ -609,21 +607,21 @@ static const short int yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { - 0, 146, 146, 147, 150, 151, 152, 153, 157, 160, - 175, 176, 176, 179, 180, 181, 182, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 202, 203, 204, 205, 210, 214, - 219, 223, 229, 233, 237, 241, 245, 249, 253, 257, - 261, 265, 269, 273, 277, 281, 285, 289, 294, 303, - 314, 315, 318, 326, 327, 328, 329, 333, 338, 343, - 348, 366, 365, 386, 387, 390, 399, 407, 412, 418, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 443, - 448, 454, 460, 466, 471, 486, 502, 508, 518, 529, - 530, 533, 538, 542, 543, 544, 545, 546, 547, 548, - 549, 550, 551, 556, 561, 566, 571, 577, 582, 587, - 592, 597, 602, 613, 613, 623, 623, 626, 626, 629, - 630, 629, 637, 638, 637, 645, 648, 658, 661, 673, - 675, 681, 692, 704 + 0, 144, 144, 145, 148, 149, 150, 151, 155, 158, + 173, 174, 174, 177, 178, 179, 180, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 200, 201, 202, 203, 208, 212, + 217, 221, 227, 231, 235, 239, 243, 247, 251, 255, + 259, 263, 267, 271, 275, 279, 283, 287, 292, 301, + 312, 313, 316, 324, 325, 326, 327, 331, 336, 341, + 346, 364, 363, 385, 386, 389, 398, 406, 411, 417, + 429, 430, 431, 432, 433, 434, 435, 436, 437, 442, + 447, 453, 459, 465, 470, 485, 501, 510, 520, 531, + 532, 535, 540, 544, 545, 546, 547, 548, 549, 550, + 551, 552, 553, 558, 563, 568, 573, 579, 584, 589, + 594, 599, 604, 615, 615, 625, 625, 628, 628, 631, + 632, 631, 639, 640, 639, 647, 650, 660, 663, 675, + 677, 683, 694, 706 }; #endif @@ -1583,12 +1581,12 @@ yyreduce: switch (yyn) { case 8: -#line 157 "src/cfgparser.yy" +#line 155 "src/cfgparser.yy" { yy_debug = (yyvsp[0].intValue); } break; case 9: -#line 160 "src/cfgparser.yy" +#line 158 "src/cfgparser.yy" { int sdebug = (yyvsp[0].intValue); if(sdebug<0) sdebug=0; @@ -1598,114 +1596,114 @@ yyreduce: break; case 38: -#line 211 "src/cfgparser.yy" +#line 209 "src/cfgparser.yy" { reglob->setAniStart( (yyvsp[0].intValue) ); } break; case 39: -#line 215 "src/cfgparser.yy" +#line 213 "src/cfgparser.yy" { /*reglob->setAniFrameTime( $2 );*/ debMsgStd("cfgparser",DM_NOTIFY,"Deprecated setting aniframetime!",1); } break; case 40: -#line 220 "src/cfgparser.yy" +#line 218 "src/cfgparser.yy" { reglob->setAniFrames( ((yyvsp[0].intValue))-1 ); } break; case 41: -#line 224 "src/cfgparser.yy" +#line 222 "src/cfgparser.yy" { reglob->setFrameSkip( ((yyvsp[0].intValue)) ); } break; case 42: -#line 230 "src/cfgparser.yy" +#line 228 "src/cfgparser.yy" { reglob->setResX( (yyvsp[-1].intValue) ); reglob->setResY( (yyvsp[0].intValue)); } break; case 43: -#line 234 "src/cfgparser.yy" +#line 232 "src/cfgparser.yy" { reglob->setAADepth( (yyvsp[0].intValue) ); } break; case 44: -#line 238 "src/cfgparser.yy" +#line 236 "src/cfgparser.yy" { reglob->setEye( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 45: -#line 242 "src/cfgparser.yy" +#line 240 "src/cfgparser.yy" { reglob->setLookat( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 46: -#line 246 "src/cfgparser.yy" +#line 244 "src/cfgparser.yy" { reglob->setUpVec( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 47: -#line 250 "src/cfgparser.yy" +#line 248 "src/cfgparser.yy" { reglob->setFovy( (yyvsp[0].floatValue) ); } break; case 48: -#line 254 "src/cfgparser.yy" +#line 252 "src/cfgparser.yy" { reglob->setAspect( (yyvsp[0].floatValue) ); } break; case 49: -#line 258 "src/cfgparser.yy" +#line 256 "src/cfgparser.yy" { reglob->setAmbientLight( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 50: -#line 262 "src/cfgparser.yy" +#line 260 "src/cfgparser.yy" { reglob->setBackgroundCol( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 51: -#line 266 "src/cfgparser.yy" +#line 264 "src/cfgparser.yy" { reglob->setOutFilename( (yyvsp[0].charValue) ); } break; case 52: -#line 270 "src/cfgparser.yy" +#line 268 "src/cfgparser.yy" { reglob->setTreeMaxDepth( (yyvsp[0].intValue) ); } break; case 53: -#line 274 "src/cfgparser.yy" +#line 272 "src/cfgparser.yy" { reglob->setTreeMaxTriangles( (yyvsp[0].intValue) ); } break; case 54: -#line 278 "src/cfgparser.yy" +#line 276 "src/cfgparser.yy" { reglob->setRayMaxDepth( (yyvsp[0].intValue) ); } break; case 55: -#line 282 "src/cfgparser.yy" +#line 280 "src/cfgparser.yy" { reglob->setDebugPixel( (yyvsp[-1].intValue), (yyvsp[0].intValue) ); } break; case 56: -#line 286 "src/cfgparser.yy" +#line 284 "src/cfgparser.yy" { reglob->setTestMode( (yyvsp[0].intValue) ); } break; case 57: -#line 290 "src/cfgparser.yy" +#line 288 "src/cfgparser.yy" { if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("OPENGL ATTRIBUTES: The attribute was not found!"); } reglob->getOpenGlAttributes()->import( attrs[(yyvsp[0].charValue)] ); } break; case 58: -#line 295 "src/cfgparser.yy" +#line 293 "src/cfgparser.yy" { if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("BLENDER ATTRIBUTES: The attribute was not found!"); } reglob->getBlenderAttributes()->import( attrs[(yyvsp[0].charValue)] ); } break; case 59: -#line 307 "src/cfgparser.yy" +#line 305 "src/cfgparser.yy" { /* reset light pointers */ currentLightOmni = NULL; @@ -1713,7 +1711,7 @@ yyreduce: break; case 62: -#line 319 "src/cfgparser.yy" +#line 317 "src/cfgparser.yy" { currentLightOmni = new ntlLightObject( reglob ); currentLight = currentLightOmni; reglob->getLightList()->push_back(currentLight); @@ -1721,28 +1719,28 @@ yyreduce: break; case 67: -#line 333 "src/cfgparser.yy" +#line 331 "src/cfgparser.yy" { currentLight->setActive( (yyvsp[0].intValue) ); } break; case 68: -#line 338 "src/cfgparser.yy" +#line 336 "src/cfgparser.yy" { currentLight->setCastShadows( (yyvsp[0].intValue) ); } break; case 69: -#line 343 "src/cfgparser.yy" +#line 341 "src/cfgparser.yy" { currentLight->setColor( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 70: -#line 348 "src/cfgparser.yy" +#line 346 "src/cfgparser.yy" { int init = 0; if(currentLightOmni != NULL) { @@ -1752,16 +1750,17 @@ yyreduce: break; case 71: -#line 366 "src/cfgparser.yy" +#line 364 "src/cfgparser.yy" { // geo classes have attributes... - reglob->getScene()->addGeoClass(currentGeoClass); + reglob->getRenderScene()->addGeoClass(currentGeoClass); + reglob->getSimScene()->addGeoClass(currentGeoClass); currentAttrib = currentGeoClass->getAttributeList(); } break; case 72: -#line 372 "src/cfgparser.yy" +#line 371 "src/cfgparser.yy" { /* reset geometry object pointers */ currentGeoObj = NULL; @@ -1769,39 +1768,39 @@ yyreduce: currentGeometrySim = NULL; currentGeometryModel = NULL; currentAttrib = NULL; -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN currentGeometryBox = NULL; -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN } break; case 75: -#line 390 "src/cfgparser.yy" +#line 389 "src/cfgparser.yy" { -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN currentGeometryBox = new ntlGeometryBox( ); currentGeoClass = currentGeometryBox; currentGeoObj = (ntlGeometryObject*)( currentGeometryBox ); -#else // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN yyerror("GEOTYPE_BOX : This object type is not supported in this version!"); -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN } break; case 76: -#line 399 "src/cfgparser.yy" +#line 398 "src/cfgparser.yy" { -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN currentGeoClass = new ntlGeometrySphere( ); currentGeoObj = (ntlGeometryObject*)( currentGeoClass ); -#else // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN yyerror("GEOTYPE_SPHERE : This object type is not supported in this version!"); -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN } break; case 77: -#line 407 "src/cfgparser.yy" +#line 406 "src/cfgparser.yy" { currentGeometryModel = new ntlGeometryObjModel( ); currentGeoClass = currentGeometryModel; @@ -1810,7 +1809,7 @@ yyreduce: break; case 78: -#line 412 "src/cfgparser.yy" +#line 411 "src/cfgparser.yy" { currentGeometrySim = new SimulationObject(); currentGeoClass = currentGeometrySim; @@ -1820,7 +1819,7 @@ yyreduce: break; case 79: -#line 418 "src/cfgparser.yy" +#line 417 "src/cfgparser.yy" { #ifdef LBM_INCLUDE_TESTSOLVERS currentGeometrySim = new SimulationCompareLbm(); @@ -1833,14 +1832,14 @@ yyreduce: break; case 89: -#line 443 "src/cfgparser.yy" +#line 442 "src/cfgparser.yy" { currentGeoClass->setName( (yyvsp[0].charValue) ); } break; case 90: -#line 448 "src/cfgparser.yy" +#line 447 "src/cfgparser.yy" { if(currentGeoObj == NULL){ yyerror(" MATERIAL : This property can only be set for geometry objects!"); } currentGeoObj->setMaterialName( (yyvsp[0].charValue) ); @@ -1848,7 +1847,7 @@ yyreduce: break; case 91: -#line 454 "src/cfgparser.yy" +#line 453 "src/cfgparser.yy" { if(currentGeoObj == NULL){ yyerror(" CAST_SHADOW : This property can only be set for geometry objects!"); } currentGeoObj->setCastShadows( (yyvsp[0].intValue) ); @@ -1856,7 +1855,7 @@ yyreduce: break; case 92: -#line 460 "src/cfgparser.yy" +#line 459 "src/cfgparser.yy" { if(currentGeoObj == NULL){ yyerror(" RECEIVE_SHADOW : This property can only be set for geometry objects!"); } currentGeoObj->setReceiveShadows( (yyvsp[0].intValue) ); @@ -1864,21 +1863,21 @@ yyreduce: break; case 93: -#line 466 "src/cfgparser.yy" +#line 465 "src/cfgparser.yy" { currentGeoClass->setVisible( (yyvsp[0].intValue) ); } break; case 94: -#line 471 "src/cfgparser.yy" +#line 470 "src/cfgparser.yy" { int init = 0; -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN if(currentGeometryBox != NULL){ currentGeometryBox->setStart( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; } -#else // ELBEEM_BLENDER -#endif // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN +#endif // ELBEEM_PLUGIN if(currentGeometrySim != NULL){ currentGeometrySim->setGeoStart( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; } if(currentGeometryModel != NULL){ @@ -1888,14 +1887,14 @@ yyreduce: break; case 95: -#line 486 "src/cfgparser.yy" +#line 485 "src/cfgparser.yy" { int init = 0; -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN if(currentGeometryBox != NULL){ currentGeometryBox->setEnd( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; } -#else // ELBEEM_BLENDER -#endif // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN +#endif // ELBEEM_PLUGIN if(currentGeometrySim != NULL){ currentGeometrySim->setGeoEnd( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; } if(currentGeometryModel != NULL){ @@ -1905,20 +1904,23 @@ yyreduce: break; case 96: -#line 502 "src/cfgparser.yy" +#line 501 "src/cfgparser.yy" { if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("GEO ATTRIBUTES: The attribute was not found!"); } - currentGeoClass->getAttributeList()->import( attrs[(yyvsp[0].charValue)] ); + else { + if(currentGeoClass->getAttributeList()) + currentGeoClass->getAttributeList()->import( attrs[(yyvsp[0].charValue)] ); + } } break; case 97: -#line 510 "src/cfgparser.yy" +#line 512 "src/cfgparser.yy" { } break; case 98: -#line 522 "src/cfgparser.yy" +#line 524 "src/cfgparser.yy" { /* reset geometry object pointers */ currentMaterial = NULL; @@ -1926,7 +1928,7 @@ yyreduce: break; case 101: -#line 534 "src/cfgparser.yy" +#line 536 "src/cfgparser.yy" { currentMaterial = new ntlMaterial( ); currentMaterial = currentMaterial; reglob->getMaterials()->push_back(currentMaterial); @@ -1934,34 +1936,34 @@ yyreduce: break; case 102: -#line 538 "src/cfgparser.yy" +#line 540 "src/cfgparser.yy" { yyerror("MATTYPE: Blinn NYI!"); } break; case 113: -#line 556 "src/cfgparser.yy" +#line 558 "src/cfgparser.yy" { currentMaterial->setName( (yyvsp[0].charValue) ); } break; case 114: -#line 561 "src/cfgparser.yy" +#line 563 "src/cfgparser.yy" { currentMaterial->setAmbientRefl( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 115: -#line 566 "src/cfgparser.yy" +#line 568 "src/cfgparser.yy" { currentMaterial->setDiffuseRefl( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 116: -#line 571 "src/cfgparser.yy" +#line 573 "src/cfgparser.yy" { currentMaterial->setSpecular( (yyvsp[-1].floatValue) ); currentMaterial->setSpecExponent( (yyvsp[0].floatValue) ); @@ -1969,56 +1971,56 @@ yyreduce: break; case 117: -#line 577 "src/cfgparser.yy" +#line 579 "src/cfgparser.yy" { currentMaterial->setMirror( (yyvsp[0].floatValue) ); } break; case 118: -#line 582 "src/cfgparser.yy" +#line 584 "src/cfgparser.yy" { currentMaterial->setTransparence( (yyvsp[0].floatValue) ); } break; case 119: -#line 587 "src/cfgparser.yy" +#line 589 "src/cfgparser.yy" { currentMaterial->setRefracIndex( (yyvsp[0].floatValue) ); } break; case 120: -#line 592 "src/cfgparser.yy" +#line 594 "src/cfgparser.yy" { currentMaterial->setTransAdditive( (yyvsp[0].floatValue) ); } break; case 121: -#line 597 "src/cfgparser.yy" +#line 599 "src/cfgparser.yy" { currentMaterial->setTransAttCol( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); } break; case 122: -#line 602 "src/cfgparser.yy" +#line 604 "src/cfgparser.yy" { currentMaterial->setFresnel( (yyvsp[0].intValue) ); } break; case 123: -#line 613 "src/cfgparser.yy" +#line 615 "src/cfgparser.yy" { currentAttrib = new AttributeList((yyvsp[-1].charValue)); currentAttrName = (yyvsp[-1].charValue); } break; case 124: -#line 616 "src/cfgparser.yy" +#line 618 "src/cfgparser.yy" { // store attribute //std::cerr << " NEW ATTR " << currentAttrName << std::endl; //currentAttrib->print(); @@ -2027,12 +2029,12 @@ yyreduce: break; case 129: -#line 629 "src/cfgparser.yy" +#line 631 "src/cfgparser.yy" { currentAttrValue.clear(); currentAttribAddName = (yyvsp[-1].charValue); } break; case 130: -#line 630 "src/cfgparser.yy" +#line 632 "src/cfgparser.yy" { currentAttrib->addAttr( currentAttribAddName, currentAttrValue, lineCount, true); //std::cerr << " ADD ATTRCHANNEL " << currentAttribAddName << std::endl; @@ -2041,12 +2043,12 @@ yyreduce: break; case 132: -#line 637 "src/cfgparser.yy" +#line 639 "src/cfgparser.yy" { currentAttrValue.clear(); currentAttribAddName = (yyvsp[-1].charValue); } break; case 133: -#line 638 "src/cfgparser.yy" +#line 640 "src/cfgparser.yy" { currentAttrib->addAttr( currentAttribAddName, currentAttrValue, lineCount, false); //std::cerr << " ADD ATTRNORM " << currentAttribAddName << std::endl; @@ -2055,21 +2057,21 @@ yyreduce: break; case 135: -#line 645 "src/cfgparser.yy" +#line 647 "src/cfgparser.yy" { //std::cerr << "LLL "<<$2<<std::endl; // ignore newline entries if(strcmp((yyvsp[0].charValue),"\n")) currentAttrValue.push_back((yyvsp[0].charValue)); } break; case 136: -#line 648 "src/cfgparser.yy" +#line 650 "src/cfgparser.yy" { //std::cerr << "LRR "<<$1<<std::endl; if(strcmp((yyvsp[0].charValue),"\n")) currentAttrValue.push_back((yyvsp[0].charValue)); } break; case 138: -#line 662 "src/cfgparser.yy" +#line 664 "src/cfgparser.yy" { if ( ((yyvsp[0].floatValue) < 0.0) || ((yyvsp[0].floatValue) > 1.0) ) { yyerror("Value out of range (only 0 to 1 allowed)"); @@ -2081,17 +2083,17 @@ yyreduce: break; case 139: -#line 674 "src/cfgparser.yy" +#line 676 "src/cfgparser.yy" { (yyval.floatValue) = (yyvsp[0].floatValue); } break; case 140: -#line 676 "src/cfgparser.yy" +#line 678 "src/cfgparser.yy" { (yyval.floatValue) = (float) (yyvsp[0].intValue); /* conversion from integers */ } break; case 141: -#line 682 "src/cfgparser.yy" +#line 684 "src/cfgparser.yy" { if ( (yyvsp[0].intValue) <= 0 ) { yy_error("Value out of range (has to be above zero)"); @@ -2103,7 +2105,7 @@ yyreduce: break; case 142: -#line 693 "src/cfgparser.yy" +#line 695 "src/cfgparser.yy" { //cout << " " << $1 << " "; if ( (yyvsp[0].intValue) < 0 ) { @@ -2116,7 +2118,7 @@ yyreduce: break; case 143: -#line 705 "src/cfgparser.yy" +#line 707 "src/cfgparser.yy" { if( ( (yyvsp[0].intValue) != 0 ) && ( (yyvsp[0].intValue) != 1 ) ) { yy_error("Boolean value has to be 1|0, 'true'|'false' or 'on'|'off'!"); @@ -2130,7 +2132,7 @@ yyreduce: } /* Line 1037 of yacc.c. */ -#line 2134 "bld-std-gcc/src/cfgparser.cpp" +#line 2136 "bld-std-gcc/src/cfgparser.cpp" yyvsp -= yylen; yyssp -= yylen; @@ -2358,7 +2360,7 @@ yyreturn: } -#line 713 "src/cfgparser.yy" +#line 715 "src/cfgparser.yy" /*---------------------------------------------------------------------------*/ diff --git a/intern/elbeem/intern/cfgparser.h b/intern/elbeem/intern/cfgparser.h index 20b46f4e346..2b7791a78cb 100644 --- a/intern/elbeem/intern/cfgparser.h +++ b/intern/elbeem/intern/cfgparser.h @@ -244,7 +244,7 @@ #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 87 "src/cfgparser.yy" +#line 85 "src/cfgparser.yy" typedef union YYSTYPE { int intValue; float floatValue; diff --git a/intern/elbeem/intern/elbeem.cpp b/intern/elbeem/intern/elbeem.cpp index a1072d84297..8e96879737f 100644 --- a/intern/elbeem/intern/elbeem.cpp +++ b/intern/elbeem/intern/elbeem.cpp @@ -12,7 +12,7 @@ #include "ntl_blenderdumper.h" extern "C" void elbeemCheckDebugEnv(void); -#include "ntl_scene.h" +#include "ntl_world.h" #include "ntl_geometrymodel.h" /*****************************************************************************/ @@ -29,15 +29,51 @@ int guiRoiMaxLev=6, guiRoiMinLev=0; //! global raytracer pointer (=world) ntlWorld *gpWorld = NULL; -//! debug output switch -bool myDebugOut = false; -//! global leave program / abort variable -bool gQuit = false; +// API +// reset elbeemSimulationSettings struct with defaults +extern "C" +void elbeemResetSettings(elbeemSimulationSettings *set) { + if(!set) return; + set->version = 2; + for(int i=0 ; i<3; i++) set->geoStart[i] = 0.0; + for(int i=0 ; i<3; i++) set->geoSize[i] = 1.0; + set->resolutionxyz = 64; + set->previewresxyz = 24; + set->realsize = 1.0; + set->viscosity = 0.000001; -// API + for(int i=0 ; i<2; i++) set->gravity[i] = 0.0; + set->gravity[2] = -9.81; + + set->animStart = 0; + set->aniFrameTime = 0.01; + set->noOfFrames = 10; + set->gstar = 0.005; + set->maxRefine = -1; + set->generateParticles = 1.0; + strcpy(set->outputPath,"./elbeemdata_"); + + set->channelSizeFrameTime=0; + set->channelFrameTime=NULL; + set->channelSizeViscosity=0; + set->channelViscosity=NULL; + set->channelSizeGravity=0; + set->channelGravity=NULL; + set->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP; + set->obstaclePartslip= 0.; + set->generateVertexVectors = 0; + set->surfaceSmoothing = 1.; + + // init identity + for(int i=0; i<16; i++) set->surfaceTrafo[i] = 0.0; + for(int i=0; i<4; i++) set->surfaceTrafo[i*4+i] = 1.0; +} + +// start fluidsim init +extern "C" int elbeemInit(elbeemSimulationSettings *settings) { gElbeemState = SIMWORLD_INVALID; strcpy(gElbeemErrorString,"[none]"); @@ -51,10 +87,41 @@ int elbeemInit(elbeemSimulationSettings *settings) { return 0; } +// reset elbeemMesh struct with zeroes +extern "C" +void elbeemResetMesh(elbeemMesh *mesh) { + if(!mesh) return; + mesh->type = 0; + mesh->numVertices = 0; + mesh->vertices = NULL; + mesh->numTriangles = 0; + mesh->triangles = NULL; + mesh->channelSizeTranslation = 0; + mesh->channelTranslation = NULL; + mesh->channelSizeRotation = 0; + mesh->channelRotation = NULL; + mesh->channelSizeScale = 0; + mesh->channelScale = NULL; + mesh->channelSizeActive = 0; + mesh->channelActive = NULL; + mesh->channelSizeInitialVel = 0; + mesh->channelInitialVel = NULL; + mesh->localInivelCoords = 0; + mesh->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP; + mesh->obstaclePartslip= 0.; + mesh->name = "[unnamed]"; +} + +// add mesh as fluidsim object +extern "C" int elbeemAddMesh(elbeemMesh *mesh) { int initType = -1; switch(mesh->type) { - case OB_FLUIDSIM_OBSTACLE: initType = FGI_BNDNO; break; + case OB_FLUIDSIM_OBSTACLE: + if (mesh->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) initType = FGI_BNDPART; + else if(mesh->obstacleType==FLUIDSIM_OBSTACLE_FREESLIP) initType = FGI_BNDFREE; + else /*if(mesh->obstacleType==FLUIDSIM_OBSTACLE_NOSLIP)*/ initType = FGI_BNDNO; + break; case OB_FLUIDSIM_FLUID: initType = FGI_FLUID; break; case OB_FLUIDSIM_INFLOW: initType = FGI_MBNDINFLOW; break; case OB_FLUIDSIM_OUTFLOW: initType = FGI_MBNDOUTFLOW; break; @@ -63,15 +130,30 @@ int elbeemAddMesh(elbeemMesh *mesh) { if(initType<0) return 1; ntlGeometryObjModel *obj = new ntlGeometryObjModel( ); - gpWorld->getRenderGlobals()->getScene()->addGeoClass( obj ); + gpWorld->getRenderGlobals()->getSimScene()->addGeoClass( obj ); obj->initModel(mesh->numVertices, mesh->vertices, mesh->numTriangles, mesh->triangles); - obj->setGeoInitId(true); + if(mesh->name) obj->setName(std::string(mesh->name)); + else obj->setName(std::string("[unnamed]")); + obj->setGeoInitId(1); obj->setGeoInitIntersect(true); obj->setGeoInitType(initType); - obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelx, mesh->iniVely, mesh->iniVelz) ); + obj->setGeoPartSlipValue(mesh->obstaclePartslip); + // use channel instead, obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelocity[0], mesh->iniVelocity[1], mesh->iniVelocity[2]) ); + obj->initChannels( + mesh->channelSizeTranslation, mesh->channelTranslation, + mesh->channelSizeRotation, mesh->channelRotation, + mesh->channelSizeScale, mesh->channelScale, + mesh->channelSizeActive, mesh->channelActive, + mesh->channelSizeInitialVel, mesh->channelInitialVel + ); + obj->setLocalCoordInivel( mesh->localInivelCoords ); + + debMsgStd("elbeemAddMesh",DM_MSG,"Added elbeem mesh: "<<obj->getName()<<" type="<<initType<<" "<<obj->getIsAnimated(), 9 ); return 0; } +// do the actual simulation +extern "C" int elbeemSimulate(void) { if(!gpWorld) return 1; @@ -82,7 +164,7 @@ int elbeemSimulate(void) { myTime_t timestart = getTime(); gpWorld->renderAnimation(); myTime_t timeend = getTime(); - debMsgStd("performElbeemSimulation",DM_NOTIFY, "El'Beem simulation done, time: "<<((timeend-timestart)/(double)1000.0) <<" seconds.\n", 2 ); + debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 ); // ok, we're done... delete gpWorld; @@ -95,4 +177,121 @@ int elbeemSimulate(void) { } +// global vector to flag values to remove +vector<int> gKeepVal; + +#define SIMPLIFY_FLOAT_EPSILON (1e-6f) +#define SIMPLIFY_DOUBLE_EPSILON (1e-12f) +#define SFLOATEQ(x,y) (ABS((x)-(y)) < SIMPLIFY_FLOAT_EPSILON) +#define SDOUBLEEQ(x,y) (ABS((x)-(y)) < SIMPLIFY_DOUBLE_EPSILON) +#define SVECFLOATEQ(x,y) ( \ + (ABS((x)[0]-(y)[0]) < SIMPLIFY_FLOAT_EPSILON) && \ + (ABS((x)[1]-(y)[1]) < SIMPLIFY_FLOAT_EPSILON) && \ + (ABS((x)[2]-(y)[2]) < SIMPLIFY_FLOAT_EPSILON) ) + +// helper function - simplify animation channels +extern "C" +int elbeemSimplifyChannelFloat(float *channel, int* size) { + bool changed = false; + int nsize = *size; + int orgsize = *size; + if(orgsize<1) return false; + gKeepVal.resize( orgsize ); + for(int i=0; i<orgsize; i++) { gKeepVal[i] = true; } + const bool debugSF = false; + + float last = channel[0 + 0]; + for(int i=1; i<orgsize; i++) { + float curr = channel[2*i + 0]; + bool remove = false; + if(SFLOATEQ(curr,last)) remove = true; + // dont remove if next value is different + if((remove)&&(i<orgsize-1)) { + float next = channel[2*(i+1)+0]; + if(!SFLOATEQ(next,curr)) remove = false; + } + if(remove) { + changed = true; + gKeepVal[i] = false; + nsize--; + } + if(debugSF) errMsg("elbeemSimplifyChannelFloat","i"<<i<<"/"<<orgsize<<" v"<<channel[ (i*2) + 0 ]<<" t"<<channel[ (i*2) + 1 ]<<" nsize="<<nsize<<" r"<<remove ); + last = curr; + } + + if(changed) { + nsize = 1; + for(int i=1; i<orgsize; i++) { + if(gKeepVal[i]) { + channel[ (nsize*2) + 0 ] = channel[ (i*2) + 0 ]; + channel[ (nsize*2) + 1 ] = channel[ (i*2) + 1 ]; + nsize++; + } + } + *size = nsize; + } + + if(debugSF) for(int i=1; i<nsize; i++) { + errMsg("elbeemSimplifyChannelFloat","n i"<<i<<"/"<<nsize<<" v"<<channel[ (i*2) + 0 ]<<" t"<<channel[ (i*2) + 1 ] ); + } + + return changed; +} + +extern "C" +int elbeemSimplifyChannelVec3(float *channel, int* size) { + bool changed = false; + int nsize = *size; + int orgsize = *size; + if(orgsize<1) return false; + gKeepVal.resize( orgsize ); + for(int i=0; i<orgsize; i++) { gKeepVal[i] = true; } + const bool debugVF = false; + + ntlVec3f last( channel[0 + 0], channel[0 + 1], channel[0 + 2] ); + for(int i=1; i<orgsize; i++) { + ntlVec3f curr( channel[4*i + 0], channel[4*i + 1], channel[4*i + 2]); + bool remove = false; + if(SVECFLOATEQ(curr,last)) remove = true; + // dont remove if next value is different + if((remove)&&(i<orgsize-1)) { + ntlVec3f next( channel[4*(i+1)+0], channel[4*(i+1)+1], channel[4*(i+1)+2]); + if(!SVECFLOATEQ(next,curr)) remove = false; + } + if(remove) { + changed = true; + gKeepVal[i] = false; + nsize--; + } + if(debugVF) errMsg("elbeemSimplifyChannelVec3","i"<<i<<"/"<<orgsize<<" v"<< + channel[ (i*4) + 0 ]<<","<< channel[ (i*4) + 1 ]<<","<< channel[ (i*4) + 2 ]<< + " t"<<channel[ (i*4) + 3 ]<<" nsize="<<nsize<<" r"<<remove ); + last = curr; + } + + if(changed) { + nsize = 1; + for(int i=1; i<orgsize; i++) { + if(gKeepVal[i]) { + for(int j=0; j<4; j++){ channel[ (nsize*4) + j ] = channel[ (i*4) + j ]; } + nsize++; + } + } + *size = nsize; + } + + if(debugVF) for(int i=1; i<nsize; i++) { + errMsg("elbeemSimplifyChannelVec3","n i"<<i<<"/"<<nsize<<" v"<< + channel[ (i*4) + 0 ]<<","<< channel[ (i*4) + 1 ]<<","<< channel[ (i*4) + 2 ]<< + " t"<<channel[ (i*4) + 3 ] ); + } + + return changed; +} + + +#undef SIMPLIFY_FLOAT_EPSILON +#undef SIMPLIFY_DOUBLE_EPSILON +#undef SFLOATEQ +#undef SDOUBLEEQ diff --git a/intern/elbeem/intern/elbeem.h b/intern/elbeem/intern/elbeem.h index efbda58a096..83a9cb99afc 100644 --- a/intern/elbeem/intern/elbeem.h +++ b/intern/elbeem/intern/elbeem.h @@ -11,21 +11,6 @@ #define ELBEEM_API_H - -/*! fluid geometry init types */ -#define FGI_FLAGSTART 16 -#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0)) -#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1)) -#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2)) -#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3)) -#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4)) -#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5)) -#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6)) -#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7)) - -#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW ) - - /*! blender types for mesh->type */ //#define OB_FLUIDSIM_DOMAIN 2 #define OB_FLUIDSIM_FLUID 4 @@ -33,6 +18,10 @@ #define OB_FLUIDSIM_INFLOW 16 #define OB_FLUIDSIM_OUTFLOW 32 +#define FLUIDSIM_OBSTACLE_NOSLIP 1 +#define FLUIDSIM_OBSTACLE_PARTSLIP 2 +#define FLUIDSIM_OBSTACLE_FREESLIP 3 + // global settings for the simulation typedef struct elbeemSimulationSettings { @@ -51,16 +40,39 @@ typedef struct elbeemSimulationSettings { /* fluid properties */ double viscosity; /* gravity strength */ - float gravx,gravy,gravz; + float gravity[3]; /* anim start end time */ float animStart, aniFrameTime; + /* no. of frames to simulate & output */ + short noOfFrames; /* g star param (LBM compressibility) */ float gstar; /* activate refinement? */ short maxRefine; + /* amount of particles to generate (0=off) */ + float generateParticles; /* store output path, and file prefix for baked fluid surface */ - char surfdataPath[160+80]; + char outputPath[160+80]; + + /* channel for frame time, visc & gravity animations */ + int channelSizeFrameTime; + float *channelFrameTime; + int channelSizeViscosity; + float *channelViscosity; + int channelSizeGravity; + float *channelGravity; // vector + + /* boundary types and settings for domain walls */ + short obstacleType; + float obstaclePartslip; + /* generate speed vectors for vertices (e.g. for image based motion blur)*/ + short generateVertexVectors; + /* strength of surface smoothing */ + float surfaceSmoothing; + + /* global transformation to apply to fluidsim mesh */ + float surfaceTrafo[4*4]; } elbeemSimulationSettings; @@ -69,9 +81,6 @@ typedef struct elbeemMesh { /* obstacle,fluid or inflow... */ short type; - /* initial velocity (for fluid/inflow) */ - float iniVelx,iniVely,iniVelz; - /* vertices */ int numVertices; float *vertices; // = float[][3]; @@ -79,13 +88,46 @@ typedef struct elbeemMesh { /* triangles */ int numTriangles; int *triangles; // = int[][3]; + + /* animation channels */ + int channelSizeTranslation; + float *channelTranslation; + int channelSizeRotation; + float *channelRotation; + int channelSizeScale; + float *channelScale; + + /* active channel */ + int channelSizeActive; + float *channelActive; + /* initial velocity channel (e.g. for inflow) */ + int channelSizeInitialVel; + float *channelInitialVel; // vector + /* use initial velocity in object coordinates? (e.g. for rotation) */ + short localInivelCoords; + /* boundary types and settings */ + short obstacleType; + float obstaclePartslip; + + /* name of the mesh, mostly for debugging */ + char *name; } elbeemMesh; // API functions +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// reset elbeemSimulationSettings struct with defaults +void elbeemResetSettings(struct elbeemSimulationSettings*); + // start fluidsim init int elbeemInit(struct elbeemSimulationSettings*); +// reset elbeemMesh struct with zeroes +void elbeemResetMesh(struct elbeemMesh*); + // add mesh as fluidsim object int elbeemAddMesh(struct elbeemMesh*); @@ -93,5 +135,30 @@ int elbeemAddMesh(struct elbeemMesh*); int elbeemSimulate(void); +// helper function - simplify animation channels +// returns if the channel and its size changed +int elbeemSimplifyChannelFloat(float *channel, int *size); +int elbeemSimplifyChannelVec3(float *channel, int *size); + +#ifdef __cplusplus +} +#endif // __cplusplus + +/******************************************************************************/ +// internal defines, do not use for setting up simulation + +/*! fluid geometry init types */ +#define FGI_FLAGSTART 16 +#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0)) +#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1)) +#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2)) +#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3)) +#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4)) +#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5)) +#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6)) +#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7)) + +#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW ) + #endif // ELBEEM_API_H diff --git a/intern/elbeem/intern/globals.h b/intern/elbeem/intern/globals.h deleted file mode 100644 index c2a092ab1c9..00000000000 --- a/intern/elbeem/intern/globals.h +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * All code distributed as part of El'Beem is covered by the version 2 of the - * GNU General Public License. See the file COPYING for details. - * Copyright 2003-2005 Nils Thuerey - * - * Global variables (unavoidable at times...) - * all defines in main.cpp - * - *****************************************************************************/ - - -/*****************************************************************************/ -//! user interface variables - -// global raytracer pointer (=world) -class ntlWorld; -extern ntlWorld *gpWorld; - -// debug output switch -extern bool myDebugOut; - -// global leave program / abort variable -extern bool gQuit; - diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 545cdc89eff..ed0fab289d8 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -9,7 +9,7 @@ #include "isosurface.h" #include "mcubes_tables.h" -#include "ntl_scene.h" +#include "ntl_ray.h" #include <algorithm> #include <stdio.h> @@ -20,23 +20,15 @@ #include <ieeefp.h> #endif -/* -template class vector<IsoLevelVertex>; -template class vector<int>; -template class vector<unsigned int>; -template class vector<float>; -template class vector<ntlVec3Gfx>; -template class vector< vector<int> >; -*/ /****************************************************************************** * Constructor *****************************************************************************/ -IsoSurface::IsoSurface(double iso, double blend) : +IsoSurface::IsoSurface(double iso) : ntlGeometryObject(), mSizex(-1), mSizey(-1), mSizez(-1), + mpData(NULL), mIsoValue( iso ), - mBlendVal( blend ), mPoints(), mpEdgeVerticesX(NULL), mpEdgeVerticesY(NULL), mpEdgeVerticesZ(NULL), mIndices(), @@ -44,7 +36,10 @@ IsoSurface::IsoSurface(double iso, double blend) : mStart(0.0), mEnd(0.0), mDomainExtent(0.0), mInitDone(false), mSmoothSurface(0.0), mSmoothNormals(0.0), - mAcrossEdge(), mAdjacentFaces() + mAcrossEdge(), mAdjacentFaces(), + mCutoff(-1), // off by default + mFlagCnt(1), + mSCrad1(0.), mSCrad2(0.), mSCcenter(0.) { } @@ -87,16 +82,6 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e // marching cubes are ready mInitDone = true; - /*unsigned long int memCnt = (3*sizeof(int)*nodes + sizeof(float)*nodes); - double memd = memCnt; - char *sizeStr = ""; - const double sfac = 1000.0; - if(memd>sfac){ memd /= sfac; sizeStr="KB"; } - if(memd>sfac){ memd /= sfac; sizeStr="MB"; } - if(memd>sfac){ memd /= sfac; sizeStr="GB"; } - if(memd>sfac){ memd /= sfac; sizeStr="TB"; } - - debMsgStd("IsoSurface::initializeIsosurface",DM_MSG,"Inited "<<PRINT_VEC(setx,sety,setz)<<" alloced:"<< memd<<" "<<sizeStr<<"." ,10);*/ } @@ -107,11 +92,10 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e *****************************************************************************/ IsoSurface::~IsoSurface( void ) { - + if(mpData) delete [] mpData; if(mpEdgeVerticesX) delete [] mpEdgeVerticesX; if(mpEdgeVerticesY) delete [] mpEdgeVerticesY; if(mpEdgeVerticesZ) delete [] mpEdgeVerticesZ; - } @@ -132,10 +116,10 @@ void IsoSurface::triangulate( void ) return; } - // get grid spacing - gsx = (mEnd[0]-mStart[0])/(double)(mSizex-1.0); - gsy = (mEnd[1]-mStart[1])/(double)(mSizey-1.0); - gsz = (mEnd[2]-mStart[2])/(double)(mSizez-1.0); + // get grid spacing (-2 to have same spacing as sim) + gsx = (mEnd[0]-mStart[0])/(double)(mSizex-2.0); + gsy = (mEnd[1]-mStart[1])/(double)(mSizey-2.0); + gsz = (mEnd[2]-mStart[2])/(double)(mSizez-2.0); // clean up previous frame mIndices.clear(); @@ -169,13 +153,13 @@ void IsoSurface::triangulate( void ) 0,0,0,0, 1,1,1,1 }; // let the cubes march - pz = mStart[2]-gsz; + pz = mStart[2]-gsz*0.5; for(int k=1;k<(mSizez-2);k++) { pz += gsz; - py = mStart[1]-gsy; + py = mStart[1]-gsy*0.5; for(int j=1;j<(mSizey-2);j++) { py += gsy; - px = mStart[0]-gsx; + px = mStart[0]-gsx*0.5; for(int i=1;i<(mSizex-2);i++) { px += gsx; int baseIn = ISOLEVEL_INDEX( i+0, j+0, k+0); @@ -275,6 +259,12 @@ void IsoSurface::triangulate( void ) } + const int coAdd=2; + if(i<coAdd+mCutoff) continue; + if(j<coAdd+mCutoff) continue; + if((mCutoff>0) && (k<coAdd)) continue; + if(i>mSizex-2-coAdd-mCutoff) continue; + if(j>mSizey-2-coAdd-mCutoff) continue; // Create the triangles... for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) { @@ -283,13 +273,10 @@ void IsoSurface::triangulate( void ) mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] ); mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] ); } - - } - } - + }//i + }// j } // k - // precalculate normals using an approximation of the scalar field gradient for(int ni=0;ni<(int)mPoints.size();ni++) { @@ -297,11 +284,10 @@ void IsoSurface::triangulate( void ) normalize( mPoints[ni].n ); } - //for(int i=0; i<mLoopSubdivs; i++) { subdivide(); }// DEBUG test - if(mSmoothSurface>0.0) { smoothSurface(mSmoothSurface); } + if(mSmoothSurface>0.0) { smoothSurface(mSmoothSurface, (mSmoothNormals<=0.0) ); } if(mSmoothNormals>0.0) { smoothNormals(mSmoothNormals); } myTime_t tritimeend = getTime(); - debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< ((tritimeend-tritimestart)/(double)1000.0)<<"s, ss="<<mSmoothSurface<<" sm="<<mSmoothNormals , 10 ); + debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<<mSmoothSurface<<","<<mSmoothNormals<<")" , 10 ); } @@ -406,7 +392,6 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) { - /****************************************************************************** * * Surface improvement @@ -418,334 +403,109 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) { * *****************************************************************************/ - -// Subdivide a mesh allways loop -/*void IsoSurface::subdivide() -{ - int i; - - mAdjacentFaces.clear(); - mAcrossEdge.clear(); - - //void TriMesh::need_adjacentfaces() - { - vector<int> numadjacentfaces(mPoints.size()); - //errMsg("SUBDIV ADJFA1", " "<<mPoints.size()<<" - "<<numadjacentfaces.size() ); - int i; - for (i = 0; i < (int)mIndices.size()/3; i++) { - numadjacentfaces[mIndices[i*3 + 0]]++; - numadjacentfaces[mIndices[i*3 + 1]]++; - numadjacentfaces[mIndices[i*3 + 2]]++; - } - - mAdjacentFaces.resize(mPoints.size()); - for (i = 0; i < (int)mPoints.size(); i++) - mAdjacentFaces[i].reserve(numadjacentfaces[i]); - - for (i = 0; i < (int)mIndices.size()/3; i++) { - for (int j = 0; j < 3; j++) - mAdjacentFaces[mIndices[i*3 + j]].push_back(i); - } - - } - - // Find the face across each edge from each other face (-1 on boundary) - // If topology is bad, not necessarily what one would expect... - //void TriMesh::need_across_edge() - { - mAcrossEdge.resize(mIndices.size(), -1); - - for (int i = 0; i < (int)mIndices.size()/3; i++) { - for (int j = 0; j < 3; j++) { - if (mAcrossEdge[i*3 + j] != -1) - continue; - int v1 = mIndices[i*3 + ((j+1)%3)]; - int v2 = mIndices[i*3 + ((j+2)%3)]; - const vector<int> &a1 = mAdjacentFaces[v1]; - const vector<int> &a2 = mAdjacentFaces[v2]; - for (int k1 = 0; k1 < (int)a1.size(); k1++) { - int other = a1[k1]; - if (other == i) - continue; - vector<int>::const_iterator it = - std::find(a2.begin(), a2.end(), other); - if (it == a2.end()) - continue; - - //int ind = (faces[other].indexof(v1)+1)%3; - int ind = -1; - if( mIndices[other*3+0] == (unsigned int)v1 ) ind = 0; - else if( mIndices[other*3+1] == (unsigned int)v1 ) ind = 1; - else if( mIndices[other*3+2] == (unsigned int)v1 ) ind = 2; - ind = (ind+1)%3; - - if ( (int)mIndices[other*3 + ((ind+1)%3)] != v2) - continue; - mAcrossEdge[i*3 + j] = other; - mAcrossEdge[other*3 + ind] = i; - break; - } - } - } - - //errMsg("SUBDIV ACREDG", "Done.\n"); - } - - //errMsg("SUBDIV","start"); - // Introduce new vertices - int nf = (int)mIndices.size() / 3; - - //vector<TriMesh::Face> newverts(nf, TriMesh::Face(-1,-1,-1)); - vector<int> newverts(nf*3); //, TriMesh::Face(-1,-1,-1)); - for(int j=0; j<(int)newverts.size(); j++) newverts[j] = -1; - - int old_nv = (int)mPoints.size(); - mPoints.reserve(4 * old_nv); - vector<int> newvert_count(old_nv + 3*nf); // wichtig...? - //errMsg("NC", newvert_count.size() ); - - for (i = 0; i < nf; i++) { - for (int j = 0; j < 3; j++) { - int ae = mAcrossEdge[i*3 + j]; - if (newverts[i*3 + j] == -1 && ae != -1) { - if (mAcrossEdge[ae*3 + 0] == i) - newverts[i*3 + j] = newverts[ae*3 + 0]; - else if (mAcrossEdge[ae*3 + 1] == i) - newverts[i*3 + j] = newverts[ae*3 + 1]; - else if (mAcrossEdge[ae*3 + 2] == i) - newverts[i*3 + j] = newverts[ae*3 + 2]; - } - if (newverts[i*3 + j] == -1) { - IsoLevelVertex ilv; - ilv.v = ntlVec3Gfx(0.0); - ilv.n = ntlVec3Gfx(0.0); - mPoints.push_back(ilv); - newverts[i*3 + j] = (int)mPoints.size() - 1; - if (ae != -1) { - if (mAcrossEdge[ae*3 + 0] == i) - newverts[ae*3 + 0] = newverts[i*3 + j]; - else if (mAcrossEdge[ae*3 + 1] == i) - newverts[ae*3 + 1] = newverts[i*3 + j]; - else if (mAcrossEdge[ae*3 + 2] == i) - newverts[ae*3 + 2] = newverts[i*3 + j]; - } - } - if(ae != -1) { - mPoints[newverts[i*3 + j]].v += - mPoints[ mIndices[i*3 + ( j )] ].v * 0.25f + // j = 0,1,2? - mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.375f + - mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.375f; -#if RECALCNORMALS==0 - mPoints[newverts[i*3 + j]].n += - mPoints[ mIndices[i*3 + ( j )] ].n * 0.25f + // j = 0,1,2? - mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.375f + - mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.375f; -#endif // RECALCNORMALS==0 - } else { - mPoints[newverts[i*3 + j]].v += - mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.5f + - mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.5f ; -#if RECALCNORMALS==0 - mPoints[newverts[i*3 + j]].n += - mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.5f + - mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.5f ; -#endif // RECALCNORMALS==0 - } - - newvert_count[newverts[i*3 + j]]++; - } - } - for (i = old_nv; i < (int)mPoints.size(); i++) { - if (!newvert_count[i]) - continue; - float scale = 1.0f / newvert_count[i]; - mPoints[i].v *= scale; - -#if RECALCNORMALS==0 - //mPoints[i].n *= scale; - //normalize( mPoints[i].n ); -#endif // RECALCNORMALS==0 - } - - // Update old vertices - for (i = 0; i < old_nv; i++) { - ntlVec3Gfx bdyavg(0.0), nbdyavg(0.0); - ntlVec3Gfx norm_bdyavg(0.0), norm_nbdyavg(0.0); // N - int nbdy = 0, nnbdy = 0; - int naf = (int)mAdjacentFaces[i].size(); - if (!naf) - continue; - for (int j = 0; j < naf; j++) { - int af = mAdjacentFaces[i][j]; - - int afi = -1; - if( mIndices[af*3+0] == (unsigned int)i ) afi = 0; - else if( mIndices[af*3+1] == (unsigned int)i ) afi = 1; - else if( mIndices[af*3+2] == (unsigned int)i ) afi = 2; - - int n1 = (afi+1) % 3; - int n2 = (afi+2) % 3; - if (mAcrossEdge[af*3 + n1] == -1) { - bdyavg += mPoints[newverts[af*3 + n1]].v; -#if RECALCNORMALS==0 - //norm_bdyavg += mPoints[newverts[af*3 + n1]].n; -#endif // RECALCNORMALS==0 - nbdy++; - } else { - nbdyavg += mPoints[newverts[af*3 + n1]].v; -#if RECALCNORMALS==0 - //norm_nbdyavg += mPoints[newverts[af*3 + n1]].n; -#endif // RECALCNORMALS==0 - nnbdy++; - } - if (mAcrossEdge[af*3 + n2] == -1) { - bdyavg += mPoints[newverts[af*3 + n2]].v; -#if RECALCNORMALS==0 - //norm_bdyavg += mPoints[newverts[af*3 + n2]].n; -#endif // RECALCNORMALS==0 - nbdy++; - } else { - nbdyavg += mPoints[newverts[af*3 + n2]].v; -#if RECALCNORMALS==0 - //norm_nbdyavg += mPoints[newverts[af*3 + n2]].n; -#endif // RECALCNORMALS==0 - nnbdy++; - } - } - - float alpha; - ntlVec3Gfx newpt; - if (nbdy) { - newpt = bdyavg / (float) nbdy; - alpha = 0.5f; - } else if (nnbdy) { - newpt = nbdyavg / (float) nnbdy; - if (nnbdy == 6) - alpha = 1.05; - else if (nnbdy == 8) - alpha = 0.86; - else if (nnbdy == 10) - alpha = 0.7; - else - alpha = 0.6; - } else { - continue; - } - mPoints[i].v *= 1.0f - alpha; - mPoints[i].v += newpt * alpha; - -#if RECALCNORMALS==0 - //mPoints[i].n *= 1.0f - alpha; - //mPoints[i].n += newpt * alpha; -#endif // RECALCNORMALS==0 - } - - // Insert new faces - mIndices.reserve(4*nf); - for (i = 0; i < nf; i++) { - mIndices.push_back( mIndices[i*3 + 0]); - mIndices.push_back( newverts[i*3 + 2]); - mIndices.push_back( newverts[i*3 + 1]); - - mIndices.push_back( mIndices[i*3 + 1]); - mIndices.push_back( newverts[i*3 + 0]); - mIndices.push_back( newverts[i*3 + 2]); - - mIndices.push_back( mIndices[i*3 + 2]); - mIndices.push_back( newverts[i*3 + 1]); - mIndices.push_back( newverts[i*3 + 0]); - - mIndices[i*3+0] = newverts[i*3+0]; - mIndices[i*3+1] = newverts[i*3+1]; - mIndices[i*3+2] = newverts[i*3+2]; - } - - // recalc normals -#if RECALCNORMALS==1 - { - int nf = (int)mIndices.size()/3, nv = (int)mPoints.size(), i; - for (i = 0; i < nv; i++) { - mPoints[i].n = ntlVec3Gfx(0.0); - } - for (i = 0; i < nf; i++) { - const ntlVec3Gfx &p0 = mPoints[mIndices[i*3+0]].v; - const ntlVec3Gfx &p1 = mPoints[mIndices[i*3+1]].v; - const ntlVec3Gfx &p2 = mPoints[mIndices[i*3+2]].v; - ntlVec3Gfx a = p0-p1, b = p1-p2, c = p2-p0; - float l2a = normNoSqrt(a), l2b = normNoSqrt(b), l2c = normNoSqrt(c); - - ntlVec3Gfx facenormal = cross(a, b); - - mPoints[mIndices[i*3+0]].n += facenormal * (1.0f / (l2a * l2c)); - mPoints[mIndices[i*3+1]].n += facenormal * (1.0f / (l2b * l2a)); - mPoints[mIndices[i*3+2]].n += facenormal * (1.0f / (l2c * l2b)); - } - - for (i = 0; i < nv; i++) { - normalize(mPoints[i].n); - } - } -#else // RECALCNORMALS==1 - for (i = 0; i < (int)mPoints.size(); i++) { - normalize(mPoints[i].n); - } -#endif // RECALCNORMALS==1 - - //errMsg("SUBDIV","done nv:"<<mPoints.size()<<" nf:"<<mIndices.size() ); -}*/ - +void IsoSurface::setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc) { + mSCrad1 = radi1*radi1; + mSCrad2 = radi2*radi2; + mSCcenter = mscc; +} // Diffuse a vector field at 1 vertex, weighted by // a gaussian of width 1/sqrt(invsigma2) -void IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt) +bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int src, float invsigma2, ntlVec3Gfx &flt) { + if((neighbors[src].size()<1) || (pointareas[src]<=0.0)) return 0; + const ntlVec3Gfx srcp = mPoints[src].v; + const ntlVec3Gfx srcn = mPoints[src].n; + if(mSCrad1>0.0 && mSCrad2>0.0) { + ntlVec3Gfx dp = mSCcenter-srcp; dp[2] = 0.0; // only xy-plane + float rd = normNoSqrt(dp); + if(rd > mSCrad2) { + //errMsg("TRi","p"<<srcp<<" c"<<mSCcenter<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" "); + //invsigma2 *= (rd*rd-mSCrad1); + //flt = ntlVec3Gfx(100); return 1; + return 0; + } else if(rd > mSCrad1) { + // optimize? + float org = 1.0/sqrt(invsigma2); + org *= (1.0- (rd-mSCrad1) / (mSCrad2-mSCrad1)); + invsigma2 = 1.0/(org*org); + //flt = ntlVec3Gfx((rd-mSCrad1) / (mSCrad2-mSCrad1)); return 1; + //errMsg("TRi","p"<<srcp<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" org:"<<org<<" is:"<<invsigma2); + //invsigma2 *= (rd*rd-mSCrad1); + //return 0; + } else { + } + } flt = ntlVec3Gfx(0.0); - flt += *(field+pointerScale*v) *pointareas[v]; - float sum_w = pointareas[v]; - const ntlVec3Gfx &nv = mPoints[v].n; - - unsigned &flag = flag_curr; - flag++; - flags[v] = flag; - vector<int> boundary = neighbors[v]; - while (!boundary.empty()) { - const int bbn = boundary.back(); - boundary.pop_back(); - if (flags[bbn] == flag) continue; + flt += *(field+pointerScale*src) *pointareas[src]; + float sum_w = pointareas[src]; + //const ntlVec3Gfx &nv = mPoints[src].n; + + int flag = mFlagCnt; + mFlagCnt++; + flags[src] = flag; + //vector<int> mDboundary = neighbors[src]; + mDboundary = neighbors[src]; + while (!mDboundary.empty()) { + const int bbn = mDboundary.back(); + mDboundary.pop_back(); + if(flags[bbn]==flag) continue; flags[bbn] = flag; + // normal check + const float nvdot = dot(srcn, mPoints[bbn].n); // faster than before d2 calc? + if(nvdot <= 0.0f) continue; // faster than before d2 calc? + // gaussian weight of width 1/sqrt(invsigma2) - const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - mPoints[v].v); + const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - srcp); if(d2 >= 9.0f) continue; // 25 also possible , slower - //float w = (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2); - float w = exp(-0.5f*d2); - if(dot(nv, mPoints[bbn].n) <= 0.0f) continue; // faster than before d2 calc? + //if(dot(srcn, mPoints[bbn].n) <= 0.0f) continue; // faster than before d2 calc? + //float w = (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2); + //float w = expf(-0.5f*d2); +#if 0 + float w=1.0; // Downweight things pointing in different directions - w *= dot(nv , mPoints[bbn].n); + w *= nvdot; //dot(srcn , mPoints[bbn].n); // Surface area "belonging" to each point w *= pointareas[bbn]; // Accumulate weight times field at neighbor flt += *(field+pointerScale*bbn)*w; - sum_w += w; - for (int i = 0; i < (int)neighbors[bbn].size(); i++) { - int nn = neighbors[bbn][i]; + // */ +#else + // more aggressive smoothing with: float w=1.0; + float w=nvdot * pointareas[bbn]; + // Accumulate weight times field at neighbor + flt += *(field+pointerScale*bbn)*w; + sum_w += w; +#endif + // */ + + for(int i = 0; i < (int)neighbors[bbn].size(); i++) { + const int nn = neighbors[bbn][i]; if (flags[nn] == flag) continue; - boundary.push_back(nn); + mDboundary.push_back(nn); } } flt /= sum_w; + return 1; } -void IsoSurface::smoothSurface(float sigma) +// REF +// TestData::getTriangles message: Time for surface generation:3.75s, S(0.0390625,0.1171875) + // ntlWorld::ntlWorld message: Time for start-sims:0s + // TestData::getTriangles message: Time for surface generation:3.69s, S(0.0390625,0.1171875) + + + +void IsoSurface::smoothSurface(float sigma, bool normSmooth) { int nv = mPoints.size(); if ((int)flags.size() != nv) flags.resize(nv); int nf = mIndices.size()/3; { // need neighbors - vector<int> numneighbors(mPoints.size()); int i; for (i = 0; i < (int)mIndices.size()/3; i++) { @@ -845,10 +605,11 @@ void IsoSurface::smoothSurface(float sigma) vector<ntlVec3Gfx> dflt(nv); for (int i = 0; i < nv; i++) { - diffuseVertexField( &mPoints[0].v, 2, - i, invsigma2, dflt[i]); - // Just keep the displacement - dflt[i] -= mPoints[i].v; + if(diffuseVertexField( &mPoints[0].v, 2, + i, invsigma2, dflt[i])) { + // Just keep the displacement + dflt[i] -= mPoints[i].v; + } else { dflt[i] = 0.0; } //?mPoints[i].v; } } // Slightly better small-neighborhood approximation @@ -869,8 +630,9 @@ void IsoSurface::smoothSurface(float sigma) // Filter displacement field vector<ntlVec3Gfx> dflt2(nv); for (int i = 0; i < nv; i++) { - diffuseVertexField( &dflt[0], 1, - i, invsigma2, dflt2[i]); + if(diffuseVertexField( &dflt[0], 1, + i, invsigma2, dflt2[i])) { } + else { /*mPoints[i].v=0.0;*/ dflt2[i] = 0.0; }//dflt2[i]; } } // Update vertex positions @@ -881,10 +643,13 @@ void IsoSurface::smoothSurface(float sigma) // when normals smoothing off, this cleans up quite well // costs ca. 50% additional time though float nsFac = 1.5f; - { float ninvsigma2 = 1.0f / (nsFac*nsFac*sigma*sigma); + if(normSmooth) { float ninvsigma2 = 1.0f / (nsFac*nsFac*sigma*sigma); for (int i = 0; i < nv; i++) { - diffuseVertexField( &mPoints[0].n, 2, i, ninvsigma2, dflt[i]); - normalize(dflt[i]); + if( diffuseVertexField( &mPoints[0].n, 2, i, ninvsigma2, dflt[i]) ) { + normalize(dflt[i]); + } else { + dflt[i] = mPoints[i].n; + } } for (int i = 0; i < nv; i++) { mPoints[i].n = dflt[i]; @@ -896,7 +661,9 @@ void IsoSurface::smoothSurface(float sigma) void IsoSurface::smoothNormals(float sigma) { - { // need neighbor + // reuse from smoothSurface + if(neighbors.size() != mPoints.size()) { + // need neighbor vector<int> numneighbors(mPoints.size()); int i; for (i = 0; i < (int)mIndices.size()/3; i++) { @@ -998,13 +765,13 @@ void IsoSurface::smoothNormals(float sigma) vector<ntlVec3Gfx> nflt(nv); for (int i = 0; i < nv; i++) { - diffuseVertexField( &mPoints[0].n, 2, i, invsigma2, nflt[i]); - normalize(nflt[i]); + if(diffuseVertexField( &mPoints[0].n, 2, i, invsigma2, nflt[i])) { + normalize(nflt[i]); + } else { nflt[i]=mPoints[i].n; } } - for (int i = 0; i < nv; i++) { - mPoints[i].n = nflt[i]; - } + // copy back + for (int i = 0; i < nv; i++) { mPoints[i].n = nflt[i]; } //errMsg("SMNRMLS","done v:"<<sigma); // DEBUG } diff --git a/intern/elbeem/intern/isosurface.h b/intern/elbeem/intern/isosurface.h index 9682b571b21..90a4e11e95f 100644 --- a/intern/elbeem/intern/isosurface.h +++ b/intern/elbeem/intern/isosurface.h @@ -40,9 +40,9 @@ class IsoSurface : public: /*! Constructor */ - IsoSurface(double iso, double blend); + IsoSurface(double iso); /*! Destructor */ - ~IsoSurface(); + virtual ~IsoSurface(); /*! Init ararys etc. */ virtual void initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx extent); @@ -63,9 +63,6 @@ class IsoSurface : //! Level of the iso surface double mIsoValue; - //! blending distance for marching cubes - double mBlendVal; - //! Store all the triangles vertices vector<IsoLevelVertex> mPoints; @@ -96,8 +93,12 @@ class IsoSurface : vector<int> mAcrossEdge; vector< vector<int> > mAdjacentFaces; - vector<unsigned> flags; - unsigned flag_curr; + //! cutoff border area + int mCutoff; + + //! trimesh vars + vector<int> flags; + int mFlagCnt; vector<ntlVec3Gfx> cornerareas; vector<float> pointareas; vector< vector<int> > neighbors; @@ -116,6 +117,8 @@ class IsoSurface : //! set loop subdiv num inline void setSmoothSurface(float set) { mSmoothSurface = set; }; inline void setSmoothNormals(float set) { mSmoothNormals = set; }; + inline float getSmoothSurface() { return mSmoothSurface; } + inline float getSmoothNormals() { return mSmoothNormals; } // geometry object functions virtual void getTriangles( vector<ntlTriangle> *triangles, @@ -155,6 +158,8 @@ class IsoSurface : return mpData + ISOLEVEL_INDEX(ii+1,jj+1,kk+1); #endif } + //! set cut off border + inline void setCutoff(int set) { mCutoff = set; }; //! OpenGL viz "interface" unsigned int getIsoVertexCount() { @@ -169,16 +174,21 @@ class IsoSurface : unsigned int *getIsoIndexArray() { return &(mIndices[0]); } + + // surface smoothing functions + void setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc); + void smoothSurface(float val, bool smoothNorm); + void smoothNormals(float val); protected: - //! computer normal + //! compute normal inline ntlVec3Gfx getNormal(int i, int j,int k); - - void subdivide(); - void smoothSurface(float val); - void smoothNormals(float val); - void diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt); + //! smoothing helper function + bool diffuseVertexField(ntlVec3Gfx *field, int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt); + vector<int> mDboundary; + float mSCrad1, mSCrad2; + ntlVec3Gfx mSCcenter; }; diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp index e9e67b1a72d..fce5a085f59 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.cpp +++ b/intern/elbeem/intern/ntl_blenderdumper.cpp @@ -14,7 +14,8 @@ #include "utilities.h" #include "ntl_matrices.h" #include "ntl_blenderdumper.h" -#include "ntl_scene.h" +#include "ntl_world.h" +#include "solver_interface.h" #include <zlib.h> @@ -31,17 +32,15 @@ ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) : AttributeList *pAttrs = glob->getBlenderAttributes(); mpTrafo = new ntlMat4Gfx(0.0); mpTrafo->initId(); - (*mpTrafo) = pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false ); + pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false, mpTrafo ); } ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) : ntlWorld(settings), mpTrafo(NULL) { // same as normal constructor here - ntlRenderGlobals *glob = mpGlob; - AttributeList *pAttrs = glob->getBlenderAttributes(); mpTrafo = new ntlMat4Gfx(0.0); - mpTrafo->initId(); - (*mpTrafo) = pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false ); + mpTrafo->initArrayCheck(settings->surfaceTrafo); + //errMsg("ntlBlenderDumper","mpTrafo inited: "<<(*mpTrafo) ); } @@ -52,6 +51,7 @@ ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) : ntlBlenderDumper::~ntlBlenderDumper() { delete mpTrafo; + debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10); } /****************************************************************************** @@ -61,11 +61,11 @@ int ntlBlenderDumper::renderScene( void ) { char nrStr[5]; /* nr conversion */ ntlRenderGlobals *glob = mpGlob; - ntlScene *scene = mpGlob->getScene(); + ntlScene *scene = mpGlob->getSimScene(); bool debugOut = true; -#if ELBEEM_BLENDER==1 +#if ELBEEM_PLUGIN==1 debugOut = false; -#endif // ELBEEM_BLENDER==1 +#endif // ELBEEM_PLUGIN==1 // output path /*std::ostringstream ecrpath(""); @@ -91,6 +91,7 @@ int ntlBlenderDumper::renderScene( void ) vector<ntlTriangle> Triangles; vector<ntlVec3Gfx> Vertices; vector<ntlVec3Gfx> VertNormals; + errMsg("ntlBlenderDumper","mpTrafo : "<<(*mpTrafo) ); /* init geometry array, first all standard objects */ int idCnt = 0; // give IDs to objects @@ -106,80 +107,117 @@ int ntlBlenderDumper::renderScene( void ) if(tid & GEOCLASSTID_SHADER) { ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter); hideObjs.push_back( (*iter)->getName() ); + geoshad->notifyShaderOfDump(glob->getAniCount(),nrStr,glob->getOutFilename()); for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin(); siter != geoshad->getObjectsEnd(); siter++) { if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8); + + (*siter)->notifyOfDump(glob->getAniCount(),nrStr,glob->getOutFilename()); + bool doDump = false; + bool isPreview = false; + // only dump final&preview surface meshes + if( (*siter)->getName().find( "final" ) != string::npos) { + doDump = true; + } else if( (*siter)->getName().find( "preview" ) != string::npos) { + doDump = true; + isPreview = true; + } + if(!doDump) continue; // only dump geo shader objects Triangles.clear(); Vertices.clear(); VertNormals.clear(); (*siter)->initialize( mpGlob ); + //int vstart = mVertNormals.size()-1; (*siter)->getTriangles(&Triangles, &Vertices, &VertNormals, idCnt); + idCnt ++; // always dump mesh, even empty ones... - //if(Vertices.size() <= 0) continue; - //if(Triangles.size() <= 0) continue; - - for(size_t i=0; i<Vertices.size(); i++) { - Vertices[i] = (*mpTrafo) * Vertices[i]; - } // dump to binary file std::ostringstream boutfilename(""); //boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj"; - boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".bobj"; + boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr; if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName() <<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<< " to "<<boutfilename.str() , 7); - bool isPreview = false; - if( (*siter)->getName().find( "preview" ) != string::npos) { - isPreview = true; - } - boutfilename << ".gz"; - - // compress all bobj's except for preview ones... gzFile gzf; - if(isPreview) { - gzf = gzopen(boutfilename.str().c_str(), "wb1"); - } else { - gzf = gzopen(boutfilename.str().c_str(), "wb9"); + + // output velocities if desired + // WARNING - this is dirty, but simobjs are the only geoshaders right now + SimulationObject *sim = (SimulationObject *)geoshad; + LbmSolverInterface *lbm = sim->getSolver(); + if((!isPreview) && (lbm->getDumpVelocities())) { + std::ostringstream bvelfilename; + bvelfilename << boutfilename.str(); + bvelfilename << ".bvel.gz"; + gzf = gzopen(bvelfilename.str().c_str(), "wb9"); + if(gzf) { + int numVerts; + if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; } + numVerts = Vertices.size(); + gzwrite(gzf, &numVerts, sizeof(numVerts)); + for(size_t i=0; i<Vertices.size(); i++) { + // returns smoothed velocity, scaled by frame time + ntlVec3Gfx v = lbm->getVelocityAt( Vertices[i][0], Vertices[i][1], Vertices[i][2] ); + // translation not necessary, test rotation & scaling? + //? v = (*mpTrafo) * v; + for(int j=0; j<3; j++) { + float vertp = v[j]; + //if(i<20) errMsg("ntlBlenderDumper","DUMP_VEL final "<<i<<" = "<<v); + gzwrite(gzf, &vertp, sizeof(vertp)); } + } + gzclose( gzf ); + } } + + // compress all bobj's + boutfilename << ".bobj.gz"; + //if(isPreview) { } else { } + gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes! if (!gzf) { errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' "); return 1; } - int wri; - float wrf; - if(sizeof(wri)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; } - wri = Vertices.size(); - gzwrite(gzf, &wri, sizeof(wri)); + // transform into source space + for(size_t i=0; i<Vertices.size(); i++) { + Vertices[i] = (*mpTrafo) * Vertices[i]; + } + // write to file + int numVerts; + if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; } + numVerts = Vertices.size(); + gzwrite(gzf, &numVerts, sizeof(numVerts)); for(size_t i=0; i<Vertices.size(); i++) { for(int j=0; j<3; j++) { - wrf = Vertices[i][j]; - gzwrite(gzf, &wrf, sizeof(wrf)); } + float vertp = Vertices[i][j]; + gzwrite(gzf, &vertp, sizeof(vertp)); } } // should be the same as Vertices.size - wri = VertNormals.size(); - gzwrite(gzf, &wri, sizeof(wri)); + if(VertNormals.size() != (size_t)numVerts) { + errMsg("ntlBlenderDumper::renderScene","Normals have to have same size as vertices!"); + VertNormals.resize( Vertices.size() ); + } + gzwrite(gzf, &numVerts, sizeof(numVerts)); for(size_t i=0; i<VertNormals.size(); i++) { for(int j=0; j<3; j++) { - wrf = VertNormals[i][j]; - gzwrite(gzf, &wrf, sizeof(wrf)); } + float normp = VertNormals[i][j]; + gzwrite(gzf, &normp, sizeof(normp)); } } - wri = Triangles.size(); - gzwrite(gzf, &wri, sizeof(wri)); + int numTris = Triangles.size(); + gzwrite(gzf, &numTris, sizeof(numTris)); for(size_t i=0; i<Triangles.size(); i++) { for(int j=0; j<3; j++) { - wri = Triangles[i].getPoints()[j]; - gzwrite(gzf, &wri, sizeof(wri)); } + int triIndex = Triangles[i].getPoints()[j]; + gzwrite(gzf, &triIndex, sizeof(triIndex)); } } gzclose( gzf ); - debMsgDirect(" Wrote: '"<<boutfilename.str()<<"'. "); + debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY," Wrote: '"<<boutfilename.str()<<"' ", 2); numGMs++; } } @@ -200,6 +238,7 @@ int ntlBlenderDumper::renderScene( void ) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10); // still render for preview... +debugOut = false; // DEBUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if(debugOut) { debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1); ntlWorld::renderScene(); } diff --git a/intern/elbeem/intern/ntl_bsptree.cpp b/intern/elbeem/intern/ntl_bsptree.cpp index 59b0fd50ea2..afa1fa5804c 100644 --- a/intern/elbeem/intern/ntl_bsptree.cpp +++ b/intern/elbeem/intern/ntl_bsptree.cpp @@ -9,7 +9,6 @@ #include "ntl_bsptree.h" -#include "ntl_scene.h" #include "utilities.h" #include <algorithm> @@ -146,7 +145,7 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : mStart(0.0), mEnd(0.0), mMaxDepth( depth ), mMaxListLength( objnum ), mpRoot( NULL) , mpNodeStack( NULL), mpTBB( NULL ), mTriangleMask( 0xFFFF ), - mCurrentDepth(0), mCurrentNodes(0) + mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0) { // init scene data pointers mpVertices = scene->getVertexPointer(); @@ -175,11 +174,12 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : mpTBB = new TriangleBBox[ noOfTriangles ]; int bbCount = 0; mStart = mEnd = (*mpVertices)[ mpTriangles->front().getPoints()[0] ]; + //errMsg("TreeDebug","Start"); for (vector<ntlTriangle>::iterator iter = mpTriangles->begin(); iter != mpTriangles->end(); iter++ ) { + //errorOut(" d "<< convertFlags2String((int)(*iter).getFlags()) <<" "<< convertFlags2String( (int)mTriangleMask)<<" add? "<<( ((int)(*iter).getFlags() & (int)mTriangleMask) != 0 ) ); // discard triangles that dont match mask - //errorOut(" d "<<(int)(*iter).getFlags() <<" "<< (int)mTriangleMask ); if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) { continue; } @@ -194,9 +194,11 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : // */ ntlVec3Gfx bbs, bbe; + //errMsg("TreeDebug","Triangle"); for(int i=0;i<3;i++) { int index = (*iter).getPoints()[i]; ntlVec3Gfx tp = (*mpVertices)[ index ]; + //errMsg("TreeDebug"," Point "<<i<<" = "<<tp<<" "); if(tp[0] < mStart[0]) mStart[0]= tp[0]; if(tp[0] > mEnd[0]) mEnd[0]= tp[0]; if(tp[1] < mStart[1]) mStart[1]= tp[1]; @@ -241,6 +243,8 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : mpRoot->cloneVec = 0; globalSortingPoints = mpVertices; mpTriDist = new char[ mppTriangles->size() ]; + mNumNodes = 1; + mAbortSubdiv = 0; /* create tree */ debugOutInter( "Generating BSP Tree... (Nodes "<< mCurrentNodes << @@ -265,9 +269,15 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) : triPerLeaf /= (gfxReal)noLeafs; debMsgStd("ntlTree::ntlTree",DM_MSG,"Tree ("<<doSort<<","<<chooseAxis<<") Stats: Leafs:"<<noLeafs<<", avgDepth:"<<avgDepth<< ", triPerLeaf:"<<triPerLeaf<<", triDoubles:"<<mTriDoubles<<", totalTris:"<<totalTris + <<" nodes:"<<mNumNodes //<<" T"<< (totalTris%3) // 0=ich, 1=f, 2=a , 2 ); + if(mAbortSubdiv) { + errMsg("ntlTree::ntlTree","Aborted... "<<mNumNodes); + deleteNode(mpRoot); + mpRoot = NULL; + } } /****************************************************************************** @@ -295,6 +305,7 @@ void ntlTree::subdivide(BSPNode *node, int depth, int axis) if( ( (int)node->members->size() > mMaxListLength) && (depth < mMaxDepth ) && (node->cloneVec<10) + && (!mAbortSubdiv) ) { gfxReal planeDiv = 0.499999; // position of plane division @@ -339,6 +350,9 @@ void ntlTree::subdivide(BSPNode *node, int depth, int axis) node->child[i]->members = NULL; nextAxis = (axis+1)%3; node->child[i]->axis = nextAxis; + mNumNodes++; + // abort when using 256MB only for tree... + if(mNumNodes*sizeof(BSPNode)> 1024*1024*512) mAbortSubdiv = 1; /* current division plane */ if(!i) { @@ -489,6 +503,7 @@ void ntlTree::intersect(const ntlRay &ray, gfxReal &distance, ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist); if((maxdist < 0.0) || + (!mpRoot) || (mindist == GFX_REAL_MAX) || (maxdist == GFX_REAL_MAX) ) { distance = -1.0; @@ -681,6 +696,7 @@ void ntlTree::intersectX(const ntlRay &ray, gfxReal &distance, ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist); // +X if((maxdist < 0.0) || + (!mpRoot) || (mindist == GFX_REAL_MAX) || (maxdist == GFX_REAL_MAX) ) { distance = -1.0; diff --git a/intern/elbeem/intern/ntl_bsptree.h b/intern/elbeem/intern/ntl_bsptree.h index d9746532fc0..face7c3aa7f 100644 --- a/intern/elbeem/intern/ntl_bsptree.h +++ b/intern/elbeem/intern/ntl_bsptree.h @@ -6,14 +6,11 @@ * Tree container for fast triangle intersects * *****************************************************************************/ - - -#ifndef NTL_TREE_HH -#define NTL_TREE_HH +#ifndef NTL_TREE_H +#define NTL_TREE_H #include "ntl_vector3dim.h" #include "ntl_ray.h" -#include "ntl_triangle.h" #define AXIS_X 0 @@ -29,6 +26,8 @@ class BSPNode; class BSPStackElement; class BSPStack; class TriangleBBox; +class ntlScene; +class ntlTriangle; //! Class for a bsp tree for triangles @@ -85,6 +84,9 @@ class ntlTree //! root node pointer BSPNode *mpRoot; + //! count no. of node + int mNumNodes; + int mAbortSubdiv; //! stack for the node pointers BSPStack *mpNodeStack; diff --git a/intern/elbeem/intern/ntl_geometryclass.h b/intern/elbeem/intern/ntl_geometryclass.h index 145f36bbc5f..bcc5a32fb58 100644 --- a/intern/elbeem/intern/ntl_geometryclass.h +++ b/intern/elbeem/intern/ntl_geometryclass.h @@ -28,6 +28,7 @@ class ntlGeometryClass //! Default constructor inline ntlGeometryClass() : mVisible( 1 ), mName( "[ObjNameUndef]" ), + mObjectId(-1), mpAttrs( NULL ) { mpAttrs = new AttributeList("objAttrs"); @@ -62,6 +63,10 @@ class ntlGeometryClass virtual inline ntlVec3Gfx *getBBStart() { return NULL; } virtual inline ntlVec3Gfx *getBBEnd() { return NULL; } + /*! Set/get the object id*/ + inline void setObjectId(int set) { mObjectId=set; } + inline int getObjectId() const { return mObjectId; } + /*! GUI - this function is called for selected objects to display debugging information with OpenGL */ virtual void drawDebugDisplay() { /* do nothing by default */ } /*! GUI - this function is called for selected objects to display interactive information with OpenGL */ @@ -79,6 +84,9 @@ class ntlGeometryClass /*! Name of this object */ string mName; + /*! global scene object id */ + int mObjectId; + /*! configuration attributes */ AttributeList *mpAttrs; diff --git a/intern/elbeem/intern/ntl_geometrymodel.cpp b/intern/elbeem/intern/ntl_geometrymodel.cpp index 2ab80f5be79..3c2e05a8c36 100644 --- a/intern/elbeem/intern/ntl_geometrymodel.cpp +++ b/intern/elbeem/intern/ntl_geometrymodel.cpp @@ -9,7 +9,7 @@ #include "ntl_geometrymodel.h" #include "ntl_ray.h" -#include "ntl_scene.h" +#include "ntl_world.h" #include "zlib.h" #ifdef WIN32 @@ -46,6 +46,13 @@ ntlGeometryObjModel::~ntlGeometryObjModel() /*****************************************************************************/ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) { + // perhaps the model is already inited from initModel below? + if(mLoaded==1) { + // init default material + searchMaterial( glob->getMaterials() ); + return; + } + ntlGeometryObject::initialize(glob); mFilename = mpAttrs->readString("filename", mFilename,"ntlGeometryObjModel", "mFilename", true); @@ -73,36 +80,32 @@ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) } } - -/* defines */ -#define T(x) model->triangles[(x)] - /****************************************************************************** - * + * init model from given vertex and triangle arrays *****************************************************************************/ -void -ntlGeometryObjModel::getTriangles( vector<ntlTriangle> *triangles, - vector<ntlVec3Gfx> *vertices, - vector<ntlVec3Gfx> *normals, int objectId ) + +int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles) { - if(!mLoaded) { // invalid type... - return; + mVertices.clear(); + mVertices.resize( numVertices ); + mNormals.resize( numVertices ); + for(int i=0; i<numVertices; i++) { + mVertices[i] = ntlVec3Gfx(vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]); + mNormals[i] = ntlVec3Gfx(1.0); // unused, set to !=0.0 } - for(int i=0; i<(int)mTriangles.size(); i+=3) { - int trip[3]; - trip[0] = mTriangles[i+0]; - trip[1] = mTriangles[i+1]; - trip[2] = mTriangles[i+2]; - sceneAddTriangle( - mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]], - mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]], - ntlVec3Gfx(0.0), 1 ); /* normal unused */ + mTriangles.clear(); + mTriangles.resize( 3*numTriangles ); + for(int i=0; i<numTriangles; i++) { + mTriangles[3*i+0] = triangles[i*3+0]; + mTriangles[3*i+1] = triangles[i*3+1]; + mTriangles[3*i+2] = triangles[i*3+2]; } - // bobj - return; -} + // inited, no need to parse attribs etc. + mLoaded = 1; + return 0; +} /****************************************************************************** @@ -119,67 +122,61 @@ int ntlGeometryObjModel::loadBobjModel(string filename) return 1; } - int wri; - int gotbytes = -1; - gotbytes = gzread(gzf, &wri, sizeof(wri) ); - if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ"," Invalid readNV size "<< wri); goto gzreaderror; } - if(sizeof(wri)!=4) { // paranoia check - errMsg("Reading GZ_BOBJ"," Invalid int size "<< wri); + int numVerts; + if(sizeof(numVerts)!=4) { // paranoia check + errMsg("Reading GZ_BOBJ"," Invalid int size, check compiler settings: int has to be 4 byte long"); goto gzreaderror; } - if(wri<0 || wri>1e9) { - errMsg("Reading GZ_BOBJ"," invalid num vertices "<< wri); + gzread(gzf, &numVerts, sizeof(numVerts) ); + if(numVerts<0 || numVerts>1e9) { + errMsg("Reading GZ_BOBJ"," invalid num vertices "<< numVerts); goto gzreaderror; } mVertices.clear(); - mVertices.resize( wri ); - for(int i=0; i<wri; i++) { + mVertices.resize( numVerts ); + for(int i=0; i<numVerts; i++) { float x[3]; for(int j=0; j<3; j++) { - gotbytes = gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); - if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ"," Invalid readV size "<< wri); goto gzreaderror; } // CHECK + gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); } mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]); } - if(debugPrint) errMsg("NV"," "<<wri<<" "<< mVertices.size() ); + if(debugPrint) errMsg("NV"," "<<numVerts<<" "<< mVertices.size() ); // should be the same as Vertices.size - gotbytes = gzread(gzf, &wri, sizeof(wri) ); - if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNN size "<< wri); goto gzreaderror; } - if(wri<0 || wri>1e9) { - errMsg("Reading GZ_BOBJ","invalid num normals "<< wri); + gzread(gzf, &numVerts, sizeof(numVerts) ); + if(numVerts<0 || numVerts>1e9) { + errMsg("Reading GZ_BOBJ","invalid num normals "<< numVerts); goto gzreaderror; } mNormals.clear(); - mNormals.resize( wri ); - for(int i=0; i<wri; i++) { + mNormals.resize( numVerts ); + for(int i=0; i<numVerts; i++) { float n[3]; for(int j=0; j<3; j++) { - gotbytes = gzread(gzf, &(n[j]), sizeof( (n[j]) ) ); - if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ","Invalid readN size "<< wri); goto gzreaderror; } + gzread(gzf, &(n[j]), sizeof( (n[j]) ) ); } mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]); } - if(debugPrint) errMsg("NN"," "<<wri<<" "<< mNormals.size() ); + if(debugPrint) errMsg("NN"," "<<numVerts<<" "<< mNormals.size() ); - gotbytes = gzread(gzf, &wri, sizeof(wri) ); - if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNT size "<< wri); goto gzreaderror; } - if(wri<0 || wri>1e9) { - errMsg("Reading GZ_BOBJ","invalid num normals "<< wri); + int numTris; + gzread(gzf, &numTris, sizeof(numTris) ); + if(numTris<0 || numTris>1e9) { + errMsg("Reading GZ_BOBJ","invalid num normals "<< numTris); goto gzreaderror; } - mTriangles.resize( 3*wri ); - for(int i=0; i<wri; i++) { + mTriangles.resize( 3*numTris ); + for(int i=0; i<numTris; i++) { int tri[3]; for(int j=0; j<3; j++) { - gotbytes = gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) ); - if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readT size "<< wri); goto gzreaderror; } + gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) ); } mTriangles[3*i+0] = tri[0]; mTriangles[3*i+1] = tri[1]; mTriangles[3*i+2] = tri[2]; } - if(debugPrint) errMsg("NT"," "<<wri<<" "<< mTriangles.size() ); + if(debugPrint) errMsg("NT"," "<<numTris<<" "<< mTriangles.size() ); debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 ); @@ -196,27 +193,34 @@ gzreaderror: /****************************************************************************** - * init model from given vertex and triangle arrays + * *****************************************************************************/ - -int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles) +void +ntlGeometryObjModel::getTriangles( vector<ntlTriangle> *triangles, + vector<ntlVec3Gfx> *vertices, + vector<ntlVec3Gfx> *normals, int objectId ) { - mVertices.clear(); - mVertices.resize( numVertices ); - for(int i=0; i<numVertices; i++) { - //mVertices[i] = ntlVec3Gfx(vertices[i][0],vertices[i][1],vertices[i][2]); - mVertices[i] = ntlVec3Gfx(vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]); + if(!mLoaded) { // invalid type... + return; } - mTriangles.clear(); - mTriangles.resize( 3*numTriangles ); - for(int i=0; i<numTriangles; i++) { - mTriangles[3*i+0] = triangles[i*3+0]; - mTriangles[3*i+1] = triangles[i*3+1]; - mTriangles[3*i+2] = triangles[i*3+2]; - } + for(int i=0; i<(int)mTriangles.size(); i+=3) { + int trip[3]; + trip[0] = mTriangles[i+0]; + trip[1] = mTriangles[i+1]; + trip[2] = mTriangles[i+2]; - return 0; + sceneAddTriangle( + mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]], + mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]], + ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */ + } + objectId = -1; // remove warning + // bobj + return; } + + + diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index a9340fd2dec..7bbae5d87a1 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -10,7 +10,8 @@ #include "ntl_geometryobject.h" -#include "ntl_renderglobals.h" +#include "ntl_world.h" +#include "ntl_matrices.h" // for FGI #include "elbeem.h" @@ -21,13 +22,23 @@ /* Default constructor */ /*****************************************************************************/ ntlGeometryObject::ntlGeometryObject() : - mpMaterial( NULL ), + mIsInitialized(false), mpMaterial( NULL ), mMaterialName( "default" ), mCastShadows( 1 ), mReceiveShadows( 1 ), mGeoInitId( -1 ), mGeoInitType( 0 ), - mInitialVelocity(0.0), - mGeoInitIntersect(false) + mInitialVelocity(0.0), mcInitialVelocity(0.0), mLocalCoordInivel(false), + mGeoInitIntersect(false), + mGeoPartSlipValue(0.0), + mOnlyThinInit(false), + mInitialPos(0.), + mcTrans(0.), mcRot(0.), mcScale(1.), + mIsAnimated(false), + mMovPoints(), mMovNormals(), + mHaveCachedMov(false), + mCachedMovPoints(), mCachedMovNormals(), + mMovPntsInited(-100.0), mMaxMovPnt(-1), + mcGeoActive(1.) { }; @@ -60,6 +71,11 @@ static int initStringTypes[GEOINIT_STRINGS] = { void ntlGeometryObject::initialize(ntlRenderGlobals *glob) { //debugOut("ntlGeometryObject::initialize: '"<<getName()<<"' ", 10); + // initialize only once... + if(mIsInitialized) return; + + // init material, always necessary + searchMaterial( glob->getMaterials() ); mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"ntlGeometryObject", "mGeoInitId", false); mGeoInitIntersect = mpAttrs->readInt("geoinit_intersect", mGeoInitIntersect,"ntlGeometryObject", "mGeoInitIntersect", false); @@ -74,7 +90,7 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) } if(!gotit) { - errFatal("ntlGeometryObject::initialize","Unkown 'geoinittype' value: '"<< ginitStr <<"' ", SIMWORLD_INITERROR); + errFatal("ntlGeometryObject::initialize","Obj '"<<mName<<"', Unkown 'geoinittype' value: '"<< ginitStr <<"' ", SIMWORLD_INITERROR); return; } } @@ -84,32 +100,77 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) // disable geo init again... mGeoInitId = -1; } - mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false)); + mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false)); + if(getAttributeList()->exists("initial_velocity") || (!mcInitialVelocity.isInited()) ) { + mcInitialVelocity = mpAttrs->readChannelVec3f("initial_velocity"); + } + // always use channel + if(!mcInitialVelocity.isInited()) { mcInitialVelocity = AnimChannel<ntlVec3Gfx>(mInitialVelocity); } + mLocalCoordInivel = mpAttrs->readBool("geoinit_localinivel", mLocalCoordInivel,"ntlGeometryObject", "mLocalCoordInivel", false); + mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false); - debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<< - " gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug + mOnlyThinInit = mpAttrs->readBool("geoinit_onlythin", mOnlyThinInit,"ntlGeometryObject", "mOnlyThinInit", false); // override cfg types mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false); mReceiveShadows = mpAttrs->readBool("recv_shad", mReceiveShadows,"ntlGeometryObject", "mReceiveShadows", false); mCastShadows = mpAttrs->readBool("cast_shad", mCastShadows,"ntlGeometryObject", "mCastShadows", false); - - // init material - searchMaterial( glob->getMaterials() ); + + // read mesh animation channels + ntlVec3d translation(0.0); + translation = mpAttrs->readVec3d("translation", translation,"ntlGeometryObject", "translation", false); + if(getAttributeList()->exists("translation") || (!mcTrans.isInited()) ) { + mcTrans = mpAttrs->readChannelVec3f("translation"); + } + ntlVec3d rotation(0.0); + rotation = mpAttrs->readVec3d("rotation", rotation,"ntlGeometryObject", "rotation", false); + if(getAttributeList()->exists("rotation") || (!mcRot.isInited()) ) { + mcRot = mpAttrs->readChannelVec3f("rotation"); + } + ntlVec3d scale(1.0); + scale = mpAttrs->readVec3d("scale", scale,"ntlGeometryObject", "scale", false); + if(getAttributeList()->exists("scale") || (!mcScale.isInited()) ) { + mcScale = mpAttrs->readChannelVec3f("scale"); + } + + float geoactive=1.; + geoactive = mpAttrs->readFloat("geoactive", geoactive,"ntlGeometryObject", "geoactive", false); + if(getAttributeList()->exists("geoactive") || (!mcGeoActive.isInited()) ) { + mcGeoActive = mpAttrs->readChannelFloat("geoactive"); + } + // always use channel + if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<double>(geoactive); } + + if( (mcTrans.accessValues().size()>1) // VALIDATE + || (mcRot.accessValues().size()>1) + || (mcScale.accessValues().size()>1) + || (mcGeoActive.accessValues().size()>1) + || (mcInitialVelocity.accessValues().size()>1) + ) { + mIsAnimated = true; + } + + mIsInitialized = true; + debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': visible="<<this->mVisible<<" gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<< + " gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug } +/*! notify object that dump is in progress (e.g. for particles) */ +// default action - do nothing... +void ntlGeometryObject::notifyOfDump(int frameNr,char *frameNrStr,string outfilename) { + bool debugOut=false; + if(debugOut) debMsgStd("ntlGeometryObject::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr<<","<<frameNr<<" to "<<outfilename, 10); // DEBUG +} /*****************************************************************************/ /* Search the material for this object from the material list */ /*****************************************************************************/ void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat) { - //errorOut("my: "<<mMaterialName); // DEBUG /* search the list... */ int i=0; for (vector<ntlMaterial*>::iterator iter = mat->begin(); iter != mat->end(); iter++) { - //if(strcmp(mMaterialName, (*iter)->getName()) == 0) { // DEBUG if( mMaterialName == (*iter)->getName() ) { //warnMsg("ntlGeometryObject::searchMaterial","for obj '"<<getName()<<"' found - '"<<(*iter)->getName()<<"' "<<i); // DEBUG mpMaterial = (*iter); @@ -118,8 +179,385 @@ void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat) i++; } errFatal("ntlGeometryObject::searchMaterial","Unknown material '"<<mMaterialName<<"' ! ", SIMWORLD_INITERROR); + mpMaterial = new ntlMaterial(); return; } +/****************************************************************************** + * static add triangle function + *****************************************************************************/ +void ntlGeometryObject::sceneAddTriangle( + ntlVec3Gfx p1,ntlVec3Gfx p2,ntlVec3Gfx p3, + ntlVec3Gfx pn1,ntlVec3Gfx pn2,ntlVec3Gfx pn3, + ntlVec3Gfx trin, bool smooth, + vector<ntlTriangle> *triangles, + vector<ntlVec3Gfx> *vertices, + vector<ntlVec3Gfx> *normals) { + ntlTriangle tri; + int tempVert; + + if(normals->size() != vertices->size()) { + errFatal("ntlGeometryObject::sceneAddTriangle","For '"<<this->mName<<"': Vertices and normals sizes to not match!!!",SIMWORLD_GENERICERROR); + + } else { + + vertices->push_back( p1 ); + normals->push_back( pn1 ); + tempVert = normals->size()-1; + tri.getPoints()[0] = tempVert; + + vertices->push_back( p2 ); + normals->push_back( pn2 ); + tempVert = normals->size()-1; + tri.getPoints()[1] = tempVert; + + vertices->push_back( p3 ); + normals->push_back( pn3 ); + tempVert = normals->size()-1; + tri.getPoints()[2] = tempVert; + + + /* init flags from ntl_ray.h */ + int flag = 0; + if(getVisible()){ flag |= TRI_GEOMETRY; } + if(getCastShadows() ) { + flag |= TRI_CASTSHADOWS; } + if( (getMaterial()->getMirror()>0.0) || + (getMaterial()->getTransparence()>0.0) || + (getMaterial()->getFresnel()>0.0) ) { + flag |= TRI_MAKECAUSTICS; } + else { + flag |= TRI_NOCAUSTICS; } + + /* init geo init id */ + int geoiId = getGeoInitId(); + if((geoiId > 0) && (!mOnlyThinInit) && (!mIsAnimated)) { + flag |= (1<< (geoiId+4)); + flag |= mGeoInitType; + } + /*errMsg("ntlScene::addTriangle","DEBUG flag="<<convertFlags2String(flag) ); */ + tri.setFlags( flag ); + + /* triangle normal missing */ + tri.setNormal( trin ); + tri.setSmoothNormals( smooth ); + tri.setObjectId( this->mObjectId ); + triangles->push_back( tri ); + } /* normals check*/ +} + + + +/******************************************************************************/ +/* Init channels from float arrays (for elbeem API) */ +/******************************************************************************/ + +#define ADD_CHANNEL_VEC(dst,nvals,val) \ + vals.clear(); time.clear(); elbeemSimplifyChannelVec3(val,&nvals); \ + for(int i=0; i<(nvals); i++) { \ + vals.push_back(ntlVec3Gfx((val)[i*4+0], (val)[i*4+1],(val)[i*4+2] )); \ + time.push_back( (val)[i*4+3] ); \ + } \ + (dst) = AnimChannel< ntlVec3Gfx >(vals,time); + +#define ADD_CHANNEL_FLOAT(dst,nvals,val) \ + valsd.clear(); time.clear(); elbeemSimplifyChannelFloat(val,&nvals); \ + for(int i=0; i<(nvals); i++) { \ + valsd.push_back( (val)[i*2+0] ); \ + time.push_back( (val)[i*2+1] ); \ + } \ + (dst) = AnimChannel< double >(valsd,time); + +void ntlGeometryObject::initChannels( + int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale, + int nAct, float *act, int nIvel, float *ivel + ) { + const bool debugInitc=true; + if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"nt:"<<nTrans<<" nr:"<<nRot<<" ns:"<<nScale, 10); + debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"na:"<<nAct<<" niv:"<<nIvel<<" ", 10); } + vector<ntlVec3Gfx> vals; + vector<double> valsd; + vector<double> time; + if((trans)&&(nTrans>0)) { ADD_CHANNEL_VEC(mcTrans, nTrans, trans); } + if((rot)&&(nRot>0)) { ADD_CHANNEL_VEC(mcRot, nRot, rot); } + if((scale)&&(nScale>0)) { ADD_CHANNEL_VEC(mcScale, nScale, scale); } + if((act)&&(nAct>0)) { ADD_CHANNEL_FLOAT(mcGeoActive, nAct, act); } + if((ivel)&&(nIvel>0)) { ADD_CHANNEL_VEC(mcInitialVelocity, nIvel, ivel); } + + if( (mcTrans.accessValues().size()>1) // VALIDATE + || (mcRot.accessValues().size()>1) + || (mcScale.accessValues().size()>1) + || (mcGeoActive.accessValues().size()>1) + || (mcInitialVelocity.accessValues().size()>1) + ) { + mIsAnimated = true; + } + if(debugInitc) { + debMsgStd("ntlGeometryObject::initChannels",DM_MSG,getName()<< + " nt:"<<mcTrans.accessValues().size()<<" nr:"<<mcRot.accessValues().size()<< + " ns:"<<mcScale.accessValues().size()<<" isAnim:"<<mIsAnimated, 10); } + + if(debugInitc) { + std::ostringstream ostr; + ostr << "trans: "; + for(size_t i=0; i<mcTrans.accessValues().size(); i++) { + ostr<<" "<<mcTrans.accessValues()[i]<<"@"<<mcTrans.accessTimes()[i]<<" "; + } ostr<<"; "; + ostr<<"rot: "; + for(size_t i=0; i<mcRot.accessValues().size(); i++) { + ostr<<" "<<mcRot.accessValues()[i]<<"@"<<mcRot.accessTimes()[i]<<" "; + } ostr<<"; "; + ostr<<"scale: "; + for(size_t i=0; i<mcScale.accessValues().size(); i++) { + ostr<<" "<<mcScale.accessValues()[i]<<"@"<<mcScale.accessTimes()[i]<<" "; + } ostr<<"; "; + ostr<<"act: "; + for(size_t i=0; i<mcGeoActive.accessValues().size(); i++) { + ostr<<" "<<mcGeoActive.accessValues()[i]<<"@"<<mcGeoActive.accessTimes()[i]<<" "; + } ostr<<"; "; + ostr<<"ivel: "; + for(size_t i=0; i<mcInitialVelocity.accessValues().size(); i++) { + ostr<<" "<<mcInitialVelocity.accessValues()[i]<<"@"<<mcInitialVelocity.accessTimes()[i]<<" "; + } ostr<<"; "; + debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"Inited "<<ostr.str(),10); + } +} +#undef ADD_CHANNEL + + +/*****************************************************************************/ +/* apply object translation at time t*/ +/*****************************************************************************/ +void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo) { + if( (mcTrans.accessValues().size()>1) // VALIDATE + || (mcRot.accessValues().size()>1) + || (mcScale.accessValues().size()>1) + || (forceTrafo) + || (!mHaveCachedMov) + ) { + // transformation is animated, continue + ntlVec3Gfx pos = mcTrans.get(t); + ntlVec3Gfx scale = mcScale.get(t); + ntlVec3Gfx rot = mcRot.get(t); + ntlMat4Gfx rotMat; + rotMat.initRotationXYZ(rot[0],rot[1],rot[2]); + pos += mInitialPos; + //errMsg("ntlGeometryObject::applyTransformation","obj="<<getName()<<" t"<<pos<<" r"<<rot<<" s"<<scale); + for(int i=vstart; i<vend; i++) { + (*verts)[i] *= scale; + (*verts)[i] = rotMat * (*verts)[i]; + (*verts)[i] += pos; + } + if(norms) { + for(int i=vstart; i<vend; i++) { + (*norms)[i] = rotMat * (*norms)[i]; + } + } + } else { + // not animated, cached points were already returned + errMsg ("ntlGeometryObject::applyTransformation","Object "<<getName()<<" used cached points "); + } +} + +/*! Prepare points for moving objects */ +void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { + if(mMovPntsInited==featureSize) return; + const bool debugMoinit=false; + + vector<ntlTriangle> triangles; + vector<ntlVec3Gfx> vertices; + vector<ntlVec3Gfx> normals; + int objectId = 1; + this->getTriangles(&triangles,&vertices,&normals,objectId); + + mMovPoints.clear(); //= vertices; + mMovNormals.clear(); //= normals; + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" has v:"<<vertices.size()<<" t:"<<triangles.size() ); + // no points? + if(vertices.size()<1) { + mMaxMovPnt=-1; + return; + } + + ntlVec3f maxscale = channelFindMaxVf(mcScale); + float maxpart = ABS(maxscale[0]); + if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]); + if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]); + float scaleFac = 1.0/(maxpart); + // TODO - better reinit from time to time? + const gfxReal fsTri = featureSize*0.5 *scaleFac; + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri ); + + // debug: count points to init + if(debugMoinit) { + errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" estimating..."); + int countp=vertices.size()*2; + for(size_t i=0; i<triangles.size(); i++) { + ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ]; + ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0; + ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0; + int divs1=0, divs2=0; + if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + errMsg("ntlGeometryObject::initMovingPoints","tri:"<<i<<" p:"<<p0<<" s1:"<<side1<<" s2:"<<side2<<" -> "<<divs1<<","<<divs2 ); + if(divs1+divs2 > 0) { + for(int u=0; u<=divs1; u++) { + for(int v=0; v<=divs2; v++) { + const gfxReal uf = (gfxReal)(u+0.25) / (gfxReal)(divs1+0.0); + const gfxReal vf = (gfxReal)(v+0.25) / (gfxReal)(divs2+0.0); + if(uf+vf>1.0) continue; + countp+=2; + } + } + } + } + errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" requires:"<<countp*2); + } + + bool discardInflowBack = false; + if( (mGeoInitType==FGI_MBNDINFLOW) && (mcInitialVelocity.accessValues().size()<1) ) discardInflowBack = true; + discardInflowBack = false; // DEBUG disable for now + + + // init std points + for(size_t i=0; i<vertices.size(); i++) { + ntlVec3Gfx p = vertices[ i ]; + ntlVec3Gfx n = normals[ i ]; + // discard inflow backsides + //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) { + if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) { + if(dot(mInitialVelocity,n)<0.0) continue; + } + mMovPoints.push_back(p); + mMovNormals.push_back(n); + } + // init points & refine... + for(size_t i=0; i<triangles.size(); i++) { + ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ]; + ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0; + ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0; + int divs1=0, divs2=0; + if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + /* if( (i!=6) && + (i!=6) ) { divs1=divs2=0; } // DEBUG */ + if(divs1+divs2 > 0) { + for(int u=0; u<=divs1; u++) { + for(int v=0; v<=divs2; v++) { + const gfxReal uf = (gfxReal)(u+0.25) / (gfxReal)(divs1+0.0); + const gfxReal vf = (gfxReal)(v+0.25) / (gfxReal)(divs2+0.0); + if(uf+vf>1.0) continue; + ntlVec3Gfx p = vertices[ triangles[i].getPoints()[0] ] * (1.0-uf-vf)+ + vertices[ triangles[i].getPoints()[1] ]*uf + + vertices[ triangles[i].getPoints()[2] ]*vf; + ntlVec3Gfx n = normals[ triangles[i].getPoints()[0] ] * (1.0-uf-vf)+ + normals[ triangles[i].getPoints()[1] ]*uf + + normals[ triangles[i].getPoints()[2] ]*vf; + normalize(n); + //if(mGeoInitType==FGI_MBNDINFLOW) { + // discard inflow backsides + if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) { + if(dot(mInitialVelocity,n)<0.0) continue; + } + + mMovPoints.push_back(p); + mMovNormals.push_back(n); + } + } + } + } + + // duplicate insides + size_t mpsize = mMovPoints.size(); + for(size_t i=0; i<mpsize; i++) { + //normalize(normals[i]); + //errMsg("TTAT"," moved:"<<(mMovPoints[i] - mMovPoints[i]*featureSize)<<" org"<<mMovPoints[i]<<" norm"<<mMovPoints[i]<<" fs"<<featureSize); + mMovPoints.push_back(mMovPoints[i] - mMovNormals[i]*0.5*featureSize); + mMovNormals.push_back(mMovNormals[i]); + } + + // find max point + mMaxMovPnt = 0; + gfxReal dist = normNoSqrt(mMovPoints[0]); + for(size_t i=0; i<mpsize; i++) { + if(normNoSqrt(mMovPoints[i])>dist) { + mMaxMovPnt = i; + dist = normNoSqrt(mMovPoints[0]); + } + } + + if( (mcTrans.accessValues().size()>1) // VALIDATE + || (mcRot.accessValues().size()>1) + || (mcScale.accessValues().size()>1) + ) { + // also do trafo... + } else { + mCachedMovPoints = mMovPoints; + mCachedMovNormals = mMovNormals; + applyTransformation(0., &mCachedMovPoints, &mCachedMovNormals, 0, mCachedMovPoints.size(), true); + mHaveCachedMov = true; + debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" cached points ", 7); + } + + mMovPntsInited = featureSize; + debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" inited v:"<<vertices.size()<<"->"<<mMovPoints.size() , 5); +} + +/*! Prepare points for moving objects */ +void ntlGeometryObject::getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms) { + if(mHaveCachedMov) { + ret = mCachedMovPoints; + if(norms) { *norms = mCachedMovNormals; } + errMsg ("ntlGeometryObject::getMovingPoints","Object "<<getName()<<" used cached points "); + return; + } + + ret = mMovPoints; + if(norms) { *norms = mMovNormals; } +} + +/*! Calculate max. velocity on object from t1 to t2 */ +ntlVec3Gfx ntlGeometryObject::calculateMaxVel(double t1, double t2) { + ntlVec3Gfx vel(0.); + if(mMaxMovPnt<0) return vel; + + vector<ntlVec3Gfx> verts1,verts2; + verts1.push_back(mMovPoints[mMaxMovPnt]); + verts2 = verts1; + applyTransformation(t1,&verts1,NULL, 0,verts1.size(), true); + applyTransformation(t2,&verts2,NULL, 0,verts2.size(), true); + + vel = (verts2[0]-verts1[0]); // /(t2-t1); + errMsg("ntlGeometryObject::calculateMaxVel","t1="<<t1<<" t2="<<t2<<" p1="<<verts1[0]<<" p2="<<verts2[0]<<" v="<<vel); + return vel; +} + +/*! get translation at time t*/ +ntlVec3Gfx ntlGeometryObject::getTranslation(double t) { + ntlVec3Gfx pos = mcTrans.get(t); + return pos; +} +/*! get active flag time t*/ +float ntlGeometryObject::getGeoActive(double t) { + //float act = mcGeoActive.getConstant(t); + float act = mcGeoActive.get(t); // if <= 0.0 -> off + return act; +} + +void ntlGeometryObject::setInitialVelocity(ntlVec3Gfx set) { + mInitialVelocity=set; + mcInitialVelocity = AnimChannel<ntlVec3Gfx>(set); +} +ntlVec3Gfx ntlGeometryObject::getInitialVelocity(double t) { + ntlVec3Gfx v = mcInitialVelocity.get(t); //return mInitialVelocity; + if(!mLocalCoordInivel) return v; + + ntlVec3Gfx rot = mcRot.get(t); + ntlMat4Gfx rotMat; + rotMat.initRotationXYZ(rot[0],rot[1],rot[2]); + v = rotMat * v; + return v; +} + diff --git a/intern/elbeem/intern/ntl_geometryobject.h b/intern/elbeem/intern/ntl_geometryobject.h index 71a5566d8eb..157d160c0e4 100644 --- a/intern/elbeem/intern/ntl_geometryobject.h +++ b/intern/elbeem/intern/ntl_geometryobject.h @@ -7,13 +7,14 @@ * all other geometry objects are derived from this one * *****************************************************************************/ -#ifndef NTL_GEOMETRYOBJECT_HH +#ifndef NTL_GEOMETRYOBJECT_H +#define NTL_GEOMETRYOBJECT_H #include "ntl_geometryclass.h" -#include "ntl_material.h" -#include "ntl_triangle.h" -class ntlRay; +#include "ntl_lighting.h" +#include "ntl_ray.h" class ntlRenderGlobals; +class ntlTriangle; class ntlGeometryObject : public ntlGeometryClass @@ -28,13 +29,16 @@ class ntlGeometryObject : public ntlGeometryClass //! Return type id virtual int getTypeId() { return GEOCLASSTID_OBJECT; } + /*! Init attributes etc. of this object */ + virtual void initialize(ntlRenderGlobals *glob); + /*! Get the triangles from this object */ virtual void getTriangles( vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) = 0; - - /*! Init attributes etc. of this object */ - virtual void initialize(ntlRenderGlobals *glob); + + /*! notify object that dump is in progress (e.g. for particles) */ + virtual void notifyOfDump(int frameNr,char *frameNrStr,string outfilename); /*! Search the material for this object from the material list */ void searchMaterial(vector<ntlMaterial *> *mat); @@ -68,20 +72,64 @@ class ntlGeometryObject : public ntlGeometryClass /*! Returns the geo init typ */ inline int getGeoInitType() const { return mGeoInitType; } - /*! Set/get the cast initial veocity attribute */ - inline void setInitialVelocity(ntlVec3Gfx set) { mInitialVelocity=set; } - inline ntlVec3Gfx getInitialVelocity() const { return mInitialVelocity; } - /*! Set/get the intersect init flag */ inline bool getGeoInitIntersect() const { return mGeoInitIntersect; } inline void setGeoInitIntersect(bool set) { mGeoInitIntersect=set; } /*! Set/get the part slip value*/ - inline bool getGeoPartSlipValue() const { return mGeoPartSlipValue; } + inline float getGeoPartSlipValue() const { return mGeoPartSlipValue; } inline void setGeoPartSlipValue(float set) { mGeoPartSlipValue=set; } + /*! Set/get the part slip value*/ + inline bool getOnlyThinInit() const { return mOnlyThinInit; } + inline void setOnlyThinInit(float set) { mOnlyThinInit=set; } + + /*! Set/get the cast initial veocity attribute */ + void setInitialVelocity(ntlVec3Gfx set); + ntlVec3Gfx getInitialVelocity(double t); + + /*! Set/get the local inivel coords flag */ + inline bool getLocalCoordInivel() const { return mLocalCoordInivel; } + inline void setLocalCoordInivel(bool set) { mLocalCoordInivel=set; } + + /*! Init channels from float arrays (for elbeem API) */ + void initChannels( + int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale, + int nAct, float *act, int nIvel, float *ivel + ); + + /*! is the object animated? */ + inline bool getIsAnimated() const { return mIsAnimated; } + + /*! apply object translation at time t*/ + void applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo); + + /*! Prepare points for moving objects */ + void initMovingPoints(gfxReal featureSize); + /*! Prepare points for moving objects (copy into ret) */ + void getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms = NULL); + /*! Calculate max. velocity on object from t1 to t2 */ + ntlVec3Gfx calculateMaxVel(double t1, double t2); + /*! get translation at time t*/ + ntlVec3Gfx getTranslation(double t); + /*! get active flag time t*/ + float getGeoActive(double t); + + /*! add triangle to scene and init flags */ + // helper function for getTriangles + void sceneAddTriangle( + ntlVec3Gfx p1,ntlVec3Gfx p2,ntlVec3Gfx p3, + ntlVec3Gfx pn1,ntlVec3Gfx pn2,ntlVec3Gfx pn3, + ntlVec3Gfx trin, bool smooth, + vector<ntlTriangle> *triangles, + vector<ntlVec3Gfx> *vertices, + vector<ntlVec3Gfx> *vertNormals); + protected: + /* initialized for scene? */ + bool mIsInitialized; + /*! Point to a property object describing the surface of this object */ ntlMaterial *mpMaterial; @@ -100,15 +148,41 @@ class ntlGeometryObject : public ntlGeometryClass int mGeoInitType; /*! initial velocity for fluid objects */ ntlVec3Gfx mInitialVelocity; + AnimChannel<ntlVec3Gfx> mcInitialVelocity; + /*! use object local inflow? */ + bool mLocalCoordInivel; /*! perform more accurate intersecting geo init for this object? */ bool mGeoInitIntersect; /*! part slip bc value */ float mGeoPartSlipValue; + /*! only init as thin object, dont fill? */ + bool mOnlyThinInit; + + /*! initial offset for rot/scale */ + ntlVec3Gfx mInitialPos; + /*! animated channels for postition, rotation and scale */ + AnimChannel<ntlVec3Gfx> mcTrans, mcRot, mcScale; + /*! easy check for animation */ + bool mIsAnimated; + + /*! moving point/normal storage */ + vector<ntlVec3Gfx> mMovPoints; + vector<ntlVec3Gfx> mMovNormals; + /*! cached points for non moving objects/timeslots */ + bool mHaveCachedMov; + vector<ntlVec3Gfx> mCachedMovPoints; + vector<ntlVec3Gfx> mCachedMovNormals; + /*! inited? */ + float mMovPntsInited; + /*! point with max. distance from center */ + int mMaxMovPnt; + + /*! animated channels for in/outflow on/off */ + AnimChannel<double> mcGeoActive; public: }; -#define NTL_GEOMETRYOBJECT_HH #endif diff --git a/intern/elbeem/intern/ntl_geometryshader.h b/intern/elbeem/intern/ntl_geometryshader.h index 06a11838149..7d767b0f8b9 100644 --- a/intern/elbeem/intern/ntl_geometryshader.h +++ b/intern/elbeem/intern/ntl_geometryshader.h @@ -38,6 +38,9 @@ class ntlGeometryShader : virtual vector<ntlGeometryObject *>::iterator getObjectsBegin() { return mObjects.begin(); } /*! Get end iterator for all objects */ virtual vector<ntlGeometryObject *>::iterator getObjectsEnd() { return mObjects.end(); } + + /*! notify object that dump is in progress (e.g. for field dump) */ + virtual void notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename) = 0; protected: diff --git a/intern/elbeem/intern/ntl_lightobject.cpp b/intern/elbeem/intern/ntl_lighting.cpp index c8db66bab74..d4eae7051e0 100644 --- a/intern/elbeem/intern/ntl_lightobject.cpp +++ b/intern/elbeem/intern/ntl_lighting.cpp @@ -8,10 +8,9 @@ *****************************************************************************/ -#include "ntl_lightobject.h" +#include "ntl_lighting.h" #include "ntl_ray.h" -#include "ntl_scene.h" -#include "ntl_renderglobals.h" +#include "ntl_world.h" /****************************************************************************** @@ -126,7 +125,7 @@ ntlColor ntlLightObject::illuminatePoint(ntlRay &reflectedRay, ntlGeometryObject ntlTriangle *tri; ntlVec3Gfx triNormal; gfxReal trit; - mpGlob->getScene()->intersectScene(rayOfLight, trit, triNormal, tri, TRI_CASTSHADOWS); + mpGlob->getRenderScene()->intersectScene(rayOfLight, trit, triNormal, tri, TRI_CASTSHADOWS); if(( trit>0 )&&( trit<lightDirNorm )) visibility = 0.0; if(mpGlob->getDebugOut() > 5) errorOut("Omni lighting with "<<visibility ); } @@ -142,3 +141,42 @@ ntlColor ntlLightObject::illuminatePoint(ntlRay &reflectedRay, ntlGeometryObject } + +/****************************************************************************** + * Default constructor + *****************************************************************************/ +ntlMaterial::ntlMaterial( void ) : + mName( "default" ), + mDiffuseRefl(0.5,0.5,0.5), mAmbientRefl(0.0,0.0,0.0), + mSpecular(0.0), mSpecExponent(0.0), mMirror(0.0), + mTransparence(0.0), mRefracIndex(0.0), mTransAdditive(0.0), mTransAttCol(0.0), + mFresnel( 0 ) + //mNtfId(0), mNtfFluid(0), mNtfSolid(0) +{ + // just do default init... +} + + + +/****************************************************************************** + * Init constructor + *****************************************************************************/ +ntlMaterial::ntlMaterial( string name, + const ntlColor& Ref, const ntlColor& Amb, + gfxReal Spec, gfxReal SpecEx, gfxReal Mirr, + gfxReal Trans, gfxReal Refrac, gfxReal TAdd, + const ntlColor& Att, int fres) +{ + mName = name; + mDiffuseRefl = Ref; + mAmbientRefl = Amb; + mSpecular = Spec; + mSpecExponent = SpecEx; + mMirror = Mirr; + mTransparence = Trans; + mRefracIndex = Refrac; + mTransAdditive = TAdd; + mTransAttCol = Att; + mFresnel = fres; +} + diff --git a/intern/elbeem/intern/ntl_material.h b/intern/elbeem/intern/ntl_lighting.h index 41bfd167bb2..af53a13ebc7 100644 --- a/intern/elbeem/intern/ntl_material.h +++ b/intern/elbeem/intern/ntl_lighting.h @@ -3,15 +3,89 @@ * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method * Copyright 2003,2004 Nils Thuerey * - * a geometry object - * all other geometry objects are derived from this one + * a light object + * default omni light implementation * *****************************************************************************/ -#ifndef NTL_MATERIAL_HH -#define NTL_MATERIAL_HH +#ifndef NTL_LIGHTING_H +#define NTL_LIGHTING_H #include "ntl_vector3dim.h" +class ntlMaterial; class ntlRay; +class ntlRenderGlobals; +class ntlGeometryObject; + + + +/* shadow map directions */ +#define LSM_RIGHT 0 +#define LSM_LEFT 1 +#define LSM_UP 2 +#define LSM_DOWN 3 +#define LSM_FRONT 4 +#define LSM_BACK 5 + +/*! Basic object for lights, all other light are derived from this one */ +class ntlLightObject +{ +public: + /* CONSTRUCTORS */ + /*! Default constructor */ + ntlLightObject(ntlRenderGlobals *glob); + /*! Constructor with parameters */ + ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col); + /*! Destructor */ + virtual ~ntlLightObject(); + + /*! prepare light for rendering (for example shadow maps) */ + virtual void prepare( bool ); + + /*! do the illumination... */ + virtual ntlColor illuminatePoint(ntlRay &reflectedRay, + ntlGeometryObject *closest, + ntlColor &highlight); + /*! shade the point */ + const ntlColor + getShadedColor(const ntlRay &reflectedray, ntlVec3Gfx lightDir, + ntlMaterial *surf, ntlColor &highlight) const; + + + /* access methods */ + /*! Access the active flag */ + inline void setActive(bool set) { mActive = set; } + inline bool getActive() const { return mActive; } + /*! Access the shadow flag */ + inline void setCastShadows(bool set) { mCastShadows = set; } + inline bool getCastShadows() const { return mCastShadows; } + /*! Access the light color */ + inline void setColor(ntlColor set) { mcColor = set; } + inline ntlColor getColor() const { return mcColor; } + + /*! Access the omni light position */ + void setPosition(ntlVec3Gfx set) { mvPosition = set; } + ntlVec3Gfx getPosition() const { return mvPosition; } + + +protected: + /*! render globals */ + ntlRenderGlobals *mpGlob; + + /*! is this light acitve? */ + bool mActive; + + /*! does it cast shadows? */ + bool mCastShadows; + + /*! color of this light */ + ntlColor mcColor; + + /*! light position */ + ntlVec3Gfx mvPosition; + +private: + +}; //! Properties of an geo object, describing the reflection properties of the surface @@ -20,12 +94,12 @@ class ntlMaterial public: // CONSTRUCTORS //! Default constructor - inline ntlMaterial( void ); + ntlMaterial( void ); //! Constructor with parameters /*! Sets reflectance, ambient reflection, specular intensity * specular exponent, mirror intensity * transparency, refraction index */ - inline ntlMaterial( string name, + ntlMaterial( string name, const ntlColor& Ref, const ntlColor& Amb, gfxReal Spec, gfxReal Exp, gfxReal Mirror, gfxReal Trans, gfxReal Refrac, gfxReal TAdd, @@ -121,47 +195,6 @@ public: }; - - -/****************************************************************************** - * Default constructor - *****************************************************************************/ -inline ntlMaterial::ntlMaterial( void ) : - mName( "default" ), - mDiffuseRefl(0.5,0.5,0.5), mAmbientRefl(0.0,0.0,0.0), - mSpecular(0.0), mSpecExponent(0.0), mMirror(0.0), - mTransparence(0.0), mRefracIndex(0.0), mTransAdditive(0.0), mTransAttCol(0.0), - mFresnel( 0 ) - //mNtfId(0), mNtfFluid(0), mNtfSolid(0) -{ - // just do default init... -} - - - -/****************************************************************************** - * Init constructor - *****************************************************************************/ -inline -ntlMaterial::ntlMaterial( string name, - const ntlColor& Ref, const ntlColor& Amb, - gfxReal Spec, gfxReal SpecEx, gfxReal Mirr, - gfxReal Trans, gfxReal Refrac, gfxReal TAdd, - const ntlColor& Att, int fres) -{ - mName = name; - mDiffuseRefl = Ref; - mAmbientRefl = Amb; - mSpecular = Spec; - mSpecExponent = SpecEx; - mMirror = Mirr; - mTransparence = Trans; - mRefracIndex = Refrac; - mTransAdditive = TAdd; - mTransAttCol = Att; - mFresnel = fres; -} - /****************************************************************************** * Macro to define the default surface properties for a newly created object *****************************************************************************/ @@ -201,3 +234,5 @@ ntlMaterial::calculateFresnel(const ntlVec3Gfx &dir, const ntlVec3Gfx &normal, g #endif + + diff --git a/intern/elbeem/intern/ntl_lightobject.h b/intern/elbeem/intern/ntl_lightobject.h deleted file mode 100644 index 19dde8829a1..00000000000 --- a/intern/elbeem/intern/ntl_lightobject.h +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * a light object - * default omni light implementation - * - *****************************************************************************/ -#ifndef NTL_LIGHTOBJECT_HH -#define NTL_LIGHTOBJECT_HH - -#include "ntl_vector3dim.h" -#include "ntl_material.h" -class ntlRay; -class ntlRenderGlobals; -class ntlGeometryObject; - - - -/* shadow map directions */ -#define LSM_RIGHT 0 -#define LSM_LEFT 1 -#define LSM_UP 2 -#define LSM_DOWN 3 -#define LSM_FRONT 4 -#define LSM_BACK 5 - -/*! Basic object for lights, all other light are derived from this one */ -class ntlLightObject -{ -public: - /* CONSTRUCTORS */ - /*! Default constructor */ - ntlLightObject(ntlRenderGlobals *glob); - /*! Constructor with parameters */ - ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col); - /*! Destructor */ - virtual ~ntlLightObject(); - - /*! prepare light for rendering (for example shadow maps) */ - virtual void prepare( bool ); - - /*! do the illumination... */ - virtual ntlColor illuminatePoint(ntlRay &reflectedRay, - ntlGeometryObject *closest, - ntlColor &highlight); - /*! shade the point */ - const ntlColor - getShadedColor(const ntlRay &reflectedray, ntlVec3Gfx lightDir, - ntlMaterial *surf, ntlColor &highlight) const; - - - /* access methods */ - /*! Access the active flag */ - inline void setActive(bool set) { mActive = set; } - inline bool getActive() const { return mActive; } - /*! Access the shadow flag */ - inline void setCastShadows(bool set) { mCastShadows = set; } - inline bool getCastShadows() const { return mCastShadows; } - /*! Access the light color */ - inline void setColor(ntlColor set) { mcColor = set; } - inline ntlColor getColor() const { return mcColor; } - - /*! Access the omni light position */ - void setPosition(ntlVec3Gfx set) { mvPosition = set; } - ntlVec3Gfx getPosition() const { return mvPosition; } - - -protected: - /*! render globals */ - ntlRenderGlobals *mpGlob; - - /*! is this light acitve? */ - bool mActive; - - /*! does it cast shadows? */ - bool mCastShadows; - - /*! color of this light */ - ntlColor mcColor; - - /*! light position */ - ntlVec3Gfx mvPosition; - -private: - -}; - -#endif - diff --git a/intern/elbeem/intern/ntl_matrices.h b/intern/elbeem/intern/ntl_matrices.h index 8a70dceb1c7..7d27a6e7c7a 100644 --- a/intern/elbeem/intern/ntl_matrices.h +++ b/intern/elbeem/intern/ntl_matrices.h @@ -77,9 +77,12 @@ public: inline void initRotationX(Scalar rot); inline void initRotationY(Scalar rot); inline void initRotationZ(Scalar rot); + inline void initRotationXYZ(Scalar rotx,Scalar roty, Scalar rotz); //! init scaling matrix inline void initScaling(Scalar scale); inline void initScaling(Scalar x, Scalar y, Scalar z); + //! from 16 value array (init id if all 0) + inline void initArrayCheck(Scalar *array); //! public to avoid [][] operators Scalar value[4][4]; //< Storage of vector values @@ -593,8 +596,8 @@ template<class Scalar> inline void ntlMatrix4x4<Scalar>::initRotationX(Scalar rot) { - double drot = (double)rot; - while(drot < 0.0) drot += (M_PI*2.0); + double drot = (double)(rot/360.0*2.0*M_PI); + //? while(drot < 0.0) drot += (M_PI*2.0); this->initId(); value[1][1] = (Scalar) cos(drot); @@ -606,8 +609,8 @@ template<class Scalar> inline void ntlMatrix4x4<Scalar>::initRotationY(Scalar rot) { - double drot = (double)rot; - while(drot < 0.0) drot += (M_PI*2.0); + double drot = (double)(rot/360.0*2.0*M_PI); + //? while(drot < 0.0) drot += (M_PI*2.0); this->initId(); value[0][0] = (Scalar) cos(drot); @@ -619,8 +622,8 @@ template<class Scalar> inline void ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot) { - double drot = (double)rot; - while(drot < 0.0) drot += (M_PI*2.0); + double drot = (double)(rot/360.0*2.0*M_PI); + //? while(drot < 0.0) drot += (M_PI*2.0); this->initId(); value[0][0] = (Scalar) cos(drot); @@ -628,6 +631,32 @@ ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot) value[1][0] = (Scalar)(-sin(drot)); value[1][1] = (Scalar) cos(drot); } +template<class Scalar> +inline void +ntlMatrix4x4<Scalar>::initRotationXYZ( Scalar rotx, Scalar roty, Scalar rotz) +{ + ntlMatrix4x4<Scalar> val; + ntlMatrix4x4<Scalar> rot; + this->initId(); + + // org + /*rot.initRotationX(rotx); + (*this) *= rot; + rot.initRotationY(roty); + (*this) *= rot; + rot.initRotationZ(rotz); + (*this) *= rot; + // org */ + + // blender + rot.initRotationZ(rotz); + (*this) *= rot; + rot.initRotationY(roty); + (*this) *= rot; + rot.initRotationX(rotx); + (*this) *= rot; + // blender */ +} //! init scaling matrix template<class Scalar> @@ -651,6 +680,20 @@ ntlMatrix4x4<Scalar>::initScaling(Scalar x, Scalar y, Scalar z) } +//! from 16 value array (init id if all 0) +template<class Scalar> +inline void +ntlMatrix4x4<Scalar>::initArrayCheck(Scalar *array) +{ + bool allZero = true; + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + value[i][j] = array[i*4+j]; + if(array[i*4+j]!=0.0) allZero=false; + } + } + if(allZero) this->initId(); +} #define NTL_MATRICES_H diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp index ed5f96a4541..5df9c0068f9 100644 --- a/intern/elbeem/intern/ntl_ray.cpp +++ b/intern/elbeem/intern/ntl_ray.cpp @@ -8,8 +8,11 @@ *****************************************************************************/ +#include "utilities.h" #include "ntl_ray.h" -#include "ntl_scene.h" +#include "ntl_world.h" +#include "ntl_geometryobject.h" +#include "ntl_geometryshader.h" /* Minimum value for refl/refr to be traced */ @@ -116,7 +119,7 @@ ntlRay::~ntlRay() #define MIDDLE 2 //! intersect ray with AABB -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN void ntlRay::intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const { char inside = true; /* inside box? */ @@ -288,7 +291,7 @@ void ntlRay::intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, n retnormal = normal; retcoord = coord; } -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN //! intersect ray with AABB void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const @@ -441,7 +444,7 @@ void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal & *****************************************************************************/ const ntlColor ntlRay::shade() //const { -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN ntlGeometryObject *closest = NULL; gfxReal minT = GFX_REAL_MAX; vector<ntlLightObject*> *lightlist = mpGlob->getLightList(); @@ -457,9 +460,9 @@ const ntlColor ntlRay::shade() //const /* find closes object that intersects */ ntlTriangle *tri = NULL; ntlVec3Gfx normal; - mpGlob->getScene()->intersectScene(*this, minT, normal, tri, 0); + mpGlob->getRenderScene()->intersectScene(*this, minT, normal, tri, 0); if(minT>0) { - closest = mpGlob->getScene()->getObject( tri->getObjectId() ); + closest = mpGlob->getRenderScene()->getObject( tri->getObjectId() ); } /* object hit... */ @@ -481,7 +484,7 @@ const ntlColor ntlRay::shade() //const ntlMaterial *clossurf = closest->getMaterial(); /*if(mpGlob->getDebugOut() > 5) { errorOut("Ray hit: at "<<intersectionPosition<<" n:"<<normal<<" dn:"<<valDN<<" ins:"<<intersectionInside<<" cl:"<<((unsigned int)closest) ); - errorOut(" t1:"<<mpGlob->getScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) ); + errorOut(" t1:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) ); errorOut(" trin:"<<tri->getNormal() ); } // debug */ @@ -559,9 +562,9 @@ const ntlColor ntlRay::shade() //const refractionPosition2 -= (triangleNormal*getVecEpsilon() ); ntlRay reflectedRay2 = ntlRay(refractionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob); - mpGlob->getScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0); + mpGlob->getRenderScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0); if(minT2>0) { - closest2 = mpGlob->getScene()->getObject( tri2->getObjectId() ); + closest2 = mpGlob->getRenderScene()->getObject( tri2->getObjectId() ); } /* object hit... */ @@ -649,13 +652,254 @@ const ntlColor ntlRay::shade() //const return ntlColor(currentColor); } -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN /* no object hit -> ray goes to infinity */ return mpGlob->getBackgroundCol(); } +/****************************************************************************** + ****************************************************************************** + ****************************************************************************** + * scene implementation + ****************************************************************************** + ****************************************************************************** + *****************************************************************************/ + + + +/****************************************************************************** + * Constructor + *****************************************************************************/ +ntlScene::ntlScene( ntlRenderGlobals *glob, bool del ) : + mpGlob( glob ), mSceneDel(del), + mpTree( NULL ), + mDisplayListId( -1 ), + mSceneBuilt( false ), mFirstInitDone( false ) +{ +} + + +/****************************************************************************** + * Destructor + *****************************************************************************/ +ntlScene::~ntlScene() +{ + if(mpTree != NULL) delete mpTree; + + // cleanup lists, only if this is the rendering cleanup scene + if(mSceneDel) { + for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); + iter != mGeos.end(); iter++) { + //errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() ); + delete (*iter); + } + for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin(); + iter != mpGlob->getLightList()->end(); iter++) { + delete (*iter); + } + for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); + iter != mpGlob->getMaterials()->end(); iter++) { + delete (*iter); + } + } + errMsg("ntlScene::~ntlScene","Deleted, ObjFree:"<<mSceneDel); +} + + +/****************************************************************************** + * Build the scene arrays (obj, tris etc.) + *****************************************************************************/ +void ntlScene::buildScene(double time,bool firstInit) +{ + const bool buildInfo=true; + + if(firstInit) { + mObjects.clear(); + /* init geometry array, first all standard objects */ + for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); + iter != mGeos.end(); iter++) { + bool geoinit = false; + int tid = (*iter)->getTypeId(); + if(tid & GEOCLASSTID_OBJECT) { + ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter); + geoinit = true; + mObjects.push_back( geoobj ); + if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName()<<" Id:"<<geoobj->getObjectId(), 5 ); + } + //if(geoshad) { + if(tid & GEOCLASSTID_SHADER) { + ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); + geoinit = true; + if(!mFirstInitDone) { + // only on first init + geoshad->initializeShader(); + } + for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin(); + siter != geoshad->getObjectsEnd(); + siter++) { + if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName()<<" Id:"<<(*siter)->getObjectId(), 5 ); + mObjects.push_back( (*siter) ); + } + } + + if(!geoinit) { + errFatal("ntlScene::BuildScene","Invalid geometry class!", SIMWORLD_INITERROR); + return; + } + } + } + + // collect triangles + mTriangles.clear(); + mVertices.clear(); + mVertNormals.clear(); + + /* for test mode deactivate transparencies etc. */ + if( mpGlob->getTestMode() ) { + debugOut("ntlScene::buildScene : Test Mode activated!", 2); + // assign random colors to dark materials + int matCounter = 0; + ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) }; + int stdColNum = 4; + for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); + iter != mpGlob->getMaterials()->end(); iter++) { + (*iter)->setTransparence(0.0); + (*iter)->setMirror(0.0); + (*iter)->setFresnel(false); + // too dark? + if( norm((*iter)->getDiffuseRefl()) <0.01) { + (*iter)->setDiffuseRefl( stdCols[matCounter] ); + matCounter ++; + matCounter = matCounter%stdColNum; + } + } + + // restrict output file size to 400 + float downscale = 1.0; + if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); } + if(mpGlob->getResY() > 400){ + float downscale2 = 400.0/(float)mpGlob->getResY(); + if(downscale2<downscale) downscale=downscale2; + } + mpGlob->setResX( (int)(mpGlob->getResX() * downscale) ); + mpGlob->setResY( (int)(mpGlob->getResY() * downscale) ); + + } + + /* collect triangles from objects */ + int idCnt = 0; // give IDs to objects + bool debugTriCollect = false; + if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Start...",5); + for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); + iter != mObjects.end(); + iter++) { + /* only add visible objects */ + if(firstInit) { + if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collect init of "<<(*iter)->getName()<<" idCnt:"<<idCnt, 4 ); + (*iter)->initialize( mpGlob ); } + if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collecting tris from "<<(*iter)->getName(), 4 ); + + int vstart = mVertNormals.size(); + (*iter)->setObjectId(idCnt); + (*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt); + (*iter)->applyTransformation(time, &mVertices, &mVertNormals, vstart, mVertices.size(), false ); + + if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Done with "<<(*iter)->getName()<<" totTris:"<<mTriangles.size()<<" totVerts:"<<mVertices.size()<<" totNorms:"<<mVertNormals.size(), 4 ); + idCnt ++; + } + if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"End",5); + + + /* calculate triangle normals, and initialize flags */ + for (vector<ntlTriangle>::iterator iter = mTriangles.begin(); + iter != mTriangles.end(); + iter++) { + + // calculate normal from triangle points + ntlVec3Gfx normal = + cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right?? + (ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) ); + normalize(normal); + (*iter).setNormal( normal ); + } + + + + // scene geometry built + mSceneBuilt = true; + + // init shaders that require complete geometry + if(!mFirstInitDone) { + // only on first init + for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); + iter != mGeos.end(); iter++) { + if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) { + ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); + geoshad->postGeoConstrInit( mpGlob ); + } + } + mFirstInitDone = true; + } + + // check unused attributes (for classes and objects!) + for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) { + if((*iter)->getAttributeList()->checkUnusedParams()) { + (*iter)->getAttributeList()->print(); // DEBUG + errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); + return; + } + } + for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) { + if((*iter)->getAttributeList()->checkUnusedParams()) { + (*iter)->getAttributeList()->print(); // DEBUG + errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); + return; + } + } + +} + +/****************************************************************************** + * Prepare the scene triangles and maps for raytracing + *****************************************************************************/ +void ntlScene::prepareScene(double time) +{ + /* init triangles... */ + buildScene(time, false); + // what for currently not used ??? + if(mpTree != NULL) delete mpTree; + mpTree = new ntlTree( mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(), + this, TRI_GEOMETRY ); + + //debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 ); +} +/****************************************************************************** + * Do some memory cleaning, when frame is finished + *****************************************************************************/ +void ntlScene::cleanupScene( void ) +{ + mTriangles.clear(); + mVertices.clear(); + mVertNormals.clear(); + + if(mpTree != NULL) delete mpTree; + mpTree = NULL; +} + + +/****************************************************************************** + * Intersect a ray with the scene triangles + *****************************************************************************/ +void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const +{ + distance = -1.0; + mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 ); + mpTree->intersect(r, distance, normal, tri, flags, false); +} + + diff --git a/intern/elbeem/intern/ntl_ray.h b/intern/elbeem/intern/ntl_ray.h index 71fac128e26..716a620bfab 100644 --- a/intern/elbeem/intern/ntl_ray.h +++ b/intern/elbeem/intern/ntl_ray.h @@ -6,14 +6,20 @@ * ray class * *****************************************************************************/ -#ifndef NTL_RAY_HH -#define NTL_RAY_HH +#ifndef NTL_RAY_H +#define NTL_RAY_H +#include <sstream> #include "ntl_vector3dim.h" -#include "ntl_lightobject.h" +#include "ntl_lighting.h" #include "ntl_geometryobject.h" -#include "ntl_renderglobals.h" +#include "ntl_bsptree.h" +class ntlTriangle; +class ntlRay; +class ntlTree; +class ntlScene; +class ntlRenderGlobals; //! store data for an intersection of a ray and a triangle // NOT YET USED @@ -131,12 +137,279 @@ private: }; - +/****************************************************************************** + * + * a single triangle + * + *****************************************************************************/ // triangle intersection code in bsptree.cpp // intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v); -// ... +/*! Triangle flag defines */ +#define TRI_GEOMETRY (1<<0) +#define TRI_CASTSHADOWS (1<<1) +#define TRI_MAKECAUSTICS (1<<2) +#define TRI_NOCAUSTICS (1<<3) + + +class ntlTriangle +{ +public: + /* CONSTRUCTORS */ + /*! Default constructor */ + inline ntlTriangle( void ); + /*! Constructor with parameters */ + inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags); + /*! Copy - Constructor */ + inline ntlTriangle(const ntlTriangle &tri); + /*! Destructor */ + inline ~ntlTriangle() {} + + /* Access methods */ + + /*! Acces to points of triangle */ + inline int *getPoints( void ) { return mPoints; } + /*! Acces normal smoothing */ + inline bool getSmoothNormals( void ) const { return mSmoothNormals; } + inline void setSmoothNormals( bool set){ mSmoothNormals = set; } + /*! Access object */ + inline int getObjectId( void ) const { return mObjectId; } + inline void setObjectId( int set) { mObjectId = set; } + /*! Acces normal index */ + inline ntlVec3Gfx getNormal( void ) const { return mNormal; } + inline void setNormal( ntlVec3Gfx set ) { mNormal = set; } + /*! Acces flags */ + inline int getFlags( void ) const { return mFlags; } + inline void setFlags( int set ) { mFlags = set; } + /*! Access last intersection ray ID */ + inline int getLastRay( void ) const { return mLastRay; } + inline void setLastRay( int set ) { mLastRay = set; } + /*! Acces bbox id */ + inline int getBBoxId( void ) const { return mBBoxId; } + inline void setBBoxId( int set ) { mBBoxId = set; } + + /*! Get average of the three points for this axis */ + inline gfxReal getAverage( int axis ) const; + + /*! operator < for sorting, uses global sorting axis */ + inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs); + /*! operator > for sorting, uses global sorting axis */ + inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs); + +protected: + +private: + + /*! indices to the three points of the triangle */ + int mPoints[3]; + + /*! bounding box id (for tree generation), -1 if invalid */ + int mBBoxId; + + /*! Should the normals of this triangle get smoothed? */ + bool mSmoothNormals; + + /*! Id of parent object */ + int mObjectId; + + /*! Index to normal (for not smooth triangles) */ + //int mNormalIndex; ?? + ntlVec3Gfx mNormal; + + /*! Flags for object attributes cast shadows, make caustics etc. */ + int mFlags; + + /*! ID of last ray that an intersection was calculated for */ + int mLastRay; + +}; + + + + +/****************************************************************************** + * Default Constructor + *****************************************************************************/ +ntlTriangle::ntlTriangle( void ) : + mBBoxId(-1), + mLastRay( 0 ) +{ + mPoints[0] = mPoints[1] = mPoints[2] = 0; + mSmoothNormals = 0; + mObjectId = 0; + mNormal = ntlVec3Gfx(0.0); + mFlags = 0; +} + + +/****************************************************************************** + * Constructor + *****************************************************************************/ +ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) : + mBBoxId(-1), + mLastRay( 0 ) +{ + mPoints[0] = p[0]; + mPoints[1] = p[1]; + mPoints[2] = p[2]; + mSmoothNormals = smooth; + mObjectId = obj; + mNormal = norm; + mFlags = setflags; +} + + +/****************************************************************************** + * Copy Constructor + *****************************************************************************/ +ntlTriangle::ntlTriangle(const ntlTriangle &tri) : + mBBoxId(-1), + mLastRay( 0 ) +{ + mPoints[0] = tri.mPoints[0]; + mPoints[1] = tri.mPoints[1]; + mPoints[2] = tri.mPoints[2]; + mSmoothNormals = tri.mSmoothNormals; + mObjectId = tri.mObjectId; + mNormal = tri.mNormal; + mFlags = tri.mFlags; +} + + + + +/****************************************************************************** + * Triangle sorting functions + *****************************************************************************/ + +/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */ +/* Static global variable for sorting direction */ +extern int globalSortingAxis; +/* Access to points array for sorting */ +extern vector<ntlVec3Gfx> *globalSortingPoints; + + +gfxReal ntlTriangle::getAverage( int axis ) const +{ + return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] + + (*globalSortingPoints)[ mPoints[1] ][axis] + + (*globalSortingPoints)[ mPoints[2] ][axis] )/3.0); +} + +bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs) +{ + return ( lhs.getAverage(globalSortingAxis) < + rhs.getAverage(globalSortingAxis) ); +} + +bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs) +{ + return ( lhs.getAverage(globalSortingAxis) > + rhs.getAverage(globalSortingAxis) ); +} + + + +/****************************************************************************** + * + * Scene object, that contains and manages all geometry objects + * + *****************************************************************************/ + + + +class ntlScene +{ +public: + /* CONSTRUCTORS */ + /*! Default constructor */ + ntlScene( ntlRenderGlobals *glob, bool del=true ); + /*! Default destructor */ + ~ntlScene(); + + /*! Add an object to the scene */ + inline void addGeoClass(ntlGeometryClass *geo) { + mGeos.push_back( geo ); + geo->setObjectId(mGeos.size()); + } + + /*! Acces a certain object */ + inline ntlGeometryObject *getObject(int id) { + if(!mSceneBuilt) { errMsg("ntlScene::getObject","Scene not inited!"); return NULL; } + return mObjects[id]; } + + /*! Acces object array */ + inline vector<ntlGeometryObject*> *getObjects() { + if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; } + return &mObjects; } + + /*! Acces geo class array */ + inline vector<ntlGeometryClass*> *getGeoClasses() { + if(!mSceneBuilt) { errMsg("ntlScene::getGeoClasses[]","Scene not inited!"); return NULL; } + return &mGeos; } + + /*! draw scene with opengl */ + //void draw(); + + /*! Build/first init the scene arrays */ + void buildScene(double time, bool firstInit); + + //! Prepare the scene triangles and maps for raytracing + void prepareScene(double time); + //! Do some memory cleaning, when frame is finished + void cleanupScene( void ); + + /*! Intersect a ray with the scene triangles */ + void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const; + + /*! return a vertex */ + ntlVec3Gfx getVertex(int index) { return mVertices[index]; } + + // for tree generation + /*! return pointer to vertices vector */ + vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; } + /*! return pointer to vertices vector */ + vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; } + /*! return pointer to vertices vector */ + vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; } + +private: + + /*! Global settings */ + ntlRenderGlobals *mpGlob; + + /*! free objects? (only necessary for render scene, which contains all) */ + bool mSceneDel; + + /*! List of geometry classes */ + vector<ntlGeometryClass *> mGeos; + + /*! List of geometry objects */ + vector<ntlGeometryObject *> mObjects; + + /*! List of triangles */ + vector<ntlTriangle> mTriangles; + /*! List of vertices */ + vector<ntlVec3Gfx> mVertices; + /*! List of normals */ + vector<ntlVec3Gfx> mVertNormals; + /*! List of triangle normals */ + vector<ntlVec3Gfx> mTriangleNormals; + + /*! Tree to store quickly intersect triangles */ + ntlTree *mpTree; + + /*! id of dislpay list for raytracer stuff */ + int mDisplayListId; + + /*! was the scene successfully built? only then getObject(i) requests are valid */ + bool mSceneBuilt; + + /*! shader/obj initializations are only done on first init */ + bool mFirstInitDone; + +}; #endif diff --git a/intern/elbeem/intern/ntl_renderglobals.h b/intern/elbeem/intern/ntl_renderglobals.h deleted file mode 100644 index 606d0588554..00000000000 --- a/intern/elbeem/intern/ntl_renderglobals.h +++ /dev/null @@ -1,365 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * main renderer class - * - *****************************************************************************/ -#ifndef NTL_RENDERGLOBALS_HH -#define NTL_RENDERGLOBALS_HH - - -#include "ntl_vector3dim.h" -#include "ntl_rndstream.h" -#include "ntl_geometryobject.h" -#include "ntl_material.h" -#include "ntl_lightobject.h" -class ntlScene; -class SimulationObject; - - - -//! Display mode -#define DM_VIZ 0 -#define DM_RAY 1 -#define DM_LBM 2 - - - -//! Class that handles global rendering parameters -class ntlRenderGlobals -{ - public: - //! Standard constructor - inline ntlRenderGlobals(); - //! Destructor - ~ntlRenderGlobals(); - - //! Returns the scene manager - inline ntlScene *getScene(void) { return mpScene; } - //! Set the scene manager - inline void setScene(ntlScene *set) { mpScene = set;} - - //! Returns the object list - //inline vector<ntlGeometryObject*> *getObjectList(void) { return mpObjList; } - //! Set the object list - //inline void setObjectList(vector<ntlGeometryObject*> *set) { mpObjList = set;} - - //! Returns the light object list - inline vector<ntlLightObject*> *getLightList(void) { return mpLightList; } - //! Set the light list - inline void setLightList(vector<ntlLightObject*> *set) { mpLightList = set;} - - //! Returns the property object list - inline vector<ntlMaterial*> *getMaterials(void) { return mpMaterials; } - //! Set the property list - inline void setMaterials(vector<ntlMaterial*> *set) { mpMaterials = set;} - - //! Returns the list of simulations - inline vector<SimulationObject*> *getSims(void) { return mpSims; } - //! Set the pointer to the list of simulations - inline void setSims(vector<SimulationObject*> *set) { mpSims = set;} - - //! Set the x resolution - inline void setResX(unsigned int set) { mResX = set; } - //! Set the y resolution - inline void setResY(unsigned int set) { mResY = set; } - //! Set the anti-aliasing depth - inline void setAADepth(int set) { mAADepth = set; } - //! Set the max color value - inline void setMaxColVal(unsigned int set) { mMaxColVal = set; } - //! Set the maximum ray recursion - inline void setRayMaxDepth(unsigned int set) { mRayMaxDepth = set; } - //! Set the eye point - inline void setEye(ntlVec3Gfx set) { mvEye = set; } - //! Set the look at vector - inline void setLookat(ntlVec3Gfx set) { mvLookat = set; } - //! Set the up vector - inline void setUpVec(ntlVec3Gfx set) { mvUpvec = set; } - //! Set the image aspect - inline void setAspect(float set) { mAspect = set; } - //! Set the field of view - inline void setFovy(float set) { mFovy = set; } - //! Set the background color - inline void setBackgroundCol(ntlColor set) { mcBackgr = set; } - //! Set the ambient lighting color - inline void setAmbientLight(ntlColor set) { mcAmbientLight = set; } - //! Set the debug output var - inline void setDebugOut(int set) { mDebugOut = set; } - - //! Set the animation start time - inline void setAniStart(int set) { mAniStart = set; } - //! Set the animation number of frames - inline void setAniFrames(int set) { mAniFrames = set; } - //! Set the animation - inline void setAniCount(int set) { mAniCount = set; } - //! Set the ray counter - inline void setCounterRays(int set) { mCounterRays = set; } - //! Set the ray shades counter - inline void setCounterShades(int set) { mCounterShades = set; } - //! Set the scenen intersection counter - inline void setCounterSceneInter(int set) { mCounterSceneInter = set; } - //! Set if existing frames should be skipped - inline void setFrameSkip(int set) { mFrameSkip = set; } - - //! Set the outfilename - inline void setOutFilename(string set) { mOutFilename = set; } - - //! get Maximum depth for BSP tree - inline void setTreeMaxDepth( int set ) { mTreeMaxDepth = set; } - //! get Maxmimum nr of triangles per BSP tree node - inline void setTreeMaxTriangles( int set ) { mTreeMaxTriangles = set; } - - //! set the enable flag of the test sphere - inline void setTestSphereEnabled( bool set ) { mTestSphereEnabled = set; } - //! set the center of the test sphere - inline void setTestSphereCenter( ntlVec3Gfx set ) { mTestSphereCenter = set; } - //! set the radius of the test sphere - inline void setTestSphereRadius( gfxReal set ) { mTestSphereRadius = set; } - //! set the material name of the test sphere - inline void setTestSphereMaterialName( char* set ) { mTestSphereMaterialName = set; } - //! set debugging pixel coordinates - inline void setDebugPixel( int setx, int sety ) { mDebugPixelX = setx; mDebugPixelY = sety; } - //! set test mode flag - inline void setTestMode( bool set ) { mTestMode = set; } - //! set single frame mode flag - inline void setSingleFrameMode(bool set) {mSingleFrameMode = set; }; - //! set single frame mode filename - inline void setSingleFrameFilename(string set) {mSingleFrameFilename = set; }; - - - //! Return the x resolution - inline unsigned int getResX(void) { return mResX; } - //! Return the y resolution - inline unsigned int getResY(void) { return mResY; } - //! Return the anti-aliasing depth - inline int getAADepth(void) { return mAADepth; } - //! Return the max color value for ppm - inline unsigned int getMaxColVal(void) { return mMaxColVal; } - //! Return the maximum ray recursion - inline unsigned int getRayMaxDepth(void) { return mRayMaxDepth; } - //! Return the eye point - inline ntlVec3Gfx getEye(void) { return mvEye; } - //! Return the look at vector - inline ntlVec3Gfx getLookat(void) { return mvLookat; } - //! Return the up vector - inline ntlVec3Gfx getUpVec(void) { return mvUpvec; } - //! Return the image aspect - inline float getAspect(void) { return mAspect; } - //! Return the field of view - inline float getFovy(void) { return mFovy; } - //! Return the background color - inline ntlColor getBackgroundCol(void) { return mcBackgr; } - //! Return the ambient color - inline ntlColor getAmbientLight(void) { return mcAmbientLight; } - //! Return the debug mode setting - inline int getDebugOut(void) { return mDebugOut; } - - //! Return the animation start time - inline int getAniStart(void) { return mAniStart; } - //! Return the animation frame number - inline int getAniFrames(void) { return mAniFrames; } - //! Return the animation counter - inline int getAniCount(void) { return mAniCount; } - //! Return the ray counter - inline int getCounterRays(void) { return mCounterRays; } - //! Return the ray shades counter - inline int getCounterShades(void) { return mCounterShades; } - //! Return the scene intersection counter - inline int getCounterSceneInter(void) { return mCounterSceneInter; } - //! Check if existing frames should be skipped - inline int getFrameSkip( void ) { return mFrameSkip; } - - - //! Return the outfilename - inline string getOutFilename(void) { return mOutFilename; } - - //! get Maximum depth for BSP tree - inline int getTreeMaxDepth( void ) { return mTreeMaxDepth; } - //! get Maxmimum nr of triangles per BSP tree node - inline int getTreeMaxTriangles( void ) { return mTreeMaxTriangles; } - - //! get open gl attribute list - inline AttributeList* getOpenGlAttributes( void ) { return mpOpenGlAttr; } - //! get blender output attribute list - inline AttributeList* getBlenderAttributes( void ) { return mpBlenderAttr; } - - //! is the test sphere enabled? - inline bool getTestSphereEnabled( void ) { return mTestSphereEnabled; } - //! get the center of the test sphere - inline ntlVec3Gfx getTestSphereCenter( void ) { return mTestSphereCenter; } - //! get the radius of the test sphere - inline gfxReal getTestSphereRadius( void) { return mTestSphereRadius; } - //! get the materialname of the test sphere - inline char *getTestSphereMaterialName( void) { return mTestSphereMaterialName; } - //! get the debug pixel coordinate - inline int getDebugPixelX( void ) { return mDebugPixelX; } - //! get the debug pixel coordinate - inline int getDebugPixelY( void ) { return mDebugPixelY; } - //! get test mode flag - inline bool getTestMode( void ) { return mTestMode; } - //! set single frame mode flag - inline bool getSingleFrameMode() { return mSingleFrameMode; }; - //! set single frame mode filename - inline string getSingleFrameFilename() { return mSingleFrameFilename; }; - - - // random number functions - //! init random numbers for photon directions - inline void initRandomDirections( int seed ) { if(mpRndDirections) delete mpRndDirections; mpRndDirections = new ntlRandomStream( seed ); } - //! get the next random photon direction - inline ntlVec3Gfx getRandomDirection( void ); - //! init random numbers for russian roulette - inline void initRandomRoulette( int seed ) { if(mpRndRoulette) delete mpRndRoulette; mpRndRoulette = new ntlRandomStream( seed ); } - //! get the next random number for russion roulette - inline gfxReal getRandomRoulette( void ) { return mpRndRoulette->getGfxReal(); } - - -protected: - -private: - - /*! Scene storage */ - ntlScene *mpScene; - - //! List of geometry objects - //vector<ntlGeometryObject*> *mpObjList; - //! List of light objects - vector<ntlLightObject*> *mpLightList; - //! List of surface properties - vector<ntlMaterial*> *mpMaterials; - /*! storage for simulations */ - vector<SimulationObject*> *mpSims; - - //! resolution of the picture - unsigned int mResX, mResY; - //! Anti-Aliasing depth - int mAADepth; - //! max color value for ppm - unsigned int mMaxColVal; - /* Maximal ray recursion depth */ - int mRayMaxDepth; - //! The eye point - ntlVec3Gfx mvEye; - //! The look at point - ntlVec3Gfx mvLookat; - //! The up vector - ntlVec3Gfx mvUpvec; - //! The image aspect = Xres/Yres - float mAspect; - //! The horizontal field of view - float mFovy; - //! The background color - ntlColor mcBackgr; - //! The ambient color - ntlColor mcAmbientLight; - //! how much debug output is needed? off by default - char mDebugOut; - - - //! animation properties, start time - int mAniStart; - //! animation properties, number of frames to render - int mAniFrames; - //! animation status, current frame number - int mAniCount; - /*! Should existing picture frames be skipped? */ - int mFrameSkip; - - - //! count the total number of rays created (also used for ray ID's) - int mCounterRays; - //! count the total number of rays shaded - int mCounterShades; - //! count the total number of scene intersections - int mCounterSceneInter; - - /*! filename of output pictures (without suffix or numbers) */ - string mOutFilename; - - //! get Maximum depth for BSP tree - int mTreeMaxDepth; - //! get Maxmimum nr of triangles per BSP tree node - int mTreeMaxTriangles; - - //! attribute list for opengl renderer - AttributeList *mpOpenGlAttr; - //! attribute list for blender output - AttributeList *mpBlenderAttr; - - - //! Enable test sphere? - bool mTestSphereEnabled; - //! Center of the test sphere - ntlVec3Gfx mTestSphereCenter; - //! Radius of the test sphere - gfxReal mTestSphereRadius; - //! Materialname of the test sphere - char *mTestSphereMaterialName; - //! coordinates of the debugging pixel - int mDebugPixelX, mDebugPixelY; - - //! test mode for quick rendering activated?, inited in ntl_scene::buildScene - bool mTestMode; - - //! single frame flag - bool mSingleFrameMode; - //! filename for single frame mode - string mSingleFrameFilename; - - /*! Two random number streams for photon generation (one for the directions, the other for russion roulette) */ - ntlRandomStream *mpRndDirections, *mpRndRoulette; - -}; - - - - -/*****************************************************************************/ -/* Constructor with standard value init */ -inline ntlRenderGlobals::ntlRenderGlobals() : - mpLightList( NULL ), mpMaterials( NULL ), mpSims( NULL ), - mResX(320), mResY(200), mAADepth(-1), mMaxColVal(255), - mRayMaxDepth( 5 ), - mvEye(0.0,0.0,5.0), mvLookat(0.0,0.0,0.0), mvUpvec(0.0,1.0,0.0), - mAspect(320.0/200.0), - mFovy(45), mcBackgr(0.0,0.0,0.0), mcAmbientLight(0.0,0.0,0.0), - mDebugOut( 0 ), - mAniStart(0), mAniFrames( -1 ), mAniCount( 0 ), - mFrameSkip( 0 ), - mCounterRays( 0 ), mCounterShades( 0 ), mCounterSceneInter( 0 ), - mOutFilename( "pic" ), - mTreeMaxDepth( 30 ), mTreeMaxTriangles( 30 ), - mpOpenGlAttr(NULL), - mpBlenderAttr(NULL), - mTestSphereEnabled( false ), - mDebugPixelX( -1 ), mDebugPixelY( -1 ), mTestMode(false), - mSingleFrameMode(false), mSingleFrameFilename(""), - mpRndDirections( NULL ), mpRndRoulette( NULL ) -{ - // create internal attribute list for opengl renderer - mpOpenGlAttr = new AttributeList("__ntlOpenGLRenderer"); - mpBlenderAttr = new AttributeList("__ntlBlenderAttr"); -}; - - -/*****************************************************************************/ -/* Destructor */ -inline ntlRenderGlobals::~ntlRenderGlobals() { - if(mpOpenGlAttr) delete mpOpenGlAttr; - if(mpBlenderAttr) delete mpBlenderAttr; -} - - -/*****************************************************************************/ -//! get the next random photon direction -inline ntlVec3Gfx ntlRenderGlobals::getRandomDirection( void ) { - return ntlVec3Gfx( - (mpRndDirections->getGfxReal()-0.5), - (mpRndDirections->getGfxReal()-0.5), - (mpRndDirections->getGfxReal()-0.5) ); -} - -#endif - diff --git a/intern/elbeem/intern/ntl_rndstream.h b/intern/elbeem/intern/ntl_rndstream.h deleted file mode 100644 index 9eaa9093a0b..00000000000 --- a/intern/elbeem/intern/ntl_rndstream.h +++ /dev/null @@ -1,127 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * A seperate random number stream (e.g. for photon tracing) - * (cf. Numerical recipes in C, sec. ed., p 283, Knuth method) - * - *****************************************************************************/ -#ifndef NTL_RANDOMSTREAM_H - - -//! some big number -#define MBIG 1000000000 - -//! modify initial seed -#define MSEED 161803398 - -//! minimum value - no idea why this is a define? -#define MZ 0 - -//! for normalization to 0..1 -#define FAC (1.0/MBIG) - - -/*! a stream of random numbers using Knuth's portable method */ -class ntlRandomStream -{ -public: - /*! Default constructor */ - inline ntlRandomStream(long seed); - /*! Destructor */ - ~ntlRandomStream() {} - - /*! get a random number from the stream */ - inline double getDouble( void ); - -#ifdef HAVE_GFXTYPES - //! gfx random functions - - /*! get a random number from the stream */ - inline gfxReal getGfxReal( void ); -#endif - -private: - - /*! random number state */ - long idnum; - - /*! pointers into number table */ - int inext, inextp; - /*! store seed and number for subtraction */ - long ma[56]; - -}; - - -/* init random stream tables */ -inline ntlRandomStream::ntlRandomStream(long seed) -{ - idnum = seed; - - long mj = MSEED - (idnum < 0 ? -idnum : idnum); - mj %= MBIG; - ma[55] = mj; - long mk = 1; - - // init table once, otherwise strange results... - for(int i=0;i<=55;i++) ma[i] = (i*i+seed); - - // init table in random order - for(int i=1;i<=54;i++) { - int ii = (21*i) % 56; - ma[ii] = mk; - mk = mj - mk; - if(mk < MZ) mk += MBIG; - mj = ma[ii]; - } - - // "warm up" generator - for(int k=1;k<=4;k++) - for(int i=1;i<=55;i++) { - ma[i] -= ma[1+ (i+30) % 55]; - if(ma[i] < MZ) ma[i] += MBIG; - } - - inext = 0; - inextp = 31; // the special "31" - idnum = 1; -} - - -/* return one random value */ -inline double ntlRandomStream::getDouble( void ) -{ - if( ++inext == 56) inext = 1; - if( ++inextp == 56) inextp = 1; - - // generate by subtaction - long mj = ma[inext] - ma[inextp]; - - // check range - if(mj < MZ) mj += MBIG; - ma[ inext ] = mj; - return (double)(mj * FAC); -} - -#ifdef HAVE_GFXTYPES -/* return one random value */ -inline gfxReal ntlRandomStream::getGfxReal( void ) -{ - if( ++inext == 56) inext = 1; - if( ++inextp == 56) inextp = 1; - - // generate by subtaction - long mj = ma[inext] - ma[inextp]; - - // check range - if(mj < MZ) mj += MBIG; - ma[ inext ] = mj; - return (gfxReal)(mj * FAC); -} -#endif - -#define NTL_RANDOMSTREAM_H -#endif - diff --git a/intern/elbeem/intern/ntl_scene.cpp b/intern/elbeem/intern/ntl_scene.cpp deleted file mode 100644 index 4e980944f22..00000000000 --- a/intern/elbeem/intern/ntl_scene.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * Scene object, that contains and manages all geometry objects - * - *****************************************************************************/ - -#include "utilities.h" -#include "ntl_scene.h" -#include "ntl_geometryobject.h" -#include "ntl_geometryshader.h" - - -/****************************************************************************** - * Constructor - *****************************************************************************/ -ntlScene::ntlScene( ntlRenderGlobals *glob ) : - mpGlob( glob ), - mpTree( NULL ), - mDisplayListId( -1 ), - mSceneBuilt( false ), mFirstInitDone( false ) -{ -} - - -/****************************************************************************** - * Destructor - *****************************************************************************/ -ntlScene::~ntlScene() -{ - cleanupScene(); - - // cleanup lists - for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); - iter != mGeos.end(); iter++) { - delete (*iter); - } - for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin(); - iter != mpGlob->getLightList()->end(); iter++) { - delete (*iter); - } - for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); - iter != mpGlob->getMaterials()->end(); iter++) { - delete (*iter); - } -} - - -/****************************************************************************** - * Build the scene arrays (obj, tris etc.) - *****************************************************************************/ -void ntlScene::buildScene( void ) -{ - const bool buildInfo=false; - mObjects.clear(); - /* init geometry array, first all standard objects */ - for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); - iter != mGeos.end(); iter++) { - bool geoinit = false; - int tid = (*iter)->getTypeId(); - if(tid & GEOCLASSTID_OBJECT) { - ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter); - geoinit = true; - mObjects.push_back( geoobj ); - if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName(), 5 ); - } - //if(geoshad) { - if(tid & GEOCLASSTID_SHADER) { - ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); - geoinit = true; - if(!mFirstInitDone) { - // only on first init - geoshad->initializeShader(); - } - for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin(); - siter != geoshad->getObjectsEnd(); - siter++) { - if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 5 ); - mObjects.push_back( (*siter) ); - } - } - - if(!geoinit) { - errFatal("ntlScene::BuildScene","Invalid geometry class!", SIMWORLD_INITERROR); - return; - } - } - - // collect triangles - mTriangles.clear(); - mVertices.clear(); - mVertNormals.clear(); - - /* for test mode deactivate transparencies etc. */ - if( mpGlob->getTestMode() ) { - debugOut("ntlScene::buildScene : Test Mode activated!", 2); - // assign random colors to dark materials - int matCounter = 0; - ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) }; - int stdColNum = 4; - for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); - iter != mpGlob->getMaterials()->end(); iter++) { - (*iter)->setTransparence(0.0); - (*iter)->setMirror(0.0); - (*iter)->setFresnel(false); - // too dark? - if( norm((*iter)->getDiffuseRefl()) <0.01) { - (*iter)->setDiffuseRefl( stdCols[matCounter] ); - matCounter ++; - matCounter = matCounter%stdColNum; - } - } - - // restrict output file size to 400 - float downscale = 1.0; - if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); } - if(mpGlob->getResY() > 400){ - float downscale2 = 400.0/(float)mpGlob->getResY(); - if(downscale2<downscale) downscale=downscale2; - } - mpGlob->setResX( (int)(mpGlob->getResX() * downscale) ); - mpGlob->setResY( (int)(mpGlob->getResY() * downscale) ); - - } - - /* collect triangles from objects */ - int idCnt = 0; // give IDs to objects - for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); - iter != mObjects.end(); - iter++) { - /* only add visible objects */ - (*iter)->initialize( mpGlob ); - (*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt); - idCnt ++; - } - - - /* calculate triangle normals, and initialize flags */ - for (vector<ntlTriangle>::iterator iter = mTriangles.begin(); - iter != mTriangles.end(); - iter++) { - - // calculate normal from triangle points - ntlVec3Gfx normal = - cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right?? - (ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) ); - normalize(normal); - (*iter).setNormal( normal ); - } - - - - // scene geometry built - mSceneBuilt = true; - - // init shaders that require complete geometry - if(!mFirstInitDone) { - // only on first init - for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); - iter != mGeos.end(); iter++) { - if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) { - ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); - geoshad->postGeoConstrInit( mpGlob ); - } - } - mFirstInitDone = true; - } - - // check unused attributes (for classes and objects!) - for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) { - if((*iter)->getAttributeList()->checkUnusedParams()) { - (*iter)->getAttributeList()->print(); // DEBUG - errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); - return; - } - } - for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) { - if((*iter)->getAttributeList()->checkUnusedParams()) { - (*iter)->getAttributeList()->print(); // DEBUG - errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); - return; - } - } - -} - -/****************************************************************************** - * Prepare the scene triangles and maps for raytracing - *****************************************************************************/ -void ntlScene::prepareScene( void ) -{ - /* init triangles... */ - buildScene(); - // what for currently not used ??? - if(mpTree != NULL) delete mpTree; - mpTree = new ntlTree( mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(), - this, TRI_GEOMETRY ); - - //debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 ); -} -/****************************************************************************** - * Do some memory cleaning, when frame is finished - *****************************************************************************/ -void ntlScene::cleanupScene( void ) -{ - mObjects.clear(); - mTriangles.clear(); - mVertices.clear(); - mVertNormals.clear(); - - if(mpTree != NULL) delete mpTree; - mpTree = NULL; -} - - -/****************************************************************************** - * Intersect a ray with the scene triangles - *****************************************************************************/ -void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const -{ - distance = -1.0; - mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 ); - mpTree->intersect(r, distance, normal, tri, flags, false); -} - - - - - - - - - diff --git a/intern/elbeem/intern/ntl_scene.h b/intern/elbeem/intern/ntl_scene.h deleted file mode 100644 index f01aedc84af..00000000000 --- a/intern/elbeem/intern/ntl_scene.h +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * Scene object, that contains and manages all geometry objects - * - *****************************************************************************/ -#ifndef NTL_SCENE_HH -#define NTL_SCENE_HH - -#include <sstream> -#include "ntl_vector3dim.h" -#include "ntl_material.h" -#include "ntl_geometryclass.h" -#include "ntl_triangle.h" -#include "ntl_bsptree.h" -class ntlRay; -class ntlGeometryObject; - - -//! convenience macro for adding triangles -#define sceneAddTriangle(p1,p2,p3, pn1,pn2,pn3, trin, smooth) {\ - \ - ntlTriangle tri;\ - int tempVert;\ - \ - if(normals->size() != vertices->size()) {\ - errFatal("getTriangles","For '"<<mName<<"': Vertices and normals sizes to not match!!!",SIMWORLD_GENERICERROR);\ - } else {\ - \ - vertices->push_back( p1 ); \ - normals->push_back( pn1 ); \ - tempVert = normals->size()-1;\ - tri.getPoints()[0] = tempVert;\ - \ - vertices->push_back( p2 ); \ - normals->push_back( pn2 ); \ - tempVert = normals->size()-1;\ - tri.getPoints()[1] = tempVert;\ - \ - vertices->push_back( p3 ); \ - normals->push_back( pn3 ); \ - tempVert = normals->size()-1;\ - tri.getPoints()[2] = tempVert;\ - \ - \ - /* init flags */\ - int flag = 0; \ - if(getVisible()){ flag |= TRI_GEOMETRY; }\ - if(getCastShadows() ) { \ - flag |= TRI_CASTSHADOWS; } \ - if( (getMaterial()->getMirror()>0.0) || \ - (getMaterial()->getTransparence()>0.0) || \ - (getMaterial()->getFresnel()>0.0) ) { \ - flag |= TRI_MAKECAUSTICS; } \ - else { \ - flag |= TRI_NOCAUSTICS; } \ - \ - /* init geo init id */\ - int geoiId = getGeoInitId(); \ - if(geoiId > 0) { \ - flag |= (1<< (geoiId+4)); \ - flag |= mGeoInitType; \ - } \ - \ - tri.setFlags( flag );\ - \ - /* triangle normal missing */\ - tri.setNormal( trin );\ - tri.setSmoothNormals( smooth );\ - tri.setObjectId( objectId );\ - triangles->push_back( tri ); \ - } /* normals check*/ \ - }\ - - - -class ntlScene -{ -public: - /* CONSTRUCTORS */ - /*! Default constructor */ - ntlScene( ntlRenderGlobals *glob ); - /*! Default destructor */ - ~ntlScene(); - - /*! Add an object to the scene */ - inline void addGeoClass(ntlGeometryClass *geo) { mGeos.push_back( geo ); } - - /*! Acces a certain object */ - inline ntlGeometryObject *getObject(int id) { - if(!mSceneBuilt) { errMsg("ntlScene::getObject","Scene not inited!"); return NULL; } - return mObjects[id]; } - - /*! Acces object array */ - inline vector<ntlGeometryObject*> *getObjects() { - if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; } - return &mObjects; } - - /*! Acces geo class array */ - inline vector<ntlGeometryClass*> *getGeoClasses() { - if(!mSceneBuilt) { errMsg("ntlScene::getGeoClasses[]","Scene not inited!"); return NULL; } - return &mGeos; } - - /*! draw scene with opengl */ - //void draw(); - - /*! Build the scene arrays */ - void buildScene( void ); - - //! Prepare the scene triangles and maps for raytracing - void prepareScene( void ); - //! Do some memory cleaning, when frame is finished - void cleanupScene( void ); - - /*! Intersect a ray with the scene triangles */ - void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const; - - /*! return a vertex */ - ntlVec3Gfx getVertex(int index) { return mVertices[index]; } - - // for tree generation - /*! return pointer to vertices vector */ - vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; } - /*! return pointer to vertices vector */ - vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; } - /*! return pointer to vertices vector */ - vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; } - -private: - - /*! Global settings */ - ntlRenderGlobals *mpGlob; - - /*! List of geometry classes */ - vector<ntlGeometryClass *> mGeos; - - /*! List of geometry objects */ - vector<ntlGeometryObject *> mObjects; - - /*! List of triangles */ - vector<ntlTriangle> mTriangles; - /*! List of vertices */ - vector<ntlVec3Gfx> mVertices; - /*! List of normals */ - vector<ntlVec3Gfx> mVertNormals; - /*! List of triangle normals */ - vector<ntlVec3Gfx> mTriangleNormals; - - /*! Tree to store quickly intersect triangles */ - ntlTree *mpTree; - - /*! id of dislpay list for raytracer stuff */ - int mDisplayListId; - - /*! was the scene successfully built? only then getObject(i) requests are valid */ - bool mSceneBuilt; - - /*! shader/obj initializations are only done on first init */ - bool mFirstInitDone; - -}; - - -#endif - diff --git a/intern/elbeem/intern/ntl_triangle.h b/intern/elbeem/intern/ntl_triangle.h deleted file mode 100644 index 7f1c7f1595e..00000000000 --- a/intern/elbeem/intern/ntl_triangle.h +++ /dev/null @@ -1,183 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * Copyright 2003,2004 Nils Thuerey - * - * a single triangle - * - *****************************************************************************/ -#ifndef NTL_TRIANGLE_HH -#define NTL_TRIANGLE_HH - - -#include "ntl_vector3dim.h" -#include "ntl_material.h" -class ntlRay; - - -/*! Triangle flag defines */ -#define TRI_GEOMETRY (1<<0) -#define TRI_CASTSHADOWS (1<<1) -#define TRI_MAKECAUSTICS (1<<2) -#define TRI_NOCAUSTICS (1<<3) - - -class ntlTriangle -{ -public: - /* CONSTRUCTORS */ - /*! Default constructor */ - inline ntlTriangle( void ); - /*! Constructor with parameters */ - inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags); - /*! Copy - Constructor */ - inline ntlTriangle(const ntlTriangle &tri); - /*! Destructor */ - inline ~ntlTriangle() {} - - /* Access methods */ - - /*! Acces to points of triangle */ - inline int *getPoints( void ) { return mPoints; } - /*! Acces normal smoothing */ - inline bool getSmoothNormals( void ) const { return mSmoothNormals; } - inline void setSmoothNormals( bool set){ mSmoothNormals = set; } - /*! Access object */ - inline int getObjectId( void ) const { return mObjectId; } - inline void setObjectId( int set) { mObjectId = set; } - /*! Acces normal index */ - inline ntlVec3Gfx getNormal( void ) const { return mNormal; } - inline void setNormal( ntlVec3Gfx set ) { mNormal = set; } - /*! Acces flags */ - inline int getFlags( void ) const { return mFlags; } - inline void setFlags( int set ) { mFlags = set; } - /*! Access last intersection ray ID */ - inline int getLastRay( void ) const { return mLastRay; } - inline void setLastRay( int set ) { mLastRay = set; } - /*! Acces bbox id */ - inline int getBBoxId( void ) const { return mBBoxId; } - inline void setBBoxId( int set ) { mBBoxId = set; } - - /*! Get average of the three points for this axis */ - inline gfxReal getAverage( int axis ) const; - - /*! operator < for sorting, uses global sorting axis */ - inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs); - /*! operator > for sorting, uses global sorting axis */ - inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs); - -protected: - -private: - - /*! indices to the three points of the triangle */ - int mPoints[3]; - - /*! bounding box id (for tree generation), -1 if invalid */ - int mBBoxId; - - /*! Should the normals of this triangle get smoothed? */ - bool mSmoothNormals; - - /*! Id of parent object */ - int mObjectId; - - /*! Index to normal (for not smooth triangles) */ - //int mNormalIndex; ?? - ntlVec3Gfx mNormal; - - /*! Flags for object attributes cast shadows, make caustics etc. */ - int mFlags; - - /*! ID of last ray that an intersection was calculated for */ - int mLastRay; - -}; - - - - -/****************************************************************************** - * Default Constructor - *****************************************************************************/ -ntlTriangle::ntlTriangle( void ) : - mBBoxId(-1), - mLastRay( 0 ) -{ - mPoints[0] = mPoints[1] = mPoints[2] = 0; - mSmoothNormals = 0; - mObjectId = 0; - mNormal = ntlVec3Gfx(0.0); - mFlags = 0; -} - - -/****************************************************************************** - * Constructor - *****************************************************************************/ -ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) : - mBBoxId(-1), - mLastRay( 0 ) -{ - mPoints[0] = p[0]; - mPoints[1] = p[1]; - mPoints[2] = p[2]; - mSmoothNormals = smooth; - mObjectId = obj; - mNormal = norm; - mFlags = setflags; -} - - -/****************************************************************************** - * Copy Constructor - *****************************************************************************/ -ntlTriangle::ntlTriangle(const ntlTriangle &tri) : - mBBoxId(-1), - mLastRay( 0 ) -{ - mPoints[0] = tri.mPoints[0]; - mPoints[1] = tri.mPoints[1]; - mPoints[2] = tri.mPoints[2]; - mSmoothNormals = tri.mSmoothNormals; - mObjectId = tri.mObjectId; - mNormal = tri.mNormal; - mFlags = tri.mFlags; -} - - - - -/****************************************************************************** - * Triangle sorting functions - *****************************************************************************/ - -/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */ -/* Static global variable for sorting direction */ -extern int globalSortingAxis; -/* Access to points array for sorting */ -extern vector<ntlVec3Gfx> *globalSortingPoints; - - -gfxReal ntlTriangle::getAverage( int axis ) const -{ - return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] + - (*globalSortingPoints)[ mPoints[1] ][axis] + - (*globalSortingPoints)[ mPoints[2] ][axis] )/3.0); -} - -bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs) -{ - return ( lhs.getAverage(globalSortingAxis) < - rhs.getAverage(globalSortingAxis) ); -} - -bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs) -{ - return ( lhs.getAverage(globalSortingAxis) > - rhs.getAverage(globalSortingAxis) ); -} - - -#endif - diff --git a/intern/elbeem/intern/ntl_vector3dim.h b/intern/elbeem/intern/ntl_vector3dim.h index de4d5f8722a..ffcaa4149e0 100644 --- a/intern/elbeem/intern/ntl_vector3dim.h +++ b/intern/elbeem/intern/ntl_vector3dim.h @@ -92,6 +92,7 @@ using std::string; #ifndef M_PI #define M_PI 3.1415926536 +#define M_E 2.7182818284 #endif // make sure elbeem plugin def is valid diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index c207fd94b90..8d1d5d4b45c 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -12,9 +12,7 @@ #include <sstream> #include "utilities.h" #include "ntl_world.h" -#include "ntl_scene.h" #include "parametrizer.h" -#include "globals.h" // for non-threaded renderViz #ifndef NOGUI @@ -25,114 +23,41 @@ /* external parser functions from cfgparser.cxx */ +#ifndef ELBEEM_PLUGIN /* parse given file as config file */ void parseFile(string filename); /* set pointers for parsing */ void setPointers( ntlRenderGlobals *setglob); +#endif // ELBEEM_PLUGIN /****************************************************************************** * Constructor *****************************************************************************/ ntlWorld::ntlWorld(string filename, bool commandlineMode) - /*: - mpGlob(NULL), - mpLightList(NULL), mpPropList(NULL), mpSims(NULL), - mpOpenGLRenderer(NULL), - mStopRenderVisualization( false ), - mThreadRunning( false ), - mSimulationTime(0.0), mFirstSim(-1), - mSingleStepDebug( false ), - mFrameCnt(0)*/ { -#if 0 - /* create scene storage */ - mpGlob = new ntlRenderGlobals(); - mpLightList = new vector<ntlLightObject*>; - mpPropList = new vector<ntlMaterial*>; - mpSims = new vector<SimulationObject*>; - - mpGlob->setLightList(mpLightList); - mpGlob->setMaterials(mpPropList); - mpGlob->setSims(mpSims); - - /* init default material */ - ntlMaterial *def = GET_GLOBAL_DEFAULT_MATERIAL; - mpPropList->push_back( def ); - - /* init the scene object */ - ntlScene *scene; - scene = new ntlScene( mpGlob ); - mpGlob->setScene( scene ); - - // moved TODO test... -#endif // 0 - - initDefaults(); -#ifndef NOGUI - // setup opengl display, save first animation step for start time - if(!commandlineMode) { - mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob ); - } -#else // NOGUI - commandlineMode = true; // remove warning... -#endif // NOGUI - // load config - setPointers( getRenderGlobals() ); - parseFile( filename.c_str() ); - finishWorldInit(); - /*if(!SIMWORLD_OK()) return; - - // init the scene for the first time - long sstartTime = getTime(); - scene->buildScene(); - 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]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) { - 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); - } +#ifndef ELBEEM_PLUGIN + + initDefaults(); +# ifdef NOGUI + commandlineMode = true; // remove warning... +# endif // NOGUI + + // load config + setPointers( getRenderGlobals() ); + parseFile( filename.c_str() ); +# ifndef NOGUI + // setup opengl display, save first animation step for start time + // init after parsing file... + if(!commandlineMode) { + mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob ); } +# endif // NOGUI + finishWorldInit(); - 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 simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); -#ifndef NOGUI - guiResetSimulationTimeRange( mSimulationTime ); -#endif - } else { - if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); - } - } -*/ +#else // ELBEEM_PLUGIN + errFatal("ntlWorld::init","Cfg file parsing not supported for API version!", SIMWORLD_INITERROR); +#endif // ELBEEM_PLUGIN } ntlWorld::ntlWorld(elbeemSimulationSettings *settings) @@ -141,34 +66,53 @@ ntlWorld::ntlWorld(elbeemSimulationSettings *settings) // todo init settings SimulationObject *sim = new SimulationObject(); mpGlob->getSims()->push_back( sim ); - mpGlob->getScene()->addGeoClass( sim ); + // important - add to both, only render scene objects are free'd + mpGlob->getRenderScene()->addGeoClass( sim ); + mpGlob->getSimScene()->addGeoClass( sim ); sim->setGeoStart(ntlVec3Gfx(settings->geoStart[0],settings->geoStart[1],settings->geoStart[2])); sim->setGeoEnd(ntlVec3Gfx( settings->geoStart[0]+settings->geoSize[0], settings->geoStart[1]+settings->geoSize[1], settings->geoStart[2]+settings->geoSize[2] )); - sim->getSolver()->setSmoothing(1.0, 0.0); - sim->getSolver()->setPreviewSize(settings->previewresxyz); - sim->getSolver()->setRefinementDesired(settings->maxRefine); + // further init in postGeoConstrInit/initializeLbmSimulation of SimulationObject + sim->copyElbeemSettings(settings); Parametrizer *param = sim->getParametrizer(); param->setSize( settings->resolutionxyz ); param->setDomainSize( settings->realsize ); param->setViscosity( settings->viscosity ); - param->setGravity( ParamVec(settings->gravx, settings->gravy, settings->gravx) ); + param->setGravity( ParamVec(settings->gravity[0], settings->gravity[1], settings->gravity[2]) ); param->setAniStart( settings->animStart ); - param->setAniFrameTime( settings->aniFrameTime ); + param->setAniFrameTimeChannel( settings->aniFrameTime ); param->setNormalizedGStar( settings->gstar ); - // dont setup lights, camera, materials...? - /* - ntlMaterial *fluidmat = new ntlMaterial( ); - currentMaterial->setAmbientRefl( ntlColor(0.3, 0.5, 0.9) ); - currentMaterial->setDiffuseRefl( ntlColor(0.3, 0.5, 0.9) ); - currentMaterial->setSpecular( 0.2 ); - currentMaterial->setSpecExponent( 10.0 ); - mpGlob->getMaterials()->push_back( fluidmat ); - // */ + // init domain channels + vector<ParamFloat> valf; + vector<ParamVec> valv; + vector<double> time; + +#define INIT_CHANNEL_FLOAT(channel,size) \ + valf.clear(); time.clear(); elbeemSimplifyChannelFloat(channel,&size); \ + for(int i=0; i<size; i++) { valf.push_back( channel[2*i+0] ); time.push_back( channel[2*i+1] ); } +#define INIT_CHANNEL_VEC(channel,size) \ + valv.clear(); time.clear(); elbeemSimplifyChannelVec3(channel,&size); \ + for(int i=0; i<size; i++) { valv.push_back( ParamVec(channel[4*i+0],channel[4*i+1],channel[4*i+2]) ); time.push_back( channel[4*i+3] ); } + + INIT_CHANNEL_FLOAT(settings->channelViscosity, settings->channelSizeViscosity); + param->initViscosityChannel(valf,time); + + INIT_CHANNEL_VEC(settings->channelGravity, settings->channelSizeGravity); + param->initGravityChannel(valv,time); + + INIT_CHANNEL_FLOAT(settings->channelFrameTime, settings->channelSizeFrameTime); + param->initAniFrameTimeChannel(valf,time); + +#undef INIT_CHANNEL_FLOAT +#undef INIT_CHANNEL_VEC + + mpGlob->setAniFrames( settings->noOfFrames ); + mpGlob->setOutFilename( settings->outputPath ); + // further init in postGeoConstrInit/initializeLbmSimulation of SimulationObject } void ntlWorld::initDefaults() @@ -196,8 +140,11 @@ void ntlWorld::initDefaults() mpPropList->push_back( def ); /* init the scene object */ - ntlScene *newscene = new ntlScene( mpGlob ); - mpGlob->setScene( newscene ); + ntlScene *renderscene = new ntlScene( mpGlob, true ); + mpGlob->setRenderScene( renderscene ); + // sim scene shouldnt delete objs, may only contain subset + ntlScene *simscene = new ntlScene( mpGlob, false ); + mpGlob->setSimScene( simscene ); } void ntlWorld::finishWorldInit() @@ -206,7 +153,10 @@ void ntlWorld::finishWorldInit() // init the scene for the first time long sstartTime = getTime(); - mpGlob->getScene()->buildScene(); + + // first init sim scene for geo setup + mpGlob->getSimScene()->buildScene(0.0, true); + mpGlob->getRenderScene()->buildScene(0.0, true); long sstopTime = getTime(); debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); @@ -225,7 +175,7 @@ void ntlWorld::finishWorldInit() // check largest timestep if(mFirstSim>=0) { - if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) { + if( (*mpSims)[i]->getTimestep() > (*mpSims)[mFirstSim]->getTimestep() ) { mFirstSim = i; debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<<i ,10); } @@ -246,7 +196,7 @@ void ntlWorld::finishWorldInit() long stopTime = getTime(); mSimulationTime += (*mpSims)[mFirstSim]->getStartTime(); - debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1); + debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start-sims:"<< getTimeString(stopTime-startTime) , 1); #ifndef NOGUI guiResetSimulationTimeRange( mSimulationTime ); #endif @@ -263,7 +213,8 @@ void ntlWorld::finishWorldInit() *****************************************************************************/ ntlWorld::~ntlWorld() { - delete mpGlob->getScene(); + delete mpGlob->getRenderScene(); + delete mpGlob->getSimScene(); delete mpGlob; delete mpLightList; delete mpPropList; @@ -271,6 +222,7 @@ ntlWorld::~ntlWorld() #ifndef NOGUI if(mpOpenGLRenderer) delete mpOpenGLRenderer; #endif // NOGUI + debMsgStd("ntlWorld",DM_NOTIFY, "ntlWorld done", 10); } /******************************************************************************/ @@ -349,9 +301,9 @@ int ntlWorld::renderVisualization( bool multiThreaded ) advanceSims(mFrameCnt); mFrameCnt++; long stopTime = getTime(); - debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for "<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<"s ", 10); + debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for t="<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<" ", 10); } else { - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); + double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(targetTime); // check paniced sims (normally done by advanceSims @@ -390,7 +342,7 @@ int ntlWorld::renderVisualization( bool multiThreaded ) int ntlWorld::singleStepVisualization( void ) { mThreadRunning = true; - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); + double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(targetTime); mSimulationTime = (*mpSims)[0]->getCurrentTime(); @@ -419,12 +371,10 @@ int ntlWorld::advanceSims(int framenum) //debMsgStd("ntlWorld::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); } - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(); -//FIXME check blender abort here... -//FIXME check no ipo export + double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); // time stopped? nothing else to do... - if( (*mpSims)[mFirstSim]->getFrameTime() <= 0.0 ){ + if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ done=true; allPanic=false; } @@ -437,17 +387,25 @@ int ntlWorld::advanceSims(int framenum) #endif // ELBEEM_BLENDER==1 // step all the sims, and check for panic + debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic, 10); // debug // timedebug while(!done) { - double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime(); + double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(nextTargetTime); // check target times done = true; allPanic = false; - 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<<" c"<<(*mpSims)[i]->getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<<targetTime, 10); // debug // timedebug + //if((framenum>0) && (nextTargetTime<=(*mpSims)[mFirstSim]->getCurrentTime()) ) { + 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; @@ -474,7 +432,7 @@ int ntlWorld::advanceSims(int framenum) /* dont check target time, if *targetTime==NULL */ void ntlWorld::singleStepSims(double targetTime) { const bool debugTime = false; - //double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime(); + //double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep(); if(debugTime) errMsg("ntlWorld::singleStepSims","Target time: "<<targetTime); for(size_t i=0;i<mpSims->size();i++) { @@ -484,7 +442,7 @@ void ntlWorld::singleStepSims(double targetTime) { bool done = false; while(!done) { // try to prevent round off errs - if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getStepTime()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug + if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getTimestep()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug if( (targetTime - sim->getCurrentTime()) > LBM_TIME_EPSILON) { if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping sim "<<i<<" t:"<< sim->getCurrentTime()); // timedebug sim->step(); @@ -509,7 +467,7 @@ void ntlWorld::singleStepSims(double targetTime) { *****************************************************************************/ int ntlWorld::renderScene( void ) { -#ifndef ELBEEM_BLENDER +#ifndef ELBEEM_PLUGIN char nrStr[5]; /* nr conversion */ //std::ostringstream outfilename(""); /* ppm file */ std::ostringstream outfn_conv(""); /* converted ppm with other suffix */ @@ -541,8 +499,8 @@ int ntlWorld::renderScene( void ) /* start program */ timeStart = getTime(); - /* build scene geometry */ - glob->getScene()->prepareScene(); + /* build scene geometry, calls buildScene(t,false) */ + glob->getRenderScene()->prepareScene(mSimulationTime); /* start program */ totalStart = getTime(); @@ -566,7 +524,7 @@ int ntlWorld::renderScene( void ) /* check if vectors are valid */ if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) { - errorOut("NTL ERROR: Invalid viewpoint vectors!\n"); + errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec); return(1); } @@ -856,15 +814,66 @@ int ntlWorld::renderScene( void ) delete [] aaCol; delete [] aaUse; delete [] finalPic; - glob->getScene()->cleanupScene(); + glob->getRenderScene()->cleanupScene(); if(mpGlob->getSingleFrameMode() ) { debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); return 1; } -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN return 0; } +/****************************************************************************** + * renderglobals + *****************************************************************************/ + + +/*****************************************************************************/ +/* Constructor with standard value init */ +ntlRenderGlobals::ntlRenderGlobals() : + mpRenderScene(NULL), mpSimScene(NULL), + mpLightList( NULL ), mpMaterials( NULL ), mpSims( NULL ), + mResX(320), mResY(200), mAADepth(-1), mMaxColVal(255), + mRayMaxDepth( 5 ), + mvEye(0.0,0.0,5.0), mvLookat(0.0,0.0,0.0), mvUpvec(0.0,1.0,0.0), + mAspect(320.0/200.0), + mFovy(45), mcBackgr(0.0,0.0,0.0), mcAmbientLight(0.0,0.0,0.0), + mDebugOut( 0 ), + mAniStart(0), mAniFrames( -1 ), mAniCount( 0 ), + mFrameSkip( 0 ), + mCounterRays( 0 ), mCounterShades( 0 ), mCounterSceneInter( 0 ), + mOutFilename( "pic" ), + mTreeMaxDepth( 30 ), mTreeMaxTriangles( 30 ), + mpOpenGlAttr(NULL), + mpBlenderAttr(NULL), + mTestSphereEnabled( false ), + mDebugPixelX( -1 ), mDebugPixelY( -1 ), mTestMode(false), + mSingleFrameMode(false), mSingleFrameFilename("") + //,mpRndDirections( NULL ), mpRndRoulette( NULL ) +{ + // create internal attribute list for opengl renderer + mpOpenGlAttr = new AttributeList("__ntlOpenGLRenderer"); + mpBlenderAttr = new AttributeList("__ntlBlenderAttr"); +}; + + +/*****************************************************************************/ +/* Destructor */ +ntlRenderGlobals::~ntlRenderGlobals() { + if(mpOpenGlAttr) delete mpOpenGlAttr; + if(mpBlenderAttr) delete mpBlenderAttr; +} + + +/*****************************************************************************/ +//! get the next random photon direction +//ntlVec3Gfx ntlRenderGlobals::getRandomDirection( void ) { + //return ntlVec3Gfx( + //(mpRndDirections->getGfxReal()-0.5), + //(mpRndDirections->getGfxReal()-0.5), + //(mpRndDirections->getGfxReal()-0.5) ); +//} + diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h index 97c27b06456..2256e85ec96 100644 --- a/intern/elbeem/intern/ntl_world.h +++ b/intern/elbeem/intern/ntl_world.h @@ -11,13 +11,14 @@ #include "ntl_vector3dim.h" #include "ntl_ray.h" +#include "ntl_lighting.h" #include "ntl_geometryobject.h" -#include "ntl_lightobject.h" -#include "ntl_renderglobals.h" -#include "ntl_material.h" #include "simulation_object.h" #include "elbeem.h" class ntlOpenGLRenderer; +class ntlScene; +class SimulationObject; +class ntlRandomStream; class ntlWorld { @@ -100,6 +101,7 @@ class ntlWorld /*! remember the current simulation time */ double mSimulationTime; + /*! first simulation that is valid */ int mFirstSim; @@ -110,4 +112,279 @@ class ntlWorld int mFrameCnt; }; + +//! Class that handles global rendering parameters +class ntlRenderGlobals +{ + public: + //! Standard constructor + ntlRenderGlobals(); + //! Destructor + ~ntlRenderGlobals(); + + //! Returns the renderscene manager (scene changes for each frame) + inline ntlScene *getRenderScene(void) { return mpRenderScene; } + //! Set the renderscene manager + inline void setRenderScene(ntlScene *set) { mpRenderScene = set;} + + //! Returns the simulation scene manager (static scene with sim objects) + inline ntlScene *getSimScene(void) { return mpSimScene; } + //! Set the simulation scene manager + inline void setSimScene(ntlScene *set) { mpSimScene = set;} + + //! Returns the light object list + inline vector<ntlLightObject*> *getLightList(void) { return mpLightList; } + //! Set the light list + inline void setLightList(vector<ntlLightObject*> *set) { mpLightList = set;} + + //! Returns the property object list + inline vector<ntlMaterial*> *getMaterials(void) { return mpMaterials; } + //! Set the property list + inline void setMaterials(vector<ntlMaterial*> *set) { mpMaterials = set;} + + //! Returns the list of simulations + inline vector<SimulationObject*> *getSims(void) { return mpSims; } + //! Set the pointer to the list of simulations + inline void setSims(vector<SimulationObject*> *set) { mpSims = set;} + + //! Set the x resolution + inline void setResX(unsigned int set) { mResX = set; } + //! Set the y resolution + inline void setResY(unsigned int set) { mResY = set; } + //! Set the anti-aliasing depth + inline void setAADepth(int set) { mAADepth = set; } + //! Set the max color value + inline void setMaxColVal(unsigned int set) { mMaxColVal = set; } + //! Set the maximum ray recursion + inline void setRayMaxDepth(unsigned int set) { mRayMaxDepth = set; } + //! Set the eye point + inline void setEye(ntlVec3Gfx set) { mvEye = set; } + //! Set the look at vector + inline void setLookat(ntlVec3Gfx set) { mvLookat = set; } + //! Set the up vector + inline void setUpVec(ntlVec3Gfx set) { mvUpvec = set; } + //! Set the image aspect + inline void setAspect(float set) { mAspect = set; } + //! Set the field of view + inline void setFovy(float set) { mFovy = set; } + //! Set the background color + inline void setBackgroundCol(ntlColor set) { mcBackgr = set; } + //! Set the ambient lighting color + inline void setAmbientLight(ntlColor set) { mcAmbientLight = set; } + //! Set the debug output var + inline void setDebugOut(int set) { mDebugOut = set; } + + //! Set the animation start time + inline void setAniStart(int set) { mAniStart = set; } + //! Set the animation number of frames + inline void setAniFrames(int set) { mAniFrames = set; } + //! Set the animation + inline void setAniCount(int set) { mAniCount = set; } + //! Set the ray counter + inline void setCounterRays(int set) { mCounterRays = set; } + //! Set the ray shades counter + inline void setCounterShades(int set) { mCounterShades = set; } + //! Set the scenen intersection counter + inline void setCounterSceneInter(int set) { mCounterSceneInter = set; } + //! Set if existing frames should be skipped + inline void setFrameSkip(int set) { mFrameSkip = set; } + + //! Set the outfilename + inline void setOutFilename(string set) { mOutFilename = set; } + + //! get Maximum depth for BSP tree + inline void setTreeMaxDepth( int set ) { mTreeMaxDepth = set; } + //! get Maxmimum nr of triangles per BSP tree node + inline void setTreeMaxTriangles( int set ) { mTreeMaxTriangles = set; } + + //! set the enable flag of the test sphere + inline void setTestSphereEnabled( bool set ) { mTestSphereEnabled = set; } + //! set the center of the test sphere + inline void setTestSphereCenter( ntlVec3Gfx set ) { mTestSphereCenter = set; } + //! set the radius of the test sphere + inline void setTestSphereRadius( gfxReal set ) { mTestSphereRadius = set; } + //! set the material name of the test sphere + inline void setTestSphereMaterialName( char* set ) { mTestSphereMaterialName = set; } + //! set debugging pixel coordinates + inline void setDebugPixel( int setx, int sety ) { mDebugPixelX = setx; mDebugPixelY = sety; } + //! set test mode flag + inline void setTestMode( bool set ) { mTestMode = set; } + //! set single frame mode flag + inline void setSingleFrameMode(bool set) {mSingleFrameMode = set; }; + //! set single frame mode filename + inline void setSingleFrameFilename(string set) {mSingleFrameFilename = set; }; + + + //! Return the x resolution + inline unsigned int getResX(void) { return mResX; } + //! Return the y resolution + inline unsigned int getResY(void) { return mResY; } + //! Return the anti-aliasing depth + inline int getAADepth(void) { return mAADepth; } + //! Return the max color value for ppm + inline unsigned int getMaxColVal(void) { return mMaxColVal; } + //! Return the maximum ray recursion + inline unsigned int getRayMaxDepth(void) { return mRayMaxDepth; } + //! Return the eye point + inline ntlVec3Gfx getEye(void) { return mvEye; } + //! Return the look at vector + inline ntlVec3Gfx getLookat(void) { return mvLookat; } + //! Return the up vector + inline ntlVec3Gfx getUpVec(void) { return mvUpvec; } + //! Return the image aspect + inline float getAspect(void) { return mAspect; } + //! Return the field of view + inline float getFovy(void) { return mFovy; } + //! Return the background color + inline ntlColor getBackgroundCol(void) { return mcBackgr; } + //! Return the ambient color + inline ntlColor getAmbientLight(void) { return mcAmbientLight; } + //! Return the debug mode setting + inline int getDebugOut(void) { return mDebugOut; } + + //! Return the animation start time + inline int getAniStart(void) { return mAniStart; } + //! Return the animation frame number + inline int getAniFrames(void) { return mAniFrames; } + //! Return the animation counter + inline int getAniCount(void) { return mAniCount; } + //! Return the ray counter + inline int getCounterRays(void) { return mCounterRays; } + //! Return the ray shades counter + inline int getCounterShades(void) { return mCounterShades; } + //! Return the scene intersection counter + inline int getCounterSceneInter(void) { return mCounterSceneInter; } + //! Check if existing frames should be skipped + inline int getFrameSkip( void ) { return mFrameSkip; } + + + //! Return the outfilename + inline string getOutFilename(void) { return mOutFilename; } + + //! get Maximum depth for BSP tree + inline int getTreeMaxDepth( void ) { return mTreeMaxDepth; } + //! get Maxmimum nr of triangles per BSP tree node + inline int getTreeMaxTriangles( void ) { return mTreeMaxTriangles; } + + //! get open gl attribute list + inline AttributeList* getOpenGlAttributes( void ) { return mpOpenGlAttr; } + //! get blender output attribute list + inline AttributeList* getBlenderAttributes( void ) { return mpBlenderAttr; } + + //! is the test sphere enabled? + inline bool getTestSphereEnabled( void ) { return mTestSphereEnabled; } + //! get the center of the test sphere + inline ntlVec3Gfx getTestSphereCenter( void ) { return mTestSphereCenter; } + //! get the radius of the test sphere + inline gfxReal getTestSphereRadius( void) { return mTestSphereRadius; } + //! get the materialname of the test sphere + inline char *getTestSphereMaterialName( void) { return mTestSphereMaterialName; } + //! get the debug pixel coordinate + inline int getDebugPixelX( void ) { return mDebugPixelX; } + //! get the debug pixel coordinate + inline int getDebugPixelY( void ) { return mDebugPixelY; } + //! get test mode flag + inline bool getTestMode( void ) { return mTestMode; } + //! set single frame mode flag + inline bool getSingleFrameMode() { return mSingleFrameMode; }; + //! set single frame mode filename + inline string getSingleFrameFilename() { return mSingleFrameFilename; }; + + +private: + + /*! Scene storage (dynamic rendering scene) */ + ntlScene *mpRenderScene; + /*! Scene storage (static sim scene, inited only once) */ + ntlScene *mpSimScene; + + //! List of light objects + vector<ntlLightObject*> *mpLightList; + //! List of surface properties + vector<ntlMaterial*> *mpMaterials; + /*! storage for simulations */ + vector<SimulationObject*> *mpSims; + + //! resolution of the picture + unsigned int mResX, mResY; + //! Anti-Aliasing depth + int mAADepth; + //! max color value for ppm + unsigned int mMaxColVal; + /* Maximal ray recursion depth */ + int mRayMaxDepth; + //! The eye point + ntlVec3Gfx mvEye; + //! The look at point + ntlVec3Gfx mvLookat; + //! The up vector + ntlVec3Gfx mvUpvec; + //! The image aspect = Xres/Yres + float mAspect; + //! The horizontal field of view + float mFovy; + //! The background color + ntlColor mcBackgr; + //! The ambient color + ntlColor mcAmbientLight; + //! how much debug output is needed? off by default + char mDebugOut; + + + //! animation properties, start time + int mAniStart; + //! animation properties, number of frames to render + int mAniFrames; + //! animation status, current frame number + int mAniCount; + /*! Should existing picture frames be skipped? */ + int mFrameSkip; + + + //! count the total number of rays created (also used for ray ID's) + int mCounterRays; + //! count the total number of rays shaded + int mCounterShades; + //! count the total number of scene intersections + int mCounterSceneInter; + + /*! filename of output pictures (without suffix or numbers) */ + string mOutFilename; + + //! get Maximum depth for BSP tree + int mTreeMaxDepth; + //! get Maxmimum nr of triangles per BSP tree node + int mTreeMaxTriangles; + + //! attribute list for opengl renderer + AttributeList *mpOpenGlAttr; + //! attribute list for blender output + AttributeList *mpBlenderAttr; + + + //! Enable test sphere? + bool mTestSphereEnabled; + //! Center of the test sphere + ntlVec3Gfx mTestSphereCenter; + //! Radius of the test sphere + gfxReal mTestSphereRadius; + //! Materialname of the test sphere + char *mTestSphereMaterialName; + //! coordinates of the debugging pixel + int mDebugPixelX, mDebugPixelY; + + //! test mode for quick rendering activated?, inited in ntl_scene::buildScene + bool mTestMode; + + //! single frame flag + bool mSingleFrameMode; + //! filename for single frame mode + string mSingleFrameFilename; + + /*! Two random number streams for photon generation (one for the directions, the other for russion roulette) */ + //ntlRandomStream *mpRndDirections, *mpRndRoulette; +}; + + + #endif diff --git a/intern/elbeem/intern/parametrizer.cpp b/intern/elbeem/intern/parametrizer.cpp index 581b04216bb..50d544d2bcf 100644 --- a/intern/elbeem/intern/parametrizer.cpp +++ b/intern/elbeem/intern/parametrizer.cpp @@ -10,6 +10,9 @@ #include <sstream> #include "parametrizer.h" +// debug output flag +#define DEBUG_PARAMCHANNELS 0 + /*! param seen debug string array */ char *ParamStrings[] = { "RelaxTime", @@ -19,7 +22,7 @@ char *ParamStrings[] = { "DomainSize", "GravityForce", "TimeLength", - "StepTime", + "Timestep", "Size", "TimeFactor", "AniFrames", @@ -42,26 +45,25 @@ char *ParamStrings[] = { * Default constructor *****************************************************************************/ Parametrizer::Parametrizer( void ) : - mRelaxTime( 1.0 ), mReynolds( 0.0 ), - mViscosity( 8.94e-7 ), mcViscosity( 8.94e-7 ), + mcViscosity( 8.94e-7 ), mSoundSpeed( 1500 ), mDomainSize( 0.1 ), mCellSize( 0.01 ), - mGravity(0.0, 0.0, 0.0), mcGravity( ParamVec(0.0) ), - mLatticeGravity(0.0, 0.0, 0.0), - mStepTime(0.0001), mDesiredStepTime(-1.0), - mMaxStepTime(-1.0), - mMinStepTime(-1.0), + 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 ), - //mAniFrames(0), - mAniFrameTime(0.0001), mcAniFrameTime(0.0001), + mcAniFrameTime(0.0001), + mAniFrameTime(0.0001), + mTimeStepScale(1.0), mAniStart(0.0), - mExtent(1.0, 1.0, 1.0), mSurfaceTension( 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)/*FIXME test 0.16666 */, mTadapLevels(1), + mTadapMaxOmega(2.0), mTadapMaxSpeed(0.1), mTadapLevels(1), + mFrameNum(0), mSeenValues( 0 ), mCalculatedValues( 0 ) - //mActive( false ) { } @@ -89,15 +91,8 @@ void Parametrizer::parseAttrList() mSetupType = mpAttrs->readString("p_setup",mSetupType, "Parametrizer","mSetupType", false); // real params - mRelaxTime = mpAttrs->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); - mcViscosity = mpAttrs->readChannelFloat("p_viscosity"); - if(getAttributeList()->exists("p_viscosity")) seenThis( PARAM_VISCOSITY ); + 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 ); @@ -105,27 +100,24 @@ void Parametrizer::parseAttrList() 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:"<<mAniFrameTime<<", resetting to 0.1"); + errMsg("Parametrizer::parseAttrList","Invalid real world domain size:"<<mDomainSize<<", resetting to 0.1"); mDomainSize = 0.1; } - mGravity = mpAttrs->readVec3d("p_gravity",mGravity, "Parametrizer","mGravity", false); - mcGravity = mpAttrs->readChannelVec3d("p_gravity"); - if(getAttributeList()->exists("p_gravity")) seenThis( PARAM_GRAVITY ); + if(getAttributeList()->exists("p_gravity")) { // || (!mcGravity.isInited()) ) { + mcGravity = mpAttrs->readChannelVec3d("p_gravity"); seenThis( PARAM_GRAVITY ); + } - mStepTime = mpAttrs->readFloat("p_steptime",mStepTime, "Parametrizer","mStepTime", false); + 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 ); - mAniFrameTime = mpAttrs->readFloat("p_aniframetime",mAniFrameTime, "Parametrizer","mAniFrameTime", false); - mcAniFrameTime = mpAttrs->readChannelFloat("p_aniframetime"); - if(getAttributeList()->exists("p_aniframetime")) { seenThis( PARAM_ANIFRAMETIME ); } - if(mAniFrameTime<0.0) { - errMsg("Parametrizer::parseAttrList","Invalid frame time:"<<mAniFrameTime<<", resetting to 0.0001"); - mAniFrameTime = 0.0001; + 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 ); @@ -134,14 +126,14 @@ void Parametrizer::parseAttrList() mAniStart = 0.0; } - mSurfaceTension = mpAttrs->readFloat("p_surfacetension",mSurfaceTension, "Parametrizer","mSurfaceTension", false); - if(getAttributeList()->exists("p_surfacetension")) seenThis( PARAM_SURFACETENSION ); + //mSurfaceTension = mpAttrs->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 ); - mCellSize = mpAttrs->readFloat("p_cellsize",mCellSize, "Parametrizer","mCellSize", false); - if(getAttributeList()->exists("p_cellsize")) seenThis( PARAM_CELLSIZE ); + 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 ); @@ -156,16 +148,28 @@ void Parametrizer::parseAttrList() /****************************************************************************** *! advance to next render/output frame *****************************************************************************/ -void Parametrizer::setFrameNum(int num) { - double frametime = (double)num; - double oldval = mAniFrameTime; - mAniFrameTime = mcAniFrameTime.get(frametime); - if(mAniFrameTime<0.0) { - errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<mAniFrameTime<<" at frame "<<num<<", resetting to "<<oldval); - mAniFrameTime = oldval; +void Parametrizer::setFrameNum(int frame) { + //double oldval = mAniFrameTime; + //mAniFrameTime = mcAniFrameTime.get(frametime); + //if(mAniFrameTime<0.0) { + //errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<mAniFrameTime<<" at frame "<<frame<<", resetting to "<<oldval); + //mAniFrameTime = oldval; } + //errMsg("ChannelAnimDebug","anim: anif"<<mAniFrameTime<<" at "<<frame<<" "); + // debug getAttributeList()->find("p_aniframetime")->print(); + mFrameNum = frame; + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","setFrameNum frame-num="<<mFrameNum); +} +/*! get time of an animation frame (renderer) */ +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:"<<anift<<" at frame "<<frame<<", resetting to "<<resetv); + anift = resetv; } - //errMsg("ChannelAnimDebug","anim: anif"<<mAniFrameTime<<" at "<<num<<" "); - getAttributeList()->find("p_aniframetime")->print(); + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<<frame<<", frametime="<<anift<<" "); + return anift; } /****************************************************************************** @@ -173,8 +177,8 @@ void Parametrizer::setFrameNum(int num) { *****************************************************************************/ ParamVec Parametrizer::calculateAddForce(ParamVec vec, string usage) { - ParamVec ret = vec * (mStepTime*mStepTime) /mCellSize; - debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<<ret<<" for '"<<usage<<"', org = "<<vec<<" dt="<<mStepTime ,10); + ParamVec ret = vec * (mTimestep*mTimestep) /mCellSize; + debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<<ret<<" for '"<<usage<<"', org = "<<vec<<" dt="<<mTimestep ,10); return ret; } @@ -196,109 +200,98 @@ ParamFloat Parametrizer::calculateCellSize(void) /* simple calulation functions */ /*****************************************************************************/ -/*! get omega for LBM */ -//ParamFloat Parametrizer::calculateOmega( void ) { return (1.0/mRelaxTime); } /*! get omega for LBM from channel */ -ParamFloat Parametrizer::calculateOmega( ParamFloat t ) { - mViscosity = mcViscosity.get(t); - ParamFloat viscStar = calculateLatticeViscosity(); - mRelaxTime = (6.0 * viscStar + 1) * 0.5; - //errMsg("ChannelAnimDebug","anim: omega"<<(1.0/mRelaxTime)<<" v"<<mViscosity<<" at "<<t<<" "); - return (1.0/mRelaxTime); +ParamFloat Parametrizer::calculateOmega( double time ) { + ParamFloat viscStar = calculateLatticeViscosity(time); + ParamFloat relaxTime = (6.0 * viscStar + 1) * 0.5; + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateOmega viscStar="<<viscStar<<" relaxtime="<<relaxTime); + return (1.0/relaxTime); } -/*! get no. of timesteps for LBM */ -//int calculateNoOfSteps( void ) { -int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) { - return (int)(timelen/mStepTime); +/*! get external force x component */ +ParamVec Parametrizer::calculateGravity( double time ) { + ParamVec grav = mcGravity.get(time); + ParamFloat forceFactor = (mTimestep *mTimestep)/mCellSize; + ParamVec latticeGravity = grav * forceFactor; + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateGravity grav="<<grav<<" ff"<<forceFactor<<" lattGrav="<<latticeGravity); + return latticeGravity; } -/*! get external force x component */ -//ParamVec Parametrizer::calculateGravity( void ) { return mLatticeGravity; } -ParamVec Parametrizer::calculateGravity( ParamFloat t ) { - mGravity = mcGravity.get(t); - ParamFloat forceFactor = (mStepTime *mStepTime)/mCellSize; - mLatticeGravity = mGravity * forceFactor; - //errMsg("ChannelAnimDebug","anim: grav"<<mLatticeGravity<<" g"<<mGravity<<" at "<<t<<" "); - return mLatticeGravity; +/*! calculate the lattice viscosity */ +ParamFloat Parametrizer::calculateLatticeViscosity( double time ) { + // check seen values + int reqValues = PARAM_VISCOSITY | PARAM_STEPTIME; + if(!checkSeenValues( reqValues ) ){ + errMsg("Parametrizer::calculateLatticeViscosity"," Missing arguments!"); + } + ParamFloat viscStar = mcViscosity.get(time) * mTimestep / (mCellSize*mCellSize); + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateLatticeViscosity viscStar="<<viscStar); + return viscStar; } /*! get no of steps for the given length in seconds */ int Parametrizer::calculateStepsForSecs( ParamFloat s ) { - return (int)(s/mStepTime); + return (int)(s/mTimestep); } /*! get start time of animation */ int Parametrizer::calculateAniStart( void ) { - return (int)(mAniStart/mStepTime); + return (int)(mAniStart/mTimestep); } /*! get no of steps for a single animation frame */ -int Parametrizer::calculateAniStepsPerFrame( void ) { +int Parametrizer::calculateAniStepsPerFrame(int frame) { if(!checkSeenValues(PARAM_ANIFRAMETIME)) { errFatal("Parametrizer::calculateAniStepsPerFrame", "Missing ani frame time argument!", SIMWORLD_INITERROR); return 1; } - int value = (int)(mAniFrameTime/mStepTime); + int value = (int)(getAniFrameTime(frame)/mTimestep); if((value<0) || (value>1000000)) { - errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<mAniFrameTime<<") <> ani-frame-time ("<<mStepTime<<") settings, aborting...", SIMWORLD_INITERROR); + errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<mAniFrameTime<<") <> ani-frame-time ("<<mTimestep<<") settings, aborting...", SIMWORLD_INITERROR); return 1; } return value; } +/*! get no. of timesteps for LBM */ +int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) { + return (int)(timelen/mTimestep); +} + /*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */ ParamVec Parametrizer::calculateExtent( void ) { return mExtent; } /*! get (scaled) surface tension */ -ParamFloat Parametrizer::calculateSurfaceTension( void ) { - return mSurfaceTension; +//ParamFloat Parametrizer::calculateSurfaceTension( void ) { return mSurfaceTension; } + +/*! get the length of a single time step */ +// explicity scaled by time factor for refinement +ParamFloat Parametrizer::getTimestep( void ) { + return mTimestep; } /*! calculate lattice velocity from real world value [m/s] */ ParamVec Parametrizer::calculateLattVelocityFromRw( ParamVec ivel ) { ParamVec velvec = ivel; velvec /= mCellSize; - velvec *= mStepTime; + velvec *= mTimestep; return velvec; } /*! calculate real world [m/s] velocity from lattice value */ ParamVec Parametrizer::calculateRwVelocityFromLatt( ParamVec ivel ) { ParamVec velvec = ivel; velvec *= mCellSize; - velvec /= mStepTime; + velvec /= mTimestep; return velvec; } -/*! get the length of a single time step */ -// explicity scaled by time factor for refinement -// testing purposes (e.g. fsgr solver) -// not working... done manually in solver -ParamFloat Parametrizer::getStepTime( void ) { - //return mTimeFactor * mStepTime; - return mStepTime; -} - -/*! calculate the lattice viscosity */ -ParamFloat Parametrizer::calculateLatticeViscosity( void ) { - // check seen values - int reqValues = PARAM_VISCOSITY | PARAM_STEPTIME; // |PARAM_CELLSIZE | PARAM_GRAVITY; - if(!checkSeenValues( reqValues ) ){ - errMsg("Parametrizer::calculateLatticeViscosity"," Missing arguments!"); - } - ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize); - return viscStar; -} - /*! get g star value with fhvol calculations */ ParamFloat Parametrizer::getCurrentGStar( void ) { ParamFloat gStar = mGStar; // check? TODO get from mNormalizedGStar? - if(mFluidVolumeHeight>0.0) { - gStar = mGStar/mFluidVolumeHeight; - } + if(mFluidVolumeHeight>0.0) { gStar = mGStar/mFluidVolumeHeight; } return gStar; } @@ -306,18 +299,12 @@ ParamFloat Parametrizer::getCurrentGStar( void ) { * 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( bool silent ) +bool Parametrizer::calculateAllMissingValues( double time, bool silent ) { bool init = false; // did we init correctly? int valuesChecked = 0; int reqValues; - // are we active anyway? - //if(!mActive) { - // not active - so there's nothing to calculate - //return true; - //} - // we always need the sizes reqValues = PARAM_SIZE; valuesChecked |= reqValues; @@ -326,10 +313,6 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) return false; } - if(checkSeenValues(PARAM_CELLSIZE)) { - errMsg("Parametrizer::calculateAllMissingValues"," Dont explicitly set cell size (use domain size instead)"); - return false; - } if(!checkSeenValues(PARAM_DOMAINSIZE)) { errMsg("Parametrizer::calculateAllMissingValues"," Missing domain size argument!"); return false; @@ -343,7 +326,6 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) /* Carolin init , see DA for details */ ParamFloat maxDeltaT = 0.0; - ParamFloat maxSpeed = 1.0/6.0; // for rough reynolds approx /* normalized gstar init */ reqValues = PARAM_NORMALIZEDGSTAR; @@ -355,7 +337,13 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) errMsg("Parametrizer::calculateAllMissingValues","Invalid NormGstar: "<<mNormalizedGStar<<"... resetting to "<<normgstarReset); mNormalizedGStar = normgstarReset; } + mGStar = mNormalizedGStar/maxsize; + +// TODO FIXME add use testdata check! +mGStar = mNormalizedGStar/mSizez; +errMsg("Warning","Used z-dir for gstar!"); + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star set to "<<mGStar<<" from normalizedGStar="<<mNormalizedGStar ,1); seenThis(PARAM_GSTAR); } @@ -370,20 +358,19 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) mGStar = gstarReset; } - ParamFloat gStar = getCurrentGStar(); + ParamFloat gStar = getCurrentGStar(); // mGStar if(mFluidVolumeHeight>0.0) { debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," height"<<mFluidVolumeHeight<<" resGStar = "<<gStar, 10); } if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star = "<<gStar, 10); - //if(!checkSeenValues(PARAM_GRAVITY)) { errMsg("Parametrizer::calculateAllMissingValues","Setup requires gravity force!"); goto failure; } ParamFloat forceStrength = 0.0; - if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm(mGravity); } - //if(forceStrength<=0) { errMsg("Parametrizer::calculateAllMissingValues"," Init failed - forceStrength = "<<forceStrength); goto failure; } + //if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm( calculateGravity(time) ); } + if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm( mcGravity.get(time) ); } // determine max. delta density per timestep trough gravity force if(forceStrength>0.0) { - maxDeltaT = sqrt( gStar*mCellSize/forceStrength ); + maxDeltaT = sqrt( gStar*mCellSize *mTimeStepScale /forceStrength ); } else { // use 1 lbm setp = 1 anim step as max maxDeltaT = mAniFrameTime; @@ -391,22 +378,22 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," targeted step time = "<<maxDeltaT, 10); - ParamFloat viscStarFac = mViscosity/(mCellSize*mCellSize); - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," viscStarFac = "<<viscStarFac, 10); + //ParamFloat viscStarFac = mViscosity/(mCellSize*mCellSize); + //if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," viscStarFac = "<<viscStarFac<<" viscosity:"<<mViscosity, 10); // time step adaptivty, only for caro with max sim speed ParamFloat setDeltaT = maxDeltaT; - if(mDesiredStepTime>0.0) { + if(mDesiredTimestep>0.0) { // explicitly set step time according to max velocity in sim - setDeltaT = mDesiredStepTime; - mDesiredStepTime = -1.0; + setDeltaT = mDesiredTimestep; if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," desired step time = "<<setDeltaT, 10); + mDesiredTimestep = -1.0; } else { // just use max delta t as current } // and once for init determine minimal delta t by omega max. - if((mMinStepTime<0.0) || (mMaxStepTime<0.0)) { + if((mMinTimestep<0.0) || (mMaxTimestep<0.0)) { ParamFloat minDeltaT; ParamFloat maxOmega = mTadapMaxOmega; ParamFloat minRelaxTime = 1.0/maxOmega; @@ -417,8 +404,8 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) maxOmega = 1.0/minRelaxTime; if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," maxOmega="<<maxOmega<<" minRelaxTime="<<minRelaxTime<<" levels="<<mTadapLevels, 1); // visc-star for min relax time to calculate min delta ta - if(mViscosity>0.0) { - minDeltaT = ((2.0*minRelaxTime-1.0)/6.0) * mCellSize * mCellSize / mViscosity; + if(mcViscosity.get(time)>0.0) { + minDeltaT = ((2.0*minRelaxTime-1.0)/6.0) * mCellSize * mCellSize / mcViscosity.get(time); } else { // visc=0, this is not physical, but might happen minDeltaT = 0.0; @@ -426,62 +413,37 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," min delta t = "<<minDeltaT<<" , range = " << (maxDeltaT/minDeltaT) ,1); // sim speed + accel shouldnt exceed 0.1? - mMaxStepTime = maxDeltaT; - mMinStepTime = minDeltaT; + mMaxTimestep = maxDeltaT; + mMinTimestep = minDeltaT; // only use once... } - setStepTime( setDeltaT ); // set mStepTime to new value - - //ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize); - ParamFloat viscStar = calculateLatticeViscosity(); - mRelaxTime = (6.0 * viscStar + 1) * 0.5; + setTimestep( setDeltaT ); // set mTimestep to new value init = true; } // finish init if(init) { - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," omega = "<<calculateOmega(0.0)<<", relax time = "<<mRelaxTime<<", delt="<<mStepTime,1); - //debMsgStd("Parametrizer::calculateAllMissingValues: lbm steps = "<<calculateNoOfSteps()<<" ",1); + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," omega = "<<calculateOmega(0.0)<<", delt="<<mTimestep,1); if(checkSeenValues(PARAM_GRAVITY)) { - ParamFloat forceFactor = (mStepTime *mStepTime)/mCellSize; - //if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," given force = "<<PRINT_NTLVEC(mGravity),1); - mLatticeGravity = mGravity * forceFactor; - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mGravity)<<", scaled with "<<forceFactor<<" to "<<mLatticeGravity,1); - } - - 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 = "<<massDelta, 10); - - mSurfaceTension = mSurfaceTension*mStepTime*mStepTime/massDelta; - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," surface tension = "<<mSurfaceTension<<" ",1); + ParamFloat forceFactor = (mTimestep *mTimestep)/mCellSize; // only used for printing... + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mcGravity.get(time))<<", scaled with "<<forceFactor<<" to "<<calculateGravity(time),1); } mExtent = ParamVec( mCellSize*mSizex, mCellSize*mSizey, mCellSize*mSizez ); - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m ",1); + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m , gs:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<" cs:"<<mCellSize,1); if(!checkSeenValues(PARAM_ANIFRAMETIME)) { errFatal("Parametrizer::calculateAllMissingValues"," Warning no ani frame time given!", SIMWORLD_INITERROR); - mAniFrameTime = mStepTime; + mAniFrameTime = mTimestep; } - //mAniFrameTime = mAniFrames * mStepTime; - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame()<<" ", 1); + //mAniFrameTime = mAniFrames * mTimestep; + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame(mFrameNum)<<" for frame "<<mFrameNum, 1); if((checkSeenValues(PARAM_ANISTART))&&(calculateAniStart()>0)) { if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<<calculateAniStart()<<" ",1); } - - // calculate reynolds number - if(mViscosity>0.0) { - ParamFloat reynoldsApprox = -1.0; - ParamFloat gridSpeed = (maxSpeed*mCellSize/mStepTime); - reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity; - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<<mDomainSize<<", assuming V="<<gridSpeed<<")= "<<reynoldsApprox<<" ", 1); - } if(!SIMWORLD_OK()) return false; // everything ok @@ -510,7 +472,59 @@ bool Parametrizer::calculateAllMissingValues( bool silent ) +// 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 = "<<massDelta, 10); + + mSurfaceTension = mSurfaceTension*mTimestep*mTimestep/massDelta; + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," surface tension = "<<mSurfaceTension<<" ",1); + } // */ + +// probably just delete: + + /*! reynolds number (calculated from domain length and max. speed [dimensionless] */ + //ParamFloat mReynolds; + + /*! set relaxation time */ + //void setRelaxTime(ParamFloat set) { mRelaxTime = set; seenThis( PARAM_RELAXTIME ); } + /*! get relaxation time */ + //ParamFloat getRelaxTime( void ) { return mRelaxTime; } + /*! set reynolds number */ + //void setReynolds(ParamFloat set) { mReynolds = set; seenThis( PARAM_REYNOLDS ); } + /*! get reynolds number */ + //ParamFloat getReynolds( void ) { return mReynolds; } + + // calculate reynolds number + /*if(mViscosity>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="<<mDomainSize<<", assuming V="<<gridSpeed<<")= "<<reynoldsApprox<<" ", 1); + } // */ + + //? mRelaxTime = mpAttrs->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; diff --git a/intern/elbeem/intern/parametrizer.h b/intern/elbeem/intern/parametrizer.h index 9140deefc0b..471fb571e35 100644 --- a/intern/elbeem/intern/parametrizer.h +++ b/intern/elbeem/intern/parametrizer.h @@ -32,7 +32,6 @@ typedef ntlVec3d ParamVec; #define PARAM_ANISTART (1<<12) #define PARAM_SURFACETENSION (1<<13) #define PARAM_DENSITY (1<<14) -#define PARAM_CELLSIZE (1<<15) #define PARAM_GSTAR (1<<16) #define PARAM_SIMMAXSPEED (1<<18) #define PARAM_FLUIDVOLHEIGHT (1<<19) @@ -58,9 +57,9 @@ class Parametrizer { void parseAttrList( void ); /*! function that tries to calculate all the missing values from the given ones - * prints errors and returns false if thats not possible */ - bool calculateAllMissingValues( bool silent = false ); - bool oldCalculateAllMissingValues( void ); + * prints errors and returns false if thats not possible + * currently needs time value as well */ + bool calculateAllMissingValues( double time, bool silent ); /*! is the parametrizer used at all? */ bool isUsed() { return true; } @@ -83,7 +82,9 @@ class Parametrizer { /*! check if the calculated flags are set in the values int */ bool checkCalculatedValues(int check) { /*errorOut( " b"<<((mSeenValues&check)==check) );*/ return ((mCalculatedValues&check)==check); } /*! advance to next render/output frame */ - void setFrameNum(int num); + void setFrameNum(int frame); + ParamFloat getAniFrameTime(int frame); + ParamFloat getCurrentAniFrameTime(){ return getAniFrameTime(mFrameNum); }; /*! scale a given speed vector in m/s to lattice values * usage string is only needed for debugging */ @@ -91,17 +92,17 @@ class Parametrizer { /* simple calulation functions */ /*! get omega for LBM */ - ParamFloat calculateOmega( ParamFloat t ); + ParamFloat calculateOmega( double time ); /*! get no. of timesteps for LBM */ int calculateNoOfSteps( ParamFloat timelen ); /*! get external force x component */ - ParamVec calculateGravity( ParamFloat t ); + ParamVec calculateGravity( double time ); /*! get no of steps for the given length in seconds */ int calculateStepsForSecs( ParamFloat s ); + /*! get no of steps for a singel animation frame */ + int calculateAniStepsPerFrame(int frame); /*! get start time of animation */ int calculateAniStart( void ); - /*! get no of steps for a singel animation frame */ - int calculateAniStepsPerFrame( void ); /*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */ ParamVec calculateExtent( void ); /*! get (scaled) surface tension */ @@ -111,7 +112,7 @@ class Parametrizer { /*! calculate size of a single cell */ ParamFloat calculateCellSize(void); /*! calculate the lattice viscosity */ - ParamFloat calculateLatticeViscosity(void); + ParamFloat calculateLatticeViscosity( double time ); /*! calculate lattice velocity from real world value [m/s] */ ParamVec calculateLattVelocityFromRw( ParamVec ivel ); @@ -119,23 +120,9 @@ class Parametrizer { ParamVec calculateRwVelocityFromLatt( ParamVec ivel ); - /*! set relaxation time */ - void setRelaxTime(ParamFloat set) { mRelaxTime = set; seenThis( PARAM_RELAXTIME ); } - /*! get relaxation time */ - ParamFloat getRelaxTime( void ) { return mRelaxTime; } - - /*! set reynolds number */ - void setReynolds(ParamFloat set) { mReynolds = set; seenThis( PARAM_REYNOLDS ); } - /*! get reynolds number */ - ParamFloat getReynolds( void ) { return mReynolds; } - /*! set kinematic viscosity */ - void setViscosity(ParamFloat set) { - mViscosity = set; seenThis( PARAM_VISCOSITY ); - mcViscosity = AnimChannel<ParamFloat>(mViscosity); - } - /*! get current kinematic viscosity (warning - this might change over time) */ - ParamFloat getViscosity( void ) { return mViscosity; } + void setViscosity(ParamFloat set) { mcViscosity = AnimChannel<ParamFloat>(set); seenThis( PARAM_VISCOSITY ); } + void initViscosityChannel(vector<ParamFloat> val, vector<double> time) { mcViscosity = AnimChannel<ParamFloat>(val,time); } /*! set speed of sound */ void setSoundSpeed(ParamFloat set) { mSoundSpeed = set; seenThis( PARAM_SOUNDSPEED ); } @@ -143,25 +130,21 @@ class Parametrizer { ParamFloat getSoundSpeed( void ) { return mSoundSpeed; } /*! set the external force */ - void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { - mGravity = ParamVec(setx,sety,setz); seenThis( PARAM_GRAVITY ); - mcGravity = AnimChannel<ParamVec>(mGravity); - } - void setGravity(ParamVec set) { - mGravity = set; seenThis( PARAM_GRAVITY ); - mcGravity = AnimChannel<ParamVec>(mGravity); - } + void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mcGravity = AnimChannel<ParamVec>(ParamVec(setx,sety,setz)); seenThis( PARAM_GRAVITY ); } + void setGravity(ParamVec set) { mcGravity = AnimChannel<ParamVec>(set); seenThis( PARAM_GRAVITY ); } + void initGravityChannel(vector<ParamVec> val, vector<double> time) { mcGravity = AnimChannel<ParamVec>(val,time); } + ParamVec getGravity(double time) { return mcGravity.get( time ); } /*! set the length of a single time step */ - void setStepTime(ParamFloat set) { mStepTime = set; seenThis( PARAM_STEPTIME ); } + void setTimestep(ParamFloat set) { mTimestep = set; seenThis( PARAM_STEPTIME ); } /*! get the length of a single time step */ - ParamFloat getStepTime( void); + ParamFloat getTimestep( void); /*! set a desired step time for rescaling/adaptive timestepping */ - void setDesiredStepTime(ParamFloat set) { mDesiredStepTime = set; } + void setDesiredTimestep(ParamFloat set) { mDesiredTimestep = set; } /*! get the length of a single time step */ - ParamFloat getMaxStepTime( void ) { return mMaxStepTime; } + ParamFloat getMaxTimestep( void ) { return mMaxTimestep; } /*! get the length of a single time step */ - ParamFloat getMinStepTime( void ) { return mMinStepTime; } + ParamFloat getMinTimestep( void ) { return mMinTimestep; } /*! set the time scaling factor */ void setTimeFactor(ParamFloat set) { mTimeFactor = set; seenThis( PARAM_TIMEFACTOR ); } @@ -173,20 +156,15 @@ class Parametrizer { void setSize(int i,int j, int k) { mSizex = i; mSizey = j; mSizez = k; seenThis( PARAM_SIZE ); } /*! set time of an animation frame (renderer) */ - void setAniFrameTime(ParamFloat set) { mAniFrameTime = set; seenThis( PARAM_ANIFRAMETIME ); } - /*! get time of an animation frame (renderer) */ - ParamFloat getAniFrameTime( void ) { return mAniFrameTime; } + //void setAniFrameTime(ParamFloat set) { mAniFrameTime = set; seenThis( PARAM_ANIFRAMETIME ); } + void setAniFrameTimeChannel(ParamFloat set) { mcAniFrameTime = AnimChannel<ParamFloat>(set); seenThis( PARAM_ANIFRAMETIME ); } + void initAniFrameTimeChannel(vector<ParamFloat> val, vector<double> time) { mcAniFrameTime = AnimChannel<ParamFloat>(val,time); seenThis( PARAM_ANIFRAMETIME ); } /*! set starting time of the animation (renderer) */ void setAniStart(ParamFloat set) { mAniStart = set; seenThis( PARAM_ANISTART ); } /*! get starting time of the animation (renderer) */ ParamFloat getAniStart( void ) { return mAniStart; } - /*! 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; } - /*! set fluid density */ void setDensity(ParamFloat set) { mDensity = set; seenThis( PARAM_DENSITY ); } /*! get fluid density */ @@ -213,8 +191,8 @@ class Parametrizer { /*! get the size of a single lbm cell */ ParamFloat getDomainSize( void ) { return mDomainSize; } - /*! set the size of a single lbm cell */ - void setCellSize(ParamFloat set) { mCellSize = set; seenThis( PARAM_CELLSIZE ); } + /*! set the size of a single lbm cell (dont use, normally set by domainsize and resolution) */ + void setCellSize(ParamFloat set) { mCellSize = set; } /*! get the size of a single lbm cell */ ParamFloat getCellSize( void ) { return mCellSize; } @@ -246,9 +224,6 @@ class Parametrizer { /*! get maximum allowed omega for time adaptivity */ int getTadapLevels( void ) { return mTadapLevels; } - /*! get current gravity value (warning this might change over time!) */ - ParamVec getGravity( void ) { return mGravity; } - /*! set */ // void set(ParamFloat set) { m = set; seenThis( PARAM_ ); } /*! get */ @@ -258,15 +233,7 @@ class Parametrizer { private: - /*! relaxation time [s] */ - ParamFloat mRelaxTime; - - /*! reynolds number (calculated from domain length and max. speed [dimensionless] */ - ParamFloat mReynolds; - /*! kinematic viscosity of the fluid [m^2/s] */ - ParamFloat mViscosity; - /*! animated channel */ AnimChannel<ParamFloat> mcViscosity; /*! speed of sound of the fluid [m/s] */ @@ -282,18 +249,14 @@ class Parametrizer { ParamFloat mTimeStep; /*! external force as acceleration [m/s^2] */ - ParamVec mGravity; AnimChannel<ParamVec> mcGravity; - /*! force converted to lattice units (returned by calc gravity) */ - ParamVec mLatticeGravity; - /*! length of one time step in the simulation */ - ParamFloat mStepTime; + ParamFloat mTimestep; /*! desired step time for rescaling/adaptive timestepping, only regarded if >0.0, reset after usage */ - ParamFloat mDesiredStepTime; + ParamFloat mDesiredTimestep; /*! minimal and maximal step times for current setup */ - ParamFloat mMaxStepTime, mMinStepTime; + ParamFloat mMaxTimestep, mMinTimestep; /*! domain resoultion, the same values as in lbmsolver */ int mSizex, mSizey, mSizez; @@ -302,9 +265,11 @@ class Parametrizer { ParamFloat mTimeFactor; /*! for renderer - length of an animation step [s] */ - ParamFloat mAniFrameTime; - /*! animated channel */ AnimChannel<ParamFloat> mcAniFrameTime; + /*! current value for next frame */ + ParamFloat mAniFrameTime; + /*! time step scaling factor for testing/debugging */ + ParamFloat mTimeStepScale; /*! for renderer - start time of the animation [s] */ ParamFloat mAniStart; @@ -312,9 +277,6 @@ class Parametrizer { /*! extent of the domain in meters */ ParamVec mExtent; - /*! surface tension, [kg/s^2] */ - ParamFloat mSurfaceTension; - /*! fluid density [kg/m^3], default 1.0 g/cm^3 */ ParamFloat mDensity; @@ -334,6 +296,8 @@ class Parametrizer { /*! no. of levels for max omega (set by fsgr, not in cfg file) */ int mTadapLevels; + /*! remember current frame number */ + int mFrameNum; /*! values that are seen for this simulation */ int mSeenValues; @@ -341,9 +305,6 @@ class Parametrizer { /*! values that are calculated from the seen ones for this simulation */ int mCalculatedValues; - /*! is the parametrizer active? */ - //bool mActive; - /*! pointer to the attribute list */ AttributeList *mpAttrs; }; diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp index 1321edb19cc..0a5af90564a 100644 --- a/intern/elbeem/intern/particletracer.cpp +++ b/intern/elbeem/intern/particletracer.cpp @@ -15,7 +15,9 @@ #include "particletracer.h" #include "ntl_matrices.h" #include "ntl_ray.h" -#include "ntl_scene.h" +#include "ntl_matrices.h" + +#include <zlib.h> @@ -24,24 +26,43 @@ *****************************************************************************/ ParticleTracer::ParticleTracer() : ntlGeometryObject(), - mParts(1), - mNumParticles(0), mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0), - mPartSize(0.01), mTrailScale(1.0), + mParts(), + //mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0), + mPartSize(0.01), mStart(-1.0), mEnd(1.0), mSimStart(-1.0), mSimEnd(1.0), mPartScale(1.0) , mPartHeadDist( 0.5 ), mPartTailDist( -4.5 ), mPartSegments( 4 ), mValueScale(0), - mValueCutoffTop(0.0), mValueCutoffBottom(0.0) + mValueCutoffTop(0.0), mValueCutoffBottom(0.0), + mDumpParts(0), mShowOnly(0), mpTrafo(NULL) { + // check env var +#ifdef ELBEEM_PLUGIN + mDumpParts=1; // default on +#endif // ELBEEM_PLUGIN + if(getenv("ELBEEM_DUMPPARTICLE")) { // DEBUG! + int set = atoi( getenv("ELBEEM_DUMPPARTICLE") ); + if((set>=0)&&(set!=mDumpParts)) { + mDumpParts=set; + debMsgStd("ParticleTracer::notifyOfDump",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mDumpParts to "<<set<<","<<mDumpParts,8); + } + } }; +ParticleTracer::~ParticleTracer() { + debMsgStd("ParticleTracer::~ParticleTracer",DM_MSG,"destroyed",10); +} + /*****************************************************************************/ //! parse settings from attributes (dont use own list!) /*****************************************************************************/ void ParticleTracer::parseAttrList(AttributeList *att) { - AttributeList *tempAtt = mpAttrs; + AttributeList *tempAtt = mpAttrs; mpAttrs = att; + int mNumParticles =0; // UNUSED + int mTrailLength = 0; // UNUSED + int mTrailInterval= 0; // UNUSED mNumParticles = mpAttrs->readInt("particles",mNumParticles, "ParticleTracer","mNumParticles", false); mTrailLength = mpAttrs->readInt("traillength",mTrailLength, "ParticleTracer","mTrailLength", false); mTrailInterval= mpAttrs->readInt("trailinterval",mTrailInterval, "ParticleTracer","mTrailInterval", false); @@ -54,17 +75,18 @@ void ParticleTracer::parseAttrList(AttributeList *att) mValueCutoffTop = mpAttrs->readFloat("part_valcutofftop",mValueCutoffTop, "ParticleTracer","mValueCutoffTop", false); mValueCutoffBottom = mpAttrs->readFloat("part_valcutoffbottom",mValueCutoffBottom, "ParticleTracer","mValueCutoffBottom", false); - mTrailScale = mpAttrs->readFloat("trail_scale",mTrailScale, "ParticleTracer","mTrailScale", false); + mDumpParts = mpAttrs->readInt ("part_dump",mDumpParts, "ParticleTracer","mDumpParts", false); + mShowOnly = mpAttrs->readInt ("part_showonly",mShowOnly, "ParticleTracer","mShowOnly", false); string matPart; matPart = mpAttrs->readString("material_part", "default", "ParticleTracer","material", false); setMaterialName( matPart ); // trail length has to be at least one, if anything should be displayed - if((mNumParticles>0)&&(mTrailLength<2)) mTrailLength = 2; + //if((mNumParticles>0)&&(mTrailLength<2)) mTrailLength = 2; // restore old list mpAttrs = tempAtt; - mParts.resize(mTrailLength*mTrailInterval); + //mParts.resize(mTrailLength*mTrailInterval); } /****************************************************************************** @@ -74,38 +96,67 @@ void ParticleTracer::draw() { } +/****************************************************************************** + * init trafo matrix + *****************************************************************************/ +void ParticleTracer::initTrafoMatrix() { + ntlVec3Gfx scale = ntlVec3Gfx( + (mEnd[0]-mStart[0])/(mSimEnd[0]-mSimStart[0]), + (mEnd[1]-mStart[1])/(mSimEnd[1]-mSimStart[1]), + (mEnd[2]-mStart[2])/(mSimEnd[2]-mSimStart[2]) + ); + ntlVec3Gfx trans = mStart; + if(!mpTrafo) mpTrafo = new ntlMat4Gfx(0.0); + mpTrafo->initId(); + for(int i=0; i<3; i++) { mpTrafo->value[i][i] = scale[i]; } + for(int i=0; i<3; i++) { mpTrafo->value[i][3] = trans[i]; } +} /****************************************************************************** - * set the number of timesteps to trace + * adapt time step by rescaling velocities *****************************************************************************/ -void ParticleTracer::setTimesteps(int steps) -{ - steps=0; // remove warning... +void ParticleTracer::adaptPartTimestep(float factor) { + for(size_t i=0; i<mParts.size(); i++) { + mParts[i].setVel( mParts[i].getVel() * factor ); + } } /****************************************************************************** * add a particle at this position *****************************************************************************/ -void ParticleTracer::addParticle(double x, double y, double z) +void ParticleTracer::addParticle(float x, float y, float z) { ntlVec3Gfx p(x,y,z); ParticleObject part( p ); - //mParts[0].push_back( part ); + //mParts.push_back( part ); // TODO handle other arrays? //part.setActive( false ); - for(size_t l=0; l<mParts.size(); l++) { + mParts.push_back( part ); + //for(size_t l=0; l<mParts.size(); l++) { // add deactivated particles to other arrays - mParts[l].push_back( part ); // deactivate further particles - if(l>1) { + //if(l>1) { //mParts[l][ mParts.size()-1 ].setActive( false ); - } - } + //} + //} } +void ParticleTracer::cleanup() { + // cleanup + int last = (int)mParts.size()-1; + //for(vector<ParticleObject>::iterator pit= getParticlesBegin();pit!= getParticlesEnd(); pit++) { + for(int i=0; i<=last; i++) { + if( mParts[i].getActive()==false ) { + ParticleObject *p = &mParts[i]; + ParticleObject *p2 = &mParts[last]; + *p = *p2; last--; mParts.pop_back(); + } + } +} + /****************************************************************************** * save particle positions before adding a new timestep * copy "one index up", newest has to remain unmodified, it will be @@ -114,6 +165,7 @@ void ParticleTracer::addParticle(double x, double y, double z) void ParticleTracer::savePreviousPositions() { //debugOut(" PARTS SIZE "<<mParts.size() ,10); + /* if(mTrailIntervalCounter==0) { //errMsg("spp"," PARTS SIZE "<<mParts.size() ); for(size_t l=mParts.size()-1; l>0; l--) { @@ -131,9 +183,65 @@ void ParticleTracer::savePreviousPositions() } mTrailIntervalCounter++; if(mTrailIntervalCounter>=mTrailInterval) mTrailIntervalCounter = 0; + UNUSED!? */ } +/*! dump particles if desired */ +void ParticleTracer::notifyOfDump(int frameNr,char *frameNrStr,string outfilename) { + debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr, 10); // DEBUG + + if(mDumpParts>0) { + // dump to binary file + std::ostringstream boutfilename(""); + //boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< this->getName() <<"_" << frameNrStr << ".obj"; + //boutfilename << outfilename <<"_particles_"<< this->getName() <<"_" << frameNrStr<< ".gz"; + boutfilename << outfilename <<"_particles_" << frameNrStr<< ".gz"; + debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: "<< this->getName() + <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" #"<<frameNr , 7); + + // output to zipped file + gzFile gzf; + gzf = gzopen(boutfilename.str().c_str(), "wb1"); + if(gzf) { + int numParts; + if(sizeof(numParts)!=4) { errMsg("ParticleTracer::notifyOfDump","Invalid int size"); return; } + // only dump active particles + numParts = 0; + for(size_t i=0; i<mParts.size(); i++) { + if(!mParts[i].getActive()) continue; + numParts++; + } + gzwrite(gzf, &numParts, sizeof(numParts)); + for(size_t i=0; i<mParts.size(); i++) { + if(!mParts[i].getActive()) { continue; } + if(mParts[i].getLifeTime()<30) { continue; } //? CHECK + ParticleObject *p = &mParts[i]; + int type = p->getType(); + ntlVec3Gfx pos = p->getPos(); + float size = p->getSize(); + + if(type&PART_FLOAT) { // WARNING same handling for dump! + // add one gridcell offset + //pos[2] += 1.0; + } + pos = (*mpTrafo) * pos; + + ntlVec3Gfx v = p->getVel(); + v[0] *= mpTrafo->value[0][0]; + v[1] *= mpTrafo->value[1][1]; + v[2] *= mpTrafo->value[2][2]; + // FIXME check: pos = (*mpTrafo) * pos; + gzwrite(gzf, &type, sizeof(type)); + gzwrite(gzf, &size, sizeof(size)); + for(int j=0; j<3; j++) { gzwrite(gzf, &pos[j], sizeof(float)); } + for(int j=0; j<3; j++) { gzwrite(gzf, &v[j], sizeof(float)); } + } + gzclose( gzf ); + } + } // dump? +} + /****************************************************************************** @@ -143,45 +251,71 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) { -#ifdef ELBEEM_BLENDER +#ifdef ELBEEM_PLUGIN // suppress warnings... vertices = NULL; triangles = NULL; normals = NULL; objectId = 0; -#else // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN // currently not used in blender + objectId = 0; // remove, deprecated + if(mDumpParts>1) { + return; // only dump, no tri-gen + } const bool debugParts = false; int tris = 0; gfxReal partNormSize = 0.01 * mPartScale; - ntlVec3Gfx pScale = ntlVec3Gfx( - (mEnd[0]-mStart[0])/(mSimEnd[0]-mSimStart[0]), - (mEnd[1]-mStart[1])/(mSimEnd[1]-mSimStart[1]), - (mEnd[2]-mStart[2])/(mSimEnd[2]-mSimStart[2]) - ); - if(debugParts) errMsg("DebugParts"," geo:"<< mSimStart<<","<<mEnd<<"; sim:"<<mSimStart<<","<<mSimEnd<<"; S "<<pScale ); - ntlVec3Gfx org = mStart; int segments = mPartSegments; - int lnewst = mTrailLength-1; - int loldst = mTrailLength-2; + //int lnewst = mTrailLength-1; + // TODO get rid of mPart[X] array + //? int loldst = mTrailLength-2; // trails gehen nicht so richtig mit der // richtung der partikel... - for(size_t i=0; i<mParts[lnewst].size(); i++) { + ntlVec3Gfx scale = ntlVec3Gfx( (mEnd[0]-mStart[0])/(mSimEnd[0]-mSimStart[0]), (mEnd[1]-mStart[1])/(mSimEnd[1]-mSimStart[1]), (mEnd[2]-mStart[2])/(mSimEnd[2]-mSimStart[2])); + ntlVec3Gfx trans = mStart; + for(size_t i=0; i<mParts.size(); i++) { //mParts[0][i].setActive(true); + ParticleObject *p = &mParts[i]; - if( mParts[lnewst][i].getActive()==false ) continue; - if( mParts[loldst][i].getActive()==false ) continue; + if(mShowOnly!=10) { + // 10=show only deleted + if( p->getActive()==false ) continue; + } else { + if( p->getActive()==true ) continue; + } + int type = p->getType(); + if(mShowOnly>0) { + switch(mShowOnly) { + case 1: if(!(type&PART_BUBBLE)) continue; break; + case 2: if(!(type&PART_DROP)) continue; break; + case 3: if(!(type&PART_INTER)) continue; break; + case 4: if(!(type&PART_FLOAT)) continue; break; + } + } else { + // by default dont display inter + if(type&PART_INTER) continue; + } + + ntlVec3Gfx pnew = p->getPos(); + if(type&PART_FLOAT) { // WARNING same handling for dump! + // add one gridcell offset + //pnew[2] += 1.0; + } - ntlVec3Gfx pnew = mParts[lnewst][i].getPos(); - ntlVec3Gfx pold = mParts[loldst][i].getPos(); - ntlVec3Gfx pdir = pnew - pold; + ntlVec3Gfx pdir = p->getVel(); gfxReal plen = normalize( pdir ); if( plen < 1e-05) pdir = ntlVec3Gfx(-1.0 ,0.0 ,0.0); - ntlVec3Gfx p = org + pnew*pScale; + ntlVec3Gfx pos = (*mpTrafo) * pnew; + //ntlVec3Gfx pos = pnew; // T + //pos[0] = pos[0]*scale[0]+trans[0]; // T + //pos[1] = pos[1]*scale[1]+trans[1]; // T + //pos[2] = pos[2]*scale[2]+trans[2]; // T gfxReal partsize = 0.0; - if(debugParts) errMsg("DebugParts"," i"<<i<<" new"<<pnew<<" old"<<pold ); + if(debugParts) errMsg("DebugParts"," i"<<i<<" new"<<pnew<<" vel"<<pdir<<" pos="<<pos ); + //if(i==0 &&(debugParts)) errMsg("DebugParts"," i"<<i<<" new"<<pnew[0]<<" pos="<<pos[0]<<" scale="<<scale[0]<<" t="<<trans[0] ); // value length scaling? if(mValueScale==1) { @@ -194,6 +328,8 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, } else { partsize = mPartScale; // no length scaling } + //if(type&(PART_DROP|PART_BUBBLE)) + partsize *= p->getSize()/5.0; ntlVec3Gfx pstart( mPartHeadDist *partsize, 0.0, 0.0 ); ntlVec3Gfx pend ( mPartTailDist *partsize, 0.0, 0.0 ); @@ -207,9 +343,9 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, ntlVec3Gfx cv2 = ntlVec3Gfx(pdir[1], -pdir[0], 0.0); ntlVec3Gfx cv3 = cross( cv1, cv2); for(int l=0; l<3; l++) { - cvmat.value[l][0] = cv1[l]; - cvmat.value[l][1] = cv2[l]; - cvmat.value[l][2] = cv3[l]; + //? cvmat.value[l][0] = cv1[l]; + //? cvmat.value[l][1] = cv2[l]; + //? cvmat.value[l][2] = cv3[l]; } pstart = (cvmat * pstart); pend = (cvmat * pend); @@ -231,10 +367,10 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, p1 = (cvmat * p1); p2 = (cvmat * p2); - sceneAddTriangle( p+pstart, p+p1, p+p2, - ns,n1,n2, ntlVec3Gfx(0.0), 1 ); - sceneAddTriangle( p+pend , p+p2, p+p1, - ns,n2,n1, ntlVec3Gfx(0.0), 1 ); + sceneAddTriangle( pos+pstart, pos+p1, pos+p2, + ns,n1,n2, ntlVec3Gfx(0.0), 1, triangles,vertices,normals ); + sceneAddTriangle( pos+pend , pos+p2, pos+p1, + ns,n2,n1, ntlVec3Gfx(0.0), 1, triangles,vertices,normals ); phi += phiD; tris += 2; @@ -244,31 +380,7 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, //} // trail return; // DEBUG - - // add trails - //double tScale = 0.01 * mPartScale * mTrailScale; - double trails = 0.01 * mPartScale * mTrailScale; - //for(int l=0; l<mParts.size()-1; l++) { - for(int l=0; l<mTrailLength-2; l++) { - for(size_t i=0; i<mParts[0].size(); i++) { - int tl1 = l*mTrailInterval; - int tl2 = (l+1)*mTrailInterval; - if( mParts[tl1][i].getActive()==false ) continue; - if( mParts[tl2][i].getActive()==false ) continue; - ntlVec3Gfx p1 = org+mParts[tl1][i].getPos()*pScale; - ntlVec3Gfx p2 = org+mParts[tl2][i].getPos()*pScale; - ntlVec3Gfx n = ntlVec3Gfx(0,0,-1); - sceneAddTriangle( p1+ntlVec3Gfx(0,trails,0), p1+ntlVec3Gfx(0,-trails,0), p2, - n,n,n, ntlVec3Gfx(0.0), 1 ); - sceneAddTriangle( p2, p1+ntlVec3Gfx(0,-trails,0), p1+ntlVec3Gfx(0,trails,0), - n,n,n, ntlVec3Gfx(0.0), 1 ); - tris += 2; - } - } - debugOut("ParticleTracer::getTriangles "<<mName<<" : Triangulated "<< (mParts[0].size()) <<" particles (triangles: "<<tris<<") ", 10); - //debugOut(" s"<<mStart<<" e"<<mEnd<<" ss"<<mSimStart<<" se"<<mSimEnd , 10); - -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN } diff --git a/intern/elbeem/intern/particletracer.h b/intern/elbeem/intern/particletracer.h index b5f5838d87f..b9179b68dc0 100644 --- a/intern/elbeem/intern/particletracer.h +++ b/intern/elbeem/intern/particletracer.h @@ -9,7 +9,18 @@ #ifndef NTL_PARTICLETRACER_H #include "ntl_geometryobject.h" +template<class Scalar> class ntlMatrix4x4; +// particle types +#define PART_BUBBLE (1<< 1) +#define PART_DROP (1<< 2) +#define PART_INTER (1<< 3) +#define PART_FLOAT (1<< 4) + +// particle state +#define PART_IN (1<< 8) +#define PART_OUT (1<< 9) +#define PART_INACTIVE (1<<10) //! A single particle class ParticleObject @@ -17,24 +28,26 @@ class ParticleObject public: //! Standard constructor inline ParticleObject(ntlVec3Gfx mp) : - mPos(mp),mVel(0.0), mStatus(0), mActive( true ) { }; + mPos(mp),mVel(0.0), mSize(1.0), mStatus(0),mLifeTime(0) { }; //! Copy constructor inline ParticleObject(const ParticleObject &a) : - mPos(a.mPos), mVel(a.mVel), - mStatus(a.mStatus), mActive(a.mActive) { }; + mPos(a.mPos), mVel(a.mVel), mSize(a.mSize), + mStatus(a.mStatus), + mLifeTime(a.mLifeTime) { }; //! Destructor inline ~ParticleObject() { /* empty */ }; //! add vector to position - inline void advance(double vx, double vy, double vz) { + inline void advance(float vx, float vy, float vz) { mPos[0] += vx; mPos[1] += vy; mPos[2] += vz; } //! advance with own velocity inline void advanceVel() { mPos += mVel; } //! add acceleration to velocity inline void addToVel(ntlVec3Gfx acc) { mVel += acc; } - //! get vector to position + //! get/set vector to position inline ntlVec3Gfx getPos() { return mPos; } + inline void setPos(ntlVec3Gfx set) { mPos=set; } //! set velocity inline void setVel(ntlVec3Gfx set) { mVel = set; } //! set velocity @@ -42,14 +55,31 @@ class ParticleObject //! get velocity inline ntlVec3Gfx getVel() { return mVel; } + //! get/set size value + inline gfxReal getSize() { return mSize; } + inline void setSize(gfxReal set) { mSize=set; } + + //! get whole flags + inline int getFlags() const { return mStatus; } + //! get status (higher byte) + inline int getStatus() const { return (mStatus&0xFF00); } + //! set status (higher byte) + inline void setStatus(int set) { mStatus = set|(mStatus&0x00FF); } + //! get type (lower byte) + inline int getType() const { return (mStatus&0x00FF); } + //! set type (lower byte) + inline void setType(int set) { mStatus = set|(mStatus&0xFF00); } //! get active flag - inline bool getActive() { return mActive; } + inline bool getActive() const { return ((mStatus&PART_INACTIVE)==0); } //! set active flag - inline void setActive(bool set) { mActive = set; } - //! get status int - inline int getStatus() { return mStatus; } - //! setstatus int - inline void setStatus(int set) { mStatus = set; } + inline void setActive(bool set) { + if(set) mStatus &= (~PART_INACTIVE); + else mStatus |= PART_INACTIVE; + } + //! get/set lifetime + inline int getLifeTime() const { return mLifeTime; } + //! set type (lower byte) + inline void setLifeTime(int set) { mLifeTime = set; } protected: @@ -57,11 +87,12 @@ class ParticleObject ntlVec3Gfx mPos; /*! the particle velocity */ ntlVec3Gfx mVel; - + /*! size / mass of particle */ + gfxReal mSize; /*! particle status */ int mStatus; - /*! particle active? */ - bool mActive; + /*! count survived time steps */ + int mLifeTime; }; @@ -73,10 +104,10 @@ class ParticleTracer : //! Standard constructor ParticleTracer(); //! Destructor - ~ParticleTracer() { /* empty */ }; + ~ParticleTracer(); //! add a particle at this position - void addParticle(double x, double y, double z); + void addParticle(float x, float y, float z); //! save particle positions before adding a new timestep void savePreviousPositions(); @@ -87,78 +118,60 @@ class ParticleTracer : //! parse settings from attributes (dont use own list!) void parseAttrList( AttributeList *att ); + //! adapt time step by rescaling velocities + void adaptPartTimestep(float factor); // access funcs - //! set the number of timesteps to trace - void setTimesteps(int steps); - - //! set the number of particles - inline void setNumParticles(int set) { mNumParticles = set; } //! get the number of particles - inline int getNumParticles() { return mNumParticles; } - - //! set the number of timesteps to trace - inline void setTrailLength(int set) { mTrailLength = set; mParts.resize(mTrailLength*mTrailInterval); } - //! get the number of timesteps to trace - inline int getTrailLength() { return mTrailLength; } - //! set the number of timesteps between each anim step saving - inline void setTrailInterval(int set) { mTrailInterval = set; mParts.resize(mTrailLength*mTrailInterval); } - - //! get the no. of particles in the current array - inline int getPartArraySize() { return mParts[0].size(); } + inline int getNumParticles() { return mParts.size(); } //! iterate over all newest particles (for advancing positions) - inline vector<ParticleObject>::iterator getParticlesBegin() { return mParts[0].begin(); } + inline vector<ParticleObject>::iterator getParticlesBegin() { return mParts.begin(); } //! end iterator for newest particles - inline vector<ParticleObject>::iterator getParticlesEnd() { return mParts[0].end(); } + inline vector<ParticleObject>::iterator getParticlesEnd() { return mParts.end(); } //! end iterator for newest particles - inline ParticleObject* getLast() { return &(mParts[0][ mParts[0].size()-1 ]); } + inline ParticleObject* getLast() { return &(mParts[ mParts.size()-1 ]); } /*! set geometry start (for renderer) */ - inline void setStart(ntlVec3Gfx set) { mStart = set; } + inline void setStart(ntlVec3Gfx set) { mStart = set; initTrafoMatrix(); } + /*! set geometry end (for renderer) */ + inline void setEnd(ntlVec3Gfx set) { mEnd = set; initTrafoMatrix(); } + /*! get values */ + inline ntlVec3Gfx getStart() { return mStart; } /*! set geometry end (for renderer) */ - inline void setEnd(ntlVec3Gfx set) { mEnd = set; } + inline ntlVec3Gfx getEnd() { return mEnd; } /*! set simulation domain start */ - inline void setSimStart(ntlVec3Gfx set) { mSimStart = set; } + inline void setSimStart(ntlVec3Gfx set) { mSimStart = set; initTrafoMatrix(); } /*! set simulation domain end */ - inline void setSimEnd(ntlVec3Gfx set) { mSimEnd = set; } + inline void setSimEnd(ntlVec3Gfx set) { mSimEnd = set; initTrafoMatrix(); } + + /*! set/get dump flag */ + inline void setDumpParts(bool set) { mDumpParts = set; } + inline bool getDumpParts() { return mDumpParts; } //! set the particle scaling factor - inline void setPartScale(double set) { mPartScale = set; } - //! set the trail scaling factor - inline void setTrailScale(double set) { mTrailScale = set; } + inline void setPartScale(float set) { mPartScale = set; } // NTL geometry implementation - /*! Get the triangles from this object */ virtual void getTriangles( vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ); + virtual void notifyOfDump(int frameNr,char *frameNrStr,string outfilename); + // free deleted particles + void cleanup(); protected: /*! the particle array (for multiple timesteps) */ - vector< vector<ParticleObject> > mParts; - - /*! desired number of particles */ - int mNumParticles; - - /*! number of particle positions to trace */ - int mTrailLength; - - /*! number of timesteps to between saving particle positions */ - int mTrailInterval; - int mTrailIntervalCounter; + vector<ParticleObject> mParts; /*! size of the particles to display */ - double mPartSize; - - /*! size of the particle trail */ - double mTrailScale; + float mPartSize; /*! start and end vectors for the triangulation region to create particles in */ ntlVec3Gfx mStart, mEnd; @@ -167,18 +180,28 @@ class ParticleTracer : ntlVec3Gfx mSimStart, mSimEnd; /*! scaling param for particles */ - double mPartScale; + float mPartScale; /*! head and tail distance for particle shapes */ - double mPartHeadDist, mPartTailDist; + float mPartHeadDist, mPartTailDist; /*! no of segments for particle cone */ int mPartSegments; /*! use length/absval of values to scale particles? */ int mValueScale; /*! value length maximal cutoff value, for mValueScale==2 */ - double mValueCutoffTop; + float mValueCutoffTop; /*! value length minimal cutoff value, for mValueScale==2 */ - double mValueCutoffBottom; + float mValueCutoffBottom; + + /*! dump particles (or certain types of) to disk? */ + int mDumpParts; + /*! show only a certain type (debugging) */ + int mShowOnly; + + //! transform matrix + ntlMatrix4x4<gfxReal> *mpTrafo; + /*! init sim/pos transformation */ + void initTrafoMatrix(); }; #define NTL_PARTICLETRACER_H diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp index bec1e82ca21..481eb836ad6 100644 --- a/intern/elbeem/intern/simulation_object.cpp +++ b/intern/elbeem/intern/simulation_object.cpp @@ -8,9 +8,13 @@ *****************************************************************************/ #include "simulation_object.h" +#include "solver_interface.h" #include "ntl_bsptree.h" -#include "ntl_scene.h" +#include "ntl_ray.h" +#include "ntl_world.h" +#include "solver_interface.h" #include "particletracer.h" +#include "elbeem.h" #ifdef _WIN32 #else @@ -32,22 +36,15 @@ SimulationObject::SimulationObject() : mpGlob(NULL), mPanic( false ), mDebugType( 1 /* =FLUIDDISPNothing*/ ), - mSolverType("-"), mStepsPerFrame( 10 ), - mpLbm(NULL), - mpParam( NULL ), + mStepsPerFrame( 10 ), + mpLbm(NULL), mpParam( NULL ), mShowSurface(true), mShowParticles(false), mSelectedCid( NULL ), + mpElbeemSettings( NULL ) - stnOld("opt"), - stnFsgr("fsgr") { mpParam = new Parametrizer(); - - for(int i=0; i<MAX_DEBDISPSET; i++) { - mDebDispSet[i].type = (i); - mDebDispSet[i].on = false; - mDebDispSet[i].scale = 1.0; - } + //for(int i=0; i<MAX_DEBDISPSET; i++) { mDebDispSet[i].type = (i); mDebDispSet[i].on = false; mDebDispSet[i].scale = 1.0; } // reset time mTime = 0.0; @@ -60,9 +57,10 @@ SimulationObject::SimulationObject() : *****************************************************************************/ SimulationObject::~SimulationObject() { - if(mpGiTree != NULL) delete mpGiTree; - delete mpLbm; - delete mpParam; + if(mpGiTree) delete mpGiTree; + if(mpElbeemSettings) delete mpElbeemSettings; + if(mpLbm) delete mpLbm; + if(mpParam) delete mpParam; debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10); } @@ -77,7 +75,7 @@ void SimulationObject::initGeoTree(int id) { return; } mGeoInitId = id; - ntlScene *scene = mpGlob->getScene(); + ntlScene *scene = mpGlob->getSimScene(); mpGiObjects = scene->getObjects(); if(mpGiTree != NULL) delete mpGiTree; @@ -95,6 +93,11 @@ void SimulationObject::freeGeoTree() { +// copy & remember settings for later use +void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) { + mpElbeemSettings = new elbeemSimulationSettings; + *mpElbeemSettings = *settings; +} /****************************************************************************** * simluation interface: initialize simulation using the given configuration file @@ -102,33 +105,34 @@ void SimulationObject::freeGeoTree() { int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) { if(!SIMWORLD_OK()) return 1; + + // already inited? + if(mpLbm) return 0; + mpGlob = glob; if(!getVisible()) { mpAttrs->setAllUsed(); return 0; } - //mDimension is deprecated - mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); - if(mSolverType == stnFsgr) { - mpLbm = createSolver(); - } else if(mSolverType == stnOld) { - errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); - return 1; - } + //mDimension, mSolverType are deprecated + string mSolverType(""); + mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); + //errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); return 1; + mpLbm = createSolver(); /* check lbm pointer */ if(mpLbm == NULL) { - errFatal("SimulationObject::initializeLbmSimulation","Unable to init dim"<<mSolverType<<" LBM solver! ", SIMWORLD_INITERROR); + errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR); return 1; } - debugOut("SimulationObject::initialized "<< mpLbm->getIdString() <<" LBM solver! ", 2); + debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2); // for non-param simulations mpLbm->setParametrizer( mpParam ); mpParam->setAttrList( getAttributeList() ); - // not needed.. done in solver_init: mpParam->setSize ... + // not needed.. done in solver_init: mpParam->setSize ... in solver_interface mpParam->parseAttrList(); mpLbm->setAttrList( getAttributeList() ); @@ -152,6 +156,27 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) mpLbm->setGeoEnd( mGeoEnd ); mpLbm->setRenderGlobals( mpGlob ); mpLbm->setName( getName() + "_lbm" ); + if(mpElbeemSettings) { + // set further settings from API struct init + mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing); + mpLbm->setSizeX(mpElbeemSettings->resolutionxyz); + mpLbm->setSizeY(mpElbeemSettings->resolutionxyz); + mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz); + mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz); + mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine); + mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles); + + string dinitType = std::string("no"); + if (mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = std::string("part"); + else if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = std::string("free"); + else /*if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = std::string("no"); + mpLbm->setDomainBound(dinitType); + mpLbm->setDomainPartSlip(mpElbeemSettings->obstaclePartslip); + mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors); + debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->obstaclePartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 ); + + debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10); + } mpLbm->initializeSolver(); // print cell type stats @@ -175,7 +200,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) } mpLbm->deleteCellIterator( &cid ); -#if ELBEEM_BLENDER!=1 +#if ELBEEM_PLUGIN!=1 char charNl = '\n'; debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5); debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5); @@ -199,12 +224,18 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl; if(diffInits > 0) { - debugOut("SimulationObject::initializeLbmSimulation celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5); + debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5); } debugOutNnl(out.str(), 5); } -#endif // ELBEEM_BLENDER==1 +#endif // ELBEEM_PLUGIN==1 + // might be modified by mpLbm + mpParts->setStart( mGeoStart ); + mpParts->setEnd( mGeoEnd ); + mpParts->setCastShadows( false ); + mpParts->setReceiveShadows( false ); + mpParts->searchMaterial( glob->getMaterials() ); mpLbm->initParticles(mpParts); // this has to be inited here - before, the values might be unknown @@ -218,12 +249,19 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) if(mShowSurface) mObjects.push_back( surf ); } - mpParts->setStart( mGeoStart ); - mpParts->setEnd( mGeoEnd ); - mpParts->setCastShadows( false ); - mpParts->setReceiveShadows( false ); - mpParts->searchMaterial( glob->getMaterials() ); - if(mShowParticles) mObjects.push_back(mpParts); +#ifdef ELBEEM_PLUGIN + mShowParticles=1; +#endif // ELBEEM_PLUGIN + //if(getenv("ELBEEM_DUMPPARTICLE")) { // DEBUG ENABLE!!!!!!!!!! + if(mpLbm->getGenerateParticles()>0.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(); @@ -247,17 +285,17 @@ void SimulationObject::setFrameNum(int num) { *****************************************************************************/ void SimulationObject::step( void ) { - if(mpParam->getAniFrameTime()>0.0) { + if(mpParam->getCurrentAniFrameTime()>0.0) { // dont advance for stopped time mpLbm->step(); mpParts->savePreviousPositions(); mpLbm->advanceParticles(mpParts); - mTime += mpParam->getStepTime(); + mTime += mpParam->getTimestep(); } if(mpLbm->getPanic()) mPanic = true; - //debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getStepTime())<<", framet="<<getFrameTime()<<") ", 10); + //debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getTimestep())<<", framet="<<getFrameTime()<<") ", 10); } /*! prepare visualization of simulation for e.g. raytracing */ void SimulationObject::prepareVisualization( void ) { @@ -273,12 +311,12 @@ double SimulationObject::getStartTime( void ) { return mpParam->getAniStart(); } /* get time for a single animation frame */ -double SimulationObject::getFrameTime( void ) { - return mpParam->getAniFrameTime(); +double SimulationObject::getFrameTime( int frame ) { + return mpParam->getAniFrameTime(frame); } /* get time for a single time step */ -double SimulationObject::getStepTime( void ) { - return mpParam->getStepTime(); +double SimulationObject::getTimestep( void ) { + return mpParam->getTimestep(); } @@ -307,17 +345,12 @@ SimulationObject::getObjectsEnd() void SimulationObject::drawDebugDisplay() { #ifndef NOGUI - //debugOut(" SD: "<<mDebugType<<" v"<<getVisible()<<" don"<< (mDebDispSet[mDebugType].on) , 10); if(!getVisible()) return; - if( mDebugType > (MAX_DEBDISPSET-1) ){ - errFatal("SimulationObject::drawDebugDisplay","Invalid debug type!", SIMWORLD_GENERICERROR); - return; - } - - mDebDispSet[ mDebugType ].on = true; + //if( mDebugType > (MAX_DEBDISPSET-1) ){ errFatal("SimulationObject::drawDebugDisplay","Invalid debug type!", SIMWORLD_GENERICERROR); return; } + //mDebDispSet[ mDebugType ].on = true; //errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type ); - mpLbm->debugDisplay( &mDebDispSet[ mDebugType ] ); + mpLbm->debugDisplay( mDebugType ); //::lbmMarkedCellDisplay<>( mpLbm ); mpLbm->lbmMarkedCellDisplay(); @@ -331,7 +364,7 @@ void SimulationObject::drawInteractiveDisplay() if(!getVisible()) return; if(mSelectedCid) { // in debugDisplayNode if dispset is on is ignored... - mpLbm->debugDisplayNode( &mDebDispSet[ FLUIDDISPGrid ], mSelectedCid ); + mpLbm->debugDisplayNode( FLUIDDISPGrid, mSelectedCid ); } #endif } @@ -365,4 +398,9 @@ void SimulationObject::setMouseClick() } } +/*! notify object that dump is in progress (e.g. for field dump) */ +void SimulationObject::notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename) { + if(!mpLbm) return; + mpLbm->notifySolverOfDump(frameNr,frameNrStr,outfilename); +} diff --git a/intern/elbeem/intern/simulation_object.h b/intern/elbeem/intern/simulation_object.h index 3105a494661..4e7bc19294d 100644 --- a/intern/elbeem/intern/simulation_object.h +++ b/intern/elbeem/intern/simulation_object.h @@ -13,13 +13,15 @@ #define USE_GLUTILITIES #include "ntl_geometryshader.h" -#include "solver_interface.h" #include "parametrizer.h" +class LbmSolverInterface; +class CellIdentifierInterface; class ntlTree; class ntlRenderGlobals; class ntlRenderGlobals; class ParticleTracer; +struct elbeemSimulationSettings; //! type fluid geometry init @@ -48,6 +50,8 @@ class SimulationObject : SimulationObject(); /*! Destructor */ virtual ~SimulationObject(); + /*! for init from API */ + void copyElbeemSettings(elbeemSimulationSettings *settings); /*! init tree for certain geometry init */ @@ -86,6 +90,8 @@ class SimulationObject : /*! Do geo etc. init */ virtual int postGeoConstrInit(ntlRenderGlobals *glob) { return initializeLbmSimulation(glob); }; virtual int initializeShader() { /* ... */ return true; }; + /*! notify object that dump is in progress (e.g. for field dump) */ + virtual void notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename); /*! simluation interface: draw the simulation with OpenGL */ virtual void draw( void ) {}; virtual vector<ntlGeometryObject *>::iterator getObjectsBegin(); @@ -97,13 +103,6 @@ class SimulationObject : /*! prepare visualization of simulation for e.g. raytracing */ virtual void prepareVisualization( void ); - /*! get current start simulation time */ - virtual double getStartTime( void ); - /*! get time for a single animation frame */ - virtual double getFrameTime( void ); - /*! get time for a single time step in the simulation */ - virtual double getStepTime( void ); - /*! GUI - display debug info */ virtual void drawDebugDisplay(); /*! GUI - display interactive info */ @@ -112,6 +111,13 @@ class SimulationObject : virtual void setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir); virtual void setMouseClick(); + /*! get current start simulation time */ + double getStartTime( void ); + /*! get time for a single animation frame */ + double getFrameTime( int frame ); + /*! get time for a single time step in the simulation */ + double getTimestep( void ); + //! access solver LbmSolverInterface *getSolver(){ return mpLbm; } @@ -143,7 +149,6 @@ class SimulationObject : //! dimension of the simulation - now given by LBM-DIM define globally //! solver type - string mSolverType; /*! when no parametrizer, use this as no. of steps per frame */ int mStepsPerFrame; @@ -165,24 +170,21 @@ class SimulationObject : bool mShowParticles; /*! debug display settings */ -#ifndef USE_MSVC6FIXES - static const int MAX_DEBDISPSET = 10; -#else - // so this is a known and documented MSVC6 bug - // work around - enum {MAX_DEBDISPSET = 10}; -#endif - fluidDispSettings mDebDispSet[ MAX_DEBDISPSET ]; + int mDebDispSetting; /*! pointer to identifier of selected node */ CellIdentifierInterface *mSelectedCid; + /*! storage of API settings */ + elbeemSimulationSettings *mpElbeemSettings; + public: // debug display setting funtions /*! set type of info to display */ inline void setDebugDisplay(int disp) { mDebugType = disp; } + inline int getDebugDisplay() { return mDebugType; } /* miscelleanous access functions */ @@ -198,10 +200,6 @@ class SimulationObject : virtual inline ntlVec3Gfx *getBBStart() { return &mGeoStart; } virtual inline ntlVec3Gfx *getBBEnd() { return &mGeoEnd; } - /*! solver dimension constants */ - const string stnOld; - const string stnFsgr; - }; diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h index 98c1882d79c..7217964e7ba 100644 --- a/intern/elbeem/intern/solver_class.h +++ b/intern/elbeem/intern/solver_class.h @@ -15,7 +15,7 @@ #include "utilities.h" #include "solver_interface.h" -#include "ntl_scene.h" +#include "ntl_ray.h" #include <stdio.h> #if PARALLEL==1 @@ -25,22 +25,14 @@ #define PARALLEL 0 #endif // PARALLEL -#ifndef LBMMODEL_DEFINED -// force compiler error! -ERROR - define model first! -#endif // LBMMODEL_DEFINED - // general solver setting defines -// default to 3dim -#ifndef LBMDIM -#define LBMDIM 3 -#endif // LBMDIM - - //! debug coordinate accesses and the like? (much slower) +// might be enabled by compilation +#ifndef FSGR_STRICT_DEBUG #define FSGR_STRICT_DEBUG 0 +#endif // FSGR_STRICT_DEBUG //! debug coordinate accesses and the like? (much slower) #define FSGR_OMEGA_DEBUG 0 @@ -81,6 +73,7 @@ ERROR - define model first! #define FSGR_MAXNOOFLEVELS 5 // enable/disable fine grid compression for finest level +// make sure this is same as useGridComp in calculateMemreqEstimate #if LBMDIM==3 #define COMPRESSGRIDS 1 #else @@ -113,15 +106,14 @@ ERROR - define model first! #endif #endif -#if ELBEEM_BLENDER!=1 +#if LBM_INCLUDE_TESTSOLVERS==1 #include "solver_test.h" -#endif // ELBEEM_BLENDER==1 +#endif // LBM_INCLUDE_TESTSOLVERS==1 /*****************************************************************************/ /*! cell access classes */ -template<typename D> class UniformFsgrCellIdentifier : - public CellIdentifierInterface + public CellIdentifierInterface , public LbmCellContents { public: //! which grid level? @@ -137,14 +129,13 @@ class UniformFsgrCellIdentifier : virtual string getAsString() { std::ostringstream ret; ret <<"{ i"<<x<<",j"<<y; - if(D::cDimension>2) ret<<",k"<<z; + if(LBMDIM>2) ret<<",k"<<z; ret <<" }"; return ret.str(); } virtual bool equal(CellIdentifierInterface* other) { - //UniformFsgrCellIdentifier<D> *cid = dynamic_cast<UniformFsgrCellIdentifier<D> *>( other ); - UniformFsgrCellIdentifier<D> *cid = (UniformFsgrCellIdentifier<D> *)( other ); + UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( other ); if(!cid) return false; if( x==cid->x && y==cid->y && z==cid->z && level==cid->level ) return true; return false; @@ -165,7 +156,7 @@ public: //! size this level was advanced to LbmFloat time; //! size of a single lbm step in time units on this level - LbmFloat stepsize; + LbmFloat timestep; //! step count int lsteps; //! gravity force for this level @@ -203,9 +194,8 @@ public: /*****************************************************************************/ /*! class for solving a LBM problem */ -template<class D> class LbmFsgrSolver : - public D // this means, the solver is a lbmData object and implements the lbmInterface + public LbmSolverInterface // this means, the solver is a lbmData object and implements the lbmInterface { public: @@ -213,26 +203,23 @@ class LbmFsgrSolver : LbmFsgrSolver(); //! Destructor virtual ~LbmFsgrSolver(); - //! id string of solver - virtual string getIdString(); - //! dimension of solver - virtual int getDimension(); //! initilize variables fom attribute list virtual void parseAttrList(); //! Initialize omegas and forces on all levels (for init/timestep change) void initLevelOmegas(); //! finish the init with config file values (allocate arrays...) - virtual bool initializeSolver(); //( ntlTree* /*tree*/, vector<ntlGeometryObject*>* /*objects*/ ); + virtual bool initializeSolver(); + //! notify object that dump is in progress (e.g. for field dump) + virtual void notifySolverOfDump(int frameNr,char *frameNrStr,string outfilename); #if LBM_USE_GUI==1 //! show simulation info (implement LbmSolverInterface pure virtual func) - virtual void debugDisplay(fluidDispSettings *set); + virtual void debugDisplay(int set); #endif - // implement CellIterator<UniformFsgrCellIdentifier> interface - typedef UniformFsgrCellIdentifier<typename D::LbmCellContents> stdCellId; + typedef UniformFsgrCellIdentifier stdCellId; virtual CellIdentifierInterface* getFirstCell( ); virtual void advanceCell( CellIdentifierInterface* ); virtual bool noEndCell( CellIdentifierInterface* ); @@ -249,7 +236,7 @@ class LbmFsgrSolver : virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set); virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set); virtual LbmFloat getEquilDf ( int ); - virtual int getDfNum ( ); + virtual ntlVec3Gfx getVelocityAt (float x, float y, float z); // convert pointers stdCellId* convertBaseCidToStdCid( CellIdentifierInterface* basecid); @@ -264,6 +251,8 @@ class LbmFsgrSolver : LBM_INLINED void initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass); LBM_INLINED void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel); LBM_INLINED void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag); + //! interpolate velocity and density at a given position + void interpolateCellValues(int level,int ei,int ej,int ek,int workSet, LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz); /*! perform a single LBM step */ void stepMain(); @@ -288,8 +277,8 @@ class LbmFsgrSolver : // gui/output debugging functions #if LBM_USE_GUI==1 - virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ); - virtual void lbmDebugDisplay(fluidDispSettings *dispset); + virtual void debugDisplayNode(int dispset, CellIdentifierInterface* cell ); + virtual void lbmDebugDisplay(int dispset); virtual void lbmMarkedCellDisplay(); #endif // LBM_USE_GUI==1 virtual void debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet=-1); @@ -298,7 +287,7 @@ class LbmFsgrSolver : void prepareVisualization( void ); /*! type for cells */ - typedef typename D::LbmCell LbmCell; + //typedef typename this->LbmCell LbmCell; protected: @@ -311,6 +300,8 @@ class LbmFsgrSolver : void adaptTimestep(); //! init mObjectSpeeds for current parametrization void recalculateObjectSpeeds(); + //! init moving obstacles for next sim step sim + void initMovingObstacles(bool staticInit); //! flag reinit step - always works on finest grid! void reinitFlags( int workSet ); //! mass dist weights @@ -347,10 +338,6 @@ class LbmFsgrSolver : //! use time adaptivity? bool mTimeAdap; - //! domain boundary free/no slip type - string mDomainBound; - //! part slip value for domain - LbmFloat mDomainPartSlipValue; //! fluid vol height LbmFloat mFVHeight; @@ -364,12 +351,17 @@ class LbmFsgrSolver : //! smoother surface initialization? int mInitSurfaceSmoothing; + //! lock time step down switching int mTimestepReduceLock; + //! count no. of switches int mTimeSwitchCounts; + // only switch of maxvel is higher for several steps... + int mTimeMaxvelStepCnt; + //! total simulation time so far - LbmFloat mSimulationTime; + LbmFloat mSimulationTime, mLastSimTime; //! smallest and largest step size so far - LbmFloat mMinStepTime, mMaxStepTime; + LbmFloat mMinTimestep, mMaxTimestep; //! track max. velocity LbmFloat mMxvx, mMxvy, mMxvz, mMaxVlen; @@ -442,17 +434,10 @@ class LbmFsgrSolver : int mDisableStandingFluidInit; //! debug function to force tadap syncing int mForceTadapRefine; - -#ifndef ELBEEM_BLENDER - // test functions - bool mUseTestdata; - LbmTestdata *mpTest; - void initTestdata(); - void destroyTestdata(); - void handleTestdata(); - void exportTestdata(); + //! border cutoff value + int mCutoff; + //! store particle tracer ParticleTracer *mpParticles; -#endif // ELBEEM_BLENDER==1 // strict debug interface # if FSGR_STRICT_DEBUG==1 @@ -467,8 +452,226 @@ class LbmFsgrSolver : LbmFloat* debRACPNT(int level, int ii,int ij,int ik, int is ); LbmFloat& debRAC(LbmFloat* s,int l); # endif // FSGR_STRICT_DEBUG==1 + + bool mUseTestdata; +#if LBM_INCLUDE_TESTSOLVERS==1 + // test functions + LbmTestdata *mpTest; + void initTestdata(); + void destroyTestdata(); + void handleTestdata(); + void exportTestdata(); + void set3dHeight(int ,int ); + public: + // needed from testdata + void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat &retux, LbmFloat &retuy); +#endif // LBM_INCLUDE_TESTSOLVERS==1 + + public: // former LbmModelLBGK functions + // relaxation funtions - implemented together with relax macros + static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz); + static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz); + inline LbmFloat getLesNoneqTensorCoeff( LbmFloat df[], LbmFloat feq[] ); + inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo); + inline void collideArrays( int i, int j, int k, // position - more for debugging + LbmFloat df[], LbmFloat &outrho, // out only! + // velocity modifiers (returns actual velocity!) + LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, LbmFloat omega, LbmFloat csmago, LbmFloat *newOmegaRet, LbmFloat *newQoRet); + + + // former LBM models + public: + +//! shorten static const definitions +#define STCON static const + +#if LBMDIM==3 + + //! id string of solver + virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D3Q19]"); } + + //! how many dimensions? UNUSED? replace by LBMDIM? + STCON int cDimension; + + // Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + //! direction vector contain vecs for all spatial dirs, even if not used for LBM model + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirT = 5, + cDirB = 6, + cDirNE = 7, + cDirNW = 8, + cDirSE = 9, + cDirSW = 10, + cDirNT = 11, + cDirNB = 12, + cDirST = 13, + cDirSB = 14, + cDirET = 15, + cDirEB = 16, + cDirWT = 17, + cDirWB = 18 + } dfDir; + + /* Vector Order 3D: + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + * 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 + * 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 + * 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 + */ + + /*! name of the dist. function + only for nicer output */ + STCON char* dfString[ 19 ]; + + /*! index of normal dist func, not used so far?... */ + STCON int dfNorm[ 19 ]; + + /*! index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 19 ]; + + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 19 ]; + /*! index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 19 ]; + + /*! dist func vectors */ + STCON int dfVecX[ 27 ]; + STCON int dfVecY[ 27 ]; + STCON int dfVecZ[ 27 ]; + + /*! arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 27 ]; + STCON LbmFloat dfDvecY[ 27 ]; + STCON LbmFloat dfDvecZ[ 27 ]; + + /*! principal directions */ + STCON int princDirX[ 2*3 ]; + STCON int princDirY[ 2*3 ]; + STCON int princDirZ[ 2*3 ]; + + /*! vector lengths */ + STCON LbmFloat dfLength[ 19 ]; + + /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 19 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ]; + static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ]; + +#else // end LBMDIM==3 , LBMDIM==2 + + //! id string of solver + virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D2Q9]"); } + + //! how many dimensions? + STCON int cDimension; + + //! Wi factors for collide step + STCON LbmFloat cCollenZero; + STCON LbmFloat cCollenOne; + STCON LbmFloat cCollenSqrtTwo; + + //! threshold value for filled/emptied cells + STCON LbmFloat cMagicNr2; + STCON LbmFloat cMagicNr2Neg; + STCON LbmFloat cMagicNr; + STCON LbmFloat cMagicNrNeg; + + //! size of a single set of distribution functions + STCON int cDfNum; + STCON int cDirNum; + + //! distribution functions directions + typedef enum { + cDirInv= -1, + cDirC = 0, + cDirN = 1, + cDirS = 2, + cDirE = 3, + cDirW = 4, + cDirNE = 5, + cDirNW = 6, + cDirSE = 7, + cDirSW = 8 + } dfDir; + + /* Vector Order 2D: + * 0 1 2 3 4 5 6 7 8 + * 0, 0,0, 1,-1, 1,-1,1,-1 + * 0, 1,-1, 0,0, 1,1,-1,-1 */ + + /* name of the dist. function + only for nicer output */ + STCON char* dfString[ 9 ]; + + /* index of normal dist func, not used so far?... */ + STCON int dfNorm[ 9 ]; + + /* index of inverse dist func, not fast, but useful... */ + STCON int dfInv[ 9 ]; + + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefX[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefY[ 9 ]; + /* index of x reflected dist func for free slip, not valid for all DFs... */ + STCON int dfRefZ[ 9 ]; + + /* dist func vectors */ + STCON int dfVecX[ 9 ]; + STCON int dfVecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON int dfVecZ[ 9 ]; + + /* arrays as before with doubles */ + STCON LbmFloat dfDvecX[ 9 ]; + STCON LbmFloat dfDvecY[ 9 ]; + /* Z, 2D values are all 0! */ + STCON LbmFloat dfDvecZ[ 9 ]; + + /*! principal directions */ + STCON int princDirX[ 2*2 ]; + STCON int princDirY[ 2*2 ]; + STCON int princDirZ[ 2*2 ]; + + /* vector lengths */ + STCON LbmFloat dfLength[ 9 ]; + + /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ + static LbmFloat dfEquil[ 9 ]; + + /*! arrays for les model coefficients */ + static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ]; + static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ]; + +#endif // LBMDIM==2 }; +#undef STCON /*****************************************************************************/ @@ -479,7 +682,7 @@ class LbmFsgrSolver : // cell mark debugging #if FSGR_STRICT_DEBUG==10 #define debugMarkCell(lev,x,y,z) \ - errMsg("debugMarkCell",D::mName<<" step: "<<D::mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \ + errMsg("debugMarkCell",this->mName<<" step: "<<this->mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \ debugMarkCellCall((lev),(x),(y),(z)); #else // FSGR_STRICT_DEBUG==1 #define debugMarkCell(lev,x,y,z) \ @@ -494,8 +697,8 @@ class LbmFsgrSolver : //! flag array acces macro #define _RFLAG(level,xx,yy,zz,set) mLevel[level].mprsFlags[set][ LBMGI((level),(xx),(yy),(zz),(set)) ] -#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set) ] -#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set) ] +#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set) ] +#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set) ] // array data layouts // standard array layout ----------------------------------------------------------------------------------------------- @@ -503,8 +706,8 @@ class LbmFsgrSolver : //#define _LBMQI(level, ii,ij,ik, is, lunused) ( ((is)*mLevel[level].lOffsz) + (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) #define _LBMQI(level, ii,ij,ik, is, lunused) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) ) #define _QCELL(level,xx,yy,zz,set,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx),(yy),(zz),(set), l)*dTotalNum +(l)]) -#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set, l)*dTotalNum +(l)]) -#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set, l)*dTotalNum +(l)]) +#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set, l)*dTotalNum +(l)]) +#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set, l)*dTotalNum +(l)]) #define QCELLSTEP dTotalNum #define _RACPNT(level, ii,ij,ik, is ) &QCELL(level,ii,ij,ik,is,0) @@ -555,7 +758,6 @@ class LbmFsgrSolver : #define dNW 6 #define dSE 7 #define dSW 8 -#define LBM_DFNUM 9 #else // direction indices #define dC 0 @@ -577,12 +779,11 @@ class LbmFsgrSolver : #define dEB 16 #define dWT 17 #define dWB 18 -#define LBM_DFNUM 19 #endif //? #define dWB 18 // default init for dFlux values -#define FLUX_INIT 0.5f * (float)(D::cDfNum) +#define FLUX_INIT 0.5f * (float)(this->cDfNum) // only for non DF dir handling! #define dNET 19 @@ -617,24 +818,44 @@ class LbmFsgrSolver : +/******************************************************************************/ +/*! equilibrium functions */ +/******************************************************************************/ + +/*! calculate length of velocity vector */ +inline LbmFloat LbmFsgrSolver::getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) { + return ((ux)*dfDvecX[l]+(uy)*dfDvecY[l]+(uz)*dfDvecZ[l]); +}; + +/*! calculate equilibrium DF for given values */ +inline LbmFloat LbmFsgrSolver::getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) { +#if FSGR_STRICT_DEBUG==1 + if((l<0)||(l>LBM_DFNUM)) { errFatal("LbmFsgrSolver::getCollideEq","Invalid DFEQ call "<<l, SIMWORLD_PANIC ); /* no access to mPanic here */ } +#endif // FSGR_STRICT_DEBUG==1 + LbmFloat tmp = getVelVecLen(l,ux,uy,uz); + return( dfLength[l] *( + + rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) + + 3.0 *tmp + + 9.0/2.0 *(tmp*tmp) ) + ); +}; + /*****************************************************************************/ /* init a given cell with flag, density, mass and equilibrium dist. funcs */ -template<class D> -void LbmFsgrSolver<D>::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) { +void LbmFsgrSolver::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) { CellFlagType pers = RFLAG(level,xx,yy,zz,set) & CFPersistMask; RFLAG(level,xx,yy,zz,set) = newflag | pers; } -template<class D> void -LbmFsgrSolver<D>::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) { +LbmFsgrSolver::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) { /* init eq. dist funcs */ LbmFloat *ecel; int workSet = mLevel[level].setCurr; ecel = RACPNT(level, i,j,k, workSet); - FORDF0 { RAC(ecel, l) = D::dfEquil[l] * rho; } + FORDF0 { RAC(ecel, l) = this->dfEquil[l] * rho; } RAC(ecel, dMass) = mass; RAC(ecel, dFfrac) = mass/rho; RAC(ecel, dFlux) = FLUX_INIT; @@ -646,14 +867,13 @@ LbmFsgrSolver<D>::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, return; } -template<class D> void -LbmFsgrSolver<D>::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) { +LbmFsgrSolver::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) { LbmFloat *ecel; int workSet = mLevel[level].setCurr; ecel = RACPNT(level, i,j,k, workSet); - FORDF0 { RAC(ecel, l) = D::getCollideEq(l, rho,vel[0],vel[1],vel[2]); } + FORDF0 { RAC(ecel, l) = getCollideEq(l, rho,vel[0],vel[1],vel[2]); } RAC(ecel, dMass) = mass; RAC(ecel, dFfrac) = mass/rho; RAC(ecel, dFlux) = FLUX_INIT; @@ -665,24 +885,20 @@ LbmFsgrSolver<D>::initVelocityCell(int level, int i,int j,int k, CellFlagType fl return; } -template<class D> -int LbmFsgrSolver<D>::getForZMinBnd() { +int LbmFsgrSolver::getForZMinBnd() { return 0; } -template<class D> -int LbmFsgrSolver<D>::getForZMin1() { - if(D::cDimension==2) return 0; +int LbmFsgrSolver::getForZMin1() { + if(LBMDIM==2) return 0; return 1; } -template<class D> -int LbmFsgrSolver<D>::getForZMaxBnd(int lev) { - if(D::cDimension==2) return 1; +int LbmFsgrSolver::getForZMaxBnd(int lev) { + if(LBMDIM==2) return 1; return mLevel[lev].lSizez -0; } -template<class D> -int LbmFsgrSolver<D>::getForZMax1(int lev) { - if(D::cDimension==2) return 1; +int LbmFsgrSolver::getForZMax1(int lev) { + if(LBMDIM==2) return 1; return mLevel[lev].lSizez -1; } diff --git a/intern/elbeem/intern/solver_dimenions.h b/intern/elbeem/intern/solver_dimenions.h deleted file mode 100644 index 04f9eb5c125..00000000000 --- a/intern/elbeem/intern/solver_dimenions.h +++ /dev/null @@ -1,21 +0,0 @@ -/****************************************************************************** - * - * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method - * All code distributed as part of El'Beem is covered by the version 2 of the - * GNU General Public License. See the file COPYING for details. - * Copyright 2003-2005 Nils Thuerey - * - * Combined 2D/3D Lattice Boltzmann Solver auxiliary classes - * - *****************************************************************************/ -#ifndef LBMHEADER_H - -/* LBM Files */ -#include "solver_interface.h" - - -#define LBMHEADER_H -#endif - - - diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp index a138ad19ca8..44b24264caf 100644 --- a/intern/elbeem/intern/solver_init.cpp +++ b/intern/elbeem/intern/solver_init.cpp @@ -7,30 +7,302 @@ * *****************************************************************************/ -#if ((!defined(__APPLE_CC__)) && (!defined(__INTEL_COMPILER))) || defined(LBM_FORCEINCLUDE) + #include "solver_class.h" #include "solver_relax.h" - // for geo init FGI_ defines #include "elbeem.h" +/*****************************************************************************/ +//! common variables + +/*****************************************************************************/ +/*! 3D implementation D3Q19 */ +#if LBMDIM==3 + + //! how many dimensions? + const int LbmFsgrSolver::cDimension = 3; + + // Wi factors for collide step + const LbmFloat LbmFsgrSolver::cCollenZero = (1.0/3.0); + const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/18.0); + const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0); + + //! threshold value for filled/emptied cells + const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005; + const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005; + const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001; + const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001; + + //! size of a single set of distribution functions + const int LbmFsgrSolver::cDfNum = 19; + //! direction vector contain vecs for all spatial dirs, even if not used for LBM model + const int LbmFsgrSolver::cDirNum = 27; + + //const string LbmFsgrSolver::dfString[ cDfNum ] = { + const char* LbmFsgrSolver::dfString[ cDfNum ] = { + " C", " N"," S"," E"," W"," T"," B", + "NE","NW","SE","SW", + "NT","NB","ST","SB", + "ET","EB","WT","WB" + }; + + const int LbmFsgrSolver::dfNorm[ cDfNum ] = { + cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB, + cDirNE, cDirNW, cDirSE, cDirSW, + cDirNT, cDirNB, cDirST, cDirSB, + cDirET, cDirEB, cDirWT, cDirWB + }; + + const int LbmFsgrSolver::dfInv[ cDfNum ] = { + cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT, + cDirSW, cDirSE, cDirNW, cDirNE, + cDirSB, cDirST, cDirNB, cDirNT, + cDirWB, cDirWT, cDirEB, cDirET + }; + + const int LbmFsgrSolver::dfRefX[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + cDirSE, cDirSW, cDirNE, cDirNW, + 0, 0, 0, 0, + cDirEB, cDirET, cDirWB, cDirWT + }; + + const int LbmFsgrSolver::dfRefY[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + cDirNW, cDirNE, cDirSW, cDirSE, + cDirNB, cDirNT, cDirSB, cDirST, + 0, 0, 0, 0 + }; + + const int LbmFsgrSolver::dfRefZ[ cDfNum ] = { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + cDirST, cDirSB, cDirNT, cDirNB, + cDirWT, cDirWB, cDirET, cDirEB + }; + + // Vector Order 3D: + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + // 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 + // 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 + // 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 + + const int LbmFsgrSolver::dfVecX[ cDirNum ] = { + 0, 0,0, 1,-1, 0,0, + 1,-1,1,-1, + 0,0,0,0, + 1,1,-1,-1, + 1,-1, 1,-1, + 1,-1, 1,-1, + }; + const int LbmFsgrSolver::dfVecY[ cDirNum ] = { + 0, 1,-1, 0,0,0,0, + 1,1,-1,-1, + 1,1,-1,-1, + 0,0,0,0, + 1, 1,-1,-1, + 1, 1,-1,-1 + }; + const int LbmFsgrSolver::dfVecZ[ cDirNum ] = { + 0, 0,0,0,0,1,-1, + 0,0,0,0, + 1,-1,1,-1, + 1,-1,1,-1, + 1, 1, 1, 1, + -1,-1,-1,-1 + }; + + const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = { + 0, 0,0, 1,-1, 0,0, + 1,-1,1,-1, + 0,0,0,0, + 1,1,-1,-1, + 1,-1, 1,-1, + 1,-1, 1,-1 + }; + const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = { + 0, 1,-1, 0,0,0,0, + 1,1,-1,-1, + 1,1,-1,-1, + 0,0,0,0, + 1, 1,-1,-1, + 1, 1,-1,-1 + }; + const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = { + 0, 0,0,0,0,1,-1, + 0,0,0,0, + 1,-1,1,-1, + 1,-1,1,-1, + 1, 1, 1, 1, + -1,-1,-1,-1 + }; + + /* principal directions */ + const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = { + 1,-1, 0,0, 0,0 + }; + const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = { + 0,0, 1,-1, 0,0 + }; + const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = { + 0,0, 0,0, 1,-1 + }; + + /*! arrays for les model coefficients, inited in lbmsolver constructor */ + LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; + LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ]; + + + const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= { + cCollenZero, + cCollenOne, cCollenOne, cCollenOne, + cCollenOne, cCollenOne, cCollenOne, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo + }; + + /* precalculated equilibrium dfs, inited in lbmsolver constructor */ + LbmFloat LbmFsgrSolver::dfEquil[ cDfNum ]; + +#else // end LBMDIM==3 , LBMDIM==2 + +/*****************************************************************************/ +/*! 2D implementation D2Q9 */ + + //! how many dimensions? + const int LbmFsgrSolver::cDimension = 2; + + //! Wi factors for collide step + const LbmFloat LbmFsgrSolver::cCollenZero = (4.0/9.0); + const LbmFloat LbmFsgrSolver::cCollenOne = (1.0/9.0); + const LbmFloat LbmFsgrSolver::cCollenSqrtTwo = (1.0/36.0); + + //! threshold value for filled/emptied cells + const LbmFloat LbmFsgrSolver::cMagicNr2 = 1.0005; + const LbmFloat LbmFsgrSolver::cMagicNr2Neg = -0.0005; + const LbmFloat LbmFsgrSolver::cMagicNr = 1.010001; + const LbmFloat LbmFsgrSolver::cMagicNrNeg = -0.010001; + + //! size of a single set of distribution functions + const int LbmFsgrSolver::cDfNum = 9; + const int LbmFsgrSolver::cDirNum = 9; + + //const string LbmFsgrSolver::dfString[ cDfNum ] = { + const char* LbmFsgrSolver::dfString[ cDfNum ] = { + " C", + " N", " S", " E", " W", + "NE", "NW", "SE","SW" + }; + + const int LbmFsgrSolver::dfNorm[ cDfNum ] = { + cDirC, + cDirN, cDirS, cDirE, cDirW, + cDirNE, cDirNW, cDirSE, cDirSW + }; + + const int LbmFsgrSolver::dfInv[ cDfNum ] = { + cDirC, + cDirS, cDirN, cDirW, cDirE, + cDirSW, cDirSE, cDirNW, cDirNE + }; + + const int LbmFsgrSolver::dfRefX[ cDfNum ] = { + 0, + 0, 0, 0, 0, + cDirSE, cDirSW, cDirNE, cDirNW + }; + + const int LbmFsgrSolver::dfRefY[ cDfNum ] = { + 0, + 0, 0, 0, 0, + cDirNW, cDirNE, cDirSW, cDirSE + }; + + const int LbmFsgrSolver::dfRefZ[ cDfNum ] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + // Vector Order 2D: + // 0 1 2 3 4 5 6 7 8 + // 0, 0,0, 1,-1, 1,-1,1,-1 + // 0, 1,-1, 0,0, 1,1,-1,-1 + + const int LbmFsgrSolver::dfVecX[ cDirNum ] = { + 0, + 0,0, 1,-1, + 1,-1,1,-1 + }; + const int LbmFsgrSolver::dfVecY[ cDirNum ] = { + 0, + 1,-1, 0,0, + 1,1,-1,-1 + }; + const int LbmFsgrSolver::dfVecZ[ cDirNum ] = { + 0, 0,0,0,0, 0,0,0,0 + }; + + const LbmFloat LbmFsgrSolver::dfDvecX[ cDirNum ] = { + 0, + 0,0, 1,-1, + 1,-1,1,-1 + }; + const LbmFloat LbmFsgrSolver::dfDvecY[ cDirNum ] = { + 0, + 1,-1, 0,0, + 1,1,-1,-1 + }; + const LbmFloat LbmFsgrSolver::dfDvecZ[ cDirNum ] = { + 0, 0,0,0,0, 0,0,0,0 + }; + + const int LbmFsgrSolver::princDirX[ 2*LbmFsgrSolver::cDimension ] = { + 1,-1, 0,0 + }; + const int LbmFsgrSolver::princDirY[ 2*LbmFsgrSolver::cDimension ] = { + 0,0, 1,-1 + }; + const int LbmFsgrSolver::princDirZ[ 2*LbmFsgrSolver::cDimension ] = { + 0,0, 0,0 + }; + + + /*! arrays for les model coefficients, inited in lbmsolver constructor */ + LbmFloat LbmFsgrSolver::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; + LbmFloat LbmFsgrSolver::lesCoeffOffdiag[ cDimension ][ cDirNum ]; + + + const LbmFloat LbmFsgrSolver::dfLength[ cDfNum ]= { + cCollenZero, + cCollenOne, cCollenOne, cCollenOne, cCollenOne, + cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo + }; + + /* precalculated equilibrium dfs, inited in lbmsolver constructor */ + LbmFloat LbmFsgrSolver::dfEquil[ cDfNum ]; + +// D2Q9 end +#endif // LBMDIM==2 + + /****************************************************************************** * Lbm Constructor *****************************************************************************/ -template<class D> -LbmFsgrSolver<D>::LbmFsgrSolver() : - D(), +LbmFsgrSolver::LbmFsgrSolver() : + //D(), mCurrentMass(0.0), mCurrentVolume(0.0), mNumProblems(0), mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0), mpPreviewSurface(NULL), - mTimeAdap(true), mDomainBound("noslip"), mDomainPartSlipValue(0.1), + mTimeAdap(true), mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false), mInitSurfaceSmoothing(0), mTimestepReduceLock(0), - mTimeSwitchCounts(0), - mSimulationTime(0.0), - mMinStepTime(0.0), mMaxStepTime(0.0), + mTimeSwitchCounts(0), mTimeMaxvelStepCnt(0), + mSimulationTime(0.0), mLastSimTime(0.0), + mMinTimestep(0.0), mMaxTimestep(0.0), mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0), mDropMode(1), mDropSize(0.15), mDropSpeed(0.0), mObjectSpeeds(), mObjectPartslips(), @@ -41,52 +313,51 @@ LbmFsgrSolver<D>::LbmFsgrSolver() : mLastOmega(1e10), mLastGravity(1e10), mNumInvIfTotal(0), mNumFsgrChanges(0), mDisableStandingFluidInit(0), - mForceTadapRefine(-1) + mForceTadapRefine(-1), mCutoff(-1) { // not much to do here... - D::mpIso = new IsoSurface( D::mIsoValue, false ); -#if ELBEEM_PLUGIN!=1 +#if LBM_INCLUDE_TESTSOLVERS==1 mpTest = new LbmTestdata(); - mpParticles = NULL; #endif // ELBEEM_PLUGIN!=1 + this->mpIso = new IsoSurface( this->mIsoValue ); // init equilibrium dist. func LbmFloat rho=1.0; FORDF0 { - D::dfEquil[l] = D::getCollideEq( l,rho, 0.0, 0.0, 0.0); + this->dfEquil[l] = this->getCollideEq( l,rho, 0.0, 0.0, 0.0); } // init LES int odm = 0; - for(int m=0; m<D::cDimension; m++) { - for(int l=0; l<D::cDfNum; l++) { - D::lesCoeffDiag[m][l] = - D::lesCoeffOffdiag[m][l] = 0.0; + for(int m=0; m<LBMDIM; m++) { + for(int l=0; l<this->cDfNum; l++) { + this->lesCoeffDiag[m][l] = + this->lesCoeffOffdiag[m][l] = 0.0; } } - for(int m=0; m<D::cDimension; m++) { - for(int n=0; n<D::cDimension; n++) { - for(int l=1; l<D::cDfNum; l++) { + for(int m=0; m<LBMDIM; m++) { + for(int n=0; n<LBMDIM; n++) { + for(int l=1; l<this->cDfNum; l++) { LbmFloat em; switch(m) { - case 0: em = D::dfDvecX[l]; break; - case 1: em = D::dfDvecY[l]; break; - case 2: em = D::dfDvecZ[l]; break; + case 0: em = this->dfDvecX[l]; break; + case 1: em = this->dfDvecY[l]; break; + case 2: em = this->dfDvecZ[l]; break; default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR); } LbmFloat en; switch(n) { - case 0: en = D::dfDvecX[l]; break; - case 1: en = D::dfDvecY[l]; break; - case 2: en = D::dfDvecZ[l]; break; + case 0: en = this->dfDvecX[l]; break; + case 1: en = this->dfDvecY[l]; break; + case 2: en = this->dfDvecZ[l]; break; default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR); } const LbmFloat coeff = em*en; if(m==n) { - D::lesCoeffDiag[m][l] = coeff; + this->lesCoeffDiag[m][l] = coeff; } else { if(m>n) { - D::lesCoeffOffdiag[odm][l] = coeff; + this->lesCoeffOffdiag[odm][l] = coeff; } } } @@ -101,7 +372,7 @@ LbmFsgrSolver<D>::LbmFsgrSolver() : mDvecNrm[0] = LbmVec(0.0); FORDF1 { mDvecNrm[l] = getNormalized( - LbmVec(D::dfDvecX[D::dfInv[l]], D::dfDvecY[D::dfInv[l]], D::dfDvecZ[D::dfInv[l]] ) + LbmVec(this->dfDvecX[this->dfInv[l]], this->dfDvecY[this->dfInv[l]], this->dfDvecZ[this->dfInv[l]] ) ) * -1.0; } @@ -109,32 +380,32 @@ LbmFsgrSolver<D>::LbmFsgrSolver() : //LbmFloat mGaussw[27]; LbmFloat totGaussw = 0.0; const LbmFloat alpha = 1.0; - const LbmFloat gw = sqrt(2.0*D::cDimension); + const LbmFloat gw = sqrt(2.0*LBMDIM); #if ELBEEM_PLUGIN!=1 errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!"); #endif - for(int n=0;(n<D::cDirNum); n++) { mGaussw[n] = 0.0; } - //for(int n=0;(n<D::cDirNum); n++) { - for(int n=0;(n<D::cDfNum); n++) { - const LbmFloat d = norm(LbmVec(D::dfVecX[n], D::dfVecY[n], D::dfVecZ[n])); + for(int n=0;(n<this->cDirNum); n++) { mGaussw[n] = 0.0; } + //for(int n=0;(n<this->cDirNum); n++) { + for(int n=0;(n<this->cDfNum); n++) { + const LbmFloat d = norm(LbmVec(this->dfVecX[n], this->dfVecY[n], this->dfVecZ[n])); LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw ); mGaussw[n] = w; totGaussw += w; } - for(int n=0;(n<D::cDirNum); n++) { + for(int n=0;(n<this->cDirNum); n++) { mGaussw[n] = mGaussw[n]/totGaussw; } + mpParticles = NULL; //addDrop(false,0,0); } /*****************************************************************************/ /* Destructor */ /*****************************************************************************/ -template<class D> -LbmFsgrSolver<D>::~LbmFsgrSolver() +LbmFsgrSolver::~LbmFsgrSolver() { - if(!D::mInitDone){ debugOut("LbmFsgrSolver::LbmFsgrSolver : not inited...",0); return; } + if(!this->mInitDone){ debugOut("LbmFsgrSolver::LbmFsgrSolver : not inited...",0); return; } #if COMPRESSGRIDS==1 delete mLevel[mMaxRefine].mprsCells[1]; mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL; @@ -146,17 +417,16 @@ LbmFsgrSolver<D>::~LbmFsgrSolver() if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s]; } } - delete D::mpIso; + delete this->mpIso; if(mpPreviewSurface) delete mpPreviewSurface; -#if ELBEEM_PLUGIN!=1 - destroyTestdata(); - delete mpTest; +#if LBM_INCLUDE_TESTSOLVERS==1 + // cleanup done during scene deletion... #endif // ELBEEM_PLUGIN!=1 // always output performance estimate debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5); - if(!D::mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10); + if(!this->mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10); } @@ -165,29 +435,27 @@ LbmFsgrSolver<D>::~LbmFsgrSolver() /****************************************************************************** * initilize variables fom attribute list *****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::parseAttrList() +void LbmFsgrSolver::parseAttrList() { LbmSolverInterface::parseStdAttrList(); string matIso("default"); - matIso = D::mpAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false ); - D::mpIso->setMaterialName( matIso ); - D::mOutputSurfacePreview = D::mpAttrs->readInt("surfacepreview", D::mOutputSurfacePreview, "SimulationLbm","D::mOutputSurfacePreview", false ); - mTimeAdap = D::mpAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false ); - mDomainBound = D::mpAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false ); - mDomainPartSlipValue = D::mpAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false ); - - mIsoWeightMethod= D::mpAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false ); - mInitSurfaceSmoothing = D::mpAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false ); - D::mSmoothSurface = D::mpAttrs->readFloat("smoothsurface", D::mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); - D::mSmoothNormals = D::mpAttrs->readFloat("smoothnormals", D::mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); - - mInitialCsmago = D::mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); + matIso = this->mpAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false ); + this->mpIso->setMaterialName( matIso ); + this->mOutputSurfacePreview = this->mpAttrs->readInt("surfacepreview", this->mOutputSurfacePreview, "SimulationLbm","this->mOutputSurfacePreview", false ); + mTimeAdap = this->mpAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false ); + this->mDomainBound = this->mpAttrs->readString("domainbound", this->mDomainBound, "SimulationLbm","mDomainBound", false ); + this->mDomainPartSlipValue = this->mpAttrs->readFloat("domainpartslip", this->mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false ); + + mIsoWeightMethod= this->mpAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false ); + mInitSurfaceSmoothing = this->mpAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false ); + this->mSmoothSurface = this->mpAttrs->readFloat("smoothsurface", this->mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); + this->mSmoothNormals = this->mpAttrs->readFloat("smoothnormals", this->mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); + + mInitialCsmago = this->mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); // deprecated! float mInitialCsmagoCoarse = 0.0; - mInitialCsmagoCoarse = D::mpAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false ); + mInitialCsmagoCoarse = this->mpAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false ); #if USE_LES==1 #else // USE_LES==1 debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2); @@ -195,42 +463,47 @@ LbmFsgrSolver<D>::parseAttrList() #endif // USE_LES==1 // refinement - mMaxRefine = D::mRefinementDesired; - mMaxRefine = D::mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false); + mMaxRefine = this->mRefinementDesired; + mMaxRefine = this->mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false); if(mMaxRefine<0) mMaxRefine=0; if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1; - mDisableStandingFluidInit = D::mpAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false); - mForceTadapRefine = D::mpAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false); + mDisableStandingFluidInit = this->mpAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false); + mForceTadapRefine = this->mpAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false); // demo mode settings - mFVHeight = D::mpAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false ); + mFVHeight = this->mpAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false ); // FIXME check needed? - mFVArea = D::mpAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false ); + mFVArea = this->mpAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false ); -#if ELBEEM_PLUGIN!=1 +#if LBM_INCLUDE_TESTSOLVERS==1 mUseTestdata = 0; - mUseTestdata = D::mpAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false); - mpTest->parseTestdataAttrList(D::mpAttrs); -#endif // ELBEEM_PLUGIN!=1 + mUseTestdata = this->mpAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false); + mpTest->parseTestdataAttrList(this->mpAttrs); +#ifdef ELBEEM_PLUGIN + mUseTestdata=1; // DEBUG +#endif // ELBEEM_PLUGIN + errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" "); +#else // LBM_INCLUDE_TESTSOLVERS!=1 + // off by default + mUseTestdata = 0; +#endif // LBM_INCLUDE_TESTSOLVERS!=1 } /****************************************************************************** * Initialize omegas and forces on all levels (for init/timestep change) *****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::initLevelOmegas() +void LbmFsgrSolver::initLevelOmegas() { // no explicit settings - D::mOmega = D::mpParam->calculateOmega(mSimulationTime); - D::mGravity = vec2L( D::mpParam->calculateGravity(mSimulationTime) ); - D::mSurfaceTension = D::mpParam->calculateSurfaceTension(); // unused + this->mOmega = this->mpParam->calculateOmega(mSimulationTime); + this->mGravity = vec2L( this->mpParam->calculateGravity(mSimulationTime) ); + this->mSurfaceTension = 0.; //this->mpParam->calculateSurfaceTension(); // unused // check if last init was ok - LbmFloat gravDelta = norm(D::mGravity-mLastGravity); - //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<D::mOmega<<" - lom:"<<mLastOmega<<" gv:"<<D::mGravity<<" - "<<mLastGravity<<" , "<<gravDelta ); - if((D::mOmega == mLastOmega) && (gravDelta<=0.0)) return; + LbmFloat gravDelta = norm(this->mGravity-mLastGravity); + //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<this->mOmega<<" - lom:"<<mLastOmega<<" gv:"<<this->mGravity<<" - "<<mLastGravity<<" , "<<gravDelta ); + if((this->mOmega == mLastOmega) && (gravDelta<=0.0)) return; if(mInitialCsmago<=0.0) { if(OPT3D==1) { @@ -242,8 +515,8 @@ LbmFsgrSolver<D>::initLevelOmegas() // use Tau instead of Omega for calculations { // init base level int i = mMaxRefine; - mLevel[i].omega = D::mOmega; - mLevel[i].stepsize = D::mpParam->getStepTime(); + mLevel[i].omega = this->mOmega; + mLevel[i].timestep = this->mpParam->getTimestep(); mLevel[i].lcsmago = mInitialCsmago; //CSMAGO_INITIAL; mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); @@ -255,42 +528,42 @@ LbmFsgrSolver<D>::initLevelOmegas() double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5; nomega = 1.0/nomega; mLevel[i].omega = (LbmFloat)nomega; - mLevel[i].stepsize = 2.0 * mLevel[i+1].stepsize; + mLevel[i].timestep = 2.0 * mLevel[i+1].timestep; mLevel[i].lcsmago = mInitialCsmago; mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago; mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0); } // for lbgk - mLevel[ mMaxRefine ].gravity = D::mGravity / mLevel[ mMaxRefine ].omega; + mLevel[ mMaxRefine ].gravity = this->mGravity / mLevel[ mMaxRefine ].omega; for(int i=mMaxRefine-1; i>=0; i--) { // should be the same on all levels... // for lbgk mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega; } - mLastOmega = D::mOmega; - mLastGravity = D::mGravity; + mLastOmega = this->mOmega; + mLastGravity = this->mGravity; // debug? invalidate old values... - D::mGravity = -100.0; - D::mOmega = -100.0; + this->mGravity = -100.0; + this->mOmega = -100.0; for(int i=0; i<=mMaxRefine; i++) { - if(!D::mSilent) { + if(!this->mSilent) { errMsg("LbmFsgrSolver", "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" offs:"<<mLevel[i].lOffsx<<","<<mLevel[i].lOffsy<<","<<mLevel[i].lOffsz <<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", " <<" cmsagp:"<<mLevel[i].lcsmago<<", " - << " ss"<<mLevel[i].stepsize<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize ); + << " ss"<<mLevel[i].timestep<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize ); } else { - if(!D::mInitDone) { + if(!this->mInitDone) { debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" " <<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5); } } } if(mMaxRefine>0) { - mDfScaleUp = (mLevel[0 ].stepsize/mLevel[0+1].stepsize)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu - mDfScaleDown = (mLevel[0+1].stepsize/mLevel[0 ].stepsize)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu + mDfScaleUp = (mLevel[0 ].timestep/mLevel[0+1].timestep)* (1.0/mLevel[0 ].omega-1.0)/ (1.0/mLevel[0+1].omega-1.0); // yu + mDfScaleDown = (mLevel[0+1].timestep/mLevel[0 ].timestep)* (1.0/mLevel[0+1].omega-1.0)/ (1.0/mLevel[0 ].omega-1.0); // yu } } @@ -298,26 +571,26 @@ LbmFsgrSolver<D>::initLevelOmegas() /****************************************************************************** * Init Solver (values should be read from config file) *****************************************************************************/ -template<class D> -bool -//LbmFsgrSolver<D>::initialize( ntlTree* /*tree*/, vector<ntlGeometryObject*>* /*objects*/ ) -LbmFsgrSolver<D>::initializeSolver() +bool LbmFsgrSolver::initializeSolver() { - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<<ALSTRING<<") ",1); + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<<ALSTRING<<") "<<this->mInitDone<<" "<<(int)this,1); // size inits to force cubic cells and mult4 level dimensions // and make sure we dont allocate too much... bool memOk = false; - int orgSx = D::mSizex; - int orgSy = D::mSizey; - int orgSz = D::mSizez; + int orgSx = this->mSizex; + int orgSy = this->mSizey; + int orgSz = this->mSizez; double sizeReduction = 1.0; - double memCnt = -1.0; + double memEstFromFunc = -1.0; string memreqStr(""); +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { mMaxRefine=0; } // force fsgr off +#endif while(!memOk) { - initGridSizes( D::mSizex, D::mSizey, D::mSizez, - D::mvGeoStart, D::mvGeoEnd, mMaxRefine, PARALLEL); - calculateMemreqEstimate( D::mSizex, D::mSizey, D::mSizez, mMaxRefine, &memCnt, &memreqStr ); + initGridSizes( this->mSizex, this->mSizey, this->mSizez, + this->mvGeoStart, this->mvGeoEnd, mMaxRefine, PARALLEL); + calculateMemreqEstimate( this->mSizex, this->mSizey, this->mSizez, mMaxRefine, &memEstFromFunc, &memreqStr ); double memLimit; if(sizeof(int)==4) { @@ -327,55 +600,52 @@ LbmFsgrSolver<D>::initializeSolver() // 64bit, just take 16GB as limit for now... memLimit = 16.0* 1024.0*1024.0*1024.0; } - if(memCnt>memLimit) { + if(memEstFromFunc>memLimit) { sizeReduction *= 0.9; - D::mSizex = (int)(orgSx * sizeReduction); - D::mSizey = (int)(orgSy * sizeReduction); - D::mSizez = (int)(orgSz * sizeReduction); - debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<memCnt<<"/"<<memLimit<<", retrying: " - <<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez, 3 ); + this->mSizex = (int)(orgSx * sizeReduction); + this->mSizey = (int)(orgSy * sizeReduction); + this->mSizez = (int)(orgSz * sizeReduction); + debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<memEstFromFunc<<"/"<<memLimit<<", retrying: " + <<this->mSizex<<" Y:"<<this->mSizey<<" Z:"<<this->mSizez, 3 ); } else { memOk = true; } } - D::mPreviewFactor = (LbmFloat)D::mOutputSurfacePreview / (LbmFloat)D::mSizex; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez<< - ", Domain: "<<D::mvGeoStart<<":"<<D::mvGeoEnd<<", "<<(D::mvGeoEnd-D::mvGeoStart)<< + this->mPreviewFactor = (LbmFloat)this->mOutputSurfacePreview / (LbmFloat)this->mSizex; + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<this->mSizex<<" Y:"<<this->mSizey<<" Z:"<<this->mSizez<< + ", Domain: "<<this->mvGeoStart<<":"<<this->mvGeoEnd<<", "<<(this->mvGeoEnd-this->mvGeoStart)<< ", est. Mem.Req.: "<<memreqStr ,2); - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG, ,2); - D::mpParam->setSize(D::mSizex, D::mSizey, D::mSizez); - - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<<D::mSizex<<" Y:"<<D::mSizey<<" Z:"<<D::mSizez ,2); + this->mpParam->setSize(this->mSizex, this->mSizey, this->mSizez); -#if ELBEEM_PLUGIN!=1 debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: " - <<"LBM_EPSILON="<<LBM_EPSILON <<" " - <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" " - <<"OPT3D="<<OPT3D <<" " + <<"LBM_EPSILON="<<LBM_EPSILON <<" " + <<"FSGR_STRICT_DEBUG="<<FSGR_STRICT_DEBUG <<" " + <<"OPT3D="<<OPT3D <<" " <<"COMPRESSGRIDS="<<COMPRESSGRIDS<<" " - <<"MASS_INVALID="<<MASS_INVALID <<" " - <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" " - <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" " - <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" " - <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" " - <<"USE_LES="<<USE_LES <<" " + <<"MASS_INVALID="<<MASS_INVALID <<" " + <<"FSGR_LISTTRICK="<<FSGR_LISTTRICK <<" " + <<"FSGR_LISTTTHRESHEMPTY="<<FSGR_LISTTTHRESHEMPTY <<" " + <<"FSGR_LISTTTHRESHFULL="<<FSGR_LISTTTHRESHFULL <<" " + <<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" " + <<"USE_LES="<<USE_LES <<" " ,10); +#if ELBEEM_PLUGIN!=1 #endif // ELBEEM_PLUGIN!=1 // perform 2D corrections... - if(D::cDimension == 2) D::mSizez = 1; + if(LBMDIM == 2) this->mSizez = 1; - D::mpParam->setSimulationMaxSpeed(0.0); - if(mFVHeight>0.0) D::mpParam->setFluidVolumeHeight(mFVHeight); - D::mpParam->setTadapLevels( mMaxRefine+1 ); + this->mpParam->setSimulationMaxSpeed(0.0); + if(mFVHeight>0.0) this->mpParam->setFluidVolumeHeight(mFVHeight); + this->mpParam->setTadapLevels( mMaxRefine+1 ); if(mForceTadapRefine>mMaxRefine) { - D::mpParam->setTadapLevels( mForceTadapRefine+1 ); + this->mpParam->setTadapLevels( mForceTadapRefine+1 ); debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<<mForceTadapRefine, 6); } - if(!D::mpParam->calculateAllMissingValues()) { + if(!this->mpParam->calculateAllMissingValues(mSimulationTime, false)) { errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR); return false; } @@ -388,7 +658,7 @@ LbmFsgrSolver<D>::initializeSolver() mLevel[i].simCellSize = 0.0; mLevel[i].omega = 0.0; mLevel[i].time = 0.0; - mLevel[i].stepsize = 1.0; + mLevel[i].timestep = 1.0; mLevel[i].gravity = LbmVec(0.0); mLevel[i].mprsCells[0] = NULL; mLevel[i].mprsCells[1] = NULL; @@ -400,9 +670,9 @@ LbmFsgrSolver<D>::initializeSolver() } // init sizes - mLevel[mMaxRefine].lSizex = D::mSizex; - mLevel[mMaxRefine].lSizey = D::mSizey; - mLevel[mMaxRefine].lSizez = D::mSizez; + mLevel[mMaxRefine].lSizex = this->mSizex; + mLevel[mMaxRefine].lSizey = this->mSizey; + mLevel[mMaxRefine].lSizez = this->mSizez; for(int i=mMaxRefine-1; i>=0; i--) { mLevel[i].lSizex = mLevel[i+1].lSizex/2; mLevel[i].lSizey = mLevel[i+1].lSizey/2; @@ -415,50 +685,50 @@ LbmFsgrSolver<D>::initializeSolver() return false; } - double memCheck = 0.0; - mLevel[ mMaxRefine ].nodeSize = ((D::mvGeoEnd[0]-D::mvGeoStart[0]) / (LbmFloat)(D::mSizex)); - mLevel[ mMaxRefine ].simCellSize = D::mpParam->getCellSize(); + double ownMemCheck = 0.0; + mLevel[ mMaxRefine ].nodeSize = ((this->mvGeoEnd[0]-this->mvGeoStart[0]) / (LbmFloat)(this->mSizex)); + mLevel[ mMaxRefine ].simCellSize = this->mpParam->getCellSize(); mLevel[ mMaxRefine ].lcellfactor = 1.0; LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); // +4 for safety ? mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - memCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); + ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); #if COMPRESSGRIDS==0 mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; - memCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); + ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); #else // COMPRESSGRIDS==0 LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ]; mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset; - memCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4); + ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4); #endif // COMPRESSGRIDS==0 LbmFloat lcfdimFac = 8.0; - if(D::cDimension==2) lcfdimFac = 4.0; + if(LBMDIM==2) lcfdimFac = 4.0; for(int i=mMaxRefine-1; i>=0; i--) { mLevel[i].nodeSize = 2.0 * mLevel[i+1].nodeSize; mLevel[i].simCellSize = 2.0 * mLevel[i+1].simCellSize; mLevel[i].lcellfactor = mLevel[i+1].lcellfactor * lcfdimFac; - if(D::cDimension==2){ mLevel[i].lSizez = 1; } // 2D + if(LBMDIM==2){ mLevel[i].lSizez = 1; } // 2D rcellSize = ((mLevel[i].lSizex*mLevel[i].lSizey*mLevel[i].lSizez) *dTotalNum); mLevel[i].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; mLevel[i].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - memCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); + ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); mLevel[i].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; mLevel[i].mprsCells[1] = new LbmFloat[ rcellSize +4 ]; - memCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); + ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); } // isosurface memory - memCheck += (3*sizeof(int)+sizeof(float)) * ((D::mSizex+2)*(D::mSizey+2)*(D::mSizez+2)); + ownMemCheck += (3*sizeof(int)+sizeof(float)) * ((this->mSizex+2)*(this->mSizey+2)*(this->mSizez+2)); // sanity check #if ELBEEM_PLUGIN!=1 - if(ABS(1.0-memCheck/memCnt)>0.01) { - errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off: "<<memCheck<<" vs. "<<memCnt ); + if(ABS(1.0-ownMemCheck/memEstFromFunc)>0.01) { + errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off! real:"<<ownMemCheck<<" vs. estimate:"<<memEstFromFunc ); } #endif // ELBEEM_PLUGIN!=1 @@ -476,15 +746,22 @@ LbmFsgrSolver<D>::initializeSolver() // calc omega, force for all levels initLevelOmegas(); - mMinStepTime = D::mpParam->getStepTime(); - mMaxStepTime = D::mpParam->getStepTime(); + mMinTimestep = this->mpParam->getTimestep(); + mMaxTimestep = this->mpParam->getTimestep(); // init isosurf - D::mpIso->setIsolevel( D::mIsoValue ); +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { + mpTest->setMaterialName( this->mpIso->getMaterialName() ); + delete this->mpIso; + this->mpIso = mpTest; + } +#endif // ELBEEM_PLUGIN!=1 + this->mpIso->setIsolevel( this->mIsoValue ); // approximate feature size with mesh resolution float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5; - D::mpIso->setSmoothSurface( D::mSmoothSurface * featureSize ); - D::mpIso->setSmoothNormals( D::mSmoothNormals * featureSize ); + this->mpIso->setSmoothSurface( this->mSmoothSurface * featureSize ); + this->mpIso->setSmoothNormals( this->mSmoothNormals * featureSize ); // init iso weight values mIsoWeightMethod int wcnt = 0; @@ -513,31 +790,31 @@ LbmFsgrSolver<D>::initializeSolver() } for(int i=0; i<27; i++) mIsoWeight[i] /= totw; - LbmVec isostart = vec2L(D::mvGeoStart); - LbmVec isoend = vec2L(D::mvGeoEnd); + LbmVec isostart = vec2L(this->mvGeoStart); + LbmVec isoend = vec2L(this->mvGeoEnd); int twodOff = 0; // 2d slices - if(D::cDimension==2) { + if(LBMDIM==2) { LbmFloat sn,se; - sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; - se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5; + sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5; + se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5; isostart[2] = sn; isoend[2] = se; twodOff = 2; } - //errMsg(" SETISO ", " "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(D::mSizex+1.0))*0.5)<<" "<<(LbmFloat)(D::mSizex+1.0)<<" " ); - D::mpIso->setStart( vec2G(isostart) ); - D::mpIso->setEnd( vec2G(isoend) ); + //errMsg(" SETISO ", " "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5)<<" "<<(LbmFloat)(this->mSizex+1.0)<<" " ); + this->mpIso->setStart( vec2G(isostart) ); + this->mpIso->setEnd( vec2G(isoend) ); LbmVec isodist = isoend-isostart; - D::mpIso->initializeIsosurface( D::mSizex+2, D::mSizey+2, D::mSizez+2+twodOff, vec2G(isodist) ); - for(int ak=0;ak<D::mSizez+2+twodOff;ak++) - for(int aj=0;aj<D::mSizey+2;aj++) - for(int ai=0;ai<D::mSizex+2;ai++) { *D::mpIso->getData(ai,aj,ak) = 0.0; } + this->mpIso->initializeIsosurface( this->mSizex+2, this->mSizey+2, this->mSizez+2+twodOff, vec2G(isodist) ); + for(int ak=0;ak<this->mSizez+2+twodOff;ak++) + for(int aj=0;aj<this->mSizey+2;aj++) + for(int ai=0;ai<this->mSizex+2;ai++) { *this->mpIso->getData(ai,aj,ak) = 0.0; } /* init array (set all invalid first) */ for(int lev=0; lev<=mMaxRefine; lev++) { FSGR_FORIJK_BOUNDS(lev) { RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage - if(!D::mAllfluid) { + if(!this->mAllfluid) { initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0); } else { initEmptyCell(lev, i,j,k, CFFluid, 1.0, 1.0); @@ -547,35 +824,37 @@ LbmFsgrSolver<D>::initializeSolver() // init defaults mAvgNumUsedCells = 0; - D::mFixMass= 0.0; + this->mFixMass= 0.0; /* init boundaries */ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10); + // init obstacles, and reinit time step size initGeometryFlags(); + mLastSimTime = -1.0; // TODO check for invalid cells? nitGenericTestCases(); // new - init noslip 1 everywhere... // half fill boundary cells? CellFlagType domainBoundType = CFInvalid; - if(mDomainBound.find(string("free")) != string::npos) { + // TODO use normal object types instad... + if(this->mDomainBound.find(string("free")) != string::npos) { domainBoundType = CFBnd | CFBndFreeslip; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<mDomainBound,10); - } else if(mDomainBound.find(string("part")) != string::npos) { + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<this->mDomainBound,10); + } else if(this->mDomainBound.find(string("part")) != string::npos) { domainBoundType = CFBnd | CFBndPartslip; // part slip type - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10); + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<this->mDomainPartSlipValue<<"), value:"<<this->mDomainBound,10); } else { domainBoundType = CFBnd | CFBndNoslip; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10); + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<this->mDomainBound,10); } // use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips) - int domainobj = (int)(D::mpGiObjects->size()); + int domainobj = (int)(this->mpGiObjects->size()); domainBoundType |= (domainobj<<24); //for(int i=0; i<(int)(domainobj+0); i++) { - //errMsg("GEOIN","i"<<i<<" "<<(*D::mpGiObjects)[i]->getName()); - //if((*D::mpGiObjects)[i] == D::mpIso) { - //check... + //errMsg("GEOIN","i"<<i<<" "<<(*this->mpGiObjects)[i]->getName()); + //if((*this->mpGiObjects)[i] == this->mpIso) { //check... //} //} //errMsg("GEOIN"," dm "<<(domainBoundType>>24)); @@ -594,7 +873,7 @@ LbmFsgrSolver<D>::initializeSolver() //initEmptyCell(mMaxRefine, mLevel[mMaxRefine].lSizex-2,j,k, domainBoundType, 0.0, BND_FILL); } - if(D::cDimension == 3) { + if(LBMDIM == 3) { // only for 3D for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) { @@ -647,8 +926,8 @@ LbmFsgrSolver<D>::initializeSolver() } mCurrentVolume = mCurrentMass = mInitialMass; - ParamVec cspv = D::mpParam->calculateCellSize(); - if(D::cDimension==2) cspv[2] = 1.0; + ParamVec cspv = this->mpParam->calculateCellSize(); + if(LBMDIM==2) cspv[2] = 1.0; inmCellCnt = 1; double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0; debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Initial Mass:"<<mInitialMass<<" normalized:"<<nrmMass, 3); @@ -656,7 +935,7 @@ LbmFsgrSolver<D>::initializeSolver() //mStartSymm = false; #if ELBEEM_PLUGIN!=1 - if((D::cDimension==2)&&(D::mSizex<200)) { + if((LBMDIM==2)&&(this->mSizex<200)) { if(!checkSymmetry("init")) { errMsg("LbmFsgrSolver::initialize","Unsymmetric init..."); } else { @@ -676,18 +955,18 @@ LbmFsgrSolver<D>::initializeSolver() adaptGrid(lev); coarseRestrictFromFine(lev); } - D::markedClearList(); + this->markedClearList(); myTime_t fsgrtend = getTime(); - if(!D::mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< ((fsgrtend-fsgrtstart)/(double)1000.0)<<"s), changes:"<<mNumFsgrChanges , 10 ); } + if(!this->mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); } mNumFsgrChanges = 0; - for(int l=0; l<D::cDirNum; l++) { + for(int l=0; l<this->cDirNum; l++) { LbmFloat area = 0.5 * 0.5 *0.5; - if(D::cDimension==2) area = 0.5 * 0.5; + if(LBMDIM==2) area = 0.5 * 0.5; - if(D::dfVecX[l]!=0) area *= 0.5; - if(D::dfVecY[l]!=0) area *= 0.5; - if(D::dfVecZ[l]!=0) area *= 0.5; + if(this->dfVecX[l]!=0) area *= 0.5; + if(this->dfVecY[l]!=0) area *= 0.5; + if(this->dfVecZ[l]!=0) area *= 0.5; mFsgrCellArea[l] = area; } // l @@ -700,35 +979,31 @@ LbmFsgrSolver<D>::initializeSolver() - if(D::cDimension==2) { - if(D::mOutputSurfacePreview) { + if(LBMDIM==2) { + if(this->mOutputSurfacePreview) { errMsg("LbmFsgrSolver::init","No preview in 2D allowed!"); - D::mOutputSurfacePreview = 0; } + this->mOutputSurfacePreview = 0; } } - if(D::mOutputSurfacePreview) { + if(this->mOutputSurfacePreview) { // same as normal one, but use reduced size - mpPreviewSurface = new IsoSurface( D::mIsoValue, false ); + mpPreviewSurface = new IsoSurface( this->mIsoValue ); mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() ); - mpPreviewSurface->setIsolevel( D::mIsoValue ); + mpPreviewSurface->setIsolevel( this->mIsoValue ); // usually dont display for rendering mpPreviewSurface->setVisible( false ); mpPreviewSurface->setStart( vec2G(isostart) ); mpPreviewSurface->setEnd( vec2G(isoend) ); LbmVec pisodist = isoend-isostart; - LbmFloat pfac = D::mPreviewFactor; - mpPreviewSurface->initializeIsosurface( (int)(pfac*D::mSizex)+2, (int)(pfac*D::mSizey)+2, (int)(pfac*D::mSizez)+2, vec2G(pisodist) ); - //mpPreviewSurface->setName( D::getName() + "preview" ); + LbmFloat pfac = this->mPreviewFactor; + mpPreviewSurface->initializeIsosurface( (int)(pfac*this->mSizex)+2, (int)(pfac*this->mSizey)+2, (int)(pfac*this->mSizez)+2, vec2G(pisodist) ); + //mpPreviewSurface->setName( this->getName() + "preview" ); mpPreviewSurface->setName( "preview" ); - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*D::mSizex)<<","<<(pfac*D::mSizey)<<","<<(pfac*D::mSizez)<<" enabled",10); + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*this->mSizex)<<","<<(pfac*this->mSizey)<<","<<(pfac*this->mSizez)<<" enabled",10); } -#if ELBEEM_PLUGIN!=1 - initTestdata(); -#endif // ELBEEM_PLUGIN!=1 - // make sure fill fracs are right for first surface generation stepMain(); @@ -743,73 +1018,454 @@ LbmFsgrSolver<D>::initializeSolver() // now really done... debugOut("LbmFsgrSolver::initialize : Init done ...",10); - D::mInitDone = 1; + this->mInitDone = 1; + +#if LBM_INCLUDE_TESTSOLVERS==1 + initTestdata(); +#endif // ELBEEM_PLUGIN!=1 + return true; } + +/*****************************************************************************/ +//! init moving obstacles for next sim step sim +/*****************************************************************************/ +void LbmFsgrSolver::initMovingObstacles(bool staticInit) { + + myTime_t monstart = getTime(); + // new test + const int level = mMaxRefine; + const int workSet = mLevel[level].setCurr; + LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime! + // for debugging - check targetTime check during DEFAULT STREAM + LbmFloat targetTime = mSimulationTime + this->mpParam->getTimestep(); + if(mLastSimTime == targetTime) { + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"Called for same time! (t="<<mSimulationTime<<" , targett="<<targetTime<<")", 1); + return; + } + //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime,10); + //if(mSimulationTime!=mLastSimTime) errMsg("LbmFsgrSolver::initMovingObstacles","time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime); + + LbmFloat rhomass = 0.0; + CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs! + CellFlagType ntype = CFInvalid; + // WARNING - copied from geo init! + int numobjs = (int)(this->mpGiObjects->size()); + ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; + // 2d display as rectangles + ntlVec3Gfx iniPos(0.0); + if(LBMDIM==2) { + dvec[2] = 1.0; + iniPos = (this->mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ))-(dvec*0.0); + } else { + iniPos = (this->mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0); + //iniPos[2] = this->mvGeoStart[2] + dvec[2]*getForZMin1(); + } + + // stats + int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0; + CellFlagType nbflag[LBM_DFNUM]; + int nbored; + vector<ntlVec3Gfx> vertices; + vector<ntlVec3Gfx> verticesOld; + int i,j,k; // grid pos init + LbmFloat ux,uy,uz, rho; + for(int OId=0; OId<numobjs; OId++) { + ntlGeometryObject *obj = (*this->mpGiObjects)[OId]; + if( (!staticInit) && (!obj->getIsAnimated()) ) continue; + if( ( staticInit) && ( obj->getIsAnimated()) ) continue; + + if(obj->getGeoInitType()&FGI_ALLBOUNDS) { + + otype = ntype = CFInvalid; + switch(obj->getGeoInitType()) { + case FGI_BNDPART: + case FGI_BNDFREE: + errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() ); + case FGI_BNDNO: + rhomass = BND_FILL; + otype = ntype = CFBnd|CFBndNoslip; + break; + case FGI_MBNDINFLOW: + otype = ntype = CFMbndInflow; + break; + case FGI_MBNDOUTFLOW: + otype = ntype = CFMbndOutflow; + break; + } + int wasActive = ((obj->getGeoActive(sourceTime)>0.)? 1:0); + int active = ((obj->getGeoActive(targetTime)>0.)? 1:0); + //errMsg("GEOACTT"," obj "<<obj->getName()<<" a:"<<active<<","<<wasActive<<" s"<<sourceTime<<" t"<<targetTime <<" v"<<mObjectSpeeds[OId] ); + // skip inactive in/out flows + if((!active) && (otype&(CFMbndOutflow|CFMbndInflow)) ) continue; + + // copied from recalculateObjectSpeeds + mObjectSpeeds[OId] = vec2L(this->mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ))); + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*this->mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 ); + + vertices.clear(); + obj->getMovingPoints(vertices); + verticesOld = vertices; + // WARNING - assumes mSimulationTime is global!? + obj->applyTransformation(targetTime, &vertices,NULL, 0, vertices.size(), false ); + monTrafo += vertices.size(); + + // correct flags from last position, but extrapolate + // velocity to next timestep + obj->applyTransformation(sourceTime, &verticesOld,NULL, 0, verticesOld.size(), false ); + monTrafo += verticesOld.size(); + + // object types + if(ntype&CFBnd){ + + // check if object is moving at all + if(obj->getIsAnimated()) { + ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime); + // FIXME? + if(normNoSqrt(objMaxVel)>0.0) { ntype |= CFBndMoving; } + // get old type - CHECK FIXME , timestep could have changed - cause trouble? + ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - this->mpParam->getTimestep(),sourceTime); + if(normNoSqrt(oldobjMaxVel)>0.0) { otype |= CFBndMoving; } + } + +#if LBMDIM==2 +#define CHECKIJK \ + if(i<=0) continue; \ + if(j<=0) continue; \ + if(i>=mLevel[level].lSizex-2) continue; \ + if(j>=mLevel[level].lSizey-2) continue; +#define POS2GRID(vec,n) \ + monTotal++;\ + i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ + j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ + k=0; +#else // LBMDIM -> 3 +#define CHECKIJK \ + if(i<=0) continue; \ + if(j<=0) continue; \ + if(k<=0) continue; \ + if(i>=mLevel[level].lSizex-2) continue; \ + if(j>=mLevel[level].lSizey-2) continue; \ + if(k>=mLevel[level].lSizez-2) continue; +#define POS2GRID(vec,n) \ + monTotal++;\ + i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ + j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ + k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); +#endif // LBMDIM + + // first pass - set new obs. cells + if(active) { + for(size_t n=0; n<vertices.size(); n++) { + //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK); + POS2GRID(vertices,n); + CHECKIJK; + //if(i==30 && j==14) { errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<" "); } + if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue; + monPoints++; + LbmVec u= vec2L((vertices[n]-verticesOld[n]) /dvec); // * timeFac; + RFLAG(level, i,j,k, workSet) = ntype; + FORDF1 { + CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l); + if(flag&(CFFluid|CFInter)) { + flag &= (~CFNoBndFluid); // remove CFNoBndFluid flag + RFLAG_NB(level, i,j,k,workSet,l) &= flag; + } + } + LbmFloat *dstCell = RACPNT(level, i,j,k,workSet); + RAC(dstCell,0) = 0.0; + if(ntype&CFBndMoving) { + //if(i==30 && j==14) { errMsg("AAABB","OId"<<OId<<" move "<<u); } + // movement? + FORDF1 { + // TODO optimize, test rho calc necessary? + // calculate destination density + LbmFloat *dfs = &QCELL_NB(level, i,j,k,workSet,l,dC); + rho = RAC(dfs,dC); + for(int nl=0; nl<this->cDfNum; nl++) rho += RAC(dfs,nl); + //rho = 1.0; + const LbmFloat factor = 2.0*this->dfLength[l]*rho* 3.0; + ux = this->dfDvecX[l]*u[0]; + uy = this->dfDvecY[l]*u[1]; + uz = this->dfDvecZ[l]*u[2]; + const LbmFloat usqr = (ux*ux+uy*uy+uz*uz)*1.5; + USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); + //ux=uy=uz=0.0; // DEBUG + RAC(dstCell,l) = factor*(ux+uy+uz); + } + } else { + FORDF1 { RAC(dstCell,l) = 0.0; } + } + //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" u"<<u<<" ul"<<PRINT_VEC(ux,uy,uz) ); + RAC(dstCell, dFlux) = targetTime; + monObsts++; + } } // bnd, is active? + + // second pass, remove old ones + if(wasActive) { + for(size_t n=0; n<verticesOld.size(); n++) { + POS2GRID(verticesOld,n); + CHECKIJK; + monPoints++; + if((RFLAG(level, i,j,k, workSet) == otype) && + (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) { + //? unused ntlVec3Gfx u= (vertices[n]-verticesOld[n]); + // from mainloop + nbored = 0; +#if OPT3D==0 + FORDF1 { + nbflag[l] = RFLAG_NB(level, i,j,k,workSet,l); + nbored |= nbflag[l]; + } +#else + const CellFlagType *pFlagCheck = &RFLAG(level, i,j,k,workSet); // omp + nbflag[dSB] = *(pFlagCheck + (-mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= nbflag[dSB]; + nbflag[dWB] = *(pFlagCheck + (-mLevel[level].lOffsy+-1)); nbored |= nbflag[dWB]; + nbflag[ dB] = *(pFlagCheck + (-mLevel[level].lOffsy)); nbored |= nbflag[dB]; + nbflag[dEB] = *(pFlagCheck + (-mLevel[level].lOffsy+ 1)); nbored |= nbflag[dEB]; + nbflag[dNB] = *(pFlagCheck + (-mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= nbflag[dNB]; + + nbflag[dSW] = *(pFlagCheck + (-mLevel[level].lOffsx+-1)); nbored |= nbflag[dSW]; + nbflag[ dS] = *(pFlagCheck + (-mLevel[level].lOffsx)); nbored |= nbflag[dS]; + nbflag[dSE] = *(pFlagCheck + (-mLevel[level].lOffsx+ 1)); nbored |= nbflag[dSE]; + + nbflag[ dW] = *(pFlagCheck + (-1)); nbored |= nbflag[dW]; + nbflag[ dE] = *(pFlagCheck + ( 1)); nbored |= nbflag[dE]; + + nbflag[dNW] = *(pFlagCheck + ( mLevel[level].lOffsx+-1)); nbored |= nbflag[dNW]; + nbflag[ dN] = *(pFlagCheck + ( mLevel[level].lOffsx)); nbored |= nbflag[dN]; + nbflag[dNE] = *(pFlagCheck + ( mLevel[level].lOffsx+ 1)); nbored |= nbflag[dNE]; + + nbflag[dST] = *(pFlagCheck + ( mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= nbflag[dST]; + nbflag[dWT] = *(pFlagCheck + ( mLevel[level].lOffsy+-1)); nbored |= nbflag[dWT]; + nbflag[ dT] = *(pFlagCheck + ( mLevel[level].lOffsy)); nbored |= nbflag[dT]; + nbflag[dET] = *(pFlagCheck + ( mLevel[level].lOffsy+ 1)); nbored |= nbflag[dET]; + nbflag[dNT] = *(pFlagCheck + ( mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= nbflag[dNT]; + // */ +#endif + CellFlagType settype = CFInvalid; + LbmFloat avgrho=0.0, avgux=0.0, avguy=0.0, avguz=0.0; + if(nbored&CFFluid) { + if(nbored&CFInter) { + settype = CFInter|CFNoInterpolSrc; rhomass = 0.001; + interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); + } else { + // ? dangerous...? settype = CFFluid|CFNoInterpolSrc; rhomass = 1.0; + settype = CFInter|CFNoInterpolSrc; rhomass = 1.0; + interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); + } + } else { + settype = CFEmpty; rhomass = 0.0; + } + //settype = CFBnd|CFBndNoslip; rhomass = 0.0; + //avgux=avguy=avguz=0.0; avgrho=1.0; + LbmVec speed(avgux,avguy,avguz); + initVelocityCell(level, i,j,k, settype, avgrho, rhomass, speed ); + monFluids++; + } // flag & simtime + } + } } // bnd, active + + else if(ntype&CFMbndInflow){ + // inflow pass - add new fluid cells + // this is slightly different for standing inflows, + // as the fluid is forced to the desired velocity inside as + // well... + const LbmFloat iniRho = 1.0; + const LbmVec vel(mObjectSpeeds[OId]); + const LbmFloat usqr = (vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])*1.5; + USQRMAXCHECK(usqr,vel[0],vel[1],vel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); + errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<vertices.size() ); + + for(size_t n=0; n<vertices.size(); n++) { + POS2GRID(vertices,n); + CHECKIJK; + // TODO - also reinit interface cells !? + if(RFLAG(level, i,j,k, workSet)!=CFEmpty) { + // test prevent particle gen for inflow inter cells + if(RFLAG(level, i,j,k, workSet)&(CFInter)) { RFLAG(level, i,j,k, workSet) &= (~CFNoBndFluid); } // remove CFNoBndFluid flag + continue; } + monFluids++; + + // TODO add OPT3D treatment + LbmFloat *tcel = RACPNT(level, i,j,k,workSet); + FORDF0 { RAC(tcel, l) = this->getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } + RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; + RAC(tcel, dFlux) = FLUX_INIT; + CellFlagType setFlag = CFInter; + changeFlag(level, i,j,k, workSet, setFlag); + mInitialMass += iniRho; + } + // second static init pass + if(staticInit) { + CellFlagType set2Flag = CFMbndInflow|(OId<<24); + for(size_t n=0; n<vertices.size(); n++) { + POS2GRID(vertices,n); + CHECKIJK; + if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } + if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { + changeFlag(level, i,j,k, workSet, set2Flag); + } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { + changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); + } + } + } // second static inflow pass + + } // inflow + + //else if(ntype&CFMbndOutflow){ + else if(ntype&CFMbndOutflow){ + const LbmFloat iniRho = 0.0; + for(size_t n=0; n<vertices.size(); n++) { + POS2GRID(vertices,n); + CHECKIJK; + // FIXME check fluid/inter cells for non-static!? + if(!(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter))) { + if((staticInit)&&(RFLAG(level, i,j,k, workSet)==CFEmpty)) { + changeFlag(level, i,j,k, workSet, CFMbndOutflow); } + continue; + } + monFluids++; + // interface cell - might be double empty? FIXME check? + + // remove fluid cells, shouldnt be here anyway + LbmFloat *tcel = RACPNT(level, i,j,k,workSet); + LbmFloat fluidRho = RAC(tcel,0); FORDF1 { fluidRho += RAC(tcel,l); } + mInitialMass -= fluidRho; + RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; + RAC(tcel, dFlux) = FLUX_INIT; + CellFlagType setFlag = CFInter; + changeFlag(level, i,j,k, workSet, setFlag); + + // same as ifemptied for if below + LbmPoint emptyp; + emptyp.x = i; emptyp.y = j; emptyp.z = k; + mListEmpty.push_back( emptyp ); + //calcCellsEmptied++; + } // points + // second static init pass + if(staticInit) { + CellFlagType set2Flag = CFMbndOutflow|(OId<<24); + for(size_t n=0; n<vertices.size(); n++) { + POS2GRID(vertices,n); + CHECKIJK; + if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } + if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { + changeFlag(level, i,j,k, workSet, set2Flag); + } else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { + changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); + } + } + } // second static outflow pass + } // outflow + } + //vector<ntlGeometryObject*> *mpGiObjects; + //Obj->getGeoInitType() ){ + } + + + /* { // DEBUG check + int workSet = mLevel[level].setCurr; + FSGR_FORIJK1(level) { + if( (RFLAG(level,i,j,k, workSet) & CFBndMoving) ) { + if(QCELL(level, i,j,k, workSet, dFlux)!=targetTime) { + errMsg("lastt"," old val!? at "<<PRINT_IJK<<" t="<<QCELL(level, i,j,k, workSet, dFlux)<<" target="<<targetTime); + } + } + } + } // DEBUG */ + +#undef CHECKIJK +#undef POS2GRID + myTime_t monend = getTime(); + errMsg("LbmFsgrSolver::initMovingObstacles","Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart)); + mLastSimTime = targetTime; +} + + /*****************************************************************************/ /*! perform geometry init (if switched on) */ /*****************************************************************************/ extern int globGeoInitDebug; //solver_interface -template<class D> -bool -LbmFsgrSolver<D>::initGeometryFlags() { +bool LbmFsgrSolver::initGeometryFlags() { int level = mMaxRefine; myTime_t geotimestart = getTime(); ntlGeometryObject *pObj; // getCellSize (due to forced cubes, use x values) - ntlVec3Gfx dvec( (D::mvGeoEnd[0]-D::mvGeoStart[0])/ ((LbmFloat)D::mSizex*2.0)); - bool thinHit = false; + //ntlVec3Gfx dvec; //( (this->mvGeoEnd[0]-this->mvGeoStart[0])/ ((LbmFloat)this->mSizex*2.0)); + //bool thinHit = false; // real cell size from now on... - dvec *= 2.0; - ntlVec3Gfx nodesize = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; - dvec = nodesize; - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< D::mGeoInitId <<") v"<<dvec,3); + //dvec *= 2.0; + //ntlVec3Gfx nodesize = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; + //dvec = nodesize; + ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< this->mGeoInitId <<") v"<<dvec,3); + // WARNING - copied to movobj init! /* init object velocities, this has always to be called for init */ - D::initGeoTree(D::mGeoInitId); - if(D::mAllfluid) { - D::freeGeoTree(); + this->initGeoTree(this->mGeoInitId); + if(this->mAllfluid) { + this->freeGeoTree(); return true; } - ntlVec3Gfx maxIniVel = vec2G( D::mpParam->calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); - D::mpParam->setSimulationMaxSpeed( norm(maxIniVel) + norm(mLevel[level].gravity) ); - LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxIniVel <<", allowed Max="<<allowMax ,5); - if(D::mpParam->getSimulationMaxSpeed() > allowMax) { + // make sure moving obstacles are inited correctly + // preinit moving obj points + int numobjs = (int)(this->mpGiObjects->size()); + for(int o=0; o<numobjs; o++) { + ntlGeometryObject *obj = (*this->mpGiObjects)[o]; + if( + ((obj->getGeoInitType()&FGI_ALLBOUNDS) && (obj->getIsAnimated())) || + (obj->getOnlyThinInit()) ) { + obj->initMovingPoints(mLevel[mMaxRefine].nodeSize); + } + } + + // max speed init + ntlVec3Gfx maxMovobjVelRw = this->getGeoMaxMovementVelocity( mSimulationTime, this->mpParam->getTimestep() ); + ntlVec3Gfx maxMovobjVel = vec2G( this->mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) ); + this->mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) ); + LbmFloat allowMax = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxMovobjVel <<" from mov. obj.="<<maxMovobjVelRw<<" , allowed Max="<<allowMax ,5); + if(this->mpParam->getSimulationMaxSpeed() > allowMax) { // similar to adaptTimestep(); - LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed(); - LbmFloat newdt = D::mpParam->getStepTime() * (allowMax / nextmax); // newtr - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< D::mpParam->getStepTime() <<" ",5); - D::mpParam->setDesiredStepTime( newdt ); - D::mpParam->calculateAllMissingValues( D::mSilent ); - maxIniVel = vec2G( D::mpParam->calculateLattVelocityFromRw( vec2P(D::getGeoMaxInitialVelocity()) )); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxIniVel,5); + LbmFloat nextmax = this->mpParam->getSimulationMaxSpeed(); + LbmFloat newdt = this->mpParam->getTimestep() * (allowMax / nextmax); // newtr + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< this->mpParam->getTimestep() <<" ",5); + this->mpParam->setDesiredTimestep( newdt ); + this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent ); + //maxIniVel = vec2G( this->mpParam->calculateLattVelocityFromRw( vec2P(this->getGeoMaxInitialVelocity()) )); + maxMovobjVel = vec2G( this->mpParam->calculateLattVelocityFromRw( vec2P(this->getGeoMaxMovementVelocity( + mSimulationTime, this->mpParam->getTimestep() )) )); + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxMovobjVel,5); } recalculateObjectSpeeds(); // */ + // init obstacles for first time step (requires obj speeds) + initMovingObstacles(true); + /* set interface cells */ ntlVec3Gfx pos,iniPos; // position of current cell LbmFloat rhomass = 0.0; + CellFlagType ntype = CFInvalid; int savedNodes = 0; int OId = -1; gfxReal distance; // 2d display as rectangles - if(D::cDimension==2) { + if(LBMDIM==2) { dvec[2] = 0.0; - iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ))-(dvec*0.0); - //iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))+dvec; + iniPos =(this->mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ))+(dvec*0.5); } else { - iniPos =(D::mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0); - iniPos[2] = D::mvGeoStart[2] + dvec[2]*getForZMin1(); + iniPos =(this->mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5); } // first init boundary conditions + // invalid cells are set to empty afterwards #define GETPOS(i,j,k) \ ntlVec3Gfx( iniPos[0]+ dvec[0]*(gfxReal)(i), \ iniPos[1]+ dvec[1]*(gfxReal)(j), \ @@ -817,23 +1473,34 @@ LbmFsgrSolver<D>::initGeometryFlags() { for(int k= getForZMin1(); k< getForZMax1(level); ++k) { for(int j=1;j<mLevel[level].lSizey-1;j++) { for(int i=1;i<mLevel[level].lSizex-1;i++) { - CellFlagType ntype = CFInvalid; + ntype = CFInvalid; - if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance)) { - //if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(1.0,0.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[0]*0.5, thinHit, true)) { - pObj = (*D::mpGiObjects)[OId]; + const bool inside = this->geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance); + // = this->geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(1.0,0.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[0]*0.5, thinHit, true); + //if(this->geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance)) { + if(inside) { + pObj = (*this->mpGiObjects)[OId]; switch( pObj->getGeoInitType() ){ case FGI_MBNDINFLOW: - rhomass = 1.0; - ntype = CFFluid|CFMbndInflow; + if(! pObj->getIsAnimated() ) { + rhomass = 1.0; + ntype = CFFluid | CFMbndInflow; + } else { + ntype = CFInvalid; + } break; case FGI_MBNDOUTFLOW: - rhomass = 0.0; - ntype = CFEmpty|CFMbndOutflow; + if(! pObj->getIsAnimated() ) { + rhomass = 0.0; + ntype = CFEmpty|CFMbndOutflow; + } else { + ntype = CFInvalid; + } break; case FGI_BNDNO: rhomass = BND_FILL; - ntype = CFBnd|CFBndNoslip; break; + ntype = CFBnd|CFBndNoslip; + break; case FGI_BNDFREE: rhomass = BND_FILL; ntype = CFBnd|CFBndFreeslip; break; @@ -869,140 +1536,17 @@ LbmFsgrSolver<D>::initGeometryFlags() { } // zmax // */ - /* - for(int k= getForZMin1(); k< getForZMax1(level); ++k) { - for(int i=1;i<mLevel[level].lSizex-1;i++) { - for(int j=1;j<mLevel[level].lSizey-1;j++) { - //errMsg("INIT0","at "<<PRINT_IJK<<" p="<<GETPOS(i,j,k)<<" j"<<j<<" "<<mLevel[level].lSizey); - //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - CellFlagType ntype = CFInvalid; - //errMsg("INIT1","at "<<PRINT_IJK<<" p="<<GETPOS(i,j,k)); - //if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,1.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[1]*0.5)) { - if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,1.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[1]*0.5, thinHit, true)) { - pObj = (*D::mpGiObjects)[OId]; - switch( pObj->getGeoInitType() ){ - case FGI_MBNDINFLOW: - rhomass = 1.0; - ntype = CFFluid|CFMbndInflow; - break; - case FGI_MBNDOUTFLOW: - rhomass = 0.0; - ntype = CFEmpty|CFMbndOutflow; - break; - default: - rhomass = BND_FILL; - ntype = CFBnd; break; - } - } - if(ntype != CFInvalid) { - // initDefaultCell - if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { - ntype |= (OId<<24); - } - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - //errMsg("INITT","at "<<PRINT_IJK<<" t="<<ntype<<" d="<<distance); - - // walk along x until hit for following inits - if(distance<=-1.0) { distance = 100.0; } - if(distance>=0.0) { - gfxReal dcnt=dvec[1]; - while(( dcnt< distance-dvec[1] )&&(j+1<mLevel[level].lSizey-1)) { - dcnt += dvec[1]; j++; - //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - savedNodes++; - if(ntype != CFInvalid) { - // rho,mass,OId are still inited from above - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - } - } - - } - } - } // zmax, j - // */ - - - /* - for(int j=1;j<mLevel[level].lSizey-1;j++) { - for(int i=1;i<mLevel[level].lSizex-1;i++) { - for(int k= getForZMin1(); k< getForZMax1(level); ++k) { - //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - CellFlagType ntype = CFInvalid; - if(D::geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(0.0,0.0,1.0), FGI_ALLBOUNDS, OId, distance, dvec[2]*0.5, thinHit, true)) { - pObj = (*D::mpGiObjects)[OId]; - switch( pObj->getGeoInitType() ){ - case FGI_MBNDINFLOW: - rhomass = 1.0; - ntype = CFFluid|CFMbndInflow; - break; - case FGI_MBNDOUTFLOW: - rhomass = 0.0; - ntype = CFEmpty|CFMbndOutflow; - break; - default: - rhomass = BND_FILL; - ntype = CFBnd; break; - } - } - if(ntype != CFInvalid) { - // initDefaultCell - if((ntype & CFMbndInflow) || (ntype & CFMbndOutflow) ) { - ntype |= (OId<<24); - } - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - errMsg("INITZ","at "<<PRINT_IJK<<" t="<<ntype<<" d="<<distance); - - // walk along x until hit for following inits - if(distance<=-1.0) { distance = 100.0; } - if(distance>=0.0) { - gfxReal dcnt=dvec[2]; - while(( dcnt< distance-dvec[2] )&&(k+1<mLevel[level].lSizez-1)) { - dcnt += dvec[2]; k++; - //if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - savedNodes++; - if(ntype != CFInvalid) { - // rho,mass,OId are still inited from above - initVelocityCell(level, i,j,k, ntype, rhomass, rhomass, mObjectSpeeds[OId] ); - } - } - } // * - - } - } - } // zmax, k - // */ - thinHit = false; - - // now init fluid layer for(int k= getForZMin1(); k< getForZMax1(level); ++k) { for(int j=1;j<mLevel[level].lSizey-1;j++) { for(int i=1;i<mLevel[level].lSizex-1;i++) { if(!(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFEmpty)) continue; - - CellFlagType ntype = CFInvalid; + ntype = CFInvalid; int inits = 0; - // DEBUG - if((j==mLevel[level].lSizey/2)&&(k==getForZMax1(level)*7/10)) globGeoInitDebug=1; - else globGeoInitDebug=0; - //errMsg("AAA","j"<<j<<"|"<<(mLevel[level].lSizey/2)<<" k"<<k<<"|"<<(getForZMax1(level)*7/10)<<" gd"<<globGeoInitDebug); - - if((i==1) && (j==31) && (k==48)) globGeoInitDebug=1; - else globGeoInitDebug=0; - bool inside = D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance); - /*if((i==1) && (j==31) && (inside)) { - globGeoInitDebug=1; - D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance); - globGeoInitDebug=0; - errMsg("III"," i1 at "<<PRINT_IJK); - } // DEBUG */ + //if((i==1) && (j==31) && (k==48)) globGeoInitDebug=1; + //else globGeoInitDebug=0; + const bool inside = this->geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance); if(inside) { - // DEBUG - - //if(D::geoInitCheckPointInside( GETPOS(i,j,k) , FGI_FLUID, OId, distance)) { ntype = CFFluid; } if(ntype != CFInvalid) { @@ -1032,19 +1576,30 @@ LbmFsgrSolver<D>::initGeometryFlags() { } } // zmax - D::freeGeoTree(); + // reset invalid to empty again + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + for(int j=1;j<mLevel[level].lSizey-1;j++) { + for(int i=1;i<mLevel[level].lSizex-1;i++) { + if(RFLAG(level, i,j,k, mLevel[level].setCurr)==CFInvalid) { + RFLAG(level, i,j,k, mLevel[level].setOther) = + RFLAG(level, i,j,k, mLevel[level].setCurr) = CFEmpty; + } + } + } + } + + this->freeGeoTree(); myTime_t geotimeend = getTime(); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< ((geotimeend-geotimestart)/(double)1000.0)<<"s,"<<savedNodes<<") " , 10 ); + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< getTimeString(geotimeend-geotimestart)<<","<<savedNodes<<") " , 10 ); //errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez)); return true; } /*****************************************************************************/ /* init part for all freesurface testcases */ -template<class D> -void -LbmFsgrSolver<D>::initFreeSurfaces() { +void LbmFsgrSolver::initFreeSurfaces() { double interfaceFill = 0.45; // filling level of interface cells + //interfaceFill = 1.0; // DEUG!! GEOMTEST!!!!!!!!!!!! // set interface cells FSGR_FORIJK1(mMaxRefine) { @@ -1093,7 +1648,7 @@ LbmFsgrSolver<D>::initFreeSurfaces() { initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); } } // interface - } + } // */ // another brute force init, make sure the fill values are right... // and make sure both sets are equal @@ -1112,35 +1667,53 @@ LbmFsgrSolver<D>::initFreeSurfaces() { // ---------------------------------------------------------------------- // smoother surface... if(mInitSurfaceSmoothing>0) { - debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing steps ",10); + debMsgStd("Surface Smoothing init", DM_MSG, "Performing "<<(mInitSurfaceSmoothing)<<" smoothing timestep ",10); #if COMPRESSGRIDS==1 - errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return; + //errFatal("NYI","COMPRESSGRIDS mInitSurfaceSmoothing",SIMWORLD_INITERROR); return; #endif // COMPRESSGRIDS==0 } for(int s=0; s<mInitSurfaceSmoothing; s++) { - FSGR_FORIJK1(mMaxRefine) { - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) { + //SGR_FORIJK1(mMaxRefine) { + + int kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); + int lev = mMaxRefine; +#if COMPRESSGRIDS==0 + for(int k=kstart;k<kend;++k) { +#else // COMPRESSGRIDS==0 + int kdir = 1; // COMPRT ON + if(mLevel[lev].setCurr==1) { + kdir = -1; + int temp = kend; + kend = kstart-1; + kstart = temp-1; + } // COMPRT + for(int k=kstart;k!=kend;k+=kdir) { +#endif // COMPRESSGRIDS==0 + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + if( TESTFLAG( RFLAG(lev, i,j,k, mLevel[lev].setCurr), CFInter) ) { LbmFloat mass = 0.0; //LbmFloat nbdiv; - FORDF0 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; - if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFFluid ){ + //FORDF0 { + for(int l=0;(l<this->cDirNum); l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFFluid ){ mass += 1.0; } - if( RFLAG(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr) & CFInter ){ - mass += QCELL(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, dMass); + if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFInter ){ + mass += QCELL(lev, ni,nj,nk, mLevel[lev].setCurr, dMass); } //nbdiv+=1.0; } //errMsg(" I ", PRINT_IJK<<" m"<<mass ); - QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass) = (mass/19.0); - QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dFfrac) = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setOther, dMass); + QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)this->cDirNum) ); + QCELL(lev, i,j,k, mLevel[lev].setOther, dFfrac) = QCELL(lev, i,j,k, mLevel[lev].setOther, dMass); } - } + }}} - mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; - mLevel[mMaxRefine].setCurr ^= 1; + mLevel[lev].setOther = mLevel[lev].setCurr; + mLevel[lev].setCurr ^= 1; } // copy back...? @@ -1148,9 +1721,7 @@ LbmFsgrSolver<D>::initFreeSurfaces() { /*****************************************************************************/ /* init part for all freesurface testcases */ -template<class D> -void -LbmFsgrSolver<D>::initStandingFluidGradient() { +void LbmFsgrSolver::initStandingFluidGradient() { // ---------------------------------------------------------------------- // standing fluid preinit const int debugStandingPreinit = 0; @@ -1203,7 +1774,8 @@ LbmFsgrSolver<D>::initStandingFluidGradient() { GRAVLOOP { int i = gravIndex[0], j = gravIndex[1], k = gravIndex[2]; if( ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFInter)) ) || - ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ){ + ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFBndMoving)) ) || + ( (RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) & (CFEmpty)) ) ) { int fluidHeight = (ABS(gravIndex[maxGravComp] - gravIMin[maxGravComp])); if(debugStandingPreinit) errMsg("Standing fp","fh="<<fluidHeight<<" gmax="<<gravIMax[maxGravComp]<<" gi="<<gravIndex[maxGravComp] ); if(fluidHeight>1) { @@ -1217,8 +1789,8 @@ LbmFsgrSolver<D>::initStandingFluidGradient() { LbmFloat fluidHeight; fluidHeight = (LbmFloat)(ABS(gravIMax[maxGravComp]-gravIMin[maxGravComp])); -#if ELBEEM_PLUGIN!=1 - mpTest->mFluidHeight = (int)fluidHeight; +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) mpTest->mFluidHeight = (int)fluidHeight; #endif // ELBEEM_PLUGIN!=1 if(debugStandingPreinit) debMsgStd("Standing fluid preinit", DM_MSG, "fheight="<<fluidHeight<<" min="<<PRINT_VEC(gravIMin[0],gravIMin[1], gravIMin[2])<<" max="<<PRINT_VEC(gravIMax[0], gravIMax[1],gravIMax[2])<< " mgc="<<maxGravComp<<" mc1="<<gravComp1<<" mc2="<<gravComp2<<" dir="<<gravDir[maxGravComp]<<" have="<<haveStandingFluid ,10); @@ -1286,10 +1858,22 @@ LbmFsgrSolver<D>::initStandingFluidGradient() { debMsgStd("Standing fluid preinit", DM_MSG, "Density gradient inited (max-rho:"<< (1.0+ (fluidHeight) * (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega)) <<", h:"<< fluidHeight<<") ", 8); +#if ELBEEM_PLUGIN!=1 && LBMDIM==3 + /*int lowj = 0; + for(int k=1;k<mLevel[lev].lSizez-1;++k) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + LbmFloat rho = 1.0+ (fluidHeight) * (mLevel[lev].gravity[maxGravComp])* (-3.0/1.0)*(mLevel[lev].omega); + RFLAG(lev, i,lowj,k, rhoworkSet^1) = + RFLAG(lev, i,lowj,k, rhoworkSet) = CFFluid; + FORDF0 { QCELL(lev, i,lowj,k, rhoworkSet, l) = this->dfEquil[l]*rho; } + QCELL(lev, i,lowj,k, rhoworkSet, dMass) = rho; + } } // */ +#endif + int preinitSteps = (haveStandingFluid* ((mLevel[lev].lSizey+mLevel[lev].lSizez+mLevel[lev].lSizex)/3) ); preinitSteps = (haveStandingFluid>>2); // not much use...? //preinitSteps = 4; // DEBUG!!!! - //D::mInitDone = 1; // GRAVTEST + //this->mInitDone = 1; // GRAVTEST //preinitSteps = 0; debMsgNnl("Standing fluid preinit", DM_MSG, "Performing "<<preinitSteps<<" prerelaxations ",10); for(int s=0; s<preinitSteps; s++) { @@ -1316,8 +1900,6 @@ LbmFsgrSolver<D>::initStandingFluidGradient() { kstart = temp-1; } // COMPRT for(int k=kstart;k!=kend;k+=kdir) { - - //errMsg("LbmFsgrSolver::mainLoop","k="<<k<<" ks="<<kstart<<" ke="<<kend<<" kdir="<<kdir ); // debug #endif // COMPRESSGRIDS==0 for(int j=0;j<mLevel[lev].lSizey-0;++j) { @@ -1349,20 +1931,18 @@ LbmFsgrSolver<D>::initStandingFluidGradient() { mLevel[lev].setOther = mLevel[lev].setCurr; mLevel[lev].setCurr ^= 1; } - //D::mInitDone = 0; // GRAVTEST + //this->mInitDone = 0; // GRAVTEST // */ myTime_t timeend = getTime(); - debMsgDirect(" done, "<<((timeend-timestart)/(double)1000.0)<<"s \n"); + debMsgDirect(" done, "<<getTimeString(timeend-timestart)<<" \n"); #undef NBFLAG } } -template<class D> -bool -LbmFsgrSolver<D>::checkSymmetry(string idstring) +bool LbmFsgrSolver::checkSymmetry(string idstring) { bool erro = false; bool symm = true; @@ -1388,7 +1968,7 @@ LbmFsgrSolver<D>::checkSymmetry(string idstring) if(lev==mMaxRefine) inb -= 1; // FSGR_SYMM_T if( RFLAG(lev, i,j,k,s) != RFLAG(lev, inb,j,k,s) ) { erro = true; - if(D::cDimension==2) { + if(LBMDIM==2) { if(msgs<maxMsgs) { msgs++; errMsg("EFLAG", PRINT_IJK<<"s"<<s<<" flag "<<RFLAG(lev, i,j,k,s)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" flag "<<RFLAG(lev, inb,j,k,s) ); } @@ -1397,7 +1977,7 @@ LbmFsgrSolver<D>::checkSymmetry(string idstring) symm = false; } if( LBM_FLOATNEQ(QCELL(lev, i,j,k,s, dMass), QCELL(lev, inb,j,k,s, dMass)) ) { erro = true; - if(D::cDimension==2) { + if(LBMDIM==2) { if(msgs<maxMsgs) { msgs++; //debMsgDirect(" mass1 "<<QCELL(lev, i,j,k,s, dMass)<<" mass2 "<<QCELL(lev, inb,j,k,s, dMass) <<std::endl); errMsg("EMASS", PRINT_IJK<<"s"<<s<<" mass "<<QCELL(lev, i,j,k,s, dMass)<<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" mass "<<QCELL(lev, inb,j,k,s, dMass) ); @@ -1412,7 +1992,7 @@ LbmFsgrSolver<D>::checkSymmetry(string idstring) LbmFloat otrho = QCELL(lev, inb,j,k, s, dC); FORDF1 { otrho += QCELL(lev, inb,j,k, s, l); } if( LBM_FLOATNEQ(nbrho, otrho) ) { erro = true; - if(D::cDimension==2) { + if(LBMDIM==2) { if(msgs<maxMsgs) { msgs++; //debMsgDirect(" rho 1 "<<nbrho <<" rho 2 "<<otrho <<std::endl); errMsg("ERHO ", PRINT_IJK<<"s"<<s<<" rho "<<nbrho <<" , at "<<PRINT_VEC(inb,j,k)<<"s"<<s<<" rho "<<otrho ); @@ -1427,7 +2007,7 @@ LbmFsgrSolver<D>::checkSymmetry(string idstring) LbmFloat maxdiv =0.0; if(erro) { errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv ); - //if(D::cDimension==2) D::mPanic = true; + //if(LBMDIM==2) this->mPanic = true; //return false; } else { errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv ); @@ -1436,24 +2016,56 @@ LbmFsgrSolver<D>::checkSymmetry(string idstring) return symm; }// */ -#endif // !defined(__APPLE_CC__) || defined(LBM_FORCEINCLUDE) - - -/****************************************************************************** - * instantiation - *****************************************************************************/ - -#if ((!defined(__APPLE_CC__)) && (!defined(__INTEL_COMPILER))) && (!defined(LBM_FORCEINCLUDE)) -#if LBMDIM==2 -#define LBM_INSTANTIATE LbmBGK2D -#endif // LBMDIM==2 -#if LBMDIM==3 -#define LBM_INSTANTIATE LbmBGK3D -#endif // LBMDIM==3 +void +LbmFsgrSolver::interpolateCellValues( + int level,int ei,int ej,int ek,int workSet, + LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz) +{ + LbmFloat avgrho = 0.0; + LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; + LbmFloat cellcnt = 0.0; + LbmFloat avgnbdf[LBM_DFNUM]; + FORDF0M { avgnbdf[m]= 0.0; } + + for(int nbl=1; nbl< this->cDfNum ; ++nbl) { + if( (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFFluid) || + ((!(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) && + (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFInter) )) { + cellcnt += 1.0; + for(int rl=0; rl< this->cDfNum ; ++rl) { + LbmFloat nbdf = QCELL_NB(level,ei,ej,ek, workSet,nbl, rl); + avgnbdf[rl] += nbdf; + avgux += (this->dfDvecX[rl]*nbdf); + avguy += (this->dfDvecY[rl]*nbdf); + avguz += (this->dfDvecZ[rl]*nbdf); + avgrho += nbdf; + } + } + } -template class LbmFsgrSolver< LBM_INSTANTIATE >; + if(cellcnt<=0.0) { + // no nbs? just use eq. + //FORDF0 { QCELL(level,ei,ej,ek, workSet, l) = this->dfEquil[l]; } + avgrho = 1.0; + avgux = avguy = avguz = 0.0; + //TTT mNumProblems++; +#if ELBEEM_PLUGIN!=1 + //this->mPanic=1; + // this can happen for worst case moving obj scenarios... + errMsg("LbmFsgrSolver::interpolateCellValues","Cellcnt<=0.0 at "<<PRINT_VEC(ei,ej,ek)); //,SIMWORLD_GENERICERROR); +#endif // ELBEEM_PLUGIN + } else { + // init speed + avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; + avgrho /= cellcnt; + FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? + } -#endif // __APPLE_CC__ __INTEL_COMPILER + retrho = avgrho; + retux = avgux; + retuy = avguy; + retuz = avguz; +} // interpolateCellValues diff --git a/intern/elbeem/intern/solver_interface.cpp b/intern/elbeem/intern/solver_interface.cpp index 1de27d4beec..04e0456286b 100644 --- a/intern/elbeem/intern/solver_interface.cpp +++ b/intern/elbeem/intern/solver_interface.cpp @@ -12,284 +12,11 @@ /* LBM Files */ #include "solver_interface.h" -#include "ntl_scene.h" #include "ntl_ray.h" +#include "ntl_world.h" #include "elbeem.h" -/*****************************************************************************/ -//! common variables - -/*****************************************************************************/ -/*! class for solver templating - 3D implementation D3Q19 */ - - //! how many dimensions? - const int LbmD3Q19::cDimension = 3; - - // Wi factors for collide step - const LbmFloat LbmD3Q19::cCollenZero = (1.0/3.0); - const LbmFloat LbmD3Q19::cCollenOne = (1.0/18.0); - const LbmFloat LbmD3Q19::cCollenSqrtTwo = (1.0/36.0); - - //! threshold value for filled/emptied cells - const LbmFloat LbmD3Q19::cMagicNr2 = 1.0005; - const LbmFloat LbmD3Q19::cMagicNr2Neg = -0.0005; - const LbmFloat LbmD3Q19::cMagicNr = 1.010001; - const LbmFloat LbmD3Q19::cMagicNrNeg = -0.010001; - - //! size of a single set of distribution functions - const int LbmD3Q19::cDfNum = 19; - //! direction vector contain vecs for all spatial dirs, even if not used for LBM model - const int LbmD3Q19::cDirNum = 27; - - //const string LbmD3Q19::dfString[ cDfNum ] = { - const char* LbmD3Q19::dfString[ cDfNum ] = { - " C", " N"," S"," E"," W"," T"," B", - "NE","NW","SE","SW", - "NT","NB","ST","SB", - "ET","EB","WT","WB" - }; - - const int LbmD3Q19::dfNorm[ cDfNum ] = { - cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB, - cDirNE, cDirNW, cDirSE, cDirSW, - cDirNT, cDirNB, cDirST, cDirSB, - cDirET, cDirEB, cDirWT, cDirWB - }; - - const int LbmD3Q19::dfInv[ cDfNum ] = { - cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT, - cDirSW, cDirSE, cDirNW, cDirNE, - cDirSB, cDirST, cDirNB, cDirNT, - cDirWB, cDirWT, cDirEB, cDirET - }; - - const int LbmD3Q19::dfRefX[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - cDirSE, cDirSW, cDirNE, cDirNW, - 0, 0, 0, 0, - cDirEB, cDirET, cDirWB, cDirWT - }; - - const int LbmD3Q19::dfRefY[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - cDirNW, cDirNE, cDirSW, cDirSE, - cDirNB, cDirNT, cDirSB, cDirST, - 0, 0, 0, 0 - }; - - const int LbmD3Q19::dfRefZ[ cDfNum ] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - cDirST, cDirSB, cDirNT, cDirNB, - cDirWT, cDirWB, cDirET, cDirEB - }; - - // Vector Order 3D: - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 - // 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 - // 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 - // 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 - - const int LbmD3Q19::dfVecX[ cDirNum ] = { - 0, 0,0, 1,-1, 0,0, - 1,-1,1,-1, - 0,0,0,0, - 1,1,-1,-1, - 1,-1, 1,-1, - 1,-1, 1,-1, - }; - const int LbmD3Q19::dfVecY[ cDirNum ] = { - 0, 1,-1, 0,0,0,0, - 1,1,-1,-1, - 1,1,-1,-1, - 0,0,0,0, - 1, 1,-1,-1, - 1, 1,-1,-1 - }; - const int LbmD3Q19::dfVecZ[ cDirNum ] = { - 0, 0,0,0,0,1,-1, - 0,0,0,0, - 1,-1,1,-1, - 1,-1,1,-1, - 1, 1, 1, 1, - -1,-1,-1,-1 - }; - - const LbmFloat LbmD3Q19::dfDvecX[ cDirNum ] = { - 0, 0,0, 1,-1, 0,0, - 1,-1,1,-1, - 0,0,0,0, - 1,1,-1,-1, - 1,-1, 1,-1, - 1,-1, 1,-1 - }; - const LbmFloat LbmD3Q19::dfDvecY[ cDirNum ] = { - 0, 1,-1, 0,0,0,0, - 1,1,-1,-1, - 1,1,-1,-1, - 0,0,0,0, - 1, 1,-1,-1, - 1, 1,-1,-1 - }; - const LbmFloat LbmD3Q19::dfDvecZ[ cDirNum ] = { - 0, 0,0,0,0,1,-1, - 0,0,0,0, - 1,-1,1,-1, - 1,-1,1,-1, - 1, 1, 1, 1, - -1,-1,-1,-1 - }; - - /* principal directions */ - const int LbmD3Q19::princDirX[ 2*LbmD3Q19::cDimension ] = { - 1,-1, 0,0, 0,0 - }; - const int LbmD3Q19::princDirY[ 2*LbmD3Q19::cDimension ] = { - 0,0, 1,-1, 0,0 - }; - const int LbmD3Q19::princDirZ[ 2*LbmD3Q19::cDimension ] = { - 0,0, 0,0, 1,-1 - }; - - /*! arrays for les model coefficients, inited in lbmsolver constructor */ - LbmFloat LbmD3Q19::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; - LbmFloat LbmD3Q19::lesCoeffOffdiag[ cDimension ][ cDirNum ]; - - - const LbmFloat LbmD3Q19::dfLength[ cDfNum ]= { - cCollenZero, - cCollenOne, cCollenOne, cCollenOne, - cCollenOne, cCollenOne, cCollenOne, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo - }; - - /* precalculated equilibrium dfs, inited in lbmsolver constructor */ - LbmFloat LbmD3Q19::dfEquil[ cDfNum ]; - -// D3Q19 end - - - -/*****************************************************************************/ -/*! class for solver templating - 2D implementation D2Q9 */ - - //! how many dimensions? - const int LbmD2Q9::cDimension = 2; - - //! Wi factors for collide step - const LbmFloat LbmD2Q9::cCollenZero = (4.0/9.0); - const LbmFloat LbmD2Q9::cCollenOne = (1.0/9.0); - const LbmFloat LbmD2Q9::cCollenSqrtTwo = (1.0/36.0); - - //! threshold value for filled/emptied cells - const LbmFloat LbmD2Q9::cMagicNr2 = 1.0005; - const LbmFloat LbmD2Q9::cMagicNr2Neg = -0.0005; - const LbmFloat LbmD2Q9::cMagicNr = 1.010001; - const LbmFloat LbmD2Q9::cMagicNrNeg = -0.010001; - - //! size of a single set of distribution functions - const int LbmD2Q9::cDfNum = 9; - const int LbmD2Q9::cDirNum = 9; - - //const string LbmD2Q9::dfString[ cDfNum ] = { - const char* LbmD2Q9::dfString[ cDfNum ] = { - " C", - " N", " S", " E", " W", - "NE", "NW", "SE","SW" - }; - - const int LbmD2Q9::dfNorm[ cDfNum ] = { - cDirC, - cDirN, cDirS, cDirE, cDirW, - cDirNE, cDirNW, cDirSE, cDirSW - }; - - const int LbmD2Q9::dfInv[ cDfNum ] = { - cDirC, - cDirS, cDirN, cDirW, cDirE, - cDirSW, cDirSE, cDirNW, cDirNE - }; - - const int LbmD2Q9::dfRefX[ cDfNum ] = { - 0, - 0, 0, 0, 0, - cDirSE, cDirSW, cDirNE, cDirNW - }; - - const int LbmD2Q9::dfRefY[ cDfNum ] = { - 0, - 0, 0, 0, 0, - cDirNW, cDirNE, cDirSW, cDirSE - }; - - const int LbmD2Q9::dfRefZ[ cDfNum ] = { - 0, 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - // Vector Order 2D: - // 0 1 2 3 4 5 6 7 8 - // 0, 0,0, 1,-1, 1,-1,1,-1 - // 0, 1,-1, 0,0, 1,1,-1,-1 - - const int LbmD2Q9::dfVecX[ cDirNum ] = { - 0, - 0,0, 1,-1, - 1,-1,1,-1 - }; - const int LbmD2Q9::dfVecY[ cDirNum ] = { - 0, - 1,-1, 0,0, - 1,1,-1,-1 - }; - const int LbmD2Q9::dfVecZ[ cDirNum ] = { - 0, 0,0,0,0, 0,0,0,0 - }; - - const LbmFloat LbmD2Q9::dfDvecX[ cDirNum ] = { - 0, - 0,0, 1,-1, - 1,-1,1,-1 - }; - const LbmFloat LbmD2Q9::dfDvecY[ cDirNum ] = { - 0, - 1,-1, 0,0, - 1,1,-1,-1 - }; - const LbmFloat LbmD2Q9::dfDvecZ[ cDirNum ] = { - 0, 0,0,0,0, 0,0,0,0 - }; - - const int LbmD2Q9::princDirX[ 2*LbmD2Q9::cDimension ] = { - 1,-1, 0,0 - }; - const int LbmD2Q9::princDirY[ 2*LbmD2Q9::cDimension ] = { - 0,0, 1,-1 - }; - const int LbmD2Q9::princDirZ[ 2*LbmD2Q9::cDimension ] = { - 0,0, 0,0 - }; - - - /*! arrays for les model coefficients, inited in lbmsolver constructor */ - LbmFloat LbmD2Q9::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ]; - LbmFloat LbmD2Q9::lesCoeffOffdiag[ cDimension ][ cDirNum ]; - - - const LbmFloat LbmD2Q9::dfLength[ cDfNum ]= { - cCollenZero, - cCollenOne, cCollenOne, cCollenOne, cCollenOne, - cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo - }; - - /* precalculated equilibrium dfs, inited in lbmsolver constructor */ - LbmFloat LbmD2Q9::dfEquil[ cDfNum ]; - -// D2Q9 end - /****************************************************************************** @@ -308,9 +35,9 @@ LbmSolverInterface::LbmSolverInterface() : mInitDone( false ), mInitDensityGradient( false ), mpAttrs( NULL ), mpParam( NULL ), - mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0), + mNumParticlesLost(0), + mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0), mDebugVelScale( 0.01 ), mNodeInfoString("+"), - mRandom( 5123 ), mvGeoStart(-1.0), mvGeoEnd(1.0), mAccurateGeoinit(0), mName("lbm_default") , @@ -321,10 +48,14 @@ LbmSolverInterface::LbmSolverInterface() : mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL ), mRefinementDesired(0), mOutputSurfacePreview(0), mPreviewFactor(0.25), - mSmoothSurface(0.0), mSmoothNormals(0.0), - mMarkedCells(), mMarkedCellIndex(0) + mSmoothSurface(1.0), mSmoothNormals(1.0), + mPartGenProb(0.), + mDumpVelocities(false), + mMarkedCells(), mMarkedCellIndex(0), + mDomainBound("noslip"), mDomainPartSlipValue(0.1), + mTForceStrength(0.0) { -#if ELBEEM_BLENDER==1 +#if ELBEEM_PLUGIN==1 if(gDebugLevel<=1) mSilent = true; #endif } @@ -341,7 +72,7 @@ void initGridSizes(int &sizex, int &sizey, int &sizez, int mMaxRefine, bool parallel) { // fix size inits to force cubic cells and mult4 level dimensions - const int debugGridsizeInit = 1; + const int debugGridsizeInit = 0; if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Called - size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" " ,10); int maxGridSize = sizex; // get max size @@ -383,6 +114,10 @@ void initGridSizes(int &sizex, int &sizey, int &sizez, void calculateMemreqEstimate( int resx,int resy,int resz, int refine, double *reqret, string *reqstr) { + // debug estimation? + const bool debugMemEst = false; + // COMPRESSGRIDS define is not available here, make sure it matches + const bool useGridComp = true; // make sure we can handle bid numbers here... all double double memCnt = 0.0; double ddTotalNum = (double)dTotalNum; @@ -392,12 +127,15 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine, double currResz = (double)resz; double rcellSize = ((currResx*currResy*currResz) *ddTotalNum); memCnt += (double)(sizeof(CellFlagType) * (rcellSize/ddTotalNum +4.0) *2.0); -#if COMPRESSGRIDS==0 - memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0); -#else // COMPRESSGRIDS==0 - double compressOffset = (double)(currResx*currResy*ddTotalNum*2.0); - memCnt += (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0)); -#endif // COMPRESSGRIDS==0 + if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"res:"<<PRINT_VEC(currResx,currResy,currResz)<<" rcellSize:"<<rcellSize<<" mc:"<<memCnt, 10); + if(!useGridComp) { + memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0); + if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," no-comp, mc:"<<memCnt, 10); + } else { + double compressOffset = (double)(currResx*currResy*ddTotalNum*2.0); + memCnt += (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0)); + if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," w-comp, mc:"<<memCnt, 10); + } for(int i=refine-1; i>=0; i--) { currResx /= 2.0; currResy /= 2.0; @@ -405,10 +143,12 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine, rcellSize = ((currResz*currResy*currResx) *ddTotalNum); memCnt += (double)(sizeof(CellFlagType) * (rcellSize/ddTotalNum +4.0) *2.0); memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0); + if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"refine "<<i<<", mc:"<<memCnt, 10); } // isosurface memory memCnt += (double)( (3*sizeof(int)+sizeof(float)) * ((resx+2)*(resy+2)*(resz+2)) ); + if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"iso, mc:"<<memCnt, 10); double memd = memCnt; char *sizeStr = ""; @@ -453,7 +193,7 @@ CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultVal return (CellFlagType)( CFFluid ); } errMsg("LbmSolverInterface::readBoundaryFlagInt","Invalid value '"<<val<<"' " ); -# if LBM_STRICT_DEBUG==1 +# if FSGR_STRICT_DEBUG==1 errFatal("readBoundaryFlagInt","Strict abort..."<<val, SIMWORLD_INITERROR); # endif return defaultValue; @@ -480,7 +220,9 @@ void LbmSolverInterface::parseStdAttrList() { mSizex = (int)sizeVec[0]; mSizey = (int)sizeVec[1]; mSizez = (int)sizeVec[2]; - mpParam->setSize(mSizex, mSizey, mSizez ); // param needs size in any case + // param needs size in any case + // test solvers might not have mpPara, though + if(mpParam) mpParam->setSize(mSizex, mSizey, mSizez ); mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmSolverInterface", "mInitDensityGradient", false); mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); @@ -488,6 +230,20 @@ void LbmSolverInterface::parseStdAttrList() { mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmSolverInterface", "mDebugVelScale", false); mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false ); + + mDumpVelocities = mpAttrs->readBool("dump_velocities", mDumpVelocities, "SimulationLbm","mDumpVelocities", false ); + if(getenv("ELBEEM_DUMPVELOCITIES")) { + int get = atoi(getenv("ELBEEM_DUMPVELOCITIES")); + if((get==0)||(get==1)) { + mDumpVelocities = get; + debMsgStd("LbmSolverInterface::parseAttrList",DM_NOTIFY,"Using envvar ELBEEM_DUMPVELOCITIES to set mDumpVelocities to "<<get<<","<<mDumpVelocities,8); + } + } + + // new test vars + mTForceStrength = mpAttrs->readFloat("tforcestrength", mTForceStrength,"LbmSolverInterface", "mTForceStrength", false); + + mPartGenProb = mpAttrs->readFloat("partgenprob", mPartGenProb,"LbmFsgrSolver", "mPartGenProb", false); } @@ -500,7 +256,7 @@ void LbmSolverInterface::parseStdAttrList() { void LbmSolverInterface::initGeoTree(int id) { if(mpGlob == NULL) { errFatal("LbmSolverInterface::initGeoTree","Requires globals!",SIMWORLD_INITERROR); return; } mGeoInitId = id; - ntlScene *scene = mpGlob->getScene(); + ntlScene *scene = mpGlob->getSimScene(); mpGiObjects = scene->getObjects(); mGiObjInside.resize( mpGiObjects->size() ); mGiObjDistance.resize( mpGiObjects->size() ); @@ -779,25 +535,26 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir, } } + /*****************************************************************************/ -/*! get max. velocity of all objects to initialize as fluid regions or inflow */ -ntlVec3Gfx LbmSolverInterface::getGeoMaxInitialVelocity() { +ntlVec3Gfx LbmSolverInterface::getGeoMaxMovementVelocity(LbmFloat simtime, LbmFloat stepsize) { ntlVec3Gfx max(0.0); if(mpGlob == NULL) return max; - - ntlScene *scene = mpGlob->getScene(); - mpGiObjects = scene->getObjects(); + // mpGiObjects has to be inited here... for(int i=0; i< (int)mpGiObjects->size(); i++) { + errMsg("MVT","i"<<i<<" "<< (*mpGiObjects)[i]->getName() ); // DEBUG if( (*mpGiObjects)[i]->getGeoInitType() & (FGI_FLUID|FGI_MBNDINFLOW) ){ - ntlVec3Gfx ovel = (*mpGiObjects)[i]->getInitialVelocity(); - if( normNoSqrt(ovel) > normNoSqrt(max) ) { max = ovel; } - //errMsg("IVT","i"<<i<<" "<< (*mpGiObjects)[i]->getInitialVelocity() ); // DEBUG + //ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime); + ntlVec3Gfx orgvel = (*mpGiObjects)[i]->calculateMaxVel( simtime, simtime+stepsize ); + if( normNoSqrt(orgvel) > normNoSqrt(max) ) { max = orgvel; } + //errMsg("MVT","i"<<i<<" a"<< (*mpGiObjects)[i]->getInitialVelocity(simtime)<<" o"<<orgvel ); // DEBUG + // TODO check if inflow and simtime + ntlVec3Gfx inivel = (*mpGiObjects)[i]->getInitialVelocity(simtime); + if( normNoSqrt(inivel) > normNoSqrt(max) ) { max = inivel; } } } - //errMsg("IVT","max "<<" "<< max ); // DEBUG - // unused !? mGiInsideCnt.resize( mpGiObjects->size() ); - + errMsg("MVT","max "<<" "<< max ); // DEBUG return max; } diff --git a/intern/elbeem/intern/solver_interface.h b/intern/elbeem/intern/solver_interface.h index ead866108bd..c86bbce2a89 100644 --- a/intern/elbeem/intern/solver_interface.h +++ b/intern/elbeem/intern/solver_interface.h @@ -29,11 +29,10 @@ #include "utilities.h" #include "ntl_bsptree.h" #include "ntl_geometryobject.h" -#include "ntl_rndstream.h" #include "parametrizer.h" #include "attributes.h" -#include "particletracer.h" #include "isosurface.h" +class ParticleTracer; // use which fp-precision for LBM? 1=float, 2=double #ifdef PRECISION_LBM_SINGLE @@ -67,6 +66,17 @@ typedef ntlVec3d LbmVec; #endif +// default to 3dim +#ifndef LBMDIM +#define LBMDIM 3 +#endif // LBMDIM + +#if LBMDIM==2 +#define LBM_DFNUM 9 +#else +#define LBM_DFNUM 19 +#endif + // conversions (lbm and parametrizer) template<class T> inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); } template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); } @@ -75,40 +85,73 @@ template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]) // bubble id type typedef int BubbleId; -// for both short int/char +// basic cell type distinctions #define CFUnused (1<< 0) #define CFEmpty (1<< 1) #define CFBnd (1<< 2) -#define CFBndNoslip (1<< 3) -#define CFBndFreeslip (1<< 4) -#define CFBndPartslip (1<< 5) -// force symmetry for flag reinit -#define CFNoInterpolSrc (1<< 6) -#define CFFluid (1<< 7) -#define CFInter (1<< 8) -#define CFNoNbFluid (1<< 9) -#define CFNoNbEmpty (1<<10) -#define CFNoDelete (1<<11) -#define CFNoBndFluid (1<<12) +#define CFMbndInflow (1<< 3) +#define CFMbndOutflow (1<< 4) +#define CFFluid (1<< 5) +#define CFInter (1<< 6) +// additional for fluid (needed separately for adaptive grids) +#define CFNoBndFluid (1<< 7) +#define CFNoDelete (1<< 8) + +// additional bnd add flags +#define CFBndNoslip (1<< 9) +#define CFBndFreeslip (1<<10) +#define CFBndPartslip (1<<11) +#define CFBndMoving (1<<12) + +// additional for fluid/interface +// force symmetry for flag reinit +#define CFNoInterpolSrc (1<< 9) +#define CFNoNbFluid (1<<10) +#define CFNoNbEmpty (1<<11) -//! refinement tags // cell treated normally on coarser grids -#define CFGrNorm (1<<13) +#define CFGrNorm (1<< 9) +#define CFGrCoarseInited (1<<10) + +// (the following values shouldnt overlap to ensure +// proper coarsening) // border cells to be interpolated from finer grid -#define CFGrFromFine (1<<14) -#define CFGrFromCoarse (1<<15) -#define CFGrCoarseInited (1<<16) +#define CFGrFromFine (1<<13) // 32k aux border marker -#define CFGrToFine (1<<17) -#define CFMbndInflow (1<<18) -#define CFMbndOutflow (1<<19) - -// debug/helper type -#define CFIgnore (1<<20) +#define CFGrToFine (1<<14) +// also needed on finest level +#define CFGrFromCoarse (1<<15) +// additional refinement tags (coarse grids only?) +// */ // above 24 is used to encode in/outflow object type #define CFPersistMask (0xFF000000 | CFMbndInflow | CFMbndOutflow) +/* +// TEST +// additional bnd add flags +#define CFBndNoslip (1<< 9) +#define CFBndFreeslip (1<<10) +#define CFBndPartslip (1<<11) +#define CFBndMoving (1<<12) + +// additional for fluid/interface +// force symmetry for flag reinit +#define CFNoInterpolSrc (1<<13) +#define CFNoNbFluid (1<<14) +#define CFNoNbEmpty (1<<15) + +// additional refinement tags (coarse grids only?) +// cell treated normally on coarser grids +#define CFGrNorm (1<<16) +// border cells to be interpolated from finer grid +#define CFGrFromFine (1<<17) +#define CFGrFromCoarse (1<<18) +#define CFGrCoarseInited (1<<19) +// 32k aux border marker +#define CFGrToFine (1<<20) +// TEST */ + // nk #define CFInvalid (CellFlagType)(1<<31) @@ -129,14 +172,12 @@ typedef int BubbleId; // max. no. of cell values for 3d #define dTotalNum 22 - /*****************************************************************************/ /*! a single lbm cell */ /* the template is only needed for * dimension dependend constants e.g. * number of df's in model */ -template<typename D> -class LbmCellTemplate { +class LbmCellContents { public: LbmFloat df[ 27 ]; // be on the safe side here... LbmFloat rho; @@ -145,52 +186,8 @@ class LbmCellTemplate { CellFlagType flag; BubbleId bubble; LbmFloat ffrac; - - //! test if a flag is set - inline bool test(CellFlagType t) { - return ((flag & t)==t); - } - //! test if any of the given flags is set - inline bool testAny(CellFlagType t) { - return ((flag & t)!=0); - } - //! test if the cell is empty - inline bool isEmpty() { - return (flag == CFEmpty); - } - - //! init default values for a certain flag type - inline void initDefaults(CellFlagType type) { - flag = type; - vel = LbmVec(0.0); - for(int l=0; l<D::cDfNum;l++) df[l] = D::dfEquil[l]; - - if(type & CFFluid) { - rho = mass = ffrac = 1.0; - bubble = -1; - } - else if(type & CFInter) { - rho = mass = ffrac = 0.0; - bubble = 0; - } - else if(type & CFBnd) { - rho = mass = ffrac = 0.0; - bubble = -1; - } - else if(type & CFEmpty) { - rho = mass = ffrac = 0.0; - bubble = 0; - } else { - // ? - rho = mass = ffrac = 0.0; - bubble = -1; - } - } - - //TODO add init method? }; - /* struct for the coordinates of a cell in the grid */ typedef struct { int x,y,z; @@ -218,13 +215,6 @@ typedef struct { #define FLUIDDISPGrid 6 #define FLUIDDISPSurface 7 -//! settings for a debug display -typedef struct fluidDispSettings_T { - int type; // what to display - bool on; // display enabled? - float scale; // additional scale param -} fluidDispSettings; - /*****************************************************************************/ @@ -265,11 +255,12 @@ class LbmSolverInterface virtual ~LbmSolverInterface() { }; //! id string of solver virtual string getIdString() = 0; - //! dimension of solver - virtual int getDimension() = 0; /*! finish the init with config file values (allocate arrays...) */ - virtual bool initializeSolver() =0; //( ntlTree *tree, vector<ntlGeometryObject*> *objects ) = 0; + virtual bool initializeSolver() =0; + + /*! notify object that dump is in progress (e.g. for field dump) */ + virtual void notifySolverOfDump(int frameNr,char *frameNrStr,string outfilename) = 0; /*! parse a boundary flag string */ CellFlagType readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed); @@ -292,7 +283,7 @@ class LbmSolverInterface #if LBM_USE_GUI==1 /*! show simulation info */ - virtual void debugDisplay(fluidDispSettings *) = 0; + virtual void debugDisplay(int) = 0; #endif /*! init tree for certain geometry init */ @@ -305,8 +296,8 @@ class LbmSolverInterface const gfxReal halfCellsize, bool &thinHit, bool recurse); /*! set render globals, for scene/tree access */ void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; }; - /*! get max. velocity of all objects to initialize as fluid regions */ - ntlVec3Gfx getGeoMaxInitialVelocity(); + /*! get max. velocity of all objects to initialize as fluid regions, and of all moving objects */ + ntlVec3Gfx getGeoMaxMovementVelocity(LbmFloat simtime, LbmFloat stepsize); /* rt interface functions */ unsigned int getIsoVertexCount() { return mpIso->getIsoVertexCount(); } @@ -374,6 +365,20 @@ class LbmSolverInterface //! set desired refinement inline void setRefinementDesired(int set){ mRefinementDesired = set; } + //! set/get dump velocities flag + inline void setDumpVelocities(bool set) { mDumpVelocities = set; } + inline bool getDumpVelocities() const { return mDumpVelocities; } + + //! set/get particle generation prob. + inline void setGenerateParticles(LbmFloat set) { mPartGenProb = set; } + inline LbmFloat getGenerateParticles() const { return mPartGenProb; } + + //! set/get dump velocities flag + inline void setDomainBound(std::string set) { mDomainBound = set; } + inline std::string getDomainBound() const { return mDomainBound; } + //! set/get dump velocities flag + inline void setDomainPartSlip(LbmFloat set) { mDomainPartSlipValue = set; } + inline LbmFloat getDomainPartSlip() const { return mDomainPartSlipValue; } // cell iterator interface @@ -399,18 +404,19 @@ class LbmSolverInterface virtual LbmVec getCellVelocity ( CellIdentifierInterface*,int ) = 0; /*! get equilibrium distribution functions */ virtual LbmFloat getEquilDf ( int ) = 0; - /*! get number of distribution functions */ - virtual int getDfNum ( ) = 0; /*! redundant cell functions */ virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir) = 0; virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set) = 0; virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0; virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0; + /*! get velocity directly from position */ + virtual ntlVec3Gfx getVelocityAt(float x, float y, float z) = 0; + // gui/output debugging functions #if LBM_USE_GUI==1 - virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifier cell ) = 0; - virtual void lbmDebugDisplay(fluidDispSettings *dispset) = 0; + virtual void debugDisplayNode(int dispset, CellIdentifier cell ) = 0; + virtual void lbmDebugDisplay(int dispset) = 0; virtual void lbmMarkedCellDisplay() = 0; #endif // LBM_USE_GUI==1 virtual void debugPrintNodeInfo(CellIdentifier cell, int forceSet=-1) = 0; @@ -484,11 +490,6 @@ class LbmSolverInterface /*! string for node info debugging output */ string mNodeInfoString; - - /*! an own random stream */ - ntlRandomStream mRandom; - - // geo init vars // TODO deprecate SimulationObject vars @@ -534,353 +535,26 @@ class LbmSolverInterface float mSmoothSurface; float mSmoothNormals; + //! particle generation probability + LbmFloat mPartGenProb; + + //! dump velocities? + bool mDumpVelocities; + // list for marked cells vector<CellIdentifierInterface *> mMarkedCells; int mMarkedCellIndex; -}; - - -//! shorten static const definitions -#define STCON static const - - -/*****************************************************************************/ -/*! class for solver templating - 3D implementation */ -class LbmD3Q19 { - - public: - - // constructor, init interface - LbmD3Q19() {}; - // virtual destructor - virtual ~LbmD3Q19() {}; - //! id string of solver - string getIdString() { return string("3D"); } - - //! how many dimensions? - STCON int cDimension; - - // Wi factors for collide step - STCON LbmFloat cCollenZero; - STCON LbmFloat cCollenOne; - STCON LbmFloat cCollenSqrtTwo; - - //! threshold value for filled/emptied cells - STCON LbmFloat cMagicNr2; - STCON LbmFloat cMagicNr2Neg; - STCON LbmFloat cMagicNr; - STCON LbmFloat cMagicNrNeg; - - //! size of a single set of distribution functions - STCON int cDfNum; - //! direction vector contain vecs for all spatial dirs, even if not used for LBM model - STCON int cDirNum; - - //! distribution functions directions - typedef enum { - cDirInv= -1, - cDirC = 0, - cDirN = 1, - cDirS = 2, - cDirE = 3, - cDirW = 4, - cDirT = 5, - cDirB = 6, - cDirNE = 7, - cDirNW = 8, - cDirSE = 9, - cDirSW = 10, - cDirNT = 11, - cDirNB = 12, - cDirST = 13, - cDirSB = 14, - cDirET = 15, - cDirEB = 16, - cDirWT = 17, - cDirWB = 18 - } dfDir; - - /* Vector Order 3D: - * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 - * 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1 - * 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1 - * 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1 - */ - - /*! name of the dist. function - only for nicer output */ - STCON char* dfString[ 19 ]; - - /*! index of normal dist func, not used so far?... */ - STCON int dfNorm[ 19 ]; - - /*! index of inverse dist func, not fast, but useful... */ - STCON int dfInv[ 19 ]; - - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefX[ 19 ]; - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefY[ 19 ]; - /*! index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefZ[ 19 ]; - - /*! dist func vectors */ - STCON int dfVecX[ 27 ]; - STCON int dfVecY[ 27 ]; - STCON int dfVecZ[ 27 ]; - - /*! arrays as before with doubles */ - STCON LbmFloat dfDvecX[ 27 ]; - STCON LbmFloat dfDvecY[ 27 ]; - STCON LbmFloat dfDvecZ[ 27 ]; - - /*! principal directions */ - STCON int princDirX[ 2*3 ]; - STCON int princDirY[ 2*3 ]; - STCON int princDirZ[ 2*3 ]; - - /*! vector lengths */ - STCON LbmFloat dfLength[ 19 ]; - - /*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ - static LbmFloat dfEquil[ 19 ]; - - /*! arrays for les model coefficients */ - static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ]; - static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ]; - -}; // LbmData3D - - -/*****************************************************************************/ -//! class for solver templating - 2D implementation -class LbmD2Q9 { - - public: - - // constructor, init interface - LbmD2Q9() {}; - // virtual destructor - virtual ~LbmD2Q9() {}; - //! id string of solver - string getIdString() { return string("2D"); } - - //! how many dimensions? - STCON int cDimension; - - //! Wi factors for collide step - STCON LbmFloat cCollenZero; - STCON LbmFloat cCollenOne; - STCON LbmFloat cCollenSqrtTwo; - - //! threshold value for filled/emptied cells - STCON LbmFloat cMagicNr2; - STCON LbmFloat cMagicNr2Neg; - STCON LbmFloat cMagicNr; - STCON LbmFloat cMagicNrNeg; - - //! size of a single set of distribution functions - STCON int cDfNum; - STCON int cDirNum; - - //! distribution functions directions - typedef enum { - cDirInv= -1, - cDirC = 0, - cDirN = 1, - cDirS = 2, - cDirE = 3, - cDirW = 4, - cDirNE = 5, - cDirNW = 6, - cDirSE = 7, - cDirSW = 8 - } dfDir; - - /* Vector Order 2D: - * 0 1 2 3 4 5 6 7 8 - * 0, 0,0, 1,-1, 1,-1,1,-1 - * 0, 1,-1, 0,0, 1,1,-1,-1 */ - - /* name of the dist. function - only for nicer output */ - STCON char* dfString[ 9 ]; - - /* index of normal dist func, not used so far?... */ - STCON int dfNorm[ 9 ]; - - /* index of inverse dist func, not fast, but useful... */ - STCON int dfInv[ 9 ]; - - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefX[ 9 ]; - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefY[ 9 ]; - /* index of x reflected dist func for free slip, not valid for all DFs... */ - STCON int dfRefZ[ 9 ]; - - /* dist func vectors */ - STCON int dfVecX[ 9 ]; - STCON int dfVecY[ 9 ]; - /* Z, 2D values are all 0! */ - STCON int dfVecZ[ 9 ]; - - /* arrays as before with doubles */ - STCON LbmFloat dfDvecX[ 9 ]; - STCON LbmFloat dfDvecY[ 9 ]; - /* Z, 2D values are all 0! */ - STCON LbmFloat dfDvecZ[ 9 ]; - - /*! principal directions */ - STCON int princDirX[ 2*2 ]; - STCON int princDirY[ 2*2 ]; - STCON int princDirZ[ 2*2 ]; - - /* vector lengths */ - STCON LbmFloat dfLength[ 9 ]; + //! domain boundary free/no slip type + std::string mDomainBound; + //! part slip value for domain + LbmFloat mDomainPartSlipValue; - /* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */ - static LbmFloat dfEquil[ 9 ]; + //! test vars + // strength of applied force + LbmFloat mTForceStrength; - /*! arrays for les model coefficients */ - static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ]; - static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ]; - -}; // LbmData3D - - - -// lbmdimensions - -// not needed hereafter -#undef STCON - - - -/*****************************************************************************/ -//! class for solver templating - lbgk (srt) model implementation -template<class DQ> -class LbmModelLBGK : public DQ , public LbmSolverInterface { - public: - - /*! type for cells contents, needed for cell id interface */ - typedef DQ LbmCellContents; - /*! type for cells */ - typedef LbmCellTemplate< LbmCellContents > LbmCell; - - // constructor - LbmModelLBGK() : DQ(), LbmSolverInterface() {}; - // virtual destructor - virtual ~LbmModelLBGK() {}; - //! id string of solver - string getIdString() { return DQ::getIdString() + string("lbgk]"); } - - /*! calculate length of velocity vector */ - static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) { - return ((ux)*DQ::dfDvecX[l]+(uy)*DQ::dfDvecY[l]+(uz)*DQ::dfDvecZ[l]); - }; - - /*! calculate equilibrium DF for given values */ - static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) { - LbmFloat tmp = getVelVecLen(l,ux,uy,uz); - return( DQ::dfLength[l] *( - + rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) - + 3.0 *tmp - + 9.0/2.0 *(tmp*tmp) ) - ); - }; - - - /*! relaxation LES functions */ - inline LbmFloat getLesNoneqTensorCoeff( - LbmFloat df[], - LbmFloat feq[] ) { - LbmFloat Qo = 0.0; - for(int m=0; m< ((DQ::cDimension*DQ::cDimension)-DQ::cDimension)/2 ; m++) { - LbmFloat qadd = 0.0; - for(int l=1; l<DQ::cDfNum; l++) { - if(DQ::lesCoeffOffdiag[m][l]==0.0) continue; - qadd += DQ::lesCoeffOffdiag[m][l]*(df[l]-feq[l]); - } - Qo += (qadd*qadd); - } - Qo *= 2.0; // off diag twice - for(int m=0; m<DQ::cDimension; m++) { - LbmFloat qadd = 0.0; - for(int l=1; l<DQ::cDfNum; l++) { - if(DQ::lesCoeffDiag[m][l]==0.0) continue; - qadd += DQ::lesCoeffDiag[m][l]*(df[l]-feq[l]); - } - Qo += (qadd*qadd); - } - Qo = sqrt(Qo); - return Qo; - } - inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) { - const LbmFloat tau = 1.0/omega; - const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0); - const LbmFloat C = csmago; - const LbmFloat Csqr = C*C; - LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr); - return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) ); - } - - // "normal" collision - inline void collideArrays(LbmFloat df[], - LbmFloat &outrho, // out only! - // velocity modifiers (returns actual velocity!) - LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, - LbmFloat omega, LbmFloat csmago, - LbmFloat *newOmegaRet, LbmFloat *newQoRet - ) { - LbmFloat rho=df[0]; - LbmFloat ux = mux; - LbmFloat uy = muy; - LbmFloat uz = muz; - for(int l=1; l<DQ::cDfNum; l++) { - rho += df[l]; - ux += (DQ::dfDvecX[l]*df[l]); - uy += (DQ::dfDvecY[l]*df[l]); - uz += (DQ::dfDvecZ[l]*df[l]); - } - LbmFloat feq[19]; - for(int l=0; l<DQ::cDfNum; l++) { - feq[l] = getCollideEq(l,rho,ux,uy,uz); - } - - LbmFloat omegaNew; - LbmFloat Qo = 0.0; - if(csmago>0.0) { - Qo = getLesNoneqTensorCoeff(df,feq); - omegaNew = getLesOmega(omega,csmago,Qo); - } else { - omegaNew = omega; // smago off... - } - if(newOmegaRet) *newOmegaRet = omegaNew; // return value for stats - if(newQoRet) *newQoRet = Qo; // return value of non-eq. stress tensor - - for(int l=0; l<DQ::cDfNum; l++) { - df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l]; - } - - mux = ux; - muy = uy; - muz = uz; - outrho = rho; - }; - -}; // LBGK - -#ifdef LBMMODEL_DEFINED -// force compiler error! -ERROR - Dont include several LBM models at once... -#endif -#define LBMMODEL_DEFINED 1 - - -typedef LbmModelLBGK< LbmD2Q9 > LbmBGK2D; -typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D; +}; // helper function to create consistent grid resolutions diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index c4f5c9ba14e..c8f0678a6f0 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -9,66 +9,60 @@ #include "solver_class.h" #include "solver_relax.h" +#include "particletracer.h" /*****************************************************************************/ /*! perform a single LBM step */ /*****************************************************************************/ -template<class D> -string LbmFsgrSolver<D>::getIdString() { - return string("FsgrSolver[") + D::getIdString(); -} - -template<class D> -int LbmFsgrSolver<D>::getDimension() { return D::cDimension; } -template<class D> -void LbmFsgrSolver<D>::step() { +void LbmFsgrSolver::step() { initLevelOmegas(); stepMain(); } -template<class D> -void -LbmFsgrSolver<D>::stepMain() +void LbmFsgrSolver::stepMain() { -#if ELBEEM_PLUGIN==1 +#if ELBEEM_BLENDER==1 // update gui display //SDL_mutexP(lobalBakeLock); if(getGlobalBakeState()<0) { // this means abort... cause panic - D::mPanic = 1; + CAUSE_PANIC; errMsg("LbmFsgrSolver::step","Got abort signal from GUI, causing panic, aborting..."); } //SDL_mutexV(lobalBakeLock); #endif // ELBEEM_PLUGIN==1 - D::markedClearList(); // DMC clearMarkedCellsList + this->markedClearList(); // DMC clearMarkedCellsList // safety check, counter reset - D::mNumUsedCells = 0; + this->mNumUsedCells = 0; mNumInterdCells = 0; mNumInvIfCells = 0; - //debugOutNnl("LbmFsgrSolver::step : "<<D::mStepCnt, 10); - if(!D::mSilent){ debMsgNnl("LbmFsgrSolver::step", DM_MSG, D::mName<<" cnt:"<<D::mStepCnt<<" ", 10); } - //debMsgDirect( "LbmFsgrSolver::step : "<<D::mStepCnt<<" "); + //debugOutNnl("LbmFsgrSolver::step : "<<this->mStepCnt, 10); + if(!this->mSilent){ debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<<this->mStepCnt<<" t:"<<mSimulationTime, 10); } + //debMsgDirect( "LbmFsgrSolver::step : "<<this->mStepCnt<<" "); myTime_t timestart = getTime(); //myTime_t timestart = 0; //if(mStartSymm) { checkSymmetry("step1"); } // DEBUG + // time adapt + mMaxVlen = mMxvz = mMxvy = mMxvx = 0.0; + + // init moving bc's, can change mMaxVlen + initMovingObstacles(false); + // important - keep for tadap - mCurrentMass = D::mFixMass; // reset here for next step + mCurrentMass = this->mFixMass; // reset here for next step mCurrentVolume = 0.0; - //stats - mMaxVlen = mMxvz = mMxvy = mMxvx = 0.0; - //change to single step advance! int levsteps = 0; - int dsbits = D::mStepCnt ^ (D::mStepCnt-1); - //errMsg("S"," step:"<<D::mStepCnt<<" s-1:"<<(D::mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits)); + int dsbits = this->mStepCnt ^ (this->mStepCnt-1); + //errMsg("S"," step:"<<this->mStepCnt<<" s-1:"<<(this->mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits)); for(int lev=0; lev<=mMaxRefine; lev++) { - //if(! (D::mStepCnt&(1<<lev)) ) { + //if(! (this->mStepCnt&(1<<lev)) ) { if( dsbits & (1<<(mMaxRefine-lev)) ) { //errMsg("S"," l"<<lev); @@ -91,44 +85,46 @@ LbmFsgrSolver<D>::stepMain() } // prepare next step - D::mStepCnt++; + this->mStepCnt++; // some dbugging output follows // calculate MLSUPS myTime_t timeend = getTime(); - D::mNumUsedCells += mNumInterdCells; // count both types for MLSUPS - mAvgNumUsedCells += D::mNumUsedCells; - D::mMLSUPS = (D::mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000); - if(D::mMLSUPS>10000){ D::mMLSUPS = -1; } - else { mAvgMLSUPS += D::mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups + this->mNumUsedCells += mNumInterdCells; // count both types for MLSUPS + mAvgNumUsedCells += this->mNumUsedCells; + this->mMLSUPS = (this->mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000); + if(this->mMLSUPS>10000){ this->mMLSUPS = -1; } + else { mAvgMLSUPS += this->mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups LbmFloat totMLSUPS = ( ((mLevel[mMaxRefine].lSizex-2)*(mLevel[mMaxRefine].lSizey-2)*(getForZMax1(mMaxRefine)-getForZMin1())) / ((timeend-timestart)/(double)1000.0) ) / (1000000); if(totMLSUPS>10000) totMLSUPS = -1; mNumInvIfTotal += mNumInvIfCells; // debug // do some formatting - if(!D::mSilent){ + if(!this->mSilent){ string sepStr(""); // DEBUG - int avgcls = (int)(mAvgNumUsedCells/(LONGINT)D::mStepCnt); - debMsgDirect( - "mlsups(curr:"<<D::mMLSUPS<< + int avgcls = (int)(mAvgNumUsedCells/(LONGINT)this->mStepCnt); + debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<<this->mStepCnt<<" t:"<<mSimulationTime<< + //debMsgDirect( + "mlsups(curr:"<<this->mMLSUPS<< " avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<< sepStr<< - " totcls:"<<(D::mNumUsedCells)<< sepStr<< + " totcls:"<<(this->mNumUsedCells)<< sepStr<< " avgcls:"<< avgcls<< sepStr<< " intd:"<<mNumInterdCells<< sepStr<< " invif:"<<mNumInvIfCells<< sepStr<< " invift:"<<mNumInvIfTotal<< sepStr<< " fsgrcs:"<<mNumFsgrChanges<< sepStr<< - " filled:"<<D::mNumFilledCells<<", emptied:"<<D::mNumEmptiedCells<< sepStr<< + " filled:"<<this->mNumFilledCells<<", emptied:"<<this->mNumEmptiedCells<< sepStr<< " mMxv:"<<mMxvx<<","<<mMxvy<<","<<mMxvz<<", tscnts:"<<mTimeSwitchCounts<< sepStr<< + " RWmxv:"<<ntlVec3Gfx(mMxvx,mMxvy,mMxvz)*(mLevel[mMaxRefine].simCellSize / mLevel[mMaxRefine].timestep)<<" "<< /* realworld vel output */ " probs:"<<mNumProblems<< sepStr<< " simt:"<<mSimulationTime<< sepStr<< - " for '"<<D::mName<<"' " ); + " for '"<<this->mName<<"' " , 10); debMsgDirect(std::endl); - debMsgDirect(D::mStepCnt<<": dccd="<< mCurrentMass<<"/"<<mCurrentVolume<<"(fix="<<D::mFixMass<<",ini="<<mInitialMass<<") "); + debMsgDirect(this->mStepCnt<<": dccd="<< mCurrentMass<<"/"<<mCurrentVolume<<"(fix="<<this->mFixMass<<",ini="<<mInitialMass<<") "); debMsgDirect(std::endl); // nicer output @@ -139,11 +135,11 @@ LbmFsgrSolver<D>::stepMain() //if((mStepCnt%10)==9) debMsgDirect("\n"); } - if(D::mStepCnt==1) { - mMinNoCells = mMaxNoCells = D::mNumUsedCells; + if(this->mStepCnt==1) { + mMinNoCells = mMaxNoCells = this->mNumUsedCells; } else { - if(D::mNumUsedCells>mMaxNoCells) mMaxNoCells = D::mNumUsedCells; - if(D::mNumUsedCells<mMinNoCells) mMinNoCells = D::mNumUsedCells; + if(this->mNumUsedCells>mMaxNoCells) mMaxNoCells = this->mNumUsedCells; + if(this->mNumUsedCells<mMinNoCells) mMinNoCells = this->mNumUsedCells; } // mass scale test @@ -167,7 +163,7 @@ LbmFsgrSolver<D>::stepMain() errMsg("MDTDD","\n\n"); errMsg("MDTDD","FORCE RESCALE MASS! " <<"ini:"<<mInitialMass<<", cur:"<<mCurrentMass<<", f="<<ABS(mInitialMass/mCurrentMass) - <<" step:"<<D::mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" " + <<" step:"<<this->mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" " ); errMsg("MDTDD","\n\n"); @@ -208,58 +204,53 @@ LbmFsgrSolver<D>::stepMain() } } +#if LBM_INCLUDE_TESTSOLVERS==1 + if((mUseTestdata)&&(this->mInitDone)) { handleTestdata(); } +#endif + // one of the last things to do - adapt timestep // was in fineAdvance before... if(mTimeAdap) { adaptTimestep(); } // time adaptivity - // debug - raw dump of ffrac values - /*if((D::mStepCnt%100)==1){ - std::ostringstream name; - name <<"fill_" << D::mStepCnt <<".dump"; - FILE *file = fopen(name.str().c_str(),"w"); - for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { - for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) { - for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { - float val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); - //fwrite( &val, sizeof(val), 1, file); // binary - fprintf(file, "%f ",val); // text - //errMsg("W", PRINT_IJK<<" val:"<<val); - } - fprintf(file, "\n"); // text - } - fprintf(file, "\n"); // text - } - fclose(file); - } // */ -#if ELBEEM_PLUGIN!=1 - if(mUseTestdata) { - if(mpTest->mDebugvalue3>0.0) handleTestdata(); - } -#endif // ELBEEM_PLUGIN!=1 +#ifndef WIN32 + // good indicator for instabilities + if( (!finite(mMxvx)) || (!finite(mMxvy)) || (!finite(mMxvz)) ) { CAUSE_PANIC; } + if( (!finite(mCurrentMass)) || (!finite(mCurrentVolume)) ) { CAUSE_PANIC; } +#endif // WIN32 + //#endif // ELBEEM_PLUGIN!=1 } -template<class D> -void -LbmFsgrSolver<D>::fineAdvance() +#define NEWDEBCHECK(str) \ + if(!this->mPanic){ FSGR_FORIJK_BOUNDS(mMaxRefine) { \ + if(RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr)&(CFFluid|CFInter)) { \ + for(int l=0;l<dTotalNum;l++) { \ + if(!finite(QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr,l))) { errMsg("NNOFIN"," "<<str<<" at "<<PRINT_IJK<<" l"<<l<<" "); }\ + }/*for*/ \ + }/*if*/ \ + } } + +void LbmFsgrSolver::fineAdvance() { // do the real thing... + //NEWDEBCHECK("t1"); mainLoop( mMaxRefine ); if(mUpdateFVHeight) { // warning assume -Y gravity... mFVHeight = mCurrentMass*mFVArea/((LbmFloat)(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizez)); if(mFVHeight<1.0) mFVHeight = 1.0; - D::mpParam->setFluidVolumeHeight(mFVHeight); + this->mpParam->setFluidVolumeHeight(mFVHeight); } + //NEWDEBCHECK("t2"); // advance time before timestep change - mSimulationTime += D::mpParam->getStepTime(); + mSimulationTime += this->mpParam->getTimestep(); // time adaptivity - D::mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) ); + this->mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) ); //if(mStartSymm) { checkSymmetry("step2"); } // DEBUG - if(!D::mSilent){ errMsg("fineAdvance"," stepped from "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps) ); } + if(!this->mSilent){ errMsg("fineAdvance"," stepped from "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps) ); } // update other set mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr; @@ -268,7 +259,8 @@ LbmFsgrSolver<D>::fineAdvance() // flag init... (work on current set, to simplify flag checks) reinitFlags( mLevel[mMaxRefine].setCurr ); - if(!D::mSilent){ errMsg("fineAdvance"," flags reinit on set "<< mLevel[mMaxRefine].setCurr ); } + if(!this->mSilent){ errMsg("fineAdvance"," flags reinit on set "<< mLevel[mMaxRefine].setCurr ); } + //NEWDEBCHECK("t3"); } @@ -276,26 +268,35 @@ LbmFsgrSolver<D>::fineAdvance() //! coarse/fine step functions /*****************************************************************************/ + +// ZDEB + // access to own dfs during step (may be changed to local array) #define MYDF(l) RAC(ccel, l) -template<class D> void -LbmFsgrSolver<D>::mainLoop(int lev) +LbmFsgrSolver::mainLoop(int lev) { // loops over _only inner_ cells ----------------------------------------------------------------------------------- LbmFloat calcCurrentMass = 0.0; LbmFloat calcCurrentVolume = 0.0; - int calcCellsFilled = D::mNumFilledCells; - int calcCellsEmptied = D::mNumEmptiedCells; - int calcNumUsedCells = D::mNumUsedCells; - + int calcCellsFilled = this->mNumFilledCells; + int calcCellsEmptied = this->mNumEmptiedCells; + int calcNumUsedCells = this->mNumUsedCells; + +# if LBM_INCLUDE_TESTSOLVERS==1 + if((mUseTestdata)&&(mpTest->mDebugvalue1>0.0)) { + // 3d region off... quit + this->mpIso->setIsolevel(-100.0); return; } +#endif // ELBEEM_PLUGIN!=1 + //printLbmCell(lev, 6,6,16, mLevel[lev].setCurr ); // DEBUG + #if PARALLEL==1 #include "paraloop.h" #else // PARALLEL==1 { // main loop region int kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); -//{ errMsg("LbmFsgrSolver::mainLoop","Err MAINADVANCE0 ks:"<< kstart<<" ke:"<<kend<<" dim:"<<D::cDimension<<" mlsz:"<< mLevel[mMaxRefine].lSizez<<" zmax1:"<<getForZMax1(mMaxRefine) ); } // DEBUG + //{ errMsg("LbmFsgrSolver::mainLoop","Err MAINADVANCE0 ks:"<< kstart<<" ke:"<<kend<<" dim:"<<LBMDIMcDimension<<" mlsz:"<< mLevel[mMaxRefine].lSizez<<" zmax1:"<<getForZMax1(mMaxRefine) ); } // DEBUG #define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); #endif // PARALLEL==1 @@ -308,7 +309,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) int nbored; LbmFloat m[LBM_DFNUM]; LbmFloat rho, ux, uy, uz, tmp, usqr; - LbmFloat mass, change, lcsmqo; + LbmFloat mass, change, lcsmqo=0.0; usqr = tmp = 0.0; #if OPT3D==1 LbmFloat lcsmqadd, lcsmeq[LBM_DFNUM], lcsmomega; @@ -343,13 +344,12 @@ LbmFsgrSolver<D>::mainLoop(int lev) pFlagDst+= (p); \ i+= (p); - // --- // now stream etc. -//{ errMsg("LbmFsgrSolver::mainLoop","Err MAINADVANCE0 ks:"<< kstart<<" ke:"<<kend<<" dim:"<<D::cDimension<<" mlsz:"<<mLevel[mMaxRefine].lSizez ); } // DEBUG + //{ errMsg("LbmFsgrSolver::mainLoop","Err MAINADVANCE0 ks:"<< kstart<<" ke:"<<kend<<" dim:"<<LBMDIM<<" mlsz:"<<mLevel[mMaxRefine].lSizez ); } // DEBUG - // use template functions for 2D/3D + // use //template functions for 2D/3D #if COMPRESSGRIDS==0 for(int k=kstart;k<kend;++k) { for(int j=1;j<mLevel[lev].lSizey-1;++j) { @@ -378,7 +378,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) #if PARALLEL==1 PARA_INITIALIZE(); - errMsg("LbmFsgrSolver::mainLoop","id="<<id<<" js="<<jstart<<" je="<<jend<<" jdir="<<(1) ); // debug + //errMsg("LbmFsgrSolver::mainLoop","id="<<id<<" js="<<jstart<<" je="<<jend<<" jdir="<<(1) ); // debug #endif // PARALLEL==1 for(int k=kstart;k!=kend;k+=kdir) { @@ -404,7 +404,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) (int)(&RFLAG(lev, i,j,k,mLevel[lev].setCurr))<<","<<(int)(&RFLAG(lev, i,j,k,mLevel[lev].setOther))<<" but is "<< (int)(pFlagSrc)<<","<<(int)(pFlagDst)<<" " ); - D::mPanic=1; + CAUSE_PANIC; } if( (&QCELL(lev, i,j,k,mLevel[lev].setCurr,0) != ccel) || (&QCELL(lev, i,j,k,mLevel[lev].setOther,0) != tcel) ) { @@ -412,7 +412,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) (int)(&QCELL(lev, i,j,k,mLevel[lev].setCurr,0))<<","<<(int)(&QCELL(lev, i,j,k,mLevel[lev].setOther,0))<<" but is "<< (int)(ccel)<<","<<(int)(tcel)<<" " ); - D::mPanic=1; + CAUSE_PANIC; } #endif oldFlag = *pFlagSrc; @@ -421,7 +421,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) // old INTCFCOARSETEST==1 if( (oldFlag & (CFGrFromCoarse)) ) { // interpolateFineFromCoarse test! - if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { + if(( this->mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { FORDF0 { RAC(tcel,l) = RAC(ccel,l); } } else { interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); @@ -439,12 +439,13 @@ LbmFsgrSolver<D>::mainLoop(int lev) // make new if cell const LbmVec vel(mObjectSpeeds[OId]); // TODO add OPT3D treatment - FORDF0 { RAC(tcel, l) = D::getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } + FORDF0 { RAC(tcel, l) = this->getCollideEq(l, iniRho,vel[0],vel[1],vel[2]); } RAC(tcel, dMass) = RAC(tcel, dFfrac) = iniRho; RAC(tcel, dFlux) = FLUX_INIT; changeFlag(lev, i,j,k, TSET(lev), CFInter); calcCurrentMass += iniRho; calcCurrentVolume += 1.0; calcNumUsedCells++; mInitialMass += iniRho; + //errMsg("INFLOW_DEBUG","ini at "<<PRINT_IJK<<" v="<<vel<<" inirho="<<iniRho); // dont treat cell until next step continue; } @@ -529,17 +530,19 @@ LbmFsgrSolver<D>::mainLoop(int lev) // only standard fluid cells (with nothing except fluid as nbs if(oldFlag&CFMbndInflow) { - // force velocity for inflow + // force velocity for inflow, necessary to have constant direction of flow + // FIXME , test also set interface cells? const int OId = oldFlag>>24; - DEFAULT_STREAM; + //? DEFAULT_STREAM; //const LbmFloat fluidRho = 1.0; // for submerged inflows, streaming would have to be performed... LbmFloat fluidRho = m[0]; FORDF1 { fluidRho += m[l]; } const LbmVec vel(mObjectSpeeds[OId]); ux=vel[0], uy=vel[1], uz=vel[2]; usqr = 1.5 * (ux*ux + uy*uy + uz*uz); - FORDF0 { RAC(tcel, l) = D::getCollideEq(l, fluidRho,ux,uy,uz); } + FORDF0 { RAC(tcel, l) = this->getCollideEq(l, fluidRho,ux,uy,uz); } rho = fluidRho; + //errMsg("INFLOW_DEBUG","std at "<<PRINT_IJK<<" v="<<vel<<" rho="<<rho); } else { if(nbored&CFBnd) { DEFAULT_STREAM; @@ -549,7 +552,6 @@ LbmFsgrSolver<D>::mainLoop(int lev) } else { // do standard stream/collide OPTIMIZED_STREAMCOLLIDE; - // FIXME check for which cells this is executed! oldFlag |= CFNoBndFluid; } } @@ -586,7 +588,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) // calculate mass exchange for interface cells LbmFloat myfrac = RAC(ccel,dFfrac); -# define nbdf(l) m[ D::dfInv[(l)] ] +# define nbdf(l) m[ this->dfInv[(l)] ] // update mass // only do boundaries for fluid cells, and interface cells without @@ -693,7 +695,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) if( (ABS(nx)+ABS(ny)+ABS(nz)) > LBM_EPSILON) { // normal ok and usable... FORDF1 { - if( (D::dfDvecX[l]*nx + D::dfDvecY[l]*ny + D::dfDvecZ[l]*nz) // dot Dvec,norml + if( (this->dfDvecX[l]*nx + this->dfDvecY[l]*ny + this->dfDvecZ[l]*nz) // dot Dvec,norml > LBM_EPSILON) { recons[l] = 2; numRecons++; @@ -707,11 +709,11 @@ LbmFsgrSolver<D>::mainLoop(int lev) #if OPT3D==0 oldRho=RAC(ccel,0); oldUx = oldUy = oldUz = 0.0; - for(int l=1; l<D::cDfNum; l++) { + for(int l=1; l<this->cDfNum; l++) { oldRho += RAC(ccel,l); - oldUx += (D::dfDvecX[l]*RAC(ccel,l)); - oldUy += (D::dfDvecY[l]*RAC(ccel,l)); - oldUz += (D::dfDvecZ[l]*RAC(ccel,l)); + oldUx += (this->dfDvecX[l]*RAC(ccel,l)); + oldUy += (this->dfDvecY[l]*RAC(ccel,l)); + oldUz += (this->dfDvecZ[l]*RAC(ccel,l)); } #else // OPT3D==0 oldRho = + RAC(ccel,dC) + RAC(ccel,dN ) @@ -750,9 +752,9 @@ LbmFsgrSolver<D>::mainLoop(int lev) // NOW - construct dist funcs from empty cells FORDF1 { if(recons[ l ]) { - m[ D::dfInv[l] ] = - D::getCollideEq(l, REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + - D::getCollideEq(D::dfInv[l], REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + m[ this->dfInv[l] ] = + this->getCollideEq(l, REFERENCE_PRESSURE, oldUx,oldUy,oldUz) + + this->getCollideEq(this->dfInv[l], REFERENCE_PRESSURE, oldUx,oldUy,oldUz) - MYDF( l ); } } @@ -780,12 +782,6 @@ LbmFsgrSolver<D>::mainLoop(int lev) if(recons[dWB]) { m[dET] = EQWB + EQET - MYDF(dWB); } #endif - // mass streaming done... do normal collide - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - ux *= mass; uy *= mass; uz *= mass; // acc. according to mass in cell - DEFAULT_COLLIDE; - PERFORM_USQRMAXCHECK; - // rho init from default collide necessary for fill/empty check below // inflow bc handling if(oldFlag & (CFMbndInflow)) { @@ -794,12 +790,161 @@ LbmFsgrSolver<D>::mainLoop(int lev) mass += 0.25; mInitialMass += 0.25; } - } + const int OId = oldFlag>>24; + const LbmVec vel(mObjectSpeeds[OId]); + ux=vel[0], uy=vel[1], uz=vel[2]; + //? usqr = 1.5 * (ux*ux + uy*uy + uz*uz); + //FORDF0 { RAC(tcel, l) = this->getCollideEq(l, fluidRho,ux,uy,uz); } rho = fluidRho; + rho = REFERENCE_PRESSURE; + FORDF0 { RAC(tcel, l) = this->getCollideEq(l, rho,ux,uy,uz); } + //errMsg("INFLOW_DEBUG","if at "<<PRINT_IJK<<" v="<<vel<<" rho="<<rho); + } else { + // normal collide + // mass streaming done... do normal collide + ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + ux *= mass; uy *= mass; uz *= mass; // acc. according to mass in cell + DEFAULT_COLLIDE; + PERFORM_USQRMAXCHECK; + // rho init from default collide necessary for fill/empty check below + } + + // testing..., particle generation +//# include "est_if.h" test_if + // also check oldFlag for CFNoNbFluid, test + // for inflow no pargen test + // NOBUBBB! + if((this->mInitDone) //&&(mUseTestdata) + && (!((oldFlag|newFlag)&CFNoNbEmpty)) + && (!((oldFlag|newFlag)&CFNoDelete)) + && (this->mPartGenProb>0.0)) { + bool bndOk=true; + if( (i<1+mCutoff)||(i>this->mSizex-1-mCutoff)|| + (j<1+mCutoff)||(j>this->mSizey-1-mCutoff)|| + (k<1+mCutoff)||(k>this->mSizez-1-mCutoff) ) { bndOk=false; } + + LbmFloat realWorldFac = (mLevel[lev].simCellSize / mLevel[lev].timestep); + LbmFloat rux = (ux * realWorldFac); + LbmFloat ruy = (uy * realWorldFac); + LbmFloat ruz = (uz * realWorldFac); + LbmFloat rl = norm(ntlVec3Gfx(rux,ruy,ruz)); + // WHMOD + const LbmFloat val2fac = 1.0; //? TODO N test? /(this->mPartGenProb); // FIXME remove factor! + bool doAdd = true; + + LbmFloat prob = (rand()/(RAND_MAX+1.0)); + LbmFloat basethresh = this->mPartGenProb*lcsmqo*rl; + if( (prob< (basethresh*rl)) && (lcsmqo>0.0095) && (rl>2.5) ) { + // add + } else { + doAdd = false; // dont... + } + +//#define SLOWDOWNREGION (2*mCutoff) +#if LBMDIM==3 + // normal +#define SLOWDOWNREGION (this->mSizez/5) +#else // LBMDIM==2 + // off +#define SLOWDOWNREGION 10 +#endif // LBMDIM==2 +#define P_LCSMQO 0.01 + + // "wind" disturbance + // use realworld relative velocity here instead? + if( + ((rl>1.0) && (lcsmqo<P_LCSMQO)) // normal checks + ||(k>this->mSizez-SLOWDOWNREGION) ) { + LbmFloat nuz = uz; + LbmFloat jdf; // = 0.05 * (rand()/(RAND_MAX+1.0)); + if(rl>1.0) jdf *= (rl-1.0); + if(k>this->mSizez-SLOWDOWNREGION) { + // special case + LbmFloat zfac = (LbmFloat)( k-(this->mSizez-SLOWDOWNREGION) ); + zfac /= (LbmFloat)(SLOWDOWNREGION); + nuz += zfac; // check max speed? OFF? + } else { + // normal probability + LbmFloat fac = P_LCSMQO-lcsmqo; + jdf *= fac; + } + FORDF1 { + jdf = 0.05 * (rand()/(RAND_MAX+1.0)); + // TODO use wind velocity? + if(jdf>0.025) { + const LbmFloat add = this->dfLength[l]*(-ux*this->dfDvecX[l]-uy*this->dfDvecY[l]-nuz*this->dfDvecZ[l])*jdf; + RAC(tcel,l) += add*jdf; } + } + //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<PRINT_VEC(ux,uy,nuz)<<" rwv"<<PRINT_VEC(rux,ruy,ruz) ); + //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<norm(LbmVec(ux,uy,nuz))<<" rwv"<<norm(LbmVec(rux,ruy,ruz)) ); + } // wind disturbance + + if(usqr<0.0001) doAdd=false; // TODO check!? + // if outside, and 20% above sea level, delete, TODO really check level? + //if((!bndOk)&&((LbmFloat)k>pTest->mFluidHeight*1.5)) { doAdd=true; } // FORCEDISSOLVE + //? if(!bndOk) doAdd=false; + //if(this->mStepCnt>700) errMsg("DFJITT"," at "<<PRINT_IJK<<"rwl:"<<rl<<" usqr:"<<usqr <<" qo:"<<lcsmqo<<" add="<<doAdd ); + + if( (doAdd) ) { // ADD DROP + LbmFloat len = norm(LbmVec(ux,uy,uz)); + // WHMOD + //for(int s=0; s<10; s++) { // multiple parts + for(int s=0; s<1; s++) { // one part! + //LbmFloat prob = this->mPartGenProb * 0.02* (rand()/(RAND_MAX+1.0)); + const LbmFloat posjitter = 1.0; + const LbmFloat posjitteroffs = posjitter*-0.5; + LbmFloat jpx = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0)); + LbmFloat jpy = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0)); + LbmFloat jpz = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0)); + + const LbmFloat jitterstr = 0.1; + const LbmFloat jitteroffs = jitterstr*-0.5; + LbmFloat jx = jitteroffs+ jitterstr* (rand()/(RAND_MAX+1.0)); + LbmFloat jy = jitteroffs+ jitterstr* (rand()/(RAND_MAX+1.0)); + LbmFloat jz = jitteroffs+ jitterstr* (rand()/(RAND_MAX+1.0)); + + // average normal & velocity + // -> mostly along velocity dir, many into surface + LbmVec pv = (LbmVec(nx+jx,ny+jy,nz+jz)*0.75 + getNormalized(LbmVec(ux,uy,uz)) )*0.35; + normalize(pv); + + LbmFloat srci = i+0.5+jpx; // TEST? + (pv[0]*1.41); + LbmFloat srcj = j+0.5+jpy; // TEST? + (pv[1]*1.41); + LbmFloat srck = k+0.5+jpz; // TEST? + (pv[2]*1.41); + int type=0; + //if((s%3)!=2) { + + type=PART_DROP; + // drop + srci += (pv[0]*1.41); + srcj += (pv[1]*1.41); + srck += (pv[2]*1.41); + if(!(RFLAG(lev, (int)(srci),(int)(srcj),(int)(srck),SRCS(lev)) &CFEmpty)) continue; // only add in good direction + //} else { type=PART_FLOAT; } + + pv *= len; + LbmFloat size = 1.0+ 9.0* (rand()/(RAND_MAX+1.0)); + + mpParticles->addParticle(srci, srcj, srck); //i+0.5+jpx,j+0.5+jpy,k+0.5+jpz); + mpParticles->getLast()->setVel(pv[0],pv[1],pv[2]); + //? mpParticles->getLast()->advanceVel(); // advance a bit outwards + mpParticles->getLast()->setStatus(PART_IN); + mpParticles->getLast()->setType(type); + //mpParticles->getLast()->setType(PART_INTER); + //if((s%3)==2) mpParticles->getLast()->setType(PART_FLOAT); + mpParticles->getLast()->setSize(size); + //errMsg("NEWPART"," at "<<PRINT_IJK<<" u="<<PRINT_VEC(ux,uy,uz) <<" RWu="<<PRINT_VEC(rux,ruy,ruz)<<" add"<<doAdd<<" pvel="<<pv ); + //errMsg("NEWPART"," at "<<PRINT_IJK<<" u="<<norm(LbmVec(ux,uy,uz)) <<" RWu="<<norm(LbmVec(rux,ruy,ruz))<<" add"<<doAdd<<" pvel="<<norm(pv) ); + //if(!bndOk){ mass -= val2fac*size*0.02; } // FORCEDISSOLVE + mass -= val2fac*size*0.0015; // NTEST! + //mass -= val2fac*size*0.001; // NTEST! +#if LBMDIM==2 + mpParticles->getLast()->setVel(pv[0],pv[1],0.0); + mpParticles->getLast()->setPos(ntlVec3Gfx(srci,srcj,0.5)); +#endif // LBMDIM==2 + } // multiple parts + } // doAdd + } // */ -# if ELBEEM_PLUGIN!=1 - // testing... -# include "test_if.h" -# endif // ELBEEM_PLUGIN // interface cell filled or emptied? iffilled = ifemptied = 0; @@ -851,7 +996,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) #else // PARALLEL==1 mListFull.push_back( filledp ); #endif // PARALLEL==1 - //D::mNumFilledCells++; // DEBUG + //this->mNumFilledCells++; // DEBUG calcCellsFilled++; } else if(ifemptied) { @@ -862,7 +1007,7 @@ LbmFsgrSolver<D>::mainLoop(int lev) #else // PARALLEL==1 mListEmpty.push_back( emptyp ); #endif // PARALLEL==1 - //D::mNumEmptiedCells++; // DEBUG + //this->mNumEmptiedCells++; // DEBUG calcCellsEmptied++; } else { // ... @@ -875,13 +1020,13 @@ LbmFsgrSolver<D>::mainLoop(int lev) float flux = FLUX_INIT; // dxqn on if(newFlag&CFNoBndFluid) { //flux = 50.0; // extreme on - for(int nn=1; nn<D::cDfNum; nn++) { - if(nbflag[nn] & (CFFluid|CFInter|CFBnd)) { flux += D::dfLength[nn]; } + for(int nn=1; nn<this->cDfNum; nn++) { + if(nbflag[nn] & (CFFluid|CFInter|CFBnd)) { flux += this->dfLength[nn]; } } // optical hack - smooth slow moving // surface regions if(usqr< sssUsqrLimit) { - for(int nn=1; nn<D::cDfNum; nn++) { + for(int nn=1; nn<this->cDfNum; nn++) { if(nbfracs[nn]!=0.0) { LbmFloat curSmooth = (sssUsqrLimit-usqr)*sssUsqrLimitInv; if(curSmooth>1.0) curSmooth=1.0; @@ -923,9 +1068,9 @@ LbmFsgrSolver<D>::mainLoop(int lev) //errMsg("DFINI"," maxr l"<<mMaxRefine<<" cm="<<calcCurrentMass<<" cv="<<calcCurrentVolume ); mLevel[lev].lmass = calcCurrentMass; mLevel[lev].lvolume = calcCurrentVolume; - D::mNumFilledCells = calcCellsFilled; - D::mNumEmptiedCells = calcCellsEmptied; - D::mNumUsedCells = calcNumUsedCells; + this->mNumFilledCells = calcCellsFilled; + this->mNumEmptiedCells = calcCellsEmptied; + this->mNumUsedCells = calcNumUsedCells; #if PARALLEL==1 PARA_FINISH(); #endif // PARALLEL==1 @@ -933,9 +1078,10 @@ LbmFsgrSolver<D>::mainLoop(int lev) // check other vars...? } -template<class D> -void -LbmFsgrSolver<D>::coarseCalculateFluxareas(int lev) +// ZDEB + + +void LbmFsgrSolver::coarseCalculateFluxareas(int lev) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); @@ -945,8 +1091,8 @@ LbmFsgrSolver<D>::coarseCalculateFluxareas(int lev) if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<D::cDirNum; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) ) { @@ -965,13 +1111,11 @@ LbmFsgrSolver<D>::coarseCalculateFluxareas(int lev) //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); } } // } TEST DEBUG - if(!D::mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } + if(!this->mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } #endif //! LBM_NOADCOARSENING==1 } -template<class D> -void -LbmFsgrSolver<D>::coarseAdvance(int lev) +void LbmFsgrSolver::coarseAdvance(int lev) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); @@ -999,7 +1143,7 @@ LbmFsgrSolver<D>::coarseAdvance(int lev) ccel -= QCELLSTEP; tcel = RACPNT(lev, 1,1,getForZMin1() ,TSET(lev)); // QTEST tcel -= QCELLSTEP; - //if(strstr(D::getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } + //if(strstr(this->getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { for(int j=1;j<mLevel[lev].lSizey-1;++j) { @@ -1034,11 +1178,11 @@ LbmFsgrSolver<D>::coarseAdvance(int lev) // old INTCFCOARSETEST==1 if((*pFlagSrc) & CFGrFromCoarse) { // interpolateFineFromCoarse test! - if(( D::mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { + if(( this->mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) { FORDF0 { RAC(tcel,l) = RAC(ccel,l); } } else { interpolateCellFromCoarse( lev, i,j,k, TSET(lev), 0.0, CFFluid|CFGrFromCoarse, false); - D::mNumUsedCells++; + this->mNumUsedCells++; } continue; // interpolateFineFromCoarse test! } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 @@ -1065,10 +1209,10 @@ LbmFsgrSolver<D>::coarseAdvance(int lev) #if FSGR_STRICT_DEBUG==1 if(rho<-1.0){ debugMarkCell(lev, i,j,k ); errMsg("INVRHOCELL_CHECK"," l"<<lev<<" "<< PRINT_IJK<<" rho:"<<rho ); - D::mPanic = 1; + CAUSE_PANIC; } #endif // FSGR_STRICT_DEBUG==1 - D::mNumUsedCells++; + this->mNumUsedCells++; } } @@ -1085,7 +1229,7 @@ LbmFsgrSolver<D>::coarseAdvance(int lev) //errMsg("coarseAdvance","level "<<lev<<" stepped from "<<mLevel[lev].setCurr<<" to "<<mLevel[lev].setOther); - if(!D::mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } + if(!this->mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } // */ // update other set @@ -1107,9 +1251,7 @@ LbmFsgrSolver<D>::coarseAdvance(int lev) // get dfs from level (lev+1) to (lev) coarse border nodes -template<class D> -void -LbmFsgrSolver<D>::coarseRestrictFromFine(int lev) +void LbmFsgrSolver::coarseRestrictFromFine(int lev) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); @@ -1153,7 +1295,7 @@ LbmFsgrSolver<D>::coarseRestrictFromFine(int lev) mNumInterdCells++; coarseRestrictCell(lev, i,j,k,srcSet,dstSet); - D::mNumUsedCells++; + this->mNumUsedCells++; } // from fine & fluid else { if(RFLAG(lev+1, 2*i,2*j,2*k,srcSet) & CFGrFromCoarse) { @@ -1164,13 +1306,11 @@ LbmFsgrSolver<D>::coarseRestrictFromFine(int lev) } } // & fluid }}} - if(!D::mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } + if(!this->mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } #endif //! LBM_NOADCOARSENING==1 } -template<class D> -bool -LbmFsgrSolver<D>::adaptGrid(int lev) { +bool LbmFsgrSolver::adaptGrid(int lev) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); lev =0; // get rid of warnings... @@ -1190,11 +1330,11 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { const int srcFineSet = mLevel[lev+1].setCurr; const bool debugRefinement = false; - // use template functions for 2D/3D - /*if(strstr(D::getName().c_str(),"Debug")) + // use //template functions for 2D/3D + /*if(strstr(this->getName().c_str(),"Debug")) if(lev+1==mMaxRefine) { // mixborder - for(int l=0;((l<D::cDirNum) && (!removeFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + for(int l=0;((l<this->cDirNum) && (!removeFromFine)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; if(RFLAG(lev+1, ni,nj,nk, srcFineSet)&CFBnd) { // NEWREFT removeFromFine=true; } @@ -1226,18 +1366,18 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { RFLAG(lev, i,j,k, dstSet) |= CFGrCoarseInited; // remove later on? FIXME? #endif // FSGR_STRICT_DEBUG==1 //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFEmpty; // FLAGTEST - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); change=true; mNumFsgrChanges++; - for(int l=1; l<D::cDirNum; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; //errMsg("performRefinement","On lev:"<<lev<<" check: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet<<" = "<<convertCellFlagType2String(RFLAG(lev, ni,nj,nk, srcSet)) ); if( ( RFLAG(lev, ni,nj,nk, srcSet)&CFFluid ) && (!(RFLAG(lev, ni,nj,nk, srcSet)&CFGrFromFine)) ) { // dont change status of nb. from fine cells // tag as inited for debugging, cell contains fluid DFs anyway RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromFine|CFGrCoarseInited; //errMsg("performRefinement","On lev:"<<lev<<" set to from fine: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet); - //if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + //if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); } } // l @@ -1272,14 +1412,14 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { // from coarse cells without unused nbs are not necessary...! -> remove bool invNb = false; bool fluidNb = false; - for(int l=1; l<D::cDirNum; l++) { + for(int l=1; l<this->cDirNum; l++) { if(RFLAG_NB(lev, i, j, k, srcSet, l) & CFUnused) { invNb = true; } if(RFLAG_NB(lev, i, j, k, srcSet, l) & (CFGrNorm)) { fluidNb = true; } } if(!invNb) { // no unused cells around -> calculate normally from now on RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); change=true; mNumFsgrChanges++; } // from advance @@ -1287,7 +1427,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { // no fluid cells near -> no transfer necessary RFLAG(lev, i,j,k, dstSet) = CFUnused; //RFLAG(lev, i,j,k, mLevel[lev].setOther) = CFUnused; // FLAGTEST - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); change=true; mNumFsgrChanges++; } // from advance @@ -1300,18 +1440,18 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<lev<<" " <<PRINT_IJK<<" due to finer from coarse cell " ); RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; if(lev>0) RFLAG(lev-1, i/2,j/2,k/2, mLevel[lev-1].setCurr) &= (~CFGrToFine); // TODO add more of these? - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); change=true; mNumFsgrChanges++; - for(int l=1; l<D::cDirNum; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if(RFLAG(lev, ni,nj,nk, srcSet)&(CFGrNorm)) { //ok - for(int m=1; m<D::cDirNum; m++) { - int mi= ni +D::dfVecX[m], mj= nj +D::dfVecY[m], mk= nk +D::dfVecZ[m]; + for(int m=1; m<this->cDirNum; m++) { + int mi= ni +this->dfVecX[m], mj= nj +this->dfVecY[m], mk= nk +this->dfVecZ[m]; if(RFLAG(lev, mi, mj, mk, srcSet)&CFUnused) { // norm cells in neighborhood with unused nbs have to be new border... RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromCoarse; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); } } // these alreay have valid values... @@ -1319,7 +1459,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { else if(RFLAG(lev, ni,nj,nk, srcSet)&(CFUnused)) { //ok // this should work because we have a valid neighborhood here for now interpolateCellFromCoarse(lev, ni, nj, nk, dstSet, interTime, CFFluid|CFGrFromCoarse, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); mNumFsgrChanges++; } } // l @@ -1347,31 +1487,31 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; change=true; mNumFsgrChanges++; - for(int l=1; l<D::cDirNum; l++) { - int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFGrFromCoarse)) { //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); RFLAG(lev+1, bi, bj, bk, srcFineSet) = setf; - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); } else if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFUnused )) { //errMsg("performRefinement","Removing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); interpolateCellFromCoarse(lev+1, bi, bj, bk, srcFineSet, interTime, setf, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); mNumFsgrChanges++; } } - for(int l=1; l<D::cDirNum; l++) { - int bi=(2*i)+D::dfVecX[l], bj=(2*j)+D::dfVecY[l], bk=(2*k)+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; if( (RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFFluid ) && (!(RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFGrFromCoarse)) ) { // all unused nbs now of coarse have to be from coarse - for(int m=1; m<D::cDirNum; m++) { - int mi= bi +D::dfVecX[m], mj= bj +D::dfVecY[m], mk= bk +D::dfVecZ[m]; + for(int m=1; m<this->cDirNum; m++) { + int mi= bi +this->dfVecX[m], mj= bj +this->dfVecY[m], mk= bk +this->dfVecZ[m]; if(RFLAG(lev+1, mi, mj, mk, srcFineSet)&CFUnused) { //errMsg("performRefinement","Changing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(mi,mj,mk) ); interpolateCellFromCoarse(lev+1, mi, mj, mk, srcFineSet, interTime, CFFluid|CFGrFromCoarse, false); - if((D::cDimension==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); mNumFsgrChanges++; } } @@ -1384,11 +1524,11 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { }}} // TEST // PASS 3 */ - if(!D::mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } + if(!this->mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } } // PASS 1-3 // refinement done - //LbmFsgrSolver<D>::performCoarsening(int lev) { + //LbmFsgrSolver::performCoarsening(int lev) { { // PASS 4,5 bool nbsok; // WARNING @@ -1399,7 +1539,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { const bool debugCoarsening = false; // PASS 5 test DEBUG - /*if(D::mInitDone) { + /*if(this->mInitDone) { for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { for(int j=1;j<mLevel[lev].lSizey-1;++j) { for(int i=1;i<mLevel[lev].lSizex-1;++i) { @@ -1416,7 +1556,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { change = true; mNumFsgrChanges++; RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); // same as restr from fine func! not necessary ?! // coarseRestrictFromFine part coarseRestrictCell(lev, i,j,k,srcSet, dstFineSet); @@ -1425,11 +1565,11 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { }}} // TEST! } // PASS 5 */ - // use template functions for 2D/3D - /*if(strstr(D::getName().c_str(),"Debug")) + // use //template functions for 2D/3D + /*if(strstr(this->getName().c_str(),"Debug")) if((nbsok)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l<D::cDirNum) && (nbsok)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + for(int l=0;((l<this->cDirNum) && (nbsok)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT nbsok=false; } @@ -1451,8 +1591,8 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { if(lev+1==mMaxRefine) reqType = CFNoBndFluid; nbsok = true; - for(int l=0; l<D::cDirNum && nbsok; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + for(int l=0; l<this->cDirNum && nbsok; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; if( (RFLAG(lev+1, ni,nj,nk, dstFineSet) & reqType) && (!(RFLAG(lev+1, ni,nj,nk, dstFineSet) & (notAllowed)) ) ){ // ok @@ -1463,8 +1603,8 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { } // dont turn CFGrFromFine above interface cells into CFGrNorm // now check nbs on same level - for(int l=1; l<D::cDirNum && nbsok; l++) { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum && nbsok; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if(RFLAG(lev, ni,nj,nk, srcSet)&(CFFluid)) { //ok } else { nbsok = false; @@ -1477,8 +1617,8 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { mNumFsgrChanges++; RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrNorm; // dfs are already ok... - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); // only check complete cubes for(int dx=-1;dx<=1;dx+=2) { @@ -1504,31 +1644,31 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { mNumFsgrChanges++; RFLAG(dstlev, dstx,dsty,dstz, dstFineSet) = CFUnused; RFLAG(dstlev, dstx,dsty,dstz, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); - for(int l=1; l<D::cDirNum; l++) { - int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFFluid)) { RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; } if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFInter)) { - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); - D::mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); + this->mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; } } // l // again check nb flags of all surrounding cells to see if any from coarse // can be convted to unused - for(int l=1; l<D::cDirNum; l++) { - int dstni=dstx+D::dfVecX[l], dstnj=dsty+D::dfVecY[l], dstnk=dstz+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; // have to be at least from coarse here... //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" "<< convertCellFlagType2String(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)) ); if(!(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFUnused) )) { bool delok = true; // careful long range here... check domain bounds? - for(int m=1; m<D::cDirNum; m++) { - int chkni=dstni+D::dfVecX[m], chknj=dstnj+D::dfVecY[m], chknk=dstnk+D::dfVecZ[m]; + for(int m=1; m<this->cDirNum; m++) { + int chkni=dstni+this->dfVecX[m], chknj=dstnj+this->dfVecY[m], chknk=dstnk+this->dfVecZ[m]; if(RFLAG(dstlev, chkni,chknj,chknk, dstFineSet)&(CFUnused|CFGrFromCoarse)) { // this nb cell is ok for deletion } else { @@ -1541,13 +1681,13 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { mNumFsgrChanges++; RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFUnused; RFLAG(dstlev, dstni,dstnj,dstnk, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); } } } // l // treat subcube //ebugMarkCell(lev,i+dx,j+dy,k+dz); - //if(D::mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); } } } } @@ -1560,13 +1700,13 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { /*if( RFLAG(lev, i,j,k,srcSet) & CFFluid) { if( RFLAG(lev+1, i*2,j*2,k*2,dstFineSet) & CFGrFromCoarse) { LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<D::cDirNum; l++) { - int ni=(2*i)+D::dfVecX[l], nj=(2*j)+D::dfVecY[l], nk=(2*k)+D::dfVecZ[l]; + for(int l=1; l<this->cDirNum; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; if(RFLAG(lev+1, ni,nj,nk, dstFineSet)& (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) ) { - //LbmFloat area = 0.25; if(D::dfVecX[l]!=0) area *= 0.5; if(D::dfVecY[l]!=0) area *= 0.5; if(D::dfVecZ[l]!=0) area *= 0.5; + //LbmFloat area = 0.25; if(this->dfVecX[l]!=0) area *= 0.5; if(this->dfVecY[l]!=0) area *= 0.5; if(this->dfVecZ[l]!=0) area *= 0.5; totArea += mFsgrCellArea[l]; } } // l @@ -1582,15 +1722,15 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { // PASS 5 org - /*if(strstr(D::getName().c_str(),"Debug")) + /*if(strstr(this->getName().c_str(),"Debug")) if((changeToFromFine)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l<D::cDirNum) && (changeToFromFine)); l++) { // FARBORD - int ni=2*i+2*D::dfVecX[l], nj=2*j+2*D::dfVecY[l], nk=2*k+2*D::dfVecZ[l]; + for(int l=0;((l<this->cDirNum) && (changeToFromFine)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT changeToFromFine=false; } } }// FARBORD */ - //if(!D::mInitDone) { + //if(!this->mInitDone) { for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { for(int j=1;j<mLevel[lev].lSizey-1;++j) { for(int i=1;i<mLevel[lev].lSizex-1;++i) { @@ -1615,7 +1755,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { change = true; mNumFsgrChanges++; RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; - if((D::cDimension==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); // same as restr from fine func! not necessary ?! // coarseRestrictFromFine part } @@ -1626,7 +1766,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { // PASS 5 */ } // coarsening, PASS 4,5 - if(!D::mSilent){ errMsg("adaptGrid"," for l"<<lev<<" done " ); } + if(!this->mSilent){ errMsg("adaptGrid"," for l"<<lev<<" done " ); } return change; #endif //! LBM_NOADCOARSENING==1 } @@ -1635,9 +1775,7 @@ LbmFsgrSolver<D>::adaptGrid(int lev) { //! cell restriction and prolongation /*****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int dstSet) +void LbmFsgrSolver::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int dstSet) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); @@ -1666,8 +1804,8 @@ LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int # if OPT3D==0 // add up weighted dfs FORDF0{ df[l] = 0.0;} - for(int n=0;(n<D::cDirNum); n++) { - int ni=2*i+1*D::dfVecX[n], nj=2*j+1*D::dfVecY[n], nk=2*k+1*D::dfVecZ[n]; + for(int n=0;(n<this->cDirNum); n++) { + int ni=2*i+1*this->dfVecX[n], nj=2*j+1*this->dfVecY[n], nk=2*k+1*this->dfVecZ[n]; ccel = RACPNT(lev+1, ni,nj,nk,srcSet);// CFINTTEST const LbmFloat weight = mGaussw[n]; FORDF0{ @@ -1685,21 +1823,21 @@ LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int FORDF0{ LbmFloat cdf = df[l]; rho += cdf; - ux += (D::dfDvecX[l]*cdf); - uy += (D::dfDvecY[l]*cdf); - uz += (D::dfDvecZ[l]*cdf); + ux += (this->dfDvecX[l]*cdf); + uy += (this->dfDvecY[l]*cdf); + uz += (this->dfDvecZ[l]*cdf); } - FORDF0{ feq[l] = D::getCollideEq(l, rho,ux,uy,uz); } + FORDF0{ feq[l] = this->getCollideEq(l, rho,ux,uy,uz); } if(mLevel[lev ].lcsmago>0.0) { - const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feq); - omegaDst = D::getLesOmega(mLevel[lev ].omega,mLevel[lev ].lcsmago,Qo); - omegaSrc = D::getLesOmega(mLevel[lev+1].omega,mLevel[lev+1].lcsmago,Qo); + const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feq); + omegaDst = this->getLesOmega(mLevel[lev ].omega,mLevel[lev ].lcsmago,Qo); + omegaSrc = this->getLesOmega(mLevel[lev+1].omega,mLevel[lev+1].lcsmago,Qo); } else { omegaDst = mLevel[lev+0].omega; /* NEWSMAGOT*/ omegaSrc = mLevel[lev+1].omega; } - dfScale = (mLevel[lev ].stepsize/mLevel[lev+1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); // yu + dfScale = (mLevel[lev ].timestep/mLevel[lev+1].timestep)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); // yu FORDF0{ RAC(tcel, l) = feq[l]+ (df[l]-feq[l])*dfScale; } @@ -1726,8 +1864,8 @@ LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int MSRC_EB = CCELG_EB(0); MSRC_WT = CCELG_WT(0); MSRC_WB = CCELG_WB(0); - for(int n=1;(n<D::cDirNum); n++) { - ccel = RACPNT(lev+1, 2*i+1*D::dfVecX[n], 2*j+1*D::dfVecY[n], 2*k+1*D::dfVecZ[n] ,srcSet); + for(int n=1;(n<this->cDirNum); n++) { + ccel = RACPNT(lev+1, 2*i+1*this->dfVecX[n], 2*j+1*this->dfVecY[n], 2*k+1*this->dfVecZ[n] ,srcSet); MSRC_C += CCELG_C(n) ; MSRC_N += CCELG_N(n) ; MSRC_S += CCELG_S(n) ; @@ -1765,7 +1903,7 @@ LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ COLL_CALCULATE_CSMOMEGAVAL(lev+1, lcsmSrcOmega); \ \ - lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev+1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ + lcsmdfscale = (mLevel[lev+0].timestep/mLevel[lev+1].timestep)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ RAC(tcel, dC ) = (lcsmeq[dC ] + (MSRC_C -lcsmeq[dC ] )*lcsmdfscale); RAC(tcel, dN ) = (lcsmeq[dN ] + (MSRC_N -lcsmeq[dN ] )*lcsmdfscale); RAC(tcel, dS ) = (lcsmeq[dS ] + (MSRC_S -lcsmeq[dS ] )*lcsmdfscale); @@ -1789,8 +1927,7 @@ LbmFsgrSolver<D>::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int #endif //! LBM_NOADCOARSENING==1 } -template<class D> -void LbmFsgrSolver<D>::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { +void LbmFsgrSolver::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { #if LBM_NOADCOARSENING==1 if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); i=j=k=dstSet=lev =0; // get rid of warnings... @@ -1811,7 +1948,7 @@ void LbmFsgrSolver<D>::interpolateCellFromCoarse(int lev, int i, int j,int k, in // this is not necessary for interpolateFineFromCoarse if(markNbs) { FORDF1{ - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if(RFLAG(lev,ni,nj,nk,dstSet)&CFUnused) { // parents have to be inited! interpolateCellFromCoarse(lev, ni, nj, nk, dstSet, t, CFFluid|CFGrFromCoarse, false); @@ -1871,7 +2008,7 @@ void LbmFsgrSolver<D>::interpolateCellFromCoarse(int lev, int i, int j,int k, in ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2)+1, t, WO1D3); } else { - D::mPanic=1; + CAUSE_PANIC; errFatal("interpolateCellFromCoarse","Invalid!?", SIMWORLD_GENERICERROR); } @@ -1883,70 +2020,74 @@ void LbmFsgrSolver<D>::interpolateCellFromCoarse(int lev, int i, int j,int k, in /*****************************************************************************/ -/*! perform a single LBM step */ +/*! change the size of the LBM time step */ /*****************************************************************************/ -template<class D> -void -LbmFsgrSolver<D>::adaptTimestep() -{ +void LbmFsgrSolver::adaptTimestep() { LbmFloat massTOld=0.0, massTNew=0.0; LbmFloat volTOld=0.0, volTNew=0.0; bool rescale = false; // do any rescale at all? LbmFloat scaleFac = -1.0; // timestep scaling + if(this->mPanic) return; LbmFloat levOldOmega[FSGR_MAXNOOFLEVELS]; LbmFloat levOldStepsize[FSGR_MAXNOOFLEVELS]; for(int lev=mMaxRefine; lev>=0 ; lev--) { levOldOmega[lev] = mLevel[lev].omega; - levOldStepsize[lev] = mLevel[lev].stepsize; + levOldStepsize[lev] = mLevel[lev].timestep; } //if(mTimeSwitchCounts>0){ errMsg("DEB CSKIP",""); return; } // DEBUG LbmFloat fac = 0.8; // modify time step by 20%, TODO? do multiple times for large changes? LbmFloat diffPercent = 0.05; // dont scale if less than 5% - LbmFloat allowMax = D::mpParam->getTadapMaxSpeed(); // maximum allowed velocity - LbmFloat nextmax = D::mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); - - //newdt = D::mpParam->getStepTime() * (allowMax/nextmax); - LbmFloat newdt = D::mpParam->getStepTime(); // newtr - if(nextmax>allowMax/fac) { - newdt = D::mpParam->getStepTime() * fac; + LbmFloat allowMax = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity + LbmFloat nextmax = this->mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); + + //newdt = this->mpParam->getTimestep() * (allowMax/nextmax); + LbmFloat newdt = this->mpParam->getTimestep(); // newtr + if(nextmax > allowMax/fac) { + mTimeMaxvelStepCnt++; } + else { mTimeMaxvelStepCnt=0; } + + // emergency, or 10 steps with high vel + if((mTimeMaxvelStepCnt>5) || (nextmax> (1.0/3.0) ) ) { + //if(nextmax > allowMax/fac) { + newdt = this->mpParam->getTimestep() * fac; } else { if(nextmax<allowMax*fac) { - newdt = D::mpParam->getStepTime() / fac; + newdt = this->mpParam->getTimestep() / fac; } } // newtr - //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<fac<<" simmaxv="<< D::mpParam->getSimulationMaxSpeed() ); + //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<fac<<" simmaxv="<< this->mpParam->getSimulationMaxSpeed() ); bool minCutoff = false; LbmFloat desireddt = newdt; - if(newdt>D::mpParam->getMaxStepTime()){ newdt = D::mpParam->getMaxStepTime(); } - if(newdt<D::mpParam->getMinStepTime()){ - newdt = D::mpParam->getMinStepTime(); + if(newdt>this->mpParam->getMaxTimestep()){ newdt = this->mpParam->getMaxTimestep(); } + if(newdt<this->mpParam->getMinTimestep()){ + newdt = this->mpParam->getMinTimestep(); if(nextmax>allowMax/fac){ minCutoff=true; } // only if really large vels... } - LbmFloat dtdiff = fabs(newdt - D::mpParam->getStepTime()); - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<D::mpParam->getMaxStepTime()<<" min"<<D::mpParam->getMinStepTime()<<" diff"<<dtdiff<< - " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxStepTime)<<" maxsteps:"<<(mSimulationTime/mMinStepTime) , 10); } + LbmFloat dtdiff = fabs(newdt - this->mpParam->getTimestep()); + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<this->mpParam->getMaxTimestep()<<" min"<<this->mpParam->getMinTimestep()<<" diff"<<dtdiff<< + " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxTimestep)<<" maxsteps:"<<(mSimulationTime/mMinTimestep) , 10); } // in range, and more than X% change? - //if( newdt < D::mpParam->getStepTime() ) // DEBUG + //if( newdt < this->mpParam->getTimestep() ) // DEBUG LbmFloat rhoAvg = mCurrentMass/mCurrentVolume; - if( (newdt<=D::mpParam->getMaxStepTime()) && (newdt>=D::mpParam->getMinStepTime()) - && (dtdiff>(D::mpParam->getStepTime()*diffPercent)) ) { + if( (newdt<=this->mpParam->getMaxTimestep()) && (newdt>=this->mpParam->getMinTimestep()) + && (dtdiff>(this->mpParam->getTimestep()*diffPercent)) ) { if((newdt>levOldStepsize[mMaxRefine])&&(mTimestepReduceLock)) { // wait some more... //debMsgNnl("LbmFsgrSolver::TAdp",DM_NOTIFY," Delayed... "<<mTimestepReduceLock<<" ",10); debMsgDirect("D"); } else { - D::mpParam->setDesiredStepTime( newdt ); + this->mpParam->setDesiredTimestep( newdt ); rescale = true; - if(!D::mSilent) { + if(!this->mSilent) { debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"\n\n\n\n",10); - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<<newdt<<" old="<<D::mpParam->getStepTime()<<" maxSpeed:"<<D::mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<D::mStepCnt, 10 ); + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<<newdt<<" old="<<this->mpParam->getTimestep()<<" maxSpeed:"<<this->mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<this->mStepCnt, 10 ); debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10); } @@ -1956,22 +2097,21 @@ LbmFsgrSolver<D>::adaptTimestep() if(mTimestepReduceLock>0) mTimestepReduceLock--; - /* // forced back and forth switchting (for testing) - const int tadtogInter = 300; + /*const int tadtogInter = 100; const double tadtogSwitch = 0.66; errMsg("TIMESWITCHTOGGLETEST","warning enabled "<< tadtogSwitch<<","<<tadtogSwitch<<" !!!!!!!!!!!!!!!!!!!"); - if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || - ((D::mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ + if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || + ((this->mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ rescale = true; minCutoff = false; - newdt = tadtogSwitch * D::mpParam->getStepTime(); - D::mpParam->setDesiredStepTime( newdt ); + newdt = tadtogSwitch * this->mpParam->getTimestep(); + this->mpParam->setDesiredTimestep( newdt ); } else - if( ((D::mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || - ((D::mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ + if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || + ((this->mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ rescale = true; minCutoff = false; - newdt = D::mpParam->getStepTime()/tadtogSwitch ; - D::mpParam->setDesiredStepTime( newdt ); + newdt = this->mpParam->getTimestep()/tadtogSwitch ; + this->mpParam->setDesiredTimestep( newdt ); } else { rescale = false; minCutoff = false; } @@ -1979,36 +2119,62 @@ LbmFsgrSolver<D>::adaptTimestep() // test mass rescale - scaleFac = newdt/D::mpParam->getStepTime(); + scaleFac = newdt/this->mpParam->getTimestep(); if(rescale) { - // fixme - warum y, wird jetzt gemittelt... + // perform acutal rescaling... + mTimeMaxvelStepCnt=0; + + // FIXME - approximate by averaging, take gravity direction here? mTimestepReduceLock = 4*(mLevel[mMaxRefine].lSizey+mLevel[mMaxRefine].lSizez+mLevel[mMaxRefine].lSizex)/3; mTimeSwitchCounts++; - D::mpParam->calculateAllMissingValues( D::mSilent ); + this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent ); recalculateObjectSpeeds(); // calc omega, force for all levels mLastOmega=1e10; mLastGravity=1e10; initLevelOmegas(); - if(D::mpParam->getStepTime()<mMinStepTime) mMinStepTime = D::mpParam->getStepTime(); - if(D::mpParam->getStepTime()>mMaxStepTime) mMaxStepTime = D::mpParam->getStepTime(); - + if(this->mpParam->getTimestep()<mMinTimestep) mMinTimestep = this->mpParam->getTimestep(); + if(this->mpParam->getTimestep()>mMaxTimestep) mMaxTimestep = this->mpParam->getTimestep(); + + // this might be called during init, before we have any particles + if(mpParticles) { mpParticles->adaptPartTimestep(scaleFac); } +#if LBM_INCLUDE_TESTSOLVERS==1 + if((mUseTestdata)&&(mpTest)) { + mpTest->adaptTimestep(scaleFac, mLevel[mMaxRefine].omega, mLevel[mMaxRefine].timestep, vec2L( mpParam->calculateGravity(mSimulationTime)) ); + } +#endif // LBM_INCLUDE_TESTSOLVERS!=1 + for(int lev=mMaxRefine; lev>=0 ; lev--) { - LbmFloat newSteptime = mLevel[lev].stepsize; + LbmFloat newSteptime = mLevel[lev].timestep; LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); - if(!D::mSilent) { + if(!this->mSilent) { debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<<lev<<" Timestep change: "<< " scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10); } if(lev!=mMaxRefine) coarseCalculateFluxareas(lev); int wss = 0, wse = 1; - // FIXME always currset!? + // only change currset (necessary for compressed grids, better for non-compr.gr.) wss = wse = mLevel[lev].setCurr; for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT // warning - check sets for higher levels...? FSGR_FORIJK1(lev) { + if( (RFLAG(lev,i,j,k, workSet) & CFBndMoving) ) { + /* + // paranoid check - shouldnt be necessary! + if(QCELL(lev, i, j, k, workSet, dFlux)!=mSimulationTime) { + errMsg("TTTT","found invalid bnd cell.... removing at "<<PRINT_IJK); + RFLAG(lev,i,j,k, workSet) = CFInter; + // init empty zero vel interface cell... + initVelocityCell(lev, i,j,k, CFInter, 1.0, 0.01, LbmVec(0.) ); + } else {// */ + for(int l=0; l<this->cDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = QCELL(lev, i, j, k, workSet, l)* scaleFac; + } + //} // ok + continue; + } if( (RFLAG(lev,i,j,k, workSet) & CFFluid) || (RFLAG(lev,i,j,k, workSet) & CFInter) || @@ -2026,12 +2192,12 @@ LbmFsgrSolver<D>::adaptTimestep() LbmVec velOld; LbmFloat rho, ux,uy,uz; rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l<D::cDfNum; l++) { + for(int l=0; l<this->cDfNum; l++) { LbmFloat m = QCELL(lev, i, j, k, workSet, l); rho += m; - ux += (D::dfDvecX[l]*m); - uy += (D::dfDvecY[l]*m); - uz += (D::dfDvecZ[l]*m); + ux += (this->dfDvecX[l]*m); + uy += (this->dfDvecY[l]*m); + uz += (this->dfDvecZ[l]*m); } rhoOld = rho; velOld = LbmVec(ux,uy,uz); @@ -2042,21 +2208,21 @@ LbmFsgrSolver<D>::adaptTimestep() LbmFloat df[LBM_DFNUM]; LbmFloat feqOld[LBM_DFNUM]; LbmFloat feqNew[LBM_DFNUM]; - for(int l=0; l<D::cDfNum; l++) { - feqOld[l] = D::getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); - feqNew[l] = D::getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); + for(int l=0; l<this->cDfNum; l++) { + feqOld[l] = this->getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); + feqNew[l] = this->getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); df[l] = QCELL(lev, i,j,k,workSet, l); } - const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feqOld); - const LbmFloat oldOmega = D::getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); - const LbmFloat newOmega = D::getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); + const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feqOld); + const LbmFloat oldOmega = this->getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); + const LbmFloat newOmega = this->getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); //newOmega = mLevel[lev].omega; // FIXME debug test //LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); const LbmFloat dfScale = (newSteptime/newOmega)/(levOldStepsize[lev]/oldOmega); //dfScale = dfScaleFac/newOmega; - for(int l=0; l<D::cDfNum; l++) { + for(int l=0; l<this->cDfNum; l++) { // org scaling //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important // new scaling @@ -2100,21 +2266,22 @@ LbmFsgrSolver<D>::adaptTimestep() } // lev - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<D::mStepCnt<< - " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxStepTime<< - " mindt"<<mMinStepTime<<" currdt"<<mLevel[mMaxRefine].stepsize, 10); + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<this->mStepCnt<< + " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxTimestep<< + " mindt"<<mMinTimestep<<" currdt"<<mLevel[mMaxRefine].timestep, 10); debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE masst:"<<massTNew<<","<<massTOld<<" org:"<<mCurrentMass<<"; "<< " volt:"<<volTNew<<","<<volTOld<<" org:"<<mCurrentVolume, 10); } else { debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep change by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt - <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<D::mOmega<<" gStar:"<<D::mpParam->getCurrentGStar() , 10); + <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<this->mOmega<<" gStar:"<<this->mpParam->getCurrentGStar() , 10); } } // rescale? + //NEWDEBCHECK("tt2"); //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG if(minCutoff) { - errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<D::mName<<" step:"<<D::mStepCnt<<" newdt="<<desireddt<<" mindt="<<D::mpParam->getMinStepTime()<<") " ); + errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<this->mName<<" step:"<<this->mStepCnt<<" newdt="<<desireddt<<" mindt="<<this->mpParam->getMinTimestep()<<") " ); //brute force resacle all the time? for(int lev=mMaxRefine; lev>=0 ; lev--) { @@ -2143,12 +2310,12 @@ LbmFsgrSolver<D>::adaptTimestep() // collide on current set LbmFloat rho, ux,uy,uz; rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l<D::cDfNum; l++) { + for(int l=0; l<this->cDfNum; l++) { LbmFloat m = QCELL(lev, i, j, k, workSet, l); rho += m; - ux += (D::dfDvecX[l]*m); - uy += (D::dfDvecY[l]*m); - uz += (D::dfDvecZ[l]*m); + ux += (this->dfDvecX[l]*m); + uy += (this->dfDvecY[l]*m); + uz += (this->dfDvecZ[l]*m); } #ifndef WIN32 if (!finite(rho)) { @@ -2165,8 +2332,8 @@ LbmFsgrSolver<D>::adaptTimestep() ux *= cfac; uy *= cfac; uz *= cfac; - for(int l=0; l<D::cDfNum; l++) { - QCELL(lev, i, j, k, workSet, l) = D::getCollideEq(l, rho, ux,uy,uz); } + for(int l=0; l<this->cDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = this->getCollideEq(l, rho, ux,uy,uz); } rescs++; debMsgDirect("B"); } @@ -2189,9 +2356,7 @@ LbmFsgrSolver<D>::adaptTimestep() * work on lists from updateCellMass to reinit cell flags *****************************************************************************/ -template<class D> -LbmFloat -LbmFsgrSolver<D>::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l) { +LbmFloat LbmFsgrSolver::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l) { //return 0.0; // test int level = mMaxRefine; LbmFloat *ccel = RACPNT(level, i,j,k, workSet); @@ -2226,8 +2391,7 @@ LbmFsgrSolver<D>::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, in return ret; } -template<class D> -void LbmFsgrSolver<D>::addToNewInterList( int ni, int nj, int nk ) { +void LbmFsgrSolver::addToNewInterList( int ni, int nj, int nk ) { #if FSGR_STRICT_DEBUG==10 // dangerous, this can change the simulation... /*for( vector<LbmPoint>::iterator iter=mListNewInter.begin(); @@ -2245,20 +2409,14 @@ void LbmFsgrSolver<D>::addToNewInterList( int ni, int nj, int nk ) { mListNewInter.push_back(newinter); } -template<class D> -void LbmFsgrSolver<D>::reinitFlags( int workSet ) -{ +void LbmFsgrSolver::reinitFlags( int workSet ) { // OLD mods: // add all to intel list? // check ffrac for new cells // new if cell inits (last loop) // vweights handling -#if ELBEEM_PLUGIN==1 - const int debugFlagreinit = 0; -#else // ELBEEM_PLUGIN==1 const int debugFlagreinit = 0; -#endif // ELBEEM_PLUGIN==1 // some things need to be read/modified on the other set int otherSet = (workSet^1); @@ -2278,66 +2436,39 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) int i=iter->x, j=iter->y, k=iter->z; if(debugFlagreinit) errMsg("FULL", PRINT_IJK<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<< QCELL(workLev, i,j,k, workSet, 0) ); // DEBUG SYMM FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + //if((LBMDIM>2)&&( (ni<=0) || (nj<=0) || (nk<=0) || (ni>=mLevel[workLev].lSizex-1) || (nj>=mLevel[workLev].lSizey-1) || (nk>=mLevel[workLev].lSizez-1) )) { + if( (ni<=0) || (nj<=0) || + (ni>=mLevel[workLev].lSizex-1) || + (nj>=mLevel[workLev].lSizey-1) +# if LBMDIM==3 + || (nk<=0) || (nk>=mLevel[workLev].lSizez-1) +# endif // LBMDIM==1 + ) { + continue; } // new bc, dont treat cells on boundary NEWBC if( RFLAG(workLev, ni,nj,nk, workSet) & CFEmpty ){ - // new and empty interface cell, dont change old flag here! - addToNewInterList(ni,nj,nk); // preinit speed, get from average surrounding cells // interpolate from non-workset to workset, sets are handled in function - { - // WARNING - other i,j,k than filling cell! - int ei=ni; int ej=nj; int ek=nk; - LbmFloat avgrho = 0.0; - LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; - LbmFloat cellcnt = 0.0; - LbmFloat avgnbdf[LBM_DFNUM]; - FORDF0M { avgnbdf[m]= 0.0; } - - for(int nbl=1; nbl< D::cDfNum ; ++nbl) { - if( (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFFluid) || - ((!(RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) && - (RFLAG_NB(workLev,ei,ej,ek,workSet,nbl) & CFInter) )) { - cellcnt += 1.0; - for(int rl=0; rl< D::cDfNum ; ++rl) { - LbmFloat nbdf = QCELL_NB(workLev,ei,ej,ek, workSet,nbl, rl); - avgnbdf[rl] += nbdf; - avgux += (D::dfDvecX[rl]*nbdf); - avguy += (D::dfDvecY[rl]*nbdf); - avguz += (D::dfDvecZ[rl]*nbdf); - avgrho += nbdf; - } - } - } - if(cellcnt<=0.0) { - // no nbs? just use eq. - //FORDF0 { QCELL(workLev,ei,ej,ek, workSet, l) = D::dfEquil[l]; } - avgrho = 1.0; - avgux = avguy = avguz = 0.0; - //TTT mNumProblems++; -#if ELBEEM_PLUGIN!=1 - D::mPanic=1; errFatal("NYI2","cellcnt<=0.0",SIMWORLD_GENERICERROR); -#endif // ELBEEM_PLUGIN - } else { - // init speed - avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; - avgrho /= cellcnt; - FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? - } + // new and empty interface cell, dont change old flag here! + addToNewInterList(ni,nj,nk); - // careful with l's... - FORDF0M { - QCELL(workLev,ei,ej,ek, workSet, m) = D::getCollideEq( m,avgrho, avgux, avguy, avguz ); - //QCELL(workLev,ei,ej,ek, workSet, l) = avgnbdf[l]; // CHECK FIXME test? - } - //errMsg("FNEW", PRINT_VEC(ei,ej,ek)<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<<avgrho<<" vel"<<PRINT_VEC(avgux,avguy,avguz) ); // DEBUG SYMM - QCELL(workLev,ei,ej,ek, workSet, dMass) = 0.0; //?? new - QCELL(workLev,ei,ej,ek, workSet, dFfrac) = 0.0; //?? new - //RFLAG(workLev,ei,ej,ek,workSet) = (CellFlagType)(CFInter|CFNoInterpolSrc); - changeFlag(workLev,ei,ej,ek,workSet, (CFInter|CFNoInterpolSrc)); - if(debugFlagreinit) errMsg("NEWE", PRINT_IJK<<" newif "<<PRINT_VEC(ei,ej,ek)<<" rho"<<avgrho<<" vel("<<avgux<<","<<avguy<<","<<avguz<<") " ); - } + LbmFloat avgrho = 0.0; + LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0; + interpolateCellValues(workLev,ni,nj,nk,workSet, avgrho,avgux,avguy,avguz); + + // careful with l's... + FORDF0M { + QCELL(workLev,ni,nj,nk, workSet, m) = this->getCollideEq( m,avgrho, avgux, avguy, avguz ); + //QCELL(workLev,ni,nj,nk, workSet, l) = avgnbdf[l]; // CHECK FIXME test? + } + //errMsg("FNEW", PRINT_VEC(ni,nj,nk)<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" rho"<<avgrho<<" vel"<<PRINT_VEC(avgux,avguy,avguz) ); // DEBUG SYMM + QCELL(workLev,ni,nj,nk, workSet, dMass) = 0.0; //?? new + QCELL(workLev,ni,nj,nk, workSet, dFfrac) = 0.0; //?? new + //RFLAG(workLev,ni,nj,nk,workSet) = (CellFlagType)(CFInter|CFNoInterpolSrc); + changeFlag(workLev,ni,nj,nk,workSet, (CFInter|CFNoInterpolSrc)); + if(debugFlagreinit) errMsg("NEWE", PRINT_IJK<<" newif "<<PRINT_VEC(ni,nj,nk)<<" rho"<<avgrho<<" vel("<<avgux<<","<<avguy<<","<<avguz<<") " ); } /* prevent surrounding interface cells from getting removed as empty cells * (also cells that are not newly inited) */ @@ -2381,14 +2512,14 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) /* set surrounding fluid cells to interface cells */ FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFFluid){ // init fluid->interface //RFLAG(workLev,ni,nj,nk, workSet) = (CellFlagType)(CFInter); changeFlag(workLev,ni,nj,nk, workSet, CFInter); /* new mass = current density */ LbmFloat nbrho = QCELL(workLev,ni,nj,nk, workSet, dC); - for(int rl=1; rl< D::cDfNum ; ++rl) { nbrho += QCELL(workLev,ni,nj,nk, workSet, rl); } + for(int rl=1; rl< this->cDfNum ; ++rl) { nbrho += QCELL(workLev,ni,nj,nk, workSet, rl); } QCELL(workLev,ni,nj,nk, workSet, dMass) = nbrho; QCELL(workLev,ni,nj,nk, workSet, dFfrac) = 1.0; @@ -2421,7 +2552,7 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) int i=iter->x, j=iter->y, k=iter->z; nbCount = 0; nbTotWeights = 0.0; FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { nbCount++; nbWeights[l] = getMassdWeight(1,i,j,k,workSet,l); @@ -2445,7 +2576,7 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) int i=iter->x, j=iter->y, k=iter->z; nbCount = 0; nbTotWeights = 0.0; FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { nbCount++; nbWeights[l] = getMassdWeight(0,i,j,k,workSet,l); @@ -2479,12 +2610,11 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) /*int nbCount = 0; LbmFloat nbWeights[LBM_DFNUM]; FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { nbCount++; nbWeights[l] = vWeights[weightIndex].val[l]; - } else { - } + } else { } }*/ //errMsg("FDIST", PRINT_IJK<<" mss"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM @@ -2492,7 +2622,7 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("FF I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { LbmFloat change = -1.0; if(nbTotWeightsp>0.0) { @@ -2507,9 +2637,9 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) massChange = 0.0; } else { // Problem! no interface neighbors - D::mFixMass += massChange; + this->mFixMass += massChange; //TTT mNumProblems++; - //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<<D::mFixMass); + //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<<this->mFixMass); } weightIndex++; @@ -2531,7 +2661,7 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) /*int nbCount = 0; LbmFloat nbWeights[LBM_DFNUM]; FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { nbCount++; nbWeights[l] = vWeights[weightIndex].val[l]; @@ -2546,7 +2676,7 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("EE I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); FORDF1 { - int ni=i+D::dfVecX[l], nj=j+D::dfVecY[l], nk=k+D::dfVecZ[l]; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; if( RFLAG(workLev,ni,nj,nk, workSet) & CFInter) { LbmFloat change = -1.0; if(nbTotWeightsp>0.0) { @@ -2560,9 +2690,9 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) massChange = 0.0; } else { // Problem! no interface neighbors - D::mFixMass += massChange; + this->mFixMass += massChange; //TTT mNumProblems++; - //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<<D::mFixMass); + //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<<this->mFixMass); } weightIndex++; @@ -2602,12 +2732,18 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) for( vector<LbmPoint>::iterator iter=mListNewInter.begin(); iter != mListNewInter.end(); iter++ ) { int i=iter->x, j=iter->y, k=iter->z; + if((i<=0) || (j<=0) || + (i>=mLevel[workLev].lSizex-1) || + (j>=mLevel[workLev].lSizey-1) || + ((LBMDIM==3) && ((k<=0) || (k>=mLevel[workLev].lSizez-1) ) ) + ) { + continue; } // new bc, dont treat cells on boundary NEWBC if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { //errMsg("???"," "<<PRINT_IJK); continue; - } + } // */ - QCELL(workLev,i,j,k, workSet, dMass) += (D::mFixMass * newIfFac); + QCELL(workLev,i,j,k, workSet, dMass) += (this->mFixMass * newIfFac); int nbored = 0; FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); } @@ -2634,8 +2770,8 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) } if(mListNewInter.size()>0){ - //errMsg("FixMassDisted"," fm:"<<D::mFixMass<<" nif:"<<mListNewInter.size() ); - D::mFixMass = 0.0; + //errMsg("FixMassDisted"," fm:"<<this->mFixMass<<" nif:"<<mListNewInter.size() ); + this->mFixMass = 0.0; } // empty lists for next step @@ -2649,42 +2785,6 @@ void LbmFsgrSolver<D>::reinitFlags( int workSet ) * instantiation *****************************************************************************/ -// ugly workaround for multiple definitions -// of template instatiations for macs... compile -// everything in one file again -#if defined(__APPLE_CC__) || (defined __INTEL_COMPILER) -#define LBM_FORCEINCLUDE -#include "solver_init.cpp" -#include "solver_util.cpp" -#undef LBM_FORCEINCLUDE -#endif // defined(__APPLE_CC__) - //! lbm factory functions -LbmSolverInterface* createSolver() { -#if LBMDIM==2 - return new LbmFsgrSolver< LbmBGK2D >(); -#endif // LBMDIM==2 -#if LBMDIM==3 - return new LbmFsgrSolver< LbmBGK3D >(); -#endif // LBMDIM==3 - return NULL; -} - - -#ifndef LBM_INSTANTIATE -#if LBMDIM==2 -#define LBM_INSTANTIATE LbmBGK2D -#endif // LBMDIM==2 -#if LBMDIM==3 -#define LBM_INSTANTIATE LbmBGK3D -#endif // LBMDIM==3 -#endif // LBM_INSTANTIATE - -template class LbmFsgrSolver< LBM_INSTANTIATE >; -// the intel compiler is too smart - so the virtual functions called from other cpp -// files have to be instantiated explcitly (otherwise this will cause undefined -// references to "non virtual thunks") ... still not working, though -//template<class LBM_INSTANTIATE> string LbmFsgrSolver<LBM_INSTANTIATE>::getIdString(); -//template<class LBM_INSTANTIATE> void LbmFsgrSolver<LBM_INSTANTIATE>::step(); - +LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); } diff --git a/intern/elbeem/intern/solver_relax.h b/intern/elbeem/intern/solver_relax.h index b2c2fcbe7cc..bc027655be0 100644 --- a/intern/elbeem/intern/solver_relax.h +++ b/intern/elbeem/intern/solver_relax.h @@ -9,7 +9,111 @@ * *****************************************************************************/ +#if FSGR_STRICT_DEBUG==1 +#define CAUSE_PANIC { this->mPanic=1; /* *((int*)(0x0)) = 1; crash*/ } +#else // FSGR_STRICT_DEBUG==1 +#define CAUSE_PANIC { this->mPanic=1; } /*set flag*/ +#endif // FSGR_STRICT_DEBUG==1 + + + +#if LBM_INCLUDE_TESTSOLVERS!=1 + +// off for non testing +#define PRECOLLIDE_MODS(rho,ux,uy,uz) + +#else // LBM_INCLUDE_TESTSOLVERS!=1 +#define PRECOLLIDE_GETPOS \ + LbmVec( \ + ((this->mvGeoEnd[0]-this->mvGeoStart[0])/(LbmFloat)this->mSizex) * (LbmFloat)i + this->mvGeoStart[0], \ + ((this->mvGeoEnd[1]-this->mvGeoStart[1])/(LbmFloat)this->mSizey) * (LbmFloat)j + this->mvGeoStart[1], \ + ((this->mvGeoEnd[2]-this->mvGeoStart[2])/(LbmFloat)this->mSizez) * (LbmFloat)k + this->mvGeoStart[2] \ + ) + +// debug modifications of collide vars (testing) +#define PRECOLLIDE_MODS(rho,ux,uy,uz) \ + if( (this->mTForceStrength>0.) && (RFLAG(0,i,j,k, mLevel[0].setCurr)&CFNoBndFluid) ) { \ + LbmVec pos = PRECOLLIDE_GETPOS; \ + LbmVec vel(ux,uy,uz); \ + mpTest->mControlParts.modifyVelocity(pos,vel); /* */\ + if((i==16)&&(j==10)){ /*debugMarkCell(0,16,10,0);*/ errMsg("FTDEB"," at "<<PRINT_IJK<<" targ:"<<vel<<",len:"<<norm(vel)<<", org:"<<ntlVec3Gfx(ux,uy,uz) ); }\ + ux = vel[0]; uy=vel[1]; uz=vel[2]; \ + /* test acutal values...? */ \ + } + /* end PRECOLLIDE_MODS */ + +// debug modifications of collide vars (testing) +#define _PRECOLLIDE_MODS(rho,ux,uy,uz) \ + if(this->mTForceStrength>0.) { \ + LbmVec u(ux,uy,uz); \ + LbmVec pos = PRECOLLIDE_GETPOS; \ + LbmVec targv = u; const int lev=0; \ + mpTest->mControlParts.modifyVelocity(pos,targv); /* */\ + LbmVec devia = (targv-u); \ + LbmVec set; \ + set = u + (devia/this->mOmega) * this->mTForceStrength; /* */\ + set = u + targv*this->mTForceStrength; /* */\ + ux = set[0]; uy=set[1]; uz=set[2]; \ + if(j==10){ errMsg("FTDEB"," at "<<PRINT_IJK<<" targ"<<targv<<","<<norm(targv)<<" set:"<<set<<","<<norm(set) ); }\ + } + /* end PRECOLLIDE_MODS */ + +#endif // LBM_INCLUDE_TESTSOLVERS!=1 + +/* + + \ + if((0) && (j>=0.01*this->mSizey) && (j<0.9*this->mSizey)) { \ + if((1) && (i>=0.5*this->mSizex) && (i<0.6*this->mSizex)) { \ + LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \ + LbmVec u(ux,uy,uz); LbmVec t(1., 0., 0.); \ + ux = len*t[0]; uy=len*t[1]; uz=len*t[2]; \ + } \ + if((1) && (i>=0.65*this->mSizex) && (i<0.75*this->mSizex)) { \ + LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \ + LbmVec u(ux,uy,uz); LbmVec t(0., 1., 0.); \ + ux = len*t[0]; uy=len*t[1]; uz=len*t[2]; \ + } \ + } \ + \ + if((0) && (j>=0.0*this->mSizey) && (j<1.0 *this->mSizey)) { \ + if((1) && (i>=0.6 *this->mSizex) && (i<0.7 *this->mSizex)) { \ + LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \ + LbmVec u(ux,uy,uz); \ + LbmVec t(0., 1., 0.); \ + LbmFloat devia = norm(u-t); \ + // 0.0001-strong, 0.000001-small, + t = u - (devia/this->mOmega) * this->mTForceStrength; \ + // ux = len*t[0]; uy=len*t[1]; uz=len*t[2]; + ux = t[0]; uy=t[1]; uz=t[2]; \ + //ux= uy= uz= 0.0; + //errMsg("DDDD"," at "<<PRINT_IJK); + } \ + } \ + if(0) { \ + LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \ + LbmVec u(ux,uy,uz); \ + LbmVec p(i/(LbmFloat)this->mSizex, j/(LbmFloat)this->mSizey, k/(LbmFloat)this->mSizez); \ + LbmVec cp(0.5, 0.5, 0.5); \ + LbmVec delt = cp - p; \ + LbmFloat dist = norm(delt); \ + normalize(delt); \ + LbmVec tang = cross(delt, LbmVec(0.,0.,1.)); \ + normalize(tang); \ + const LbmFloat falloff = 5.0; \ + LbmVec targv = tang*1.0 * 1.0/(1.0+falloff*dist); \ + LbmVec devia = (targv-u); \ + LbmFloat devial = norm(devia); \ + LbmVec set; \ + set = u +targv * this->mTForceStrength; \ + set = u + (devia/this->mOmega) * this->mTForceStrength; \ + ux = set[0]; uy=set[1]; uz=set[2]; \ + if(j==10){ errMsg("FTDEB"," at "<<PRINT_IJK<<" dist:"<<delt<<","<<dist<<" targ"<<targv<<","<<norm(targv)<<" set:"<<set<<","<<norm(set) ); }\ + } \ + +*/ + /****************************************************************************** * normal relaxation *****************************************************************************/ @@ -165,20 +269,20 @@ // treatment of freeslip reflection // used both for OPT and nonOPT #define DEFAULT_STREAM_FREESLIP(l,invl,mnbf) \ - /*const int inv_l = D::dfInv[l];*/ \ + /*const int inv_l = this->dfInv[l];*/ \ int nb1 = 0, nb2 = 0; /* is neighbor in this direction an obstacle? */\ LbmFloat newval = 0.0; /* new value for m[l], differs for free/part slip */\ - const int dx = D::dfVecX[invl], dy = D::dfVecY[invl], dz = D::dfVecZ[invl]; \ + const int dx = this->dfVecX[invl], dy = this->dfVecY[invl], dz = this->dfVecZ[invl]; \ if(dz==0) { \ nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \ nb2 = !(RFLAG(lev, i+dx,j, k, SRCS(lev))&(CFFluid|CFInter)); \ if((nb1)&&(!nb2)) { \ /* x reflection */\ - newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ + newval = QCELL(lev, i+dx,j,k,SRCS(lev), this->dfRefX[l]); \ } else \ if((!nb1)&&(nb2)) { \ /* y reflection */\ - newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ + newval = QCELL(lev, i,j+dy,k,SRCS(lev), this->dfRefY[l]); \ } else { \ /* normal no slip in all other cases */\ newval = QCELL(lev, i,j,k,SRCS(lev), invl); \ @@ -189,11 +293,11 @@ nb2 = !(RFLAG(lev, i+dx,j,k, SRCS(lev))&(CFFluid|CFInter)); \ if((nb1)&&(!nb2)) { \ /* x reflection */\ - newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ + newval = QCELL(lev, i+dx,j,k,SRCS(lev), this->dfRefX[l]); \ } else \ if((!nb1)&&(nb2)) { \ /* z reflection */\ - newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ + newval = QCELL(lev, i,j,k+dz,SRCS(lev), this->dfRefZ[l]); \ } else { \ /* normal no slip in all other cases */\ newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \ @@ -205,11 +309,11 @@ nb2 = !(RFLAG(lev, i,j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \ if((nb1)&&(!nb2)) { \ /* y reflection */\ - newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ + newval = QCELL(lev, i,j+dy,k,SRCS(lev), this->dfRefY[l]); \ } else \ if((!nb1)&&(nb2)) { \ /* z reflection */\ - newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ + newval = QCELL(lev, i,j,k+dz,SRCS(lev), this->dfRefZ[l]); \ } else { \ /* normal no slip in all other cases */\ newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \ @@ -217,7 +321,7 @@ } \ if(mnbf & CFBndPartslip) { /* part slip interpolation */ \ const LbmFloat partv = mObjectPartslips[(int)(mnbf>>24)]; \ - m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \ + m[l] = RAC(ccel, this->dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \ } else {\ m[l] = newval; /* normal free slip*/\ }\ @@ -228,20 +332,22 @@ #if FSGR_STRICT_DEBUG==1 #define MARKCELLCHECK \ - debugMarkCell(lev,i,j,k); D::mPanic=1; -#define STREAMCHECK(ni,nj,nk,nl) \ - if((m[l] < -1.0) || (m[l]>1.0)) {\ - errMsg("STREAMCHECK","Invalid streamed DF l"<<l<<" value:"<<m[l]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\ + debugMarkCell(lev,i,j,k); CAUSE_PANIC; +#define STREAMCHECK(id,ni,nj,nk,nl) \ + if((m[nl] < -1.0) || (m[nl]>1.0)) {\ + errMsg("STREAMCHECK","ID"<<id<<" Invalid streamed DF nl"<<nl<<" value:"<<m[nl]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\ " nfc"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr)<<" nfo"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setOther) ); \ + /*FORDF0{ errMsg("STREAMCHECK"," at "<<PRINT_IJK<<" df "<<l<<"="<<m[l] ); } */ \ MARKCELLCHECK; \ } #define COLLCHECK \ if( (rho>2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\ errMsg("COLLCHECK","Invalid collision values r:"<<rho<<" u:"PRINT_VEC(ux,uy,uz)<<" at? "<<PRINT_IJK ); \ + /*FORDF0{ errMsg("COLLCHECK"," at? "<<PRINT_IJK<<" df "<<l<<"="<<m[l] ); }*/ \ MARKCELLCHECK; \ } #else -#define STREAMCHECK(ni,nj,nk,nl) +#define STREAMCHECK(id, ni,nj,nk,nl) #define COLLCHECK #endif @@ -249,121 +355,38 @@ #define DEFAULT_STREAM \ m[dC] = RAC(ccel,dC); \ + STREAMCHECK(1, i,j,k, dC); \ FORDF1 { \ - CellFlagType nbf = nbflag[ D::dfInv[l] ];\ + CellFlagType nbf = nbflag[ this->dfInv[l] ];\ if(nbf & CFBnd) { \ if(nbf & CFBndNoslip) { \ /* no slip, default */ \ - m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \ + m[l] = RAC(ccel, this->dfInv[l] ); /* noslip */ \ + if(nbf&CFBndMoving) m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \ + STREAMCHECK(2, i,j,k, l); \ } else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \ /* free slip */ \ if(l<=LBMDIM*2) { \ - m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \ + m[l] = RAC(ccel, this->dfInv[l] ); STREAMCHECK(3, i,j,k, l); /* noslip for <dim*2 */ \ } else { \ - const int inv_l = D::dfInv[l]; \ - DEFAULT_STREAM_FREESLIP(l,inv_l,nbf); \ - } /* l>2*dim free slip */ \ - \ - } /* type reflect */\ - else {\ - errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \ - } \ - } else { \ - m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ - } \ - } - -#define _________________DEFAULT_STREAM \ - m[dC] = RAC(ccel,dC); \ - FORDF1 { \ - CellFlagType nbf = nbflag[ D::dfInv[l] ];\ - if(nbf & CFBnd) { \ - if(nbf & CFBndNoslip) { \ - /* no slip, default */ \ - m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \ - } else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \ - /* free slip */ \ - if(l<=LBMDIM*2) { \ - m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \ - } else { \ - const int inv_l = D::dfInv[l]; \ - int debug_srcl = -1; \ - int nb1 = 0, nb2 = 0; /* is neighbor in this direction an obstacle? */\ - LbmFloat newval = 0.0; /* new value for m[l], differs for free/part slip */\ - const int dx = D::dfVecX[inv_l], dy = D::dfVecY[inv_l], dz = D::dfVecZ[inv_l]; \ + const int inv_l = this->dfInv[l]; \ + DEFAULT_STREAM_FREESLIP(l,inv_l,nbf); \ + } /* l>2*dim free slip */ \ \ - if(dz==0) { \ - nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); /* FIXME add noslip|free|part here */ \ - nb2 = !(RFLAG(lev, i+dx,j, k, SRCS(lev))&(CFFluid|CFInter)); \ - if((nb1)&&(!nb2)) { \ - /* x reflection */\ - newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ - debug_srcl = D::dfRefX[l]; \ - } else \ - if((!nb1)&&(nb2)) { \ - /* y reflection */\ - newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ - debug_srcl = D::dfRefY[l]; \ - } else { \ - /* normal no slip in all other cases */\ - newval = QCELL(lev, i,j,k,SRCS(lev), inv_l); \ - debug_srcl = inv_l; \ - } \ - } else /* z=0 */\ - if(dy==0) { \ - nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \ - nb2 = !(RFLAG(lev, i+dx,j,k, SRCS(lev))&(CFFluid|CFInter)); \ - if((nb1)&&(!nb2)) { \ - /* x reflection */\ - newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \ - } else \ - if((!nb1)&&(nb2)) { \ - /* z reflection */\ - newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ - } else { \ - /* normal no slip in all other cases */\ - newval = ( QCELL(lev, i,j,k,SRCS(lev), inv_l) ); \ - } \ - /* end y=0 */ \ - } else { \ - /* x=0 */\ - nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \ - nb2 = !(RFLAG(lev, i,j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \ - if((nb1)&&(!nb2)) { \ - /* y reflection */\ - newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \ - } else \ - if((!nb1)&&(nb2)) { \ - /* z reflection */\ - newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \ - } else { \ - /* normal no slip in all other cases */\ - newval = ( QCELL(lev, i,j,k,SRCS(lev), inv_l) ); \ - } \ - } \ - if(nbf & CFBndPartslip) { /* part slip interpolation */ \ - const LbmFloat partv = mObjectPartslips[(int)(nbf>>24)]; \ - m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \ - } else {\ - m[l] = newval; /* normal free slip*/\ - }\ - /*if(RFLAG(lev, i,j,k, SRCS(lev))&CFInter) errMsg("FS","at "<<PRINT_IJK<<",l"<<l<<" nb1"<<nb1<<" nb2"<<nb2<<" dx"<<PRINT_VEC(dx,dy,dz)<<",srcl"<<debug_srcl<<" -> "<<newval );*/ \ - } /* l>2*dim free slip */ \ - \ } /* type reflect */\ else {\ - errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \ + errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<this->dfInv[l] ); \ } \ } else { \ m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + STREAMCHECK(4, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \ } \ } + // careful ux,uy,uz need to be inited before! #define DEFAULT_COLLIDE \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -372,13 +395,13 @@ m[0] = RAC(ccel,0); \ FORDF1 { /* df0 is set later on... */ \ /* FIXME CHECK INV ? */\ - if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); CAUSE_PANIC; \ } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + STREAMCHECK(8, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \ } \ - rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ + rho=m[0]; \ ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -387,6 +410,20 @@ #else // 3D, opt OPT3D==true +// handle mov. obj +#if FSGR_STRICT_DEBUG==1 +#define LBMDS_ADDMOV(linv,l) if(nbflag[linv]&CFBndMoving){ \ + if(QCELL_NBINV(lev, i, j, k, SRCS(lev), l,dFlux)== (mSimulationTime+this->mpParam->getTimestep()) ) { \ + m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \ + } else { \ + CAUSE_PANIC; errMsg("INVALID_MOV_OBJ_TIME"," at "<<PRINT_IJK<<" from l"<<l<<" t="<<mSimulationTime<<" ct="<<QCELL_NBINV(lev, i, j, k, SRCS(lev), l,dFlux)); \ + } \ + } +#else // FSGR_STRICT_DEBUG==1 +#define LBMDS_ADDMOV(linv,l) if(nbflag[linv]&CFBndMoving){ m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); } /* obs. speed*/ +#endif // FSGR_STRICT_DEBUG==1 + +// default stream opt3d add moving bc val #define DEFAULT_STREAM \ m[dC] = RAC(ccel,dC); \ /* explicit streaming */ \ @@ -400,26 +437,26 @@ m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \ } else { \ /* explicit streaming, normal velocity always zero for obstacles */ \ - if(nbflag[dS ]&CFBnd) { m[dN ] = RAC(ccel,dS ); } else { m[dN ] = CSRC_N ; } \ - if(nbflag[dN ]&CFBnd) { m[dS ] = RAC(ccel,dN ); } else { m[dS ] = CSRC_S ; } \ - if(nbflag[dW ]&CFBnd) { m[dE ] = RAC(ccel,dW ); } else { m[dE ] = CSRC_E ; } \ - if(nbflag[dE ]&CFBnd) { m[dW ] = RAC(ccel,dE ); } else { m[dW ] = CSRC_W ; } \ - if(nbflag[dB ]&CFBnd) { m[dT ] = RAC(ccel,dB ); } else { m[dT ] = CSRC_T ; } \ - if(nbflag[dT ]&CFBnd) { m[dB ] = RAC(ccel,dT ); } else { m[dB ] = CSRC_B ; } \ + if(nbflag[dS ]&CFBnd) { m[dN ] = RAC(ccel,dS ); LBMDS_ADDMOV(dS ,dN ); } else { m[dN ] = CSRC_N ; } \ + if(nbflag[dN ]&CFBnd) { m[dS ] = RAC(ccel,dN ); LBMDS_ADDMOV(dN ,dS ); } else { m[dS ] = CSRC_S ; } \ + if(nbflag[dW ]&CFBnd) { m[dE ] = RAC(ccel,dW ); LBMDS_ADDMOV(dW ,dE ); } else { m[dE ] = CSRC_E ; } \ + if(nbflag[dE ]&CFBnd) { m[dW ] = RAC(ccel,dE ); LBMDS_ADDMOV(dE ,dW ); } else { m[dW ] = CSRC_W ; } \ + if(nbflag[dB ]&CFBnd) { m[dT ] = RAC(ccel,dB ); LBMDS_ADDMOV(dB ,dT ); } else { m[dT ] = CSRC_T ; } \ + if(nbflag[dT ]&CFBnd) { m[dB ] = RAC(ccel,dT ); LBMDS_ADDMOV(dT ,dB ); } else { m[dB ] = CSRC_B ; } \ \ /* also treat free slip here */ \ - if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} } else { m[dNE] = CSRC_NE; } \ - if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} } else { m[dNW] = CSRC_NW; } \ - if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} } else { m[dSE] = CSRC_SE; } \ - if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} } else { m[dSW] = CSRC_SW; } \ - if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} } else { m[dNT] = CSRC_NT; } \ - if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} } else { m[dNB] = CSRC_NB; } \ - if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} } else { m[dST] = CSRC_ST; } \ - if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} } else { m[dSB] = CSRC_SB; } \ - if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} } else { m[dET] = CSRC_ET; } \ - if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} } else { m[dEB] = CSRC_EB; } \ - if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} } else { m[dWT] = CSRC_WT; } \ - if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} } else { m[dWB] = CSRC_WB; } \ + if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); LBMDS_ADDMOV(dSW,dNE); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} } else { m[dNE] = CSRC_NE; } \ + if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); LBMDS_ADDMOV(dSE,dNW); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} } else { m[dNW] = CSRC_NW; } \ + if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); LBMDS_ADDMOV(dNW,dSE); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} } else { m[dSE] = CSRC_SE; } \ + if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); LBMDS_ADDMOV(dNE,dSW); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} } else { m[dSW] = CSRC_SW; } \ + if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); LBMDS_ADDMOV(dSB,dNT); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} } else { m[dNT] = CSRC_NT; } \ + if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); LBMDS_ADDMOV(dST,dNB); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} } else { m[dNB] = CSRC_NB; } \ + if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); LBMDS_ADDMOV(dNB,dST); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} } else { m[dST] = CSRC_ST; } \ + if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); LBMDS_ADDMOV(dNT,dSB); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} } else { m[dSB] = CSRC_SB; } \ + if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); LBMDS_ADDMOV(dWB,dET); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} } else { m[dET] = CSRC_ET; } \ + if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); LBMDS_ADDMOV(dWT,dEB); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} } else { m[dEB] = CSRC_EB; } \ + if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); LBMDS_ADDMOV(dEB,dWT); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} } else { m[dWT] = CSRC_WT; } \ + if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); LBMDS_ADDMOV(dET,dWB); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} } else { m[dWB] = CSRC_WB; } \ } @@ -522,9 +559,10 @@ + MSRC_ST - MSRC_SB \ + MSRC_ET - MSRC_EB \ + MSRC_WT - MSRC_WB ; \ + PRECOLLIDE_MODS(rho,ux,uy,uz); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev, MSRC_)\ + COLL_CALCULATE_NONEQTENSOR(lev, MSRC_); \ COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \ CSMOMEGA_STATS(lev,lcsmomega); \ \ @@ -579,6 +617,7 @@ + MSRC_ST - MSRC_SB \ + MSRC_ET - MSRC_EB \ + MSRC_WT - MSRC_WB ; \ + PRECOLLIDE_MODS(rho,ux,uy,uz); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ \ RAC(tcel,dC ) = (1.0-OMEGA(lev))*MSRC_C + OMEGA(lev)*EQC ; \ @@ -624,6 +663,7 @@ + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB + mLevel[lev].gravity[1]; \ uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB \ + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB + mLevel[lev].gravity[2]; \ + PRECOLLIDE_MODS(rho,ux,uy,uz); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ COLL_CALCULATE_NONEQTENSOR(lev, MSRC_) \ @@ -664,6 +704,7 @@ + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ + PRECOLLIDE_MODS(rho,ux,uy,uz); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ COLL_CALCULATE_NONEQTENSOR(lev, CSRC_) \ @@ -703,6 +744,7 @@ + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ + PRECOLLIDE_MODS(rho,ux,uy,uz); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ RAC(tcel,dC ) = (1.0-OMEGA(lev))*CSRC_C + OMEGA(lev)*EQC ; \ RAC(tcel,dN ) = (1.0-OMEGA(lev))*CSRC_N + OMEGA(lev)*EQN ; \ @@ -734,13 +776,12 @@ #define OPTIMIZED_STREAMCOLLIDE_DEBUG \ m[0] = RAC(ccel,0); \ FORDF1 { /* df0 is set later on... */ \ - if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); CAUSE_PANIC;\ } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ - STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \ + STREAMCHECK(9, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \ } \ rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -752,13 +793,12 @@ /*DEBUG \ m[0] = RAC(ccel,0); \ FORDF1 { \ - if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \ + if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl");CAUSE_PANIC; \ } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ } \ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lcsmomega ); \ rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ */ #if USE_LES==1 @@ -811,7 +851,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc ((( (at))>0.0) && (!(QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setOther, l) > -1.0 ))) ){ \ errMsg("INVDFSCHECK", " l"<<(alev)<<" "<<PRINT_VEC((ai),(aj),(ak))<<" fc:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )<<" fo:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )<<" dfl"<<l ); \ debugMarkCell((alev), (ai),(aj),(ak));\ - D::mPanic = 1; \ + CAUSE_PANIC; \ } // end ADD_INT_DFSCHECK #define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) \ @@ -821,7 +861,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc " fc:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )) <<\ " fold:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )) ); \ debugMarkCell((alev), (ai),(aj),(ak));\ - D::mPanic = 1; \ + CAUSE_PANIC; \ } // end ADD_INT_DFSCHECK @@ -833,7 +873,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc if( (RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) != (CFFluid|CFGrFromCoarse)) ){\ errMsg("INTFLAGUNU_CHECK", PRINT_VEC(i,j,k)<<" child not unused at l"<<(lev+1)<<" "<<PRINT_VEC((ix),(iy),(iz))<<" flag: "<< RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) ); \ debugMarkCell((lev+1), (ix),(iy),(iz));\ - D::mPanic = 1; \ + CAUSE_PANIC; \ }\ RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) |= CFGrCoarseInited; \ // INTUNUTCHECK @@ -841,7 +881,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc if( QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) <= 0.0 ){\ errMsg("INVDFCCELLCHECK", "caseId:"<<caseId<<" "<<PRINT_VEC(i,j,k)<<" child inter at "<<PRINT_VEC((ix),(iy),(iz))<<" invalid df "<<l<<" = "<< QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) ); \ debugMarkCell((lev+1), (ix),(iy),(iz));\ - D::mPanic = 1; \ + CAUSE_PANIC; \ }\ // INTSTRICTCHECK @@ -858,11 +898,11 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc { /*LbmFloat rho,ux,uy,uz;*/ \ rho = ux=uy=uz=0.0; \ FORDF0{ LbmFloat m = QCELL(lev,i,j,k, dstSet, l); \ - rho += m; ux += (D::dfDvecX[l]*m); uy += (D::dfDvecY[l]*m); uz += (D::dfDvecZ[l]*m); \ - if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m ); D::mPanic=1; }\ + rho += m; ux += (this->dfDvecX[l]*m); uy += (this->dfDvecY[l]*m); uz += (this->dfDvecZ[l]*m); \ + if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m );CAUSE_PANIC;}\ /*errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" df"<<l<<":"<<m );*/ \ } \ - /*if(D::mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \ + /*if(this->mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \ if(markNbs) errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); \ /*errMsg("interpolateCellFromCoarse", "ICFC_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); */\ } \ @@ -872,7 +912,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc /* might also have CFGrCoarseInited (shouldnt be a problem here)*/ \ errMsg("interpolateCellFromCoarse", "CHECK cell not CFGrFromCoarse? "<<PRINT_IJK<<" flag:"<< RFLAG(lev,i,j,k, dstSet)<<" fstr:"<<convertCellFlagType2String( RFLAG(lev,i,j,k, dstSet) )); \ /* FIXME check this warning...? return; this can happen !? */ \ - /*D::mPanic = 1;*/ \ + /*CAUSE_PANIC;*/ \ } \ // end INTDEBOUT #else // FSGR_STRICT_DEBUG==1 @@ -894,15 +934,15 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l); \ df *= (afac); \ rho += df; \ - ux += (D::dfDvecX[l]*df); \ - uy += (D::dfDvecY[l]*df); \ - uz += (D::dfDvecZ[l]*df); \ + ux += (this->dfDvecX[l]*df); \ + uy += (this->dfDvecY[l]*df); \ + uz += (this->dfDvecZ[l]*df); \ intDf[l] += df; \ } // write interpolated dfs back to cell (correct non-eq. parts) #define IDF_WRITEBACK_ \ FORDF0{ \ - LbmFloat eq = D::getCollideEq(l, rho,ux,uy,uz);\ + LbmFloat eq = getCollideEq(l, rho,ux,uy,uz);\ QCELL(lev,i,j,k, dstSet, l) = (eq+ (intDf[l]-eq)*mDfScaleDown);\ } \ /* check that all values are ok */ \ @@ -913,18 +953,18 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc LbmFloat feq[LBM_DFNUM]; \ LbmFloat dfScale = mDfScaleDown; \ FORDF0{ \ - feq[l] = D::getCollideEq(l, rho,ux,uy,uz); \ + feq[l] = getCollideEq(l, rho,ux,uy,uz); \ } \ if(mLevel[lev ].lcsmago>0.0) {\ - LbmFloat Qo = D::getLesNoneqTensorCoeff(intDf,feq); \ - omegaDst = D::getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \ - omegaSrc = D::getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \ + LbmFloat Qo = this->getLesNoneqTensorCoeff(intDf,feq); \ + omegaDst = this->getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \ + omegaSrc = this->getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \ } else {\ omegaDst = mLevel[lev+0].omega; \ omegaSrc = mLevel[lev-1].omega;\ } \ \ - dfScale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \ + dfScale = (mLevel[lev+0].timestep/mLevel[lev-1].timestep)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \ FORDF0{ \ /*errMsg("SMAGO"," org"<<mDfScaleDown<<" n"<<dfScale<<" qc"<< QCELL(lev,i,j,k, dstSet, l)<<" idf"<<intDf[l]<<" eq"<<feq[l] ); */ \ QCELL(lev,i,j,k, dstSet, l) = (feq[l]+ (intDf[l]-feq[l])*dfScale);\ @@ -1015,7 +1055,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ COLL_CALCULATE_CSMOMEGAVAL(lev-1, lcsmSrcOmega); \ \ - lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ + lcsmdfscale = (mLevel[lev+0].timestep/mLevel[lev-1].timestep)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \ RAC(dstcell, dC ) = (lcsmeq[dC ] + (intDf[dC ]-lcsmeq[dC ] )*lcsmdfscale);\ RAC(dstcell, dN ) = (lcsmeq[dN ] + (intDf[dN ]-lcsmeq[dN ] )*lcsmdfscale);\ RAC(dstcell, dS ) = (lcsmeq[dS ] + (intDf[dS ]-lcsmeq[dS ] )*lcsmdfscale);\ @@ -1070,3 +1110,104 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc #endif// OPT3D==0 + + +/******************************************************************************/ +/*! relaxation LES functions */ +/******************************************************************************/ + + +inline LbmFloat LbmFsgrSolver::getLesNoneqTensorCoeff( + LbmFloat df[], + LbmFloat feq[] ) { + LbmFloat Qo = 0.0; + for(int m=0; m< ((LBMDIM*LBMDIM)-LBMDIM)/2 ; m++) { + LbmFloat qadd = 0.0; + for(int l=1; l<this->cDfNum; l++) { + if(this->lesCoeffOffdiag[m][l]==0.0) continue; + qadd += this->lesCoeffOffdiag[m][l]*(df[l]-feq[l]); + } + Qo += (qadd*qadd); + } + Qo *= 2.0; // off diag twice + for(int m=0; m<LBMDIM; m++) { + LbmFloat qadd = 0.0; + for(int l=1; l<this->cDfNum; l++) { + if(this->lesCoeffDiag[m][l]==0.0) continue; + qadd += this->lesCoeffDiag[m][l]*(df[l]-feq[l]); + } + Qo += (qadd*qadd); + } + Qo = sqrt(Qo); + return Qo; +}; + +inline LbmFloat LbmFsgrSolver::getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) { + const LbmFloat tau = 1.0/omega; + const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0); + const LbmFloat C = csmago; + const LbmFloat Csqr = C*C; + LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr); + return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) ); +} + +#define DEBUG_CALCPRINTCELL(str,df) {\ + LbmFloat rho=df[0], ux=0., uy=0., uz=0.; \ + for(int l=1; l<this->cDfNum; l++) { \ + rho += df[l]; \ + ux += (this->dfDvecX[l]*df[l]); \ + uy += (this->dfDvecY[l]*df[l]); \ + uz += (this->dfDvecZ[l]*df[l]); \ + } \ + errMsg("DEBUG_CALCPRINTCELL",">"<<str<<" rho="<<rho<<" vel="<<ntlVec3Gfx(ux,uy,uz) ); \ + } /* END DEBUG_CALCPRINTCELL */ + +// "normal" collision +inline void LbmFsgrSolver::collideArrays( + int i, int j, int k, // position - more for debugging + LbmFloat df[], + LbmFloat &outrho, // out only! + // velocity modifiers (returns actual velocity!) + LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, + LbmFloat omega, LbmFloat csmago, + LbmFloat *newOmegaRet, LbmFloat *newQoRet + ) { + LbmFloat rho=df[0]; + LbmFloat ux = mux; + LbmFloat uy = muy; + LbmFloat uz = muz; + for(int l=1; l<this->cDfNum; l++) { + rho += df[l]; + ux += (this->dfDvecX[l]*df[l]); + uy += (this->dfDvecY[l]*df[l]); + uz += (this->dfDvecZ[l]*df[l]); + } + + PRECOLLIDE_MODS(rho,ux,uy,uz); + LbmFloat feq[19]; + for(int l=0; l<this->cDfNum; l++) { + feq[l] = getCollideEq(l,rho,ux,uy,uz); + } + + LbmFloat omegaNew; + LbmFloat Qo = 0.0; + if(csmago>0.0) { + Qo = getLesNoneqTensorCoeff(df,feq); + omegaNew = getLesOmega(omega,csmago,Qo); + } else { + omegaNew = omega; // smago off... + } + if(newOmegaRet) *newOmegaRet = omegaNew; // return value for stats + if(newQoRet) *newQoRet = Qo; // return value of non-eq. stress tensor + + for(int l=0; l<this->cDfNum; l++) { + df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l]; + } + if((i==16)&&(j==10)) DEBUG_CALCPRINTCELL( "2dcoll "<<PRINT_IJK, df); + + mux = ux; + muy = uy; + muz = uz; + outrho = rho; +}; + diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp index 9c2a0035024..7406c55acbc 100644 --- a/intern/elbeem/intern/solver_util.cpp +++ b/intern/elbeem/intern/solver_util.cpp @@ -7,8 +7,9 @@ * *****************************************************************************/ -#if ((!defined(__APPLE_CC__)) && (!defined(__INTEL_COMPILER))) || defined(LBM_FORCEINCLUDE) #include "solver_class.h" +#include "solver_relax.h" +#include "particletracer.h" /****************************************************************************** @@ -16,8 +17,7 @@ *****************************************************************************/ //! for raytracing -template<class D> -void LbmFsgrSolver<D>::prepareVisualization( void ) { +void LbmFsgrSolver::prepareVisualization( void ) { int lev = mMaxRefine; int workSet = mLevel[lev].setCurr; @@ -31,7 +31,7 @@ void LbmFsgrSolver<D>::prepareVisualization( void ) { for(int k= 0; k< 5; ++k) for(int j=0;j<mLevel[lev].lSizey-0;j++) for(int i=0;i<mLevel[lev].lSizex-0;i++) { - *D::mpIso->lbmGetData(i,j,ZKOFF)=0.0; + *this->mpIso->lbmGetData(i,j,ZKOFF)=0.0; } #else // LBMDIM==2 // 3d, use normal bounds @@ -41,7 +41,7 @@ void LbmFsgrSolver<D>::prepareVisualization( void ) { for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) for(int j=0;j<mLevel[lev].lSizey-0;j++) for(int i=0;i<mLevel[lev].lSizex-0;i++) { - *D::mpIso->lbmGetData(i,j,ZKOFF)=0.0; + *this->mpIso->lbmGetData(i,j,ZKOFF)=0.0; } #endif // LBMDIM==2 @@ -63,153 +63,183 @@ void LbmFsgrSolver<D>::prepareVisualization( void ) { /* // flicker-test-fix: no real difference if( (!(RFLAG(lev, i,j,k,workSet)&CFNoBndFluid)) && (RFLAG(lev, i,j,k,workSet)&CFNoNbFluid) && - (val<D::mIsoValue) ){ - val = D::mIsoValue*1.1; } + (val<this->mIsoValue) ){ + val = this->mIsoValue*1.1; } // */ } else { // fluid? val = 1.0; ///27.0; } // */ - *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[2] ); + *this->mpIso->lbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] ); + *this->mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] ); + *this->mpIso->lbmGetData( i+1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[2] ); - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[5] ); + *this->mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] ); + *this->mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] ); + *this->mpIso->lbmGetData( i+1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[5] ); - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[8] ); + *this->mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] ); + *this->mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] ); + *this->mpIso->lbmGetData( i+1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[8] ); - *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[11] ); + *this->mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] ); + *this->mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] ); + *this->mpIso->lbmGetData( i+1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[11] ); - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF ) += ( val * mIsoWeight[14] ); + *this->mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] ); + *this->mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] ); + *this->mpIso->lbmGetData( i+1 , j ,ZKOFF ) += ( val * mIsoWeight[14] ); - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[17] ); + *this->mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] ); + *this->mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] ); + *this->mpIso->lbmGetData( i+1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[17] ); - *D::mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] ); - *D::mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] ); - *D::mpIso->lbmGetData( i+1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[20] ); + *this->mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] ); + *this->mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] ); + *this->mpIso->lbmGetData( i+1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[20] ); - *D::mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] ); - *D::mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] ); - *D::mpIso->lbmGetData( i+1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[23] ); + *this->mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] ); + *this->mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] ); + *this->mpIso->lbmGetData( i+1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[23] ); - *D::mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] ); - *D::mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] ); - *D::mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] ); + *this->mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] ); + *this->mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] ); + *this->mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] ); } -#if ELBEEM_PLUGIN!=1 - if(mUseTestdata) { +#if LBM_INCLUDE_TESTSOLVERS==1 + /*if(mUseTestdata) { int border = 1; for(int k=0;k<mLevel[mMaxRefine].lSizez-1;k++) for(int j=0;j<mLevel[mMaxRefine].lSizey-1;j++) { for(int l=0; l<=border; l++) { - *D::mpIso->lbmGetData( l-1, j,ZKOFF) = *D::mpIso->lbmGetData( border+1, j,ZKOFF); - *D::mpIso->lbmGetData( mLevel[mMaxRefine].lSizex-l, j,ZKOFF) = *D::mpIso->lbmGetData( mLevel[mMaxRefine].lSizex-border-1, j,ZKOFF); + *this->mpIso->lbmGetData( l-1, j,ZKOFF) = *this->mpIso->lbmGetData( border+1, j,ZKOFF); + *this->mpIso->lbmGetData( mLevel[mMaxRefine].lSizex-l, j,ZKOFF) = *this->mpIso->lbmGetData( mLevel[mMaxRefine].lSizex-border-1, j,ZKOFF); } } for(int k=0;k<mLevel[mMaxRefine].lSizez-1;k++) for(int i=-1;i<mLevel[mMaxRefine].lSizex+1;i++) { for(int l=0; l<=border; l++) { - *D::mpIso->lbmGetData( i, l-1, ZKOFF) = *D::mpIso->lbmGetData( i, border+1, ZKOFF); - *D::mpIso->lbmGetData( i, mLevel[mMaxRefine].lSizey-l, ZKOFF) = *D::mpIso->lbmGetData( i, mLevel[mMaxRefine].lSizey-border-1, ZKOFF); + *this->mpIso->lbmGetData( i, l-1, ZKOFF) = *this->mpIso->lbmGetData( i, border+1, ZKOFF); + *this->mpIso->lbmGetData( i, mLevel[mMaxRefine].lSizey-l, ZKOFF) = *this->mpIso->lbmGetData( i, mLevel[mMaxRefine].lSizey-border-1, ZKOFF); } } - if(D::cDimension == 3) { + if(LBMDIM == 3) { // only for 3D for(int j=-1;j<mLevel[mMaxRefine].lSizey+1;j++) for(int i=-1;i<mLevel[mMaxRefine].lSizex+1;i++) { for(int l=0; l<=border; l++) { - *D::mpIso->lbmGetData( i,j,l-1 ) = *D::mpIso->lbmGetData( i,j, border+1 ); - *D::mpIso->lbmGetData( i,j,mLevel[mMaxRefine].lSizez-l) = *D::mpIso->lbmGetData( i,j,mLevel[mMaxRefine].lSizez-1-border); + *this->mpIso->lbmGetData( i,j,l-1 ) = *this->mpIso->lbmGetData( i,j, border+1 ); + *this->mpIso->lbmGetData( i,j,mLevel[mMaxRefine].lSizez-l) = *this->mpIso->lbmGetData( i,j,mLevel[mMaxRefine].lSizez-1-border); } } } - } // testdata -#endif // ELBEEM_PLUGIN + } // testdata */ +#endif // LBM_INCLUDE_TESTSOLVERS==1 // */ // update preview, remove 2d? - if(D::mOutputSurfacePreview) { - int pvsx = (int)(D::mPreviewFactor*D::mSizex); - int pvsy = (int)(D::mPreviewFactor*D::mSizey); - int pvsz = (int)(D::mPreviewFactor*D::mSizez); - //float scale = (float)D::mSizex / previewSize; - LbmFloat scalex = (LbmFloat)D::mSizex/(LbmFloat)pvsx; - LbmFloat scaley = (LbmFloat)D::mSizey/(LbmFloat)pvsy; - LbmFloat scalez = (LbmFloat)D::mSizez/(LbmFloat)pvsz; - for(int k= 0; k< ((D::cDimension==3) ? (pvsz-1):1) ; ++k) + if((this->mOutputSurfacePreview)&&(LBMDIM==3)) { + int pvsx = (int)(this->mPreviewFactor*this->mSizex); + int pvsy = (int)(this->mPreviewFactor*this->mSizey); + int pvsz = (int)(this->mPreviewFactor*this->mSizez); + //float scale = (float)this->mSizex / previewSize; + LbmFloat scalex = (LbmFloat)this->mSizex/(LbmFloat)pvsx; + LbmFloat scaley = (LbmFloat)this->mSizey/(LbmFloat)pvsy; + LbmFloat scalez = (LbmFloat)this->mSizez/(LbmFloat)pvsz; + for(int k= 0; k< (pvsz-1); ++k) for(int j=0;j< pvsy;j++) for(int i=0;i< pvsx;i++) { - *mpPreviewSurface->lbmGetData(i,j,k) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(i,j,k) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) ); } // set borders again... - for(int k= 0; k< ((D::cDimension == 3) ? (pvsz-1):1) ; ++k) { + for(int k= 0; k< (pvsz-1); ++k) { for(int j=0;j< pvsy;j++) { - *mpPreviewSurface->lbmGetData(0,j,k) = *D::mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) ); - *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *D::mpIso->lbmGetData( D::mSizex-1, (int)(j*scaley), (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(0,j,k) = *this->mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *this->mpIso->lbmGetData( this->mSizex-1, (int)(j*scaley), (int)(k*scalez) ); } for(int i=0;i< pvsx;i++) { - *mpPreviewSurface->lbmGetData(i,0,k) = *D::mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) ); - *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *D::mpIso->lbmGetData( (int)(i*scalex), D::mSizey-1, (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(i,0,k) = *this->mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) ); + *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *this->mpIso->lbmGetData( (int)(i*scalex), this->mSizey-1, (int)(k*scalez) ); } } - if(D::cDimension == 3) { - // only for 3D + for(int j=0;j<pvsy;j++) + for(int i=0;i<pvsx;i++) { + *mpPreviewSurface->lbmGetData(i,j,0) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0); + *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , this->mSizez-1); + } + + if(mUseTestdata) { + // also remove preview border + for(int k= 0; k< (pvsz-1); ++k) { + for(int j=0;j< pvsy;j++) { + *mpPreviewSurface->lbmGetData(0,j,k) = + *mpPreviewSurface->lbmGetData(1,j,k) = + *mpPreviewSurface->lbmGetData(2,j,k); + *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = + *mpPreviewSurface->lbmGetData(pvsx-2,j,k) = + *mpPreviewSurface->lbmGetData(pvsx-3,j,k); + //0.0; + } + for(int i=0;i< pvsx;i++) { + *mpPreviewSurface->lbmGetData(i,0,k) = + *mpPreviewSurface->lbmGetData(i,1,k) = + *mpPreviewSurface->lbmGetData(i,2,k); + *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = + *mpPreviewSurface->lbmGetData(i,pvsy-2,k) = + *mpPreviewSurface->lbmGetData(i,pvsy-3,k); + //0.0; + } + } for(int j=0;j<pvsy;j++) for(int i=0;i<pvsx;i++) { - *mpPreviewSurface->lbmGetData(i,j,0) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0); - *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *D::mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , D::mSizez-1); - } - } // borders done... + *mpPreviewSurface->lbmGetData(i,j,0) = + *mpPreviewSurface->lbmGetData(i,j,1) = + *mpPreviewSurface->lbmGetData(i,j,2); + *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = + *mpPreviewSurface->lbmGetData(i,j,pvsz-2) = + *mpPreviewSurface->lbmGetData(i,j,pvsz-3); + //0.0; + } + } } -#if ELBEEM_PLUGIN!=1 - if(D::mInitDone) { - if(mpTest->mDebugvalue3<=0.0) handleTestdata(); - } -#endif // ELBEEM_PLUGIN!=1 // correction return; } /*! calculate speeds of fluid objects (or inflow) */ -template<class D> -void LbmFsgrSolver<D>::recalculateObjectSpeeds() { - int numobjs = (int)(D::mpGiObjects->size()); +void LbmFsgrSolver::recalculateObjectSpeeds() { + const bool debugRecalc = false; + int numobjs = (int)(this->mpGiObjects->size()); // note - (numobjs + 1) is entry for domain settings + + if(debugRecalc) errMsg("recalculateObjectSpeeds","start, #obj:"<<numobjs); if(numobjs>255-1) { errFatal("LbmFsgrSolver::recalculateObjectSpeeds","More than 256 objects currently not supported...",SIMWORLD_INITERROR); return; } mObjectSpeeds.resize(numobjs+1); for(int i=0; i<(int)(numobjs+0); i++) { - mObjectSpeeds[i] = vec2L(D::mpParam->calculateLattVelocityFromRw( vec2P( (*D::mpGiObjects)[i]->getInitialVelocity() ))); - //errMsg("recalculateObjectSpeeds","id"<<i<<" set to "<< mObjectSpeeds[i]<<", unscaled:"<< (*D::mpGiObjects)[i]->getInitialVelocity() ); + mObjectSpeeds[i] = vec2L(this->mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[i]->getInitialVelocity(mSimulationTime) ))); + if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<<i<<" set to "<< mObjectSpeeds[i]<<", unscaled:"<< (*this->mpGiObjects)[i]->getInitialVelocity(mSimulationTime) ); } // also reinit part slip values here mObjectPartslips.resize(numobjs+1); for(int i=0; i<(int)(numobjs+0); i++) { - mObjectPartslips[i] = (LbmFloat)(*D::mpGiObjects)[i]->getGeoPartSlipValue(); + mObjectPartslips[i] = (LbmFloat)(*this->mpGiObjects)[i]->getGeoPartSlipValue(); + if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<<i<<" parts "<< mObjectPartslips[i] ); } - //errMsg("GEOIN"," dm set "<<mDomainPartSlipValue); - mObjectPartslips[numobjs] = mDomainPartSlipValue; + + mObjectPartslips[numobjs] = this->mDomainPartSlipValue; + if(debugRecalc) errMsg("recalculateObjectSpeeds","done, domain:"<<mObjectPartslips[numobjs]<<" n"<<numobjs); } @@ -217,13 +247,12 @@ void LbmFsgrSolver<D>::recalculateObjectSpeeds() { /*****************************************************************************/ /*! debug object display */ /*****************************************************************************/ -template<class D> -vector<ntlGeometryObject*> LbmFsgrSolver<D>::getDebugObjects() { +vector<ntlGeometryObject*> LbmFsgrSolver::getDebugObjects() { vector<ntlGeometryObject*> debo; - if(D::mOutputSurfacePreview) { + if(this->mOutputSurfacePreview) { debo.push_back( mpPreviewSurface ); } -#if ELBEEM_PLUGIN!=1 +#if LBM_INCLUDE_TESTSOLVERS==1 if(mUseTestdata) { vector<ntlGeometryObject*> tdebo; tdebo = mpTest->getDebugObjects(); @@ -238,143 +267,511 @@ vector<ntlGeometryObject*> LbmFsgrSolver<D>::getDebugObjects() { *****************************************************************************/ /*! init particle positions */ -template<class D> -int LbmFsgrSolver<D>::initParticles(ParticleTracer *partt) { -#if ELBEEM_PLUGIN==1 - partt = NULL; // remove warning -#else // ELBEEM_PLUGIN +int LbmFsgrSolver::initParticles(ParticleTracer *partt) { int workSet = mLevel[mMaxRefine].setCurr; int tries = 0; int num = 0; mpParticles=partt; - //partt->setSimEnd ( ntlVec3Gfx(D::mSizex-1, D::mSizey-1, getForZMax1()) ); - partt->setSimEnd ( ntlVec3Gfx(D::mSizex, D::mSizey, getForZMaxBnd(mMaxRefine)) ); + partt->setStart( this->mvGeoStart + ntlVec3Gfx(mLevel[mMaxRefine].nodeSize*0.5) ); + partt->setEnd ( this->mvGeoEnd + ntlVec3Gfx(mLevel[mMaxRefine].nodeSize*0.5) ); + partt->setSimStart( ntlVec3Gfx(0.0) ); + partt->setSimEnd ( ntlVec3Gfx(this->mSizex, this->mSizey, getForZMaxBnd(mMaxRefine)) ); while( (num<partt->getNumParticles()) && (tries<100*partt->getNumParticles()) ) { - double x,y,z; - x = 0.0+(( (float)(D::mSizex-1) ) * (rand()/(RAND_MAX+1.0)) ); - y = 0.0+(( (float)(D::mSizey-1) ) * (rand()/(RAND_MAX+1.0)) ); - z = 0.0+(( (float) getForZMax1(mMaxRefine) )* (rand()/(RAND_MAX+1.0)) ); - int i = (int)(x-0.5); - int j = (int)(y-0.5); - int k = (int)(z-0.5); - if(D::cDimension==2) { + LbmFloat x,y,z; + x = 0.0+(( (LbmFloat)(this->mSizex-1) ) * (rand()/(RAND_MAX+1.0)) ); + y = 0.0+(( (LbmFloat)(this->mSizey-1) ) * (rand()/(RAND_MAX+1.0)) ); + z = 0.0+(( (LbmFloat) getForZMax1(mMaxRefine) )* (rand()/(RAND_MAX+1.0)) ); + int i = (int)(x+0.5); + int j = (int)(y+0.5); + int k = (int)(z+0.5); + if(LBMDIM==2) { k = 0; z = 0.5; // place in the middle of domain } if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) || - TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) ) { // only fluid cells? + TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { // only fluid cells? // in fluid... partt->addParticle(x,y,z); + partt->getLast()->setStatus(PART_IN); + partt->getLast()->setType(PART_BUBBLE); num++; } tries++; } - debMsgStd("LbmFsgrSolver::initParticles",DM_MSG,"Added "<<num<<" particles ", 10); + + + // DEBUG TEST +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { + const bool partDebug=false; + if(mpTest->mDebugvalue2!=0.0){ errMsg("LbmTestdata"," part init "<<mpTest->mDebugvalue2); } + if(mpTest->mDebugvalue2==-12.0){ + const int lev = mMaxRefine; + for(int i=5;i<15;i++) { + LbmFloat x,y,z; + y = 0.5+(LbmFloat)(i); + x = mLevel[lev].lSizex/20.0*10.0; + z = mLevel[lev].lSizez/20.0*2.0; + partt->addParticle(x,y,z); + partt->getLast()->setStatus(PART_IN); + partt->getLast()->setType(PART_BUBBLE); + partt->getLast()->setSize( (-4.0+(LbmFloat)i)/1.0 ); + if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); + } + } + if(mpTest->mDebugvalue2==-11.0){ + const int lev = mMaxRefine; + for(int i=5;i<15;i++) { + LbmFloat x,y,z; + y = 10.5+(LbmFloat)(i); + x = mLevel[lev].lSizex/20.0*10.0; + z = mLevel[lev].lSizez/20.0*40.0; + partt->addParticle(x,y,z); + partt->getLast()->setStatus(PART_IN); + partt->getLast()->setType(PART_DROP); + partt->getLast()->setSize( (-4.0+(LbmFloat)i)/1.0 ); + if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); + } + } + if(mpTest->mDebugvalue2==-10.0){ + const int lev = mMaxRefine; + const int sx = mLevel[lev].lSizex; + const int sy = mLevel[lev].lSizey; + //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) { + //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) { + for(int j=-(int)(sy*0.5);j<(int)(1.5*sy);++j) { for(int i=-(int)(sx*0.5);i<(int)(1.5*sx);++i) { + //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) { + LbmFloat x,y,z; + x = 0.0+(LbmFloat)(i); + y = 0.0+(LbmFloat)(j); + //z = 0.5+(LbmFloat)(k); + z = mLevel[lev].lSizez/20.0*8.0 - 1.0; + partt->addParticle(x,y,z); + //if( (i>0)&&(i<sx) && (j>0)&&(j<sy) ) { partt->getLast()->setStatus(PART_IN); } else { partt->getLast()->setStatus(PART_OUT); } + partt->getLast()->setStatus(PART_IN); + partt->getLast()->setType(PART_FLOAT); + partt->getLast()->setSize( 15.0 ); + if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() ); + } + } } + } + // DEBUG TEST +#endif // LBM_INCLUDE_TESTSOLVERS + + + debMsgStd("LbmFsgrSolver::initParticles",DM_MSG,"Added "<<num<<" particles, genProb:"<<this->mPartGenProb, 10); if(num != partt->getNumParticles()) return 1; -#endif // ELBEEM_PLUGIN return 0; } -template<class D> -void LbmFsgrSolver<D>::advanceParticles(ParticleTracer *partt) { -#if ELBEEM_PLUGIN==1 - partt = NULL; // remove warning -#else // ELBEEM_PLUGIN +void LbmFsgrSolver::advanceParticles(ParticleTracer *partt) { int workSet = mLevel[mMaxRefine].setCurr; LbmFloat vx=0.0,vy=0.0,vz=0.0; LbmFloat rho, df[27]; //feq[27]; - if(mpParticles!=partt) { errMsg("LbmFsgrSolver<D>::advanceParticles","Invalid ParticleTracer..."); } + if(mpParticles!=partt) { errMsg("LbmFsgrSolver::advanceParticles","Invalid ParticleTracer..."); } +#define DEL_PART { \ + /*errMsg("PIT","DEL AT "<< __LINE__<<" type:"<<p->getType()<<" "); */ \ + p->setActive( false ); \ + continue; } + + myTime_t parttstart = getTime(); + const LbmFloat cellsize = this->mpParam->getCellSize(); + const LbmFloat timestep = this->mpParam->getTimestep(); + //const LbmFloat viscAir = 1.79 * 1e-5; // RW2L kin. viscosity, mu + const LbmFloat viscWater = 1.0 * 1e-6; // RW2L kin. viscosity, mu + const LbmFloat rhoAir = 1.2; // [kg m^-3] RW2L + const LbmFloat rhoWater = 1000.0; // RW2L + const LbmFloat minDropSize = 0.0005; // [m], = 2mm RW2L + const LbmVec velAir(0.); // [m / s] + + const LbmFloat r1 = 0.005; // r max + const LbmFloat r2 = 0.0005; // r min + const LbmFloat v1 = 9.0; // v max + const LbmFloat v2 = 2.0; // v min + const LbmVec rwgrav = vec2L( this->mpParam->getGravity(mSimulationTime) ); // TODO use timestep size + //bool isIn,isOut,isInZ; + //const int cutval = 1+mCutoff/2; // TODO FIXME add half border! + //const int cutval = mCutoff/2; // TODO FIXME add half border! + //const int cutval = 0; // TODO FIXME add half border! + const int cutval = mCutoff; // use full border!? + int actCnt=0; + if(this->mStepCnt%50==49) { partt->cleanup(); } for(vector<ParticleObject>::iterator pit= partt->getParticlesBegin(); pit!= partt->getParticlesEnd(); pit++) { - //errorOut(" pit "<< (*pit).getPos() ); + //errMsg("PIT"," pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags())<<" vel:"<< (*pit).getVel() ); + //errMsg("PIT"," pit pos:"<< (*pit).getPos()<<" vel:"<< (*pit).getVel()<<" status:"<<convertFlags2String((*pit).getFlags()) <<" " <<partt->getStart()<<" "<<partt->getEnd() ); + //int flag = (*pit).getFlags(); if( (*pit).getActive()==false ) continue; int i,j,k; ParticleObject *p = &(*pit); + p->setLifeTime(p->getLifeTime()+1); // nearest neighbor, particle positions don't include empty bounds ntlVec3Gfx pos = p->getPos(); i= (int)(pos[0]+0.5); j= (int)(pos[1]+0.5); k= (int)(pos[2]+0.5); - if(D::cDimension==2) { + if(LBMDIM==2) { k = 0; } - if( (i<0)||(i>D::mSizex-1)|| - (j<0)||(j>D::mSizey-1)|| - (k<0)||(k>D::mSizez-1) ) { - p->setActive( false ); - continue; + // only testdata handling, all for sws +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { + if(mpTest->mDebugvalue1>0.0){ + p->setStatus(PART_OUT); + mpTest->handleParticle(p, i,j,k); continue; + } } +#endif // LBM_INCLUDE_TESTSOLVERS==1 + + if(p->getStatus()&PART_IN) { // IN + if( (i<cutval)||(i>this->mSizex-1-cutval)|| + (j<cutval)||(j>this->mSizey-1-cutval) + //||(k<cutval)||(k>this->mSizez-1-cutval) + ) { + if(!mUseTestdata) { DEL_PART; + } else { + p->setStatus(PART_OUT); + /* del? */ //if((rand()/(RAND_MAX+1.0))<0.5) DEL_PART; + } + } + } else { // OUT rough check + // check in again? + if( (i>=cutval)&&(i<=this->mSizex-1-cutval)&& + (j>=cutval)&&(j<=this->mSizey-1-cutval) + //&&(k>=cutval)&&(k<=this->mSizez-1-cutval) + ) { + p->setStatus(PART_IN); + /* del? */ //if((rand()/(RAND_MAX+1.0))<0.5) DEL_PART; + } } + //p->setStatus(PART_OUT);// DEBUG always out! + + if(p->getType()==PART_BUBBLE) { - if(p->getStatus()==0) { // no interpol rho = vx = vy = vz = 0.0; - FORDF0{ - LbmFloat cdf = QCELL(mMaxRefine, i,j,k, workSet, l); - df[l] = cdf; - rho += cdf; - vx += (D::dfDvecX[l]*cdf); - vy += (D::dfDvecY[l]*cdf); - vz += (D::dfDvecZ[l]*cdf); - } + if(p->getStatus()&PART_IN) { // IN + if(k>=cutval) { + if(k>this->mSizez-1-cutval) DEL_PART; + FORDF0{ + LbmFloat cdf = QCELL(mMaxRefine, i,j,k, workSet, l); + df[l] = cdf; + rho += cdf; + vx += (this->dfDvecX[l]*cdf); + vy += (this->dfDvecY[l]*cdf); + vz += (this->dfDvecZ[l]*cdf); + } - // remove gravity influence - //FORDF0{ feq[l] = D::getCollideEq(l, rho,vx,vy,vz); } - //const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feq); - //const LbmFloat lesomega = D::getLesOmega(mLevel[mMaxRefine].omega,mLevel[mMaxRefine].lcsmago,Qo); - const LbmFloat lesomega = mLevel[mMaxRefine].omega; // no les - vx -= mLevel[mMaxRefine].gravity[0] * lesomega*0.5; - vy -= mLevel[mMaxRefine].gravity[1] * lesomega*0.5; - vz -= mLevel[mMaxRefine].gravity[2] * lesomega*0.5; - - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) || - TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { - // still ok - } else { - // out of bounds, deactivate... - // FIXME make fsgr treatment - p->setActive( false ); - continue; - D::mNumParticlesLost++; + // remove gravity influence + const LbmFloat lesomega = mLevel[mMaxRefine].omega; // no les + vx -= mLevel[mMaxRefine].gravity[0] * lesomega*0.5; + vy -= mLevel[mMaxRefine].gravity[1] * lesomega*0.5; + vz -= mLevel[mMaxRefine].gravity[2] * lesomega*0.5; + + if( RFLAG(mMaxRefine, i,j,k, workSet)&(CFFluid) ) { + // still ok + } else { // OUT + // out of bounds, deactivate... + // FIXME make fsgr treatment + p->setType( PART_FLOAT ); continue; + } + } else { + // below 3d region, just rise + } + } else { // OUT +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { mpTest->handleParticle(p, i,j,k); } + else DEL_PART; +#else // LBM_INCLUDE_TESTSOLVERS==1 + DEL_PART; +#endif // LBM_INCLUDE_TESTSOLVERS==1 + // TODO use x,y vel...? } - p->advance( vx,vy,vz ); - // fluid particle - } else { - p->setVel( p->getVel() * 0.999 ); // dampen... - p->addToVel( vec2G(mLevel[mMaxRefine].gravity) ); + ntlVec3Gfx v = p->getVel(); // dampen... + if(mUseTestdata) { + // test rise + //O vz = p->getVel()[2]-0.5*mLevel[mMaxRefine].gravity[2]; + + LbmFloat radius = p->getSize() * minDropSize; + LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity + LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity + LbmVec velRel = velWater - velPart; + LbmFloat velRelNorm = norm(velRel); + // TODO calculate values in lattice units, compute CD?!??! + LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3 + //const LbmFloat cd = + + LbmVec fb = -rwgrav* pvolume *rhoWater; + LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater; + LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize); + //LbmVec change = (fb+fd) *timestep / (pvolume*rhoAir) *(timestep/cellsize); + //actCnt++; // should be after active test + if(actCnt<0) { + errMsg("\nPIT","BTEST1 vol="<<pvolume<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel); + errMsg("PIT","BTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscW="<<viscWater<<" ss/mb="<<(timestep/(pvolume*rhoAir))); + errMsg("PIT","BTEST2 grav="<<rwgrav<<" " ); + errMsg("PIT","BTEST2 change="<<(change)<<" fb="<<(fb)<<" fd="<<(fd)<<" "); + errMsg("PIT","BTEST2 change="<<norm(change)<<" fb="<<norm(fb)<<" fd="<<norm(fd)<<" "); +#if LOOPTEST==1 + errMsg("PIT","BTEST2 n="<<n<<" "); // LOOPTEST! DEBUG +#endif // LOOPTEST==1 + errMsg("PIT","\n"); + } + + //v += change; + //v += ntlVec3Gfx(vx,vy,vz); + LbmVec fd2 = (LbmVec(vx,vy,vz)-vec2L(p->getVel())) * 6.0*M_PI*radius* (1e-3); //viscWater; + LbmFloat w = 0.99; + vz = (1.0-w)*vz + w*(p->getVel()[2]-0.5*(p->getSize()/5.0)*mLevel[mMaxRefine].gravity[2]); + v = ntlVec3Gfx(vx,vy,vz)+vec2G(fd2); + } + p->setVel( v ); + //p->setVel( ntlVec3Gfx(vx,vy,vz) ); p->advanceVel(); - //errMsg("NNNPART"," at "<<p->getPos()<<" u="<<p->getVel() ); - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) || - TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { - // still ok + // fluid particle + } + + // drop handling + else if(p->getType()==PART_DROP) { + ntlVec3Gfx v = p->getVel(); // dampen... + + if(1) { + LbmFloat radius = p->getSize() * minDropSize; + LbmVec velPart = vec2L(p->getVel()) *cellsize /timestep; // * cellsize / timestep; // L2RW, lattice velocity + LbmVec velRel = velAir - velPart; + //LbmVec velRelLat = velRel /cellsize*timestep; // L2RW + LbmFloat velRelNorm = norm(velRel); + // TODO calculate values in lattice units, compute CD?!??! + LbmFloat mb = rhoWater * 4.0/3.0 * M_PI* radius*radius*radius; // mass: 4/3 pi r^3 rho + const LbmFloat rw = (r1-radius)/(r1-r2); + const LbmFloat rmax = (0.5 + 0.5*rw); + const LbmFloat vmax = (v2 + (v1-v2)* (1.0-rw) ); + const LbmFloat cd = (rmax) * (velRelNorm)/(vmax); + + LbmVec fg = rwgrav * mb;// * (1.0-rhoAir/rhoWater); + LbmVec fd = velRel* velRelNorm* cd*M_PI *rhoAir *0.5 *radius*radius; + LbmVec change = (fg+ fd ) *timestep / mb *(timestep/cellsize); + + //actCnt++; // should be after active test + if(actCnt<0) { + errMsg("\nPIT","NTEST1 mb="<<mb<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel<<" pgetVel="<<p->getVel() ); + //errMsg("PIT","NTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscAir="<<viscAir<<" ss/mb="<<(timestep/mb)); + //errMsg("PIT","NTEST2 grav="<<rwgrav<<" mb="<<mb<<" "<<" cd="<<cd ); + //errMsg("PIT","NTEST2 change="<<norm(change)<<" fg="<<norm(fg)<<" fd="<<norm(fd)<<" "); + } + + v += vec2G(change); + p->setVel(v); + // NEW } else { - // out of bounds, deactivate... - // FIXME make fsgr treatment - p->setActive( false ); - continue; - D::mNumParticlesLost++; + p->setVel( v * 0.999 ); // dampen... + p->setVel( v ); // DEBUG! + p->addToVel( vec2G(mLevel[mMaxRefine].gravity) );\ + } // OLD + p->advanceVel(); + + if(p->getStatus()&PART_IN) { // IN + if(k<cutval) { DEL_PART; continue; } + if(k<=this->mSizez-1-cutval){ + //if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFEmpty|CFInter)) { + if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFEmpty)) { + // still ok + } else if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFInter) ){ + // FIXME make fsgr treatment + if(p->getLifeTime()>50) { + p->setType( PART_FLOAT ); continue; + } else DEL_PART; + } else { + DEL_PART; + this->mNumParticlesLost++; + } + } + } else { // OUT +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { mpTest->handleParticle(p, i,j,k); } + else{ DEL_PART; } +#else // LBM_INCLUDE_TESTSOLVERS==1 + { DEL_PART; } +#endif // LBM_INCLUDE_TESTSOLVERS==1 } + } // air particle + + // inter particle + else if(p->getType()==PART_INTER) { + if(p->getStatus()&PART_IN) { // IN + if((k<cutval)||(k>this->mSizez-1-cutval)) { + // undecided particle above or below... remove? + DEL_PART; + } + + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { + // still ok + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) ) { + //errMsg("PIT","NEWBUB pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) ); + + //p->setType( PART_BUBBLE ); continue; + // currently bubbles off! DEBUG! + DEL_PART; // DEBUG bubbles off for siggraph + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) { + //errMsg("PIT","NEWDROP pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) ); + //? if(p->getLifeTime()>50) { + // only use drops that really flew for a while...? + //? } else DEL_PART; + //if( (i<=cutval)||(i>=this->mSizex-1-cutval)|| + //(j<=cutval)||(j>=this->mSizey-1-cutval)) { + //} else + //if(p->getLifeTime()>10) { + p->setType( PART_DROP ); continue; + //} else DEL_PART; + + } + } else { // OUT + // undecided particle outside... remove? + DEL_PART; + } + } + + // float particle + else if(p->getType()==PART_FLOAT) { + // test - delte on boundary!? + //if( (i<=cutval)||(i>=this->mSizex-1-cutval)|| (j<=cutval)||(j>=this->mSizey-1-cutval)) { DEL_PART; } // DEBUG TEST + + LbmFloat prob = 1.0; +#if LBM_INCLUDE_TESTSOLVERS==1 + // vanishing + prob = (rand()/(RAND_MAX+1.0)); + if((mUseTestdata)&&(k>mpTest->mFluidHeight)) { + LbmFloat fac = (LbmFloat)(k-mpTest->mFluidHeight)/(LbmFloat)(10*(mLevel[mMaxRefine].lSizez-mpTest->mFluidHeight)); + prob /= fac; // TODO test? errMsg("T","T "<<prob<<" "<<fac); + } + if(prob<mLevel[mMaxRefine].timestep*0.1) DEL_PART; +#else // LBM_INCLUDE_TESTSOLVERS==1 +#endif // LBM_INCLUDE_TESTSOLVERS==1 + + if(p->getStatus()&PART_IN) { // IN + if((k<cutval)||(k>this->mSizez-1-cutval)) DEL_PART; + //ntlVec3Gfx v = getVelocityAt(i,j,k); + rho = vx = vy = vz = 0.0; + + //const int DEPTH_AVG=11; // TODO how much!? + const int DEPTH_AVG=7; // TODO how much!? + int ccnt=0; + for(int kk=1;kk<DEPTH_AVG;kk+=2) { + //for(int kk=1;kk<DEPTH_AVG;kk+=1) { + if((k-kk)<1) continue; + if(RFLAG(mMaxRefine, i,j,k, workSet)&(CFFluid|CFInter)) {} else continue; + ccnt++; + FORDF0{ + LbmFloat cdf = QCELL(mMaxRefine, i,j,k-kk, workSet, l); + df[l] = cdf; + //rho += cdf; + vx += (this->dfDvecX[l]*cdf); + vy += (this->dfDvecY[l]*cdf); + vz += (this->dfDvecZ[l]*cdf); + } + } + if(ccnt) { + vx /=(LbmFloat)(ccnt * 1.0); // half xy speed! value2 + vy /=(LbmFloat)(ccnt * 1.0); + vz /=(LbmFloat)(ccnt); } + // forced vanishing + if(k>this->mSizez*3/4) { if(prob<3.0*mLevel[mMaxRefine].timestep*0.1) DEL_PART;} + + if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) ) { + if((1) && (k<this->mSizez-3) && + ( + TESTFLAG( RFLAG(mMaxRefine, i,j,k+1, workSet), CFInter ) || + TESTFLAG( RFLAG(mMaxRefine, i,j,k+2, workSet), CFInter ) ) + ) { + vz = p->getVel()[2]-0.5*mLevel[mMaxRefine].gravity[2]; + if(vz<0.0) vz=0.0; + } else DEL_PART; + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { + // keep in interface , one grid cell offset is added in part. gen + } + // check if above inter, remove otherwise + else if((1) && (k>2) && ( + TESTFLAG( RFLAG(mMaxRefine, i,j,k-1, workSet), CFInter ) || + TESTFLAG( RFLAG(mMaxRefine, i,j,k-2, workSet), CFInter ) ) + ) { + vz = p->getVel()[2]+0.5*mLevel[mMaxRefine].gravity[2]; + if(vz>0.0) vz=0.0; + } else DEL_PART; // */ + /* + // move down from empty + else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) { + vz = p->getVel()[2]+0.5*mLevel[mMaxRefine].gravity[2]; + if(vz>0.0) vz=0.0; + //DEL_PART; // ???? + } else { DEL_PART; } // */ + //vz = 0.0; // DEBUG + ntlVec3Gfx v(vx,vy,vz); + p->setVel( vec2G(v) ); //? + //p->setVel( vec2G(v)*0.75 + p->getVel()*0.25 ); //? + p->advanceVel(); + //errMsg("PIT","IN pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) ); + } else { +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata) { mpTest->handleParticle(p, i,j,k); } + else DEL_PART; +#else // LBM_INCLUDE_TESTSOLVERS==1 + DEL_PART; +#endif // LBM_INCLUDE_TESTSOLVERS==1 + //errMsg("PIT","OUT pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) ); + } + } + + // unknown particle type + else { + errMsg("LbmFsgrSolver::advanceParticles","PIT pit invalid type!? "<<p->getStatus() ); + } } -#endif // ELBEEM_PLUGIN + myTime_t parttend = getTime(); + debMsgStd("LbmFsgrSolver::advanceParticles",DM_MSG,"Time for particle update:"<< getTimeString(parttend-parttstart)<<" "<<partt->getNumParticles() , 10 ); } +void LbmFsgrSolver::notifySolverOfDump(int frameNr,char *frameNrStr,string outfilename) { + // debug - raw dump of ffrac values + if(getenv("ELBEEM_RAWDEBUGDUMP")) { + std::ostringstream name; + //name <<"fill_" << this->mStepCnt <<".dump"; + name << outfilename<< frameNrStr <<".dump"; + FILE *file = fopen(name.str().c_str(),"w"); + if(file) { + + for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) { + for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) { + for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) { + float val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac); + //fwrite( &val, sizeof(val), 1, file); // binary + fprintf(file, "%f ",val); // text + //errMsg("W", PRINT_IJK<<" val:"<<val); + } + fprintf(file, "\n"); // text + } + fprintf(file, "\n"); // text + } + fclose(file); + + } // file + } // */ +} /*****************************************************************************/ /*! internal quick print function (for debugging) */ /*****************************************************************************/ -template<class D> void -LbmFsgrSolver<D>::printLbmCell(int level, int i, int j, int k, int set) { +LbmFsgrSolver::printLbmCell(int level, int i, int j, int k, int set) { stdCellId *newcid = new stdCellId; newcid->level = level; newcid->x = i; @@ -385,15 +782,14 @@ LbmFsgrSolver<D>::printLbmCell(int level, int i, int j, int k, int set) { debugPrintNodeInfo( newcid, set ); delete newcid; } -template<class D> void -LbmFsgrSolver<D>::debugMarkCellCall(int level, int vi,int vj,int vk) { +LbmFsgrSolver::debugMarkCellCall(int level, int vi,int vj,int vk) { stdCellId *newcid = new stdCellId; newcid->level = level; newcid->x = vi; newcid->y = vj; newcid->z = vk; - addCellToMarkedList( newcid ); + this->addCellToMarkedList( newcid ); } @@ -414,9 +810,8 @@ extern int guiRoiMaxLev, guiRoiMinLev; #define CID_EY (int)( (mLevel[cid->level].lSizey-1) * guiRoiEY ) #define CID_EZ (int)( (mLevel[cid->level].lSizez-1) * guiRoiEZ ) -template<class D> CellIdentifierInterface* -LbmFsgrSolver<D>::getFirstCell( ) { +LbmFsgrSolver::getFirstCell( ) { int level = mMaxRefine; #if LBMDIM==3 @@ -434,17 +829,14 @@ LbmFsgrSolver<D>::getFirstCell( ) { return cid; } -template<class D> -typename LbmFsgrSolver<D>::stdCellId* -LbmFsgrSolver<D>::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { +LbmFsgrSolver::stdCellId* +LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { //stdCellId *cid = dynamic_cast<stdCellId*>( basecid ); stdCellId *cid = (stdCellId*)( basecid ); return cid; } -template<class D> -void -LbmFsgrSolver<D>::advanceCell( CellIdentifierInterface* basecid) { +void LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); if(cid->getEnd()) return; @@ -467,39 +859,32 @@ LbmFsgrSolver<D>::advanceCell( CellIdentifierInterface* basecid) { //debugOut(" ADa "<<cid->x<<","<<cid->y<<","<<cid->z<<" e"<<cid->getEnd(), 10); } -template<class D> -bool -LbmFsgrSolver<D>::noEndCell( CellIdentifierInterface* basecid) { +bool LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return (!cid->getEnd()); } -template<class D> -void -LbmFsgrSolver<D>::deleteCellIterator( CellIdentifierInterface** cid ) { +void LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { delete *cid; *cid = NULL; } -template<class D> -CellIdentifierInterface* -LbmFsgrSolver<D>::getCellAt( ntlVec3Gfx pos ) { +CellIdentifierInterface* LbmFsgrSolver::getCellAt( ntlVec3Gfx pos ) { //int cellok = false; - pos -= (D::mvGeoStart); + pos -= (this->mvGeoStart); LbmFloat mmaxsize = mLevel[mMaxRefine].nodeSize; for(int level=mMaxRefine; level>=0; level--) { // finest first //for(int level=0; level<=mMaxRefine; level++) { // coarsest first LbmFloat nsize = mLevel[level].nodeSize; int x,y,z; - //LbmFloat nsize = getCellSize(NULL)[0]*2.0; - x = (int)((pos[0]-0.5*mmaxsize) / nsize ); - y = (int)((pos[1]-0.5*mmaxsize) / nsize ); - z = (int)((pos[2]-0.5*mmaxsize) / nsize ); - if(D::cDimension==2) z = 0; + // CHECK +- maxsize? + x = (int)((pos[0]+0.5*mmaxsize) / nsize ); + y = (int)((pos[1]+0.5*mmaxsize) / nsize ); + z = (int)((pos[2]+0.5*mmaxsize) / nsize ); + if(LBMDIM==2) z = 0; // double check... - //int level = mMaxRefine; if(x<0) continue; if(y<0) continue; if(z<0) continue; @@ -518,7 +903,7 @@ LbmFsgrSolver<D>::getCellAt( ntlVec3Gfx pos ) { newcid->x = x; newcid->y = y; newcid->z = z; - //errMsg("cellAt",D::mName<<" "<<pos<<" l"<<level<<":"<<x<<","<<y<<","<<z<<" "<<convertCellFlagType2String(RFLAG(level, x,y,z, mLevel[level].setCurr)) ); + //errMsg("cellAt",this->mName<<" "<<pos<<" l"<<level<<":"<<x<<","<<y<<","<<z<<" "<<convertCellFlagType2String(RFLAG(level, x,y,z, mLevel[level].setCurr)) ); return newcid; } @@ -528,60 +913,50 @@ LbmFsgrSolver<D>::getCellAt( ntlVec3Gfx pos ) { // INFO functions -template<class D> -int -LbmFsgrSolver<D>::getCellSet ( CellIdentifierInterface* basecid) { +int LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return mLevel[cid->level].setCurr; //return mLevel[cid->level].setOther; } -template<class D> -int -LbmFsgrSolver<D>::getCellLevel ( CellIdentifierInterface* basecid) { +int LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return cid->level; } -template<class D> -ntlVec3Gfx -LbmFsgrSolver<D>::getCellOrigin ( CellIdentifierInterface* basecid) { +ntlVec3Gfx LbmFsgrSolver::getCellOrigin ( CellIdentifierInterface* basecid) { ntlVec3Gfx ret; stdCellId *cid = convertBaseCidToStdCid(basecid); ntlVec3Gfx cs( mLevel[cid->level].nodeSize ); - if(D::cDimension==2) { cs[2] = 0.0; } + if(LBMDIM==2) { cs[2] = 0.0; } - if(D::cDimension==2) { - ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], (D::mvGeoEnd[2]-D::mvGeoStart[2])*0.5 ) + if(LBMDIM==2) { + ret =(this->mvGeoStart + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ) + ntlVec3Gfx(0.0,0.0,cs[1]*-0.25)*cid->level ) +getCellSize(basecid); } else { - ret =(D::mvGeoStart -(cs*0.5) + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], cid->z *cs[2] )) + ret =(this->mvGeoStart + ntlVec3Gfx( cid->x *cs[0], cid->y *cs[1], cid->z *cs[2] )) +getCellSize(basecid); } return (ret); } -template<class D> -ntlVec3Gfx -LbmFsgrSolver<D>::getCellSize ( CellIdentifierInterface* basecid) { +ntlVec3Gfx LbmFsgrSolver::getCellSize ( CellIdentifierInterface* basecid) { // return half size stdCellId *cid = convertBaseCidToStdCid(basecid); ntlVec3Gfx retvec( mLevel[cid->level].nodeSize * 0.5 ); // 2d display as rectangles - if(D::cDimension==2) { retvec[2] = 0.0; } + if(LBMDIM==2) { retvec[2] = 0.0; } return (retvec); } -template<class D> -LbmFloat -LbmFsgrSolver<D>::getCellDensity ( CellIdentifierInterface* basecid,int set) { +LbmFloat LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int set) { stdCellId *cid = convertBaseCidToStdCid(basecid); LbmFloat rho = 0.0; //FORDF0 { rho += QCELL(cid->level, cid->x,cid->y,cid->z, set, l); } // ORG - //return ((rho-1.0) * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize) +1.0; // ORG + //return ((rho-1.0) * mLevel[cid->level].simCellSize / mLevel[cid->level].timestep) +1.0; // ORG if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) { // test LbmFloat ux,uy,uz; ux=uy=uz= 0.0; @@ -589,87 +964,133 @@ LbmFsgrSolver<D>::getCellDensity ( CellIdentifierInterface* basecid,int set) { LbmFloat df[27], feqOld[27]; FORDF0 { rho += QCELL(lev, cid->x,cid->y,cid->z, set, l); - ux += D::dfDvecX[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); - uy += D::dfDvecY[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); - uz += D::dfDvecZ[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); + ux += this->dfDvecX[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); + uy += this->dfDvecY[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); + uz += this->dfDvecZ[l]* QCELL(lev, cid->x,cid->y,cid->z, set, l); df[l] = QCELL(lev, cid->x,cid->y,cid->z, set, l); } FORDF0 { - feqOld[l] = D::getCollideEq(l, rho,ux,uy,uz); + feqOld[l] = getCollideEq(l, rho,ux,uy,uz); } - const LbmFloat Qo = D::getLesNoneqTensorCoeff(df,feqOld); - //const LbmFloat modOmega = D::getLesOmega(mLevel[lev].omega, mLevel[lev].lcsmago,Qo); + // debugging mods + //const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feqOld); + //const LbmFloat modOmega = this->getLesOmega(mLevel[lev].omega, mLevel[lev].lcsmago,Qo); //rho = (2.0-modOmega) *25.0; - rho = Qo*100.0; + //rho = Qo*100.0; //if(cid->x==24){ errMsg("MODOMT"," at "<<PRINT_VEC(cid->x,cid->y,cid->z)<<" = "<<rho<<" "<<Qo); } //else{ rho=0.0; } } // test return rho; // test } -template<class D> -LbmVec -LbmFsgrSolver<D>::getCellVelocity ( CellIdentifierInterface* basecid,int set) { +LbmVec LbmFsgrSolver::getCellVelocity ( CellIdentifierInterface* basecid,int set) { stdCellId *cid = convertBaseCidToStdCid(basecid); + // skip non-fluid cells + if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&(CFFluid|CFInter)) { + // ok go on... + } else { + return LbmVec(0.0); + } + LbmFloat ux,uy,uz; ux=uy=uz= 0.0; FORDF0 { - ux += D::dfDvecX[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - uy += D::dfDvecY[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); - uz += D::dfDvecZ[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + ux += this->dfDvecX[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + uy += this->dfDvecY[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); + uz += this->dfDvecZ[l]* QCELL(cid->level, cid->x,cid->y,cid->z, set, l); } LbmVec vel(ux,uy,uz); // TODO fix... - return (vel * mLevel[cid->level].simCellSize / mLevel[cid->level].stepsize * D::mDebugVelScale); // normal + return (vel * mLevel[cid->level].simCellSize / mLevel[cid->level].timestep * this->mDebugVelScale); // normal } -template<class D> -LbmFloat -LbmFsgrSolver<D>::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { +LbmFloat LbmFsgrSolver::getCellDf( CellIdentifierInterface* basecid,int set, int dir) { stdCellId *cid = convertBaseCidToStdCid(basecid); return QCELL(cid->level, cid->x,cid->y,cid->z, set, dir); } -template<class D> -LbmFloat -LbmFsgrSolver<D>::getCellMass( CellIdentifierInterface* basecid,int set) { +LbmFloat LbmFsgrSolver::getCellMass( CellIdentifierInterface* basecid,int set) { stdCellId *cid = convertBaseCidToStdCid(basecid); return QCELL(cid->level, cid->x,cid->y,cid->z, set, dMass); } -template<class D> -LbmFloat -LbmFsgrSolver<D>::getCellFill( CellIdentifierInterface* basecid,int set) { +LbmFloat LbmFsgrSolver::getCellFill( CellIdentifierInterface* basecid,int set) { stdCellId *cid = convertBaseCidToStdCid(basecid); if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFFluid) return 1.0; return 0.0; //return QCELL(cid->level, cid->x,cid->y,cid->z, set, dFfrac); } -template<class D> -CellFlagType -LbmFsgrSolver<D>::getCellFlag( CellIdentifierInterface* basecid,int set) { +CellFlagType LbmFsgrSolver::getCellFlag( CellIdentifierInterface* basecid,int set) { stdCellId *cid = convertBaseCidToStdCid(basecid); return RFLAG(cid->level, cid->x,cid->y,cid->z, set); } -template<class D> -LbmFloat -LbmFsgrSolver<D>::getEquilDf( int l ) { - return D::dfEquil[l]; +LbmFloat LbmFsgrSolver::getEquilDf( int l ) { + return this->dfEquil[l]; } -template<class D> -int -LbmFsgrSolver<D>::getDfNum( ) { - return D::cDfNum; + +ntlVec3Gfx LbmFsgrSolver::getVelocityAt (float xp, float yp, float zp) { + ntlVec3Gfx avgvel(0.0); + LbmFloat avgnum = 0.; + + // taken from getCellAt! + const int level = mMaxRefine; + const int workSet = mLevel[level].setCurr; + LbmFloat nsize = mLevel[level].nodeSize; + const int x = (int)((-this->mvGeoStart[0]+xp-0.5*nsize) / nsize ); + const int y = (int)((-this->mvGeoStart[1]+yp-0.5*nsize) / nsize ); + int z = (int)((-this->mvGeoStart[2]+zp-0.5*nsize) / nsize ); + if(LBMDIM==2) z=0; + //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) ); + + // return fluid/if/border cells + // search neighborhood, do smoothing + FORDF0{ + int i=x+this->dfVecX[l]; + int j=y+this->dfVecY[l]; + int k=z+this->dfVecZ[l]; + + if( (i<0) || (j<0) || (k<0) + || (i>=mLevel[level].lSizex) + || (j>=mLevel[level].lSizey) + || (k>=mLevel[level].lSizez) ) continue; + + if( (RFLAG(level, i,j,k, mLevel[level].setCurr)&(CFFluid|CFInter)) ) { + ntlVec3Gfx vel(0.0); + LbmFloat *ccel = RACPNT(level, i,j,k ,workSet); // omp + for(int n=1; n<this->cDfNum; n++) { + vel[0] += (this->dfDvecX[n]*RAC(ccel,n)); + vel[1] += (this->dfDvecY[n]*RAC(ccel,n)); + vel[2] += (this->dfDvecZ[n]*RAC(ccel,n)); + } + + avgvel += vel; + avgnum += 1.0; + if(l==0) { // center slightly more weight + avgvel += vel; avgnum += 1.0; + } + } // */ + } + + if(avgnum>0.) { + ntlVec3Gfx retv = avgvel / avgnum; + retv *= nsize/mLevel[level].timestep; + // scale for current animation settings (frame time) + retv *= mpParam->getCurrentAniFrameTime(); + //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() ); + return retv; + } + // no cells here...? + //errMsg("DUMPVEL"," at "<<PRINT_VEC(xp,yp,zp)<<" v"<<avgvel<<" n"<<avgnum<<" no vel !?"); + return ntlVec3Gfx(0.); } #if LBM_USE_GUI==1 //! show simulation info (implement SimulationObject pure virtual func) -template<class D> void -LbmFsgrSolver<D>::debugDisplay(fluidDispSettings *set){ - //lbmDebugDisplay< LbmFsgrSolver<D> >( set, this ); +LbmFsgrSolver::debugDisplay(int set){ + //lbmDebugDisplay< LbmFsgrSolver >( set, this ); lbmDebugDisplay( set ); } #endif @@ -680,8 +1101,7 @@ LbmFsgrSolver<D>::debugDisplay(fluidDispSettings *set){ #if FSGR_STRICT_DEBUG==1 #define STRICT_EXIT *((int *)0)=0; -template<class D> -int LbmFsgrSolver<D>::debLBMGI(int level, int ii,int ij,int ik, int is) { +int LbmFsgrSolver::debLBMGI(int level, int ii,int ij,int ik, int is) { if(level < 0){ errMsg("LbmStrict::debLBMGI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } if(level > mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } @@ -696,28 +1116,24 @@ int LbmFsgrSolver<D>::debLBMGI(int level, int ii,int ij,int ik, int is) { return _LBMGI(level, ii,ij,ik, is); }; -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG(int level, int xx,int yy,int zz,int set){ +CellFlagType& LbmFsgrSolver::debRFLAG(int level, int xx,int yy,int zz,int set){ return _RFLAG(level, xx,yy,zz,set); }; -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { +CellFlagType& LbmFsgrSolver::debRFLAG_NB(int level, int xx,int yy,int zz,int set, int dir) { if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } // warning might access all spatial nbs - if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>this->cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } return _RFLAG_NB(level, xx,yy,zz,set, dir); }; -template<class D> -CellFlagType& LbmFsgrSolver<D>::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { +CellFlagType& LbmFsgrSolver::debRFLAG_NBINV(int level, int xx,int yy,int zz,int set, int dir) { if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>this->cDirNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } return _RFLAG_NBINV(level, xx,yy,zz,set, dir); }; -template<class D> -int LbmFsgrSolver<D>::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { +int LbmFsgrSolver::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { if(level < 0){ errMsg("LbmStrict::debLBMQI"," invLev- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } if(level > mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } @@ -730,44 +1146,39 @@ int LbmFsgrSolver<D>::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { if(is<0){ errMsg("LbmStrict"," invS- l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } if(is>1){ errMsg("LbmStrict"," invS+ l"<<level<<"|"<<ii<<","<<ij<<","<<ik<<" s"<<is); STRICT_EXIT; } if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } - if(l>D::cDfNum){ // dFfrac is an exception + if(l>this->cDfNum){ // dFfrac is an exception if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } #if COMPRESSGRIDS==1 - //if((!D::mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug + //if((!this->mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug #endif // COMPRESSGRIDS==1 return _LBMQI(level, ii,ij,ik, is, l); }; -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL(int level, int xx,int yy,int zz,int set,int l) { +LbmFloat& LbmFsgrSolver::debQCELL(int level, int xx,int yy,int zz,int set,int l) { //errMsg("LbmStrict","debQCELL debug: l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" l"<<l<<" index"<<LBMGI(level, xx,yy,zz,set)); return _QCELL(level, xx,yy,zz,set,l); }; -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { +LbmFloat& LbmFsgrSolver::debQCELL_NB(int level, int xx,int yy,int zz,int set, int dir,int l) { if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>this->cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } return _QCELL_NB(level, xx,yy,zz,set, dir,l); }; -template<class D> -LbmFloat& LbmFsgrSolver<D>::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { +LbmFloat& LbmFsgrSolver::debQCELL_NBINV(int level, int xx,int yy,int zz,int set, int dir,int l) { if(dir<0) { errMsg("LbmStrict"," invD- l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } - if(dir>D::cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } + if(dir>this->cDfNum){ errMsg("LbmStrict"," invD+ l"<<level<<"|"<<xx<<","<<yy<<","<<zz<<" s"<<set<<" d"<<dir); STRICT_EXIT; } return _QCELL_NBINV(level, xx,yy,zz,set, dir,l); }; -template<class D> -LbmFloat* LbmFsgrSolver<D>::debRACPNT(int level, int ii,int ij,int ik, int is ) { +LbmFloat* LbmFsgrSolver::debRACPNT(int level, int ii,int ij,int ik, int is ) { return _RACPNT(level, ii,ij,ik, is ); }; -template<class D> -LbmFloat& LbmFsgrSolver<D>::debRAC(LbmFloat* s,int l) { +LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<<l); STRICT_EXIT; } if(l>dTotalNum){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } - //if(l>D::cDfNum){ // dFfrac is an exception + //if(l>this->cDfNum){ // dFfrac is an exception //if((l != dMass) && (l != dFfrac) && (l != dFlux)){ errMsg("LbmStrict"," invD+ "<<" l"<<l); STRICT_EXIT; } } return _RAC(s,l); }; @@ -785,8 +1196,7 @@ LbmFloat& LbmFsgrSolver<D>::debRAC(LbmFloat* s,int l) { #include "../gui/gui_utilities.h" //! display a single node -template<class D> -void LbmFsgrSolver<D>::debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ) { +void LbmFsgrSolver::debugDisplayNode(int dispset, CellIdentifierInterface* cell ) { //debugOut(" DD: "<<cell->getAsString() , 10); ntlVec3Gfx org = this->getCellOrigin( cell ); ntlVec3Gfx halfsize = this->getCellSize( cell ); @@ -796,7 +1206,7 @@ void LbmFsgrSolver<D>::debugDisplayNode(fluidDispSettings *dispset, CellIdentifi bool showcell = true; int linewidth = 1; ntlColor col(0.5); - LbmFloat cscale = dispset->scale; + LbmFloat cscale = 1.0; //dispset->scale; #define DRAWDISPCUBE(col,scale) \ { glLineWidth( linewidth ); \ @@ -821,7 +1231,7 @@ void LbmFsgrSolver<D>::debugDisplayNode(fluidDispSettings *dispset, CellIdentifi else if(flag& CFFluid ) { if(!guiShowFluid ) return; } - switch(dispset->type) { + switch(dispset) { case FLUIDDISPNothing: { showcell = false; } break; @@ -947,35 +1357,44 @@ void LbmFsgrSolver<D>::debugDisplayNode(fluidDispSettings *dispset, CellIdentifi //! debug display function // D has to implement the CellIterator interface -template<class D> -void LbmFsgrSolver<D>::lbmDebugDisplay(fluidDispSettings *dispset) { - //je nach solver...? - if(!dispset->on) return; +void LbmFsgrSolver::lbmDebugDisplay(int dispset) { + // DEBUG always display testdata +#if LBM_INCLUDE_TESTSOLVERS==1 + if(mUseTestdata){ mpTest->testDebugDisplay(dispset); } +#endif // LBM_INCLUDE_TESTSOLVERS==1 + if(dispset<=FLUIDDISPNothing) return; + //if(!dispset->on) return; glDisable( GL_LIGHTING ); // dont light lines - typename D::CellIdentifier cid = this->getFirstCell(); +#if LBM_INCLUDE_TESTSOLVERS==1 + if((!mUseTestdata)|| (mUseTestdata)&&(mpTest->mDebugvalue1<=0.0)) { +#endif // LBM_INCLUDE_TESTSOLVERS==1 + + LbmFsgrSolver::CellIdentifier cid = this->getFirstCell(); for(; this->noEndCell( cid ); this->advanceCell( cid ) ) { this->debugDisplayNode(dispset, cid ); } delete cid; +#if LBM_INCLUDE_TESTSOLVERS==1 + } // 3d check +#endif // LBM_INCLUDE_TESTSOLVERS==1 + glEnable( GL_LIGHTING ); // dont light lines } //! debug display function // D has to implement the CellIterator interface -template<class D> -void LbmFsgrSolver<D>::lbmMarkedCellDisplay() { - fluidDispSettings dispset; +void LbmFsgrSolver::lbmMarkedCellDisplay() { + //fluidDispSettings dispset; // trick - display marked cells as grid displa -> white, big - dispset.type = FLUIDDISPGrid; - dispset.on = true; + int dispset = FLUIDDISPGrid; glDisable( GL_LIGHTING ); // dont light lines - typename D::CellIdentifier cid = this->markedGetFirstCell(); + LbmFsgrSolver::CellIdentifier cid = this->markedGetFirstCell(); while(cid) { - this->debugDisplayNode(&dispset, cid ); + this->debugDisplayNode(dispset, cid ); cid = this->markedAdvanceCell(); } delete cid; @@ -986,8 +1405,7 @@ void LbmFsgrSolver<D>::lbmMarkedCellDisplay() { #endif // LBM_USE_GUI==1 //! display a single node -template<class D> -void LbmFsgrSolver<D>::debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet) { +void LbmFsgrSolver::debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet) { //string printInfo, // force printing of one set? default = -1 = off bool printDF = false; @@ -1037,7 +1455,7 @@ void LbmFsgrSolver<D>::debugPrintNodeInfo(CellIdentifierInterface* cell, int for debMsgStd(" ",DM_MSG, "Printing set:"<<workset<<" orgSet:"<<set, 1); if(printDF) { - for(int l=0; l<this->getDfNum(); l++) { // FIXME ?? + for(int l=0; l<LBM_DFNUM; l++) { // FIXME ?? debMsgStd(" ",DM_MSG, " Df"<<l<<": "<<this->getCellDf(cell,workset,l), 1); } } @@ -1054,24 +1472,9 @@ void LbmFsgrSolver<D>::debugPrintNodeInfo(CellIdentifierInterface* cell, int for if(printMass) { debMsgStd(" ",DM_MSG, " Mss: "<<this->getCellMass(cell,workset), 1); } + // dirty... TODO fixme + debMsgStd(" ",DM_MSG, " Flx: "<<this->getCellDf(cell,workset,dFlux), 1); } } -#endif // !defined(__APPLE_CC__) || defined(LBM_FORCEINCLUDE) - -/****************************************************************************** - * instantiation - *****************************************************************************/ -#if ((!defined(__APPLE_CC__)) && (!defined(__INTEL_COMPILER))) && (!defined(LBM_FORCEINCLUDE)) - -#if LBMDIM==2 -#define LBM_INSTANTIATE LbmBGK2D -#endif // LBMDIM==2 -#if LBMDIM==3 -#define LBM_INSTANTIATE LbmBGK3D -#endif // LBMDIM==3 - -template class LbmFsgrSolver< LBM_INSTANTIATE >; - -#endif // __APPLE_CC__ __INTEL_COMPILER diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp index 340a306c7f1..7cb4dd50577 100644 --- a/intern/elbeem/intern/utilities.cpp +++ b/intern/elbeem/intern/utilities.cpp @@ -30,8 +30,8 @@ extern "C" void simulateThreadIncreaseFrame(void); extern "C" SDL_mutex *globalBakeLock; // global state variables extern "C" int globalBakeState; -extern "C" int globalBakeFrame; -#endif // ELBEEM_BLENDER==1 +//extern "C" int globalBakeFrame; not needed...? +#endif // ELBEEM_PLUGIN==1 #include "utilities.h" @@ -184,8 +184,9 @@ myTime_t getTime() string getTimeString(myTime_t usecs) { std::ostringstream ret; //myTime_t us = usecs % 1000; - myTime_t ms = usecs / (60*1000); - myTime_t ss = (usecs / 1000) - (ms*60); + myTime_t ms = (myTime_t)( (double)usecs / (60.0*1000.0) ); + myTime_t ss = (myTime_t)( ((double)usecs / 1000.0) - ((double)ms*60.0) ); + int ps = (int)( ((double)usecs - (double)ss*1000.0)/10.0 ); //ret.setf(ios::showpoint|ios::fixed); //ret.precision(5); ret.width(7); @@ -193,7 +194,13 @@ string getTimeString(myTime_t usecs) { if(ms>0) { ret << ms<<"m"<< ss<<"s" ; } else { - ret << ss<<"s" ; + if(ps>0) { + ret << ss<<"."; + if(ps<10) { ret <<"0"; } + ret <<ps<<"s" ; + } else { + ret << ss<<"s" ; + } } return ret.str(); } @@ -368,6 +375,7 @@ double elbeemEstimateMemreq(int res, #if ELBEEM_BLENDER==1 +// Blender state sync void setGlobalBakeState(int set) { SDL_mutexP(globalBakeLock); globalBakeState = set; diff --git a/intern/elbeem/intern/utilities.h b/intern/elbeem/intern/utilities.h index 19d93c3a91c..3ba023e4730 100644 --- a/intern/elbeem/intern/utilities.h +++ b/intern/elbeem/intern/utilities.h @@ -27,13 +27,13 @@ bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker); /* debugging outputs , debug level 0 (off) to 10 (max) */ -#ifdef ELBEEM_BLENDER +#ifdef ELBEEM_PLUGIN #define DEBUG 0 void setGlobalBakeState(int set); int getGlobalBakeState(void); -#else // ELBEEM_BLENDER +#else // ELBEEM_PLUGIN #define DEBUG 10 -#endif // ELBEEM_BLENDER +#endif // ELBEEM_PLUGIN extern "C" int gDebugLevel; // state of the simulation world diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index c51a50dd313..89ac6040eb6 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -555,26 +555,46 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3] mdm->freeNors = 0; mdm->freeVerts = 0; - if (vertCos) { + if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&& + (ob->fluidsimSettings->meshSurface) && + (me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert) ) { + // dont recompute for fluidsim mesh, use from readBobjgz + // TODO? check for modifiers!? int i; - - /* copy the original verts to preserve flag settings; if this is too - * costly, must at least use MEM_callocN to clear flags */ - mdm->verts = MEM_dupallocN( me->mvert ); - for (i=0; i<me->totvert; i++) { - VECCOPY(mdm->verts[i].co, vertCos[i]); - } mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors); mdm->freeNors = 1; - mdm->freeVerts = 1; + for (i=0; i<me->totvert; i++) { + MVert *mv= &mdm->verts[i]; + MVert *fsv; + fsv = &ob->fluidsimSettings->meshSurfNormals[i]; + VECCOPY(mv->no, fsv->no); + //mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals + } } else { + // recompute normally + + if (vertCos) { + int i; + + /* copy the original verts to preserve flag settings; if this is too + * costly, must at least use MEM_callocN to clear flags */ + mdm->verts = MEM_dupallocN( me->mvert ); + for (i=0; i<me->totvert; i++) { + VECCOPY(mdm->verts[i].co, vertCos[i]); + } + mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors); + mdm->freeNors = 1; + mdm->freeVerts = 1; + } else { // XXX this is kinda hacky because we shouldn't really be editing // the mesh here, however, we can't just call mesh_build_faceNormals(ob) // because in the case when a key is applied to a mesh the vertex normals // would never be correctly computed. - mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors); - mdm->freeNors = 1; - } + mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors); + mdm->freeNors = 1; + } + } // fs TEST return (DerivedMesh*) mdm; } @@ -2072,8 +2092,9 @@ void writeBobjgz(char *filename, struct Object *ob) wri = dlm->totvert; gzwrite(gzf, &wri, sizeof(wri)); for(i=0; i<wri;i++) { - VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */ - Mat4MulVecfl(ob->obmat, vec); + VECCOPY(vec, dlm->mvert[i].co); + //VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */ + //Mat4MulVecfl(ob->obmat, vec); for(j=0; j<3; j++) { wrf = vec[j]; gzwrite(gzf, &wrf, sizeof( wrf )); @@ -2087,7 +2108,8 @@ void writeBobjgz(char *filename, struct Object *ob) for(i=0; i<wri;i++) { VECCOPY(vec, dlm->mvert[i].no); // FIXME divide? mv->no[0]= (short)(no[0]*32767.0); - Mat3MulVecfl(rotmat, vec); + //VECCOPY(vec, dlm->mvert[i].no); + //Mat3MulVecfl(rotmat, vec); Normalise(vec); for(j=0; j<3; j++) { wrf = vec[j]; @@ -2130,8 +2152,63 @@ void writeBobjgz(char *filename, struct Object *ob) dm->release(dm); } +void initElbeemMesh(struct Object *ob, + int *numVertices, float **vertices, + int *numTriangles, int **triangles) +{ + DispListMesh *dlm = NULL; + DerivedMesh *dm = NULL; + MFace *mface = NULL; + int countTris=0, i; + float *verts; + int *tris; + + dm = mesh_create_derived_render(ob); + if(!dm) { *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; } + dlm = dm->convertToDispListMesh(dm, 1); + if(!dlm) { dm->release(dm); *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; } + mface = dlm->mface; + + *numVertices = dlm->totvert; + verts = MEM_callocN( dlm->totvert*3*sizeof(float), "elbeemmesh_vertices"); + for(i=0; i<dlm->totvert; i++) { + VECCOPY( &verts[i*3], dlm->mvert[i].co); + } + *vertices = verts; + + for(i=0; i<dlm->totface; i++) { + countTris++; + if(mface[i].v4) { countTris++; } + } + *numTriangles = countTris; + tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles"); + countTris = 0; + for(i=0; i<dlm->totface; i++) { + int face[4]; + face[0] = mface[i].v1; + face[1] = mface[i].v2; + face[2] = mface[i].v3; + face[3] = mface[i].v4; + + tris[countTris*3+0] = face[0]; + tris[countTris*3+1] = face[1]; + tris[countTris*3+2] = face[2]; + countTris++; + if(face[3]) { + tris[countTris*3+0] = face[0]; + tris[countTris*3+1] = face[2]; + tris[countTris*3+2] = face[3]; + countTris++; + } + } + *triangles = tris; + + if(dlm) displistmesh_free(dlm); + dm->release(dm); +} + /* read .bobj.gz file into a fluidsimDerivedMesh struct */ -Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm) +Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm) { int wri,i,j; char debugStrBuffer[256]; @@ -2211,9 +2288,13 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm) for(i=0; i<newmesh->totvert;i++) { for(j=0; j<3; j++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); - newmesh->mvert[i].no[j] = wrf*32767.0; + newmesh->mvert[i].no[j] = (short)(wrf*32767.0f); + //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst } + //fprintf(stderr," DEBDPCN nm%d, %d = %d,%d,%d \n", + //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]); } + //fprintf(stderr," DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]); /* compute no. of triangles */ @@ -2258,6 +2339,61 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm) return newmesh; } +/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */ +void readVelgz(char *filename, Object *srcob) +{ + char debugStrBuffer[256]; + int wri, i, j; + float wrf; + gzFile gzf; + MVert *vverts = srcob->fluidsimSettings->meshSurfNormals; + int len = strlen(filename); + Mesh *mesh = srcob->data; + // mesh and vverts have to be valid from loading... + + // clean up in any case + for(i=0; i<mesh->totvert;i++) { + for(j=0; j<3; j++) { + vverts[i].co[j] = 0.; + } + } + if(srcob->fluidsimSettings->typeFlags&OB_FSDOMAIN_NOVECGEN) return; + + if(len<7) { + //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG + return; + } + + // .bobj.gz , correct filename + // 87654321 + filename[len-6] = 'v'; + filename[len-5] = 'e'; + filename[len-4] = 'l'; + + snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer); + gzf = gzopen(filename, "rb"); + if (!gzf) { + //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG + return; + } + + gzread(gzf, &wri, sizeof( wri )); + if(wri != mesh->totvert) { + //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG + return; + } + + for(i=0; i<mesh->totvert;i++) { + for(j=0; j<3; j++) { + gzread(gzf, &wrf, sizeof( wrf )); + vverts[i].co[j] = wrf; + } + //if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG + } + + gzclose(gzf); +} + /* ***************************** fluidsim derived mesh ***************************** */ @@ -2297,6 +2433,9 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams) if(srcob->data == srcob->fluidsimSettings->meshSurface) srcob->data = srcob->fluidsimSettings->orgMesh; srcob->fluidsimSettings->meshSurface = NULL; + + if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals); + srcob->fluidsimSettings->meshSurfNormals = NULL; } // init bounding box @@ -2305,7 +2444,7 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams) lastBB[0] = bbSize[0]; // TEST lastBB[1] = bbSize[1]; lastBB[2] = bbSize[2]; - fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize); + fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB); // check free fsmesh... TODO if(!useRenderParams) { @@ -2314,7 +2453,8 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams) displaymode = srcob->fluidsimSettings->renderDisplayMode; } - snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug + snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n", + srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug elbeemDebugOut(debugStrBuffer); // debug strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR); @@ -2335,7 +2475,11 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams) snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile); // debug elbeemDebugOut(debugStrBuffer); // debug - mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ); + if(displaymode!=2) { // dont add bounding box for final + mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL); + } else { + mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize ); + } if(!mesh) { // display org. object upon failure srcob->data = srcob->fluidsimSettings->orgMesh; @@ -2347,13 +2491,27 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams) } srcob->fluidsimSettings->meshSurface = mesh; srcob->data = mesh; + srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert); + + // load vertex velocities, if they exist... + // TODO? use generate flag as loading flag as well? + // warning, needs original .bobj.gz mesh loading filename + if(displaymode==3) { + readVelgz(targetFile, srcob); + } else { + // no data for preview, only clear... + int i,j; + for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} + } + + //fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]); return; } /* helper function */ /* init axis aligned BB for mesh object */ void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4], - /*RET*/ float start[3], /*RET*/ float size[3] ) + /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh ) { float bbsx=0.0, bbsy=0.0, bbsz=0.0; float bbex=1.0, bbey=1.0, bbez=1.0; @@ -2388,6 +2546,25 @@ void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4], size[1] = bbey-bbsy; size[2] = bbez-bbsz; } + + // init bounding box mesh? + if(bbmesh) { + int i,j; + Mesh *newmesh = NULL; + if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); } + else { newmesh = *bbmesh; } + + newmesh->totvert = 8; + if(!newmesh->mvert) newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimBBMesh_bobjvertices"); + for(i=0; i<8; i++) { + for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j]; + } + + newmesh->totface = 6; + if(!newmesh->mface) newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimBBMesh_bobjfaces"); + + *bbmesh = newmesh; + } } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 51701c19ca0..9d8857d4119 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1610,8 +1610,8 @@ static void dag_object_time_update_flags(Object *ob) } if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings)) { // fluidsimSettings might not be initialized during load... - if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) { - ob->recalc |= OB_RECALC_DATA; // NT + if(ob->fluidsimSettings->type & (OB_FLUIDSIM_DOMAIN|OB_FLUIDSIM_PARTICLE)) { + ob->recalc |= OB_RECALC_DATA; // NT FSPARTICLE } } break; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 663fe02aaf0..2a95bd82872 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -51,6 +51,11 @@ #include "DNA_object_force.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" +// FSPARTICLE +#include "DNA_object_fluidsim.h" +#include "LBM_fluidsim.h" +#include <zlib.h> +#include <string.h> #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -1594,6 +1599,7 @@ void build_particle_system(Object *ob) float *volengths= NULL, *folengths= NULL; int deform=0, a, totpart, paf_sta, paf_end; int waitcursor_set= 0, totvert, totface, curface, curvert; + int readMask =0, activeParts; /* return conditions */ if(ob->type!=OB_MESH) return; @@ -1604,6 +1610,104 @@ void build_particle_system(Object *ob) if(paf->keys) MEM_freeN(paf->keys); /* free as early as possible, for returns */ paf->keys= NULL; + // FSPARTICLE all own created... + if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (ob->fluidsimSettings) && + (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) { + char *suffix = "fluidsurface_particles_#"; + char *suffix2 = ".gz"; + char filename[256]; + int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading + int j, numFileParts; + gzFile gzf; + float vel[3]; + + if(ob==G.obedit) { // off... + paf->totpart = 1; + return; + } + + // ok, start loading + strcpy(filename, ob->fluidsimSettings->surfdataPath); + strcat(filename, suffix); + BLI_convertstringcode(filename, G.sce, curFrame); // fixed #frame-no + strcat(filename, suffix2); + + gzf = gzopen(filename, "rb"); + if (!gzf) { + //char debugStrBuffer[256]; + //define win32... snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s'\n", filename); + //elbeemDebugOut(debugStrBuffer); + paf->totpart = 1; + return; + } + + gzread(gzf, &totpart, sizeof(totpart)); + numFileParts = totpart; + totpart = (G.rendering)?totpart:(paf->disp*totpart)/100; + paf->totpart= totpart; + paf->totkey= 1; + /* initialize particles */ + new_particle(paf);// ? + ftime = 0.0; + dtime= 0.0f; + + // set up reading mask + //for(j=1; j<=4; j++ ){ if(ob->fluidsimSettings->guiDisplayMode&j) readMask |= (1<<j); } + readMask = ob->fluidsimSettings->guiDisplayMode; + activeParts=0; + // FIXME only allocate needed ones? + + //fprintf(stderr,"FSPARTICLE debug set %s , tot%d mask=%d \n", filename, totpart, readMask ); + for(a=0; a<totpart; a++, ftime+=dtime) { + int ptype=0; + short shsize=0; + float convertSize=0.0; + gzread(gzf, &ptype, sizeof( ptype )); + //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d t=%d , mask=%d , active%d\n", filename, a, ptype, readMask, activeParts ); + if(ptype&readMask) { + activeParts++; + pa= new_particle(paf); + pa->time= ftime; + pa->lifetime= ftime + G.scene->r.efra +1.0; + pa->co[0] = 0.0; + pa->co[1] = + pa->co[2] = 1.0*(float)a / (float)totpart; + pa->no[0] = pa->no[1] = pa->no[2] = 0.0; + pa->mat_nr= paf->omat; + gzread(gzf, &convertSize, sizeof( float )); + // convert range of 1.0-10.0 to shorts 1000-10000) + shsize = (short)(convertSize*1000.0); + pa->rt = shsize; + //if(a<200) fprintf(stderr,"SREAD %f %d %d \n",convertSize,shsize,pa->rt); + + for(j=0; j<3; j++) { + float wrf; + gzread(gzf, &wrf, sizeof( wrf )); + pa->co[j] = wrf; + //fprintf(stderr,"Rj%d ",j); + } + for(j=0; j<3; j++) { + float wrf; + gzread(gzf, &wrf, sizeof( wrf )); + vel[j] = wrf; + } + } else { + // skip... + for(j=0; j<2*3+1; j++) { + float wrf; gzread(gzf, &wrf, sizeof( wrf )); + } + } + //fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime ); + } + gzclose( gzf ); + + totpart = paf->totpart = activeParts; + //fprintf(stderr,"PARTOBH debug %s %d \n", ob->id.name, totpart); // DEBUG + return; + } + + if(paf->end < paf->sta) return; if( (paf->flag & PAF_OFACE) && (paf->flag & PAF_FACE)==0) return; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 13821ea3712..c7587bbeb59 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -171,6 +171,13 @@ int snd_ar[SND_TOTIPO]= { SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN }; +int fluidsim_ar[FLUIDSIM_TOTIPO]= { + FLUIDSIM_VISC, FLUIDSIM_TIME, + FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z , + FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z , + FLUIDSIM_ACTIVE +}; + float frame_to_float(int cfra) /* see also bsystem_time in object.c */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ff1948af18d..cbe3195da27 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2371,6 +2371,10 @@ static void lib_link_object(FileData *fd, Main *main) act= act->next; } + if(ob->fluidsimSettings) { + ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo); + } + lib_link_scriptlink(fd, &ob->id, &ob->scriptlink); lib_link_modifiers(fd, ob); } diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 06611ec6dda..8ae27f26e7d 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -58,6 +58,7 @@ char *getname_cu_ei(int nr); char *getname_la_ei(int nr); char *getname_cam_ei(int nr); char *getname_snd_ei(int nr); +char *getname_fluidsim_ei(int nr); struct EditIpo *get_active_editipo(void); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 82c9756f2b3..b5b0e5ac39e 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -252,8 +252,9 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la /* Fluidsim button defines */ #define B_FLUIDSIM_BAKE 1450 -#define B_FLUIDSIM_SELDIR 1451 +#define B_FLUIDSIM_SELDIR 1451 #define B_FLUIDSIM_FORCEREDRAW 1452 +#define B_FLUIDSIM_MAKEPART 1453 #define B_GROUP_RELINK 1460 diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 71f4a30bb24..7e71da6df76 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -127,6 +127,7 @@ typedef struct Library { #define ID_AR MAKE_ID2('A', 'R') #define ID_AC MAKE_ID2('A', 'C') #define ID_SCRIPT MAKE_ID2('P', 'Y') +#define ID_FLUIDSIM MAKE_ID2('F', 'S') #define ID_NT MAKE_ID2('N', 'T') /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index c05c27ede6b..fc30c1ec5e6 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -326,6 +326,26 @@ typedef short IPO_Channel; #define CO_ROLL 9 */ +/* ******************** */ +/* fluidsim ipos NT */ + +#define FLUIDSIM_TOTIPO 9 +#define FLUIDSIM_TOTNAM 9 + +#define FLUIDSIM_VISC 1 +#define FLUIDSIM_TIME 2 + +#define FLUIDSIM_GRAV_X 3 +#define FLUIDSIM_GRAV_Y 4 +#define FLUIDSIM_GRAV_Z 5 + +#define FLUIDSIM_VEL_X 6 +#define FLUIDSIM_VEL_Y 7 +#define FLUIDSIM_VEL_Z 8 + +#define FLUIDSIM_ACTIVE 9 + + /* these are IpoCurve specific */ /* **************** IPO ********************* */ diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index 1b5b77591f7..e2e2ecd5570 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -33,12 +33,15 @@ #ifndef DNA_OBJECT_FLUIDSIM_H #define DNA_OBJECT_FLUIDSIM_H +#include "DNA_ID.h" #ifdef __cplusplus extern "C" { #endif struct Mesh; +struct Ipo; +struct MVert; typedef struct FluidsimSettings { /* domain,fluid or obstacle */ @@ -87,6 +90,24 @@ typedef struct FluidsimSettings { /* store start coords of axis aligned bounding box together with size */ /* values are inited during derived mesh display */ float bbStart[3], bbSize[3]; + + /* animated params */ + struct Ipo *ipo; + + /* additional flags depending on the type, lower short contains flags + * to check validity, higher short additional flags */ + int typeFlags; + + /* boundary "stickiness" for part slip values */ + float partSlipValue; + /* particle generation - on if >0, then determines amount */ + float generateParticles, dummy; + /* particle display - size scaling, and alpha influence */ + float particleInfSize, particleInfAlpha; + + /* save fluidsurface normals in mvert.no, and surface vertex velocities (if available) in mvert.co */ + struct MVert *meshSurfNormals; + } FluidsimSettings; /* ob->fluidsimSettings defines */ @@ -96,6 +117,24 @@ typedef struct FluidsimSettings { #define OB_FLUIDSIM_OBSTACLE 8 #define OB_FLUIDSIM_INFLOW 16 #define OB_FLUIDSIM_OUTFLOW 32 +#define OB_FLUIDSIM_PARTICLE 64 + +#define OB_TYPEFLAG_START 16 +#define OB_FSGEO_THIN (1<<(OB_TYPEFLAG_START+1)) +#define OB_FSBND_NOSLIP (1<<(OB_TYPEFLAG_START+2)) +#define OB_FSBND_PARTSLIP (1<<(OB_TYPEFLAG_START+3)) +#define OB_FSBND_FREESLIP (1<<(OB_TYPEFLAG_START+4)) +#define OB_FSINFLOW_LOCALCOORD (1<<(OB_TYPEFLAG_START+5)) +#define OB_FSDOMAIN_NOVECGEN (1<<(OB_TYPEFLAG_START+6)) + +// guiDisplayMode particle flags +#define OB_FSDOM_GEOM 1 +#define OB_FSDOM_PREVIEW 2 +#define OB_FSDOM_FINAL 3 +#define OB_FSPART_BUBBLE (1<<1) +#define OB_FSPART_DROP (1<<2) +#define OB_FSPART_NEWPART (1<<3) +#define OB_FSPART_FLOAT (1<<4) #ifdef __cplusplus } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 937a5834964..6498cf534ba 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -56,6 +56,7 @@ #include "DNA_meta_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" +#include "DNA_object_fluidsim.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "DNA_view3d_types.h" @@ -447,6 +448,104 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_ } } +// NT same as calc_vertexnormals, but dont modify the existing vertex normals +// only recalculate other render data. If this is at some point used for other things than fluidsim, +// this could be made on option for the normal calc_vertexnormals +static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent) +{ + int a; + + /* dont clear vertex normals here */ + // OFF for(a=startvert; a<re->totvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; } + /* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */ + for(a=startvlak; a<re->totvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(re, a); + if(vlr->flag & ME_SMOOTH) { + VertRen *adrve1= vlr->v1; + VertRen *adrve2= vlr->v2; + VertRen *adrve3= vlr->v3; + VertRen *adrve4= vlr->v4; + float n1[3], n2[3], n3[3], n4[3]; + float fac1, fac2, fac3, fac4=0.0f; + + VecSubf(n1, adrve2->co, adrve1->co); + Normalise(n1); + VecSubf(n2, adrve3->co, adrve2->co); + Normalise(n2); + if(adrve4==NULL) { + VecSubf(n3, adrve1->co, adrve3->co); + Normalise(n3); + fac1= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]); + fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); + fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); + } + else { + VecSubf(n3, adrve4->co, adrve3->co); + Normalise(n3); + VecSubf(n4, adrve1->co, adrve4->co); + Normalise(n4); + + fac1= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]); + fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); + fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); + fac4= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]); + + if(!(vlr->flag & R_NOPUNOFLIP)) { + if( contrpuntnormr(vlr->n, adrve4->n) ) fac4= -fac4; + } + } + + if(do_tangent) + calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4); + } + } + + /* do solid faces */ + for(a=startvlak; a<re->totvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(re, a); + if((vlr->flag & ME_SMOOTH)==0) { + float *f1= vlr->v1->n; + if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); + f1= vlr->v2->n; + if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); + f1= vlr->v3->n; + if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); + if(vlr->v4) { + f1= vlr->v4->n; + if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n); + } + } + } + + /* normalise vertex normals */ + for(a=startvert; a<re->totvert; a++) { + VertRen *ver= RE_findOrAddVert(re, a); + Normalise(ver->n); + if(do_tangent) { + float *tav= RE_vertren_get_tangent(re, ver, 0); + if(tav) Normalise(tav); + } + } + + /* vertex normal (puno) switch flags for during render */ + for(a=startvlak; a<re->totvlak; a++) { + VlakRen *vlr= RE_findOrAddVlak(re, a); + if((vlr->flag & R_NOPUNOFLIP)==0) { + VertRen *adrve1= vlr->v1; + VertRen *adrve2= vlr->v2; + VertRen *adrve3= vlr->v3; + VertRen *adrve4= vlr->v4; + vlr->puno &= ~15; + if ((vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2])<0.0) vlr->puno= 1; + if ((vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2])<0.0) vlr->puno+= 2; + if ((vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2])<0.0) vlr->puno+= 4; + if(adrve4) { + if((vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2])<0.0) vlr->puno+= 8; + } + } + } +} + /* ------------------------------------------------------------------------- */ /* Autosmoothing: */ /* ------------------------------------------------------------------------- */ @@ -742,6 +841,12 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf) float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3]; int a, mat_nr=1, seed; + int useFluidsimParticles = 0; // FSPARTICLE + float haloScale = 1.0; //NT scale halos + float iniAlpha = 0.0; // restore material alpha + + + pa= paf->keys; if(pa==NULL || paf->disp!=100) { build_particle_system(ob); @@ -767,6 +872,10 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf) else ptime= 0.0; ctime= bsystem_time(ob, 0, (float)re->scene->r.cfra, ptime); seed= ma->seed1; + if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) { + useFluidsimParticles = 1; + iniAlpha = ma->alpha; + } for(a=0; a<paf->totpart; a++, pa+=paf->totkey, seed++) { @@ -810,7 +919,16 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf) execute_ipo((ID *)ma, ma->ipo); } - hasize= ma->hasize; + //NT scale halos FSPARTICLE + if(useFluidsimParticles) { + // rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0 + double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ; + haloScale = (float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize); + ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha); + if(ma->alpha>1.) ma->alpha = 1.; + } + + hasize= ma->hasize * haloScale; if(ma->mode & MA_HALOPUNO) { xn= pa->no[0]; @@ -852,6 +970,8 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf) MEM_freeN(paf->keys); paf->keys= NULL; } + + if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore... } @@ -1442,6 +1562,7 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts) float *orco=0; int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs; int end, do_autosmooth=0, totvert = 0, dm_needsfree; + int useFluidmeshNormals = 0; // NT fluidsim, use smoothed normals? me= ob->data; @@ -1493,6 +1614,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts) dm_needsfree= 1; if(dm==NULL) return; /* in case duplicated object fails? */ + + if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&& + (ob->fluidsimSettings->meshSurface) ) { + useFluidmeshNormals = 1; + } dlm = dm->convertToDispListMesh(dm, 1); @@ -1514,6 +1641,16 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts) if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */ MTC_Mat4MulVecfl(mat, ver->co); + if(useFluidmeshNormals) { + xn = mvert->no[0]/ 32767.0; + yn = mvert->no[1]/ 32767.0; + zn = mvert->no[2]/ 32767.0; + /* transfor to cam space */ + ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + } // useFluidmeshNormals + if(orco) { ver->orco= orco; orco+=3; @@ -1705,7 +1842,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts) autosmooth(re, mat, totverto, totvlako, me->smoothresh); } - calc_vertexnormals(re, totverto, totvlako, need_tangent); + if(useFluidmeshNormals) { + // do not recalculate, only init render data + calc_fluidsimnormals(re, totverto, totvlako, need_tangent); + } else { + calc_vertexnormals(re, totverto, totvlako, need_tangent); + } if(need_stress) calc_edge_stress(re, me, totverto, totvlako); @@ -3126,9 +3268,84 @@ static void calculate_speedvectors(Render *re, float *vectors, int startvert, in speed[0]= zco[0]; speed[1]= zco[1]; } + } } +static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, int endvert, int step, Object *fsob) +{ + VertRen *ver= NULL; + float *speed, div, zco[2]; + float zmulx= re->winx/2, zmuly= re->winy/2, len; + float winsq= re->winx*re->winy, winroot= sqrt(winsq); + int a, j; + float hoco[4], fsvec[4], camco[4]; + float mat[4][4]; + float imat[4][4]; + MVert *vverts; + + /* only one step needed */ + if(step) return 1; + + Mat4CpyMat4(mat, re->viewmat); + MTC_Mat4Invert(imat, mat); + + /* set first vertex OK */ + a= startvert-1; + ver= re->vertnodes[a>>8].vert + (a & 255); + + if( (!fsob->fluidsimSettings) || (!fsob->fluidsimSettings->meshSurfNormals) ) return 0; + vverts = fsob->fluidsimSettings->meshSurfNormals; + //fprintf(stderr, "GZ_VEL obj '%s', calc load_fluidsimspeedvectors\n",fsob->id.name); // NT DEBUG + + if( endvert-startvert != fsob->fluidsimSettings->meshSurface->totvert ) { + //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", endvert-startvert , fsob->fluidsimSettings->meshSurface->totvert); // DEBUG + return 0; + } + + for(a=startvert; a<endvert; a++, vectors+=2) { + if((a & 255)==0) + ver= re->vertnodes[a>>8].vert; + else + ver++; + + // get fluid velocity + fsvec[3] = 0.; + //fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test + for(j=0;j<3;j++) fsvec[j] = vverts[a-startvert].co[j]; + + // transform (=rotate) to cam space + camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2]; + camco[1]= imat[1][0]*fsvec[0] + imat[1][1]*fsvec[1] + imat[1][2]*fsvec[2]; + camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2]; + + // get homogenous coordinates + projectverto(camco, re->winmat, hoco); + + /* now map hocos to screenspace, uses very primitive clip still */ + // use ho[3] of original vertex, xy component of vel. direction + if(ver->ho[3]<0.1f) div= 10.0f; + else div= 1.0f/ver->ho[3]; + zco[0]= zmulx*hoco[0]*div; + zco[1]= zmuly*hoco[1]*div; + + // maximize speed as usual + len= zco[0]*zco[0] + zco[1]*zco[1]; + if(len > winsq) { + len= winroot/sqrt(len); + zco[0]*= len; zco[1]*= len; + } + + speed= RE_vertren_get_winspeed(re, ver, 1); + // set both to the same value + speed[0]= speed[2]= zco[0]; + speed[1]= speed[3]= zco[1]; + //if(a<20) fprintf(stderr,"speed %d %f,%f | camco %f,%f,%f | hoco %f,%f,%f,%f \n", a, speed[0], speed[1], camco[0],camco[1], camco[2], hoco[0],hoco[1], hoco[2],hoco[3]); // NT DEBUG + } + + return 1; +} + /* makes copy per object of all vectors */ /* result should be that we can free entire database */ static void copy_dbase_object_vectors(Render *re, ListBase *lb) @@ -3236,13 +3453,21 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) // printf("speed table: missing object %s\n", obren->ob->id.name+2); continue; } - /* check if both have same amounts of vertices */ - if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) { - printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2); - continue; - } - - calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step); + + // NT check for fluidsim special treatment + if((obren->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obren->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) { + // use preloaded per vertex simulation data , only does calculation for step=1 + // NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls... + load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob); + } else { + /* check if both have same amounts of vertices */ + if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) { + printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2); + continue; + } + + calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step); + } // not fluidsim } } } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 9f43e06926c..f584109db81 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -1377,6 +1377,27 @@ void do_object_panels(unsigned short event) /* write config files (currently no simulation) */ fluidsimBake(ob); break; + case B_FLUIDSIM_MAKEPART: + ob= OBACT; + { + PartEff *paf= NULL; + /* prepare fluidsim particle display */ + // simplified delete effect, create new - recalc some particles... + if(ob==NULL || ob->type!=OB_MESH) break; + ob->fluidsimSettings->type = 0; + // reset type, and init particle system once normally + eff= ob->effect.first; + //if((eff) && (eff->flag & SELECT)) { BLI_remlink(&ob->effect, eff); free_effect(eff); } + if(!eff){ copy_act_effect(ob); DAG_scene_sort(G.scene); } + paf = give_parteff(ob); + paf->totpart = 1000; paf->sta = paf->end = 1.0; // generate some particles... + build_particle_system(ob); + + ob->fluidsimSettings->type = OB_FLUIDSIM_PARTICLE; + } + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + break; case B_FLUIDSIM_SELDIR: { ScrArea *sa = closest_bigger_area(); ob= OBACT; @@ -2290,6 +2311,7 @@ static void object_panel_fluidsim(Object *ob) uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Inflow", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_INFLOW, 20.0, 4.0, "Object adds fluid to the simulation."); uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Outflow", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OUTFLOW, 20.0, 5.0, "Object removes fluid from the simulation."); + uiDefButS(block, ROW, B_FLUIDSIM_MAKEPART ,"Particle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_PARTICLE,20.0, 3.0, "Object is a fixed obstacle."); uiBlockEndAlign(block); yline -= lineHeight; yline -= 2*separateHeight; @@ -2304,7 +2326,11 @@ static void object_panel_fluidsim(Object *ob) elbeemEstimateMemreq(fss->resolutionxyz, ob->fluidsimSettings->bbSize[0],ob->fluidsimSettings->bbSize[1],ob->fluidsimSettings->bbSize[2], fss->maxRefine, memString); - uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options."); + //uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options."); + uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Std", 0,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 0, 20.0, 0, "Show standard domain options."); + uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Adv", 25,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 1, 20.0, 1, "Show advanced domain options."); + uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Bnd", 50,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 2, 20.0, 2, "Show domain boundary options."); + uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE",90, yline,210,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame."); yline -= lineHeight; yline -= 2*separateHeight; @@ -2324,6 +2350,7 @@ static void object_panel_fluidsim(Object *ob) yline -= lineHeight; yline -= 2*separateHeight; + if((fss->guiDisplayMode<1) || (fss->guiDisplayMode>3)){ fss->guiDisplayMode=2; } // can be changed by particle setting uiDefBut(block, LABEL, 0, "Disp.-Qual.:", 0,yline, 90,objHeight, NULL, 0.0, 0, 0, 0, ""); uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "GuiDisplayMode%t|Geometry %x1|Preview %x2|Final %x3", 90,yline,105,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh in the blender gui."); @@ -2335,7 +2362,7 @@ static void object_panel_fluidsim(Object *ob) uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in"); uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in"); // FIXME what is the 79.0 above? - } else { + } else if(fss->show_advancedoptions == 1) { // advanced options uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Gravity:", 0, yline, 90,objHeight, NULL, 0.0, 0, 0, 0, ""); @@ -2362,7 +2389,7 @@ static void object_panel_fluidsim(Object *ob) yline -= 1*separateHeight; uiDefBut(block, LABEL, 0, "Realworld-size:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 1.0, 10, 0, "Size of the simulation domain in meters."); + uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 10.0, 10, 0, "Size of the simulation domain in meters."); yline -= lineHeight; yline -= 2*separateHeight; @@ -2374,6 +2401,31 @@ static void object_panel_fluidsim(Object *ob) uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->gstar, 0.001, 0.10, 10,0, "Allowed compressibility due to gravitational force for standing fluid (directly affects simulation step size)."); yline -= lineHeight; + } else if(fss->show_advancedoptions == 2) { + // copied from obstacle... + //yline -= lineHeight + 5; + uiDefBut(block, LABEL, 0, "Domain boundary type settings:", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, ""); + yline -= lineHeight; + uiBlockBeginAlign(block); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects."); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!"); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!"); + uiBlockEndAlign(block); + yline -= lineHeight; + if(fss->typeFlags&OB_FSBND_PARTSLIP) { + uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, "."); + yline -= lineHeight; + } + + uiDefBut(block, LABEL, 0, "Generate Particles:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->generateParticles, 0.0, 10.0, 10,0, "Amount of particles to generate (0=off, 1=normal, >1=more)."); + yline -= lineHeight; + + uiDefBut(block, LABEL, 0, "Generate&Use SpeedVecs:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, OB_FSDOMAIN_NOVECGEN, REDRAWBUTSOBJECT, "Disable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Default is to generate and use fluidsim vertex speed vectors, this option switches calculation off during bake, and disables loading."); + yline -= lineHeight; + // copied from obstacle... } } else if( @@ -2390,15 +2442,64 @@ static void object_panel_fluidsim(Object *ob) uiDefButF(block, NUM, B_DIFF, "Z:", 200, yline, 100,objHeight, &fss->iniVelz, -1000.1, 1000.1, 10, 0, "Fluid velocity in Z direction"); uiBlockEndAlign(block); yline -= lineHeight; + + if(fss->type == OB_FLUIDSIM_INFLOW) { + uiDefBut(block, LABEL, 0, "Local Inflow Coords", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, OB_FSINFLOW_LOCALCOORD, REDRAWBUTSOBJECT, "Enable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Use local coordinates for inflow (e.g. for rotating objects)."); + yline -= lineHeight; + } } - else if( - (fss->type == OB_FLUIDSIM_OBSTACLE) - || (fss->type == OB_FLUIDSIM_OUTFLOW) - ) { + else if( (fss->type == OB_FLUIDSIM_OUTFLOW) ) { yline -= lineHeight + 5; uiDefBut(block, LABEL, 0, "No additional settings as of now...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, ""); + } + else if( (fss->type == OB_FLUIDSIM_OBSTACLE) ) { + yline -= lineHeight + 5; + + uiBlockBeginAlign(block); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects."); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!"); + uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!"); + uiBlockEndAlign(block); + yline -= lineHeight; + + if(fss->typeFlags&OB_FSBND_PARTSLIP) { + uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, "."); + yline -= lineHeight; + } + yline -= lineHeight; } + else if(fss->type == OB_FLUIDSIM_PARTICLE) { + + if(fss->guiDisplayMode==0) fss->guiDisplayMode=2; // default drops + uiDefBut(block, LABEL, 0, "Part.-Type:", 0,yline,100,objHeight, NULL, 0.0, 0, 0, 0, ""); + // TODO make toggle buttons + //uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "Gui%t|Bubble %x2|Drop %x4|Newparts %x8|Float %x16", + //100,yline,200,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "Which type of particles to display."); + //uiDefButS(block, MENU, B_DIFF, "Render%t|Geometry %x1|Preview %x2|Final %x3", + //195,yline,105,objHeight, &fss->renderDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh for rendering."); + uiDefBut(block, LABEL, 0, "Drops", 100,yline,200,objHeight, NULL, 0.0, 0, 0, 0, ""); + fss->guiDisplayMode = 4; // fix to drops for now + yline -= lineHeight; + + uiDefBut(block, LABEL, 0, "Size Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfSize, 0.0, 2.0, 10,0, "Amount of particle size scaling: 0=off (all same size), 1=full (range 0.2-2.0), >1=stronger."); + yline -= lineHeight; + uiDefBut(block, LABEL, 0, "Alpha Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfAlpha, 0.0, 2.0, 10,0, "Amount of particle alpha change, inverse of size influence: 0=off (all same alpha), 1=full (large particles get lower alphas, smaller ones higher values)."); + yline -= lineHeight; + + yline -= 1*separateHeight; + + // FSPARTICLE also select input files + uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in"); + uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in"); + yline -= lineHeight; + + + } else { yline -= lineHeight + 5; /* not yet set */ diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 7a09fc9a80d..697dcce20cb 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -67,6 +67,8 @@ #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "DNA_world_types.h" +// FSPARTICLE +#include "DNA_object_fluidsim.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -2502,7 +2504,10 @@ static void draw_particle_system(Object *ob, PartEff *paf) int a, totpart; pa= paf->keys; - if(pa==NULL) { + // FSPARTICLE always rebuild fluid particle system upon change... + if( (pa==NULL) + || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) + ) { build_particle_system(ob); pa= paf->keys; if(pa==NULL) return; @@ -2558,7 +2563,10 @@ static void draw_static_particle_system(Object *ob, PartEff *paf, int dt) int a, use_norm=0, totpart; pa= paf->keys; - if(pa==NULL) { + // FSPARTICLE always rebuild upon change... + if( (pa==NULL) + || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) + ) { build_particle_system(ob); pa= paf->keys; if(pa==NULL) return; diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index b8953a63fc6..aaf60c62ceb 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -60,6 +60,7 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" +#include "DNA_object_fluidsim.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" @@ -122,6 +123,7 @@ extern int snd_ar[]; extern int ac_ar[]; extern int co_ar[]; extern int te_ar[]; +extern int fluidsim_ar[]; // NT /* forwards */ #define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1)) @@ -428,6 +430,32 @@ static void make_ob_editipo(Object *ob, SpaceIpo *si) ei++; } + //fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo); +} + +// copied from make_seq_editipo +static void make_fluidsim_editipo(SpaceIpo *si) // NT +{ + EditIpo *ei; + int a; + char *name; + ei= si->editipo= MEM_callocN(FLUIDSIM_TOTIPO*sizeof(EditIpo), "fluidsim_editipo"); + si->totipo = FLUIDSIM_TOTIPO; + for(a=0; a<FLUIDSIM_TOTIPO; a++) { + //fprintf(stderr,"FSINAME %d %d \n",a,fluidsim_ar[a], (int)(getname_fluidsim_ei(fluidsim_ar[a])) ); + name = getname_fluidsim_ei(fluidsim_ar[a]); + strcpy(ei->name, name); + ei->adrcode= fluidsim_ar[a]; + ei->col= ipo_rainbow(a, FLUIDSIM_TOTIPO); + ei->icu= find_ipocurve(si->ipo, ei->adrcode); + if(ei->icu) { + ei->flag = ei->icu->flag; + } + //else { ei->flag |= IPO_VISIBLE; } + //fprintf(stderr,"FSIMAKE eif%d,icuf%d icu%d %d|%d\n", ei->flag,ei->icu->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT); + //fprintf(stderr,"FSIMAKE eif%d icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT); + ei++; + } } static void make_seq_editipo(SpaceIpo *si) @@ -886,6 +914,12 @@ static void make_editipo(void) ob->ipowin= ID_PO; } } + else if(G.sipo->blocktype==ID_FLUIDSIM) { + if (ob) { // NT + ob->ipowin= ID_FLUIDSIM; + make_fluidsim_editipo(G.sipo); + } + } if(G.sipo->editipo==0) return; @@ -1059,6 +1093,13 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname // if(sound) *ipo= sound->ipo; // } } + else if(blocktype==ID_FLUIDSIM) { + if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) { + FluidsimSettings *fss= ob->fluidsimSettings; + *from= (ID *)ob; + if(fss) *ipo= fss->ipo; + } + } } /* called on each redraw, check if editipo data has to be remade */ @@ -1674,6 +1715,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname) } return NULL; } + else if(blocktype== ID_FLUIDSIM) { + Object *ob= (Object *)from; + if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + FluidsimSettings *fss= ob->fluidsimSettings; + if(fss->ipo==NULL) { + fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); + //fprintf(stderr,"FSIPO NEW!\n"); + } + return fss->ipo; + } + } } break; case ID_MA: diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c index 22587c2da3c..ed9466a3bf9 100644 --- a/source/blender/src/editipo_lib.c +++ b/source/blender/src/editipo_lib.c @@ -93,6 +93,7 @@ char *snd_ic_names[SND_TOTNAM] = { "Vol", "Pitch", "Pan", "Atten" }; char *ac_ic_names[AC_TOTNAM] = {"LocX", "LocY", "LocZ", "SizeX", "SizeY", "SizeZ", "QuatW", "QuatX", "QuatY", "QuatZ"}; char *ic_name_empty[1] ={ "" }; +char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time", "GravX","GravY","GravZ", "VelX","VelY","VelZ", "Active" }; char *getname_ac_ei(int nr) { @@ -198,6 +199,12 @@ char *getname_snd_ei(int nr) return ic_name_empty[0]; } +char *getname_fluidsim_ei(int nr) +{ + if(nr <= FLUIDSIM_TOTIPO) return fluidsim_ic_names[nr-1]; + return ic_name_empty[0]; +} + void boundbox_ipocurve(IpoCurve *icu) { diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index 83aec9ccbee..85119d9a2cc 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -178,6 +178,7 @@ void swap_visible_editipo(void) } } else ei->flag &= ~IPO_VISIBLE; + printf("FSISWAP %d, icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT); ei++; } diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index bab93250d23..a608b079266 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -52,6 +52,7 @@ #include "DNA_scene_types.h" #include "DNA_camera_types.h" #include "DNA_screen_types.h" +#include "DNA_ipo_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -69,6 +70,9 @@ #include "BKE_DerivedMesh.h" #include "BKE_ipo.h" #include "LBM_fluidsim.h" +// FIXME move? +// TODO FIXME DOUBLE elbeem.h! in intern/extern... +#include "elbeem.h" #include "BLI_editVert.h" #include "BIF_editdeform.h" @@ -80,7 +84,6 @@ #include "BSE_headerbuttons.h" #include "mydevice.h" - #include "SDL.h" #include "SDL_thread.h" #include "SDL_mutex.h" @@ -99,6 +102,9 @@ #undef main #endif +// from DerivedMesh.c +void initElbeemMesh(struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles); + /* from header info.c */ extern int start_progress_bar(void); extern void end_progress_bar(void); @@ -179,6 +185,7 @@ FluidsimSettings *fluidsimSettingsNew(struct Object *srcob) fss->orgMesh = (Mesh *)srcob->data; fss->meshSurface = NULL; fss->meshBB = NULL; + fss->meshSurfNormals = NULL; // first init of bounding box fss->bbStart[0] = 0.0; @@ -187,7 +194,15 @@ FluidsimSettings *fluidsimSettingsNew(struct Object *srcob) fss->bbSize[0] = 1.0; fss->bbSize[1] = 1.0; fss->bbSize[2] = 1.0; - fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize); + fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize, &fss->meshBB); + + fss->typeFlags = 0; + fss->partSlipValue = 0.0; + + fss->generateParticles = 0.0; + fss->particleInfSize = 0.0; + fss->particleInfAlpha = 0.0; + return fss; } @@ -202,6 +217,16 @@ void fluidsimSettingsFree(FluidsimSettings *fss) MEM_freeN(freeFsMesh); } + freeFsMesh = fss->meshBB; + if(freeFsMesh) { // same as before... + if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert); + if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge); + if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface); + MEM_freeN(freeFsMesh); + } + + if(fss->meshSurfNormals) MEM_freeN(fss->meshSurfNormals); + MEM_freeN(fss); } @@ -213,17 +238,121 @@ void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *sr } + + +/* ******************************************************************************** */ +/* ********************** fluid sim channel helper functions ********************** */ +/* ******************************************************************************** */ + +// no. of entries for the two channel sizes +#define CHANNEL_FLOAT 1 +#define CHANNEL_VEC 3 + +#define FS_FREE_ONECHANNEL(c,str) { \ + if(c){ MEM_freeN(c); c=NULL; } \ +} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n"); + +#define FS_FREE_CHANNELS { \ + FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\ + FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\ + FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \ + FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\ + FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\ + for(i=0;i<256;i++) { \ + FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \ + FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \ + FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \ + FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \ + FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \ + } \ +} // end FS FREE CHANNELS + + +// simplify channels before printing +// for API this is done anyway upon init +static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries) +{ + int i,j; + int channelSize = paramsize; + + if(entries==3) { + elbeemSimplifyChannelVec3( channel, &channelSize); + } else if(entries==1) { + elbeemSimplifyChannelFloat( channel, &channelSize); + } else { + // invalid, cant happen? + } + + fprintf(file, " CHANNEL %s = \n", str); + for(i=0; i<channelSize;i++) { + fprintf(file," "); + for(j=0;j<=entries;j++) { // also print time value + fprintf(file," %f ", channel[i*(entries+1)+j] ); + if(j==entries-1){ fprintf(file," "); } + } + fprintf(file," \n"); + } + + fprintf(file, " ; \n" ); +} + + +static void fluidsimInitChannel(float **setchannel, int size, float *time, + int *icuIds, float *defaults, Ipo* ipo, int entries) { + int i,j; + IpoCurve* icus[3]; + char *cstr = NULL; + float *channel = NULL; + float aniFrlen = G.scene->r.framelen; + if((entries<1) || (entries>3)) { + printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries); + entries = 1; + } + + cstr = "fluidsiminit_channelfloat"; + if(entries>1) cstr = "fluidsiminit_channelvec"; + channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr ); + + if(ipo) { + for(i=0; i<entries; i++) icus[i] = find_ipocurve(ipo, icuIds[i] ); + } else { + for(i=0; i<entries; i++) icus[i] = NULL; + } + + for(j=0; j<entries; j++) { + if(icus[j]) { + for(i=1; i<=size; i++) { + calc_icu(icus[j], aniFrlen*((float)i) ); + channel[(i-1)*(entries+1) + j] = icus[j]->curval; + } + } else { + for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; } + } + } + // set time values + for(i=1; i<=size; i++) { + channel[(i-1)*(entries+1) + entries] = time[i]; + } + + *setchannel = channel; +} + + + +/* ******************************************************************************** */ /* ********************** simulation thread ************************* */ +/* ******************************************************************************** */ + SDL_mutex *globalBakeLock=NULL; int globalBakeState = 0; // 0 everything ok, -1 abort simulation, 1 sim done int globalBakeFrame = 0; // run simulation in seperate thread -int fluidsimSimulateThread(void *ptr) { - char* fnameCfgPath = (char*)(ptr); - int ret; +int fluidsimSimulateThread(void) { // *ptr) { + //char* fnameCfgPath = (char*)(ptr); + int ret=0; - ret = performElbeemSimulation(fnameCfgPath); + ret = elbeemSimulate(); SDL_mutexP(globalBakeLock); if(globalBakeState==0) { // if no error, set to normal exit @@ -242,31 +371,27 @@ void simulateThreadIncreaseFrame(void) { SDL_mutexV(globalBakeLock); } -/* remember files created during bake for deletion */ - //createdFiles[numCreatedFiles] = (char *)malloc(strlen(str)+1); - //strcpy(createdFiles[numCreatedFiles] ,str); -#define ADD_CREATEDFILE(str) \ - if(numCreatedFiles<255) {\ - createdFiles[numCreatedFiles] = strdup(str); \ - numCreatedFiles++; } +/* ******************************************************************************** */ /* ********************** write fluidsim config to file ************************* */ +/* ******************************************************************************** */ + void fluidsimBake(struct Object *ob) { FILE *fileCfg; int i; struct Object *fsDomain = NULL; - FluidsimSettings *fssDomain; + FluidsimSettings *domainSettings; struct Object *obit = NULL; /* object iterator */ int origFrame = G.scene->r.cfra; char debugStrBuffer[256]; int dirExist = 0; int gridlevels = 0; - char *createdFiles[256]; - int numCreatedFiles = 0; - int doDeleteCreatedFiles = 1; int simAborted = 0; // was the simulation aborted by user? - char *delEnvStr = "BLENDER_DELETEELBEEMFILES"; + int doExportOnly = 0; + char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY"; + const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp + //char *channelNames[3] = { "translation","rotation","scale" }; char *suffixConfig = "fluidsim.cfg"; char *suffixSurface = "fluidsurface"; @@ -275,17 +400,46 @@ void fluidsimBake(struct Object *ob) char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access int outStringsChanged = 0; // modified? copy back before baking int haveSomeFluid = 0; // check if any fluid objects are set - int noFrames = G.scene->r.efra - 1 /*G.scene->r.sfra*/; - const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp + // config vars, inited before either export or run... + double calcViscosity = 0.0; + int noFrames; + double aniFrameTime; + float aniFrlen; + int channelObjCount; + float *bbStart = NULL; + float *bbSize = NULL; + float domainMat[4][4]; + float invDomMat[4][4]; + // channel data + int allchannelSize; // fixed by no. of frames + int startFrame = 1; // dont use G.scene->r.sfra here, always start with frame 1 + // easy frame -> sim time calc + float *timeAtFrame=NULL, *timeAtIndex=NULL; + // domain + float *channelDomainTime = NULL; + float *channelDomainViscosity = NULL; + float *channelDomainGravity = NULL; + // objects (currently max. 256 objs) + float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale + float *channelObjInivel[256]; // initial velocities + float *channelObjActive[256]; // obj active channel if(getenv(strEnvName)) { int dlevel = atoi(getenv(strEnvName)); elbeemSetDebugLevel(dlevel); - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); + elbeemDebugOut(debugStrBuffer); + } + if(getenv(exportEnvStr)) { + doExportOnly = atoi(getenv(exportEnvStr)); + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); elbeemDebugOut(debugStrBuffer); } + // make sure it corresponds to startFrame setting + // old: noFrames = G.scene->r.efra - G.scene->r.sfra +1; + noFrames = G.scene->r.efra - 0; if(noFrames<=0) { pupmenu("Fluidsim Bake Error%t|No frames to export - check your animation range settings. Aborted%x0"); return; @@ -296,36 +450,37 @@ void fluidsimBake(struct Object *ob) if((obit->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(obit->type==OB_MESH)) { if(obit->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) { if(obit != ob) { - snprintf(debugStrBuffer,256,"fluidsimBake::warning - More than one domain!\n"); - elbeemDebugOut(debugStrBuffer); + //snprintf(debugStrBuffer,256,"fluidsimBake::warning - More than one domain!\n"); elbeemDebugOut(debugStrBuffer); + pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0"); + return; } } } } /* these both have to be valid, otherwise we wouldnt be here...*/ fsDomain = ob; - fssDomain = ob->fluidsimSettings; + domainSettings = ob->fluidsimSettings; /* rough check of settings... */ - if(fssDomain->previewresxyz > fssDomain->resolutionxyz) { - snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", fssDomain->previewresxyz , fssDomain->resolutionxyz); + if(domainSettings->previewresxyz > domainSettings->resolutionxyz) { + snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz); elbeemDebugOut(debugStrBuffer); - fssDomain->previewresxyz = fssDomain->resolutionxyz; + domainSettings->previewresxyz = domainSettings->resolutionxyz; } // set adaptive coarsening according to resolutionxyz // this should do as an approximation, with in/outflow // doing this more accurate would be overkill // perhaps add manual setting? - if(fssDomain->maxRefine <0) { - if(fssDomain->resolutionxyz>128) { + if(domainSettings->maxRefine <0) { + if(domainSettings->resolutionxyz>128) { gridlevels = 2; } else - if(fssDomain->resolutionxyz>64) { + if(domainSettings->resolutionxyz>64) { gridlevels = 1; } else { gridlevels = 0; } } else { - gridlevels = fssDomain->maxRefine; + gridlevels = domainSettings->maxRefine; } snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); elbeemDebugOut(debugStrBuffer); @@ -347,12 +502,13 @@ void fluidsimBake(struct Object *ob) } // prepare names... - strncpy(targetDir, fssDomain->surfdataPath, FILE_MAXDIR); - strncpy(newSurfdataPath, fssDomain->surfdataPath, FILE_MAXDIR); + strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); + strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no strcpy(targetFile, targetDir); strcat(targetFile, suffixConfig); + if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file // make sure all directories exist // as the bobjs use the same dir, this only needs to be checked // for the cfg output @@ -361,7 +517,11 @@ void fluidsimBake(struct Object *ob) // check selected directory // simply try to open cfg file for writing to test validity of settings fileCfg = fopen(targetFile, "w"); - if(fileCfg) { dirExist = 1; fclose(fileCfg); } + if(fileCfg) { + dirExist = 1; fclose(fileCfg); + // remove cfg dummy from directory test + if(!doExportOnly) { BLI_delete(targetFile, 0,0); } + } if((strlen(targetDir)<1) || (!dirExist)) { char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE]; @@ -395,316 +555,302 @@ void fluidsimBake(struct Object *ob) selection = pupmenu(dispmsg); if(selection<1) return; // 0 from menu, or -1 aborted strcpy(targetDir, newSurfdataPath); + strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no } + // -------------------------------------------------------------------------------------------- + // dump data for start frame + // CHECK more reasonable to number frames according to blender? // dump data for frame 0 - G.scene->r.cfra = 1 /*G.scene->r.sfra*/; + G.scene->r.cfra = startFrame; scene_update_for_newframe(G.scene, G.scene->lay); - - // start writing - strcpy(targetFile, targetDir); - strcat(targetFile, suffixConfig); - // make sure these directories exist as well - if(outStringsChanged) { - BLI_make_existing_file(targetFile); - } - fileCfg = fopen(targetFile, "w"); - if(!fileCfg) { - snprintf(debugStrBuffer,256,"fluidsimBake::error - Unable to open file for writing '%s'\n", targetFile); - elbeemDebugOut(debugStrBuffer); - pupmenu("Fluidsim Bake Error%t|Unable to output files... Aborted%x0"); - return; + // init common export vars for both file export and run + for(i=0; i<256; i++) { + channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL; + channelObjInivel[i] = NULL; + channelObjActive[i] = NULL; + } + allchannelSize = G.scene->r.efra; // always use till last frame + aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; + // blender specific - scale according to map old/new settings in anim panel: + aniFrlen = G.scene->r.framelen; + if(domainSettings->viscosityMode==1) { + /* manual mode */ + calcViscosity = (1.0/(domainSettings->viscosityExponent*10)) * domainSettings->viscosityValue; + } else { + calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ]; } - ADD_CREATEDFILE(targetFile); - - fprintf(fileCfg, "# Blender ElBeem File , Source %s , Frame %d, to %s \n\n\n", G.sce, -1, targetFile ); - // file open -> valid settings -> store - strncpy(fssDomain->surfdataPath, newSurfdataPath, FILE_MAXDIR); - - /* output simulation settings */ - { - double calcViscosity = 0.0; - double aniFrameTime = (fssDomain->animEnd - fssDomain->animStart)/(double)noFrames; - char *simString = "\n" - "attribute \"simulation1\" { \n" - " solver = \"fsgr\"; \n" "\n" - " p_domainsize = " "%f" /* realsize */ "; \n" - " p_anistart = " "%f" /* aniStart*/ "; \n" - " p_gravity = " "%f %f %f" /* pGravity*/ "; \n" "\n" - " p_normgstar = %f; \n" /* use gstar param? */ - " p_viscosity = " "%f" /* pViscosity*/ "; \n" "\n" - - " maxrefine = " "%d" /* maxRefine*/ "; \n" - " size = " "%d" /* gridSize*/ "; \n" - " surfacepreview = " "%d" /* previewSize*/ "; \n" - " smoothsurface = 1.0; \n" - - " geoinitid = 1; \n" "\n" - " isovalue = 0.4900; \n" - " isoweightmethod = 1; \n" "\n" - "\n" ; - - if(fssDomain->viscosityMode==1) { - /* manual mode */ - calcViscosity = (1.0/(fssDomain->viscosityExponent*10)) * fssDomain->viscosityValue; - } else { - calcViscosity = fluidsimViscosityPreset[ fssDomain->viscosityMode ]; + bbStart = fsDomain->fluidsimSettings->bbStart; + bbSize = fsDomain->fluidsimSettings->bbSize; + fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize, &domainSettings->meshBB); + + // always init + { int timeIcu[1] = { FLUIDSIM_TIME }; + float timeDef[1] = { 1. }; + int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z }; + float gravDef[3] = { domainSettings->gravx, domainSettings->gravy, domainSettings->gravz }; + int viscIcu[1] = { FLUIDSIM_VISC }; + float viscDef[1] = { 1. }; + + // time channel is a bit special, init by hand... + timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex"); + for(i=0; i<=G.scene->r.efra; i++) { + timeAtIndex[i] = (float)(i-startFrame); } - fprintf(fileCfg, simString, - (double)fssDomain->realsize, - (double)fssDomain->animStart, - (double)fssDomain->gravx, (double)fssDomain->gravy, (double)fssDomain->gravz, - (double)fssDomain->gstar, - calcViscosity, - gridlevels, (int)fssDomain->resolutionxyz, (int)fssDomain->previewresxyz - ); - - // export animatable params - if(fsDomain->ipo) { - int i; - float tsum=0.0, shouldbe=0.0; - fprintf(fileCfg, " CHANNEL p_aniframetime = "); - for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) { - float anit = (calc_ipo_time(fsDomain->ipo, i+1) - - calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime; - if(anit<0.0) anit = 0.0; - tsum += anit; + fluidsimInitChannel( &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + // time channel is a multiplicator for aniFrameTime + if(channelDomainTime) { + for(i=0; i<allchannelSize; i++) { + channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0]; + if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.; } - // make sure inaccurate integration doesnt modify end time - shouldbe = ((float)(G.scene->r.efra - 1 /*G.scene->r.sfra*/)) *aniFrameTime; - for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) { - float anit = (calc_ipo_time(fsDomain->ipo, i+1) - - calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime; - if(anit<0.0) anit = 0.0; - anit *= (shouldbe/tsum); - fprintf(fileCfg," %f %d \n",anit, (i-1)); // start with 0 + } + timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe"); + timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1 + if(channelDomainTime) { + for(i=2; i<=allchannelSize; i++) { + timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0]; } - fprintf(fileCfg, "; #cfgset, base=%f \n", aniFrameTime ); - //fprintf(stderr, "DEBUG base=%f tsum=%f, sb=%f, ts2=%f \n", aniFrameTime, tsum,shouldbe,tsum2 ); } else { - fprintf(fileCfg, " p_aniframetime = " "%f" /* 2 aniFrameTime*/ "; #cfgset \n" , - aniFrameTime ); + for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } } - - fprintf(fileCfg, "} \n" ); - } - // output blender object transformation - { - float domainMat[4][4]; - float invDomMat[4][4]; - char* blendattrString = "\n" - "attribute \"btrafoattr\" { \n" - " transform = %f %f %f %f " - " %f %f %f %f " - " %f %f %f %f " - " %f %f %f %f ;\n" - "} \n"; - - MTC_Mat4CpyMat4(domainMat, fsDomain->obmat); - if(!Mat4Invert(invDomMat, domainMat)) { - snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); - elbeemDebugOut(debugStrBuffer); - // FIXME add fatal msg - return; + fluidsimInitChannel( &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + if(channelDomainViscosity) { + for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; } } + fluidsimInitChannel( &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC ); + } // domain channel init + + // init obj movement channels + channelObjCount=0; + for(obit= G.main->object.first; obit; obit= obit->id.next) { + //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG + if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (obit->type==OB_MESH) && + (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH + (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) { + + // cant use fluidsimInitChannel for obj channels right now, due + // to the special DXXX channels, and the rotation specialities + IpoCurve *icuex[3][3]; + int icuIds[3][3] = { + {OB_LOC_X, OB_LOC_Y, OB_LOC_Z}, + {OB_ROT_X, OB_ROT_Y, OB_ROT_Z}, + {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} + }; + // relative ipos + IpoCurve *icudex[3][3]; + int icudIds[3][3] = { + {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z}, + {OB_DROT_X, OB_DROT_Y, OB_DROT_Z}, + {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} + }; + int j,k; + float vals[3] = {0.0,0.0,0.0}; + int o = channelObjCount; + int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z }; + float inivelDefs[3] = { obit->fluidsimSettings->iniVelx, obit->fluidsimSettings->iniVely, obit->fluidsimSettings->iniVelz }; + int activeIcu[1] = { FLUIDSIM_ACTIVE }; + float activeDefs[1] = { 1 }; // default to on + + // check & init loc,rot,size + for(j=0; j<3; j++) { + for(k=0; k<3; k++) { + icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] ); + icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] ); + } + } - fprintf(fileCfg, blendattrString, - invDomMat[0][0],invDomMat[1][0],invDomMat[2][0],invDomMat[3][0], - invDomMat[0][1],invDomMat[1][1],invDomMat[2][1],invDomMat[3][1], - invDomMat[0][2],invDomMat[1][2],invDomMat[2][2],invDomMat[3][2], - invDomMat[0][3],invDomMat[1][3],invDomMat[2][3],invDomMat[3][3] ); - } - + for(j=0; j<3; j++) { + channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel"); + for(i=1; i<=allchannelSize; i++) { + + for(k=0; k<3; k++) { + if(icuex[j][k]) { + calc_icu(icuex[j][k], aniFrlen*((float)i) ); + vals[k] = icuex[j][k]->curval; + } else { + float setval=0.0; + if(j==0) { setval = obit->loc[k]; + } else if(j==1) { setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI ); + } else { setval = obit->size[k]; } + vals[k] = setval; + } + if(icudex[j][k]) { + calc_icu(icudex[j][k], aniFrlen*((float)i) ); + vals[k] += icudex[j][k]->curval; + } + } // k + + for(k=0; k<3; k++) { + float set = vals[k]; + if(j==1) { // rot is downscaled by 10 for ipo !? + set = 360.0 - (10.0*set); + } + channelObjMove[o][j][(i-1)*4 + k] = set; // - obit->loc[k]; + } // k + channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i]; + } + } + fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, obit->fluidsimSettings->ipo, CHANNEL_VEC ); + fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT ); - fprintf(fileCfg, "raytracing {\n"); - - /* output picture settings for preview renders */ - { - char *rayString = "\n" - " anistart= 0; \n" - " aniframes= " "%d" /*1 frameEnd-frameStart+0*/ "; #cfgset \n" - " frameSkip= false; \n" - " filename= \"" "%s" /* rayPicFilename*/ "\"; #cfgset \n" - " aspect 1.0; \n" - " resolution " "%d %d" /*2,3 blendResx,blendResy*/ "; #cfgset \n" - " antialias 1; \n" - " ambientlight (1, 1, 1); \n" - " maxRayDepth 6; \n" - " treeMaxDepth 25; \n" - " treeMaxTriangles 8; \n" - " background (0.08, 0.08, 0.20); \n" - " eyepoint= (" "%f %f %f"/*4,5,6 eyep*/ "); #cfgset \n" - " lookat= (" "%f %f %f"/*7,8,9 lookatp*/ "); #cfgset \n" - " upvec= (0 0 1); \n" - " fovy= " "%f" /*blendFov*/ "; #cfgset \n" - " blenderattr= \"btrafoattr\"; \n" - "\n\n"; - - char *lightString = "\n" - " light { \n" - " type= omni; \n" - " active= 1; \n" - " color= (1.0, 1.0, 1.0); \n" - " position= (" "%f %f %f"/*1,2,3 eyep*/ "); #cfgset \n" - " castShadows= 1; \n" - " } \n\n" ; - - struct Object *cam = G.scene->camera; - float eyex=2.0, eyey=2.0, eyez=2.0; - int resx = 200, resy=200; - float lookatx=0.0, lookaty=0.0, lookatz=0.0; - float fov = 45.0; + channelObjCount++; - strcpy(targetFile, targetDir); - strcat(targetFile, suffixSurface); - resx = G.scene->r.xsch; - resy = G.scene->r.ysch; - if((cam) && (cam->type == OB_CAMERA)) { - Camera *camdata= G.scene->camera->data; - double lens = camdata->lens; - double imgRatio = (double)resx/(double)resy; - fov = 360.0 * atan(16.0*imgRatio/lens) / M_PI; - //R.near= camdata->clipsta; R.far= camdata->clipend; - - eyex = cam->loc[0]; - eyey = cam->loc[1]; - eyez = cam->loc[2]; - // TODO - place lookat in middle of domain? } + } - fprintf(fileCfg, rayString, - (noFrames+1), targetFile, resx,resy, - eyex, eyey, eyez , - lookatx, lookaty, lookatz, - fov - ); - fprintf(fileCfg, lightString, - eyex, eyey, eyez ); + // init trafo matrix + MTC_Mat4CpyMat4(domainMat, fsDomain->obmat); + if(!Mat4Invert(invDomMat, domainMat)) { + snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); + elbeemDebugOut(debugStrBuffer); + // FIXME add fatal msg + FS_FREE_CHANNELS; + return; } - /* output fluid domain */ - { - char * domainString = "\n" - " geometry { \n" - " type= fluidlbm; \n" - " name = \"" "%s" /*name*/ "\"; #cfgset \n" - " visible= 1; \n" - " attributes= \"simulation1\"; \n" - //" define { material_surf = \"fluidblue\"; } \n" - " start= " "%f %f %f" /*bbstart*/ "; #cfgset \n" - " end = " "%f %f %f" /*bbend */ "; #cfgset \n" - " } \n" - "\n"; - float *bbStart = fsDomain->fluidsimSettings->bbStart; - float *bbSize = fsDomain->fluidsimSettings->bbSize; - fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize); - - fprintf(fileCfg, domainString, - fsDomain->id.name, - bbStart[0], bbStart[1], bbStart[2], - bbStart[0]+bbSize[0], bbStart[1]+bbSize[1], bbStart[2]+bbSize[2] - ); + // -------------------------------------------------------------------------------------------- + // start writing / exporting + strcpy(targetFile, targetDir); + strcat(targetFile, suffixConfig); + if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file + // make sure these directories exist as well + if(outStringsChanged) { + BLI_make_existing_file(targetFile); } - - /* setup geometry */ - { - char *objectStringStart = - " geometry { \n" - " type= objmodel; \n" - " name = \"" "%s" /* name */ "\"; #cfgset \n" - // DEBUG , also obs invisible? - " visible= 0; \n" - " define { \n" ; - char *obstacleString = - " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n" - " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ; - char *fluidString = - " geoinittype= \"" "%s" /* type */ "\"; \n" - " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" - " initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n" ; - char *objectStringEnd = - " geoinit_intersect = 1; \n" /* always use accurate init here */ - " geoinitid= 1; \n" - " } \n" - " } \n" - "\n" ; - char fnameObjdat[FILE_MAXFILE]; - + if(!doExportOnly) { + SDL_Thread *simthr = NULL; + + // perform simulation with El'Beem api and SDL threads + elbeemSimulationSettings fsset; + fsset.version = 1; + + // setup global settings + for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i]; + for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i]; + // simulate with 50^3 + fsset.resolutionxyz = (int)domainSettings->resolutionxyz; + fsset.previewresxyz = (int)domainSettings->previewresxyz; + // 10cm water domain + fsset.realsize = domainSettings->realsize; + fsset.viscosity = calcViscosity; + // earth gravity + fsset.gravity[0] = domainSettings->gravx; + fsset.gravity[1] = domainSettings->gravy; + fsset.gravity[2] = domainSettings->gravz; + // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz + fsset.animStart = domainSettings->animStart; + fsset.aniFrameTime = aniFrameTime; + fsset.noOfFrames = noFrames - 1; // is otherwise subtracted in parser + strcpy(targetFile, targetDir); + strcat(targetFile, suffixSurface); + // defaults for compressibility and adaptive grids + fsset.gstar = domainSettings->gstar; + fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels + fsset.generateParticles = domainSettings->generateParticles; + strcpy( fsset.outputPath, targetFile); + + // domain channels + fsset.channelSizeFrameTime = + fsset.channelSizeViscosity = + fsset.channelSizeGravity = allchannelSize; + fsset.channelFrameTime = channelDomainTime; + fsset.channelViscosity = channelDomainViscosity; + fsset.channelGravity = channelDomainGravity; + + if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; + else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; + else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; + fsset.obstaclePartslip = domainSettings->partSlipValue; + fsset.generateVertexVectors = (int)(!(domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN)); + // fprintf(stderr," VVV %d %d \n",fsset.generateVertexVectors , (domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN)); // DEBUG + + // init blender trafo matrix + // fprintf(stderr,"elbeemInit - mpTrafo:\n"); + { int j; + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + fsset.surfaceTrafo[i*4+j] = invDomMat[j][i]; + // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) ); + } + } } + + // init solver with settings + elbeemInit(&fsset); + + // init objects + channelObjCount = 0; for(obit= G.main->object.first; obit; obit= obit->id.next) { //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG - if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // if has to match 3 places! // CHECKMATCH (obit->type==OB_MESH) && - (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) + (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && + (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) { - fluidsimGetGeometryObjFilename(obit, fnameObjdat); //, outPrefix); - strcpy(targetFile, targetDir); - strcat(targetFile, fnameObjdat); - fprintf(fileCfg, objectStringStart, obit->id.name ); // abs path - if(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) { - fprintf(fileCfg, fluidString, "fluid", targetFile, // do use absolute paths? - (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz ); - } - if(obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) { - fprintf(fileCfg, fluidString, "inflow", targetFile, // do use absolute paths? - (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz ); - } - if(obit->fluidsimSettings->type == OB_FLUIDSIM_OUTFLOW) { - fprintf(fileCfg, fluidString, "outflow", targetFile, // do use absolute paths? - (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz ); - } - if(obit->fluidsimSettings->type == OB_FLUIDSIM_OBSTACLE) { - fprintf(fileCfg, obstacleString, "bnd_no" , targetFile); // abs path - } - fprintf(fileCfg, objectStringEnd ); // abs path - ADD_CREATEDFILE(targetFile); - writeBobjgz(targetFile, obit); - } - } - } - - /* fluid material */ - fprintf(fileCfg, - " material { \n" - " type= phong; \n" - " name= \"fluidblue\"; \n" - " diffuse= 0.3 0.5 0.9; \n" - " ambient= 0.1 0.1 0.1; \n" - " specular= 0.2 10.0; \n" - " } \n" ); - - + float *verts=NULL; + int *tris=NULL; + int numVerts=0, numTris=0; + int o = channelObjCount; + elbeemMesh fsmesh; + elbeemResetMesh( &fsmesh ); + fsmesh.type = obit->fluidsimSettings->type;; + // get name of object for debugging solver + fsmesh.name = obit->id.name; + + initElbeemMesh(obit, &numVerts, &verts, &numTris, &tris); + fsmesh.numVertices = numVerts; + fsmesh.numTriangles = numTris; + fsmesh.vertices = verts; + fsmesh.triangles = tris; + + fsmesh.channelSizeTranslation = + fsmesh.channelSizeRotation = + fsmesh.channelSizeScale = + fsmesh.channelSizeInitialVel = + fsmesh.channelSizeActive = allchannelSize; + + fsmesh.channelTranslation = channelObjMove[o][0]; + fsmesh.channelRotation = channelObjMove[o][1]; + fsmesh.channelScale = channelObjMove[o][2]; + fsmesh.channelActive = channelObjActive[o]; + if( (fsmesh.type == OB_FLUIDSIM_FLUID) || + (fsmesh.type == OB_FLUIDSIM_INFLOW) ) { + fsmesh.channelInitialVel = channelObjInivel[o]; + fsmesh.localInivelCoords = ((obit->fluidsimSettings->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0); + } - fprintf(fileCfg, "} // end raytracing\n"); - fclose(fileCfg); + if( (obit->fluidsimSettings->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; + else if((obit->fluidsimSettings->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; + else if((obit->fluidsimSettings->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; + fsmesh.obstaclePartslip = obit->fluidsimSettings->partSlipValue; - strcpy(targetFile, targetDir); - strcat(targetFile, suffixConfig); - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile); - elbeemDebugOut(debugStrBuffer); + elbeemAddMesh(&fsmesh); - // perform simulation - { - SDL_Thread *simthr = NULL; + if(verts) MEM_freeN(verts); + if(tris) MEM_freeN(tris); + channelObjCount++; + } // valid mesh + } // objects + globalBakeLock = SDL_CreateMutex(); // set to neutral, -1 means user abort, -2 means init error globalBakeState = 0; - globalBakeFrame = 1; + globalBakeFrame = 0; simthr = SDL_CreateThread(fluidsimSimulateThread, targetFile); -#ifndef WIN32 - // DEBUG for win32 debugging, dont use threads... -#endif // WIN32 + if(!simthr) { snprintf(debugStrBuffer,256,"fluidsimBake::error: Unable to create thread... running without one.\n"); elbeemDebugOut(debugStrBuffer); set_timecursor(0); - performElbeemSimulation(targetFile); + elbeemSimulate(); } else { int done = 0; unsigned short event=0; @@ -747,7 +893,8 @@ void fluidsimBake(struct Object *ob) // redraw the 3D for showing progress once in a while... if(lastRedraw!=globalBakeFrame) { ScrArea *sa; - G.scene->r.cfra = lastRedraw = globalBakeFrame; + G.scene->r.cfra = startFrame+globalBakeFrame; + lastRedraw = globalBakeFrame; update_for_newframe_muted(); sa= G.curscreen->areabase.first; while(sa) { @@ -762,19 +909,278 @@ void fluidsimBake(struct Object *ob) } SDL_DestroyMutex(globalBakeLock); globalBakeLock = NULL; - } // thread creation + } // El'Beem API init, thread creation + // -------------------------------------------------------------------------------------------- + else + { // write config file to be run with command line simulator + fileCfg = fopen(targetFile, "w"); + if(!fileCfg) { + snprintf(debugStrBuffer,256,"fluidsimBake::error - Unable to open file for writing '%s'\n", targetFile); + elbeemDebugOut(debugStrBuffer); + + pupmenu("Fluidsim Bake Error%t|Unable to output files... Aborted%x0"); + FS_FREE_CHANNELS; + return; + } + //ADD_CREATEDFILE(targetFile); + + fprintf(fileCfg, "# Blender ElBeem File , Source %s , Frame %d, to %s \n\n\n", G.sce, -1, targetFile ); + // file open -> valid settings -> store + strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); + + /* output simulation settings */ + { + char *dtype[3] = { "no", "part", "free" }; + float pslip = domainSettings->partSlipValue; int bi=0; + char *simString = "\n" + "attribute \"simulation1\" { \n" + " solver = \"fsgr\"; \n" "\n" + " p_domainsize = " "%f" /* realsize */ "; \n" + " p_anistart = " "%f" /* aniStart*/ "; \n" + " p_normgstar = %f; \n" /* use gstar param? */ + " maxrefine = " "%d" /* maxRefine*/ "; \n" + " size = " "%d" /* gridSize*/ "; \n" + " surfacepreview = " "%d" /* previewSize*/ "; \n" + " dump_velocities = " "%d" /* vector dump */ "; \n" + " smoothsurface = 1.0; \n" + " smoothnormals = 1.0; \n" + " geoinitid = 1; \n" "\n" + " isovalue = 0.4900; \n" + " isoweightmethod = 1; \n" "\n" ; - // cleanup sim files - if(getenv(delEnvStr)) { - doDeleteCreatedFiles = atoi(getenv(delEnvStr)); - } - for(i=0; i<numCreatedFiles; i++) { - if(doDeleteCreatedFiles>0) { - //fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]); // debug - BLI_delete(createdFiles[i], 0,0); + fprintf(fileCfg, simString, + (double)domainSettings->realsize, (double)domainSettings->animStart, (double)domainSettings->gstar, + gridlevels, (int)domainSettings->resolutionxyz, (int)domainSettings->previewresxyz , + (int)(!(domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN)) + ); + + if((domainSettings->typeFlags&OB_FSBND_NOSLIP)) bi=0; + else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) bi=1; + else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) bi=2; + fprintf(fileCfg, " domainbound = %s; domainpartslip=%f; \n", dtype[bi], pslip); + + fprintf(fileCfg," # org aniframetime: %f \n", aniFrameTime); + fluidsimPrintChannel(fileCfg, channelDomainTime,allchannelSize,"p_aniframetime",CHANNEL_FLOAT); + fluidsimPrintChannel(fileCfg, channelDomainViscosity,allchannelSize,"p_viscosity",CHANNEL_FLOAT); + fluidsimPrintChannel(fileCfg, channelDomainGravity, allchannelSize,"p_gravity",CHANNEL_VEC); + + fprintf(fileCfg, "\n} \n" ); } - free(createdFiles[i]); - } + + // output blender object transformation + { + char* blendattrString = "\n" + "attribute \"btrafoattr\" { \n" + " transform = %f %f %f %f " + " %f %f %f %f " + " %f %f %f %f " + " %f %f %f %f ;\n" + "} \n"; + + fprintf(fileCfg, blendattrString, + invDomMat[0][0],invDomMat[1][0],invDomMat[2][0],invDomMat[3][0], + invDomMat[0][1],invDomMat[1][1],invDomMat[2][1],invDomMat[3][1], + invDomMat[0][2],invDomMat[1][2],invDomMat[2][2],invDomMat[3][2], + invDomMat[0][3],invDomMat[1][3],invDomMat[2][3],invDomMat[3][3] ); + } + + + + fprintf(fileCfg, "raytracing {\n"); + + /* output picture settings for preview renders */ + { + char *rayString = "\n" + " anistart= 0; \n" + " aniframes= " "%d" /*1 frameEnd-frameStart+0*/ "; #cfgset \n" + " frameSkip= false; \n" + " filename= \"" "%s" /* rayPicFilename*/ "\"; #cfgset \n" + " aspect 1.0; \n" + " resolution " "%d %d" /*2,3 blendResx,blendResy*/ "; #cfgset \n" + " antialias 1; \n" + " ambientlight (1, 1, 1); \n" + " maxRayDepth 6; \n" + " treeMaxDepth 25; \n" + " treeMaxTriangles 8; \n" + " background (0.08, 0.08, 0.20); \n" + " eyepoint= (" "%f %f %f"/*4,5,6 eyep*/ "); #cfgset \n" + " lookat= (" "%f %f %f"/*7,8,9 lookatp*/ "); #cfgset \n" + " upvec= (0 0 1); \n" + " fovy= " "%f" /*blendFov*/ "; #cfgset \n" + " blenderattr= \"btrafoattr\"; \n" + "\n\n"; + + char *lightString = "\n" + " light { \n" + " type= omni; \n" + " active= 1; \n" + " color= (1.0, 1.0, 1.0); \n" + " position= (" "%f %f %f"/*1,2,3 eyep*/ "); #cfgset \n" + " castShadows= 1; \n" + " } \n\n" ; + + struct Object *cam = G.scene->camera; + float eyex=2.0, eyey=2.0, eyez=2.0; + int resx = 200, resy=200; + float lookatx=0.0, lookaty=0.0, lookatz=0.0; + float fov = 45.0; + + strcpy(targetFile, targetDir); + strcat(targetFile, suffixSurface); + resx = G.scene->r.xsch; + resy = G.scene->r.ysch; + if((cam) && (cam->type == OB_CAMERA)) { + Camera *camdata= G.scene->camera->data; + double lens = camdata->lens; + double imgRatio = (double)resx/(double)resy; + fov = 360.0 * atan(16.0*imgRatio/lens) / M_PI; + //R.near= camdata->clipsta; R.far= camdata->clipend; + + eyex = cam->loc[0]; + eyey = cam->loc[1]; + eyez = cam->loc[2]; + // TODO - place lookat in middle of domain? + } + + fprintf(fileCfg, rayString, + (noFrames+0), targetFile, resx,resy, + eyex, eyey, eyez , + lookatx, lookaty, lookatz, + fov + ); + fprintf(fileCfg, lightString, + eyex, eyey, eyez ); + } + + + /* output fluid domain */ + { + char * domainString = "\n" + " geometry { \n" + " type= fluidlbm; \n" + " name = \"" "%s" /*name*/ "\"; #cfgset \n" + " visible= 1; \n" + " attributes= \"simulation1\"; \n" + //" define { material_surf = \"fluidblue\"; } \n" + " start= " "%f %f %f" /*bbstart*/ "; #cfgset \n" + " end = " "%f %f %f" /*bbend */ "; #cfgset \n" + " } \n" + "\n"; + fprintf(fileCfg, domainString, + fsDomain->id.name, + bbStart[0], bbStart[1], bbStart[2], + bbStart[0]+bbSize[0], bbStart[1]+bbSize[1], bbStart[2]+bbSize[2] + ); + } + + + /* setup geometry */ + { + char *objectStringStart = + " geometry { \n" + " type= objmodel; \n" + " name = \"" "%s" /* name */ "\"; #cfgset \n" + // DEBUG , also obs invisible? + " visible= 0; \n" + " define { \n" ; + char *outflowString = + " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n" + " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ; + char *obstacleString = + " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n" + " geoinit_partslip = \"" "%f" /* partslip */ "\"; #cfgset \n" + " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ; + char *fluidString = + " geoinittype= \"" "%s" /* type */ "\"; \n" + " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ; + //" initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n" ; + char *inflowString = + " geoinittype= \"" "%s" /* type */ "\"; \n" + " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" + //" initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n" + " geoinit_localinivel = " "%d" /* local coords */ "; #cfgset \n" ; + char *objectStringEnd = + " geoinit_intersect = 1; \n" /* always use accurate init here */ + " geoinitid= 1; \n" + " } \n" + " } \n" + "\n" ; + char fnameObjdat[FILE_MAXFILE]; + + channelObjCount = 0; + for(obit= G.main->object.first; obit; obit= obit->id.next) { + if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (obit->type==OB_MESH) && // if has to match 3 places! // CHECKMATCH + (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && + (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) + ) { + + fluidsimGetGeometryObjFilename(obit, fnameObjdat); + strcpy(targetFile, targetDir); + strcat(targetFile, fnameObjdat); + fprintf(fileCfg, objectStringStart, obit->id.name ); // abs path + if(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) { + fprintf(fileCfg, fluidString, "fluid", targetFile // do use absolute paths? + //,(double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz + ); + } + if(obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) { + int locc = ((obit->fluidsimSettings->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0); + fprintf(fileCfg, inflowString, "inflow", targetFile // do use absolute paths? + //,(double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz + ,locc ); + } + if(obit->fluidsimSettings->type == OB_FLUIDSIM_OBSTACLE) { + char *btype[3] = { "bnd_no", "bnd_part", "bnd_free" }; + float pslip = obit->fluidsimSettings->partSlipValue; int bi=0; + if((obit->fluidsimSettings->typeFlags&OB_FSBND_NOSLIP)) bi=0; + else if((obit->fluidsimSettings->typeFlags&OB_FSBND_PARTSLIP)) bi=1; + else if((obit->fluidsimSettings->typeFlags&OB_FSBND_FREESLIP)) bi=2; + fprintf(fileCfg, obstacleString, btype[bi], pslip, targetFile); // abs path + } + if(obit->fluidsimSettings->type == OB_FLUIDSIM_OUTFLOW) { + fprintf(fileCfg, outflowString, "outflow" , targetFile); // abs path + } + + fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][0],allchannelSize, "translation", CHANNEL_VEC); + fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][1],allchannelSize, "rotation" , CHANNEL_VEC); + fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][2],allchannelSize, "scale" , CHANNEL_VEC); + fluidsimPrintChannel(fileCfg, channelObjActive[channelObjCount] ,allchannelSize, "geoactive" , CHANNEL_FLOAT); + if( (obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) || + (obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) ) { + fluidsimPrintChannel(fileCfg, channelObjInivel[channelObjCount],allchannelSize,"initial_velocity" ,CHANNEL_VEC); + } + channelObjCount++; + + fprintf(fileCfg, objectStringEnd ); // abs path + writeBobjgz(targetFile, obit); + } + } + } + + /* fluid material */ + fprintf(fileCfg, + " material { \n" + " type= phong; \n" + " name= \"fluidblue\"; \n" + " diffuse= 0.3 0.5 0.9; \n" + " ambient= 0.1 0.1 0.1; \n" + " specular= 0.2 10.0; \n" + " } \n" ); + + fprintf(fileCfg, "} // end raytracing\n"); + fclose(fileCfg); + + strcpy(targetFile, targetDir); + strcat(targetFile, suffixConfig); + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile); + elbeemDebugOut(debugStrBuffer); + + pupmenu("Fluidsim Bake Message%t|Config files exported successfully!%x0"); + } // config file export done! + + // -------------------------------------------------------------------------------------------- + FS_FREE_CHANNELS; // go back to "current" blender time waitcursor(0); diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 9271fe834d4..48b98e9a65d 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -53,6 +53,7 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" +#include "DNA_object_fluidsim.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_texture_types.h" @@ -141,6 +142,14 @@ void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo) conchan->ipo= ipo; } } + else if(si->blocktype==ID_FLUIDSIM) { // NT + if( (ob->fluidsimSettings) && + (ob->fluidsimSettings->ipo) ) { + // decrement users counter + ob->fluidsimSettings->ipo->id.us--; + } + ob->fluidsimSettings->ipo = ipo; + } else if(si->blocktype==ID_OB) { if(ob->ipo) ob->ipo->id.us--; @@ -798,6 +807,9 @@ static char *ipo_modeselect_pup(void) #ifdef __CON_IPO str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT); #endif + if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD); + } } str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE); @@ -1135,6 +1147,8 @@ void ipo_buttons(void) icon = ICON_SEQUENCE; else if(G.sipo->blocktype == ID_TE) icon = ICON_TEXTURE; + else if(G.sipo->blocktype == ID_FLUIDSIM) + icon = ICON_WORLD; uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type"); |