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 //! 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 "<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 '"<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 AttributeList::readChannelFloat(string name) { if(!exists(name)) { return AnimChannel(0.0); } - return find(name)->getChannelFloat(); + AnimChannel ret = find(name)->getChannelFloat(); + find(name)->setUsed(true); + channelSimplifyd(ret); + return ret; } AnimChannel AttributeList::readChannelInt(string name) { if(!exists(name)) { return AnimChannel(0); } - return find(name)->getChannelInt(); + AnimChannel ret = find(name)->getChannelInt(); + find(name)->setUsed(true); + channelSimplifyi(ret); + return ret; } AnimChannel AttributeList::readChannelVec3d(string name) { if(!exists(name)) { return AnimChannel(0.0); } - return find(name)->getChannelVec3d(); + AnimChannel ret = find(name)->getChannelVec3d(); + find(name)->setUsed(true); + channelSimplifyVd(ret); + return ret; +} +AnimChannel AttributeList::readChannelVec3f(string name) { + if(!exists(name)) { return AnimChannel(0.0); } + + AnimChannel convert = find(name)->getChannelVec3d(); + // convert to float + vector vals; + for(size_t i=0; i times = convert.accessTimes(); + AnimChannel 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 channel) { + ntlVec3f ret(0.0); + float maxLen = 0.0; + for(size_t i=0; imaxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +ntlVec3d channelFindMaxVd (AnimChannel channel) { + ntlVec3d ret(0.0); + float maxLen = 0.0; + for(size_t i=0; imaxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +int channelFindMaxi (AnimChannel channel) { + int ret = 0; + float maxLen = 0.0; + for(size_t i=0; imaxLen) { ret= (int)channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +float channelFindMaxf (AnimChannel channel) { + float ret = 0.0; + float maxLen = 0.0; + for(size_t i=0; imaxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} +double channelFindMaxd (AnimChannel channel) { + double ret = 0.0; + float maxLen = 0.0; + for(size_t i=0; imaxLen) { ret=channel.accessValues()[i]; maxLen=nlen; } + } + return ret; +} + +/****************************************************************************** + // unoptimized channel simplification functions, use elbeem.cpp functions + // warning - currently only with single precision + *****************************************************************************/ + +template +static bool channelSimplifyScalarT(AnimChannel &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 vals; + vector times; + for(int i=0; i(vals, times); + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() ); + } + delete [] nchannel; + return ret; +} +bool channelSimplifyi (AnimChannel &channel) { return channelSimplifyScalarT(channel); } +bool channelSimplifyf (AnimChannel &channel) { return channelSimplifyScalarT(channel); } +bool channelSimplifyd (AnimChannel &channel) { return channelSimplifyScalarT(channel); } +template +static bool channelSimplifyVecT(AnimChannel &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 vals; + vector times; + for(int i=0; i(vals, times); + if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() ); + } + delete [] nchannel; + return ret; +} +bool channelSimplifyVf (AnimChannel &channel) { + return channelSimplifyVecT(channel); +} +bool channelSimplifyVd (AnimChannel &channel) { + return channelSimplifyVecT(channel); +} + +template +string AnimChannel::printChannel() { + std::ostringstream ostr; + ostr << " CHANNEL #"<< mValue.size() <<" = { "; + for(size_t i=0;i class ntlMatrix4x4; //! An animated attribute channel @@ -19,19 +19,24 @@ template 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 v, vector 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[mTimes.size()-1]) { return mValue[mTimes.size()-1]; } for(size_t i=0; i &accessValues() { return mValue; } + //! raw access of time vector + vector &accessTimes() { return mTimes; } + protected: + /*! inited at least once? */ + bool mInited; /*! anim channel attribute values */ vector mValue; /*! anim channel attr times */ vector 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 *mat); //! get channel as integer value AnimChannel getChannelInt(); //! get channel as double value AnimChannel getChannelFloat(); - //! get channel as double value + //! get channel as double vector AnimChannel 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 defaultValue, string source,string target, bool needed, ntlMatrix4x4 *mat); //! read attributes channels (attribute should be inited before) AnimChannel readChannelInt(string name); AnimChannel readChannelFloat(string name); AnimChannel readChannelVec3d(string name); + AnimChannel 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 channel); +ntlVec3d channelFindMaxVd (AnimChannel channel); +int channelFindMaxi (AnimChannel channel); +float channelFindMaxf (AnimChannel channel); +double channelFindMaxd (AnimChannel channel); + +// unoptimized channel simplification functions, use elbeem.cpp functions +bool channelSimplifyVf (AnimChannel &channel); +bool channelSimplifyVd (AnimChannel &channel); +bool channelSimplifyi (AnimChannel &channel); +bool channelSimplifyf (AnimChannel &channel); +bool channelSimplifyd (AnimChannel &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 - -// 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:"< - -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, + 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, - 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, + 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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 + 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, 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 103, 79, 56, 565, 7, 565, 565, 565, 565, 565, + 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 34, 24, 15, 7, 565, 565, 565, 565, 565, 565, + 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 @@ -825,7 +828,7 @@ extern "C" int yy_wrap (void ) { return 1; } * rules start */ /*----------------------------------------------------------------------------*/ -#line 829 "" +#line 832 "" #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 "" +#line 989 "" 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 "<" +#line 1609 "" 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 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< 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; + + 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: "<getName()<<" type="<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: "< 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; itype */ //#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 #include @@ -20,23 +20,15 @@ #include #endif -/* -template class vector; -template class vector; -template class vector; -template class vector; -template class vector; -template class vector< vector >; -*/ /****************************************************************************** * 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 "<0) && (kmSizex-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; i0.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="< numadjacentfaces(mPoints.size()); - //errMsg("SUBDIV ADJFA1", " "< &a1 = mAdjacentFaces[v1]; - const vector &a2 = mAdjacentFaces[v2]; - for (int k1 = 0; k1 < (int)a1.size(); k1++) { - int other = a1[k1]; - if (other == i) - continue; - vector::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 newverts(nf, TriMesh::Face(-1,-1,-1)); - vector 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 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:"<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"< 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"< boundary = neighbors[v]; - while (!boundary.empty()) { - const int bbn = boundary.back(); - boundary.pop_back(); - if (flags[bbn] == flag) continue; + int flag = mFlagCnt; + mFlagCnt++; + flags[src] = flag; + //vector 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; - // gaussian weight of width 1/sqrt(invsigma2) - const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - mPoints[v].v); - 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? + // 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 - srcp); + if(d2 >= 9.0f) continue; // 25 also possible , slower + //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 numneighbors(mPoints.size()); int i; for (i = 0; i < (int)mIndices.size()/3; i++) { @@ -845,10 +605,11 @@ void IsoSurface::smoothSurface(float sigma) vector 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 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 numneighbors(mPoints.size()); int i; for (i = 0; i < (int)mIndices.size()/3; i++) { @@ -998,13 +765,13 @@ void IsoSurface::smoothNormals(float sigma) vector 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:"< mPoints; @@ -96,8 +93,12 @@ class IsoSurface : vector mAcrossEdge; vector< vector > mAdjacentFaces; - vector flags; - unsigned flag_curr; + //! cutoff border area + int mCutoff; + + //! trimesh vars + vector flags; + int mFlagCnt; vector cornerareas; vector pointareas; vector< vector > 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 *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 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 @@ -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 Triangles; vector Vertices; vector 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(*iter); hideObjs.push_back( (*iter)->getName() ); + geoshad->notifyShaderOfDump(glob->getAniCount(),nrStr,glob->getOutFilename()); for (vector::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; igetOutFilename() <<"_"<< (*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:"<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; igetVelocityAt( 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 "< @@ -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::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 "< 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 ("<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,9 +80,117 @@ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) } } +/****************************************************************************** + * init model from given vertex and triangle arrays + *****************************************************************************/ + +int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles) +{ + mVertices.clear(); + mVertices.resize( numVertices ); + mNormals.resize( numVertices ); + for(int i=0; i1e9) { + errMsg("Reading GZ_BOBJ"," invalid num vertices "<< numVerts); + goto gzreaderror; + } + mVertices.clear(); + mVertices.resize( numVerts ); + for(int i=0; i1e9) { + errMsg("Reading GZ_BOBJ","invalid num normals "<< numVerts); + goto gzreaderror; + } + mNormals.clear(); + mNormals.resize( numVerts ); + for(int i=0; i1e9) { + errMsg("Reading GZ_BOBJ","invalid num normals "<< numTris); + goto gzreaderror; + } + mTriangles.resize( 3*numTris ); + for(int i=0; itriangles[(x)] /****************************************************************************** * @@ -94,129 +209,18 @@ ntlGeometryObjModel::getTriangles( vector *triangles, 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 */ + ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */ } + objectId = -1; // remove warning // bobj return; } -/****************************************************************************** - * load model from .obj file - *****************************************************************************/ - -int ntlGeometryObjModel::loadBobjModel(string filename) -{ - const bool debugPrint=false; - gzFile gzf; - gzf = gzopen(filename.c_str(), "rb"); - if (!gzf) { - errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n", SIMWORLD_INITERROR ); - 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); - goto gzreaderror; - } - if(wri<0 || wri>1e9) { - errMsg("Reading GZ_BOBJ"," invalid num vertices "<< wri); - goto gzreaderror; - } - mVertices.clear(); - mVertices.resize( wri ); - for(int i=0; i1e9) { - errMsg("Reading GZ_BOBJ","invalid num normals "<< wri); - goto gzreaderror; - } - mNormals.clear(); - mNormals.resize( wri ); - for(int i=0; i1e9) { - errMsg("Reading GZ_BOBJ","invalid num normals "<< wri); - goto gzreaderror; - } - mTriangles.resize( 3*wri ); - for(int i=0; igetMaterials() ); 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 '"<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(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 '"<getName()<<"': gid="<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(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 '"<getName()<<"': visible="<mVisible<<" gid="<getName()<<" frame:"< *mat) { - //errorOut("my: "<::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()<<"' "< *mat) i++; } errFatal("ntlGeometryObject::searchMaterial","Unknown material '"< *triangles, + vector *vertices, + vector *normals) { + ntlTriangle tri; + int tempVert; + + if(normals->size() != vertices->size()) { + errFatal("ntlGeometryObject::sceneAddTriangle","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 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="<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:"< vals; + vector valsd; + vector 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:"< *verts, vector *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="< triangles; + vector vertices; + vector normals; + int objectId = 1; + this->getTriangles(&triangles,&vertices,&normals,objectId); + + mMovPoints.clear(); //= vertices; + mMovNormals.clear(); //= normals; + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Object "<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:"< fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + errMsg("ntlGeometryObject::initMovingPoints","tri:"< "< 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 "< 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; idist) { + 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 "<"< &ret, vector *norms) { + if(mHaveCachedMov) { + ret = mCachedMovPoints; + if(norms) { *norms = mCachedMovNormals; } + errMsg ("ntlGeometryObject::getMovingPoints","Object "< 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="< *triangles, vector *vertices, vector *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 *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 *verts, vector *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 &ret, vector *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 *triangles, + vector *vertices, + vector *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 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 mcTrans, mcRot, mcScale; + /*! easy check for animation */ + bool mIsAnimated; + + /*! moving point/normal storage */ + vector mMovPoints; + vector mMovNormals; + /*! cached points for non moving objects/timeslots */ + bool mHaveCachedMov; + vector mCachedMovPoints; + vector mCachedMovNormals; + /*! inited? */ + float mMovPntsInited; + /*! point with max. distance from center */ + int mMaxMovPnt; + + /*! animated channels for in/outflow on/off */ + AnimChannel 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::iterator getObjectsBegin() { return mObjects.begin(); } /*! Get end iterator for all objects */ virtual vector::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 similarity index 78% rename from intern/elbeem/intern/ntl_lightobject.cpp rename to 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 )&&( tritgetDebugOut() > 5) errorOut("Omni lighting with "< inline void ntlMatrix4x4::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 inline void ntlMatrix4x4::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 inline void ntlMatrix4x4::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::initRotationZ(Scalar rot) value[1][0] = (Scalar)(-sin(drot)); value[1][1] = (Scalar) cos(drot); } +template +inline void +ntlMatrix4x4::initRotationXYZ( Scalar rotx, Scalar roty, Scalar rotz) +{ + ntlMatrix4x4 val; + ntlMatrix4x4 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 @@ -651,6 +680,20 @@ ntlMatrix4x4::initScaling(Scalar x, Scalar y, Scalar z) } +//! from 16 value array (init id if all 0) +template +inline void +ntlMatrix4x4::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 *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 "<getScene()->getVertex(tri->getPoints()[0])<<" t2:"<getScene()->getVertex(tri->getPoints()[1])<<" t3:"<getScene()->getVertex(tri->getPoints()[2]) ); + errorOut(" t1:"<getRenderScene()->getVertex(tri->getPoints()[0])<<" t2:"<getRenderScene()->getVertex(tri->getPoints()[1])<<" t3:"<getScene()->getVertex(tri->getPoints()[2]) ); errorOut(" trin:"<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::iterator iter = mGeos.begin(); + iter != mGeos.end(); iter++) { + //errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() ); + delete (*iter); + } + for (vector::iterator iter = mpGlob->getLightList()->begin(); + iter != mpGlob->getLightList()->end(); iter++) { + delete (*iter); + } + for (vector::iterator iter = mpGlob->getMaterials()->begin(); + iter != mpGlob->getMaterials()->end(); iter++) { + delete (*iter); + } + } + errMsg("ntlScene::~ntlScene","Deleted, ObjFree:"<::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 "<getName()<<" Id:"<getObjectId(), 5 ); + } + //if(geoshad) { + if(tid & GEOCLASSTID_SHADER) { + ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); + geoinit = true; + if(!mFirstInitDone) { + // only on first init + geoshad->initializeShader(); + } + for (vector::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::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(downscale2setResX( (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::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:"<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:"<::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::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::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::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:"<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 #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 *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 *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 *getObjects() { + if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; } + return &mObjects; } + + /*! Acces geo class array */ + inline vector *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 *getVertexPointer( void ) { return &mVertices; } + /*! return pointer to vertices vector */ + vector *getVertexNormalPointer( void ) { return &mVertNormals; } + /*! return pointer to vertices vector */ + vector *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 mGeos; + + /*! List of geometry objects */ + vector mObjects; + + /*! List of triangles */ + vector mTriangles; + /*! List of vertices */ + vector mVertices; + /*! List of normals */ + vector mVertNormals; + /*! List of triangle normals */ + vector 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 *getObjectList(void) { return mpObjList; } - //! Set the object list - //inline void setObjectList(vector *set) { mpObjList = set;} - - //! Returns the light object list - inline vector *getLightList(void) { return mpLightList; } - //! Set the light list - inline void setLightList(vector *set) { mpLightList = set;} - - //! Returns the property object list - inline vector *getMaterials(void) { return mpMaterials; } - //! Set the property list - inline void setMaterials(vector *set) { mpMaterials = set;} - - //! Returns the list of simulations - inline vector *getSims(void) { return mpSims; } - //! Set the pointer to the list of simulations - inline void setSims(vector *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 *mpObjList; - //! List of light objects - vector *mpLightList; - //! List of surface properties - vector *mpMaterials; - /*! storage for simulations */ - vector *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::iterator iter = mGeos.begin(); - iter != mGeos.end(); iter++) { - delete (*iter); - } - for (vector::iterator iter = mpGlob->getLightList()->begin(); - iter != mpGlob->getLightList()->end(); iter++) { - delete (*iter); - } - for (vector::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::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 "<getName(), 5 ); - } - //if(geoshad) { - if(tid & GEOCLASSTID_SHADER) { - ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); - geoinit = true; - if(!mFirstInitDone) { - // only on first init - geoshad->initializeShader(); - } - for (vector::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::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(downscale2setResX( (int)(mpGlob->getResX() * downscale) ); - mpGlob->setResY( (int)(mpGlob->getResY() * downscale) ); - - } - - /* collect triangles from objects */ - int idCnt = 0; // give IDs to objects - for (vector::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::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::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::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::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:"<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 -#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 '"<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 *getObjects() { - if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; } - return &mObjects; } - - /*! Acces geo class array */ - inline vector *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 *getVertexPointer( void ) { return &mVertices; } - /*! return pointer to vertices vector */ - vector *getVertexNormalPointer( void ) { return &mVertNormals; } - /*! return pointer to vertices vector */ - vector *getTrianglePointer( void ) { return &mTriangles; } - -private: - - /*! Global settings */ - ntlRenderGlobals *mpGlob; - - /*! List of geometry classes */ - vector mGeos; - - /*! List of geometry objects */ - vector mObjects; - - /*! List of triangles */ - vector mTriangles; - /*! List of vertices */ - vector mVertices; - /*! List of normals */ - vector mVertNormals; - /*! List of triangle normals */ - vector 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 *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 #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; - mpPropList = new vector; - mpSims = new vector; +#ifndef ELBEEM_PLUGIN - mpGlob->setLightList(mpLightList); - mpGlob->setMaterials(mpPropList); - mpGlob->setSims(mpSims); + initDefaults(); +# ifdef NOGUI + commandlineMode = true; // remove warning... +# endif // NOGUI - /* 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;isize();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: "<=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:"<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 valf; + vector valv; + vector time; + +#define INIT_CHANNEL_FLOAT(channel,size) \ + valf.clear(); time.clear(); elbeemSimplifyChannelFloat(channel,&size); \ + for(int i=0; ichannelViscosity, 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: "<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 "<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 "<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 "<size()<<" t"<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;isize();i++) { - if(!(*mpSims)[i]->getVisible()) continue; - if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? - //debMsgStd("ntlWorld::advanceSims",DM_MSG, " sim "<getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<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:"<getTimestep() ); + allPanic = true; + } else { + for(size_t i=0;isize();i++) { + if(!(*mpSims)[i]->getVisible()) continue; + if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!? + debMsgStd("ntlWorld::advanceSims",DM_MSG, "Sim "<getCurrentTime()<<", nt:"<getPanic()<<", targett:"<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: "<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 "<getCurrentTime()<<" target:"<getCurrentTime())<<" stept:"<getStepTime()<<" leps:"<getCurrentTime()<<" target:"<getCurrentTime())<<" stept:"<getTimestep()<<" leps:"<getCurrentTime()) > LBM_TIME_EPSILON) { if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping 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="<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 *getLightList(void) { return mpLightList; } + //! Set the light list + inline void setLightList(vector *set) { mpLightList = set;} + + //! Returns the property object list + inline vector *getMaterials(void) { return mpMaterials; } + //! Set the property list + inline void setMaterials(vector *set) { mpMaterials = set;} + + //! Returns the list of simulations + inline vector *getSims(void) { return mpSims; } + //! Set the pointer to the list of simulations + inline void setSims(vector *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 *mpLightList; + //! List of surface properties + vector *mpMaterials; + /*! storage for simulations */ + vector *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 #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:"<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:"<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:"<find("p_aniframetime")->print(); + mFrameNum = frame; + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","setFrameNum frame-num="<find("p_aniframetime")->print(); + if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<1000000)) { - errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="< ani-frame-time ("< ani-frame-time ("<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: "<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 = "<0.0)) { - ParamFloat massDelta = 1.0; - ParamFloat densityStar = 1.0; - massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize; - if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<0)) { if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<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="<0.0)) { + ParamFloat massDelta = 1.0; + ParamFloat densityStar = 1.0; + massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize; + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<0.0) { + ParamFloat maxSpeed = 1.0/6.0; // for rough reynolds approx + ParamFloat reynoldsApprox = -1.0; + ParamFloat gridSpeed = (maxSpeed*mCellSize/mTimestep); + reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity; + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<readFloat("p_relaxtime",mRelaxTime, "Parametrizer","mRelaxTime", false); + //if(getAttributeList()->exists("p_relaxtime")) seenThis( PARAM_RELAXTIME ); + //? mReynolds = mpAttrs->readFloat("p_reynolds",mReynolds, "Parametrizer","mReynolds", false); + //if(getAttributeList()->exists("p_reynolds")) seenThis( PARAM_REYNOLDS ); + + //mViscosity = mpAttrs->readFloat("p_viscosity",mViscosity, "Parametrizer","mViscosity", false); + //if(getAttributeList()->exists("p_viscosity") || (!mcViscosity.isInited()) ) { } + //if(getAttributeList()->exists("p_viscosity")) + //ParamFloat viscStar = calculateLatticeViscosity(time); + //RelaxTime = (6.0 * viscStar + 1) * 0.5; 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(mViscosity); - } - /*! get current kinematic viscosity (warning - this might change over time) */ - ParamFloat getViscosity( void ) { return mViscosity; } + void setViscosity(ParamFloat set) { mcViscosity = AnimChannel(set); seenThis( PARAM_VISCOSITY ); } + void initViscosityChannel(vector val, vector time) { mcViscosity = AnimChannel(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(mGravity); - } - void setGravity(ParamVec set) { - mGravity = set; seenThis( PARAM_GRAVITY ); - mcGravity = AnimChannel(mGravity); - } + void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mcGravity = AnimChannel(ParamVec(setx,sety,setz)); seenThis( PARAM_GRAVITY ); } + void setGravity(ParamVec set) { mcGravity = AnimChannel(set); seenThis( PARAM_GRAVITY ); } + void initGravityChannel(vector val, vector time) { mcGravity = AnimChannel(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(set); seenThis( PARAM_ANIFRAMETIME ); } + void initAniFrameTimeChannel(vector val, vector time) { mcAniFrameTime = AnimChannel(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 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 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 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 @@ -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 "<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; i1) { + //if(l>1) { //mParts[l][ mParts.size()-1 ].setActive( false ); - } - } + //} + //} } +void ParticleTracer::cleanup() { + // cleanup + int last = (int)mParts.size()-1; + //for(vector::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 "<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:"<getName()<<" frame:"<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:"<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 *triangles, vector *vertices, vector *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<<","<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 = mParts[lnewst][i].getPos(); - ntlVec3Gfx pold = mParts[loldst][i].getPos(); - ntlVec3Gfx pdir = pnew - pold; + ntlVec3Gfx pnew = p->getPos(); + if(type&PART_FLOAT) { // WARNING same handling for dump! + // add one gridcell offset + //pnew[2] += 1.0; + } + + 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"< 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::iterator getParticlesBegin() { return mParts[0].begin(); } + inline vector::iterator getParticlesBegin() { return mParts.begin(); } //! end iterator for newest particles - inline vector::iterator getParticlesEnd() { return mParts[0].end(); } + inline vector::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; } + inline void setEnd(ntlVec3Gfx set) { mEnd = set; initTrafoMatrix(); } + /*! get values */ + inline ntlVec3Gfx getStart() { return mStart; } + /*! set geometry end (for renderer) */ + 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 *triangles, vector *vertices, vector *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 > 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 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 *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; igetScene(); + 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 + + //mDimension, mSolverType are deprecated + string mSolverType(""); 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; - } - + //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"<getIdString() <<" LBM solver! ", 2); + debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<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: "<generateVertexVectors<<","<getDumpVelocities(), 9 ); + + debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<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: " < 0) { - debugOut("SimulationObject::initializeLbmSimulation celltype Warning: Diffinits="<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 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 '"<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: "< (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::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 #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 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"<2) ret<<",k"<2) ret<<",k"< *cid = dynamic_cast *>( other ); - UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( 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 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* /*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 interface - typedef UniformFsgrCellIdentifier 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: "<mName<<" step: "<mStepCnt<<" lev:"<<(lev)<<" marking "<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 "< -void LbmFsgrSolver::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 void -LbmFsgrSolver::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::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, return; } -template void -LbmFsgrSolver::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::initVelocityCell(int level, int i,int j,int k, CellFlagType fl return; } -template -int LbmFsgrSolver::getForZMinBnd() { +int LbmFsgrSolver::getForZMinBnd() { return 0; } -template -int LbmFsgrSolver::getForZMin1() { - if(D::cDimension==2) return 0; +int LbmFsgrSolver::getForZMin1() { + if(LBMDIM==2) return 0; return 1; } -template -int LbmFsgrSolver::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 -int LbmFsgrSolver::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 -LbmFsgrSolver::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::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; mcDfNum; l++) { + this->lesCoeffDiag[m][l] = + this->lesCoeffOffdiag[m][l] = 0.0; } } - for(int m=0; mcDfNum; 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="<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="<lesCoeffDiag[m][l] = coeff; } else { if(m>n) { - D::lesCoeffOffdiag[odm][l] = coeff; + this->lesCoeffOffdiag[odm][l] = coeff; } } } @@ -101,7 +372,7 @@ LbmFsgrSolver::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::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;(ncDirNum); n++) { mGaussw[n] = 0.0; } + //for(int n=0;(ncDirNum); n++) { + for(int n=0;(ncDfNum); 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;(ncDirNum); n++) { mGaussw[n] = mGaussw[n]/totGaussw; } + mpParticles = NULL; //addDrop(false,0,0); } /*****************************************************************************/ /* Destructor */ /*****************************************************************************/ -template -LbmFsgrSolver::~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::~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::~LbmFsgrSolver() /****************************************************************************** * initilize variables fom attribute list *****************************************************************************/ -template -void -LbmFsgrSolver::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 ); + 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= 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 ); + 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 = D::mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", 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::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:"< -void -LbmFsgrSolver::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:"<mGravity-mLastGravity); + //errMsg("ChannelAnimDebug","t:"<mOmega<<" - lom:"<mGravity<<" - "<mOmega == mLastOmega) && (gravDelta<=0.0)) return; if(mInitialCsmago<=0.0) { if(OPT3D==1) { @@ -242,8 +515,8 @@ LbmFsgrSolver::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::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 "<mInitDone) { debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<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::initLevelOmegas() /****************************************************************************** * Init Solver (values should be read from config file) *****************************************************************************/ -template -bool -//LbmFsgrSolver::initialize( ntlTree* /*tree*/, vector* /*objects*/ ) -LbmFsgrSolver::initializeSolver() +bool LbmFsgrSolver::initializeSolver() { - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... (Layout:"<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::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 "<mSizex = (int)(orgSx * sizeReduction); + this->mSizey = (int)(orgSy * sizeReduction); + this->mSizez = (int)(orgSz * sizeReduction); + debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<mSizex<<" Y:"<mSizey<<" Z:"<mSizez, 3 ); } else { memOk = true; } } - D::mPreviewFactor = (LbmFloat)D::mOutputSurfacePreview / (LbmFloat)D::mSizex; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<mPreviewFactor = (LbmFloat)this->mOutputSurfacePreview / (LbmFloat)this->mSizex; + debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<mSizex<<" Y:"<mSizey<<" Z:"<mSizez<< + ", Domain: "<mvGeoStart<<":"<mvGeoEnd<<", "<<(this->mvGeoEnd-this->mvGeoStart)<< ", est. Mem.Req.: "<setSize(D::mSizex, D::mSizey, D::mSizez); + this->mpParam->setSize(this->mSizex, this->mSizey, this->mSizez); - //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Size X:"<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 "<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::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::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::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: "<0.01) { + errMsg("LbmFsgrSolver::initialize","Sanity Error - memory estimate is off! real:"<::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::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 ", " "<setStart( vec2G(isostart) ); - D::mpIso->setEnd( vec2G(isoend) ); + //errMsg(" SETISO ", " "<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;akgetData(ai,aj,ak) = 0.0; } + this->mpIso->initializeIsosurface( this->mSizex+2, this->mSizey+2, this->mSizez+2+twodOff, vec2G(isodist) ); + for(int ak=0;akmSizez+2+twodOff;ak++) + for(int aj=0;ajmSizey+2;aj++) + for(int ai=0;aimSizex+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::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(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); } else { domainBoundType = CFBnd | CFBndNoslip; - debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<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"<getName()); - //if((*D::mpGiObjects)[i] == D::mpIso) { - //check... + //errMsg("GEOIN","i"<mpGiObjects)[i]->getName()); + //if((*this->mpGiObjects)[i] == this->mpIso) { //check... //} //} //errMsg("GEOIN"," dm "<<(domainBoundType>>24)); @@ -594,7 +873,7 @@ LbmFsgrSolver::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::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:"<::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::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:"<mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<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::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::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="<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 vertices; + vector verticesOld; + int i,j,k; // grid pos init + LbmFloat ux,uy,uz, rho; + for(int OId=0; OIdmpGiObjects)[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 "<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 "<getName()<<" a:"<mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ))); + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<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 "< "<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"< "<getName()<<" inflow "<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 *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 "< -bool -LbmFsgrSolver::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"<mGeoInitId <<") v"<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="<getSimulationMaxSpeed() > allowMax) { + // make sure moving obstacles are inited correctly + // preinit moving obj points + int numobjs = (int)(this->mpGiObjects->size()); + for(int o=0; ompGiObjects)[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.="<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::initGeometryFlags() { for(int k= getForZMin1(); k< getForZMax1(level); ++k) { for(int j=1;jgeoInitCheckPointInside( 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::initGeometryFlags() { } // zmax // */ - /* - for(int k= getForZMin1(); k< getForZMax1(level); ++k) { - for(int i=1;igeoInitCheckPointInside( 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::initGeometryFlags() { } } // zmax - D::freeGeoTree(); + // reset invalid to empty again + for(int k= getForZMin1(); k< getForZMax1(level); ++k) { + for(int j=1;jfreeGeoTree(); myTime_t geotimeend = getTime(); - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< ((geotimeend-geotimestart)/(double)1000.0)<<"s,"< -void -LbmFsgrSolver::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::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::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; scDirNum); 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"<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::initFreeSurfaces() { /*****************************************************************************/ /* init part for all freesurface testcases */ -template -void -LbmFsgrSolver::initStandingFluidGradient() { +void LbmFsgrSolver::initStandingFluidGradient() { // ---------------------------------------------------------------------- // standing fluid preinit const int debugStandingPreinit = 0; @@ -1203,7 +1774,8 @@ LbmFsgrSolver::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="<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 "<::initStandingFluidGradient() { kstart = temp-1; } // COMPRT for(int k=kstart;k!=kend;k+=kdir) { - - //errMsg("LbmFsgrSolver::mainLoop","k="< -bool -LbmFsgrSolver::checkSymmetry(string idstring) +bool LbmFsgrSolver::checkSymmetry(string idstring) { bool erro = false; bool symm = true; @@ -1388,7 +1968,7 @@ LbmFsgrSolver::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::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::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::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::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 - -template class LbmFsgrSolver< LBM_INSTANTIATE >; - -#endif // __APPLE_CC__ __INTEL_COMPILER + +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; + } + } + } + + 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 "<=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 "<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 "<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"<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"<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"<getInitialVelocity(simtime)<<" o"<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 inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); } template inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); } @@ -75,40 +85,73 @@ template 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) - -//! refinement tags -// cell treated normally on coarser grids -#define CFGrNorm (1<<13) -// border cells to be interpolated from finer grid -#define CFGrFromFine (1<<14) -#define CFGrFromCoarse (1<<15) -#define CFGrCoarseInited (1<<16) -// 32k aux border marker -#define CFGrToFine (1<<17) -#define CFMbndInflow (1<<18) -#define CFMbndOutflow (1<<19) +#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) -// debug/helper type -#define CFIgnore (1<<20) +// 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) + +// cell treated normally on coarser grids +#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<<13) +// 32k aux border marker +#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 -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 *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,355 +535,28 @@ class LbmSolverInterface float mSmoothSurface; float mSmoothNormals; + //! particle generation probability + LbmFloat mPartGenProb; + + //! dump velocities? + bool mDumpVelocities; + // list for marked cells vector mMarkedCells; int mMarkedCellIndex; + + //! domain boundary free/no slip type + std::string mDomainBound; + //! part slip value for domain + LbmFloat mDomainPartSlipValue; + + //! test vars + // strength of applied force + LbmFloat mTForceStrength; + }; -//! 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 ]; - - /* 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 ]; - -}; // LbmData3D - - - -// lbmdimensions - -// not needed hereafter -#undef STCON - - - -/*****************************************************************************/ -//! class for solver templating - lbgk (srt) model implementation -template -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; l0.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 LbmBGK2D; -typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D; - - // helper function to create consistent grid resolutions void initGridSizes(int &mSizex, int &mSizey, int &mSizez, ntlVec3Gfx &mvGeoStart, ntlVec3Gfx &mvGeoEnd, 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 -string LbmFsgrSolver::getIdString() { - return string("FsgrSolver[") + D::getIdString(); -} -template -int LbmFsgrSolver::getDimension() { return D::cDimension; } - -template -void LbmFsgrSolver::step() { +void LbmFsgrSolver::step() { initLevelOmegas(); stepMain(); } -template -void -LbmFsgrSolver::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 : "<mStepCnt, 10); + if(!this->mSilent){ debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<mStepCnt<<" t:"<mStepCnt<<" "); myTime_t timestart = getTime(); //myTime_t timestart = 0; //if(mStartSymm) { checkSymmetry("step1"); } // DEBUG - // important - keep for tadap - mCurrentMass = D::mFixMass; // reset here for next step - mCurrentVolume = 0.0; - - //stats + // time adapt mMaxVlen = mMxvz = mMxvy = mMxvx = 0.0; + // init moving bc's, can change mMaxVlen + initMovingObstacles(false); + + // important - keep for tadap + mCurrentMass = this->mFixMass; // reset here for next step + mCurrentVolume = 0.0; + //change to single step advance! int levsteps = 0; - int dsbits = D::mStepCnt ^ (D::mStepCnt-1); - //errMsg("S"," step:"<mStepCnt ^ (this->mStepCnt-1); + //errMsg("S"," step:"<mStepCnt<<" s-1:"<<(this->mStepCnt-1)<<" xf:"<mStepCnt&(1<::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:"<mStepCnt); + debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<mStepCnt<<" t:"<mMLSUPS<< " avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<< sepStr<< - " totcls:"<<(D::mNumUsedCells)<< sepStr<< + " totcls:"<<(this->mNumUsedCells)<< sepStr<< " avgcls:"<< avgcls<< sepStr<< " intd:"<mNumFilledCells<<", emptied:"<mNumEmptiedCells<< sepStr<< " mMxv:"<mName<<"' " , 10); debMsgDirect(std::endl); - debMsgDirect(D::mStepCnt<<": dccd="<< mCurrentMass<<"/"<mStepCnt<<": dccd="<< mCurrentMass<<"/"<mFixMass<<",ini="<::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::mNumUsedCellsmNumUsedCells>mMaxNoCells) mMaxNoCells = this->mNumUsedCells; + if(this->mNumUsedCellsmNumUsedCells; } // mass scale test @@ -167,7 +163,7 @@ LbmFsgrSolver::stepMain() errMsg("MDTDD","\n\n"); errMsg("MDTDD","FORCE RESCALE MASS! " <<"ini:"<mStepCnt<<" levstep:"<::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;jmDebugvalue3>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 -void -LbmFsgrSolver::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;lsetFluidVolumeHeight(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 "<mSilent){ errMsg("fineAdvance"," stepped from "<::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::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 void -LbmFsgrSolver::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:"<::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::mainLoop(int lev) pFlagDst+= (p); \ i+= (p); - // --- // now stream etc. -//{ errMsg("LbmFsgrSolver::mainLoop","Err MAINADVANCE0 ks:"<< kstart<<" ke:"<::mainLoop(int lev) #if PARALLEL==1 PARA_INITIALIZE(); - errMsg("LbmFsgrSolver::mainLoop","id="<::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::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::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 "<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) && (lcsmqothis->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:"<pTest->mFluidHeight*1.5)) { doAdd=true; } // FORCEDISSOLVE + //? if(!bndOk) doAdd=false; + //if(this->mStepCnt>700) errMsg("DFJITT"," at "<::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::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::mainLoop(int lev) float flux = FLUX_INIT; // dxqn on if(newFlag&CFNoBndFluid) { //flux = 50.0; // extreme on - for(int nn=1; nncDfNum; 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; nncDfNum; nn++) { if(nbfracs[nn]!=0.0) { LbmFloat curSmooth = (sssUsqrLimit-usqr)*sssUsqrLimitInv; if(curSmooth>1.0) curSmooth=1.0; @@ -923,9 +1068,9 @@ LbmFsgrSolver::mainLoop(int lev) //errMsg("DFINI"," maxr l"<::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; lcDirNum; 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::coarseCalculateFluxareas(int lev) //errMsg("DFINI"," at l"<mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "< -void -LbmFsgrSolver::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 ("<::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::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::coarseAdvance(int lev) #if FSGR_STRICT_DEBUG==1 if(rho<-1.0){ debugMarkCell(lev, i,j,k ); errMsg("INVRHOCELL_CHECK"," l"<mNumUsedCells++; } } @@ -1085,7 +1229,7 @@ LbmFsgrSolver::coarseAdvance(int lev) //errMsg("coarseAdvance","level "<mSilent){ errMsg("coarseAdvance","level "<::coarseAdvance(int lev) // get dfs from level (lev+1) to (lev) coarse border nodes -template -void -LbmFsgrSolver::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 ("<::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::coarseRestrictFromFine(int lev) } } // & fluid }}} - if(!D::mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"< -bool -LbmFsgrSolver::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 ("<::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;((lcDirNum) && (!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::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; lcDirNum; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; //errMsg("performRefinement","On lev:"<::adaptGrid(int lev) { // from coarse cells without unused nbs are not necessary...! -> remove bool invNb = false; bool fluidNb = false; - for(int l=1; lcDirNum; 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::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::adaptGrid(int lev) { //errMsg("performRefinement","Removing CFGrFromCoarse on 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; lcDirNum; 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; mcDirNum; 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::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::adaptGrid(int lev) { RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; change=true; mNumFsgrChanges++; - for(int l=1; lcDirNum; 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)<<" "<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; mcDirNum; 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)<<" "<::adaptGrid(int lev) { }}} // TEST // PASS 3 */ - if(!D::mSilent){ errMsg("performRefinement"," for l"<mSilent){ errMsg("performRefinement"," for l"<::performCoarsening(int lev) { + //LbmFsgrSolver::performCoarsening(int lev) { { // PASS 4,5 bool nbsok; // WARNING @@ -1399,7 +1539,7 @@ LbmFsgrSolver::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::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::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;((lcDirNum) && (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::adaptGrid(int lev) { if(lev+1==mMaxRefine) reqType = CFNoBndFluid; nbsok = true; - for(int l=0; lcDirNum && 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::adaptGrid(int lev) { } // dont turn CFGrFromFine above interface cells into CFGrNorm // now check nbs on same level - for(int l=1; lcDirNum && 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::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"<mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<::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"<mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<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; lcDirNum; 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"<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::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:"<mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<::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; lcDirNum; 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::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;((lcDirNum) && (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::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::adaptGrid(int lev) { // PASS 5 */ } // coarsening, PASS 4,5 - if(!D::mSilent){ errMsg("adaptGrid"," for l"<mSilent){ errMsg("adaptGrid"," for l"<::adaptGrid(int lev) { //! cell restriction and prolongation /*****************************************************************************/ -template -void -LbmFsgrSolver::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 ("<::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;(ncDirNum); 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::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::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;(ncDirNum); 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::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::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int #endif //! LBM_NOADCOARSENING==1 } -template -void LbmFsgrSolver::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 ("<::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::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::interpolateCellFromCoarse(int lev, int i, int j,int k, in /*****************************************************************************/ -/*! perform a single LBM step */ +/*! change the size of the LBM time step */ /*****************************************************************************/ -template -void -LbmFsgrSolver::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); + LbmFloat allowMax = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity + LbmFloat nextmax = this->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; + //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(nextmaxgetStepTime() / fac; + newdt = this->mpParam->getTimestep() / fac; } } // newtr - //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<getMaxStepTime()<<" min"<getMinStepTime()<<" diff"<mpParam->getTimestep()); + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<mpParam->getMaxTimestep()<<" min"<mpParam->getMinTimestep()<<" diff"<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... "<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="<getSimulationMaxSpeed()<<" next:"<mpParam->getSimulationMaxSpeed()<<" next:"<mStepCnt, 10 ); debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< "rhoAvg="<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::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()getStepTime(); - if(D::mpParam->getStepTime()>mMaxStepTime) mMaxStepTime = D::mpParam->getStepTime(); + if(this->mpParam->getTimestep()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: "<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::adaptTimestep() LbmVec velOld; LbmFloat rho, ux,uy,uz; rho=0.0; ux = uy = uz = 0.0; - for(int l=0; lcDfNum; 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::adaptTimestep() LbmFloat df[LBM_DFNUM]; LbmFloat feqOld[LBM_DFNUM]; LbmFloat feqNew[LBM_DFNUM]; - for(int l=0; lcDfNum; 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; lcDfNum; l++) { // org scaling //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important // new scaling @@ -2100,21 +2266,22 @@ LbmFsgrSolver::adaptTimestep() } // lev - if(!D::mSilent) { - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<mSilent) { + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<mStepCnt<< + " no"<getCurrentGStar() , 10); + <<", oldDt:"<mOmega<<" gStar:"<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:"<mName<<" step:"<mStepCnt<<" newdt="<=0 ; lev--) { @@ -2143,12 +2310,12 @@ LbmFsgrSolver::adaptTimestep() // collide on current set LbmFloat rho, ux,uy,uz; rho=0.0; ux = uy = uz = 0.0; - for(int l=0; lcDfNum; 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::adaptTimestep() ux *= cfac; uy *= cfac; uz *= cfac; - for(int l=0; lcDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = this->getCollideEq(l, rho, ux,uy,uz); } rescs++; debMsgDirect("B"); } @@ -2189,9 +2356,7 @@ LbmFsgrSolver::adaptTimestep() * work on lists from updateCellMass to reinit cell flags *****************************************************************************/ -template -LbmFloat -LbmFsgrSolver::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::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, in return ret; } -template -void LbmFsgrSolver::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::iterator iter=mListNewInter.begin(); @@ -2245,20 +2409,14 @@ void LbmFsgrSolver::addToNewInterList( int ni, int nj, int nk ) { mListNewInter.push_back(newinter); } -template -void LbmFsgrSolver::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::reinitFlags( int workSet ) int i=iter->x, j=iter->y, k=iter->z; if(debugFlagreinit) errMsg("FULL", PRINT_IJK<<" mss"<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; - } - } - } + // new and empty interface cell, dont change old flag here! + addToNewInterList(ni,nj,nk); - 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? - } + 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,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"<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"<::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::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::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::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"<::reinitFlags( int workSet ) const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("FF I", PRINT_IJK<<" "<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::reinitFlags( int workSet ) massChange = 0.0; } else { // Problem! no interface neighbors - D::mFixMass += massChange; + this->mFixMass += massChange; //TTT mNumProblems++; - //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<mFixMass); } weightIndex++; @@ -2531,7 +2661,7 @@ void LbmFsgrSolver::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::reinitFlags( int workSet ) const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("EE I", PRINT_IJK<<" "<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::reinitFlags( int workSet ) massChange = 0.0; } else { // Problem! no interface neighbors - D::mFixMass += massChange; + this->mFixMass += massChange; //TTT mNumProblems++; - //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<mFixMass); } weightIndex++; @@ -2602,12 +2732,18 @@ void LbmFsgrSolver::reinitFlags( int workSet ) for( vector::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("???"," "<mFixMass * newIfFac); int nbored = 0; FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); } @@ -2634,8 +2770,8 @@ void LbmFsgrSolver::reinitFlags( int workSet ) } if(mListNewInter.size()>0){ - //errMsg("FixMassDisted"," fm:"<mFixMass<<" nif:"<mFixMass = 0.0; } // empty lists for next step @@ -2649,42 +2785,6 @@ void LbmFsgrSolver::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 string LbmFsgrSolver::getIdString(); -//template void LbmFsgrSolver::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 "<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 "<=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 "<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 "<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"<1.0)) {\ + errMsg("STREAMCHECK","ID"<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); \ } \ } -#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 >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 "< "<2*dim free slip */ \ - \ - } /* type reflect */\ - else {\ - errMsg("LbmFsgrSolver","Invalid Bnd type at "<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 "<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)<<" "<1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<dfDvecX[l]*m); uy += (this->dfDvecY[l]*m); uz += (this->dfDvecZ[l]*m); \ + if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<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"<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; mcDfNum; 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; lcDfNum; 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",">"<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; lcDfNum; 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; lcDfNum; l++) { + df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l]; + } + if((i==16)&&(j==10)) DEBUG_CALCPRINTCELL( "2dcoll "< -void LbmFsgrSolver::prepareVisualization( void ) { +void LbmFsgrSolver::prepareVisualization( void ) { int lev = mMaxRefine; int workSet = mLevel[lev].setCurr; @@ -31,7 +31,7 @@ void LbmFsgrSolver::prepareVisualization( void ) { for(int k= 0; k< 5; ++k) for(int j=0;jlbmGetData(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::prepareVisualization( void ) { for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k) for(int j=0;jlbmGetData(i,j,ZKOFF)=0.0; + *this->mpIso->lbmGetData(i,j,ZKOFF)=0.0; } #endif // LBMDIM==2 @@ -63,153 +63,183 @@ void LbmFsgrSolver::prepareVisualization( void ) { /* // flicker-test-fix: no real difference if( (!(RFLAG(lev, i,j,k,workSet)&CFNoBndFluid)) && (RFLAG(lev, i,j,k,workSet)&CFNoNbFluid) && - (valmIsoValue) ){ + 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;klbmGetData( 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;klbmGetData( 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;jlbmGetData( 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;jlbmGetData(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;jlbmGetData(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 -void LbmFsgrSolver::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:"<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"<getInitialVelocity() ); + mObjectSpeeds[i] = vec2L(this->mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[i]->getInitialVelocity(mSimulationTime) ))); + if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<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"<mDomainPartSlipValue; + if(debugRecalc) errMsg("recalculateObjectSpeeds","done, domain:"<::recalculateObjectSpeeds() { /*****************************************************************************/ /*! debug object display */ /*****************************************************************************/ -template -vector LbmFsgrSolver::getDebugObjects() { +vector LbmFsgrSolver::getDebugObjects() { vector debo; - if(D::mOutputSurfacePreview) { + if(this->mOutputSurfacePreview) { debo.push_back( mpPreviewSurface ); } -#if ELBEEM_PLUGIN!=1 +#if LBM_INCLUDE_TESTSOLVERS==1 if(mUseTestdata) { vector tdebo; tdebo = mpTest->getDebugObjects(); @@ -238,143 +267,511 @@ vector LbmFsgrSolver::getDebugObjects() { *****************************************************************************/ /*! init particle positions */ -template -int LbmFsgrSolver::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( (numgetNumParticles()) && (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 "<mDebugvalue2!=0.0){ errMsg("LbmTestdata"," part init "<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 "<getLast()->getPos() <<" s"<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 "<getLast()->getPos() <<" s"<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)&&(i0)&&(jgetLast()->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 "<getLast()->getPos() <<" s"<getLast()->getSize() ); + } + } } + } + // DEBUG TEST +#endif // LBM_INCLUDE_TESTSOLVERS + + + debMsgStd("LbmFsgrSolver::initParticles",DM_MSG,"Added "<mPartGenProb, 10); if(num != partt->getNumParticles()) return 1; -#endif // ELBEEM_PLUGIN return 0; } -template -void LbmFsgrSolver::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::advanceParticles","Invalid ParticleTracer..."); } + if(mpParticles!=partt) { errMsg("LbmFsgrSolver::advanceParticles","Invalid ParticleTracer..."); } +#define DEL_PART { \ + /*errMsg("PIT","DEL AT "<< __LINE__<<" type:"<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::iterator pit= partt->getParticlesBegin(); pit!= partt->getParticlesEnd(); pit++) { - //errorOut(" pit "<< (*pit).getPos() ); + //errMsg("PIT"," pit "<< (*pit).getPos()<<" status:"<getStart()<<" "<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( (ithis->mSizex-1-cutval)|| + (jthis->mSizey-1-cutval) + //||(kthis->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 + 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...? } - // 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; + ntlVec3Gfx v = p->getVel(); // dampen... + if(mUseTestdata) { + // test rise + //O vz = p->getVel()[2]-0.5*mLevel[mMaxRefine].gravity[2]; - 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++; + 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="<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->advance( vx,vy,vz ); - // fluid particle - } else { - p->setVel( p->getVel() * 0.999 ); // dampen... - p->addToVel( vec2G(mLevel[mMaxRefine].gravity) ); + p->setVel( v ); + //p->setVel( ntlVec3Gfx(vx,vy,vz) ); p->advanceVel(); - //errMsg("NNNPART"," at "<getPos()<<" u="<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="<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(kmSizez-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((kthis->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:"<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:"<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 "<getStatus()&PART_IN) { // IN + if((kthis->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;kkdfDvecX[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) && (kmSizez-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:"<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:"<getStatus() ); + } } -#endif // ELBEEM_PLUGIN + myTime_t parttend = getTime(); + debMsgStd("LbmFsgrSolver::advanceParticles",DM_MSG,"Time for particle update:"<< getTimeString(parttend-parttstart)<<" "<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 void -LbmFsgrSolver::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::printLbmCell(int level, int i, int j, int k, int set) { debugPrintNodeInfo( newcid, set ); delete newcid; } -template void -LbmFsgrSolver::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 CellIdentifierInterface* -LbmFsgrSolver::getFirstCell( ) { +LbmFsgrSolver::getFirstCell( ) { int level = mMaxRefine; #if LBMDIM==3 @@ -434,17 +829,14 @@ LbmFsgrSolver::getFirstCell( ) { return cid; } -template -typename LbmFsgrSolver::stdCellId* -LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { +LbmFsgrSolver::stdCellId* +LbmFsgrSolver::convertBaseCidToStdCid( CellIdentifierInterface* basecid) { //stdCellId *cid = dynamic_cast( basecid ); stdCellId *cid = (stdCellId*)( basecid ); return cid; } -template -void -LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { +void LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); if(cid->getEnd()) return; @@ -467,39 +859,32 @@ LbmFsgrSolver::advanceCell( CellIdentifierInterface* basecid) { //debugOut(" ADa "<x<<","<y<<","<z<<" e"<getEnd(), 10); } -template -bool -LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { +bool LbmFsgrSolver::noEndCell( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return (!cid->getEnd()); } -template -void -LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { +void LbmFsgrSolver::deleteCellIterator( CellIdentifierInterface** cid ) { delete *cid; *cid = NULL; } -template -CellIdentifierInterface* -LbmFsgrSolver::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::getCellAt( ntlVec3Gfx pos ) { newcid->x = x; newcid->y = y; newcid->z = z; - //errMsg("cellAt",D::mName<<" "<mName<<" "<::getCellAt( ntlVec3Gfx pos ) { // INFO functions -template -int -LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { +int LbmFsgrSolver::getCellSet ( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return mLevel[cid->level].setCurr; //return mLevel[cid->level].setOther; } -template -int -LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { +int LbmFsgrSolver::getCellLevel ( CellIdentifierInterface* basecid) { stdCellId *cid = convertBaseCidToStdCid(basecid); return cid->level; } -template -ntlVec3Gfx -LbmFsgrSolver::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 -ntlVec3Gfx -LbmFsgrSolver::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 -LbmFloat -LbmFsgrSolver::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::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 "<x,cid->y,cid->z)<<" = "< -LbmVec -LbmFsgrSolver::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 -LbmFloat -LbmFsgrSolver::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 -LbmFloat -LbmFsgrSolver::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 -LbmFloat -LbmFsgrSolver::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 -CellFlagType -LbmFsgrSolver::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 -LbmFloat -LbmFsgrSolver::getEquilDf( int l ) { - return D::dfEquil[l]; +LbmFloat LbmFsgrSolver::getEquilDf( int l ) { + return this->dfEquil[l]; } -template -int -LbmFsgrSolver::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"<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; ncDfNum; 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"<getCurrentAniFrameTime() ); + return retv; + } + // no cells here...? + //errMsg("DUMPVEL"," at "< void -LbmFsgrSolver::debugDisplay(fluidDispSettings *set){ - //lbmDebugDisplay< LbmFsgrSolver >( set, this ); +LbmFsgrSolver::debugDisplay(int set){ + //lbmDebugDisplay< LbmFsgrSolver >( set, this ); lbmDebugDisplay( set ); } #endif @@ -680,8 +1101,7 @@ LbmFsgrSolver::debugDisplay(fluidDispSettings *set){ #if FSGR_STRICT_DEBUG==1 #define STRICT_EXIT *((int *)0)=0; -template -int LbmFsgrSolver::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"< mMaxRefine){ errMsg("LbmStrict::debLBMGI"," invLev+ l"<::debLBMGI(int level, int ii,int ij,int ik, int is) { return _LBMGI(level, ii,ij,ik, is); }; -template -CellFlagType& LbmFsgrSolver::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 -CellFlagType& LbmFsgrSolver::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"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"<this->cDirNum){ errMsg("LbmStrict"," invD+ l"< -CellFlagType& LbmFsgrSolver::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"<D::cDirNum){ errMsg("LbmStrict"," invD+ l"<this->cDirNum){ errMsg("LbmStrict"," invD+ l"< -int LbmFsgrSolver::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"< mMaxRefine){ errMsg("LbmStrict::debLBMQI"," invLev+ l"<::debLBMQI(int level, int ii,int ij,int ik, int is, int l) { if(is<0){ errMsg("LbmStrict"," invS- l"<1){ errMsg("LbmStrict"," invS+ 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"<mInitDone) && (is!=mLevel[level].setCurr)){ STRICT_EXIT; } // COMPRT debug #endif // COMPRESSGRIDS==1 return _LBMQI(level, ii,ij,ik, is, l); }; -template -LbmFloat& LbmFsgrSolver::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"< -LbmFloat& LbmFsgrSolver::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"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"<this->cDfNum){ errMsg("LbmStrict"," invD+ l"< -LbmFloat& LbmFsgrSolver::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"<D::cDfNum){ errMsg("LbmStrict"," invD+ l"<this->cDfNum){ errMsg("LbmStrict"," invD+ l"< -LbmFloat* LbmFsgrSolver::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 -LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { +LbmFloat& LbmFsgrSolver::debRAC(LbmFloat* s,int l) { if(l<0) { errMsg("LbmStrict"," invD- "<<" l"<dTotalNum){ errMsg("LbmStrict"," invD+ "<<" 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"<::debRAC(LbmFloat* s,int l) { #include "../gui/gui_utilities.h" //! display a single node -template -void LbmFsgrSolver::debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell ) { +void LbmFsgrSolver::debugDisplayNode(int dispset, CellIdentifierInterface* cell ) { //debugOut(" DD: "<getAsString() , 10); ntlVec3Gfx org = this->getCellOrigin( cell ); ntlVec3Gfx halfsize = this->getCellSize( cell ); @@ -796,7 +1206,7 @@ void LbmFsgrSolver::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::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::debugDisplayNode(fluidDispSettings *dispset, CellIdentifi //! debug display function // D has to implement the CellIterator interface -template -void LbmFsgrSolver::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 -void LbmFsgrSolver::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::lbmMarkedCellDisplay() { #endif // LBM_USE_GUI==1 //! display a single node -template -void LbmFsgrSolver::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::debugPrintNodeInfo(CellIdentifierInterface* cell, int for debMsgStd(" ",DM_MSG, "Printing set:"<getDfNum(); l++) { // FIXME ?? + for(int l=0; lgetCellDf(cell,workset,l), 1); } } @@ -1054,24 +1472,9 @@ void LbmFsgrSolver::debugPrintNodeInfo(CellIdentifierInterface* cell, int for if(printMass) { debMsgStd(" ",DM_MSG, " Mss: "<getCellMass(cell,workset), 1); } + // dirty... TODO fixme + debMsgStd(" ",DM_MSG, " Flx: "<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 <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; itotvert; 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; itotvert; 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; itotvert; 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; imvert[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; imvert[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; itotvert; i++) { + VECCOPY( &verts[i*3], dlm->mvert[i].co); + } + *vertices = verts; + + for(i=0; itotface; i++) { + countTris++; + if(mface[i].v4) { countTris++; } + } + *numTriangles = countTris; + tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles"); + countTris = 0; + for(i=0; itotface; 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; itotvert;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; itotvert;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; itotvert;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; itotvert;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 +#include #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<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; atime= 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; atotvert; 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; atotvlak; 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; atotvlak; 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; atotvert; 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; atotvlak; 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; atotpart; 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; avertnodes[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,14 +2442,63 @@ 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; 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)) @@ -426,6 +428,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; aname, 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++; } } @@ -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; ir.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; icurval; + } + } 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); + + // 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 ]; + } - // start writing + 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); + } + fluidsimInitChannel( &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + // time channel is a multiplicator for aniFrameTime + if(channelDomainTime) { + for(i=0; ianimStart; // start at index 1 + if(channelDomainTime) { + for(i=2; i<=allchannelSize; i++) { + timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0]; + } + } else { + for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } + } + + fluidsimInitChannel( &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + if(channelDomainViscosity) { + for(i=0; iipo, 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] ); + } + } + + 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 ); + + channelObjCount++; + + } + } + + // 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; + } + + + // -------------------------------------------------------------------------------------------- + // 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); } - 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; - } - 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); + if(!doExportOnly) { + SDL_Thread *simthr = NULL; - /* 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 ]; - } - 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*/; ir.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; - } - // 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*/; ir.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 - } - 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 ); - } - - 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; - } - - 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; + // 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); - 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; + // defaults for compressibility and adaptive grids + fsset.gstar = domainSettings->gstar; + fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels + fsset.generateParticles = domainSettings->generateParticles; + strcpy( fsset.outputPath, targetFile); - eyex = cam->loc[0]; - eyey = cam->loc[1]; - eyez = cam->loc[2]; - // TODO - place lookat in middle of domain? - } + // domain channels + fsset.channelSizeFrameTime = + fsset.channelSizeViscosity = + fsset.channelSizeGravity = allchannelSize; + fsset.channelFrameTime = channelDomainTime; + fsset.channelViscosity = channelDomainViscosity; + fsset.channelGravity = channelDomainGravity; - fprintf(fileCfg, rayString, - (noFrames+1), targetFile, resx,resy, - eyex, eyey, eyez , - lookatx, lookaty, lookatz, - fov - ); - fprintf(fileCfg, lightString, - eyex, eyey, eyez ); - } + 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) ); + } + } } - /* 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] - ); - } - - - /* 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]; - + // 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; - fprintf(fileCfg, "} // end raytracing\n"); - fclose(fileCfg); + 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); + } - strcpy(targetFile, targetDir); - strcat(targetFile, suffixConfig); - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile); - elbeemDebugOut(debugStrBuffer); + 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; - // perform simulation - { - SDL_Thread *simthr = NULL; + elbeemAddMesh(&fsmesh); + + 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 - - // cleanup sim files - if(getenv(delEnvStr)) { - doDeleteCreatedFiles = atoi(getenv(delEnvStr)); - } - for(i=0; i0) { - //fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]); // debug - BLI_delete(createdFiles[i], 0,0); + } // 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; } - free(createdFiles[i]); - } + //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" ; + + 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" ); + } + + // 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");