diff options
author | Nils Thuerey <nils@thuerey.de> | 2006-05-11 12:09:02 +0400 |
---|---|---|
committer | Nils Thuerey <nils@thuerey.de> | 2006-05-11 12:09:02 +0400 |
commit | 6d935aee423c1dd9dfc16adb3049cf571a038ee3 (patch) | |
tree | 1e30a936590a27b18558c3af3cf031223b4117ad /intern/elbeem | |
parent | 66f0950d34d16d21d2457a7a38eb05b5c70658c4 (diff) |
- New options for mesh voxelization: shell only (also
works for non closed objects), volume ("normal"/old way of
doing it), and a combination of both:
http://www10.informatik.uni-erlangen.de/~sinithue/blender/voltcomp_sm.jpg
- Finally included bjornmose MSVC6 fixes
- Added support for animated meshes, e.g. meshes with
parented skeletons. Is enabled for obstacles with a new button.
A simple example with Bassam's mancandy can be found here:
http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid2_mancandy.mpg
http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid2_mancandy.blend
(Warning - keep meshes as simple as possible, e.g. turn off subsurf
for baking. Export probably shoulb be further optimized.)
- Changed handling of no/free/part slip obstacles, see:
http://www10.informatik.uni-erlangen.de/~sinithue/blender/bndtcomp_sm.jpg
- Removed surface particle option for upcoming release,
needs more testing & tweaking
- Added tracer particles instead (swimming along in the fluid)
- Updated wiki (description of IPOs still missing).
Diffstat (limited to 'intern/elbeem')
37 files changed, 3662 insertions, 2387 deletions
diff --git a/intern/elbeem/extern/LBM_fluidsim.h b/intern/elbeem/extern/LBM_fluidsim.h index c93d1292e47..a6ba16a9599 100644 --- a/intern/elbeem/extern/LBM_fluidsim.h +++ b/intern/elbeem/extern/LBM_fluidsim.h @@ -52,7 +52,7 @@ void fluidsimSettingsFree(struct FluidsimSettings* sb); 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); +void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time); struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh, float* bbstart, float *bbsize); /* create derived mesh for fluid sim objects */ diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h index f0d154c18a4..8eb8a5433b1 100644 --- a/intern/elbeem/extern/elbeem.h +++ b/intern/elbeem/extern/elbeem.h @@ -11,22 +11,28 @@ #define ELBEEM_API_H -/*! blender types for mesh->type */ -//#define OB_FLUIDSIM_DOMAIN 2 -#define OB_FLUIDSIM_FLUID 4 -#define OB_FLUIDSIM_OBSTACLE 8 -#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 +// simulation run callback function type (elbeemSimulationSettings->runsimCallback) +// best use with FLUIDSIM_CBxxx defines below. +// >parameters +// return values: 0=continue, 1=stop, 2=abort +// data pointer: user data pointer from elbeemSimulationSettings->runsimUserData +// status integer: 1=running simulation, 2=new frame saved +// frame integer: if status is 1, contains current frame number +typedef int (*elbeemRunSimulationCallback)(void *data, int status, int frame); +#define FLUIDSIM_CBRET_CONTINUE 0 +#define FLUIDSIM_CBRET_STOP 1 +#define FLUIDSIM_CBRET_ABORT 2 +#define FLUIDSIM_CBSTATUS_STEP 1 +#define FLUIDSIM_CBSTATUS_NEWFRAME 2 // global settings for the simulation typedef struct elbeemSimulationSettings { /* version number */ short version; + /* id number of simulation domain, needed if more than a + * single domain should be simulated */ + short domainId; /* geometrical extent */ float geoStart[3], geoSize[3]; @@ -49,8 +55,10 @@ typedef struct elbeemSimulationSettings { float gstar; /* activate refinement? */ short maxRefine; - /* amount of particles to generate (0=off) */ + /* probability for surface particle generation (0.0=off) */ float generateParticles; + /* amount of tracer particles to generate (0=off) */ + int numTracerParticles; /* store output path, and file prefix for baked fluid surface */ char outputPath[160+80]; @@ -77,17 +85,43 @@ typedef struct elbeemSimulationSettings { /* development variables, testing for upcoming releases...*/ float farFieldSize; + /* callback function to notify calling program of performed simulation steps + * or newly available frame data, if NULL it is ignored */ + elbeemRunSimulationCallback runsimCallback; + /* pointer passed to runsimCallback for user data storage */ + void* runsimUserData; + } elbeemSimulationSettings; +// defines for elbeemMesh->type below +#define OB_FLUIDSIM_FLUID 4 +#define OB_FLUIDSIM_OBSTACLE 8 +#define OB_FLUIDSIM_INFLOW 16 +#define OB_FLUIDSIM_OUTFLOW 32 + +// defines for elbeemMesh->obstacleType below +#define FLUIDSIM_OBSTACLE_NOSLIP 1 +#define FLUIDSIM_OBSTACLE_PARTSLIP 2 +#define FLUIDSIM_OBSTACLE_FREESLIP 3 + +#define OB_VOLUMEINIT_VOLUME 1 +#define OB_VOLUMEINIT_SHELL 2 +#define OB_VOLUMEINIT_BOTH (OB_VOLUMEINIT_SHELL|OB_VOLUMEINIT_VOLUME) + // a single mesh object typedef struct elbeemMesh { /* obstacle,fluid or inflow... */ short type; + /* id of simulation domain it belongs to */ + short parentDomainId; /* vertices */ int numVertices; - float *vertices; // = float[][3]; + float *vertices; // = float[n][3]; + /* animated vertices */ + int channelSizeVertices; + float *channelVertices; // = float[channelSizeVertices* (n*3+1) ]; /* triangles */ int numTriangles; @@ -112,6 +146,8 @@ typedef struct elbeemMesh { /* boundary types and settings */ short obstacleType; float obstaclePartslip; + /* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */ + short volumeInitType; /* name of the mesh, mostly for debugging */ char *name; @@ -123,11 +159,16 @@ typedef struct elbeemMesh { extern "C" { #endif // __cplusplus + // reset elbeemSimulationSettings struct with defaults void elbeemResetSettings(struct elbeemSimulationSettings*); // start fluidsim init (returns !=0 upon failure) -int elbeemInit(struct elbeemSimulationSettings*); +int elbeemInit(void); + +// start fluidsim init (returns !=0 upon failure) +int elbeemAddDomain(struct elbeemSimulationSettings*); + // get failure message during simulation or init // if an error occured (the string is copied into buffer, // max. length = 256 chars ) @@ -142,6 +183,9 @@ int elbeemAddMesh(struct elbeemMesh*); // do the actual simulation int elbeemSimulate(void); +// continue a previously stopped simulation +int elbeemContinueSimulation(void); + // helper functions @@ -185,7 +229,5 @@ double elbeemEstimateMemreq(int res, #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/attributes.cpp b/intern/elbeem/intern/attributes.cpp index abdd931a4bf..f970f6ee5af 100644 --- a/intern/elbeem/intern/attributes.cpp +++ b/intern/elbeem/intern/attributes.cpp @@ -119,7 +119,7 @@ int Attribute::getAsInt() errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); #if ELBEEM_PLUGIN!=1 - gElbeemState = -4; // parse error + setElbeemState( -4 ); // parse error #endif return 0; } @@ -159,7 +159,7 @@ double Attribute::getAsFloat() errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); #if ELBEEM_PLUGIN!=1 - gElbeemState = -4; // parse error + setElbeemState( -4 ); // parse error #endif return 0.0; } @@ -211,7 +211,7 @@ ntlVec3d Attribute::getAsVec3d() errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); #if ELBEEM_PLUGIN!=1 - gElbeemState = -4; // parse error + setElbeemState( -4 ); // parse error #endif return ntlVec3d(0.0); } @@ -267,7 +267,7 @@ void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat) errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ); #if ELBEEM_PLUGIN!=1 - gElbeemState = -4; // parse error + setElbeemState( -4 ); // parse error #endif *mat = ntlMat4Gfx(0.0); return; @@ -349,6 +349,30 @@ AnimChannel<ntlVec3d> Attribute::getChannelVec3d() { return AnimChannel<ntlVec3d>(valVec,timeVec); } +//! get channel as float vector set +AnimChannel<ntlSetVec3f> +Attribute::getChannelSetVec3f() { + vector<double> timeVec; + ntlSetVec3f setv; + vector< ntlSetVec3f > valVec; + + if((!initChannel(3)) || (!mIsChannel)) { + timeVec.push_back( 0.0 ); + setv.mVerts.push_back( vec2F( getAsVec3d() ) ); + valVec.push_back( setv ); + } else { + for(size_t i=0; i<mChannel.size(); i++) { + mValue = mChannel[i]; + ntlVec3f val = vec2F( getAsVec3d() ); + timeVec.push_back( mTimes[i] ); + setv.mVerts.push_back( val ); + } + valVec.push_back( setv ); + valVec.push_back( setv ); + } + + return AnimChannel<ntlSetVec3f>(valVec,timeVec); +} /****************************************************************************** * check if there were unknown params @@ -447,29 +471,50 @@ bool AttributeList::ignoreParameter(string name, string source) { } // read channels -AnimChannel<double> AttributeList::readChannelFloat(string name) { - if(!exists(name)) { return AnimChannel<double>(0.0); } - AnimChannel<double> ret = find(name)->getChannelFloat(); +AnimChannel<int> AttributeList::readChannelInt(string name, int defaultValue, string source, string target, bool needed) { + if(!exists(name)) { return AnimChannel<int>(defaultValue); } + AnimChannel<int> ret = find(name)->getChannelInt(); find(name)->setUsed(true); - channelSimplifyd(ret); + channelSimplifyi(ret); return ret; } -AnimChannel<int> AttributeList::readChannelInt(string name) { - if(!exists(name)) { return AnimChannel<int>(0); } - AnimChannel<int> ret = find(name)->getChannelInt(); +AnimChannel<double> AttributeList::readChannelFloat(string name, double defaultValue, string source, string target, bool needed ) { + if(!exists(name)) { return AnimChannel<double>(defaultValue); } + AnimChannel<double> ret = find(name)->getChannelFloat(); find(name)->setUsed(true); - channelSimplifyi(ret); + channelSimplifyd(ret); return ret; } -AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name) { - if(!exists(name)) { return AnimChannel<ntlVec3d>(0.0); } +AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name, ntlVec3d defaultValue, string source, string target, bool needed ) { + if(!exists(name)) { return AnimChannel<ntlVec3d>(defaultValue); } AnimChannel<ntlVec3d> ret = find(name)->getChannelVec3d(); find(name)->setUsed(true); channelSimplifyVd(ret); return ret; } -AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name) { - if(!exists(name)) { return AnimChannel<ntlVec3f>(0.0); } +AnimChannel<ntlSetVec3f> AttributeList::readChannelSetVec3f(string name, ntlSetVec3f defaultValue, string source, string target, bool needed) { + if(!exists(name)) { return AnimChannel<ntlSetVec3f>(defaultValue); } + AnimChannel<ntlSetVec3f> ret = find(name)->getChannelSetVec3f(); + find(name)->setUsed(true); + //channelSimplifyVf(ret); + return ret; +} +AnimChannel<float> AttributeList::readChannelSinglePrecFloat(string name, float defaultValue, string source, string target, bool needed ) { + if(!exists(name)) { return AnimChannel<float>(defaultValue); } + AnimChannel<double> convert = find(name)->getChannelFloat(); + find(name)->setUsed(true); + channelSimplifyd(convert); + // convert to float vals + vector<float> vals; + for(size_t i=0; i<convert.accessValues().size(); i++) { + vals.push_back( (float)(convert.accessValues()[i]) ); + } + vector<double> times = convert.accessTimes(); + AnimChannel<float> ret(vals, times); + return ret; +} +AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name, ntlVec3f defaultValue, string source, string target, bool needed) { + if(!exists(name)) { return AnimChannel<ntlVec3f>(defaultValue); } AnimChannel<ntlVec3d> convert = find(name)->getChannelVec3d(); // convert to float @@ -672,6 +717,7 @@ bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel) { return channelSimplifyVecT<ntlVec3d>(channel); } +//! debug function, prints channel as string template<class Scalar> string AnimChannel<Scalar>::printChannel() { std::ostringstream ostr; @@ -684,5 +730,65 @@ string AnimChannel<Scalar>::printChannel() { return ostr.str(); } // */ +//! debug function, prints to stdout if DEBUG_CHANNELS flag is enabled, used in constructors +template<class Scalar> +void AnimChannel<Scalar>::debugPrintChannel() { + if(DEBUG_CHANNELS) { errMsg("channelCons"," : " << this->printChannel() ); } +} + + +ntlSetVec3f::ntlSetVec3f(double v ) { + mVerts.clear(); + mVerts.push_back( ntlVec3f(v) ); +} +const ntlSetVec3f& +ntlSetVec3f::operator=(double v ) { + mVerts.clear(); + mVerts.push_back( ntlVec3f(v) ); + return *this; +} + +std::ostream& operator<<( std::ostream& os, const ntlSetVec3f& vs ) { + os<< "{"; + for(int j=0;j<(int)vs.mVerts.size();j++) os<<vs.mVerts[j]; + os<< "}"; + return os; +} + +ntlSetVec3f& +ntlSetVec3f::operator+=( double v ) +{ + for(int j=0;j<(int)(mVerts.size()) ;j++) { + mVerts[j] += v; + } + return *this; +} + +ntlSetVec3f& +ntlSetVec3f::operator+=( const ntlSetVec3f &v ) +{ + for(int j=0;j<(int)MIN(mVerts.size(),v.mVerts.size()) ;j++) { + mVerts[j] += v.mVerts[j]; + } + return *this; +} + +ntlSetVec3f& +ntlSetVec3f::operator*=( double v ) +{ + for(int j=0;j<(int)(mVerts.size()) ;j++) { + mVerts[j] *= v; + } + return *this; +} + +ntlSetVec3f& +ntlSetVec3f::operator*=( const ntlSetVec3f &v ) +{ + for(int j=0;j<(int)MIN(mVerts.size(),v.mVerts.size()) ;j++) { + mVerts[j] *= v.mVerts[j]; + } + return *this; +} diff --git a/intern/elbeem/intern/attributes.h b/intern/elbeem/intern/attributes.h index 730e136f962..20e5341d5fc 100644 --- a/intern/elbeem/intern/attributes.h +++ b/intern/elbeem/intern/attributes.h @@ -12,6 +12,9 @@ #include "utilities.h" template<class T> class ntlMatrix4x4; +class ntlSetVec3f; +std::ostream& operator<<( std::ostream& os, const ntlSetVec3f& i ); + //! An animated attribute channel @@ -21,15 +24,15 @@ class AnimChannel public: // default constructor AnimChannel() : - mValue(), mTimes() { mInited = false; } + mValue(), mTimes() { mInited = false; debugPrintChannel(); } // null init constructor AnimChannel(Scalar null) : - mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; mInited = true; } + mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; mInited = true; debugPrintChannel(); } // proper init - AnimChannel(vector<Scalar> v, vector<double> t) : - mValue(v), mTimes(t) { mInited = true; } + AnimChannel(vector<Scalar> &v, vector<double> &t) : + mValue(v), mTimes(t) { mInited = true; debugPrintChannel(); } // desctructor, nothing to do ~AnimChannel() { }; @@ -45,7 +48,14 @@ class AnimChannel // interpolate double d = mTimes[i+1]-mTimes[i]; double f = (t-mTimes[i])/d; - return (Scalar)(mValue[i] * (1.0-f) + mValue[i+1] * f); + //return (Scalar)(mValue[i] * (1.0-f) + mValue[i+1] * f); + Scalar ret,tmp; + ret = mValue[i]; + ret *= 1.-f; + tmp = mValue[i+1]; + tmp *= f; + ret += tmp; + return ret; } } // whats this...? @@ -77,6 +87,8 @@ class AnimChannel //! debug function, prints channel as string string printChannel(); + //! debug function, prints to stdout if DEBUG_CHANNELS flag is enabled, used in constructors + void debugPrintChannel(); //! valid init? bool isInited() { return mInited; } @@ -145,6 +157,8 @@ class Attribute AnimChannel<double> getChannelFloat(); //! get channel as double vector AnimChannel<ntlVec3d> getChannelVec3d(); + //! get channel as float vector set + AnimChannel<ntlSetVec3f> getChannelSetVec3f(); //! get the concatenated string of all value string string getCompleteString(); @@ -181,6 +195,22 @@ class Attribute }; +// helper class (not templated) for animated meshes +class ntlSetVec3f { + public: + ntlSetVec3f(): mVerts() {}; + ntlSetVec3f(double v); + ntlSetVec3f(vector<ntlVec3f> &v) { mVerts = v; }; + + const ntlSetVec3f& operator=(double v ); + ntlSetVec3f& operator+=( double v ); + ntlSetVec3f& operator+=( const ntlSetVec3f &v ); + ntlSetVec3f& operator*=( double v ); + ntlSetVec3f& operator*=( const ntlSetVec3f &v ); + + vector<ntlVec3f> mVerts; +}; + //! The list of configuration attributes class AttributeList { @@ -230,10 +260,13 @@ class AttributeList ntlVec3d readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed); void readMat4Gfx(string name, ntlMatrix4x4<gfxReal> defaultValue, string source,string target, bool needed, ntlMatrix4x4<gfxReal> *mat); //! read attributes channels (attribute should be inited before) - AnimChannel<int> readChannelInt(string name); - AnimChannel<double> readChannelFloat(string name); - AnimChannel<ntlVec3d> readChannelVec3d(string name); - AnimChannel<ntlVec3f> readChannelVec3f(string name); + AnimChannel<int> readChannelInt( string name, int defaultValue=0, string source=string("src"), string target=string("dst"), bool needed=false ); + AnimChannel<double> readChannelFloat( string name, double defaultValue=0, string source=string("src"), string target=string("dst"), bool needed=false ); + AnimChannel<ntlVec3d> readChannelVec3d( string name, ntlVec3d defaultValue=ntlVec3d(0.), string source=string("src"), string target=string("dst"), bool needed=false ); + AnimChannel<ntlSetVec3f> readChannelSetVec3f(string name, ntlSetVec3f defaultValue=ntlSetVec3f(0.), string source=string("src"), string target=string("dst"), bool needed=false ); + // channels with conversion + AnimChannel<ntlVec3f> readChannelVec3f( string name, ntlVec3f defaultValue=ntlVec3f(0.), string source=string("src"), string target=string("dst"), bool needed=false ); + AnimChannel<float> readChannelSinglePrecFloat( string name, float defaultValue=0., string source=string("src"), string target=string("dst"), bool needed=false ); //! set that a parameter can be given, and will be ignored... bool ignoreParameter(string name, string source); diff --git a/intern/elbeem/intern/elbeem.cpp b/intern/elbeem/intern/elbeem.cpp index daee5f831d6..bd96b9fce6a 100644 --- a/intern/elbeem/intern/elbeem.cpp +++ b/intern/elbeem/intern/elbeem.cpp @@ -36,7 +36,8 @@ ntlWorld *gpWorld = NULL; extern "C" void elbeemResetSettings(elbeemSimulationSettings *set) { if(!set) return; - set->version = 2; + set->version = 3; + set->domainId = 0; 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; @@ -52,7 +53,8 @@ void elbeemResetSettings(elbeemSimulationSettings *set) { set->noOfFrames = 10; set->gstar = 0.005; set->maxRefine = -1; - set->generateParticles = 1.0; + set->generateParticles = 0.0; + set->numTracerParticles = 0; strcpy(set->outputPath,"./elbeemdata_"); set->channelSizeFrameTime=0; @@ -68,6 +70,8 @@ void elbeemResetSettings(elbeemSimulationSettings *set) { set->surfaceSmoothing = 1.; set->farFieldSize = 0.; + set->runsimCallback = NULL; + set->runsimUserData = NULL; // init identity for(int i=0; i<16; i++) set->surfaceTrafo[i] = 0.0; @@ -76,24 +80,35 @@ void elbeemResetSettings(elbeemSimulationSettings *set) { // start fluidsim init extern "C" -int elbeemInit(elbeemSimulationSettings *settings) { - gElbeemState = SIMWORLD_INVALID; - strcpy(gElbeemErrorString,"[none]"); +int elbeemInit() { + setElbeemState( SIMWORLD_INITIALIZING ); + setElbeemErrorString("[none]"); elbeemCheckDebugEnv(); debMsgStd("performElbeemSimulation",DM_NOTIFY,"El'Beem Simulation Init Start as Plugin, debugLevel:"<<gDebugLevel<<" ...\n", 2); // create world object with initial settings - ntlBlenderDumper *elbeem = new ntlBlenderDumper(settings); + ntlBlenderDumper *elbeem = new ntlBlenderDumper(); gpWorld = elbeem; return 0; } +// start fluidsim init +extern "C" +int elbeemAddDomain(elbeemSimulationSettings *settings) { + // has to be inited... + if((getElbeemState() == SIMWORLD_INVALID) && (!gpWorld)) { elbeemInit(); } + if(getElbeemState() != SIMWORLD_INITIALIZING) { errFatal("elbeemAddDomain","Unable to init simulation world",SIMWORLD_INITERROR); } + // create domain with given settings + gpWorld->addDomain(settings); + return 0; +} + // error message access extern "C" void elbeemGetErrorString(char *buffer) { if(!buffer) return; - strncpy(buffer,gElbeemErrorString,256); + strncpy(buffer,getElbeemErrorString(),256); } // reset elbeemMesh struct with zeroes @@ -105,6 +120,7 @@ void elbeemResetMesh(elbeemMesh *mesh) { mesh->vertices = NULL; mesh->numTriangles = 0; mesh->triangles = NULL; + mesh->channelSizeTranslation = 0; mesh->channelTranslation = NULL; mesh->channelSizeRotation = 0; @@ -116,15 +132,24 @@ void elbeemResetMesh(elbeemMesh *mesh) { mesh->channelSizeInitialVel = 0; mesh->channelInitialVel = NULL; mesh->localInivelCoords = 0; + mesh->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP; + mesh->volumeInitType= OB_VOLUMEINIT_VOLUME; mesh->obstaclePartslip= 0.; + + mesh->channelSizeVertices = 0; + mesh->channelVertices = NULL; + mesh->name = "[unnamed]"; } +int globalMeshCounter = 1; // add mesh as fluidsim object extern "C" int elbeemAddMesh(elbeemMesh *mesh) { int initType = -1; + if(getElbeemState() != SIMWORLD_INITIALIZING) { errFatal("elbeemAddMesh","World and domain not initialized, call elbeemInit and elbeemAddDomain before...", SIMWORLD_INITERROR); } + switch(mesh->type) { case OB_FLUIDSIM_OBSTACLE: if (mesh->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) initType = FGI_BNDPART; @@ -140,13 +165,22 @@ int elbeemAddMesh(elbeemMesh *mesh) { ntlGeometryObjModel *obj = new ntlGeometryObjModel( ); gpWorld->getRenderGlobals()->getSimScene()->addGeoClass( obj ); - obj->initModel(mesh->numVertices, mesh->vertices, mesh->numTriangles, mesh->triangles); - if(mesh->name) obj->setName(std::string(mesh->name)); - else obj->setName(std::string("[unnamed]")); - obj->setGeoInitId(1); + obj->initModel( + mesh->numVertices, mesh->vertices, mesh->numTriangles, mesh->triangles, + mesh->channelSizeVertices, mesh->channelVertices ); + if(mesh->name) obj->setName(string(mesh->name)); + else { + char meshname[100]; + snprintf(meshname,100,"mesh%04d",globalMeshCounter); + obj->setName(string(meshname)); + } + globalMeshCounter++; + obj->setGeoInitId( mesh->parentDomainId+1 ); obj->setGeoInitIntersect(true); obj->setGeoInitType(initType); obj->setGeoPartSlipValue(mesh->obstaclePartslip); + if((mesh->volumeInitType<VOLUMEINIT_VOLUME)||(mesh->volumeInitType>VOLUMEINIT_BOTH)) mesh->volumeInitType = VOLUMEINIT_VOLUME; + obj->setVolumeInit(mesh->volumeInitType); // use channel instead, obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelocity[0], mesh->iniVelocity[1], mesh->iniVelocity[2]) ); obj->initChannels( mesh->channelSizeTranslation, mesh->channelTranslation, @@ -167,17 +201,19 @@ int elbeemSimulate(void) { if(!gpWorld) return 1; gpWorld->finishWorldInit(); - - if(SIMWORLD_OK()) { - gElbeemState = SIMWORLD_INITED; + if( isSimworldOk() ) { myTime_t timestart = getTime(); gpWorld->renderAnimation(); myTime_t timeend = getTime(); - debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 ); - // ok, we're done... - delete gpWorld; - gpWorld = NULL; + if(getElbeemState() != SIMWORLD_STOP) { + // ok, we're done... + delete gpWorld; + gpWorld = NULL; + debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 ); + } else { + debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation stopped, time so far: "<<getTimeString(timeend-timestart)<<".", 2 ); + } return 0; } @@ -186,6 +222,32 @@ int elbeemSimulate(void) { } +// continue a previously stopped simulation +extern "C" +int elbeemContinueSimulation(void) { + + if(getElbeemState() != SIMWORLD_STOP) { + errMsg("elbeemContinueSimulation","No running simulation found! Aborting..."); + if(gpWorld) delete gpWorld; + return 1; + } + + myTime_t timestart = getTime(); + gpWorld->renderAnimation(); + myTime_t timeend = getTime(); + + if(getElbeemState() != SIMWORLD_STOP) { + // ok, we're done... + delete gpWorld; + gpWorld = NULL; + debMsgStd("elbeemContinueSimulation",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 ); + } else { + debMsgStd("elbeemContinueSimulation",DM_NOTIFY, "El'Beem simulation stopped, time so far: "<<getTimeString(timeend-timestart)<<".", 2 ); + } + return 0; +} + + // global vector to flag values to remove vector<int> gKeepVal; diff --git a/intern/elbeem/intern/elbeem.h b/intern/elbeem/intern/elbeem.h index f0d154c18a4..8eb8a5433b1 100644 --- a/intern/elbeem/intern/elbeem.h +++ b/intern/elbeem/intern/elbeem.h @@ -11,22 +11,28 @@ #define ELBEEM_API_H -/*! blender types for mesh->type */ -//#define OB_FLUIDSIM_DOMAIN 2 -#define OB_FLUIDSIM_FLUID 4 -#define OB_FLUIDSIM_OBSTACLE 8 -#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 +// simulation run callback function type (elbeemSimulationSettings->runsimCallback) +// best use with FLUIDSIM_CBxxx defines below. +// >parameters +// return values: 0=continue, 1=stop, 2=abort +// data pointer: user data pointer from elbeemSimulationSettings->runsimUserData +// status integer: 1=running simulation, 2=new frame saved +// frame integer: if status is 1, contains current frame number +typedef int (*elbeemRunSimulationCallback)(void *data, int status, int frame); +#define FLUIDSIM_CBRET_CONTINUE 0 +#define FLUIDSIM_CBRET_STOP 1 +#define FLUIDSIM_CBRET_ABORT 2 +#define FLUIDSIM_CBSTATUS_STEP 1 +#define FLUIDSIM_CBSTATUS_NEWFRAME 2 // global settings for the simulation typedef struct elbeemSimulationSettings { /* version number */ short version; + /* id number of simulation domain, needed if more than a + * single domain should be simulated */ + short domainId; /* geometrical extent */ float geoStart[3], geoSize[3]; @@ -49,8 +55,10 @@ typedef struct elbeemSimulationSettings { float gstar; /* activate refinement? */ short maxRefine; - /* amount of particles to generate (0=off) */ + /* probability for surface particle generation (0.0=off) */ float generateParticles; + /* amount of tracer particles to generate (0=off) */ + int numTracerParticles; /* store output path, and file prefix for baked fluid surface */ char outputPath[160+80]; @@ -77,17 +85,43 @@ typedef struct elbeemSimulationSettings { /* development variables, testing for upcoming releases...*/ float farFieldSize; + /* callback function to notify calling program of performed simulation steps + * or newly available frame data, if NULL it is ignored */ + elbeemRunSimulationCallback runsimCallback; + /* pointer passed to runsimCallback for user data storage */ + void* runsimUserData; + } elbeemSimulationSettings; +// defines for elbeemMesh->type below +#define OB_FLUIDSIM_FLUID 4 +#define OB_FLUIDSIM_OBSTACLE 8 +#define OB_FLUIDSIM_INFLOW 16 +#define OB_FLUIDSIM_OUTFLOW 32 + +// defines for elbeemMesh->obstacleType below +#define FLUIDSIM_OBSTACLE_NOSLIP 1 +#define FLUIDSIM_OBSTACLE_PARTSLIP 2 +#define FLUIDSIM_OBSTACLE_FREESLIP 3 + +#define OB_VOLUMEINIT_VOLUME 1 +#define OB_VOLUMEINIT_SHELL 2 +#define OB_VOLUMEINIT_BOTH (OB_VOLUMEINIT_SHELL|OB_VOLUMEINIT_VOLUME) + // a single mesh object typedef struct elbeemMesh { /* obstacle,fluid or inflow... */ short type; + /* id of simulation domain it belongs to */ + short parentDomainId; /* vertices */ int numVertices; - float *vertices; // = float[][3]; + float *vertices; // = float[n][3]; + /* animated vertices */ + int channelSizeVertices; + float *channelVertices; // = float[channelSizeVertices* (n*3+1) ]; /* triangles */ int numTriangles; @@ -112,6 +146,8 @@ typedef struct elbeemMesh { /* boundary types and settings */ short obstacleType; float obstaclePartslip; + /* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */ + short volumeInitType; /* name of the mesh, mostly for debugging */ char *name; @@ -123,11 +159,16 @@ typedef struct elbeemMesh { extern "C" { #endif // __cplusplus + // reset elbeemSimulationSettings struct with defaults void elbeemResetSettings(struct elbeemSimulationSettings*); // start fluidsim init (returns !=0 upon failure) -int elbeemInit(struct elbeemSimulationSettings*); +int elbeemInit(void); + +// start fluidsim init (returns !=0 upon failure) +int elbeemAddDomain(struct elbeemSimulationSettings*); + // get failure message during simulation or init // if an error occured (the string is copied into buffer, // max. length = 256 chars ) @@ -142,6 +183,9 @@ int elbeemAddMesh(struct elbeemMesh*); // do the actual simulation int elbeemSimulate(void); +// continue a previously stopped simulation +int elbeemContinueSimulation(void); + // helper functions @@ -185,7 +229,5 @@ double elbeemEstimateMemreq(int res, #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/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 07bc6b7c855..373a6f74761 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -303,7 +303,7 @@ void IsoSurface::triangulate( void ) /****************************************************************************** * Get triangles for rendering *****************************************************************************/ -void IsoSurface::getTriangles( vector<ntlTriangle> *triangles, +void IsoSurface::getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) { @@ -311,6 +311,7 @@ void IsoSurface::getTriangles( vector<ntlTriangle> *triangles, debugOut("IsoSurface::getTriangles warning: Not initialized! ", 10); return; } + t = 0.; //return; // DEBUG /* triangulate field */ @@ -355,12 +356,6 @@ void IsoSurface::getTriangles( vector<ntlTriangle> *triangles, 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(); diff --git a/intern/elbeem/intern/isosurface.h b/intern/elbeem/intern/isosurface.h index 5e5115ef236..d1ff1529069 100644 --- a/intern/elbeem/intern/isosurface.h +++ b/intern/elbeem/intern/isosurface.h @@ -123,7 +123,7 @@ class IsoSurface : inline float getSmoothNormals() { return mSmoothNormals; } // geometry object functions - virtual void getTriangles( vector<ntlTriangle> *triangles, + virtual void getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ); diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp index ecd1967c877..4468dda750f 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.cpp +++ b/intern/elbeem/intern/ntl_blenderdumper.cpp @@ -24,23 +24,14 @@ /****************************************************************************** * Constructor *****************************************************************************/ -ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) : - ntlWorld(filename,commandlineMode), - mpTrafo(NULL) +ntlBlenderDumper::ntlBlenderDumper() : ntlWorld() { - ntlRenderGlobals *glob = mpGlob; - AttributeList *pAttrs = glob->getBlenderAttributes(); - mpTrafo = new ntlMat4Gfx(0.0); - mpTrafo->initId(); - pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false, mpTrafo ); + // same as normal constructor here } -ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) : - ntlWorld(settings), mpTrafo(NULL) +ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) : + ntlWorld(filename,commandlineMode) { - // same as normal constructor here - mpTrafo = new ntlMat4Gfx(0.0); - mpTrafo->initArrayCheck(settings->surfaceTrafo); - //errMsg("ntlBlenderDumper","mpTrafo inited: "<<(*mpTrafo) ); + // init world } @@ -50,7 +41,6 @@ ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) : *****************************************************************************/ ntlBlenderDumper::~ntlBlenderDumper() { - delete mpTrafo; debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10); } @@ -67,16 +57,6 @@ int ntlBlenderDumper::renderScene( void ) debugOut = false; #endif // ELBEEM_PLUGIN==1 - // output path - /*std::ostringstream ecrpath(""); - ecrpath << "/tmp/ecr_" << getpid() <<"/"; - // make sure the dir exists - std::ostringstream ecrpath_create(""); - ecrpath_create << "mkdir " << ecrpath.str(); - system( ecrpath_create.str().c_str() ); - // */ - - vector<string> hideObjs; // geom shaders to hide vector<string> gmName; // gm names vector<string> gmMat; // materials for gm int numGMs = 0; // no. of .obj models created @@ -91,7 +71,6 @@ int ntlBlenderDumper::renderScene( void ) vector<ntlTriangle> Triangles; vector<ntlVec3Gfx> Vertices; vector<ntlVec3Gfx> VertNormals; - //errMsg("ntlBlenderDumper","mpTrafo : "<<(*mpTrafo) ); /* init geometry array, first all standard objects */ int idCnt = 0; // give IDs to objects @@ -106,14 +85,16 @@ int ntlBlenderDumper::renderScene( void ) } if(tid & GEOCLASSTID_SHADER) { ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter); - hideObjs.push_back( (*iter)->getName() ); - geoshad->notifyShaderOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,glob->getOutFilename()); + std::string outname = geoshad->getOutFilename(); + if(outname.length()<1) outname = mpGlob->getOutFilename(); + geoshad->notifyShaderOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname); + for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin(); siter != geoshad->getObjectsEnd(); siter++) { if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8); - (*siter)->notifyOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,glob->getOutFilename(), this->mSimulationTime); + (*siter)->notifyOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname, this->mSimulationTime); bool doDump = false; bool isPreview = false; // only dump final&preview surface meshes @@ -130,8 +111,7 @@ int ntlBlenderDumper::renderScene( void ) Vertices.clear(); VertNormals.clear(); (*siter)->initialize( mpGlob ); - //int vstart = mVertNormals.size()-1; - (*siter)->getTriangles(&Triangles, &Vertices, &VertNormals, idCnt); + (*siter)->getTriangles(this->mSimulationTime, &Triangles, &Vertices, &VertNormals, idCnt); idCnt ++; @@ -139,8 +119,8 @@ int ntlBlenderDumper::renderScene( void ) // dump to binary file std::ostringstream boutfilename(""); - //boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj"; - boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr; + //boutfilename << ecrpath.str() << outname <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj"; + boutfilename << outname <<"_"<< (*siter)->getName() <<"_" << nrStr; if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName() <<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<< " to "<<boutfilename.str() , 7); @@ -164,7 +144,6 @@ int ntlBlenderDumper::renderScene( void ) // returns smoothed velocity, scaled by frame time ntlVec3Gfx v = lbm->getVelocityAt( Vertices[i][0], Vertices[i][1], Vertices[i][2] ); // translation not necessary, test rotation & scaling? - //? v = (*mpTrafo) * v; for(int j=0; j<3; j++) { float vertp = v[j]; //if(i<20) errMsg("ntlBlenderDumper","DUMP_VEL final "<<i<<" = "<<v); @@ -182,10 +161,18 @@ int ntlBlenderDumper::renderScene( void ) errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' "); return 1; } - // transform into source space - for(size_t i=0; i<Vertices.size(); i++) { - Vertices[i] = (*mpTrafo) * Vertices[i]; + //! current transform matrix + ntlMatrix4x4<gfxReal> *trafo; + trafo = lbm->getDomainTrafo(); + if(trafo) { + //trafo->initArrayCheck(ettings->surfaceTrafo); + //errMsg("ntlBlenderDumper","mpTrafo : "<<(*mpTrafo) ); + // transform into source space + for(size_t i=0; i<Vertices.size(); i++) { + Vertices[i] = (*trafo) * Vertices[i]; + } } + // write to file int numVerts; if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; } diff --git a/intern/elbeem/intern/ntl_blenderdumper.h b/intern/elbeem/intern/ntl_blenderdumper.h index 64f9f81021d..57f155fc5ff 100644 --- a/intern/elbeem/intern/ntl_blenderdumper.h +++ b/intern/elbeem/intern/ntl_blenderdumper.h @@ -9,15 +9,13 @@ #ifndef NTL_BLENDERDUMPER_H #include "ntl_world.h" -template<class Scalar> class ntlMatrix4x4; - class ntlBlenderDumper : public ntlWorld { public: /*! Constructor */ + ntlBlenderDumper(); ntlBlenderDumper(string filename, bool commandlineMode); - ntlBlenderDumper(elbeemSimulationSettings *); /*! Destructor */ virtual ~ntlBlenderDumper( void ); @@ -26,8 +24,6 @@ public: protected: - //! transform matrix - ntlMatrix4x4<gfxReal> *mpTrafo; }; #define NTL_BLENDERDUMPER_H diff --git a/intern/elbeem/intern/ntl_geometryclass.h b/intern/elbeem/intern/ntl_geometryclass.h index bcc5a32fb58..0b7a4e98388 100644 --- a/intern/elbeem/intern/ntl_geometryclass.h +++ b/intern/elbeem/intern/ntl_geometryclass.h @@ -28,8 +28,7 @@ class ntlGeometryClass //! Default constructor inline ntlGeometryClass() : mVisible( 1 ), mName( "[ObjNameUndef]" ), - mObjectId(-1), - mpAttrs( NULL ) + mObjectId(-1), mpAttrs( NULL ), mGeoInitId(-1) { mpAttrs = new AttributeList("objAttrs"); }; @@ -76,6 +75,11 @@ class ntlGeometryClass /*! GUI - notify object that mouse was clicked at last pos */ virtual void setMouseClick() { /* do nothing by default */ } + /*! Returns the geo init id */ + inline void setGeoInitId(int set) { mGeoInitId=set; } + /*! Returns the geo init id */ + inline int getGeoInitId() const { return mGeoInitId; } + protected: /*! Object visible on/off */ @@ -90,6 +94,10 @@ class ntlGeometryClass /*! configuration attributes */ AttributeList *mpAttrs; + /* fluid init data */ + /*! id of fluid init (is used in solver initialization), additional data stored only for objects */ + int mGeoInitId; + private: }; diff --git a/intern/elbeem/intern/ntl_geometrymodel.cpp b/intern/elbeem/intern/ntl_geometrymodel.cpp index 3c2e05a8c36..598abbddfac 100644 --- a/intern/elbeem/intern/ntl_geometrymodel.cpp +++ b/intern/elbeem/intern/ntl_geometrymodel.cpp @@ -26,7 +26,11 @@ ntlGeometryObjModel::ntlGeometryObjModel( void ) : ntlGeometryObject(), mvStart( 0.0 ), mvEnd( 1.0 ), mLoaded( false ), - mTriangles(), mVertices(), mNormals() + mTriangles(), mVertices(), mNormals(), + mcAniVerts(), mcAniNorms(), + mcAniTimes(), mAniTimeScale(1.), mAniTimeOffset(0.), + mvCPSStart(-10000.), mvCPSEnd(10000.), + mCPSFilename(""), mCPSWidth(0.1), mCPSTimestep(1.) { } @@ -41,6 +45,13 @@ ntlGeometryObjModel::~ntlGeometryObjModel() } +/*! is the mesh animated? */ +bool ntlGeometryObjModel::getMeshAnimated() { + const bool ret = (mcAniVerts.getSize()>1); + //errMsg("getMeshAnimated","ret="<<ret<<", size="<<mcAniVerts.getSize() ); + return ret; +} + /*****************************************************************************/ /* Init attributes etc. of this object */ /*****************************************************************************/ @@ -57,14 +68,14 @@ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) mFilename = mpAttrs->readString("filename", mFilename,"ntlGeometryObjModel", "mFilename", true); if(mFilename == "") { - errMsg("ntlGeometryObjModel::getTriangles","Filename not given!"); + errMsg("ntlGeometryObjModel::initialize","Filename not given!"); return; } const char *suffix = strrchr(mFilename.c_str(), '.'); if (suffix) { if (!strncasecmp(suffix, ".obj", 4)) { - errMsg("ntlGeometryObjModel::getTriangles",".obj files not supported!"); + errMsg("ntlGeometryObjModel::initialize",".obj files not supported!"); return; } else if (!strncasecmp(suffix, ".gz", 3)) { //mType = 1; // assume its .bobj.gz @@ -73,18 +84,33 @@ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) } } + if(getAttributeList()->exists("ani_times") || (!mcAniTimes.isInited()) ) { + mcAniTimes = mpAttrs->readChannelFloat("ani_times"); + } + mAniTimeScale = mpAttrs->readFloat("ani_timescale", mAniTimeScale,"ntlGeometryObjModel", "mAniTimeScale", false); + mAniTimeOffset = mpAttrs->readFloat("ani_timeoffset", mAniTimeOffset,"ntlGeometryObjModel", "mAniTimeOffset", false); + + mCPSWidth = mpAttrs->readFloat("cps_width", mCPSWidth,"ntlGeometryObjModel", "mCPSWidth", false); + mCPSTimestep = mpAttrs->readFloat("cps_timestep", mCPSTimestep,"ntlGeometryObjModel", "mCPSTimestep", false); + mvCPSStart = vec2G( mpAttrs->readVec3d("cps_start", vec2D(mvCPSStart),"ntlGeometryObjModel", "mvCPSStart", false)); + mvCPSEnd = vec2G( mpAttrs->readVec3d("cps_end", vec2D(mvCPSEnd),"ntlGeometryObjModel", "mvCPSEnd", false)); + // continue with standard obj if(loadBobjModel(mFilename)==0) mLoaded=1; if(!mLoaded) { debMsgStd("ntlGeometryObjModel",DM_WARNING,"Unable to load object file '"<<mFilename<<"' !", 0); } + if(getMeshAnimated()) { + this->mIsAnimated = true; + } } /****************************************************************************** * init model from given vertex and triangle arrays *****************************************************************************/ -int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles) +int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles, + int channelSize, float *channelVertices) { mVertices.clear(); mVertices.resize( numVertices ); @@ -96,10 +122,57 @@ int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTria mTriangles.clear(); mTriangles.resize( 3*numTriangles ); + int triangleErrs=0; for(int i=0; i<numTriangles; i++) { - mTriangles[3*i+0] = triangles[i*3+0]; - mTriangles[3*i+1] = triangles[i*3+1]; - mTriangles[3*i+2] = triangles[i*3+2]; + for(int j=0;j<3;j++) { + mTriangles[3*i+j] = triangles[i*3+j]; + if(mTriangles[3*i+j]<0) { mTriangles[3*i+j]=0; triangleErrs++; } + if(mTriangles[3*i+j]>=numVertices) { mTriangles[3*i+j]=0; triangleErrs++; } + } + } + if(triangleErrs>0) { + errMsg("ntlGeometryObjModel::initModel","Triangle errors occurred ("<<triangleErrs<<")!"); + } + + //fprintf(stderr,"initModel DEBUG %d \n",channelSize); + debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Csize:"<<channelSize<<", Cvert:"<<(long)(channelVertices) ,10); + if(channelVertices && (channelSize>0)) { + vector<ntlSetVec3f> aniverts; + vector<ntlSetVec3f> aninorms; + vector<double> anitimes; + aniverts.clear(); + aninorms.clear(); + anitimes.clear(); + for(int frame=0; frame<channelSize; frame++) { + ntlSetVec3f averts; averts.mVerts.clear(); + ntlSetVec3f anorms; averts.mVerts.clear(); + int setsize = (3*numVertices+1); + + ntlVec3Gfx p(0.),n(1.); + for(int i=0; i<numVertices; i++) { + for(int j=0; j<3; j++) p[j] = channelVertices[frame*setsize+ 3*i +j]; + averts.mVerts.push_back(p); + anorms.mVerts.push_back(p); + //debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Frame:"<<frame<<",i:"<<i<<" "<<p,10); + } + if( ((int)averts.mVerts.size()==numVertices) && + ((int)anorms.mVerts.size()==numVertices) ) { + aniverts.push_back(averts); + aninorms.push_back(anorms); + double time = (double)channelVertices[frame*setsize+ setsize-1]; + anitimes.push_back(time); + } else { + errMsg("ntlGeometryObjModel::initModel","Invalid mesh, obj="<<this->getName()<<" frame="<<frame<<" verts="<<averts.mVerts.size()<<"/"<<numVertices<<". Skipping..."); + } + //debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Frame:"<<frame<<" at t="<<time,10); + } + + mcAniVerts = AnimChannel<ntlSetVec3f>(aniverts,anitimes); + mcAniNorms = AnimChannel<ntlSetVec3f>(aninorms,anitimes); + debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Ani sets inited: "<< mcAniVerts.accessValues().size() <<","<<mcAniNorms.accessValues().size() <<" ", 1 ); + } + if(getMeshAnimated()) { + this->mIsAnimated = true; } // inited, no need to parse attribs etc. @@ -107,6 +180,48 @@ int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTria return 0; } +/*! init triangle divisions */ +void ntlGeometryObjModel::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri) { + // warning - copied from geomobj calc! + errMsg("ntlGeometryObjModel","calcTriangleDivs special!"); + mTriangleDivs1.resize( tris.size() ); + mTriangleDivs2.resize( tris.size() ); + mTriangleDivs3.resize( tris.size() ); + for(size_t i=0; i<tris.size(); i++) { + ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ]; + ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ]; + ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ]; + ntlVec3Gfx side1 = p1 - p0; + ntlVec3Gfx side2 = p2 - p0; + ntlVec3Gfx side3 = p1 - p2; + int divs1=0, divs2=0, divs3=0; + if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + //if(normNoSqrt(side3) > fsTri*fsTri) { divs3 = (int)(norm(side3)/fsTri); } + + // special handling + // warning, requires objmodel triangle treatment (no verts dups) + if(getMeshAnimated()) { + vector<ntlSetVec3f> &sverts = mcAniVerts.accessValues(); + for(int s=0; s<(int)sverts.size(); s++) { + p0 = sverts[s].mVerts[ tris[i].getPoints()[0] ]; + p1 = sverts[s].mVerts[ tris[i].getPoints()[1] ]; + p2 = sverts[s].mVerts[ tris[i].getPoints()[2] ]; + side1 = p1 - p0; side2 = p2 - p0; side3 = p1 - p2; + int tdivs1=0, tdivs2=0, tdivs3=0; + if(normNoSqrt(side1) > fsTri*fsTri) { tdivs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { tdivs2 = (int)(norm(side2)/fsTri); } + if(tdivs1>divs1) divs1=tdivs1; + if(tdivs2>divs2) divs2=tdivs2; + if(tdivs3>divs3) divs3=tdivs3; + } + } // */ + mTriangleDivs1[i] = divs1; + mTriangleDivs2[i] = divs2; + mTriangleDivs3[i] = divs3; + } +} + /****************************************************************************** * load model from .obj file @@ -114,7 +229,13 @@ int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTria int ntlGeometryObjModel::loadBobjModel(string filename) { - const bool debugPrint=false; + bool haveAniSets=false; + vector<ntlSetVec3f> aniverts; + vector<ntlSetVec3f> aninorms; + vector<double> anitimes; + + const bool debugPrint=true; + const bool debugPrintFull=true; gzFile gzf; gzf = gzopen(filename.c_str(), "rb"); if (!gzf) { @@ -140,6 +261,7 @@ int ntlGeometryObjModel::loadBobjModel(string filename) gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); } mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]); + if(debugPrintFull) errMsg("FULLV"," "<<i<<" "<< mVertices[i] ); } if(debugPrint) errMsg("NV"," "<<numVerts<<" "<< mVertices.size() ); @@ -157,6 +279,7 @@ int ntlGeometryObjModel::loadBobjModel(string filename) gzread(gzf, &(n[j]), sizeof( (n[j]) ) ); } mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]); + if(debugPrintFull) errMsg("FULLN"," "<<i<<" "<< mNormals[i] ); } if(debugPrint) errMsg("NN"," "<<numVerts<<" "<< mNormals.size() ); @@ -180,8 +303,99 @@ int ntlGeometryObjModel::loadBobjModel(string filename) debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 ); + // try to load animated mesh + aniverts.clear(); + aninorms.clear(); + anitimes.clear(); + while(1) { + //ntlVec3Gfx check; + float x[3]; + float frameTime=0.; + int bytesRead = 0; + int numNorms2=-1, numVerts2=-1; + //for(int j=0; j<3; j++) { + //x[j] = 0.; + //bytesRead += gzread(gzf, &(x[j]), sizeof(float) ); + //} + //check = ntlVec3Gfx(x[0],x[1],x[2]); + //if(debugPrint) errMsg("ANI_NV1"," "<<check<<" "<<" bytes:"<<bytesRead ); + bytesRead += gzread(gzf, &frameTime, sizeof(frameTime) ); + //if(bytesRead!=3*sizeof(float)) { + if(bytesRead!=sizeof(float)) { + debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' no ani sets. ", 10 ); + if(anitimes.size()>0) { + // finally init channels and stop reading file + mcAniVerts = AnimChannel<ntlSetVec3f>(aniverts,anitimes); + mcAniNorms = AnimChannel<ntlSetVec3f>(aninorms,anitimes); + } + goto gzreaddone; + } + bytesRead += gzread(gzf, &numVerts2, sizeof(numVerts2) ); + haveAniSets=true; + // continue to read new set + vector<ntlVec3Gfx> vertset; + vector<ntlVec3Gfx> normset; + vertset.resize(numVerts); + normset.resize(numVerts); + //vertset[0] = check; + if(debugPrintFull) errMsg("FUL1V"," "<<0<<" "<< vertset[0] ); + + for(int i=0; i<numVerts; i++) { // start at one! + for(int j=0; j<3; j++) { + bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); + } + vertset[i] = ntlVec3Gfx(x[0],x[1],x[2]); + if(debugPrintFull) errMsg("FUL2V"," "<<i<<" "<< vertset[i] ); + } + if(debugPrint) errMsg("ANI_VV"," "<<numVerts<<" "<< vertset.size()<<" bytes:"<<bytesRead ); + + bytesRead += gzread(gzf, &numNorms2, sizeof(numNorms2) ); + for(int i=0; i<numVerts; i++) { + for(int j=0; j<3; j++) { + bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); + } + normset[i] = ntlVec3Gfx(x[0],x[1],x[2]); + if(debugPrintFull) errMsg("FUL2N"," "<<i<<" "<< normset[i] ); + } + if(debugPrint) errMsg("ANI_NV"," "<<numVerts<<","<<numVerts2<<","<<numNorms2<<","<< normset.size()<<" bytes:"<<bytesRead ); + + // set ok + if(bytesRead== (int)( (numVerts*2*3+1) *sizeof(float)+2*sizeof(int) ) ) { + if(aniverts.size()==0) { + // TODO, ignore first mesh? + double anitime = (double)(frameTime-1.); // start offset!? anitimes.size(); + // get for current frame entry + if(mcAniTimes.getSize()>1) anitime = mcAniTimes.get(anitime); + anitime = anitime*mAniTimeScale+mAniTimeOffset; + + anitimes.push_back( anitime ); + aniverts.push_back( ntlSetVec3f(mVertices) ); + aninorms.push_back( ntlSetVec3f(mNormals) ); + if(debugPrint) errMsg("ANI_NV","new set "<<mVertices.size()<<","<< mNormals.size()<<" time:"<<anitime ); + } + double anitime = (double)(frameTime); //anitimes.size(); + // get for current frame entry + if(mcAniTimes.getSize()>1) anitime = mcAniTimes.get(anitime); + anitime = anitime*mAniTimeScale+mAniTimeOffset; + + anitimes.push_back( anitime ); + aniverts.push_back( ntlSetVec3f(vertset) ); + aninorms.push_back( ntlSetVec3f(normset) ); + if(debugPrint) errMsg("ANI_NV","new set "<<vertset.size()<<","<< normset.size()<<" time:"<<anitime ); + } else { + errMsg("ntlGeometryObjModel::loadBobjModel","Malformed ani set! Aborting... ("<<bytesRead<<") "); + goto gzreaddone; + } + } // anim sets */ + +gzreaddone: + + if(haveAniSets) { + debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' ani sets loaded: "<< mcAniVerts.accessValues().size() <<","<<mcAniNorms.accessValues().size() <<" ", 1 ); + } gzclose( gzf ); return 0; + gzreaderror: mTriangles.clear(); mVertices.clear(); @@ -196,24 +410,36 @@ gzreaderror: * *****************************************************************************/ void -ntlGeometryObjModel::getTriangles( vector<ntlTriangle> *triangles, +ntlGeometryObjModel::getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) { if(!mLoaded) { // invalid type... return; } + if(mcAniVerts.getSize()>1) { mVertices = mcAniVerts.get(t).mVerts; } + if(mcAniNorms.getSize()>1) { mNormals = mcAniNorms.get(t).mVerts; } + + int startvert = vertices->size(); + vertices->resize( vertices->size() + mVertices.size() ); + normals->resize( normals->size() + mVertices.size() ); + for(int i=0; i<(int)mVertices.size(); i++) { + (*vertices)[startvert+i] = mVertices[i]; + (*normals)[startvert+i] = mNormals[i]; + } + triangles->reserve(triangles->size() + mTriangles.size() ); for(int i=0; i<(int)mTriangles.size(); i+=3) { int trip[3]; - trip[0] = mTriangles[i+0]; - trip[1] = mTriangles[i+1]; - trip[2] = mTriangles[i+2]; - - sceneAddTriangle( - mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]], - mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]], - ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */ + trip[0] = startvert+mTriangles[i+0]; + trip[1] = startvert+mTriangles[i+1]; + trip[2] = startvert+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 , triangles,vertices,normals ); /* normal unused */ + sceneAddTriangleNoVert( trip, ntlVec3Gfx(0.0), 1 , triangles ); /* normal unused */ } objectId = -1; // remove warning // bobj diff --git a/intern/elbeem/intern/ntl_geometrymodel.h b/intern/elbeem/intern/ntl_geometrymodel.h index 929b8c59841..f911279489d 100644 --- a/intern/elbeem/intern/ntl_geometrymodel.h +++ b/intern/elbeem/intern/ntl_geometrymodel.h @@ -28,16 +28,24 @@ class ntlGeometryObjModel : public ntlGeometryObject /*! Filename setting etc. */ virtual void initialize(ntlRenderGlobals *glob); + /*! is the mesh animated? */ + virtual bool getMeshAnimated(); /* create triangles from obj */ - virtual void getTriangles( vector<ntlTriangle> *triangles, + virtual void getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ); /*! load model from .bobj file, returns !=0 upon error */ int loadBobjModel(string filename); /*! init model from given vertex and triangle arrays */ - int initModel(int numVertices, float *vertices, int numTriangles, int *triangles); + int initModel(int numVertices, float *vertices, int numTriangles, int *triangles, + int channelSize, float *channelVertices); + /*! init triangle divisions */ + virtual void calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri); + + /*! do ani mesh CPS */ + void calculateCPS(string filename); private: @@ -55,6 +63,20 @@ class ntlGeometryObjModel : public ntlGeometryObject vector<ntlVec3Gfx> mVertices; vector<ntlVec3Gfx> mNormals; + /*! animated channels for vertices, if given will override getris by default */ + AnimChannel<ntlSetVec3f> mcAniVerts; + AnimChannel<ntlSetVec3f> mcAniNorms; + /*! map entrie of anim mesh to sim times */ + AnimChannel<double> mcAniTimes; + /*! timing mapping & offset for config files */ + double mAniTimeScale, mAniTimeOffset; + + /*! ani mesh cps params */ + ntlVec3Gfx mvCPSStart, mvCPSEnd; + string mCPSFilename; + gfxReal mCPSWidth, mCPSTimestep; + + public: /* Access methods */ diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index 5ab13a946d3..90c3b3437ea 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -24,19 +24,19 @@ ntlGeometryObject::ntlGeometryObject() : mIsInitialized(false), mpMaterial( NULL ), mMaterialName( "default" ), - mCastShadows( 1 ), - mReceiveShadows( 1 ), - mGeoInitId( -1 ), mGeoInitType( 0 ), + mCastShadows( 1 ), mReceiveShadows( 1 ), + mGeoInitType( 0 ), mInitialVelocity(0.0), mcInitialVelocity(0.0), mLocalCoordInivel(false), mGeoInitIntersect(false), mGeoPartSlipValue(0.0), - mOnlyThinInit(false), + mVolumeInit(VOLUMEINIT_VOLUME), mInitialPos(0.), mcTrans(0.), mcRot(0.), mcScale(1.), mIsAnimated(false), - mMovPoints(), mMovNormals(), + mMovPoints(), //mMovNormals(), mHaveCachedMov(false), - mCachedMovPoints(), mCachedMovNormals(), + mCachedMovPoints(), //mCachedMovNormals(), + mTriangleDivs1(), mTriangleDivs2(), mTriangleDivs3(), mMovPntsInited(-100.0), mMaxMovPnt(-1), mcGeoActive(1.) { @@ -50,6 +50,30 @@ ntlGeometryObject::~ntlGeometryObject() { } +/*! is the mesh animated? */ +bool ntlGeometryObject::getMeshAnimated() { + // off by default, on for e.g. ntlGeometryObjModel + return false; +} + +/*! init object anim flag */ +bool ntlGeometryObject::checkIsAnimated() { + if( (mcTrans.accessValues().size()>1) // VALIDATE + || (mcRot.accessValues().size()>1) + || (mcScale.accessValues().size()>1) + || (mcGeoActive.accessValues().size()>1) + || (mcInitialVelocity.accessValues().size()>1) + ) { + mIsAnimated = true; + } + + // fluid objects always have static init! + if(mGeoInitType==FGI_FLUID) { + mIsAnimated=false; + } + return mIsAnimated; +} + /*****************************************************************************/ /* Init attributes etc. of this object */ /*****************************************************************************/ @@ -77,10 +101,10 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) // init material, always necessary searchMaterial( glob->getMaterials() ); - mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"ntlGeometryObject", "mGeoInitId", false); + this->mGeoInitId = mpAttrs->readInt("geoinitid", this->mGeoInitId,"ntlGeometryObject", "mGeoInitId", false); mGeoInitIntersect = mpAttrs->readInt("geoinit_intersect", mGeoInitIntersect,"ntlGeometryObject", "mGeoInitIntersect", false); string ginitStr = mpAttrs->readString("geoinittype", "", "ntlGeometryObject", "mGeoInitType", false); - if(mGeoInitId>=0) { + if(this->mGeoInitId>=0) { bool gotit = false; for(int i=0; i<GEOINIT_STRINGS; i++) { if(ginitStr== initStringStrs[i]) { @@ -95,10 +119,10 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) } } - int geoActive = mpAttrs->readInt("geoinitactive", 1,"ntlGeometryObject", "mGeoInitId", false); + int geoActive = mpAttrs->readInt("geoinitactive", 1,"ntlGeometryObject", "geoActive", false); if(!geoActive) { // disable geo init again... - mGeoInitId = -1; + this->mGeoInitId = -1; } mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false)); if(getAttributeList()->exists("initial_velocity") || (!mcInitialVelocity.isInited()) ) { @@ -109,7 +133,11 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) mLocalCoordInivel = mpAttrs->readBool("geoinit_localinivel", mLocalCoordInivel,"ntlGeometryObject", "mLocalCoordInivel", false); mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false); + bool mOnlyThinInit = false; // deprecated! mOnlyThinInit = mpAttrs->readBool("geoinit_onlythin", mOnlyThinInit,"ntlGeometryObject", "mOnlyThinInit", false); + if(mOnlyThinInit) mVolumeInit = VOLUMEINIT_SHELL; + mVolumeInit = mpAttrs->readInt("geoinit_volumeinit", mVolumeInit,"ntlGeometryObject", "mVolumeInit", false); + if((mVolumeInit<VOLUMEINIT_VOLUME)||(mVolumeInit>VOLUMEINIT_BOTH)) mVolumeInit = VOLUMEINIT_VOLUME; // override cfg types mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false); @@ -141,17 +169,18 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob) // always use channel if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<double>(geoactive); } - if( (mcTrans.accessValues().size()>1) // VALIDATE - || (mcRot.accessValues().size()>1) - || (mcScale.accessValues().size()>1) - || (mcGeoActive.accessValues().size()>1) - || (mcInitialVelocity.accessValues().size()>1) - ) { - mIsAnimated = true; - } + //if( (mcTrans.accessValues().size()>1) // VALIDATE + //|| (mcRot.accessValues().size()>1) + //|| (mcScale.accessValues().size()>1) + //|| (mcGeoActive.accessValues().size()>1) + //|| (mcInitialVelocity.accessValues().size()>1) + //) { + //mIsAnimated = true; + //} + checkIsAnimated(); mIsInitialized = true; - debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': visible="<<this->mVisible<<" gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<< + debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': visible="<<this->mVisible<<" gid="<<this->mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<< " gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug } @@ -222,16 +251,11 @@ void ntlGeometryObject::sceneAddTriangle( 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)) { + //if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME) && (!mIsAnimated)) { + if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME)) { flag |= (1<< (geoiId+4)); flag |= mGeoInitType; } @@ -246,6 +270,38 @@ void ntlGeometryObject::sceneAddTriangle( } /* normals check*/ } +void ntlGeometryObject::sceneAddTriangleNoVert(int *trips, + ntlVec3Gfx trin, bool smooth, + vector<ntlTriangle> *triangles) { + ntlTriangle tri; + + tri.getPoints()[0] = trips[0]; + tri.getPoints()[1] = trips[1]; + tri.getPoints()[2] = trips[2]; + + // same as normal sceneAddTriangle + + /* init flags from ntl_ray.h */ + int flag = 0; + if(getVisible()){ flag |= TRI_GEOMETRY; } + if(getCastShadows() ) { + flag |= TRI_CASTSHADOWS; } + + /* init geo init id */ + int geoiId = getGeoInitId(); + if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME)) { + flag |= (1<< (geoiId+4)); + flag |= mGeoInitType; + } + /*errMsg("ntlScene::addTriangle","DEBUG flag="<<convertFlags2String(flag) ); */ + tri.setFlags( flag ); + + /* triangle normal missing */ + tri.setNormal( trin ); + tri.setSmoothNormals( smooth ); + tri.setObjectId( this->mObjectId ); + triangles->push_back( tri ); +} /******************************************************************************/ @@ -284,14 +340,15 @@ void ntlGeometryObject::initChannels( 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( (mcTrans.accessValues().size()>1) // VALIDATE + //|| (mcRot.accessValues().size()>1) + //|| (mcScale.accessValues().size()>1) + //|| (mcGeoActive.accessValues().size()>1) + //|| (mcInitialVelocity.accessValues().size()>1) + //) { + //mIsAnimated = true; + //} + checkIsAnimated(); if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,getName()<< " nt:"<<mcTrans.accessValues().size()<<" nr:"<<mcRot.accessValues().size()<< @@ -336,7 +393,7 @@ void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, || (!mHaveCachedMov) ) { // transformation is animated, continue - ntlVec3Gfx pos = mcTrans.get(t); + ntlVec3Gfx pos = getTranslation(t); ntlVec3Gfx scale = mcScale.get(t); ntlVec3Gfx rot = mcRot.get(t); ntlMat4Gfx rotMat; @@ -347,6 +404,7 @@ void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, (*verts)[i] *= scale; (*verts)[i] = rotMat * (*verts)[i]; (*verts)[i] += pos; + //if(i<10) errMsg("ntlGeometryObject::applyTransformation"," v"<<i<<"/"<<vend<<"="<<(*verts)[i]); } if(norms) { for(int i=vstart; i<vend; i++) { @@ -355,30 +413,62 @@ void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, } } else { // not animated, cached points were already returned - errMsg ("ntlGeometryObject::applyTransformation","Object "<<getName()<<" used cached points "); + //errMsg ("ntlGeometryObject::applyTransformation","Object "<<getName()<<" used cached points "); + } +} + +/*! init triangle divisions */ +void ntlGeometryObject::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri) { + mTriangleDivs1.resize( tris.size() ); + mTriangleDivs2.resize( tris.size() ); + mTriangleDivs3.resize( tris.size() ); + for(size_t i=0; i<tris.size(); i++) { + const ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ]; + const ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ]; + const ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ]; + const ntlVec3Gfx side1 = p1 - p0; + const ntlVec3Gfx side2 = p2 - p0; + const ntlVec3Gfx side3 = p1 - p2; + int divs1=0, divs2=0, divs3=0; + if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + //if(normNoSqrt(side3) > fsTri*fsTri) { divs3 = (int)(norm(side3)/fsTri); } + /*if(getMeshAnimated()) { + vector<ntlSetVec3f> *verts =mcAniVerts.accessValues(); + for(int s=0; s<verts->size(); s++) { + int tdivs1=0, tdivs2=0, tdivs3=0; + if(normNoSqrt(side1) > fsTri*fsTri) { tdivs1 = (int)(norm(side1)/fsTri); } + if(normNoSqrt(side2) > fsTri*fsTri) { tdivs2 = (int)(norm(side2)/fsTri); } + if(tdivs1>divs1) divs1=tdivs1; + if(tdivs2>divs2) divs2=tdivs2; + } + }*/ + mTriangleDivs1[i] = divs1; + mTriangleDivs2[i] = divs2; + mTriangleDivs3[i] = divs3; } } /*! Prepare points for moving objects */ -void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { - if(mMovPntsInited==featureSize) return; +void ntlGeometryObject::initMovingPoints(double time, gfxReal featureSize) { + if((mMovPntsInited==featureSize)&&(!getMeshAnimated())) return; const bool debugMoinit=false; + //vector<ntlVec3Gfx> movNormals; vector<ntlTriangle> triangles; vector<ntlVec3Gfx> vertices; - vector<ntlVec3Gfx> normals; + vector<ntlVec3Gfx> vnormals; int objectId = 1; - this->getTriangles(&triangles,&vertices,&normals,objectId); + this->getTriangles(time, &triangles,&vertices,&vnormals,objectId); mMovPoints.clear(); //= vertices; - mMovNormals.clear(); //= normals; + //movNormals.clear(); //= vnormals; if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" has v:"<<vertices.size()<<" t:"<<triangles.size() ); // no points? if(vertices.size()<1) { mMaxMovPnt=-1; return; } - ntlVec3f maxscale = channelFindMaxVf(mcScale); float maxpart = ABS(maxscale[0]); if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]); @@ -388,8 +478,12 @@ void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { const gfxReal fsTri = featureSize*0.5 *scaleFac; if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri ); + if(mTriangleDivs1.size()!=triangles.size()) { + calcTriangleDivs(vertices,triangles,fsTri); + } + // debug: count points to init - if(debugMoinit) { + /*if(debugMoinit) { errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" estimating..."); int countp=vertices.size()*2; for(size_t i=0; i<triangles.size(); i++) { @@ -412,7 +506,7 @@ void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { } } errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" requires:"<<countp*2); - } + } // */ bool discardInflowBack = false; if( (mGeoInitType==FGI_MBNDINFLOW) && (mcInitialVelocity.accessValues().size()<1) ) discardInflowBack = true; @@ -422,79 +516,87 @@ void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { // init std points for(size_t i=0; i<vertices.size(); i++) { ntlVec3Gfx p = vertices[ i ]; - ntlVec3Gfx n = normals[ i ]; + ntlVec3Gfx n = vnormals[ i ]; // discard inflow backsides //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) { if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) { if(dot(mInitialVelocity,n)<0.0) continue; } mMovPoints.push_back(p); - mMovNormals.push_back(n); + //movNormals.push_back(n); + //errMsg("ntlGeometryObject::initMovingPoints","std"<<i<<" p"<<p<<" n"<<n<<" "); } // init points & refine... for(size_t i=0; i<triangles.size(); i++) { - ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ]; - ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0; - ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0; - int divs1=0, divs2=0; - if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } - if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } - /* if( (i!=6) && - (i!=6) ) { divs1=divs2=0; } // DEBUG */ + int *trips = triangles[i].getPoints(); + const ntlVec3Gfx p0 = vertices[ trips[0] ]; + const ntlVec3Gfx side1 = vertices[ trips[1] ] - p0; + const ntlVec3Gfx side2 = vertices[ trips[2] ] - p0; + int divs1=mTriangleDivs1[i], divs2=mTriangleDivs2[i]; + //if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); } + //if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); } + const ntlVec3Gfx trinorm = getNormalized(cross(side1,side2))*0.5*featureSize; + if(discardInflowBack) { + if(dot(mInitialVelocity,trinorm)<0.0) continue; + } + //errMsg("ntlGeometryObject::initMovingPoints","Tri1 "<<vertices[trips[0]]<<","<<vertices[trips[1]]<<","<<vertices[trips[2]]<<" "<<divs1<<","<<divs2 ); if(divs1+divs2 > 0) { for(int u=0; u<=divs1; u++) { for(int v=0; v<=divs2; v++) { const gfxReal uf = (gfxReal)(u+0.25) / (gfxReal)(divs1+0.0); const gfxReal vf = (gfxReal)(v+0.25) / (gfxReal)(divs2+0.0); if(uf+vf>1.0) continue; - 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) { + ntlVec3Gfx p = + vertices[ trips[0] ] * (1.0-uf-vf)+ + vertices[ trips[1] ] * uf + + vertices[ trips[2] ] * vf; + //ntlVec3Gfx n = vnormals[ + //trips[0] ] * (1.0-uf-vf)+ + //vnormals[ trips[1] ]*uf + + //vnormals[ trips[2] ]*vf; + //normalize(n); // 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); + mMovPoints.push_back(p - trinorm); + //movNormals.push_back(n); + //movNormals.push_back(trinorm); + //errMsg("TRINORM","p"<<p<<" n"<<n<<" trin"<<trinorm); } } } } // duplicate insides - size_t mpsize = mMovPoints.size(); - for(size_t i=0; i<mpsize; i++) { - //normalize(normals[i]); + //size_t mpsize = mMovPoints.size(); + //for(size_t i=0; i<mpsize; i++) { + //normalize(vnormals[i]); //errMsg("TTAT"," moved:"<<(mMovPoints[i] - mMovPoints[i]*featureSize)<<" org"<<mMovPoints[i]<<" norm"<<mMovPoints[i]<<" fs"<<featureSize); - mMovPoints.push_back(mMovPoints[i] - mMovNormals[i]*0.5*featureSize); - mMovNormals.push_back(mMovNormals[i]); - } + //mMovPoints.push_back(mMovPoints[i] - movNormals[i]*0.5*featureSize); + //movNormals.push_back(movNormals[i]); + //} // find max point mMaxMovPnt = 0; gfxReal dist = normNoSqrt(mMovPoints[0]); - for(size_t i=0; i<mpsize; i++) { + for(size_t i=0; i<mMovPoints.size(); i++) { if(normNoSqrt(mMovPoints[i])>dist) { mMaxMovPnt = i; dist = normNoSqrt(mMovPoints[0]); } } - if( (mcTrans.accessValues().size()>1) // VALIDATE + if( (this-getMeshAnimated()) + || (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); + //mCachedMovNormals = movNormals; + //applyTransformation(time, &mCachedMovPoints, &mCachedMovNormals, 0, mCachedMovPoints.size(), true); + applyTransformation(time, &mCachedMovPoints, NULL, 0, mCachedMovPoints.size(), true); mHaveCachedMov = true; debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" cached points ", 7); } @@ -502,18 +604,186 @@ void ntlGeometryObject::initMovingPoints(gfxReal featureSize) { mMovPntsInited = featureSize; debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" inited v:"<<vertices.size()<<"->"<<mMovPoints.size() , 5); } +/*! Prepare points for animated objects, + * init both sets, never used cached points + * discardInflowBack ignore */ +void ntlGeometryObject::initMovingPointsAnim( + double srctime, vector<ntlVec3Gfx> &srcmovPoints, + double dsttime, vector<ntlVec3Gfx> &dstmovPoints, + gfxReal featureSize, + ntlVec3Gfx geostart, ntlVec3Gfx geoend + ) { + const bool debugMoinit=false; + + //vector<ntlVec3Gfx> srcmovNormals; + //vector<ntlVec3Gfx> dstmovNormals; + + vector<ntlTriangle> srctriangles; + vector<ntlVec3Gfx> srcvertices; + vector<ntlVec3Gfx> unused_normals; + vector<ntlTriangle> dsttriangles; + vector<ntlVec3Gfx> dstvertices; + //vector<ntlVec3Gfx> dstnormals; + int objectId = 1; + // TODO optimize? , get rid of normals? + unused_normals.clear(); + this->getTriangles(srctime, &srctriangles,&srcvertices,&unused_normals,objectId); + unused_normals.clear(); + this->getTriangles(dsttime, &dsttriangles,&dstvertices,&unused_normals,objectId); + + srcmovPoints.clear(); + dstmovPoints.clear(); + //srcmovNormals.clear(); + //dstmovNormals.clear(); + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","Object "<<getName()<<" has srcv:"<<srcvertices.size()<<" srct:"<<srctriangles.size() ); + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","Object "<<getName()<<" has dstv:"<<dstvertices.size()<<" dstt:"<<dsttriangles.size() ); + // no points? + if(srcvertices.size()<1) { + mMaxMovPnt=-1; + return; + } + if((srctriangles.size() != dsttriangles.size()) || + (srcvertices.size() != dstvertices.size()) ) { + errMsg("ntlGeometryObject::initMovingPointsAnim","Invalid triangle numbers! Aborting..."); + return; + } + ntlVec3f maxscale = channelFindMaxVf(mcScale); + float maxpart = ABS(maxscale[0]); + if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]); + if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]); + float scaleFac = 1.0/(maxpart); + // TODO - better reinit from time to time? + const gfxReal fsTri = featureSize*0.5 *scaleFac; + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri ); + + if(mTriangleDivs1.size()!=srctriangles.size()) { + calcTriangleDivs(srcvertices,srctriangles,fsTri); + } + + + // init std points + for(size_t i=0; i<srcvertices.size(); i++) { + srcmovPoints.push_back(srcvertices[i]); + //srcmovNormals.push_back(srcnormals[i]); + } + for(size_t i=0; i<dstvertices.size(); i++) { + dstmovPoints.push_back(dstvertices[i]); + //dstmovNormals.push_back(dstnormals[i]); + } + if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","stats src:"<<srcmovPoints.size()<<" dst:"<<dstmovPoints.size()<<" " ); + // init points & refine... + for(size_t i=0; i<srctriangles.size(); i++) { + const int divs1=mTriangleDivs1[i]; + const int divs2=mTriangleDivs2[i]; + if(divs1+divs2 > 0) { + int *srctrips = srctriangles[i].getPoints(); + int *dsttrips = dsttriangles[i].getPoints(); + const ntlVec3Gfx srcp0 = srcvertices[ srctrips[0] ]; + const ntlVec3Gfx srcside1 = srcvertices[ srctrips[1] ] - srcp0; + const ntlVec3Gfx srcside2 = srcvertices[ srctrips[2] ] - srcp0; + const ntlVec3Gfx dstp0 = dstvertices[ dsttrips[0] ]; + const ntlVec3Gfx dstside1 = dstvertices[ dsttrips[1] ] - dstp0; + const ntlVec3Gfx dstside2 = dstvertices[ dsttrips[2] ] - dstp0; + const ntlVec3Gfx src_trinorm = getNormalized(cross(srcside1,srcside2))*0.5*featureSize; + const ntlVec3Gfx dst_trinorm = getNormalized(cross(dstside1,dstside2))*0.5*featureSize; + //errMsg("ntlGeometryObject::initMovingPointsAnim","Tri1 "<<srcvertices[srctrips[0]]<<","<<srcvertices[srctrips[1]]<<","<<srcvertices[srctrips[2]]<<" "<<divs1<<","<<divs2 ); + 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 srcp = + srcvertices[ srctrips[0] ] * (1.0-uf-vf)+ + srcvertices[ srctrips[1] ] * uf + + srcvertices[ srctrips[2] ] * vf; + ntlVec3Gfx dstp = + dstvertices[ dsttrips[0] ] * (1.0-uf-vf)+ + dstvertices[ dsttrips[1] ] * uf + + dstvertices[ dsttrips[2] ] * vf; + + // cutoffDomain + if((srcp[0]<geostart[0]) && (dstp[0]<geostart[0])) continue; + if((srcp[1]<geostart[1]) && (dstp[1]<geostart[1])) continue; + if((srcp[2]<geostart[2]) && (dstp[2]<geostart[2])) continue; + if((srcp[0]>geoend[0] ) && (dstp[0]>geoend[0] )) continue; + if((srcp[1]>geoend[1] ) && (dstp[1]>geoend[1] )) continue; + if((srcp[2]>geoend[2] ) && (dstp[2]>geoend[2] )) continue; + + //ntlVec3Gfx srcn = + //srcnormals[ srctriangles[i].getPoints()[0] ] * (1.0-uf-vf)+ + //srcnormals[ srctriangles[i].getPoints()[1] ] * uf + + //srcnormals[ srctriangles[i].getPoints()[2] ] * vf; + //normalize(srcn); + srcmovPoints.push_back(srcp); + srcmovPoints.push_back(srcp-src_trinorm); + //srcmovNormals.push_back(srcn); + + //ntlVec3Gfx dstn = + //dstnormals[ dsttriangles[i].getPoints()[0] ] * (1.0-uf-vf)+ + //dstnormals[ dsttriangles[i].getPoints()[1] ] * uf + + //dstnormals[ dsttriangles[i].getPoints()[2] ] * vf; + //normalize(dstn); + dstmovPoints.push_back(dstp); + dstmovPoints.push_back(dstp-dst_trinorm); + //dstmovNormals.push_back(dstn); + + /*if(debugMoinit && (i>=0)) errMsg("ntlGeometryObject::initMovingPointsAnim"," "<< + //srcmovPoints[ srcmovPoints.size()-1 ]<<","<< + //srcmovNormals[ srcmovNormals.size()-1 ]<<" "<< + //dstmovPoints[ dstmovPoints.size()-1 ]<<","<< + //dstmovNormals[ dstmovNormals.size()-1 ]<<" " + (srcmovNormals[ srcmovPoints.size()-1 ]- + dstmovNormals[ dstmovPoints.size()-1 ])<<" " + ); + // */ + } + } + } + } + + /*if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","stats src:"<<srcmovPoints.size()<<","<<srcmovNormals.size()<<" dst:"<<dstmovPoints.size()<<","<<dstmovNormals.size() ); + // duplicate insides + size_t mpsize = srcmovPoints.size(); + for(size_t i=0; i<mpsize; i++) { + srcmovPoints.push_back(srcmovPoints[i] - srcmovNormals[i]*1.0*featureSize); + //? srcnormals.push_back(srcnormals[i]); + } + mpsize = dstmovPoints.size(); + for(size_t i=0; i<mpsize; i++) { + dstmovPoints.push_back(dstmovPoints[i] - dstmovNormals[i]*1.0*featureSize); + //? dstnormals.push_back(dstnormals[i]); + } + // */ + + /*if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","stats src:"<<srcmovPoints.size()<<","<<srcmovNormals.size()<<" dst:"<<dstmovPoints.size()<<","<<dstmovNormals.size() ); + for(size_t i=0; i<srcmovPoints.size(); i++) { + ntlVec3Gfx p1 = srcmovPoints[i]; + ntlVec3Gfx p2 = dstmovPoints[i]; + gfxReal len = norm(p1-p2); + if(len>0.01) { errMsg("ntlGeometryObject::initMovingPointsAnim"," i"<<i<<" "<< p1<<" "<<p2<<" "<<len); } + } // */ + + // find max point not necessary + debMsgStd("ntlGeometryObject::initMovingPointsAnim",DM_MSG,"Object "<<getName()<<" inited v:"<<srcvertices.size()<<"->"<<srcmovPoints.size()<<","<<dstmovPoints.size() , 5); +} /*! Prepare points for moving objects */ void ntlGeometryObject::getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms) { if(mHaveCachedMov) { ret = mCachedMovPoints; - if(norms) { *norms = mCachedMovNormals; } - errMsg ("ntlGeometryObject::getMovingPoints","Object "<<getName()<<" used cached points "); + if(norms) { + //*norms = mCachedMovNormals; + errMsg("ntlGeometryObject","getMovingPoints - Normals currently unused!"); + } + //errMsg ("ntlGeometryObject::getMovingPoints","Object "<<getName()<<" used cached points "); // DEBUG return; } ret = mMovPoints; - if(norms) { *norms = mMovNormals; } + if(norms) { + errMsg("ntlGeometryObject","getMovingPoints - Normals currently unused!"); + //*norms = mMovNormals; + } } @@ -536,6 +806,31 @@ ntlVec3Gfx ntlGeometryObject::calculateMaxVel(double t1, double t2) { /*! get translation at time t*/ ntlVec3Gfx ntlGeometryObject::getTranslation(double t) { ntlVec3Gfx pos = mcTrans.get(t); + // DEBUG CP_FORCECIRCLEINIT 1 + /*if( + (mName.compare(string("0__ts1"))==0) || + (mName.compare(string("1__ts1"))==0) || + (mName.compare(string("2__ts1"))==0) || + (mName.compare(string("3__ts1"))==0) || + (mName.compare(string("4__ts1"))==0) || + (mName.compare(string("5__ts1"))==0) || + (mName.compare(string("6__ts1"))==0) || + (mName.compare(string("7__ts1"))==0) || + (mName.compare(string("8__ts1"))==0) || + (mName.compare(string("9__ts1"))==0) + ) { int j=mName[0]-'0'; + ntlVec3Gfx ppos(0.); { // DEBUG + const float tscale=10.; + const float tprevo = 0.33; + const ntlVec3Gfx toff(50,50,0); + const ntlVec3Gfx oscale(30,30,0); + ppos[0] = cos(tscale* t - tprevo*(float)j + M_PI -0.1) * oscale[0] + toff[0]; + ppos[1] = -sin(tscale* t - tprevo*(float)j + M_PI -0.1) * oscale[1] + toff[1]; + ppos[2] = toff[2]; } // DEBUG + pos = ppos; + pos[2] = 0.15; + } + // DEBUG CP_FORCECIRCLEINIT 1 */ return pos; } /*! get active flag time t*/ diff --git a/intern/elbeem/intern/ntl_geometryobject.h b/intern/elbeem/intern/ntl_geometryobject.h index ae81d748818..5fe994682e3 100644 --- a/intern/elbeem/intern/ntl_geometryobject.h +++ b/intern/elbeem/intern/ntl_geometryobject.h @@ -19,6 +19,10 @@ class ntlTriangle; #define DUMP_FULLGEOMETRY 1 #define DUMP_PARTIAL 2 +#define VOLUMEINIT_VOLUME 1 +#define VOLUMEINIT_SHELL 2 +#define VOLUMEINIT_BOTH (VOLUMEINIT_SHELL|VOLUMEINIT_VOLUME) + class ntlGeometryObject : public ntlGeometryClass { @@ -35,7 +39,7 @@ class ntlGeometryObject : public ntlGeometryClass virtual void initialize(ntlRenderGlobals *glob); /*! Get the triangles from this object */ - virtual void getTriangles( vector<ntlTriangle> *triangles, + virtual void getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) = 0; @@ -65,12 +69,8 @@ class ntlGeometryObject : public ntlGeometryClass /*! Returns the cast shadows attribute */ inline int getCastShadows() const { return mCastShadows; } - /*! Returns the geo init id */ - inline void setGeoInitId(int set) { mGeoInitId=set; } /*! Returns the geo init typ */ inline void setGeoInitType(int set) { mGeoInitType=set; } - /*! Returns the geo init id */ - inline int getGeoInitId() const { return mGeoInitId; } /*! Returns the geo init typ */ inline int getGeoInitType() const { return mGeoInitType; } @@ -83,8 +83,8 @@ class ntlGeometryObject : public ntlGeometryClass 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; } + inline int getVolumeInit() const { return mVolumeInit; } + inline void setVolumeInit(int set) { mVolumeInit=set; } /*! Set/get the cast initial veocity attribute */ void setInitialVelocity(ntlVec3Gfx set); @@ -102,12 +102,23 @@ class ntlGeometryObject : public ntlGeometryClass /*! is the object animated? */ inline bool getIsAnimated() const { return mIsAnimated; } + /*! init object anim flag */ + bool checkIsAnimated(); + /*! is the mesh animated? */ + virtual bool getMeshAnimated(); + /*! init triangle divisions */ + virtual void calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri); /*! apply object translation at time t*/ void applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo); /*! Prepare points for moving objects */ - void initMovingPoints(gfxReal featureSize); + void initMovingPoints(double time, gfxReal featureSize); + /*! Prepare points for animated objects */ + void initMovingPointsAnim( + double srctime, vector<ntlVec3Gfx> &srcpoints, + double dsttime, vector<ntlVec3Gfx> &dstpoints, + gfxReal featureSize, ntlVec3Gfx geostart, ntlVec3Gfx geoend ); /*! Prepare points for moving objects (copy into ret) */ void getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms = NULL); /*! Calculate max. velocity on object from t1 to t2 */ @@ -126,6 +137,9 @@ class ntlGeometryObject : public ntlGeometryClass vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *vertNormals); + void sceneAddTriangleNoVert(int *trips, + ntlVec3Gfx trin, bool smooth, + vector<ntlTriangle> *triangles); protected: @@ -144,8 +158,6 @@ class ntlGeometryObject : public ntlGeometryClass int mReceiveShadows; /* fluid init data */ - /*! id of fluid init (is used in solver initialization) */ - int mGeoInitId; /*! fluid object type (fluid, obstacle, accelerator etc.) */ int mGeoInitType; /*! initial velocity for fluid objects */ @@ -158,7 +170,7 @@ class ntlGeometryObject : public ntlGeometryClass /*! part slip bc value */ float mGeoPartSlipValue; /*! only init as thin object, dont fill? */ - bool mOnlyThinInit; + int mVolumeInit; /*! initial offset for rot/scale */ ntlVec3Gfx mInitialPos; @@ -169,11 +181,13 @@ class ntlGeometryObject : public ntlGeometryClass /*! moving point/normal storage */ vector<ntlVec3Gfx> mMovPoints; - vector<ntlVec3Gfx> mMovNormals; + // unused vector<ntlVec3Gfx> mMovNormals; /*! cached points for non moving objects/timeslots */ bool mHaveCachedMov; vector<ntlVec3Gfx> mCachedMovPoints; - vector<ntlVec3Gfx> mCachedMovNormals; + // unused vector<ntlVec3Gfx> mCachedMovNormals; + /*! precomputed triangle divisions */ + vector<int> mTriangleDivs1,mTriangleDivs2,mTriangleDivs3; /*! inited? */ float mMovPntsInited; /*! point with max. distance from center */ diff --git a/intern/elbeem/intern/ntl_geometryshader.h b/intern/elbeem/intern/ntl_geometryshader.h index 6adc5629a2d..07be18a8ef9 100644 --- a/intern/elbeem/intern/ntl_geometryshader.h +++ b/intern/elbeem/intern/ntl_geometryshader.h @@ -21,7 +21,8 @@ class ntlGeometryShader : //! Default constructor inline ntlGeometryShader() : - ntlGeometryClass() {}; + ntlGeometryClass(), mOutFilename("") + {}; //! Default destructor virtual ~ntlGeometryShader() {}; @@ -42,11 +43,17 @@ class ntlGeometryShader : /*! notify object that dump is in progress (e.g. for field dump) */ virtual void notifyShaderOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) = 0; + /*! get ouput filename, returns global render outfile if empty */ + std::string getOutFilename( void ) { return mOutFilename; } + protected: //! vector for the objects vector<ntlGeometryObject *> mObjects; + + /*! surface output name for this simulation */ + std::string mOutFilename; }; #endif diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp index 5df9c0068f9..c838e6f6f84 100644 --- a/intern/elbeem/intern/ntl_ray.cpp +++ b/intern/elbeem/intern/ntl_ray.cpp @@ -803,7 +803,7 @@ void ntlScene::buildScene(double time,bool firstInit) int vstart = mVertNormals.size(); (*iter)->setObjectId(idCnt); - (*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt); + (*iter)->getTriangles(time, &mTriangles, &mVertices, &mVertNormals, idCnt); (*iter)->applyTransformation(time, &mVertices, &mVertNormals, vstart, mVertices.size(), false ); if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Done with "<<(*iter)->getName()<<" totTris:"<<mTriangles.size()<<" totVerts:"<<mVertices.size()<<" totNorms:"<<mVertNormals.size(), 4 ); @@ -837,7 +837,10 @@ void ntlScene::buildScene(double time,bool firstInit) iter != mGeos.end(); iter++) { if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) { ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); - geoshad->postGeoConstrInit( mpGlob ); + if(geoshad->postGeoConstrInit( mpGlob )) { + errFatal("ntlScene::buildScene","Init failed for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); + return; + } } } mFirstInitDone = true; diff --git a/intern/elbeem/intern/ntl_ray.h b/intern/elbeem/intern/ntl_ray.h index 716a620bfab..2321cee15e9 100644 --- a/intern/elbeem/intern/ntl_ray.h +++ b/intern/elbeem/intern/ntl_ray.h @@ -149,8 +149,6 @@ private: /*! 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 @@ -217,7 +215,7 @@ private: //int mNormalIndex; ?? ntlVec3Gfx mNormal; - /*! Flags for object attributes cast shadows, make caustics etc. */ + /*! Flags for object attributes cast shadows */ int mFlags; /*! ID of last ray that an intersection was calculated for */ diff --git a/intern/elbeem/intern/ntl_vector3dim.h b/intern/elbeem/intern/ntl_vector3dim.h index ffcaa4149e0..2e50330a807 100644 --- a/intern/elbeem/intern/ntl_vector3dim.h +++ b/intern/elbeem/intern/ntl_vector3dim.h @@ -201,6 +201,9 @@ private: +//! global string for formatting vector output in utilities.cpp +extern char *globVecFormatStr; + /************************************************************************* Outputs the object in human readable form using the format [x,y,z] @@ -209,7 +212,10 @@ template<class Scalar> std::ostream& operator<<( std::ostream& os, const ntlVector3Dim<Scalar>& i ) { - os << '[' << i[0] << ", " << i[1] << ", " << i[2] << ']'; + char buf[256]; + snprintf(buf,256,globVecFormatStr,i[0],i[1],i[2]); + os << std::string(buf); + //os << '[' << i[0] << ", " << i[1] << ", " << i[2] << ']'; return os; } diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index 8d1d5d4b45c..6b4dc7b6054 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -34,6 +34,11 @@ void setPointers( ntlRenderGlobals *setglob); /****************************************************************************** * Constructor *****************************************************************************/ + +ntlWorld::ntlWorld() { + initDefaults(); +} + ntlWorld::ntlWorld(string filename, bool commandlineMode) { #ifndef ELBEEM_PLUGIN @@ -60,12 +65,18 @@ ntlWorld::ntlWorld(string filename, bool commandlineMode) #endif // ELBEEM_PLUGIN } -ntlWorld::ntlWorld(elbeemSimulationSettings *settings) + +int globalDomainCounter = 1; +int ntlWorld::addDomain(elbeemSimulationSettings *settings) { - initDefaults(); - // todo init settings + // create domain obj SimulationObject *sim = new SimulationObject(); + char simname[100]; + snprintf(simname,100,"domain%04d",globalDomainCounter); + globalDomainCounter++; + sim->setName(std::string(simname)); mpGlob->getSims()->push_back( sim ); + // important - add to both, only render scene objects are free'd mpGlob->getRenderScene()->addGeoClass( sim ); mpGlob->getSimScene()->addGeoClass( sim ); @@ -80,10 +91,7 @@ ntlWorld::ntlWorld(elbeemSimulationSettings *settings) Parametrizer *param = sim->getParametrizer(); param->setSize( settings->resolutionxyz ); param->setDomainSize( settings->realsize ); - param->setViscosity( settings->viscosity ); - param->setGravity( ParamVec(settings->gravity[0], settings->gravity[1], settings->gravity[2]) ); param->setAniStart( settings->animStart ); - param->setAniFrameTimeChannel( settings->aniFrameTime ); param->setNormalizedGStar( settings->gstar ); // init domain channels @@ -98,21 +106,30 @@ ntlWorld::ntlWorld(elbeemSimulationSettings *settings) valv.clear(); time.clear(); elbeemSimplifyChannelVec3(channel,&size); \ for(int i=0; i<size; i++) { valv.push_back( ParamVec(channel[4*i+0],channel[4*i+1],channel[4*i+2]) ); time.push_back( channel[4*i+3] ); } - INIT_CHANNEL_FLOAT(settings->channelViscosity, settings->channelSizeViscosity); - param->initViscosityChannel(valf,time); + param->setViscosity( settings->viscosity ); + if((settings->channelViscosity)&&(settings->channelSizeViscosity>0)) { + INIT_CHANNEL_FLOAT(settings->channelViscosity, settings->channelSizeViscosity); + param->initViscosityChannel(valf,time); } - INIT_CHANNEL_VEC(settings->channelGravity, settings->channelSizeGravity); - param->initGravityChannel(valv,time); + param->setGravity( ParamVec(settings->gravity[0], settings->gravity[1], settings->gravity[2]) ); + if((settings->channelGravity)&&(settings->channelSizeGravity>0)) { + INIT_CHANNEL_VEC(settings->channelGravity, settings->channelSizeGravity); + param->initGravityChannel(valv,time); } - INIT_CHANNEL_FLOAT(settings->channelFrameTime, settings->channelSizeFrameTime); - param->initAniFrameTimeChannel(valf,time); + param->setAniFrameTimeChannel( settings->aniFrameTime ); + if((settings->channelFrameTime)&&(settings->channelSizeFrameTime>0)) { + INIT_CHANNEL_FLOAT(settings->channelFrameTime, settings->channelSizeFrameTime); + param->initAniFrameTimeChannel(valf,time); } #undef INIT_CHANNEL_FLOAT #undef INIT_CHANNEL_VEC - mpGlob->setAniFrames( settings->noOfFrames ); + // might be set by previous domain + if(mpGlob->getAniFrames() < settings->noOfFrames) mpGlob->setAniFrames( settings->noOfFrames ); + // set additionally to SimulationObject->mOutFilename mpGlob->setOutFilename( settings->outputPath ); - // further init in postGeoConstrInit/initializeLbmSimulation of SimulationObject + + return 0; } void ntlWorld::initDefaults() @@ -149,18 +166,19 @@ void ntlWorld::initDefaults() void ntlWorld::finishWorldInit() { - if(!SIMWORLD_OK()) return; + if(! isSimworldOk() ) return; // init the scene for the first time long sstartTime = getTime(); // first init sim scene for geo setup mpGlob->getSimScene()->buildScene(0.0, true); + if(! isSimworldOk() ) return; mpGlob->getRenderScene()->buildScene(0.0, true); + if(! isSimworldOk() ) return; long sstopTime = getTime(); debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10); - if(!SIMWORLD_OK()) return; // TODO check simulations, run first steps mFirstSim = -1; if(mpSims->size() > 0) { @@ -204,6 +222,9 @@ void ntlWorld::finishWorldInit() if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1); } } + + if(! isSimworldOk() ) return; + setElbeemState( SIMWORLD_INITED ); } @@ -237,11 +258,9 @@ void ntlWorld::setSingleFrameOut(string singleframeFilename) { *****************************************************************************/ // blender interface -#if ELBEEM_BLENDER==1 -extern "C" { - void simulateThreadIncreaseFrame(void); -} -#endif // ELBEEM_BLENDER==1 +//#if ELBEEM_BLENDER==1 +//extern "C" { void simulateThreadIncreaseFrame(void); } +//#endif // ELBEEM_BLENDER==1 int ntlWorld::renderAnimation( void ) { @@ -258,20 +277,32 @@ int ntlWorld::renderAnimation( void ) } mThreadRunning = true; // not threaded, but still use the same flags - renderScene(); + if(getElbeemState() == SIMWORLD_INITED) { + renderScene(); + } else if(getElbeemState() == SIMWORLD_STOP) { + // dont render now, just continue + setElbeemState( SIMWORLD_INITED ); + mFrameCnt--; // counted one too many from last abort... + } else { + debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"Not properly inited, stopping...",1); + return 1; + } + if(mpSims->size() <= 0) { debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1); return 1; } - for(mFrameCnt=0; ((mFrameCnt<mpGlob->getAniFrames()) && (!getStopRenderVisualization() )); mFrameCnt++) { + bool simok = true; + for( ; ((mFrameCnt<mpGlob->getAniFrames()) && (!getStopRenderVisualization() ) && (simok)); mFrameCnt++) { if(!advanceSims(mFrameCnt)) { renderScene(); -#if ELBEEM_BLENDER==1 +//#if ELBEEM_BLENDER==1 // update Blender gui display after each frame - simulateThreadIncreaseFrame(); -#endif // ELBEEM_BLENDER==1 + //simulateThreadIncreaseFrame(); +//#endif // ELBEEM_BLENDER==1 } // else means sim panicked, so dont render... + else { simok=false; } } mThreadRunning = false; return 0; @@ -285,8 +316,10 @@ int ntlWorld::renderAnimation( void ) int ntlWorld::renderVisualization( bool multiThreaded ) { #ifndef NOGUI - //gfxReal deltat = 0.0015; + if(getElbeemState() != SIMWORLD_INITED) { return 0; } + if(multiThreaded) mThreadRunning = true; + // TODO, check global state? while(!getStopRenderVisualization()) { if(mpSims->size() <= 0) { @@ -315,7 +348,7 @@ int ntlWorld::renderVisualization( bool multiThreaded ) warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" ); setStopRenderVisualization( true ); } - if(!SIMWORLD_OK()) { + if(! isSimworldOk() ) { warnMsg("ntlWorld::advanceSims","World state error... stopping" ); setStopRenderVisualization( true ); } @@ -368,7 +401,11 @@ int ntlWorld::advanceSims(int framenum) { bool done = false; bool allPanic = true; - //debMsgStd("ntlWorld::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug + + // stop/quit, dont display/render + if(getElbeemState()==SIMWORLD_STOP) { + return 1; + } for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); } double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); @@ -378,16 +415,15 @@ int ntlWorld::advanceSims(int framenum) done=true; allPanic=false; } -#if ELBEEM_BLENDER==1 + int gstate = 0; +//#if ELBEEM_BLENDER==1 // same as solver_main check, but no mutex check here - if(getGlobalBakeState()<0) { - // this means abort... cause panic - allPanic = true; done = true; - } -#endif // ELBEEM_BLENDER==1 + //gstate = getGlobalBakeState(); + //if(gstate<0) { allPanic = true; done = true; } // this means abort... cause panic +//#endif // ELBEEM_BLENDER==1 // step all the sims, and check for panic - debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic, 10); // debug // timedebug + debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic<<" gstate:"<<gstate, 10); // debug // timedebug while(!done) { double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep(); singleStepSims(nextTargetTime); @@ -395,7 +431,7 @@ int ntlWorld::advanceSims(int framenum) // check target times done = true; allPanic = false; - //if((framenum>0) && (nextTargetTime<=(*mpSims)[mFirstSim]->getCurrentTime()) ) { + if((*mpSims)[mFirstSim]->getTimestep() <1e-9 ) { // safety check, avoid timesteps that are too small errMsg("ntlWorld::advanceSims","Invalid time step, causing panic! curr:"<<(*mpSims)[mFirstSim]->getCurrentTime()<<" next:"<<nextTargetTime<<", stept:"<< (*mpSims)[mFirstSim]->getTimestep() ); @@ -468,12 +504,11 @@ void ntlWorld::singleStepSims(double targetTime) { int ntlWorld::renderScene( void ) { #ifndef ELBEEM_PLUGIN - char nrStr[5]; /* nr conversion */ - //std::ostringstream outfilename(""); /* ppm file */ - std::ostringstream outfn_conv(""); /* converted ppm with other suffix */ - ntlRenderGlobals *glob; /* storage for global rendering parameters */ - myTime_t timeStart,totalStart,timeEnd; /* measure user running time */ - myTime_t rendStart,rendEnd; /* measure user rendering time */ + char nrStr[5]; // nr conversion + std::ostringstream outfn_conv(""); // converted ppm with other suffix + ntlRenderGlobals *glob; // storage for global rendering parameters + myTime_t timeStart,totalStart,timeEnd; // measure user running time + myTime_t rendStart,rendEnd; // measure user rendering time glob = mpGlob; /* check if picture already exists... */ diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h index 131f1828601..18f388a5af4 100644 --- a/intern/elbeem/intern/ntl_world.h +++ b/intern/elbeem/intern/ntl_world.h @@ -23,16 +23,18 @@ class ntlRandomStream; class ntlWorld { public: + /*! Constructor for API init */ + ntlWorld(); /*! Constructor */ ntlWorld(string filename, bool commandlineMode); - /*! Constructor for API init */ - ntlWorld(elbeemSimulationSettings *simSettings); /*! Destructor */ virtual ~ntlWorld( void ); /*! default init for all contructors */ void initDefaults(); /*! common world contruction stuff once the scene is set up */ void finishWorldInit(); + /*! add domain for API init */ + int addDomain(elbeemSimulationSettings *simSettings); /*! render a whole animation (command line mode) */ int renderAnimation( void ); diff --git a/intern/elbeem/intern/parametrizer.cpp b/intern/elbeem/intern/parametrizer.cpp index 50d544d2bcf..b9dc1c36239 100644 --- a/intern/elbeem/intern/parametrizer.cpp +++ b/intern/elbeem/intern/parametrizer.cpp @@ -55,7 +55,6 @@ Parametrizer::Parametrizer( void ) : mSizex(50), mSizey(50), mSizez(50), mTimeFactor( 1.0 ), mcAniFrameTime(0.0001), - mAniFrameTime(0.0001), mTimeStepScale(1.0), mAniStart(0.0), mExtent(1.0, 1.0, 1.0), //mSurfaceTension( 0.0 ), @@ -149,17 +148,11 @@ void Parametrizer::parseAttrList() *! advance to next render/output frame *****************************************************************************/ void Parametrizer::setFrameNum(int frame) { - //double oldval = mAniFrameTime; - //mAniFrameTime = mcAniFrameTime.get(frametime); - //if(mAniFrameTime<0.0) { - //errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<mAniFrameTime<<" at frame "<<frame<<", resetting to "<<oldval); - //mAniFrameTime = oldval; } - //errMsg("ChannelAnimDebug","anim: anif"<<mAniFrameTime<<" at "<<frame<<" "); - // debug getAttributeList()->find("p_aniframetime")->print(); mFrameNum = frame; if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","setFrameNum frame-num="<<mFrameNum); } /*! get time of an animation frame (renderer) */ +// also used by: mpParam->getCurrentAniFrameTime() , e.g. for velocity dump ParamFloat Parametrizer::getAniFrameTime( int frame ) { double frametime = (double)frame; ParamFloat anift = mcAniFrameTime.get(frametime); @@ -168,7 +161,7 @@ ParamFloat Parametrizer::getAniFrameTime( int frame ) { errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<anift<<" at frame "<<frame<<", resetting to "<<resetv); anift = resetv; } - if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<<frame<<", frametime="<<anift<<" "); + if((0)|| (DEBUG_PARAMCHANNELS)) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<<frame<<", frametime="<<anift<<" "); return anift; } @@ -247,7 +240,7 @@ int Parametrizer::calculateAniStepsPerFrame(int frame) { } int value = (int)(getAniFrameTime(frame)/mTimestep); if((value<0) || (value>1000000)) { - errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<mAniFrameTime<<") <> ani-frame-time ("<<mTimestep<<") settings, aborting...", SIMWORLD_INITERROR); + errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<value<<") <> ani-frame-time ("<<mTimestep<<") settings, aborting...", SIMWORLD_INITERROR); return 1; } return value; @@ -373,7 +366,7 @@ errMsg("Warning","Used z-dir for gstar!"); maxDeltaT = sqrt( gStar*mCellSize *mTimeStepScale /forceStrength ); } else { // use 1 lbm setp = 1 anim step as max - maxDeltaT = mAniFrameTime; + maxDeltaT = getAniFrameTime(0); } if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," targeted step time = "<<maxDeltaT, 10); @@ -436,16 +429,16 @@ errMsg("Warning","Used z-dir for gstar!"); if(!checkSeenValues(PARAM_ANIFRAMETIME)) { errFatal("Parametrizer::calculateAllMissingValues"," Warning no ani frame time given!", SIMWORLD_INITERROR); - mAniFrameTime = mTimestep; + setAniFrameTimeChannel( mTimestep ); } - //mAniFrameTime = mAniFrames * mTimestep; + if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame(mFrameNum)<<" for frame "<<mFrameNum, 1); if((checkSeenValues(PARAM_ANISTART))&&(calculateAniStart()>0)) { if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<<calculateAniStart()<<" ",1); } - if(!SIMWORLD_OK()) return false; + if(! isSimworldOk() ) return false; // everything ok return true; } @@ -471,6 +464,51 @@ errMsg("Warning","Used z-dir for gstar!"); } +/****************************************************************************** + * init debug functions + *****************************************************************************/ + + +/*! set kinematic viscosity */ +void Parametrizer::setViscosity(ParamFloat set) { + mcViscosity = AnimChannel<ParamFloat>(set); + seenThis( PARAM_VISCOSITY ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcViscosity set = "<< mcViscosity.printChannel() ); } +} +void Parametrizer::initViscosityChannel(vector<ParamFloat> val, vector<double> time) { + mcViscosity = AnimChannel<ParamFloat>(val,time); + seenThis( PARAM_VISCOSITY ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcViscosity initc = "<< mcViscosity.printChannel() ); } +} + +/*! set the external force */ +void Parametrizer::setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { + mcGravity = AnimChannel<ParamVec>(ParamVec(setx,sety,setz)); + seenThis( PARAM_GRAVITY ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcGravity set = "<< mcGravity.printChannel() ); } +} +void Parametrizer::setGravity(ParamVec set) { + mcGravity = AnimChannel<ParamVec>(set); + seenThis( PARAM_GRAVITY ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcGravity set = "<< mcGravity.printChannel() ); } +} +void Parametrizer::initGravityChannel(vector<ParamVec> val, vector<double> time) { + mcGravity = AnimChannel<ParamVec>(val,time); + seenThis( PARAM_GRAVITY ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcGravity initc = "<< mcGravity.printChannel() ); } +} + +/*! set time of an animation frame (renderer) */ +void Parametrizer::setAniFrameTimeChannel(ParamFloat set) { + mcAniFrameTime = AnimChannel<ParamFloat>(set); + seenThis( PARAM_ANIFRAMETIME ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcAniFrameTime set = "<< mcAniFrameTime.printChannel() ); } +} +void Parametrizer::initAniFrameTimeChannel(vector<ParamFloat> val, vector<double> time) { + mcAniFrameTime = AnimChannel<ParamFloat>(val,time); + seenThis( PARAM_ANIFRAMETIME ); + if(DEBUG_PARAMCHANNELS) { errMsg("DebugChannels","Parametrizer::mcAniFrameTime initc = "<< mcAniFrameTime.printChannel() ); } +} // OLD interface stuff // reactivate at some point? diff --git a/intern/elbeem/intern/parametrizer.h b/intern/elbeem/intern/parametrizer.h index 471fb571e35..c0df399b7ee 100644 --- a/intern/elbeem/intern/parametrizer.h +++ b/intern/elbeem/intern/parametrizer.h @@ -119,22 +119,25 @@ class Parametrizer { /*! calculate real world [m/s] velocity from lattice value */ ParamVec calculateRwVelocityFromLatt( ParamVec ivel ); - - /*! set kinematic viscosity */ - void setViscosity(ParamFloat set) { mcViscosity = AnimChannel<ParamFloat>(set); seenThis( PARAM_VISCOSITY ); } - void initViscosityChannel(vector<ParamFloat> val, vector<double> time) { mcViscosity = AnimChannel<ParamFloat>(val,time); } - /*! set speed of sound */ void setSoundSpeed(ParamFloat set) { mSoundSpeed = set; seenThis( PARAM_SOUNDSPEED ); } /*! get speed of sound */ ParamFloat getSoundSpeed( void ) { return mSoundSpeed; } + /*! set kinematic viscosity */ + void setViscosity(ParamFloat set); + void initViscosityChannel(vector<ParamFloat> val, vector<double> time); + /*! set the external force */ - void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mcGravity = AnimChannel<ParamVec>(ParamVec(setx,sety,setz)); seenThis( PARAM_GRAVITY ); } - void setGravity(ParamVec set) { mcGravity = AnimChannel<ParamVec>(set); seenThis( PARAM_GRAVITY ); } - void initGravityChannel(vector<ParamVec> val, vector<double> time) { mcGravity = AnimChannel<ParamVec>(val,time); } + void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz); + void setGravity(ParamVec set); + void initGravityChannel(vector<ParamVec> val, vector<double> time); ParamVec getGravity(double time) { return mcGravity.get( time ); } + /*! set time of an animation frame (renderer) */ + void setAniFrameTimeChannel(ParamFloat set); + void initAniFrameTimeChannel(vector<ParamFloat> val, vector<double> time); + /*! set the length of a single time step */ void setTimestep(ParamFloat set) { mTimestep = set; seenThis( PARAM_STEPTIME ); } /*! get the length of a single time step */ @@ -155,11 +158,6 @@ class Parametrizer { void setSize(int ijk) { mSizex = ijk; mSizey = ijk; mSizez = ijk; seenThis( PARAM_SIZE ); } 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 ); } - void setAniFrameTimeChannel(ParamFloat set) { mcAniFrameTime = AnimChannel<ParamFloat>(set); seenThis( PARAM_ANIFRAMETIME ); } - void initAniFrameTimeChannel(vector<ParamFloat> val, vector<double> time) { mcAniFrameTime = AnimChannel<ParamFloat>(val,time); seenThis( PARAM_ANIFRAMETIME ); } - /*! set starting time of the animation (renderer) */ void setAniStart(ParamFloat set) { mAniStart = set; seenThis( PARAM_ANISTART ); } /*! get starting time of the animation (renderer) */ @@ -266,8 +264,6 @@ class Parametrizer { /*! for renderer - length of an animation step [s] */ AnimChannel<ParamFloat> mcAniFrameTime; - /*! current value for next frame */ - ParamFloat mAniFrameTime; /*! time step scaling factor for testing/debugging */ ParamFloat mTimeStepScale; diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp index 828674675e2..c49c1b1a07e 100644 --- a/intern/elbeem/intern/particletracer.cpp +++ b/intern/elbeem/intern/particletracer.cpp @@ -33,23 +33,17 @@ ParticleTracer::ParticleTracer() : 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 ), + mPartScale(0.1) , mPartHeadDist( 0.1 ), mPartTailDist( -0.1 ), mPartSegments( 4 ), mValueScale(0), mValueCutoffTop(0.0), mValueCutoffBottom(0.0), - mDumpParts(0), mDumpText(0), mDumpTextFile(""), mShowOnly(0), - mNumInitialParts(0), mpTrafo(NULL) + mDumpParts(0), //mDumpText(0), + mDumpTextFile(""), + mDumpTextInterval(0.), mDumpTextLastTime(0.), mDumpTextCount(0), + mShowOnly(0), + mNumInitialParts(0), mpTrafo(NULL), + mInitStart(-1.), mInitEnd(-1.), + mPrevs(), mTrailTimeLast(0.), mTrailInterval(-1.), mTrailLength(0) { - // 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("ParticleTrace",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mDumpParts to "<<set<<","<<mDumpParts,8); - //} - //} debMsgStd("ParticleTracer::ParticleTracer",DM_MSG,"inited",10); }; @@ -66,7 +60,7 @@ void ParticleTracer::parseAttrList(AttributeList *att) mpAttrs = att; mNumInitialParts = mpAttrs->readInt("particles",mNumInitialParts, "ParticleTracer","mNumInitialParts", false); - errMsg(" NUMP"," "<<mNumInitialParts); + //errMsg(" NUMP"," "<<mNumInitialParts); mPartScale = mpAttrs->readFloat("part_scale",mPartScale, "ParticleTracer","mPartScale", false); mPartHeadDist = mpAttrs->readFloat("part_headdist",mPartHeadDist, "ParticleTracer","mPartHeadDist", false); mPartTailDist = mpAttrs->readFloat("part_taildist",mPartTailDist, "ParticleTracer","mPartTailDist", false); @@ -76,19 +70,23 @@ void ParticleTracer::parseAttrList(AttributeList *att) mValueCutoffBottom = mpAttrs->readFloat("part_valcutoffbottom",mValueCutoffBottom, "ParticleTracer","mValueCutoffBottom", false); mDumpParts = mpAttrs->readInt ("part_dump",mDumpParts, "ParticleTracer","mDumpParts", false); - mDumpText = mpAttrs->readInt ("part_textdump",mDumpText, "ParticleTracer","mDumpText", false); + // mDumpText deprecatd, use mDumpTextInterval>0. instead mShowOnly = mpAttrs->readInt ("part_showonly",mShowOnly, "ParticleTracer","mShowOnly", false); mDumpTextFile= mpAttrs->readString("part_textdumpfile",mDumpTextFile, "ParticleTracer","mDumpTextFile", false); + mDumpTextInterval= mpAttrs->readFloat("part_textdumpinterval",mDumpTextInterval, "ParticleTracer","mDumpTextInterval", false); string matPart; matPart = mpAttrs->readString("material_part", "default", "ParticleTracer","material", false); setMaterialName( matPart ); + mInitStart = mpAttrs->readFloat("part_initstart",mInitStart, "ParticleTracer","mInitStart", false); + mInitEnd = mpAttrs->readFloat("part_initend", mInitEnd, "ParticleTracer","mInitEnd", false); + // unused... - int mTrailLength = 0; // UNUSED - int mTrailInterval= 0; // UNUSED + //int mTrailLength = 0; // UNUSED + //int mTrailInterval= 0; // UNUSED mTrailLength = mpAttrs->readInt("traillength",mTrailLength, "ParticleTracer","mTrailLength", false); - mTrailInterval= mpAttrs->readInt("trailinterval",mTrailInterval, "ParticleTracer","mTrailInterval", false); + mTrailInterval= mpAttrs->readFloat("trailinterval",mTrailInterval, "ParticleTracer","mTrailInterval", false); // restore old list mpAttrs = tempAtt; @@ -134,24 +132,14 @@ void ParticleTracer::addParticle(float x, float y, float z) { ntlVec3Gfx p(x,y,z); ParticleObject part( p ); - //mParts.push_back( part ); - // TODO handle other arrays? - //part.setActive( false ); mParts.push_back( part ); - //for(size_t l=0; l<mParts.size(); l++) { - // add deactivated particles to other arrays - // deactivate further particles - //if(l>1) { - //mParts[l][ mParts.size()-1 ].setActive( false ); - //} - //} } void ParticleTracer::cleanup() { // cleanup int last = (int)mParts.size()-1; - if(mDumpText>0) { errMsg("ParticleTracer::cleanup","Skipping cleanup due to text dump..."); return; } + if(mDumpTextInterval>0.) { errMsg("ParticleTracer::cleanup","Skipping cleanup due to text dump..."); return; } for(int i=0; i<=last; i++) { if( mParts[i].getActive()==false ) { @@ -166,7 +154,7 @@ void ParticleTracer::cleanup() { *! dump particles if desired *****************************************************************************/ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename, double simtime) { - debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr, 10); // DEBUG + debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr<<" dumpp"<<mDumpParts, 10); // DEBUG if( (dumptype==DUMP_FULLGEOMETRY)&& @@ -186,13 +174,11 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str numParts = 0; for(size_t i=0; i<mParts.size(); i++) { if(!mParts[i].getActive()) continue; - //if(mParts[i].getLifeTime()<30) { continue; } //? CHECK numParts++; } gzwrite(gzf, &numParts, sizeof(numParts)); for(size_t i=0; i<mParts.size(); i++) { if(!mParts[i].getActive()) { continue; } - //if(mParts[i].getLifeTime()<30) { continue; } //? CHECK ParticleObject *p = &mParts[i]; //int type = p->getType(); // export whole type info int type = p->getFlags(); // debug export whole type & status info @@ -221,17 +207,21 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str gzclose( gzf ); } } // dump? +} +void ParticleTracer::checkDumpTextPositions(double simtime) { // dfor partial & full dump - if(mDumpText>0) { + errMsg("ParticleTracer::checkDumpTextPositions","t="<<simtime<<" last:"<<mDumpTextLastTime<<" inter:"<<mDumpTextInterval); + + if((mDumpTextInterval>0.) && (simtime>mDumpTextLastTime+mDumpTextInterval)) { // dump to binary file std::ostringstream boutfilename(""); if(mDumpTextFile.length()>1) { boutfilename << mDumpTextFile << ".cpart2"; } else { - boutfilename << outfilename <<"_particles" << ".cpart2"; + boutfilename << boutfilename <<"_particles" << ".cpart2"; } - debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"T-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" #"<<frameNr , 7); + debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"T-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" " , 7); int numParts = 0; // only dump bubble particles @@ -242,27 +232,34 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str } // output to text file - gzFile gzf; - if(frameNr==0) { - gzf = gzopen(boutfilename.str().c_str(), "w0"); + //gzFile gzf; + FILE *stf; + if(mDumpTextCount==0) { + //gzf = gzopen(boutfilename.str().c_str(), "w0"); + stf = fopen(boutfilename.str().c_str(), "w"); - gzprintf( gzf, "\n\n# cparts generated by elbeem \n# no. of parts \nN %d \n\n",numParts); + fprintf( stf, "\n\n# cparts generated by elbeem \n# no. of parts \nN %d \n\n",numParts); // fixed time scale for now - gzprintf( gzf, "T %f \n\n", 1.0); + fprintf( stf, "T %f \n\n", 1.0); } else { - gzf = gzopen(boutfilename.str().c_str(), "a+0"); + //gzf = gzopen(boutfilename.str().c_str(), "a+0"); + stf = fopen(boutfilename.str().c_str(), "a+"); } // add current set - if(gzf) { - gzprintf( gzf, "\n\n# new set at frame %d,t%f,p%d --------------------------------- \n\n", frameNr, simtime, numParts ); - gzprintf( gzf, "S %f \n\n", simtime ); + if(stf) { + fprintf( stf, "\n\n# new set at frame %d,t%f,p%d --------------------------------- \n\n", mDumpTextCount, simtime, numParts ); + fprintf( stf, "S %f \n\n", simtime ); for(size_t i=0; i<mParts.size(); i++) { ParticleObject *p = &mParts[i]; ntlVec3Gfx pos = p->getPos(); float size = p->getSize(); - if(!mParts[i].getActive()) { size=0.; } // switch "off" + float infl = 1.; + //if(!mParts[i].getActive()) { size=0.; } // switch "off" + if(!mParts[i].getActive()) { infl=0.; } // switch "off" + if(!mParts[i].getInFluid()) { infl=0.; } // switch "off" + if(mParts[i].getLifeTime()<0.) { infl=0.; } // not yet active... pos = (*mpTrafo) * pos; ntlVec3Gfx v = p->getVel(); @@ -270,23 +267,45 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str v[1] *= mpTrafo->value[1][1]; v[2] *= mpTrafo->value[2][2]; - gzprintf( gzf, "P %f %f %f \n", pos[0],pos[1],pos[2] ); - gzprintf( gzf, "s %f \n", size ); - gzprintf( gzf, "\n", size ); + fprintf( stf, "P %f %f %f \n", pos[0],pos[1],pos[2] ); + if(size!=1.0) fprintf( stf, "s %f \n", size ); + if(infl!=1.0) fprintf( stf, "i %f \n", infl ); + fprintf( stf, "\n" ); } - gzprintf( gzf, "# %d end ", frameNr ); - gzclose( gzf ); + fprintf( stf, "# %d end ", mDumpTextCount ); + //gzclose( gzf ); + fclose( stf ); + + mDumpTextCount++; } + + mDumpTextLastTime += mDumpTextInterval; } + } +void ParticleTracer::checkTrails(double time) { + if(mTrailLength<1) return; + if(time-mTrailTimeLast > mTrailInterval) { + + if( (int)mPrevs.size() < mTrailLength) mPrevs.resize( mTrailLength ); + for(int i=mPrevs.size()-1; i>0; i--) { + mPrevs[i] = mPrevs[i-1]; + //errMsg("TRAIL"," from "<<i<<" to "<<(i-1) ); + } + mPrevs[0] = mParts; + + mTrailTimeLast += mTrailInterval; + } +} + /****************************************************************************** * Get triangles for rendering *****************************************************************************/ -void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, +void ParticleTracer::getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ) { @@ -295,6 +314,7 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, vertices = NULL; triangles = NULL; normals = NULL; objectId = 0; #else // ELBEEM_PLUGIN + int pcnt = 0; // currently not used in blender objectId = 0; // remove, deprecated if(mDumpParts>1) { @@ -303,21 +323,28 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, const bool debugParts = false; int tris = 0; - gfxReal partNormSize = 0.01 * mPartScale; int segments = mPartSegments; - - //int lnewst = mTrailLength-1; - // TODO get rid of mPart[X] array - //? int loldst = mTrailLength-2; - // trails gehen nicht so richtig mit der - // richtung der partikel... - 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; + t = 0.; // doesnt matter - for(size_t i=0; i<mParts.size(); i++) { - //mParts[0][i].setActive(true); - ParticleObject *p = &mParts[i]; + for(size_t t=0; t<mPrevs.size()+1; t++) { + vector<ParticleObject> *dparts; + if(t==0) { + dparts = &mParts; + } else { + dparts = &mPrevs[t-1]; + } + //errMsg("TRAILT","prevs"<<t<<"/"<<mPrevs.size()<<" parts:"<<dparts->size() ); + + gfxReal partscale = mPartScale; + if(t>1) { + partscale *= (gfxReal)(mPrevs.size()+1-t) / (gfxReal)(mPrevs.size()+1); + } + gfxReal partNormSize = 0.01 * partscale; + //for(size_t i=0; i<mParts.size(); i++) { + for(size_t i=0; i<dparts->size(); i++) { + ParticleObject *p = &( (*dparts)[i] ); // mParts[i]; if(mShowOnly!=10) { // 10=show only deleted @@ -339,34 +366,36 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, if(type&PART_INTER) continue; } + pcnt++; ntlVec3Gfx pnew = p->getPos(); if(type&PART_FLOAT) { // WARNING same handling for dump! + if(p->getStatus()&PART_IN) { pnew[2] += 0.8; } // offset for display // add one gridcell offset //pnew[2] += 1.0; } +#if LBMDIM==2 + pnew[2] += 0.001; // DEBUG + pnew[2] += 0.009; // DEBUG +#endif ntlVec3Gfx pdir = p->getVel(); gfxReal plen = normalize( pdir ); if( plen < 1e-05) pdir = ntlVec3Gfx(-1.0 ,0.0 ,0.0); ntlVec3Gfx pos = (*mpTrafo) * pnew; - //ntlVec3Gfx pos = pnew; // T - //pos[0] = pos[0]*scale[0]+trans[0]; // T - //pos[1] = pos[1]*scale[1]+trans[1]; // T - //pos[2] = pos[2]*scale[2]+trans[2]; // T gfxReal partsize = 0.0; if(debugParts) errMsg("DebugParts"," i"<<i<<" new"<<pnew<<" vel"<<pdir<<" pos="<<pos ); //if(i==0 &&(debugParts)) errMsg("DebugParts"," i"<<i<<" new"<<pnew[0]<<" pos="<<pos[0]<<" scale="<<scale[0]<<" t="<<trans[0] ); // value length scaling? if(mValueScale==1) { - partsize = mPartScale * plen; + partsize = partscale * plen; } else if(mValueScale==2) { // cut off scaling if(plen > mValueCutoffTop) continue; if(plen < mValueCutoffBottom) continue; - partsize = mPartScale * plen; + partsize = partscale * plen; } else { - partsize = mPartScale; // no length scaling + partsize = partscale; // no length scaling } //if(type&(PART_DROP|PART_BUBBLE)) partsize *= p->getSize()/5.0; @@ -382,11 +411,7 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, ntlVec3Gfx cv1 = pdir; ntlVec3Gfx cv2 = ntlVec3Gfx(pdir[1], -pdir[0], 0.0); ntlVec3Gfx cv3 = cross( cv1, cv2); - for(int l=0; l<3; l++) { - //? cvmat.value[l][0] = cv1[l]; - //? cvmat.value[l][1] = cv2[l]; - //? cvmat.value[l][2] = cv3[l]; - } + //? for(int l=0; l<3; l++) { cvmat.value[l][0] = cv1[l]; cvmat.value[l][1] = cv2[l]; cvmat.value[l][2] = cv3[l]; } pstart = (cvmat * pstart); pend = (cvmat * pend); @@ -417,7 +442,9 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles, } } - //} // trail + } // t + + debMsgStd("ParticleTracer::getTriangles",DM_MSG,"Dumped "<<pcnt<<"/"<<mParts.size()<<" parts, tris:"<<tris<<", showonly:"<<mShowOnly,10); return; // DEBUG #endif // ELBEEM_PLUGIN diff --git a/intern/elbeem/intern/particletracer.h b/intern/elbeem/intern/particletracer.h index 453c1a793c0..f08bd58dc09 100644 --- a/intern/elbeem/intern/particletracer.h +++ b/intern/elbeem/intern/particletracer.h @@ -22,10 +22,12 @@ template<class Scalar> class ntlMatrix4x4; #define PART_IN (1<< 8) #define PART_OUT (1<< 9) #define PART_INACTIVE (1<<10) +#define PART_OUTFLUID (1<<11) // defines for particle movement #define MOVE_FLOATS 1 #define FLOAT_JITTER 0.03 +//#define FLOAT_JITTER 0.0 extern int ParticleObjectIdCnt; @@ -47,6 +49,8 @@ class ParticleObject //! add vector to position inline void advance(float vx, float vy, float vz) { mPos[0] += vx; mPos[1] += vy; mPos[2] += vz; } + inline void advanceVec(ntlVec3Gfx v) { + mPos[0] += v[0]; mPos[1] += v[1]; mPos[2] += v[2]; } //! advance with own velocity inline void advanceVel() { mPos += mVel; } //! add acceleration to velocity @@ -83,10 +87,17 @@ class ParticleObject if(set) mStatus &= (~PART_INACTIVE); else mStatus |= PART_INACTIVE; } + //! get influid flag + inline bool getInFluid() const { return ((mStatus&PART_OUTFLUID)==0); } + //! set influid flag + inline void setInFluid(bool set) { + if(set) mStatus &= (~PART_OUTFLUID); + else mStatus |= PART_OUTFLUID; + } //! get/set lifetime - inline int getLifeTime() const { return mLifeTime; } + inline float getLifeTime() const { return mLifeTime; } //! set type (lower byte) - inline void setLifeTime(int set) { mLifeTime = set; } + inline void setLifeTime(float set) { mLifeTime = set; } inline int getId() const { return mId; } @@ -103,7 +114,7 @@ class ParticleObject /*! particle status */ int mStatus; /*! count survived time steps */ - int mLifeTime; + float mLifeTime; }; @@ -161,24 +172,34 @@ class ParticleTracer : /*! set/get dump flag */ inline void setDumpParts(bool set) { mDumpParts = set; } inline bool getDumpParts() { return mDumpParts; } - /*! set/get dump flag */ - inline void setDumpText(bool set) { mDumpText = set; } - inline bool getDumpText() { return mDumpText; } /*! set/get dump text file */ - inline void setDumpTextFile(std::string set) { mDumpTextFile = set; } - inline std::string getDumpTextFile() { return mDumpTextFile; } + inline void setDumpTextFile(string set) { mDumpTextFile = set; } + inline string getDumpTextFile() { return mDumpTextFile; } + /*! set/get dump text interval */ + inline void setDumpTextInterval(float set) { mDumpTextInterval = set; } + inline float getDumpTextInterval() { return mDumpTextInterval; } + /*! set/get init times */ + inline void setInitStart(float set) { mInitStart = set; } + inline float getInitStart() { return mInitStart; } + inline void setInitEnd(float set) { mInitEnd = set; } + inline float getInitEnd() { return mInitEnd; } //! set the particle scaling factor inline void setPartScale(float set) { mPartScale = set; } + //! called after each frame to check if positions should be dumped + void checkDumpTextPositions(double simtime); // NTL geometry implementation /*! Get the triangles from this object */ - virtual void getTriangles( vector<ntlTriangle> *triangles, + virtual void getTriangles(double t, vector<ntlTriangle> *triangles, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, int objectId ); virtual void notifyOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename,double simtime); + + // notify of next step for trails + void checkTrails(double time); // free deleted particles void cleanup(); @@ -211,10 +232,12 @@ class ParticleTracer : /*! dump particles (or certain types of) to disk? */ int mDumpParts; - /*! dump particles (or certain types of) to disk? */ - int mDumpText; /*! text dump output file */ - std::string mDumpTextFile; + string mDumpTextFile; + /*! text dump interval, start at t=0, dumping active if >0 */ + float mDumpTextInterval; + float mDumpTextLastTime; + int mDumpTextCount; /*! show only a certain type (debugging) */ int mShowOnly; /*! no. of particles to init */ @@ -222,9 +245,17 @@ class ParticleTracer : //! transform matrix ntlMatrix4x4<gfxReal> *mpTrafo; - /*! init sim/pos transformation */ void initTrafoMatrix(); + + //! init time distribution start/end + float mInitStart, mInitEnd; + + /*! the particle array (for multiple timesteps) */ + vector< vector<ParticleObject> > mPrevs; + /* prev pos save interval */ + float mTrailTimeLast, mTrailInterval; + int mTrailLength; }; #define NTL_PARTICLETRACER_H diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp index 116d68d6824..5d8a73e6ab8 100644 --- a/intern/elbeem/intern/simulation_object.cpp +++ b/intern/elbeem/intern/simulation_object.cpp @@ -32,11 +32,10 @@ LbmSolverInterface* createSolver(); SimulationObject::SimulationObject() : ntlGeometryShader(), mGeoStart(-100.0), mGeoEnd(100.0), - mGeoInitId(-1), mpGiTree(NULL), mpGiObjects(NULL), + mpGiTree(NULL), mpGiObjects(NULL), mpGlob(NULL), mPanic( false ), mDebugType( 1 /* =FLUIDDISPNothing*/ ), - mStepsPerFrame( 10 ), mpLbm(NULL), mpParam( NULL ), mShowSurface(true), mShowParticles(false), mSelectedCid( NULL ), @@ -48,7 +47,6 @@ SimulationObject::SimulationObject() : // reset time mTime = 0.0; - mDisplayTime = 0.0; } @@ -69,12 +67,11 @@ SimulationObject::~SimulationObject() /*****************************************************************************/ /*! init tree for certain geometry init */ /*****************************************************************************/ -void SimulationObject::initGeoTree(int id) { +void SimulationObject::initGeoTree() { if(mpGlob == NULL) { errFatal("SimulationObject::initGeoTree error","Requires globals!", SIMWORLD_INITERROR); return; } - mGeoInitId = id; ntlScene *scene = mpGlob->getSimScene(); mpGiObjects = scene->getObjects(); @@ -97,6 +94,8 @@ void SimulationObject::freeGeoTree() { void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) { mpElbeemSettings = new elbeemSimulationSettings; *mpElbeemSettings = *settings; + + mGeoInitId = settings->domainId+1; } /****************************************************************************** @@ -104,7 +103,7 @@ void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) { *****************************************************************************/ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) { - if(!SIMWORLD_OK()) return 1; + if(! isSimworldOk() ) return 1; // already inited? if(mpLbm) return 0; @@ -116,16 +115,16 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) } + this->mGeoInitId = mpAttrs->readInt("geoinitid", this->mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); //mDimension, mSolverType are deprecated string mSolverType(""); mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); - //errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); return 1; mpLbm = createSolver(); /* check lbm pointer */ if(mpLbm == NULL) { errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR); - return 1; + return 2; } debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2); @@ -140,10 +139,10 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) mpParts = new ParticleTracer(); mpParts->parseAttrList( getAttributeList() ); - if(!SIMWORLD_OK()) return 1; + if(! isSimworldOk() ) return 3; mpParts->setName( getName() + "_part" ); mpParts->initialize( glob ); - if(!SIMWORLD_OK()) return 1; + if(! isSimworldOk() ) return 4; // init material settings string matMc("default"); @@ -152,6 +151,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false ); checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" ); + mpLbm->setLbmInitId( mGeoInitId ); mpLbm->setGeoStart( mGeoStart ); mpLbm->setGeoEnd( mGeoEnd ); mpLbm->setRenderGlobals( mpGlob ); @@ -159,6 +159,8 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) mpLbm->setParticleTracer( mpParts ); if(mpElbeemSettings) { // set further settings from API struct init + if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath); + mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo ); mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing); mpLbm->setSizeX(mpElbeemSettings->resolutionxyz); mpLbm->setSizeY(mpElbeemSettings->resolutionxyz); @@ -166,11 +168,13 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz); mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine); mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles); + // set initial particles + mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles); - 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"); + string dinitType = string("no"); + if (mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part"); + else if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free"); + else /*if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no"); mpLbm->setDomainBound(dinitType); mpLbm->setDomainPartSlip(mpElbeemSettings->obstaclePartslip); mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors); @@ -179,7 +183,13 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10); } - mpLbm->initializeSolver(); + + if(! mpLbm->initializeSolverMemory() ) { errMsg("SimulationObject::initialize","initializeSolverMemory failed"); mPanic=true; return 10; } + if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverMemory status"); mPanic=true; return 11; } + if(! mpLbm->initializeSolverGrids() ) { errMsg("SimulationObject::initialize","initializeSolverGrids failed"); mPanic=true; return 12; } + if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverGrids status"); mPanic=true; return 13; } + if(! mpLbm->initializeSolverPostinit() ) { errMsg("SimulationObject::initialize","initializeSolverPostin failed"); mPanic=true; return 14; } + if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverPostin status"); mPanic=true; return 15; } // print cell type stats const int jmax = sizeof(CellFlagType)*8; @@ -202,7 +212,6 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) } mpLbm->deleteCellIterator( &cid ); -#if ELBEEM_PLUGIN!=1 char charNl = '\n'; debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5); debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5); @@ -215,7 +224,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) } // compute dist. of empty/bnd - fluid - if // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11), - { + if(1){ std::ostringstream out; out.precision(2); out.width(4); int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8]; @@ -226,11 +235,10 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl; if(diffInits > 0) { - debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5); + debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5); } debugOutNnl(out.str(), 5); } -#endif // ELBEEM_PLUGIN==1 // might be modified by mpLbm mpParts->setStart( mGeoStart ); @@ -253,8 +261,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob) #ifdef ELBEEM_PLUGIN mShowParticles=1; #endif // ELBEEM_PLUGIN - //if(getenv("ELBEEM_DUMPPARTICLE")) { // DEBUG ENABLE!!!!!!!!!! - if(mpLbm->getGenerateParticles()>0.0) { + if((mpLbm->getGenerateParticles()>0.0)||(mpParts->getNumInitialParticles()>0)) { mShowParticles=1; mpParts->setDumpParts(true); } @@ -293,6 +300,11 @@ void SimulationObject::step( void ) } if(mpLbm->getPanic()) mPanic = true; + checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); + //if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) { + //int ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, FLUIDSIM_CBSTATUS_STEP, 0); + //errMsg("runSimulationCallback cbtest1"," "<<this->getName()<<" ret="<<ret); + //} //debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getTimestep())<<", framet="<<getFrameTime()<<") ", 10); } /*! prepare visualization of simulation for e.g. raytracing */ @@ -399,6 +411,34 @@ void SimulationObject::setMouseClick() /*! notify object that dump is in progress (e.g. for field dump) */ void SimulationObject::notifyShaderOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) { if(!mpLbm) return; + mpLbm->notifySolverOfDump(dumptype, frameNr,frameNrStr,outfilename); + checkCallerStatus(FLUIDSIM_CBSTATUS_NEWFRAME, frameNr); +} + +/*! check status (e.g. stop/abort) from calling program, returns !=0 if sth. happened... */ +int SimulationObject::checkCallerStatus(int status, int frame) { + //return 0; // DEBUG + int ret = 0; + if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) { + ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, status,frame); + if(ret!=FLUIDSIM_CBRET_CONTINUE) { + if(ret==FLUIDSIM_CBRET_STOP) { + debMsgStd("SimulationObject::notifySolverOfDump",DM_NOTIFY,"Got stop signal from caller",1); + setElbeemState( SIMWORLD_STOP ); + } + else if(ret==FLUIDSIM_CBRET_ABORT) { + errFatal("SimulationObject::notifySolverOfDump","Got abort signal from caller, aborting...", SIMWORLD_GENERICERROR ); + mPanic = 1; + } + else { + errMsg("SimulationObject::notifySolverOfDump","Invalid callback return value: "<<ret<<", ignoring... "); + } + } + } + + errMsg("SimulationObject::checkCallerStatus","s="<<status<<",f="<<frame<<" "<<this->getName()<<" ret="<<ret); + if(isSimworldOk()) return 0; + return 1; } diff --git a/intern/elbeem/intern/simulation_object.h b/intern/elbeem/intern/simulation_object.h index b8d1e90596d..200cad85221 100644 --- a/intern/elbeem/intern/simulation_object.h +++ b/intern/elbeem/intern/simulation_object.h @@ -55,7 +55,7 @@ class SimulationObject : /*! init tree for certain geometry init */ - void initGeoTree(int id); + void initGeoTree(); /*! destroy tree etc. when geometry init done */ void freeGeoTree(); /*! get fluid init type at certain position */ @@ -67,10 +67,6 @@ class SimulationObject : /*! get current (max) simulation time */ double getCurrentTime( void ) { return mTime; } - - /*! set time to display */ - void setDisplayTime(double set) { mDisplayTime = set; } - /*! set geometry generation start point */ virtual void setGeoStart(ntlVec3Gfx set) { mGeoStart = set; } /*! set geometry generation end point */ @@ -126,14 +122,11 @@ class SimulationObject : /*! current time in the simulation */ double mTime; - /*! time to display in the visualizer */ - double mDisplayTime; - /*! for display - start and end vectors for geometry */ ntlVec3Gfx mGeoStart, mGeoEnd; /*! geometry init id */ - int mGeoInitId; + //? int mGeoInitId; /*! tree object for geomerty initialization */ ntlTree *mpGiTree; /*! object vector for geo init */ @@ -147,18 +140,9 @@ class SimulationObject : /*! debug info to display */ int mDebugType; - //! dimension of the simulation - now given by LBM-DIM define globally - //! solver type - - /*! when no parametrizer, use this as no. of steps per frame */ - int mStepsPerFrame; - /*! pointer to the lbm solver */ LbmSolverInterface *mpLbm; - /*! marching cubes object */ - //mCubes *mpMC; - /*! parametrizer for lbm solver */ Parametrizer *mpParam; @@ -193,8 +177,9 @@ class SimulationObject : /*! init parametrizer for anim step length */ Parametrizer *getParametrizer() { return mpParam; } - /*! Access marching cubes object */ - //mCubes *getMCubes( void ) { return mpMC; } + /*! check status (e.g. stop/abort) from calling program, returns !=0 if sth. happened... */ + // parameters same as elbeem runsimCallback + int checkCallerStatus(int status, int frame); /*! get bounding box of fluid for GUI */ virtual inline ntlVec3Gfx *getBBStart() { return &mGeoStart; } diff --git a/intern/elbeem/intern/solver_adap.cpp b/intern/elbeem/intern/solver_adap.cpp new file mode 100644 index 00000000000..aade9b30545 --- /dev/null +++ b/intern/elbeem/intern/solver_adap.cpp @@ -0,0 +1,1293 @@ +/****************************************************************************** + * + * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method + * Copyright 2003,2004,2005 Nils Thuerey + * + * Adaptivity functions + * + *****************************************************************************/ + +#include "solver_class.h" +#include "solver_relax.h" +#include "particletracer.h" + + + +/*****************************************************************************/ +//! coarse step functions +/*****************************************************************************/ + + + +void LbmFsgrSolver::coarseCalculateFluxareas(int lev) +{ +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + lev =0; // get rid of warnings... +#else + FSGR_FORIJK_BOUNDS(lev) { + if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { + if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { + LbmFloat totArea = mFsgrCellArea[0]; // for l=0 + for(int l=1; l<this->cDirNum; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& + (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + ) { + totArea += mFsgrCellArea[l]; + } + } // l + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; + //continue; + } else + if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & (CFEmpty|CFUnused)) { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; + //continue; + } else { + QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; + } + //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); + } + } // } TEST DEBUG + if(!this->mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } +#endif //! LBM_NOADCOARSENING==1 +} + +void LbmFsgrSolver::coarseAdvance(int lev) +{ +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + lev =0; // get rid of warnings... +#else + LbmFloat calcCurrentMass = 0.0; + LbmFloat calcCurrentVolume = 0.0; + + LbmFloat *ccel = NULL; + LbmFloat *tcel = NULL; + LbmFloat m[LBM_DFNUM]; + LbmFloat rho, ux, uy, uz, tmp, usqr, lcsmqo; +#if OPT3D==1 + LbmFloat lcsmqadd, lcsmeq[LBM_DFNUM], lcsmomega; +#endif // OPT3D==true + m[0] = tmp = usqr = 0.0; + + coarseCalculateFluxareas(lev); + // copied from fineAdv. + CellFlagType *pFlagSrc = &RFLAG(lev, 1,1,getForZMin1(),SRCS(lev)); + CellFlagType *pFlagDst = &RFLAG(lev, 1,1,getForZMin1(),TSET(lev)); + pFlagSrc -= 1; + pFlagDst -= 1; + ccel = RACPNT(lev, 1,1,getForZMin1() ,SRCS(lev)); // QTEST + ccel -= QCELLSTEP; + tcel = RACPNT(lev, 1,1,getForZMin1() ,TSET(lev)); // QTEST + tcel -= QCELLSTEP; + //if(strstr(this->getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } + + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { +#if FSGR_STRICT_DEBUG==1 + rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG +#endif + pFlagSrc++; + pFlagDst++; + ccel += QCELLSTEP; + tcel += QCELLSTEP; + + // from coarse cells without unused nbs are not necessary...! -> remove + if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + bool invNb = false; + FORDF1 { if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } } + if(!invNb) { + // WARNING - this modifies source flag array... + *pFlagSrc = CFFluid|CFGrNorm; +#if ELBEEM_PLUGIN!=1 + errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<<lev<<" "<<PRINT_IJK); +#endif // ELBEEM_PLUGIN!=1 + // move to perform coarsening? + } + } // */ + +#if FSGR_STRICT_DEBUG==1 + *pFlagDst = *pFlagSrc; // always set other set... +#else + *pFlagDst = (*pFlagSrc & (~CFGrCoarseInited)); // always set other set... , remove coarse inited flag +#endif + + // old INTCFCOARSETEST==1 + if((*pFlagSrc) & CFGrFromCoarse) { // interpolateFineFromCoarse test! + 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); + this->mNumUsedCells++; + } + continue; // interpolateFineFromCoarse test! + } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 + + if( ((*pFlagSrc) & (CFFluid)) ) { + ccel = RACPNT(lev, i,j,k ,SRCS(lev)); + tcel = RACPNT(lev, i,j,k ,TSET(lev)); + + if( ((*pFlagSrc) & (CFGrFromFine)) ) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? + continue; // comes from fine grid + } + // also ignore CFGrFromCoarse + else if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? + continue; + } + + OPTIMIZED_STREAMCOLLIDE; + *pFlagDst |= CFNoBndFluid; // test? + calcCurrentVolume += RAC(ccel,dFlux); + calcCurrentMass += RAC(ccel,dFlux)*rho; + //ebugMarkCell(lev+1, 2*i+1,2*j+1,2*k ); +#if FSGR_STRICT_DEBUG==1 + if(rho<-1.0){ debugMarkCell(lev, i,j,k ); + errMsg("INVRHOCELL_CHECK"," l"<<lev<<" "<< PRINT_IJK<<" rho:"<<rho ); + CAUSE_PANIC; + } +#endif // FSGR_STRICT_DEBUG==1 + this->mNumUsedCells++; + + } + } + pFlagSrc+=2; // after x + pFlagDst+=2; // after x + ccel += (QCELLSTEP*2); + tcel += (QCELLSTEP*2); + } + pFlagSrc+= mLevel[lev].lSizex*2; // after y + pFlagDst+= mLevel[lev].lSizex*2; // after y + ccel += (QCELLSTEP*mLevel[lev].lSizex*2); + tcel += (QCELLSTEP*mLevel[lev].lSizex*2); + } // all cell loop k,j,i + + + //errMsg("coarseAdvance","level "<<lev<<" stepped from "<<mLevel[lev].setCurr<<" to "<<mLevel[lev].setOther); + if(!this->mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } + // */ + + // update other set + mLevel[lev].setOther = mLevel[lev].setCurr; + mLevel[lev].setCurr ^= 1; + mLevel[lev].lsteps++; + mLevel[lev].lmass = calcCurrentMass * mLevel[lev].lcellfactor; + mLevel[lev].lvolume = calcCurrentVolume * mLevel[lev].lcellfactor; +#if ELBEEM_PLUGIN!=1 + errMsg("DFINI", " m l"<<lev<<" m="<<mLevel[lev].lmass<<" c="<<calcCurrentMass<<" lcf="<< mLevel[lev].lcellfactor ); + errMsg("DFINI", " v l"<<lev<<" v="<<mLevel[lev].lvolume<<" c="<<calcCurrentVolume<<" lcf="<< mLevel[lev].lcellfactor ); +#endif // ELBEEM_PLUGIN +#endif //! LBM_NOADCOARSENING==1 +} + +/*****************************************************************************/ +//! multi level functions +/*****************************************************************************/ + + +// get dfs from level (lev+1) to (lev) coarse border nodes +void LbmFsgrSolver::coarseRestrictFromFine(int lev) +{ +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + lev =0; // get rid of warnings... +#else + if((lev<0) || ((lev+1)>mMaxRefine)) return; +#if FSGR_STRICT_DEBUG==1 + // reset all unused cell values to invalid + int unuCnt = 0; + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,mLevel[lev].setCurr); + if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { + FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } + unuCnt++; + // set here + } else if( ((*pFlagSrc) & (CFFluid|CFGrNorm)) == (CFFluid|CFGrNorm) ) { + // simulated... + } else { + // reset in interpolation + //errMsg("coarseRestrictFromFine"," reset l"<<lev<<" "<<PRINT_IJK); + } + if( ((*pFlagSrc) & (CFEmpty|CFUnused)) ) { // test, also reset? + FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } + } // test + } } } + errMsg("coarseRestrictFromFine"," reset l"<<lev<<" fluid|coarseBorder cells: "<<unuCnt); +#endif // FSGR_STRICT_DEBUG==1 + const int srcSet = mLevel[lev+1].setCurr; + const int dstSet = mLevel[lev].setCurr; + + //restrict + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,dstSet); + if((*pFlagSrc) & (CFFluid)) { + if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { + // do resctriction + mNumInterdCells++; + coarseRestrictCell(lev, i,j,k,srcSet,dstSet); + + this->mNumUsedCells++; + } // from fine & fluid + else { + if(RFLAG(lev+1, 2*i,2*j,2*k,srcSet) & CFGrFromCoarse) { + RFLAG(lev, i,j,k,dstSet) |= CFGrToFine; + } else { + RFLAG(lev, i,j,k,dstSet) &= (~CFGrToFine); + } + } + } // & fluid + }}} + if(!this->mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } +#endif //! LBM_NOADCOARSENING==1 +} + +bool LbmFsgrSolver::adaptGrid(int lev) { +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + lev =0; // get rid of warnings... + return false; +#else + if((lev<0) || ((lev+1)>mMaxRefine)) return false; + bool change = false; + { // refinement, PASS 1-3 + + //bool nbsok; + // FIXME remove TIMEINTORDER ? + LbmFloat interTime = 0.0; + // update curr from other, as streaming afterwards works on curr + // thus read only from srcSet, modify other + const int srcSet = mLevel[lev].setOther; + const int dstSet = mLevel[lev].setCurr; + const int srcFineSet = mLevel[lev+1].setCurr; + const bool debugRefinement = false; + + // use //template functions for 2D/3D + /*if(strstr(this->getName().c_str(),"Debug")) + if(lev+1==mMaxRefine) { // mixborder + for(int l=0;((l<this->cDirNum) && (!removeFromFine)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, srcFineSet)&CFBnd) { // NEWREFT + removeFromFine=true; + } + } + } // FARBORD */ + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + bool removeFromFine = false; + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & reqType) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & (notAllowed)) ) ){ // ok + } else { + removeFromFine=true; + } + + if(removeFromFine) { + // dont turn CFGrFromFine above interface cells into CFGrNorm + //errMsg("performRefinement","Removing CFGrFromFine on lev"<<lev<<" " <<PRINT_IJK<<" srcflag:"<<convertCellFlagType2String(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet)) <<" set:"<<dstSet ); + RFLAG(lev, i,j,k, dstSet) = CFEmpty; +#if FSGR_STRICT_DEBUG==1 + // for interpolation later on during fine grid fixing + // these cells are still correctly inited + 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); + change=true; + mNumFsgrChanges++; + for(int l=1; l<this->cDirNum; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + //errMsg("performRefinement","On lev:"<<lev<<" check: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet<<" = "<<convertCellFlagType2String(RFLAG(lev, ni,nj,nk, srcSet)) ); + if( ( RFLAG(lev, ni,nj,nk, srcSet)&CFFluid ) && + (!(RFLAG(lev, ni,nj,nk, srcSet)&CFGrFromFine)) ) { // dont change status of nb. from fine cells + // tag as inited for debugging, cell contains fluid DFs anyway + RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromFine|CFGrCoarseInited; + //errMsg("performRefinement","On lev:"<<lev<<" set to from fine: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet); + //if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + } + } // l + + // FIXME fix fine level? + } + + // recheck from fine flag + } + }}} // TEST + // PASS 1 */ + + + /*if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { + bool invNb = false; + FORDF1 { + if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } + } + if(!invNb) { + *pFlagSrc = CFFluid|CFGrNorm; + errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<<lev<<" "<<PRINT_IJK); + } + } // */ + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST + for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST + for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST + + // test from coarseAdvance + // from coarse cells without unused nbs are not necessary...! -> remove + + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromCoarse) { + + // from coarse cells without unused nbs are not necessary...! -> remove + bool invNb = false; + bool fluidNb = false; + for(int l=1; l<this->cDirNum; l++) { + if(RFLAG_NB(lev, i, j, k, srcSet, l) & CFUnused) { invNb = true; } + if(RFLAG_NB(lev, i, j, k, srcSet, l) & (CFGrNorm)) { fluidNb = true; } + } + if(!invNb) { + // no unused cells around -> calculate normally from now on + RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + } // from advance + if(!fluidNb) { + // 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + } // from advance + + + // dont allow double transfer + // this might require fixing the neighborhood + if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse)) { + // dont turn CFGrFromFine above interface cells into CFGrNorm + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<lev<<" " <<PRINT_IJK<<" due to finer from coarse cell " ); + RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; + if(lev>0) RFLAG(lev-1, i/2,j/2,k/2, mLevel[lev-1].setCurr) &= (~CFGrToFine); // TODO add more of these? + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); + change=true; + mNumFsgrChanges++; + for(int l=1; l<this->cDirNum; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + if(RFLAG(lev, ni,nj,nk, srcSet)&(CFGrNorm)) { //ok + for(int m=1; m<this->cDirNum; m++) { + int mi= ni +this->dfVecX[m], mj= nj +this->dfVecY[m], mk= nk +this->dfVecZ[m]; + if(RFLAG(lev, mi, mj, mk, srcSet)&CFUnused) { + // norm cells in neighborhood with unused nbs have to be new border... + RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromCoarse; + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + } + } + // these alreay have valid values... + } + 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); + mNumFsgrChanges++; + } + } // l + } // double transer + + } // from coarse + + } } } + // PASS 2 */ + + + // fix dstSet from fine cells here + // warning - checks CFGrFromFine on dstset changed before! + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST + for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST + for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST + + //if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + if(RFLAG(lev, i,j,k, dstSet) & CFGrFromFine) { + // modify finer level border + if((RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse))) { + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" from l"<<lev<<" " <<PRINT_IJK ); + CellFlagType setf = CFFluid; + if(lev+1 < mMaxRefine) setf = CFFluid|CFGrNorm; + RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; + change=true; + mNumFsgrChanges++; + for(int l=1; l<this->cDirNum; l++) { + int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; + if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFGrFromCoarse)) { + //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); + RFLAG(lev+1, bi, bj, bk, srcFineSet) = setf; + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + } + else if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFUnused )) { + //errMsg("performRefinement","Removing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); + interpolateCellFromCoarse(lev+1, bi, bj, bk, srcFineSet, interTime, setf, false); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); + mNumFsgrChanges++; + } + } + for(int l=1; l<this->cDirNum; l++) { + int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; + if( (RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFFluid ) && + (!(RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFGrFromCoarse)) ) { + // all unused nbs now of coarse have to be from coarse + for(int m=1; m<this->cDirNum; m++) { + int mi= bi +this->dfVecX[m], mj= bj +this->dfVecY[m], mk= bk +this->dfVecZ[m]; + if(RFLAG(lev+1, mi, mj, mk, srcFineSet)&CFUnused) { + //errMsg("performRefinement","Changing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(mi,mj,mk) ); + interpolateCellFromCoarse(lev+1, mi, mj, mk, srcFineSet, interTime, CFFluid|CFGrFromCoarse, false); + if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); + mNumFsgrChanges++; + } + } + // nbs prepared... + } + } + } + + } // convert regions of from fine + }}} // TEST + // PASS 3 */ + + if(!this->mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } + } // PASS 1-3 + // refinement done + + //LbmFsgrSolver::performCoarsening(int lev) { + { // PASS 4,5 + bool nbsok; + // WARNING + // now work on modified curr set + const int srcSet = mLevel[lev].setCurr; + const int dstlev = lev+1; + const int dstFineSet = mLevel[dstlev].setCurr; + const bool debugCoarsening = false; + + // PASS 5 test DEBUG + /*if(this->mInitDone) { + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { + // check empty -> from fine conversion + bool changeToFromFine = false; + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ + changeToFromFine=true; } + if(changeToFromFine) { + change = true; + mNumFsgrChanges++; + RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; + 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); + } + } // only check empty cells + }}} // TEST! + } // PASS 5 */ + + // use //template functions for 2D/3D + /*if(strstr(this->getName().c_str(),"Debug")) + if((nbsok)&&(lev+1==mMaxRefine)) { // mixborder + for(int l=0;((l<this->cDirNum) && (nbsok)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT + nbsok=false; + } + } + } // FARBORD */ + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + // from coarse cells without unused nbs are not necessary...! -> remove + // perform check from coarseAdvance here? + if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { + // remove from fine cells now that are completely in fluid + // FIXME? check that new from fine in performRefinement never get deleted here afterwards? + // or more general, one cell never changed more than once? + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + //const CellFlagType notNbAllowed = (CFInter|CFBnd|CFGrFromFine); unused + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + + nbsok = true; + for(int l=0; l<this->cDirNum && nbsok; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; + if( (RFLAG(lev+1, ni,nj,nk, dstFineSet) & reqType) && + (!(RFLAG(lev+1, ni,nj,nk, dstFineSet) & (notAllowed)) ) ){ + // ok + } else { + nbsok=false; + } + // FARBORD + } + // dont turn CFGrFromFine above interface cells into CFGrNorm + // now check nbs on same level + for(int l=1; l<this->cDirNum && nbsok; l++) { + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + if(RFLAG(lev, ni,nj,nk, srcSet)&(CFFluid)) { //ok + } else { + nbsok = false; + } + } // l + + if(nbsok) { + // conversion to coarse fluid cell + change = true; + mNumFsgrChanges++; + RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrNorm; + // dfs are already ok... + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + + // only check complete cubes + for(int dx=-1;dx<=1;dx+=2) { + for(int dy=-1;dy<=1;dy+=2) { + for(int dz=-1*(LBMDIM&1);dz<=1*(LBMDIM&1);dz+=2) { // 2d/3d + // check for norm and from coarse, as the coarse level might just have been refined... + if( + // we now the flag of the current cell! ( RFLAG(lev, i , j , k , srcSet)&(CFGrNorm)) && + ( RFLAG(lev, i+dx, j , k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + + ( RFLAG(lev, i+dx, j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i+dx, j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i , j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && + ( RFLAG(lev, i+dx, j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) + ) { + // middle source node on higher level + int dstx = (2*i)+dx; + int dsty = (2*j)+dy; + int dstz = (2*k)+dz; + + mNumFsgrChanges++; + RFLAG(dstlev, dstx,dsty,dstz, dstFineSet) = CFUnused; + RFLAG(dstlev, dstx,dsty,dstz, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); + + for(int l=1; l<this->cDirNum; l++) { + int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; + if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFFluid)) { + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; + } + if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFInter)) { + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); + this->mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; + } + } // l + + // again check nb flags of all surrounding cells to see if any from coarse + // can be convted to unused + for(int l=1; l<this->cDirNum; l++) { + int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; + // have to be at least from coarse here... + //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" "<< convertCellFlagType2String(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)) ); + if(!(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFUnused) )) { + bool delok = true; + // careful long range here... check domain bounds? + for(int m=1; m<this->cDirNum; m++) { + int chkni=dstni+this->dfVecX[m], chknj=dstnj+this->dfVecY[m], chknk=dstnk+this->dfVecZ[m]; + if(RFLAG(dstlev, chkni,chknj,chknk, dstFineSet)&(CFUnused|CFGrFromCoarse)) { + // this nb cell is ok for deletion + } else { + delok=false; // keep it! + } + //errMsg("performCoarsening"," CHECK "<<PRINT_VEC(dstni,dstnj,dstnk)<<" to "<<PRINT_VEC( chkni,chknj,chknk )<<" f:"<< convertCellFlagType2String( RFLAG(dstlev, chkni,chknj,chknk, dstFineSet))<<" nbsok"<<delok ); + } + //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" ok"<<delok ); + if(delok) { + mNumFsgrChanges++; + RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFUnused; + RFLAG(dstlev, dstni,dstnj,dstnk, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); + } + } + } // l + // treat subcube + //ebugMarkCell(lev,i+dx,j+dy,k+dz); + //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); + } + } } } + + } // ? + } // convert regions of from fine + }}} // TEST! + // PASS 4 */ + + // reinit cell area value + /*if( RFLAG(lev, i,j,k,srcSet) & CFFluid) { + if( RFLAG(lev+1, i*2,j*2,k*2,dstFineSet) & CFGrFromCoarse) { + LbmFloat totArea = mFsgrCellArea[0]; // for l=0 + for(int l=1; l<this->cDirNum; l++) { + int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)& + (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) + ) { + //LbmFloat area = 0.25; if(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 + QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = + QCELL(lev, i,j,k,srcSet, dFlux) = totArea; + } else { + QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = + QCELL(lev, i,j,k,srcSet, dFlux) = 1.0; + } + //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,srcSet, dFlux) ); + } + // */ + + + // PASS 5 org + /*if(strstr(this->getName().c_str(),"Debug")) + if((changeToFromFine)&&(lev+1==mMaxRefine)) { // mixborder + for(int l=0;((l<this->cDirNum) && (changeToFromFine)); l++) { // FARBORD + int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; + if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT + changeToFromFine=false; } + } + }// FARBORD */ + //if(!this->mInitDone) { + for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { + for(int j=1;j<mLevel[lev].lSizey-1;++j) { + for(int i=1;i<mLevel[lev].lSizex-1;++i) { + + + if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { + // check empty -> from fine conversion + bool changeToFromFine = false; + const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); + CellFlagType reqType = CFGrNorm; + if(lev+1==mMaxRefine) reqType = CFNoBndFluid; + + if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && + (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ + // DEBUG + changeToFromFine=true; + } + + // FARBORD + + if(changeToFromFine) { + change = true; + mNumFsgrChanges++; + RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; + if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); + // same as restr from fine func! not necessary ?! + // coarseRestrictFromFine part + } + } // only check empty cells + + }}} // TEST! + //} // init done + // PASS 5 */ + } // coarsening, PASS 4,5 + + if(!this->mSilent){ errMsg("adaptGrid"," for l"<<lev<<" done " ); } + return change; +#endif //! LBM_NOADCOARSENING==1 +} + +/*****************************************************************************/ +//! cell restriction and prolongation +/*****************************************************************************/ + +void LbmFsgrSolver::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int dstSet) +{ +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + i=j=k=srcSet=dstSet=lev =0; // get rid of warnings... +#else + LbmFloat *ccel = RACPNT(lev+1, 2*i,2*j,2*k,srcSet); + LbmFloat *tcel = RACPNT(lev , i,j,k ,dstSet); + + LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; + //LbmFloat *ccel = NULL; + //LbmFloat *tcel = NULL; +#if OPT3D==1 + LbmFloat m[LBM_DFNUM]; + // for macro add + LbmFloat usqr; + //LbmFloat *addfcel, *dstcell; + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; + LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; +#else // OPT3D==true + LbmFloat df[LBM_DFNUM]; + LbmFloat omegaDst, omegaSrc; + LbmFloat feq[LBM_DFNUM]; + LbmFloat dfScale = mDfScaleUp; +#endif // OPT3D==true + +# if OPT3D==0 + // add up weighted dfs + FORDF0{ df[l] = 0.0;} + for(int n=0;(n<this->cDirNum); n++) { + int ni=2*i+1*this->dfVecX[n], nj=2*j+1*this->dfVecY[n], nk=2*k+1*this->dfVecZ[n]; + ccel = RACPNT(lev+1, ni,nj,nk,srcSet);// CFINTTEST + const LbmFloat weight = mGaussw[n]; + FORDF0{ + LbmFloat cdf = weight * RAC(ccel,l); +# if FSGR_STRICT_DEBUG==1 + if( cdf<-1.0 ){ errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]); } +# endif + //errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]<<" = "<<cdf<<" , w"<<weight); + df[l] += cdf; + } + } + + // calc rho etc. from weighted dfs + rho = ux = uy = uz = 0.0; + FORDF0{ + LbmFloat cdf = df[l]; + rho += cdf; + ux += (this->dfDvecX[l]*cdf); + uy += (this->dfDvecY[l]*cdf); + uz += (this->dfDvecZ[l]*cdf); + } + + FORDF0{ feq[l] = this->getCollideEq(l, rho,ux,uy,uz); } + if(mLevel[lev ].lcsmago>0.0) { + 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 ].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; + } +# else // OPT3D + // similar to OPTIMIZED_STREAMCOLLIDE_UNUSED + + //rho = ux = uy = uz = 0.0; + MSRC_C = CCELG_C(0) ; + MSRC_N = CCELG_N(0) ; + MSRC_S = CCELG_S(0) ; + MSRC_E = CCELG_E(0) ; + MSRC_W = CCELG_W(0) ; + MSRC_T = CCELG_T(0) ; + MSRC_B = CCELG_B(0) ; + MSRC_NE = CCELG_NE(0); + MSRC_NW = CCELG_NW(0); + MSRC_SE = CCELG_SE(0); + MSRC_SW = CCELG_SW(0); + MSRC_NT = CCELG_NT(0); + MSRC_NB = CCELG_NB(0); + MSRC_ST = CCELG_ST(0); + MSRC_SB = CCELG_SB(0); + MSRC_ET = CCELG_ET(0); + MSRC_EB = CCELG_EB(0); + MSRC_WT = CCELG_WT(0); + MSRC_WB = CCELG_WB(0); + for(int n=1;(n<this->cDirNum); n++) { + ccel = RACPNT(lev+1, 2*i+1*this->dfVecX[n], 2*j+1*this->dfVecY[n], 2*k+1*this->dfVecZ[n] ,srcSet); + MSRC_C += CCELG_C(n) ; + MSRC_N += CCELG_N(n) ; + MSRC_S += CCELG_S(n) ; + MSRC_E += CCELG_E(n) ; + MSRC_W += CCELG_W(n) ; + MSRC_T += CCELG_T(n) ; + MSRC_B += CCELG_B(n) ; + MSRC_NE += CCELG_NE(n); + MSRC_NW += CCELG_NW(n); + MSRC_SE += CCELG_SE(n); + MSRC_SW += CCELG_SW(n); + MSRC_NT += CCELG_NT(n); + MSRC_NB += CCELG_NB(n); + MSRC_ST += CCELG_ST(n); + MSRC_SB += CCELG_SB(n); + MSRC_ET += CCELG_ET(n); + MSRC_EB += CCELG_EB(n); + MSRC_WT += CCELG_WT(n); + MSRC_WB += CCELG_WB(n); + } + rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T + + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT + + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; + ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW + + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB; + uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW + + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB; + uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB + + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB; + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ + \ + lcsmeq[dC] = EQC ; \ + COLL_CALCULATE_DFEQ(lcsmeq); \ + COLL_CALCULATE_NONEQTENSOR(lev+0, MSRC_ )\ + COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ + COLL_CALCULATE_CSMOMEGAVAL(lev+1, lcsmSrcOmega); \ + \ + 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); + RAC(tcel, dE ) = (lcsmeq[dE ] + (MSRC_E -lcsmeq[dE ] )*lcsmdfscale); + RAC(tcel, dW ) = (lcsmeq[dW ] + (MSRC_W -lcsmeq[dW ] )*lcsmdfscale); + RAC(tcel, dT ) = (lcsmeq[dT ] + (MSRC_T -lcsmeq[dT ] )*lcsmdfscale); + RAC(tcel, dB ) = (lcsmeq[dB ] + (MSRC_B -lcsmeq[dB ] )*lcsmdfscale); + RAC(tcel, dNE) = (lcsmeq[dNE] + (MSRC_NE-lcsmeq[dNE] )*lcsmdfscale); + RAC(tcel, dNW) = (lcsmeq[dNW] + (MSRC_NW-lcsmeq[dNW] )*lcsmdfscale); + RAC(tcel, dSE) = (lcsmeq[dSE] + (MSRC_SE-lcsmeq[dSE] )*lcsmdfscale); + RAC(tcel, dSW) = (lcsmeq[dSW] + (MSRC_SW-lcsmeq[dSW] )*lcsmdfscale); + RAC(tcel, dNT) = (lcsmeq[dNT] + (MSRC_NT-lcsmeq[dNT] )*lcsmdfscale); + RAC(tcel, dNB) = (lcsmeq[dNB] + (MSRC_NB-lcsmeq[dNB] )*lcsmdfscale); + RAC(tcel, dST) = (lcsmeq[dST] + (MSRC_ST-lcsmeq[dST] )*lcsmdfscale); + RAC(tcel, dSB) = (lcsmeq[dSB] + (MSRC_SB-lcsmeq[dSB] )*lcsmdfscale); + RAC(tcel, dET) = (lcsmeq[dET] + (MSRC_ET-lcsmeq[dET] )*lcsmdfscale); + RAC(tcel, dEB) = (lcsmeq[dEB] + (MSRC_EB-lcsmeq[dEB] )*lcsmdfscale); + RAC(tcel, dWT) = (lcsmeq[dWT] + (MSRC_WT-lcsmeq[dWT] )*lcsmdfscale); + RAC(tcel, dWB) = (lcsmeq[dWB] + (MSRC_WB-lcsmeq[dWB] )*lcsmdfscale); +# endif // OPT3D==0 +#endif //! LBM_NOADCOARSENING==1 +} + +void LbmFsgrSolver::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { +#if LBM_NOADCOARSENING==1 + if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); + i=j=k=dstSet=lev =0; // get rid of warnings... + t=0.0; flagSet=0; markNbs=false; +#else + LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; + LbmFloat intDf[19] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + +#if OPT3D==1 + // for macro add + LbmFloat addDfFacT, addVal, usqr; + LbmFloat *addfcel, *dstcell; + LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; + LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; +#endif // OPT3D==true + + // SET required nbs to from coarse (this might overwrite flag several times) + // this is not necessary for interpolateFineFromCoarse + if(markNbs) { + FORDF1{ + 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); + } + } } + + // change flag of cell to be interpolated + RFLAG(lev,i,j,k, dstSet) = flagSet; + mNumInterdCells++; + + // interpolation lines... + int betx = i&1; + int bety = j&1; + int betz = k&1; + + if((!betx) && (!bety) && (!betz)) { + ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2 , 0.0, 1.0); + } + else if(( betx) && (!bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D1); + } + else if((!betx) && ( bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D1); + } + else if((!betx) && (!bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D1); + } + else if(( betx) && ( bety) && (!betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D2); + } + else if((!betx) && ( bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D2); + } + else if(( betx) && (!bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D2); + } + else if(( betx) && ( bety) && ( betz)) { + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D3); + ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D3); + ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2)+1, t, WO1D3); + } + else { + CAUSE_PANIC; + errFatal("interpolateCellFromCoarse","Invalid!?", SIMWORLD_GENERICERROR); + } + + IDF_WRITEBACK; + return; +#endif //! LBM_NOADCOARSENING==1 +} + + + +/*****************************************************************************/ +/*! change the size of the LBM time step */ +/*****************************************************************************/ +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].timestep; + } + //if(mTimeSwitchCounts>0){ errMsg("DEB CSKIP",""); return; } // DEBUG + + const LbmFloat reduceFac = 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 = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity + LbmFloat nextmax = this->mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); + + //newdt = this->mpParam->getTimestep() * (allowMax/nextmax); + LbmFloat newdt = this->mpParam->getTimestep(); // newtr + if(nextmax > allowMax/reduceFac) { + mTimeMaxvelStepCnt++; } + else { mTimeMaxvelStepCnt=0; } + + // emergency, or 10 steps with high vel + if((mTimeMaxvelStepCnt>5) || (nextmax> (1.0/3.0)) || (mForceTimeStepReduce) ) { + //if(nextmax > allowMax/reduceFac) { + newdt = this->mpParam->getTimestep() * reduceFac; + } else { + if(nextmax<allowMax*reduceFac) { + newdt = this->mpParam->getTimestep() / reduceFac; + } + } // newtr + //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<reduceFac<<" simmaxv="<< this->mpParam->getSimulationMaxSpeed() ); + + bool minCutoff = false; + LbmFloat desireddt = newdt; + if(newdt>this->mpParam->getMaxTimestep()){ newdt = this->mpParam->getMaxTimestep(); } + if(newdt<this->mpParam->getMinTimestep()){ + newdt = this->mpParam->getMinTimestep(); + if(nextmax>allowMax/reduceFac){ minCutoff=true; } // only if really large vels... + } + + LbmFloat dtdiff = fabs(newdt - this->mpParam->getTimestep()); + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<this->mpParam->getMaxTimestep()<<" min"<<this->mpParam->getMinTimestep()<<" diff"<<dtdiff<< + " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxTimestep)<<" maxsteps:"<<(mSimulationTime/mMinTimestep) , 10); } + + // in range, and more than X% change? + //if( newdt < this->mpParam->getTimestep() ) // DEBUG + LbmFloat rhoAvg = mCurrentMass/mCurrentVolume; + if( (newdt<=this->mpParam->getMaxTimestep()) && (newdt>=this->mpParam->getMinTimestep()) + && (dtdiff>(this->mpParam->getTimestep()*diffPercent)) ) { + if((newdt>levOldStepsize[mMaxRefine])&&(mTimestepReduceLock)) { + // wait some more... + //debMsgNnl("LbmFsgrSolver::TAdp",DM_NOTIFY," Delayed... "<<mTimestepReduceLock<<" ",10); + debMsgDirect("D"); + } else { + this->mpParam->setDesiredTimestep( newdt ); + rescale = true; + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"\n\n\n\n",10); + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<<newdt<<" old="<<this->mpParam->getTimestep()<<" maxSpeed:"<<this->mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<this->mStepCnt, 10 ); + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< + "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10); + } + } // really change dt + } + + if(mTimestepReduceLock>0) mTimestepReduceLock--; + + + // forced back and forth switchting (for testing) + /*const int tadtogInter = 100; + const double tadtogSwitch = 0.66; + errMsg("TIMESWITCHTOGGLETEST","warning enabled "<< tadtogSwitch<<","<<tadtogSwitch<<" !!!!!!!!!!!!!!!!!!!"); + if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || + ((this->mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ + rescale = true; minCutoff = false; + newdt = tadtogSwitch * this->mpParam->getTimestep(); + this->mpParam->setDesiredTimestep( newdt ); + } else + if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || + ((this->mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ + rescale = true; minCutoff = false; + newdt = this->mpParam->getTimestep()/tadtogSwitch ; + this->mpParam->setDesiredTimestep( newdt ); + } else { + rescale = false; minCutoff = false; + } + // */ + + // test mass rescale + + scaleFac = newdt/this->mpParam->getTimestep(); + if(rescale) { + // perform acutal rescaling... + mTimeMaxvelStepCnt=0; + mForceTimeStepReduce = false; + + // FIXME - approximate by averaging, take gravity direction here? + mTimestepReduceLock = 4*(mLevel[mMaxRefine].lSizey+mLevel[mMaxRefine].lSizez+mLevel[mMaxRefine].lSizex)/3; + + mTimeSwitchCounts++; + this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent ); + recalculateObjectSpeeds(); + // calc omega, force for all levels + mLastOmega=1e10; mLastGravity=1e10; + initLevelOmegas(); + if(this->mpParam->getTimestep()<mMinTimestep) mMinTimestep = this->mpParam->getTimestep(); + if(this->mpParam->getTimestep()>mMaxTimestep) mMaxTimestep = this->mpParam->getTimestep(); + + // this might be called during init, before we have any particles + if(mpParticles) { mpParticles->adaptPartTimestep(scaleFac); } +#if LBM_INCLUDE_TESTSOLVERS==1 + if((mUseTestdata)&&(mpTest)) { + mpTest->adaptTimestep(scaleFac, mLevel[mMaxRefine].omega, mLevel[mMaxRefine].timestep, vec2L( mpParam->calculateGravity(mSimulationTime)) ); + mpTest->mGrav3d = mLevel[mMaxRefine].gravity; + } +#endif // LBM_INCLUDE_TESTSOLVERS!=1 + + for(int lev=mMaxRefine; lev>=0 ; lev--) { + LbmFloat newSteptime = mLevel[lev].timestep; + LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); + + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<<lev<<" Timestep change: "<< + " scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10); + } + if(lev!=mMaxRefine) coarseCalculateFluxareas(lev); + + int wss = 0, wse = 1; + // only change currset (necessary for compressed grids, better for non-compr.gr.) + wss = wse = mLevel[lev].setCurr; + for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT + // warning - check sets for higher levels...? + FSGR_FORIJK1(lev) { + if( (RFLAG(lev,i,j,k, workSet) & CFBndMoving) ) { + /* + // paranoid check - shouldnt be necessary! + if(QCELL(lev, i, j, k, workSet, dFlux)!=mSimulationTime) { + errMsg("TTTT","found invalid bnd cell.... removing at "<<PRINT_IJK); + RFLAG(lev,i,j,k, workSet) = CFInter; + // init empty zero vel interface cell... + initVelocityCell(lev, i,j,k, CFInter, 1.0, 0.01, LbmVec(0.) ); + } else {// */ + for(int l=0; l<this->cDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = QCELL(lev, i, j, k, workSet, l)* scaleFac; + } + //} // ok + continue; + } + if( + (RFLAG(lev,i,j,k, workSet) & CFFluid) || + (RFLAG(lev,i,j,k, workSet) & CFInter) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || + (RFLAG(lev,i,j,k, workSet) & CFGrNorm) + ) { + // these cells have to be scaled... + } else { + continue; + } + + // collide on current set + LbmFloat rhoOld; + LbmVec velOld; + LbmFloat rho, ux,uy,uz; + rho=0.0; ux = uy = uz = 0.0; + for(int l=0; l<this->cDfNum; l++) { + LbmFloat m = QCELL(lev, i, j, k, workSet, l); + rho += m; + ux += (this->dfDvecX[l]*m); + uy += (this->dfDvecY[l]*m); + uz += (this->dfDvecZ[l]*m); + } + rhoOld = rho; + velOld = LbmVec(ux,uy,uz); + + LbmFloat rhoNew = (rhoOld-rhoAvg)*scaleFac +rhoAvg; + LbmVec velNew = velOld * scaleFac; + + LbmFloat df[LBM_DFNUM]; + LbmFloat feqOld[LBM_DFNUM]; + LbmFloat feqNew[LBM_DFNUM]; + for(int l=0; l<this->cDfNum; l++) { + feqOld[l] = this->getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); + feqNew[l] = this->getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); + df[l] = QCELL(lev, i,j,k,workSet, l); + } + const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feqOld); + const LbmFloat oldOmega = this->getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); + const LbmFloat newOmega = this->getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); + //newOmega = mLevel[lev].omega; // FIXME debug test + + //LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); + const LbmFloat dfScale = (newSteptime/newOmega)/(levOldStepsize[lev]/oldOmega); + //dfScale = dfScaleFac/newOmega; + + for(int l=0; l<this->cDfNum; l++) { + // org scaling + //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important + // new scaling + LbmFloat dfn = feqNew[l] + (df[l]-feqOld[l])*dfScale*feqNew[l]/feqOld[l]; // non-eq. scaling, important + //df = eqNew + (df-eqOld)*dfScale; // modified ig scaling, no real difference? + QCELL(lev, i,j,k,workSet, l) = dfn; + } + + if(RFLAG(lev,i,j,k, workSet) & CFInter) { + //if(workSet==mLevel[lev].setCurr) + LbmFloat area = 1.0; + if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux); + massTOld += QCELL(lev, i,j,k,workSet, dMass) * area; + volTOld += QCELL(lev, i,j,k,workSet, dFfrac); + + // wrong... QCELL(i,j,k,workSet, dMass] = (QCELL(i,j,k,workSet, dFfrac]*rhoNew); + QCELL(lev, i,j,k,workSet, dMass) = (QCELL(lev, i,j,k,workSet, dMass)/rhoOld*rhoNew); + QCELL(lev, i,j,k,workSet, dFfrac) = (QCELL(lev, i,j,k,workSet, dMass)/rhoNew); + + //if(workSet==mLevel[lev].setCurr) + massTNew += QCELL(lev, i,j,k,workSet, dMass); + volTNew += QCELL(lev, i,j,k,workSet, dFfrac); + } + if(RFLAG(lev,i,j,k, workSet) & CFFluid) { // DEBUG + if(RFLAG(lev,i,j,k, workSet) & (CFGrFromFine|CFGrFromCoarse)) { // DEBUG + // dont include + } else { + LbmFloat area = 1.0; + if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux) * mLevel[lev].lcellfactor; + //if(workSet==mLevel[lev].setCurr) + massTOld += rhoOld*area; + //if(workSet==mLevel[lev].setCurr) + massTNew += rhoNew*area; + volTOld += area; + volTNew += area; + } + } + + } // IJK + } // workSet + + } // lev + + if(!this->mSilent) { + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<this->mStepCnt<< + " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxTimestep<< + " mindt"<<mMinTimestep<<" currdt"<<mLevel[mMaxRefine].timestep, 10); + debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE masst:"<<massTNew<<","<<massTOld<<" org:"<<mCurrentMass<<"; "<< + " volt:"<<volTNew<<","<<volTOld<<" org:"<<mCurrentVolume, 10); + } else { + debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep change by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt + <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<this->mOmega<<" gStar:"<<this->mpParam->getCurrentGStar() , 10); + } + } // rescale? + //NEWDEBCHECK("tt2"); + + //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG + if(minCutoff) { + errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<this->mName<<" step:"<<this->mStepCnt<<" newdt="<<desireddt<<" mindt="<<this->mpParam->getMinTimestep()<<") " ); + //brute force resacle all the time? + + for(int lev=mMaxRefine; lev>=0 ; lev--) { + int rescs=0; + int wss = 0, wse = 1; +#if COMPRESSGRIDS==1 + if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; +#endif // COMPRESSGRIDS==1 + for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT + //for(int workSet = 0; workSet<=1; workSet++) { + FSGR_FORIJK1(lev) { + + //if( (RFLAG(lev, i,j,k, workSet) & CFFluid) || (RFLAG(lev, i,j,k, workSet) & CFInter) ) { + if( + (RFLAG(lev,i,j,k, workSet) & CFFluid) || + (RFLAG(lev,i,j,k, workSet) & CFInter) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || + (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || + (RFLAG(lev,i,j,k, workSet) & CFGrNorm) + ) { + // these cells have to be scaled... + } else { + continue; + } + + // collide on current set + LbmFloat rho, ux,uy,uz; + rho=0.0; ux = uy = uz = 0.0; + for(int l=0; l<this->cDfNum; l++) { + LbmFloat m = QCELL(lev, i, j, k, workSet, l); + rho += m; + ux += (this->dfDvecX[l]*m); + uy += (this->dfDvecY[l]*m); + uz += (this->dfDvecZ[l]*m); + } +#ifndef WIN32 + if (!finite(rho)) { + errMsg("adaptTimestep","Brute force non-finite rho at"<<PRINT_IJK); // DEBUG! + rho = 1.0; + ux = uy = uz = 0.0; + QCELL(lev, i, j, k, workSet, dMass) = 1.0; + QCELL(lev, i, j, k, workSet, dFfrac) = 1.0; + } +#endif // WIN32 + + if( (ux*ux+uy*uy+uz*uz)> (allowMax*allowMax) ) { + LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); + ux *= cfac; + uy *= cfac; + uz *= cfac; + for(int l=0; l<this->cDfNum; l++) { + QCELL(lev, i, j, k, workSet, l) = this->getCollideEq(l, rho, ux,uy,uz); } + rescs++; + debMsgDirect("B"); + } + + } } + //if(rescs>0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } + debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"<<lev<<" rescs:"<<rescs, 1); + //TTT mNumProblems += rescs; // add to problem display... + } // lev,set,ijk + + } // try brute force rescale? + + // time adap done... +} + + + diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h index b24183411ef..10b172dde4b 100644 --- a/intern/elbeem/intern/solver_class.h +++ b/intern/elbeem/intern/solver_class.h @@ -208,8 +208,15 @@ class LbmFsgrSolver : 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(); + + // multi step solver init + /*! finish the init with config file values (allocate arrays...) */ + virtual bool initializeSolverMemory(); + /*! init solver arrays */ + virtual bool initializeSolverGrids(); + /*! prepare actual simulation start, setup viz etc */ + virtual bool initializeSolverPostinit(); + //! notify object that dump is in progress (e.g. for field dump) virtual void notifySolverOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename); @@ -338,6 +345,8 @@ class LbmFsgrSolver : //! use time adaptivity? bool mTimeAdap; + //! force smaller timestep for next LBM step? (eg for mov obj) + bool mForceTimeStepReduce; //! fluid vol height LbmFloat mFVHeight; @@ -395,6 +404,12 @@ class LbmFsgrSolver : vector<LbmVec> mObjectSpeeds; //! partslip bc. values for obstacle boundary conditions vector<LbmFloat> mObjectPartslips; + //! moving object mass boundary condition values + vector<LbmFloat> mObjectMassMovnd; + + //! permanent movobj vert storage + vector<ntlVec3Gfx> mMOIVertices; + vector<ntlVec3Gfx> mMOIVerticesOld; //! get isofield weights int mIsoWeightMethod; @@ -459,9 +474,12 @@ class LbmFsgrSolver : void destroyTestdata(); void handleTestdata(); void set3dHeight(int ,int ); + + void initCpdata(); + void handleCpdata(); public: - // needed from testdata - void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat *retux, LbmFloat *retuy); + // needed for testdata + void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat *retux, LbmFloat *retuy, LbmFloat *retuz); #endif // LBM_INCLUDE_TESTSOLVERS==1 public: // former LbmModelLBGK functions @@ -473,7 +491,9 @@ class LbmFsgrSolver : 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); + LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, + LbmFloat omega, LbmVec gravity, LbmFloat csmago, + LbmFloat *newOmegaRet, LbmFloat *newQoRet); // former LBM models diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp index a417c33caa9..908355fdb13 100644 --- a/intern/elbeem/intern/solver_init.cpp +++ b/intern/elbeem/intern/solver_init.cpp @@ -13,6 +13,10 @@ // for geo init FGI_ defines #include "elbeem.h" +// all boundary types at once +#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW ) + + /*****************************************************************************/ //! common variables @@ -296,7 +300,7 @@ LbmFsgrSolver::LbmFsgrSolver() : mNumProblems(0), mAvgMLSUPS(0.0), mAvgMLSUPSCnt(0.0), mpPreviewSurface(NULL), - mTimeAdap(true), + mTimeAdap(true), mForceTimeStepReduce(false), mFVHeight(0.0), mFVArea(1.0), mUpdateFVHeight(false), mInitSurfaceSmoothing(0), mTimestepReduceLock(0), @@ -305,11 +309,13 @@ LbmFsgrSolver::LbmFsgrSolver() : mMinTimestep(0.0), mMaxTimestep(0.0), mMaxNoCells(0), mMinNoCells(0), mAvgNumUsedCells(0), mDropMode(1), mDropSize(0.15), mDropSpeed(0.0), - mObjectSpeeds(), mObjectPartslips(), + mObjectSpeeds(), mObjectPartslips(), mObjectMassMovnd(), + mMOIVertices(), mMOIVerticesOld(), mIsoWeightMethod(1), mMaxRefine(1), mDfScaleUp(-1.0), mDfScaleDown(-1.0), - mInitialCsmago(0.04), mDebugOmegaRet(0.0), + mInitialCsmago(0.03), // set to 0.02 for mMaxRefine==0 below + mDebugOmegaRet(0.0), mLastOmega(1e10), mLastGravity(1e10), mNumInvIfTotal(0), mNumFsgrChanges(0), mDisableStandingFluidInit(0), @@ -450,16 +456,6 @@ void LbmFsgrSolver::parseAttrList() this->mSmoothSurface = this->mpAttrs->readFloat("smoothsurface", this->mSmoothSurface, "SimulationLbm","mSmoothSurface", false ); this->mSmoothNormals = this->mpAttrs->readFloat("smoothnormals", this->mSmoothNormals, "SimulationLbm","mSmoothNormals", false ); - mInitialCsmago = this->mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); - // deprecated! - float mInitialCsmagoCoarse = 0.0; - mInitialCsmagoCoarse = 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); - mInitialCsmago = 0.0; -#endif // USE_LES==1 - // refinement mMaxRefine = this->mRefinementDesired; mMaxRefine = this->mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false); @@ -481,12 +477,24 @@ void LbmFsgrSolver::parseAttrList() mUseTestdata=1; // DEBUG #endif // ELBEEM_PLUGIN errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" "); + #else // LBM_INCLUDE_TESTSOLVERS!=1 // off by default mUseTestdata = 0; if(mFarFieldSize>=2.) mUseTestdata=1; // equiv. to test solver check - if(mUseTestdata) { mMaxRefine=0; } // force fsgr off #endif // LBM_INCLUDE_TESTSOLVERS!=1 + if(mUseTestdata) { mMaxRefine=0; } // force fsgr off + + if(mMaxRefine==0) mInitialCsmago=0.02; + mInitialCsmago = this->mpAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false ); + // deprecated! + float mInitialCsmagoCoarse = 0.0; + 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); + mInitialCsmago = 0.0; +#endif // USE_LES==1 } @@ -571,7 +579,9 @@ void LbmFsgrSolver::initLevelOmegas() /****************************************************************************** * Init Solver (values should be read from config file) *****************************************************************************/ -bool LbmFsgrSolver::initializeSolver() + +/*! finish the init with config file values (allocate arrays...) */ +bool LbmFsgrSolver::initializeSolverMemory() { debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<this->mInitDone<<" "<<(void*)this,1); @@ -597,7 +607,7 @@ bool LbmFsgrSolver::initializeSolver() calculateMemreqEstimate( this->mSizex, this->mSizey, this->mSizez, mMaxRefine, &memEstFromFunc, &memreqStr ); double memLimit; - if(sizeof(int)==4) { + if(sizeof(void*)==4) { // 32bit system, limit to 2GB memLimit = 2.0* 1024.0*1024.0*1024.0; } else { @@ -619,6 +629,7 @@ bool LbmFsgrSolver::initializeSolver() this->mPreviewFactor = (LbmFloat)this->mOutputSurfacePreview / (LbmFloat)this->mSizex; debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<this->mSizex<<" Y:"<<this->mSizey<<" Z:"<<this->mSizez<< ", Domain: "<<this->mvGeoStart<<":"<<this->mvGeoEnd<<", "<<(this->mvGeoEnd-this->mvGeoStart)<< + ", Intbytes: "<< sizeof(void*) << ", est. Mem.Req.: "<<memreqStr ,2); this->mpParam->setSize(this->mSizex, this->mSizey, this->mSizez); @@ -835,10 +846,43 @@ bool LbmFsgrSolver::initializeSolver() } } + if(LBMDIM==2) { + if(this->mOutputSurfacePreview) { + errMsg("LbmFsgrSolver::init","No preview in 2D allowed!"); + this->mOutputSurfacePreview = 0; } + } +#if LBM_USE_GUI==1 + if(this->mOutputSurfacePreview) { + errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0"); + this->mOutputSurfacePreview = 0; } +#endif // LBM_USE_GUI==1 + if(this->mOutputSurfacePreview) { + // same as normal one, but use reduced size + mpPreviewSurface = new IsoSurface( this->mIsoValue ); + mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() ); + 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 = 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*this->mSizex)<<","<<(pfac*this->mSizey)<<","<<(pfac*this->mSizez)<<" enabled",10); + } + // init defaults mAvgNumUsedCells = 0; this->mFixMass= 0.0; + return true; +} +/*! init solver arrays */ +bool LbmFsgrSolver::initializeSolverGrids() { /* init boundaries */ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Boundary init...",10); // init obstacles, and reinit time step size @@ -919,6 +963,8 @@ bool LbmFsgrSolver::initializeSolver() } // Symmetry tests */ + //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal1, causing panic, aborting..."); return false; } + // prepare interface cells initFreeSurfaces(); initStandingFluidGradient(); @@ -956,9 +1002,12 @@ bool LbmFsgrSolver::initializeSolver() } } #endif // ELBEEM_PLUGIN!=1 - + return true; +} - // ---------------------------------------------------------------------- + +/*! prepare actual simulation start, setup viz etc */ +bool LbmFsgrSolver::initializeSolverPostinit() { // coarsen region myTime_t fsgrtstart = getTime(); for(int lev=mMaxRefine-1; lev>=0; lev--) { @@ -991,38 +1040,8 @@ bool LbmFsgrSolver::initializeSolver() } } // first copy flags */ - - if(LBMDIM==2) { - if(this->mOutputSurfacePreview) { - errMsg("LbmFsgrSolver::init","No preview in 2D allowed!"); - this->mOutputSurfacePreview = 0; } - } -#if LBM_USE_GUI==1 - if(this->mOutputSurfacePreview) { - errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0"); - this->mOutputSurfacePreview = 0; } -#endif // LBM_USE_GUI==1 - - if(this->mOutputSurfacePreview) { - - // same as normal one, but use reduced size - mpPreviewSurface = new IsoSurface( this->mIsoValue ); - mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() ); - 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 = 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*this->mSizex)<<","<<(pfac*this->mSizey)<<","<<(pfac*this->mSizez)<<" enabled",10); - } - + // old mpPreviewSurface init + //if(getGlobalBakeState()<0) { CAUSE_PANIC; errMsg("LbmFsgrSolver::initialize","Got abort signal2, causing panic, aborting..."); return false; } // make sure fill fracs are right for first surface generation stepMain(); @@ -1036,11 +1055,12 @@ bool LbmFsgrSolver::initializeSolver() // now really done... - debugOut("LbmFsgrSolver::initialize : SurfaceGen: SmsOrg("<<this->mSmoothSurface<<","<<this->mSmoothNormals<<","<<featureSize<<"), Iso("<<this->mpIso->getSmoothSurface()<<","<<this->mpIso->getSmoothNormals()<<") ",10); + debugOut("LbmFsgrSolver::initialize : SurfaceGen: SmsOrg("<<this->mSmoothSurface<<","<<this->mSmoothNormals<< /*","<<featureSize<<*/ "), Iso("<<this->mpIso->getSmoothSurface()<<","<<this->mpIso->getSmoothNormals()<<") ",10); debugOut("LbmFsgrSolver::initialize : Init done ... ",10); this->mInitDone = 1; #if LBM_INCLUDE_TESTSOLVERS==1 + initCpdata(); initTestdata(); #endif // ELBEEM_PLUGIN!=1 // not inited? dont use... @@ -1052,14 +1072,54 @@ bool LbmFsgrSolver::initializeSolver() +// macros for mov obj init +#if LBMDIM==2 + +#define POS2GRID_CHECK(vec,n) \ + monTotal++;\ + const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ + if(i<=0) continue; \ + if(i>=mLevel[level].lSizex-1) continue; \ + const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ + if(j<=0) continue; \ + if(j>=mLevel[level].lSizey-1) continue; \ + const int k=0; \ + +#else // LBMDIM -> 3 +#define POS2GRID_CHECK(vec,n) \ + monTotal++;\ + const int i=(int)( ((vec)[n][0]-iniPos[0])/dvec[0] +0.0); \ + if(i<=0) continue; \ + if(i>=mLevel[level].lSizex-1) continue; \ + const int j=(int)( ((vec)[n][1]-iniPos[1])/dvec[1] +0.0); \ + if(j<=0) continue; \ + if(j>=mLevel[level].lSizey-1) continue; \ + const int k=(int)( ((vec)[n][2]-iniPos[2])/dvec[2] +0.0); \ + if(k<=0) continue; \ + if(k>=mLevel[level].lSizez-1) continue; \ + +#endif // LBMDIM + +// calculate object velocity from vert arrays in objvel vec +#define OBJVEL_CALC \ + LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { \ + const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; \ + USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); \ + if(usqr>maxusqr) { \ + /* cutoff at maxVelVal */ \ + for(int jj=0; jj<3; jj++) { \ + if(objvel[jj]>0.) objvel[jj] = maxVelVal; \ + if(objvel[jj]<0.) objvel[jj] = -maxVelVal; \ + } \ + } } /*****************************************************************************/ //! init moving obstacles for next sim step sim /*****************************************************************************/ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { - myTime_t monstart = getTime(); - // new test + + // movobj init const int level = mMaxRefine; const int workSet = mLevel[level].setCurr; LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime! @@ -1072,6 +1132,9 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime,10); //if(mSimulationTime!=mLastSimTime) errMsg("LbmFsgrSolver::initMovingObstacles","time: "<<mSimulationTime<<" lasttt:"<<mLastSimTime); + const LbmFloat maxVelVal = 0.1666; + const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; + LbmFloat rhomass = 0.0; CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs! CellFlagType ntype = CFInvalid; @@ -1088,30 +1151,53 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { //iniPos[2] = this->mvGeoStart[2] + dvec[2]*getForZMin1(); } + if( (int)mObjectMassMovnd.size() < numobjs) { + for(int i=mObjectMassMovnd.size(); i<numobjs; i++) { + mObjectMassMovnd.push_back(0.); + } + } + // stats int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0; - CellFlagType nbflag[LBM_DFNUM]; int nbored; - vector<ntlVec3Gfx> vertices; - vector<ntlVec3Gfx> verticesOld; - int i,j,k; // grid pos init - LbmFloat ux,uy,uz, rho; for(int OId=0; OId<numobjs; OId++) { ntlGeometryObject *obj = (*this->mpGiObjects)[OId]; - if( (!staticInit) && (!obj->getIsAnimated()) ) continue; - if( ( staticInit) && ( obj->getIsAnimated()) ) continue; + bool skip = false; + if(obj->getGeoInitId() != this->mLbmInitId) skip=true; + if( (!staticInit) && (!obj->getIsAnimated()) ) skip=true; + if( ( staticInit) && ( obj->getIsAnimated()) ) skip=true; + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" skip:"<<skip<<", static:"<<staticInit<<" anim:"<<obj->getIsAnimated()<<" gid:"<<obj->getGeoInitId()<<" simgid:"<<this->mLbmInitId, 10); + if(skip) continue; - if(obj->getGeoInitType()&FGI_ALLBOUNDS) { + if( (obj->getGeoInitType()&FGI_ALLBOUNDS) || + (obj->getGeoInitType()&FGI_FLUID) && staticInit ) { otype = ntype = CFInvalid; switch(obj->getGeoInitType()) { case FGI_BNDPART: case FGI_BNDFREE: - errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() ); - case FGI_BNDNO: - rhomass = BND_FILL; + if(!staticInit) { + errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() ); + otype = ntype = CFBnd|CFBndNoslip; + } else { + if(obj->getGeoInitType()==FGI_BNDPART) otype = ntype = CFBnd|CFBndPartslip; + if(obj->getGeoInitType()==FGI_BNDFREE) otype = ntype = CFBnd|CFBndFreeslip; + } + break; + /* + case FGI_BNDPART: rhomass = BND_FILL; + otype = ntype = CFBnd|CFBndPartslip; + break; + case FGI_BNDFREE: rhomass = BND_FILL; + otype = ntype = CFBnd|CFBndFreeslip; + break; + // */ + case FGI_BNDNO: rhomass = BND_FILL; otype = ntype = CFBnd|CFBndNoslip; break; + case FGI_FLUID: + otype = ntype = CFFluid; + break; case FGI_MBNDINFLOW: otype = ntype = CFMbndInflow; break; @@ -1123,23 +1209,35 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { int active = ((obj->getGeoActive(targetTime)>0.)? 1:0); //errMsg("GEOACTT"," obj "<<obj->getName()<<" a:"<<active<<","<<wasActive<<" s"<<sourceTime<<" t"<<targetTime <<" v"<<mObjectSpeeds[OId] ); // skip inactive in/out flows + if(ntype==CFInvalid){ errMsg("LbmFsgrSolver::initMovingObstacles","Invalid obj type "<<obj->getGeoInitType()); continue; } if((!active) && (otype&(CFMbndOutflow|CFMbndInflow)) ) continue; // copied from recalculateObjectSpeeds mObjectSpeeds[OId] = vec2L(this->mpParam->calculateLattVelocityFromRw( vec2P( (*this->mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ))); debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*this->mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 ); - vertices.clear(); - obj->getMovingPoints(vertices); - verticesOld = vertices; - // WARNING - assumes mSimulationTime is global!? - obj->applyTransformation(targetTime, &vertices,NULL, 0, vertices.size(), false ); - monTrafo += vertices.size(); - - // correct flags from last position, but extrapolate - // velocity to next timestep - obj->applyTransformation(sourceTime, &verticesOld,NULL, 0, verticesOld.size(), false ); - monTrafo += verticesOld.size(); + mMOIVertices.clear(); + if(obj->getMeshAnimated()) { + // do two full update + mMOIVerticesOld.clear(); + obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, mLevel[mMaxRefine].nodeSize, this->mvGeoStart, this->mvGeoEnd); + monTrafo += mMOIVerticesOld.size(); + obj->applyTransformation(sourceTime, &mMOIVerticesOld,NULL, 0, mMOIVerticesOld.size(), false ); + monTrafo += mMOIVertices.size(); + obj->applyTransformation(targetTime, &mMOIVertices,NULL, 0, mMOIVertices.size(), false ); + } else { + // only do transform update + obj->getMovingPoints(mMOIVertices); + mMOIVerticesOld = mMOIVertices; + // WARNING - assumes mSimulationTime is global!? + obj->applyTransformation(targetTime, &mMOIVertices,NULL, 0, mMOIVertices.size(), false ); + monTrafo += mMOIVertices.size(); + + // correct flags from last position, but extrapolate + // velocity to next timestep + obj->applyTransformation(sourceTime, &mMOIVerticesOld,NULL, 0, mMOIVerticesOld.size(), false ); + monTrafo += mMOIVerticesOld.size(); + } // object types if(ntype&CFBnd){ @@ -1153,144 +1251,189 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { 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 + if(obj->getMeshAnimated()) { ntype |= CFBndMoving; otype |= CFBndMoving; } + CellFlagType rflagnb[27]; + LbmFloat massCheck = 0.; + int massReinits=0; + bool fillCells = (mObjectMassMovnd[OId]<=-1.); + LbmFloat massCScale; //, massCScalePos, massCScaleNeg; + //if(mInitialMass>0.) { + //massCScale = (mInitialMass-mObjectMassMovnd[OId])/mInitialMass; + massCScale = 1.-(mObjectMassMovnd[OId]/(LbmFloat)(mMOIVertices.size()/10) ); + //massCScalePos = MIN(massCScale,1.); + //massCScaleNeg = MAX(massCScale,1.); + //} else { + //massCScale = massCScalePos = massCScaleNeg = 1.; + //} // first pass - set new obs. cells if(active) { - for(size_t n=0; n<vertices.size(); n++) { - //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK); - POS2GRID(vertices,n); - CHECKIJK; - //if(i==30 && j==14) { errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<" "); } - if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue; - monPoints++; - LbmVec u= vec2L((vertices[n]-verticesOld[n]) /dvec); // * timeFac; - RFLAG(level, i,j,k, workSet) = ntype; - FORDF1 { - CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l); - if(flag&(CFFluid|CFInter)) { - flag &= (~CFNoBndFluid); // remove CFNoBndFluid flag - RFLAG_NB(level, i,j,k,workSet,l) &= flag; + for(size_t n=0; n<mMOIVertices.size(); n++) { + //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK); + POS2GRID_CHECK(mMOIVertices,n); + //if(i==30 && j==14) { errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK<<" "); } + if(QCELL(level, i,j,k, workSet, dFlux)==targetTime) continue; + monPoints++; + + // check mass + if(RFLAG(level, i,j,k, workSet)&(CFFluid)) { + FORDF0 { + massCheck -= QCELL(level, i,j,k, workSet, l); + } + massReinits++; } - } - LbmFloat *dstCell = RACPNT(level, i,j,k,workSet); - RAC(dstCell,0) = 0.0; - if(ntype&CFBndMoving) { - //if(i==30 && j==14) { errMsg("AAABB","OId"<<OId<<" move "<<u); } - // movement? + if(RFLAG(level, i,j,k, workSet)&(CFInter)) { + massCheck -= QCELL(level, i,j,k, workSet, dMass); + massReinits++; + } + + RFLAG(level, i,j,k, workSet) = ntype; FORDF1 { - // TODO optimize, test rho calc necessary? - // calculate destination density - LbmFloat *dfs = &QCELL_NB(level, i,j,k,workSet,l,dC); - rho = RAC(dfs,dC); - for(int nl=0; nl<this->cDfNum; nl++) rho += RAC(dfs,nl); - //rho = 1.0; - const LbmFloat factor = 2.0*this->dfLength[l]*rho* 3.0; - ux = this->dfDvecX[l]*u[0]; - uy = this->dfDvecY[l]*u[1]; - uz = this->dfDvecZ[l]*u[2]; - const LbmFloat usqr = (ux*ux+uy*uy+uz*uz)*1.5; - USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); - //ux=uy=uz=0.0; // DEBUG - RAC(dstCell,l) = factor*(ux+uy+uz); + //CellFlagType flag = RFLAG_NB(level, i,j,k,workSet,l); + rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l); + if(rflagnb[l]&(CFFluid|CFInter)) { + rflagnb[l] &= (~CFNoBndFluid); // remove CFNoBndFluid flag + RFLAG_NB(level, i,j,k,workSet,l) &= rflagnb[l]; + } } - } else { - FORDF1 { RAC(dstCell,l) = 0.0; } - } - //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" u"<<u<<" ul"<<PRINT_VEC(ux,uy,uz) ); - RAC(dstCell, dFlux) = targetTime; - monObsts++; - } } // bnd, is active? + LbmFloat *dstCell = RACPNT(level, i,j,k,workSet); + RAC(dstCell,0) = 0.0; + if(ntype&CFBndMoving) { + OBJVEL_CALC; + //LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); // * timeFac; + //const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; + //USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); + //if(usqr>maxusqr) { + // cutoff at maxVelVal + //for(int jj=0; jj<3; jj++) { + //if(objvel[jj]>0.) objvel[jj] = maxVelVal; + //if(objvel[jj]<0.) objvel[jj] = -maxVelVal; + //} + //} + //objvel[0]=objvel[1]=objvel[2]=0.0; // DEBUG + + // compute fluid acceleration + FORDF1 { + if(rflagnb[l]&(CFFluid|CFInter)) { + const LbmFloat ux = this->dfDvecX[l]*objvel[0]; + const LbmFloat uy = this->dfDvecY[l]*objvel[1]; + const LbmFloat uz = this->dfDvecZ[l]*objvel[2]; + LbmFloat factor = 1.2*this->dfLength[l]* 3.0 *(ux+uy+uz); // rhoTest, dont multiply by density... + //if(factor>0.) factor *= massCScalePos; + //else factor *= massCScaleNeg; + //if(ntype&CFBndFreeslip) { factor=0.; } // FIXME! + RAC(dstCell,l) = factor; + massCheck += RAC(dstCell,l); + } else { + RAC(dstCell,l) = 0.; + } + } + } else { + FORDF1 { RAC(dstCell,l) = 0.0; } + } + //errMsg("AAABB","OId"<<OId<<" n"<<n<<" -> "<<PRINT_IJK" objvel"<<objvel<<" ul"<<PRINT_VEC(ux,uy,uz) ); + RAC(dstCell, dFlux) = targetTime; + monObsts++; + } // points + } // bnd, is active? // second pass, remove old ones if(wasActive) { - for(size_t n=0; n<verticesOld.size(); n++) { - POS2GRID(verticesOld,n); - CHECKIJK; - monPoints++; - if((RFLAG(level, i,j,k, workSet) == otype) && - (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) { - //? unused ntlVec3Gfx u= (vertices[n]-verticesOld[n]); - // from mainloop - nbored = 0; -#if OPT3D==0 - FORDF1 { - nbflag[l] = RFLAG_NB(level, i,j,k,workSet,l); - nbored |= nbflag[l]; - } -#else - const CellFlagType *pFlagCheck = &RFLAG(level, i,j,k,workSet); // omp - nbflag[dSB] = *(pFlagCheck + (-mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= nbflag[dSB]; - nbflag[dWB] = *(pFlagCheck + (-mLevel[level].lOffsy+-1)); nbored |= nbflag[dWB]; - nbflag[ dB] = *(pFlagCheck + (-mLevel[level].lOffsy)); nbored |= nbflag[dB]; - nbflag[dEB] = *(pFlagCheck + (-mLevel[level].lOffsy+ 1)); nbored |= nbflag[dEB]; - nbflag[dNB] = *(pFlagCheck + (-mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= nbflag[dNB]; - - nbflag[dSW] = *(pFlagCheck + (-mLevel[level].lOffsx+-1)); nbored |= nbflag[dSW]; - nbflag[ dS] = *(pFlagCheck + (-mLevel[level].lOffsx)); nbored |= nbflag[dS]; - nbflag[dSE] = *(pFlagCheck + (-mLevel[level].lOffsx+ 1)); nbored |= nbflag[dSE]; - - nbflag[ dW] = *(pFlagCheck + (-1)); nbored |= nbflag[dW]; - nbflag[ dE] = *(pFlagCheck + ( 1)); nbored |= nbflag[dE]; - - nbflag[dNW] = *(pFlagCheck + ( mLevel[level].lOffsx+-1)); nbored |= nbflag[dNW]; - nbflag[ dN] = *(pFlagCheck + ( mLevel[level].lOffsx)); nbored |= nbflag[dN]; - nbflag[dNE] = *(pFlagCheck + ( mLevel[level].lOffsx+ 1)); nbored |= nbflag[dNE]; - - nbflag[dST] = *(pFlagCheck + ( mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= nbflag[dST]; - nbflag[dWT] = *(pFlagCheck + ( mLevel[level].lOffsy+-1)); nbored |= nbflag[dWT]; - nbflag[ dT] = *(pFlagCheck + ( mLevel[level].lOffsy)); nbored |= nbflag[dT]; - nbflag[dET] = *(pFlagCheck + ( mLevel[level].lOffsy+ 1)); nbored |= nbflag[dET]; - nbflag[dNT] = *(pFlagCheck + ( mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= nbflag[dNT]; - // */ + for(size_t n=0; n<mMOIVerticesOld.size(); n++) { + POS2GRID_CHECK(mMOIVerticesOld,n); + monPoints++; + if((RFLAG(level, i,j,k, workSet) == otype) && + (QCELL(level, i,j,k, workSet, dFlux) != targetTime)) { + //? unused ntlVec3Gfx objvel= (mMOIVertices[n]-mMOIVerticesOld[n]); + // from mainloop + nbored = 0; +//#if OPT3D==0 + FORDF1 { + rflagnb[l] = RFLAG_NB(level, i,j,k,workSet,l); + nbored |= rflagnb[l]; + } +/*#else + const CellFlagType *pFlagCheck = &RFLAG(level, i,j,k,workSet); // omp + rflagnb[dSB] = *(pFlagCheck + (-mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= rflagnb[dSB]; + rflagnb[dWB] = *(pFlagCheck + (-mLevel[level].lOffsy+-1)); nbored |= rflagnb[dWB]; + rflagnb[ dB] = *(pFlagCheck + (-mLevel[level].lOffsy)); nbored |= rflagnb[dB]; + rflagnb[dEB] = *(pFlagCheck + (-mLevel[level].lOffsy+ 1)); nbored |= rflagnb[dEB]; + rflagnb[dNB] = *(pFlagCheck + (-mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= rflagnb[dNB]; + + rflagnb[dSW] = *(pFlagCheck + (-mLevel[level].lOffsx+-1)); nbored |= rflagnb[dSW]; + rflagnb[ dS] = *(pFlagCheck + (-mLevel[level].lOffsx)); nbored |= rflagnb[dS]; + rflagnb[dSE] = *(pFlagCheck + (-mLevel[level].lOffsx+ 1)); nbored |= rflagnb[dSE]; + + rflagnb[ dW] = *(pFlagCheck + (-1)); nbored |= rflagnb[dW]; + rflagnb[ dE] = *(pFlagCheck + ( 1)); nbored |= rflagnb[dE]; + + rflagnb[dNW] = *(pFlagCheck + ( mLevel[level].lOffsx+-1)); nbored |= rflagnb[dNW]; + rflagnb[ dN] = *(pFlagCheck + ( mLevel[level].lOffsx)); nbored |= rflagnb[dN]; + rflagnb[dNE] = *(pFlagCheck + ( mLevel[level].lOffsx+ 1)); nbored |= rflagnb[dNE]; + + rflagnb[dST] = *(pFlagCheck + ( mLevel[level].lOffsy+-mLevel[level].lOffsx)); nbored |= rflagnb[dST]; + rflagnb[dWT] = *(pFlagCheck + ( mLevel[level].lOffsy+-1)); nbored |= rflagnb[dWT]; + rflagnb[ dT] = *(pFlagCheck + ( mLevel[level].lOffsy)); nbored |= rflagnb[dT]; + rflagnb[dET] = *(pFlagCheck + ( mLevel[level].lOffsy+ 1)); nbored |= rflagnb[dET]; + rflagnb[dNT] = *(pFlagCheck + ( mLevel[level].lOffsy+ mLevel[level].lOffsx)); nbored |= rflagnb[dNT]; #endif - CellFlagType settype = CFInvalid; - LbmFloat avgrho=0.0, avgux=0.0, avguy=0.0, avguz=0.0; - if(nbored&CFFluid) { - if(nbored&CFInter) { - settype = CFInter|CFNoInterpolSrc; rhomass = 0.001; - interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); - } else { - // ? dangerous...? settype = CFFluid|CFNoInterpolSrc; rhomass = 1.0; + // */ + CellFlagType settype = CFInvalid; + //LbmFloat avgrho=0.0, avgux=0.0, avguy=0.0, avguz=0.0; + if(nbored&CFFluid) { + settype = CFInter|CFNoInterpolSrc; + if(fillCells) rhomass = 1.0; + else rhomass = 0.; + + //interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); + //LbmVec speed(avgux,avguy,avguz); + //initVelocityCell(level, i,j,k, settype, avgrho, rhomass, speed ); + OBJVEL_CALC; + initVelocityCell(level, i,j,k, settype, 1., rhomass, objvel ); + massCheck += rhomass; + } + /*else if((nbored&CFInter)&&(fillCells)) { settype = CFInter|CFNoInterpolSrc; rhomass = 1.0; - interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); + _interpolateCellValues(level,i,j,k, workSet, avgrho,avgux,avguy,avguz); + } // */ + else { + settype = CFEmpty; rhomass = 0.0; + initEmptyCell(level, i,j,k, settype, 1., rhomass ); } - } else { - settype = CFEmpty; rhomass = 0.0; - } - //settype = CFBnd|CFBndNoslip; rhomass = 0.0; - //avgux=avguy=avguz=0.0; avgrho=1.0; - LbmVec speed(avgux,avguy,avguz); - initVelocityCell(level, i,j,k, settype, avgrho, rhomass, speed ); - monFluids++; - } // flag & simtime + //settype = CFBnd|CFBndNoslip; rhomass = 0.0; + //avgux=avguy=avguz=0.0; avgrho=1.0; + monFluids++; + massReinits++; + } // flag & simtime + } + } // wasactive + + // only compute mass transfer when init is done + if(this->mInitDone) { + errMsg("initMov","Massd test "<<obj->getName()<<" dccd massCheck="<<massCheck<<" massReinits"<<massReinits<< + " fillCells"<<fillCells<<" massmovbnd:"<<mObjectMassMovnd[OId]<<" massCScale"<<massCScale<<" inim:"<<mInitialMass ); + mObjectMassMovnd[OId] += massCheck; } - } } // bnd, active + } // bnd, active + + else if(ntype&CFFluid){ + // second static init pass + if(staticInit) { + //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" verts"<<mMOIVertices.size() ,9); + CellFlagType setflflag = CFFluid; //|(OId<<24); + for(size_t n=0; n<mMOIVertices.size(); n++) { + POS2GRID_CHECK(mMOIVertices,n); + if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } + if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { + //changeFlag(level, i,j,k, workSet, setflflag); + //QCELL(level, i,j,k, workSet,dMass) = 1.; QCELL(level, i,j,k, workSet,dFfrac) = 1.; + //initVelocityCell(level, i,j,k, setflflag, 1., 1., speed ); + initVelocityCell(level, i,j,k, setflflag, 1., 1., mObjectSpeeds[OId] ); + } + //else if(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter)) { changeFlag(level, i,j,k, workSet, RFLAG(level, i,j,k, workSet)|set2Flag); } + } + } // second static inflow pass + } // fluid else if(ntype&CFMbndInflow){ // inflow pass - add new fluid cells @@ -1301,11 +1444,10 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { const LbmVec vel(mObjectSpeeds[OId]); const LbmFloat usqr = (vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])*1.5; USQRMAXCHECK(usqr,vel[0],vel[1],vel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); - errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<vertices.size() ); + //errMsg("LbmFsgrSolver::initMovingObstacles","id"<<OId<<" "<<obj->getName()<<" inflow "<<staticInit<<" "<<mMOIVertices.size() ); - for(size_t n=0; n<vertices.size(); n++) { - POS2GRID(vertices,n); - CHECKIJK; + for(size_t n=0; n<mMOIVertices.size(); n++) { + POS2GRID_CHECK(mMOIVertices,n); // TODO - also reinit interface cells !? if(RFLAG(level, i,j,k, workSet)!=CFEmpty) { // test prevent particle gen for inflow inter cells @@ -1325,9 +1467,8 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { // second static init pass if(staticInit) { CellFlagType set2Flag = CFMbndInflow|(OId<<24); - for(size_t n=0; n<vertices.size(); n++) { - POS2GRID(vertices,n); - CHECKIJK; + for(size_t n=0; n<mMOIVertices.size(); n++) { + POS2GRID_CHECK(mMOIVertices,n); if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { changeFlag(level, i,j,k, workSet, set2Flag); @@ -1339,12 +1480,10 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { } // inflow - //else if(ntype&CFMbndOutflow){ else if(ntype&CFMbndOutflow){ const LbmFloat iniRho = 0.0; - for(size_t n=0; n<vertices.size(); n++) { - POS2GRID(vertices,n); - CHECKIJK; + for(size_t n=0; n<mMOIVertices.size(); n++) { + POS2GRID_CHECK(mMOIVertices,n); // FIXME check fluid/inter cells for non-static!? if(!(RFLAG(level, i,j,k, workSet)&(CFFluid|CFInter))) { if((staticInit)&&(RFLAG(level, i,j,k, workSet)==CFEmpty)) { @@ -1372,9 +1511,8 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { // second static init pass if(staticInit) { CellFlagType set2Flag = CFMbndOutflow|(OId<<24); - for(size_t n=0; n<vertices.size(); n++) { - POS2GRID(vertices,n); - CHECKIJK; + for(size_t n=0; n<mMOIVertices.size(); n++) { + POS2GRID_CHECK(mMOIVertices,n); if(RFLAG(level, i,j,k, workSet)&(CFMbndInflow|CFMbndOutflow)){ continue; } if(RFLAG(level, i,j,k, workSet)&(CFEmpty)) { changeFlag(level, i,j,k, workSet, set2Flag); @@ -1384,10 +1522,9 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { } } // second static outflow pass } // outflow - } - //vector<ntlGeometryObject*> *mpGiObjects; - //Obj->getGeoInitType() ){ - } + + } // allbound check + } // OId /* { // DEBUG check @@ -1401,10 +1538,9 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) { } } // DEBUG */ -#undef CHECKIJK -#undef POS2GRID +#undef POS2GRID_CHECK myTime_t monend = getTime(); - errMsg("LbmFsgrSolver::initMovingObstacles","Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart)); + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7); mLastSimTime = targetTime; } @@ -1417,19 +1553,12 @@ bool LbmFsgrSolver::initGeometryFlags() { int level = mMaxRefine; myTime_t geotimestart = getTime(); ntlGeometryObject *pObj; - // getCellSize (due to forced cubes, use x values) - //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; ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0; - debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< this->mGeoInitId <<") v"<<dvec,3); + debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< this->mLbmInitId <<") v"<<dvec,3); // WARNING - copied to movobj init! /* init object velocities, this has always to be called for init */ - this->initGeoTree(this->mGeoInitId); + this->initGeoTree(); if(this->mAllfluid) { this->freeGeoTree(); return true; } @@ -1439,10 +1568,14 @@ bool LbmFsgrSolver::initGeometryFlags() { int numobjs = (int)(this->mpGiObjects->size()); for(int o=0; o<numobjs; o++) { ntlGeometryObject *obj = (*this->mpGiObjects)[o]; + //debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9); if( ((obj->getGeoInitType()&FGI_ALLBOUNDS) && (obj->getIsAnimated())) || - (obj->getOnlyThinInit()) ) { - obj->initMovingPoints(mLevel[mMaxRefine].nodeSize); + (obj->getVolumeInit()&VOLUMEINIT_SHELL) ) { + if(!obj->getMeshAnimated()) { + debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" type "<<obj->getGeoInitType()<<" anim"<<obj->getIsAnimated()<<" "<<obj->getVolumeInit() ,9); + obj->initMovingPoints(mSimulationTime, mLevel[mMaxRefine].nodeSize); + } } } @@ -1459,7 +1592,6 @@ bool LbmFsgrSolver::initGeometryFlags() { 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); @@ -1499,8 +1631,6 @@ bool LbmFsgrSolver::initGeometryFlags() { ntype = CFInvalid; const bool inside = this->geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance); - // = this->geoInitCheckPointInside( GETPOS(i,j,k) , ntlVec3Gfx(1.0,0.0,0.0), FGI_ALLBOUNDS, OId, distance, dvec[0]*0.5, thinHit, true); - //if(this->geoInitCheckPointInside( GETPOS(i,j,k) , FGI_ALLBOUNDS, OId, distance)) { if(inside) { pObj = (*this->mpGiObjects)[OId]; switch( pObj->getGeoInitType() ){ @@ -1626,18 +1756,24 @@ void LbmFsgrSolver::initFreeSurfaces() { // set interface cells FSGR_FORIJK1(mMaxRefine) { - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid )) { - int initInter = 0; // check for neighboring empty cells + //int initInter = 0; // check for neighboring empty cells FORDF1 { - if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l), CFEmpty ) ) { - initInter = 1; + int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; + if( TESTFLAG( RFLAG(mMaxRefine, ni, nj, nk, mLevel[mMaxRefine].setCurr), CFEmpty ) ) { + LbmFloat arho=0., aux=0., auy=0., auz=0.; + interpolateCellValues(mMaxRefine, ni,nj,nk, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz); + //errMsg("TINI"," "<<PRINT_VEC(ni,nj,nk)<<" v"<<LbmVec(aux,auy,auz) ); + initEmptyCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill); + initVelocityCell(mMaxRefine, ni,nj,nk, CFInter, arho, interfaceFill, LbmVec(aux,auy,auz) ); + //initEmptyCell(level, i,j,k, settype, avgrho, rhomass, speed ); */ + //initInter = 1; } } - if(initInter) { + /*if(initInter) { QCELL(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr, dMass) = interfaceFill; RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setCurr) = RFLAG(mMaxRefine,i,j,k,mLevel[mMaxRefine].setOther) = CFInter; - } + } // */ } } @@ -1655,11 +1791,9 @@ void LbmFsgrSolver::initFreeSurfaces() { } NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l); } - // remove cells with no fluid or interface neighbors if((NBs & CFFluid)==0) { delit = 1; } if((NBs & CFInter)==0) { delit = 1; } - // remove cells with no empty neighbors if(noEmptyNB) { delit = 2; } @@ -1668,7 +1802,10 @@ void LbmFsgrSolver::initFreeSurfaces() { initEmptyCell(mMaxRefine, i,j,k, CFEmpty, 1.0, 0.0); } if(delit==2) { - initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); + //initEmptyCell(mMaxRefine, i,j,k, CFFluid, 1.0, 1.0); + LbmFloat arho=0., aux=0., auy=0., auz=0.; + interpolateCellValues(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, arho,aux,auy,auz); + initVelocityCell(mMaxRefine, i,j,k, CFFluid, arho,1., LbmVec(aux,auy,auz) ); } } // interface } // */ @@ -1945,8 +2082,8 @@ void LbmFsgrSolver::initStandingFluidGradient() { nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l); } DEFAULT_STREAM; - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - DEFAULT_COLLIDE; + //ux = [0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + DEFAULT_COLLIDEG(mLevel[lev].gravity); } for(int l=LBM_DFNUM; l<dTotalNum;l++) { RAC(tcel,l) = RAC(ccel,l); } } } } // GRAVLOOP @@ -2048,8 +2185,8 @@ LbmFsgrSolver::interpolateCellValues( 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; } + //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) || @@ -2058,7 +2195,7 @@ LbmFsgrSolver::interpolateCellValues( 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; + //avgnbdf[rl] += nbdf; avgux += (this->dfDvecX[rl]*nbdf); avguy += (this->dfDvecY[rl]*nbdf); avguz += (this->dfDvecZ[rl]*nbdf); @@ -2082,7 +2219,7 @@ LbmFsgrSolver::interpolateCellValues( // init speed avgux /= cellcnt; avguy /= cellcnt; avguz /= cellcnt; avgrho /= cellcnt; - FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? + //FORDF0M { avgnbdf[m] /= cellcnt; } // CHECK FIXME test? } retrho = avgrho; @@ -2092,3 +2229,11 @@ LbmFsgrSolver::interpolateCellValues( } // interpolateCellValues +/****************************************************************************** + * instantiation + *****************************************************************************/ + +//! lbm factory functions +LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); } + + diff --git a/intern/elbeem/intern/solver_interface.cpp b/intern/elbeem/intern/solver_interface.cpp index ee2f8f281be..d682445645d 100644 --- a/intern/elbeem/intern/solver_interface.cpp +++ b/intern/elbeem/intern/solver_interface.cpp @@ -11,6 +11,7 @@ *****************************************************************************/ /* LBM Files */ +#include "ntl_matrices.h" #include "solver_interface.h" #include "ntl_ray.h" #include "ntl_world.h" @@ -38,12 +39,11 @@ LbmSolverInterface::LbmSolverInterface() : mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0), mDebugVelScale( 0.01 ), mNodeInfoString("+"), - mvGeoStart(-1.0), mvGeoEnd(1.0), + mvGeoStart(-1.0), mvGeoEnd(1.0), mpSimTrafo(NULL), mAccurateGeoinit(0), mName("lbm_default") , mpIso( NULL ), mIsoValue(0.499), mSilent(false) , - mGeoInitId( 1 ), mpGiTree( NULL ), mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL ), mRefinementDesired(0), @@ -58,8 +58,14 @@ LbmSolverInterface::LbmSolverInterface() : #if ELBEEM_PLUGIN==1 if(gDebugLevel<=1) mSilent = true; #endif + mpSimTrafo = new ntlMat4Gfx(0.0); + mpSimTrafo->initId(); } +LbmSolverInterface::~LbmSolverInterface() +{ + if(mpSimTrafo) delete mpSimTrafo; +} /****************************************************************************** @@ -173,6 +179,9 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine, //debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Required Grid memory: "<< memd <<" "<< sizeStr<<" ",4); } +void LbmSolverInterface::initDomainTrafo(float *mat) { + mpSimTrafo->initArrayCheck(mat); +} /*******************************************************************************/ /*! parse a boundary flag string */ @@ -215,6 +224,8 @@ void LbmSolverInterface::parseStdAttrList() { mBoundaryTop = readBoundaryFlagInt("boundary_top", mBoundaryTop,"LbmSolverInterface", "mBoundaryTop", false); mBoundaryBottom= readBoundaryFlagInt("boundary_bottom", mBoundaryBottom,"LbmSolverInterface", "mBoundaryBottom", false); + mpAttrs->readMat4Gfx("domain_trafo" , (*mpSimTrafo), "ntlBlenderDumper","mpSimTrafo", false, mpSimTrafo ); + LbmVec sizeVec(mSizex,mSizey,mSizez); sizeVec = vec2L( mpAttrs->readVec3d("size", vec2P(sizeVec), "LbmSolverInterface", "sizeVec", false) ); mSizex = (int)sizeVec[0]; @@ -225,7 +236,6 @@ void LbmSolverInterface::parseStdAttrList() { if(mpParam) mpParam->setSize(mSizex, mSizey, mSizez ); mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmSolverInterface", "mInitDensityGradient", false); - mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false); mIsoValue = mpAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false ); mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmSolverInterface", "mDebugVelScale", false); @@ -241,13 +251,13 @@ void LbmSolverInterface::parseStdAttrList() { } // new test vars - mTForceStrength = mpAttrs->readFloat("tforcestrength", mTForceStrength,"LbmSolverInterface", "mTForceStrength", false); + mTForceStrength = 0.; // set from test solver mpAttrs->readFloat("tforcestrength", mTForceStrength,"LbmSolverInterface", "mTForceStrength", false); mFarFieldSize = mpAttrs->readFloat("farfieldsize", mFarFieldSize,"LbmSolverInterface", "mFarFieldSize", false); // old compat float sizeScale = mpAttrs->readFloat("test_scale", 0.,"LbmTestdata", "mSizeScale", false); if((mFarFieldSize<=0.)&&(sizeScale>0.)) { mFarFieldSize=sizeScale; errMsg("LbmTestdata","Warning - using mSizeScale..."); } - mCppfStage = mpAttrs->readFloat("cppfstage", mCppfStage,"LbmSolverInterface", "mCppfStage", false); + mCppfStage = mpAttrs->readInt("cppfstage", mCppfStage,"LbmSolverInterface", "mCppfStage", false); mPartGenProb = mpAttrs->readFloat("partgenprob", mPartGenProb,"LbmFsgrSolver", "mPartGenProb", false); } @@ -258,9 +268,8 @@ void LbmSolverInterface::parseStdAttrList() { /*****************************************************************************/ /*! init tree for certain geometry init */ -void LbmSolverInterface::initGeoTree(int id) { +void LbmSolverInterface::initGeoTree() { if(mpGlob == NULL) { errFatal("LbmSolverInterface::initGeoTree","Requires globals!",SIMWORLD_INITERROR); return; } - mGeoInitId = id; ntlScene *scene = mpGlob->getSimScene(); mpGiObjects = scene->getObjects(); mGiObjInside.resize( mpGiObjects->size() ); @@ -268,11 +277,12 @@ void LbmSolverInterface::initGeoTree(int id) { mGiObjSecondDist.resize( mpGiObjects->size() ); for(size_t i=0; i<mpGiObjects->size(); i++) { if((*mpGiObjects)[i]->getGeoInitIntersect()) mAccurateGeoinit=true; + debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"id:"<<mLbmInitId<<" obj:"<< (*mpGiObjects)[i]->getName() <<" gid:"<<(*mpGiObjects)[i]->getGeoInitId(), 9 ); } debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Accurate geo init: "<<mAccurateGeoinit, 9) if(mpGiTree != NULL) delete mpGiTree; - char treeFlag = (1<<(mGeoInitId+4)); + char treeFlag = (1<<(this->mLbmInitId+4)); mpGiTree = new ntlTree( 15, 8, // warning - fixed values for depth & maxtriangles here... scene, treeFlag ); @@ -548,7 +558,7 @@ ntlVec3Gfx LbmSolverInterface::getGeoMaxMovementVelocity(LbmFloat simtime, LbmFl // mpGiObjects has to be inited here... for(int i=0; i< (int)mpGiObjects->size(); i++) { - errMsg("MVT","i"<<i<<" "<< (*mpGiObjects)[i]->getName() ); // DEBUG + //errMsg("LbmSolverInterface::getGeoMaxMovementVelocity","i="<<i<<" "<< (*mpGiObjects)[i]->getName() ); // DEBUG if( (*mpGiObjects)[i]->getGeoInitType() & (FGI_FLUID|FGI_MBNDINFLOW) ){ //ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime); ntlVec3Gfx orgvel = (*mpGiObjects)[i]->calculateMaxVel( simtime, simtime+stepsize ); @@ -559,7 +569,7 @@ ntlVec3Gfx LbmSolverInterface::getGeoMaxMovementVelocity(LbmFloat simtime, LbmFl if( normNoSqrt(inivel) > normNoSqrt(max) ) { max = inivel; } } } - errMsg("MVT","max "<<" "<< max ); // DEBUG + errMsg("LbmSolverInterface::getGeoMaxMovementVelocity", "max="<< max ); // DEBUG return max; } diff --git a/intern/elbeem/intern/solver_interface.h b/intern/elbeem/intern/solver_interface.h index ee4ecd79077..4cbdd2945e5 100644 --- a/intern/elbeem/intern/solver_interface.h +++ b/intern/elbeem/intern/solver_interface.h @@ -81,6 +81,8 @@ typedef ntlVec3d LbmVec; template<class T> inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); } template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); } +template<class Scalar> class ntlMatrix4x4; + // bubble id type typedef int BubbleId; @@ -105,52 +107,28 @@ typedef int BubbleId; // additional for fluid/interface // force symmetry for flag reinit -#define CFNoInterpolSrc (1<< 9) -#define CFNoNbFluid (1<<10) -#define CFNoNbEmpty (1<<11) +#define CFNoInterpolSrc (1<<13) +#define CFNoNbFluid (1<<14) +#define CFNoNbEmpty (1<<15) // cell treated normally on coarser grids -#define CFGrNorm (1<< 9) -#define CFGrCoarseInited (1<<10) +#define CFGrNorm (1<<16) +#define CFGrCoarseInited (1<<17) // (the following values shouldnt overlap to ensure // proper coarsening) // border cells to be interpolated from finer grid -#define CFGrFromFine (1<<13) +#define CFGrFromFine (1<<18) // 32k aux border marker -#define CFGrToFine (1<<14) +#define CFGrToFine (1<<19) // also needed on finest level -#define CFGrFromCoarse (1<<15) +#define CFGrFromCoarse (1<<20) // 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) @@ -172,6 +150,7 @@ typedef int BubbleId; // max. no. of cell values for 3d #define dTotalNum 22 + /*****************************************************************************/ /*! a single lbm cell */ /* the template is only needed for @@ -191,9 +170,9 @@ class LbmCellContents { /* struct for the coordinates of a cell in the grid */ typedef struct { int x,y,z; + int flag; // special handling? } LbmPoint; - /* struct for the coordinates of a cell in the grid */ typedef struct { char active; // bubble in use, oder may be overwritten? @@ -252,12 +231,17 @@ class LbmSolverInterface //! Constructor LbmSolverInterface(); //! Destructor - virtual ~LbmSolverInterface() { }; + virtual ~LbmSolverInterface(); //! id string of solver virtual string getIdString() = 0; + // multi step solver init /*! finish the init with config file values (allocate arrays...) */ - virtual bool initializeSolver() =0; + virtual bool initializeSolverMemory() =0; + /*! init solver arrays */ + virtual bool initializeSolverGrids() =0; + /*! prepare actual simulation start, setup viz etc */ + virtual bool initializeSolverPostinit() =0; /*! notify object that dump is in progress (e.g. for field dump) */ virtual void notifySolverOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) = 0; @@ -287,7 +271,7 @@ class LbmSolverInterface #endif /*! init tree for certain geometry init */ - void initGeoTree(int id); + void initGeoTree(); /*! destroy tree etc. when geometry init done */ void freeGeoTree(); /*! check for a certain flag type at position org (needed for e.g. quadtree refinement) */ @@ -345,8 +329,13 @@ class LbmSolverInterface inline ntlVec3Gfx getGeoEnd() const { return mvGeoEnd; } /*! access geo init vars */ - inline void setGeoInitId(int set) { mGeoInitId = set; } - inline int getGeoInitId() const { return mGeoInitId; } + inline void setLbmInitId(int set) { mLbmInitId = set; } + inline int getLbmInitId() const { return mLbmInitId; } + + /*! init domain transformation matrix from float array */ + void initDomainTrafo(float *mat); + /*! get domain transformation matrix to have object centered fluid vertices */ + inline ntlMatrix4x4<gfxReal> *getDomainTrafo() { return mpSimTrafo; } /*! access name string */ inline void setName(string set) { mName = set; } @@ -377,8 +366,8 @@ class LbmSolverInterface 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; } + inline void setDomainBound(string set) { mDomainBound = set; } + inline string getDomainBound() const { return mDomainBound; } //! set/get dump velocities flag inline void setDomainPartSlip(LbmFloat set) { mDomainPartSlipValue = set; } inline LbmFloat getDomainPartSlip() const { return mDomainPartSlipValue; } @@ -506,6 +495,8 @@ class LbmSolverInterface /*! for display - start and end vectors for geometry */ ntlVec3Gfx mvGeoStart, mvGeoEnd; + //! domain vertex trafos + ntlMatrix4x4<gfxReal> *mpSimTrafo; /*! perform accurate geometry init? */ bool mAccurateGeoinit; @@ -521,8 +512,8 @@ class LbmSolverInterface //! debug output? bool mSilent; - /*! geometry init id */ - int mGeoInitId; + /*! geometry init id, passed from ntl_geomclass */ + int mLbmInitId; /*! tree object for geomerty initialization */ ntlTree *mpGiTree; /*! object vector for geo init */ @@ -557,7 +548,7 @@ class LbmSolverInterface int mMarkedCellIndex; //! domain boundary free/no slip type - std::string mDomainBound; + string mDomainBound; //! part slip value for domain LbmFloat mDomainPartSlipValue; diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index 10fca60c546..70ff3106645 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -23,16 +23,6 @@ void LbmFsgrSolver::step() { void LbmFsgrSolver::stepMain() { -#if ELBEEM_BLENDER==1 - // update gui display - //SDL_mutexP(lobalBakeLock); - if(getGlobalBakeState()<0) { - // this means abort... cause panic - CAUSE_PANIC; - errMsg("LbmFsgrSolver::step","Got abort signal from GUI, causing panic, aborting..."); - } - //SDL_mutexV(lobalBakeLock); -#endif // ELBEEM_PLUGIN==1 this->markedClearList(); // DMC clearMarkedCellsList // safety check, counter reset @@ -52,8 +42,12 @@ void LbmFsgrSolver::stepMain() // init moving bc's, can change mMaxVlen initMovingObstacles(false); +#if LBM_INCLUDE_TESTSOLVERS==1 + handleCpdata(); +#endif // important - keep for tadap + LbmFloat lastMass = mCurrentMass; mCurrentMass = this->mFixMass; // reset here for next step mCurrentVolume = 0.0; @@ -122,15 +116,7 @@ void LbmFsgrSolver::stepMain() " probs:"<<mNumProblems<< sepStr<< " simt:"<<mSimulationTime<< sepStr<< " for '"<<this->mName<<"' " , 10); - debMsgDirect(std::endl); - - // nicer output - debMsgDirect(std::endl); // - //debMsgStd(" ",DM_MSG," ",10); - } else { - debMsgDirect("."); - //if((mStepCnt%10)==9) debMsgDirect("\n"); - } + } else { debMsgDirect("."); } if(this->mStepCnt==1) { mMinNoCells = mMaxNoCells = this->mNumUsedCells; @@ -207,6 +193,10 @@ void LbmFsgrSolver::stepMain() // advance positions with current grid advanceParticles(); + if(mpParticles) { + mpParticles->checkDumpTextPositions(mSimulationTime); + mpParticles->checkTrails(mSimulationTime); + } // one of the last things to do - adapt timestep // was in fineAdvance before... @@ -224,8 +214,10 @@ void LbmFsgrSolver::stepMain() // output total step time timeend = getTime(); debMsgStd("LbmFsgrSolver::stepMain",DM_MSG,"step:"<<this->mStepCnt - <<": dccd="<< mCurrentMass<<"/"<<mCurrentVolume<<"(fix="<<this->mFixMass<<",ini="<<mInitialMass<<"), " + <<": dccd="<< mCurrentMass<<",d"<<(lastMass-mCurrentMass)<<"/"<<mCurrentVolume<<"(fix="<<this->mFixMass<<",ini="<<mInitialMass<<"), " <<" totst:"<<getTimeString(timeend-timestart), 3); + // nicer output + debMsgDirect(std::endl); //#endif // ELBEEM_PLUGIN!=1 } @@ -250,7 +242,6 @@ void LbmFsgrSolver::fineAdvance() if(mFVHeight<1.0) mFVHeight = 1.0; this->mpParam->setFluidVolumeHeight(mFVHeight); } - //NEWDEBCHECK("t2"); // advance time before timestep change mSimulationTime += this->mpParam->getTimestep(); @@ -267,17 +258,14 @@ void LbmFsgrSolver::fineAdvance() // flag init... (work on current set, to simplify flag checks) reinitFlags( mLevel[mMaxRefine].setCurr ); if(!this->mSilent){ errMsg("fineAdvance"," flags reinit on set "<< mLevel[mMaxRefine].setCurr ); } - //NEWDEBCHECK("t3"); } /*****************************************************************************/ -//! coarse/fine step functions +//! fine step function /*****************************************************************************/ -// ZDEB - // access to own dfs during step (may be changed to local array) #define MYDF(l) RAC(ccel, l) @@ -291,7 +279,7 @@ LbmFsgrSolver::mainLoop(int lev) int calcCellsEmptied = this->mNumEmptiedCells; int calcNumUsedCells = this->mNumUsedCells; const int cutMin = 1; - const int cutConst = mCutoff+1; + const int cutConst = mCutoff+2; # if LBM_INCLUDE_TESTSOLVERS==1 // 3d region off... quit @@ -471,7 +459,7 @@ LbmFsgrSolver::mainLoop(int lev) changeFlag(lev, i,j,k, TSET(lev), CFInter); // same as ifemptied for if below - LbmPoint emptyp; + LbmPoint emptyp; emptyp.flag = 0; emptyp.x = i; emptyp.y = j; emptyp.z = k; #if PARALLEL==1 calcListEmpty[id].push_back( emptyp ); @@ -554,8 +542,8 @@ LbmFsgrSolver::mainLoop(int lev) } else { if(nbored&CFBnd) { DEFAULT_STREAM; - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - DEFAULT_COLLIDE; + //ux = [0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; + DEFAULT_COLLIDEG(mLevel[lev].gravity); oldFlag &= (~CFNoBndFluid); } else { // do standard stream/collide @@ -580,9 +568,15 @@ LbmFsgrSolver::mainLoop(int lev) | CFNoInterpolSrc | CFNoBndFluid )); - if(!(nbored&CFBnd)) { + if(!(nbored&CFBndNoslip)) { //NEWSURFT NEWSURFTNOS newFlag |= CFNoBndFluid; } + /*if(!(nbored&CFBnd)) { //NEWSURFT NEWSURFTNOS + // explicitly check for noslip neighbors + bool hasnoslipnb = false; + FORDF1 { if((nbflag[l]&CFBnd)&&(nbflag[l]&CFBndNoslip)) hasnoslipnb=true; } + if(!hasnoslipnb) newFlag |= CFNoBndFluid; + } // */ // store own dfs and mass mass = RAC(ccel,dMass); @@ -596,6 +590,7 @@ LbmFsgrSolver::mainLoop(int lev) // calculate mass exchange for interface cells LbmFloat myfrac = RAC(ccel,dFfrac); + if(myfrac<0.) myfrac=0.; // NEWSURFT # define nbdf(l) m[ this->dfInv[(l)] ] // update mass @@ -605,6 +600,7 @@ LbmFsgrSolver::mainLoop(int lev) // which Df's have to be reconstructed? // for fluid cells - just the f_i difference from streaming to empty cells ---- numRecons = 0; + bool onlyBndnb = ((!(oldFlag&CFNoBndFluid))&&(oldFlag&CFNoNbFluid)&&(nbored&CFBndNoslip)); FORDF1 { // dfl loop recons[l] = 0; @@ -622,8 +618,11 @@ LbmFsgrSolver::mainLoop(int lev) if((oldFlag&CFNoBndFluid)&&(nbflag[l]&CFNoBndFluid)) { mynbfac = QCELL_NB(lev, i,j,k,SRCS(lev),l, dFlux) / QCELL(lev, i,j,k,SRCS(lev), dFlux); nbnbfac = 1.0/mynbfac; + onlyBndnb = false; } else { mynbfac = nbnbfac = 1.0; // switch calc flux off + goto changeDefault; // NEWSURFT + //change = 0.; goto changeDone; // NEWSURFT } //mynbfac = nbnbfac = 1.0; // switch calc flux off t3 @@ -663,10 +662,12 @@ LbmFsgrSolver::mainLoop(int lev) break; }} // inter-inter exchange + changeDefault: ; // just do normal mass exchange... change = ( nbnbfac*nbdf(l) - mynbfac*MYDF(l) ) ; changeDone: ; nbfracs[l] = QCELL_NB(lev, i,j,k, SRCS(lev),l, dFfrac); + if(nbfracs[l]<0.) nbfracs[l] = 0.; // NEWSURFT change *= (myfrac + nbfracs[l]) * 0.5; } // the other cell is interface @@ -766,10 +767,11 @@ LbmFsgrSolver::mainLoop(int lev) - MYDF( l ); } } + usqr = 1.5 * (oldUx*oldUx + oldUy*oldUy + oldUz*oldUz); // needed later on #else ux=oldUx, uy=oldUy, uz=oldUz; // no local vars, only for usqr rho = REFERENCE_PRESSURE; - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); + usqr = 1.5 * (ux*ux + uy*uy + uz*uz); // needed later on if(recons[dN ]) { m[dS ] = EQN + EQS - MYDF(dN ); } if(recons[dS ]) { m[dN ] = EQS + EQN - MYDF(dS ); } if(recons[dE ]) { m[dW ] = EQE + EQW - MYDF(dE ); } @@ -806,21 +808,30 @@ LbmFsgrSolver::mainLoop(int lev) rho = REFERENCE_PRESSURE; FORDF0 { RAC(tcel, l) = this->getCollideEq(l, rho,ux,uy,uz); } //errMsg("INFLOW_DEBUG","if at "<<PRINT_IJK<<" v="<<vel<<" rho="<<rho); - } else { - // normal collide - // mass streaming done... do normal collide - ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; - ux *= mass; uy *= mass; uz *= mass; // acc. according to mass in cell - DEFAULT_COLLIDE; - PERFORM_USQRMAXCHECK; - // rho init from default collide necessary for fill/empty check below + } else { + // NEWSURFT, todo optimize! + if(onlyBndnb) { //if(usqr<0.001*0.001) { + rho = ux = uy = uz = 0.; + FORDF0{ + rho += m[l]; + ux += (this->dfDvecX[l]*m[l]); + uy += (this->dfDvecY[l]*m[l]); + uz += (this->dfDvecZ[l]*m[l]); + } + FORDF0 { RAC(tcel, l) = this->getCollideEq(l, rho,ux,uy,uz); } + } else {// NEWSURFT */ + // normal collide + // mass streaming done... do normal collide + LbmVec grav = mLevel[lev].gravity*mass; + DEFAULT_COLLIDEG(grav); + PERFORM_USQRMAXCHECK; + // rho init from default collide necessary for fill/empty check below + } // test } // testing..., particle generation -//# include "est_if.h" test_if // also check oldFlag for CFNoNbFluid, test - // for inflow no pargen test - // NOBUBBB! + // for inflow no pargen test // NOBUBBB! if((this->mInitDone) //&&(mUseTestdata) //&& (!((oldFlag|newFlag)&CFNoNbEmpty)) && (!((oldFlag|newFlag)&CFNoDelete)) @@ -846,14 +857,28 @@ LbmFsgrSolver::mainLoop(int lev) LbmFloat basethresh = this->mPartGenProb*lcsmqo*rl; // reduce probability in outer region - if( (i<cutConst)||(i>this->mSizex-cutConst) ){ prob *= 0.5; } - if( (j<cutConst)||(j>this->mSizey-cutConst) ){ prob *= 0.5; } - if( (k<cutConst)||(k>this->mSizez-cutConst) ){ prob *= 0.5; } + //if( (i<cutConst)||(i>this->mSizex-cutConst) ){ prob *= 0.5; } + //if( (j<cutConst)||(j>this->mSizey-cutConst) ){ prob *= 0.5; } + //if( (k<cutConst)||(k>this->mSizez-cutConst) ){ prob *= 0.5; } + // NEW TEST 040627 + //if( (i<cutConst)||(i>this->mSizex-cutConst) ){ doAdd=false; } + //if( (j<cutConst)||(j>this->mSizey-cutConst) ){ doAdd=false; } + //if( (k<cutConst)||(k>this->mSizez-cutConst) ){ doAdd=false; } + const int pibord = mLevel[mMaxRefine].lSizex/2-cutConst; + const int pjbord = mLevel[mMaxRefine].lSizey/2-cutConst; + LbmFloat pifac = 1.-(LbmFloat)(ABS(i-pibord)) / (LbmFloat)(pibord); + LbmFloat pjfac = 1.-(LbmFloat)(ABS(j-pjbord)) / (LbmFloat)(pjbord); + if(pifac<0.) pifac=0.; + if(pjfac<0.) pjfac=0.; + //const LbmFloat pkfac = 1.-(LbmFloat)(ABS(k-mLevel[mMaxRefine].lSizez/2))/(LbmFloat)(mLevel[mMaxRefine].lSizez/2); + //errMsg("PROBTTT"," at "<<PRINT_IJK<<" prob"<<prob<<" pifac"<<pifac<<" pjfac"<<pjfac<<" "<<(basethresh*rl*pifac*pjfac)); + //prob *= pifac*pjfac; //*pkfac; //#define RWVEL_THRESH 1.0 #define RWVEL_THRESH 1.5 #define RWVEL_WINDTHRESH (RWVEL_THRESH*0.5) - if( (prob< (basethresh*rl)) && (lcsmqo>0.0095) && (rl>RWVEL_THRESH) ) { + //if( (prob< (basethresh*rl)) && (lcsmqo>0.0095) && (rl>RWVEL_THRESH) ) { + if( (prob< (basethresh*rl*pifac*pjfac)) && (lcsmqo>0.0095) && (rl>RWVEL_THRESH) ) { // add } else { doAdd = false; // dont... @@ -862,7 +887,7 @@ LbmFsgrSolver::mainLoop(int lev) //#define SLOWDOWNREGION (2*mCutoff) #if LBMDIM==3 // normal -#define SLOWDOWNREGION (this->mSizez/5) +#define SLOWDOWNREGION (this->mSizez/4) #else // LBMDIM==2 // off #define SLOWDOWNREGION 10 @@ -871,9 +896,9 @@ LbmFsgrSolver::mainLoop(int lev) // "wind" disturbance // use realworld relative velocity here instead? - if( (doAdd) && ( - ((rl>RWVEL_WINDTHRESH) && (lcsmqo<P_LCSMQO)) // normal checks - ||(k>this->mSizez-SLOWDOWNREGION) )) { + if( (doAdd && + ((rl>RWVEL_WINDTHRESH) && (lcsmqo<P_LCSMQO)) )// normal checks + ||(k>this->mSizez-SLOWDOWNREGION) ) { LbmFloat nuz = uz; LbmFloat jdf; // = 0.05 * (rand()/(RAND_MAX+1.0)); if(rl>RWVEL_WINDTHRESH) jdf *= (rl-RWVEL_WINDTHRESH); @@ -881,7 +906,8 @@ LbmFsgrSolver::mainLoop(int lev) // special case LbmFloat zfac = (LbmFloat)( k-(this->mSizez-SLOWDOWNREGION) ); zfac /= (LbmFloat)(SLOWDOWNREGION); - nuz += zfac; // check max speed? OFF? + nuz += (1.0) * zfac; // check max speed? OFF? + //errMsg("TOPT"," at "<<PRINT_IJK<<" zfac"<<zfac); } else { // normal probability LbmFloat fac = P_LCSMQO-lcsmqo; @@ -892,7 +918,7 @@ LbmFsgrSolver::mainLoop(int lev) // 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; } + RAC(tcel,l) += add; } } //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<PRINT_VEC(ux,uy,nuz)<<" rwv"<<PRINT_VEC(rux,ruy,ruz) ); //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<norm(LbmVec(ux,uy,nuz))<<" rwv"<<norm(LbmVec(rux,ruy,ruz)) ); @@ -986,30 +1012,27 @@ LbmFsgrSolver::mainLoop(int lev) if(!iffilled) { // remove cells independent from amount of change... if( (oldFlag & CFNoNbEmpty)&&(newFlag & CFNoNbEmpty)&& - ( (mass>(rho*FSGR_LISTTTHRESHFULL)) || ((nbored&CFInter)==0) ) - ) { + ( (mass>(rho*FSGR_LISTTTHRESHFULL)) || ((nbored&CFInter)==0) )) { //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","filled "<<PRINT_IJK); }; iffilled = 1; } } if(!ifemptied) { if( (oldFlag & CFNoNbFluid)&&(newFlag & CFNoNbFluid)&& - ( (mass<(rho*FSGR_LISTTTHRESHEMPTY)) || ((nbored&CFInter)==0) ) - ) - { + ( (mass<(rho*FSGR_LISTTTHRESHEMPTY)) || ((nbored&CFInter)==0) )) { //if((nbored&CFInter)==0){ errMsg("NBORED!CFINTER","emptied "<<PRINT_IJK); }; ifemptied = 1; } } } // nobndfluid only */ #endif - //iffilled = ifemptied = 0; // DEBUG!!!!!!!!!!!!!!! // now that all dfs are known, handle last changes if(iffilled) { - LbmPoint filledp; + LbmPoint filledp; filledp.flag=0; + if(!(newFlag&CFNoBndFluid)) filledp.flag |= 1; // NEWSURFT filledp.x = i; filledp.y = j; filledp.z = k; #if PARALLEL==1 calcListFull[id].push_back( filledp ); @@ -1020,7 +1043,8 @@ LbmFsgrSolver::mainLoop(int lev) calcCellsFilled++; } else if(ifemptied) { - LbmPoint emptyp; + LbmPoint emptyp; emptyp.flag=0; + if(!(newFlag&CFNoBndFluid)) emptyp.flag |= 1; // NEWSURFT emptyp.x = i; emptyp.y = j; emptyp.z = k; #if PARALLEL==1 calcListEmpty[id].push_back( emptyp ); @@ -1029,10 +1053,7 @@ LbmFsgrSolver::mainLoop(int lev) #endif // PARALLEL==1 //this->mNumEmptiedCells++; // DEBUG calcCellsEmptied++; - } else { - // ... - } - + } // dont cutoff values -> better cell conversions RAC(tcel,dFfrac) = (mass/rho); @@ -1098,1278 +1119,6 @@ LbmFsgrSolver::mainLoop(int lev) // check other vars...? } -// ZDEB - - -void LbmFsgrSolver::coarseCalculateFluxareas(int lev) -{ -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - lev =0; // get rid of warnings... -#else - FSGR_FORIJK_BOUNDS(lev) { - if( RFLAG(lev, i,j,k,mLevel[lev].setCurr) & CFFluid) { - if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & CFGrFromCoarse) { - LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<this->cDirNum; l++) { - int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, mLevel[lev+1].setCurr)& - (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - ) { - totArea += mFsgrCellArea[l]; - } - } // l - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = totArea; - //continue; - } else - if( RFLAG(lev+1, i*2,j*2,k*2,mLevel[lev+1].setCurr) & (CFEmpty|CFUnused)) { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 1.0; - //continue; - } else { - QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) = 0.0; - } - //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,mLevel[lev].setCurr, dFlux) ); - } - } // } TEST DEBUG - if(!this->mSilent){ debMsgStd("coarseCalculateFluxareas",DM_MSG,"level "<<lev<<" calculated", 7); } -#endif //! LBM_NOADCOARSENING==1 -} - -void LbmFsgrSolver::coarseAdvance(int lev) -{ -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - lev =0; // get rid of warnings... -#else - LbmFloat calcCurrentMass = 0.0; - LbmFloat calcCurrentVolume = 0.0; - - LbmFloat *ccel = NULL; - LbmFloat *tcel = NULL; - LbmFloat m[LBM_DFNUM]; - LbmFloat rho, ux, uy, uz, tmp, usqr, lcsmqo; -#if OPT3D==1 - LbmFloat lcsmqadd, lcsmeq[LBM_DFNUM], lcsmomega; -#endif // OPT3D==true - m[0] = tmp = usqr = 0.0; - - coarseCalculateFluxareas(lev); - // copied from fineAdv. - CellFlagType *pFlagSrc = &RFLAG(lev, 1,1,getForZMin1(),SRCS(lev)); - CellFlagType *pFlagDst = &RFLAG(lev, 1,1,getForZMin1(),TSET(lev)); - pFlagSrc -= 1; - pFlagDst -= 1; - ccel = RACPNT(lev, 1,1,getForZMin1() ,SRCS(lev)); // QTEST - ccel -= QCELLSTEP; - tcel = RACPNT(lev, 1,1,getForZMin1() ,TSET(lev)); // QTEST - tcel -= QCELLSTEP; - //if(strstr(this->getName().c_str(),"Debug")){ errMsg("DEBUG","DEBUG!!!!!!!!!!!!!!!!!!!!!!!"); } - - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { -#if FSGR_STRICT_DEBUG==1 - rho = ux = uy = uz = tmp = usqr = -100.0; // DEBUG -#endif - pFlagSrc++; - pFlagDst++; - ccel += QCELLSTEP; - tcel += QCELLSTEP; - - // from coarse cells without unused nbs are not necessary...! -> remove - if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - bool invNb = false; - FORDF1 { if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } } - if(!invNb) { - // WARNING - this modifies source flag array... - *pFlagSrc = CFFluid|CFGrNorm; -#if ELBEEM_PLUGIN!=1 - errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<<lev<<" "<<PRINT_IJK); -#endif // ELBEEM_PLUGIN!=1 - // move to perform coarsening? - } - } // */ - -#if FSGR_STRICT_DEBUG==1 - *pFlagDst = *pFlagSrc; // always set other set... -#else - *pFlagDst = (*pFlagSrc & (~CFGrCoarseInited)); // always set other set... , remove coarse inited flag -#endif - - // old INTCFCOARSETEST==1 - if((*pFlagSrc) & CFGrFromCoarse) { // interpolateFineFromCoarse test! - 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); - this->mNumUsedCells++; - } - continue; // interpolateFineFromCoarse test! - } // interpolateFineFromCoarse test! old INTCFCOARSETEST==1 - - if( ((*pFlagSrc) & (CFFluid)) ) { - ccel = RACPNT(lev, i,j,k ,SRCS(lev)); - tcel = RACPNT(lev, i,j,k ,TSET(lev)); - - if( ((*pFlagSrc) & (CFGrFromFine)) ) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? - continue; // comes from fine grid - } - // also ignore CFGrFromCoarse - else if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - FORDF0 { RAC(tcel,l) = RAC(ccel,l); } // always copy...? - continue; - } - - OPTIMIZED_STREAMCOLLIDE; - *pFlagDst |= CFNoBndFluid; // test? - calcCurrentVolume += RAC(ccel,dFlux); - calcCurrentMass += RAC(ccel,dFlux)*rho; - //ebugMarkCell(lev+1, 2*i+1,2*j+1,2*k ); -#if FSGR_STRICT_DEBUG==1 - if(rho<-1.0){ debugMarkCell(lev, i,j,k ); - errMsg("INVRHOCELL_CHECK"," l"<<lev<<" "<< PRINT_IJK<<" rho:"<<rho ); - CAUSE_PANIC; - } -#endif // FSGR_STRICT_DEBUG==1 - this->mNumUsedCells++; - - } - } - pFlagSrc+=2; // after x - pFlagDst+=2; // after x - ccel += (QCELLSTEP*2); - tcel += (QCELLSTEP*2); - } - pFlagSrc+= mLevel[lev].lSizex*2; // after y - pFlagDst+= mLevel[lev].lSizex*2; // after y - ccel += (QCELLSTEP*mLevel[lev].lSizex*2); - tcel += (QCELLSTEP*mLevel[lev].lSizex*2); - } // all cell loop k,j,i - - - //errMsg("coarseAdvance","level "<<lev<<" stepped from "<<mLevel[lev].setCurr<<" to "<<mLevel[lev].setOther); - if(!this->mSilent){ errMsg("coarseAdvance","level "<<lev<<" stepped from "<<SRCS(lev)<<" to "<<TSET(lev)); } - // */ - - // update other set - mLevel[lev].setOther = mLevel[lev].setCurr; - mLevel[lev].setCurr ^= 1; - mLevel[lev].lsteps++; - mLevel[lev].lmass = calcCurrentMass * mLevel[lev].lcellfactor; - mLevel[lev].lvolume = calcCurrentVolume * mLevel[lev].lcellfactor; -#if ELBEEM_PLUGIN!=1 - errMsg("DFINI", " m l"<<lev<<" m="<<mLevel[lev].lmass<<" c="<<calcCurrentMass<<" lcf="<< mLevel[lev].lcellfactor ); - errMsg("DFINI", " v l"<<lev<<" v="<<mLevel[lev].lvolume<<" c="<<calcCurrentVolume<<" lcf="<< mLevel[lev].lcellfactor ); -#endif // ELBEEM_PLUGIN -#endif //! LBM_NOADCOARSENING==1 -} - -/*****************************************************************************/ -//! multi level functions -/*****************************************************************************/ - - -// get dfs from level (lev+1) to (lev) coarse border nodes -void LbmFsgrSolver::coarseRestrictFromFine(int lev) -{ -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - lev =0; // get rid of warnings... -#else - if((lev<0) || ((lev+1)>mMaxRefine)) return; -#if FSGR_STRICT_DEBUG==1 - // reset all unused cell values to invalid - int unuCnt = 0; - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,mLevel[lev].setCurr); - if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { - FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } - unuCnt++; - // set here - } else if( ((*pFlagSrc) & (CFFluid|CFGrNorm)) == (CFFluid|CFGrNorm) ) { - // simulated... - } else { - // reset in interpolation - //errMsg("coarseRestrictFromFine"," reset l"<<lev<<" "<<PRINT_IJK); - } - if( ((*pFlagSrc) & (CFEmpty|CFUnused)) ) { // test, also reset? - FORDF0{ QCELL(lev, i,j,k,mLevel[lev].setCurr, l) = -10000.0; } - } // test - } } } - errMsg("coarseRestrictFromFine"," reset l"<<lev<<" fluid|coarseBorder cells: "<<unuCnt); -#endif // FSGR_STRICT_DEBUG==1 - const int srcSet = mLevel[lev+1].setCurr; - const int dstSet = mLevel[lev].setCurr; - - //restrict - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - CellFlagType *pFlagSrc = &RFLAG(lev, i,j,k,dstSet); - if((*pFlagSrc) & (CFFluid)) { - if( ((*pFlagSrc) & (CFFluid|CFGrFromFine)) == (CFFluid|CFGrFromFine) ) { - // do resctriction - mNumInterdCells++; - coarseRestrictCell(lev, i,j,k,srcSet,dstSet); - - this->mNumUsedCells++; - } // from fine & fluid - else { - if(RFLAG(lev+1, 2*i,2*j,2*k,srcSet) & CFGrFromCoarse) { - RFLAG(lev, i,j,k,dstSet) |= CFGrToFine; - } else { - RFLAG(lev, i,j,k,dstSet) &= (~CFGrToFine); - } - } - } // & fluid - }}} - if(!this->mSilent){ errMsg("coarseRestrictFromFine"," from l"<<(lev+1)<<",s"<<mLevel[lev+1].setCurr<<" to l"<<lev<<",s"<<mLevel[lev].setCurr); } -#endif //! LBM_NOADCOARSENING==1 -} - -bool LbmFsgrSolver::adaptGrid(int lev) { -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - lev =0; // get rid of warnings... - return false; -#else - if((lev<0) || ((lev+1)>mMaxRefine)) return false; - bool change = false; - { // refinement, PASS 1-3 - - //bool nbsok; - // FIXME remove TIMEINTORDER ? - LbmFloat interTime = 0.0; - // update curr from other, as streaming afterwards works on curr - // thus read only from srcSet, modify other - const int srcSet = mLevel[lev].setOther; - const int dstSet = mLevel[lev].setCurr; - const int srcFineSet = mLevel[lev+1].setCurr; - const bool debugRefinement = false; - - // use //template functions for 2D/3D - /*if(strstr(this->getName().c_str(),"Debug")) - if(lev+1==mMaxRefine) { // mixborder - for(int l=0;((l<this->cDirNum) && (!removeFromFine)); l++) { // FARBORD - int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, srcFineSet)&CFBnd) { // NEWREFT - removeFromFine=true; - } - } - } // FARBORD */ - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - bool removeFromFine = false; - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & reqType) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet) & (notAllowed)) ) ){ // ok - } else { - removeFromFine=true; - } - - if(removeFromFine) { - // dont turn CFGrFromFine above interface cells into CFGrNorm - //errMsg("performRefinement","Removing CFGrFromFine on lev"<<lev<<" " <<PRINT_IJK<<" srcflag:"<<convertCellFlagType2String(RFLAG(lev+1, (2*i),(2*j),(2*k), srcFineSet)) <<" set:"<<dstSet ); - RFLAG(lev, i,j,k, dstSet) = CFEmpty; -#if FSGR_STRICT_DEBUG==1 - // for interpolation later on during fine grid fixing - // these cells are still correctly inited - 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,i,j,k); - change=true; - mNumFsgrChanges++; - for(int l=1; l<this->cDirNum; l++) { - int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; - //errMsg("performRefinement","On lev:"<<lev<<" check: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet<<" = "<<convertCellFlagType2String(RFLAG(lev, ni,nj,nk, srcSet)) ); - if( ( RFLAG(lev, ni,nj,nk, srcSet)&CFFluid ) && - (!(RFLAG(lev, ni,nj,nk, srcSet)&CFGrFromFine)) ) { // dont change status of nb. from fine cells - // tag as inited for debugging, cell contains fluid DFs anyway - RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromFine|CFGrCoarseInited; - //errMsg("performRefinement","On lev:"<<lev<<" set to from fine: "<<PRINT_VEC(ni,nj,nk)<<" set:"<<dstSet); - //if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - } - } // l - - // FIXME fix fine level? - } - - // recheck from fine flag - } - }}} // TEST - // PASS 1 */ - - - /*if( ((*pFlagSrc) & (CFGrFromCoarse)) ) { - bool invNb = false; - FORDF1 { - if(RFLAG_NB(lev, i, j, k, SRCS(lev), l) & CFUnused) { invNb = true; } - } - if(!invNb) { - *pFlagSrc = CFFluid|CFGrNorm; - errMsg("coarseAdvance","FC2NRM_CHECK Converted CFGrFromCoarse to Norm at "<<lev<<" "<<PRINT_IJK); - } - } // */ - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST - for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST - for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST - - // test from coarseAdvance - // from coarse cells without unused nbs are not necessary...! -> remove - - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromCoarse) { - - // from coarse cells without unused nbs are not necessary...! -> remove - bool invNb = false; - bool fluidNb = false; - for(int l=1; l<this->cDirNum; l++) { - if(RFLAG_NB(lev, i, j, k, srcSet, l) & CFUnused) { invNb = true; } - if(RFLAG_NB(lev, i, j, k, srcSet, l) & (CFGrNorm)) { fluidNb = true; } - } - if(!invNb) { - // no unused cells around -> calculate normally from now on - RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - } // from advance - if(!fluidNb) { - // 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - } // from advance - - - // dont allow double transfer - // this might require fixing the neighborhood - if(RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse)) { - // dont turn CFGrFromFine above interface cells into CFGrNorm - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<lev<<" " <<PRINT_IJK<<" due to finer from coarse cell " ); - RFLAG(lev, i,j,k, dstSet) = CFFluid|CFGrNorm; - if(lev>0) RFLAG(lev-1, i/2,j/2,k/2, mLevel[lev-1].setCurr) &= (~CFGrToFine); // TODO add more of these? - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev, i, j, k); - change=true; - mNumFsgrChanges++; - for(int l=1; l<this->cDirNum; l++) { - int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; - if(RFLAG(lev, ni,nj,nk, srcSet)&(CFGrNorm)) { //ok - for(int m=1; m<this->cDirNum; m++) { - int mi= ni +this->dfVecX[m], mj= nj +this->dfVecY[m], mk= nk +this->dfVecZ[m]; - if(RFLAG(lev, mi, mj, mk, srcSet)&CFUnused) { - // norm cells in neighborhood with unused nbs have to be new border... - RFLAG(lev, ni,nj,nk, dstSet) = CFFluid|CFGrFromCoarse; - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - } - } - // these alreay have valid values... - } - 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((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev,ni,nj,nk); - mNumFsgrChanges++; - } - } // l - } // double transer - - } // from coarse - - } } } - // PASS 2 */ - - - // fix dstSet from fine cells here - // warning - checks CFGrFromFine on dstset changed before! - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { // TEST - for(int j=1;j<mLevel[lev].lSizey-1;++j) { // TEST - for(int i=1;i<mLevel[lev].lSizex-1;++i) { // TEST - - //if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - if(RFLAG(lev, i,j,k, dstSet) & CFGrFromFine) { - // modify finer level border - if((RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)&(CFGrFromCoarse))) { - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" from l"<<lev<<" " <<PRINT_IJK ); - CellFlagType setf = CFFluid; - if(lev+1 < mMaxRefine) setf = CFFluid|CFGrNorm; - RFLAG(lev+1, 2*i,2*j,2*k, srcFineSet)=setf; - change=true; - mNumFsgrChanges++; - for(int l=1; l<this->cDirNum; l++) { - int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; - if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFGrFromCoarse)) { - //errMsg("performRefinement","Removing CFGrFromCoarse on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); - RFLAG(lev+1, bi, bj, bk, srcFineSet) = setf; - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); - } - else if(RFLAG(lev+1, bi, bj, bk, srcFineSet)&(CFUnused )) { - //errMsg("performRefinement","Removing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(bi,bj,bk) ); - interpolateCellFromCoarse(lev+1, bi, bj, bk, srcFineSet, interTime, setf, false); - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,bi,bj,bk); - mNumFsgrChanges++; - } - } - for(int l=1; l<this->cDirNum; l++) { - int bi=(2*i)+this->dfVecX[l], bj=(2*j)+this->dfVecY[l], bk=(2*k)+this->dfVecZ[l]; - if( (RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFFluid ) && - (!(RFLAG(lev+1, bi, bj, bk, srcFineSet)&CFGrFromCoarse)) ) { - // all unused nbs now of coarse have to be from coarse - for(int m=1; m<this->cDirNum; m++) { - int mi= bi +this->dfVecX[m], mj= bj +this->dfVecY[m], mk= bk +this->dfVecZ[m]; - if(RFLAG(lev+1, mi, mj, mk, srcFineSet)&CFUnused) { - //errMsg("performRefinement","Changing CFUnused on lev"<<(lev+1)<<" "<<PRINT_VEC(mi,mj,mk) ); - interpolateCellFromCoarse(lev+1, mi, mj, mk, srcFineSet, interTime, CFFluid|CFGrFromCoarse, false); - if((LBMDIM==2)&&(debugRefinement)) debugMarkCell(lev+1,mi,mj,mk); - mNumFsgrChanges++; - } - } - // nbs prepared... - } - } - } - - } // convert regions of from fine - }}} // TEST - // PASS 3 */ - - if(!this->mSilent){ errMsg("performRefinement"," for l"<<lev<<" done ("<<change<<") " ); } - } // PASS 1-3 - // refinement done - - //LbmFsgrSolver::performCoarsening(int lev) { - { // PASS 4,5 - bool nbsok; - // WARNING - // now work on modified curr set - const int srcSet = mLevel[lev].setCurr; - const int dstlev = lev+1; - const int dstFineSet = mLevel[dstlev].setCurr; - const bool debugCoarsening = false; - - // PASS 5 test DEBUG - /*if(this->mInitDone) { - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { - // check empty -> from fine conversion - bool changeToFromFine = false; - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ - changeToFromFine=true; } - if(changeToFromFine) { - change = true; - mNumFsgrChanges++; - RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; - 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); - } - } // only check empty cells - }}} // TEST! - } // PASS 5 */ - - // use //template functions for 2D/3D - /*if(strstr(this->getName().c_str(),"Debug")) - if((nbsok)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l<this->cDirNum) && (nbsok)); l++) { // FARBORD - int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT - nbsok=false; - } - } - } // FARBORD */ - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - // from coarse cells without unused nbs are not necessary...! -> remove - // perform check from coarseAdvance here? - if(RFLAG(lev, i,j,k, srcSet) & CFGrFromFine) { - // remove from fine cells now that are completely in fluid - // FIXME? check that new from fine in performRefinement never get deleted here afterwards? - // or more general, one cell never changed more than once? - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - //const CellFlagType notNbAllowed = (CFInter|CFBnd|CFGrFromFine); unused - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - - nbsok = true; - for(int l=0; l<this->cDirNum && nbsok; l++) { - int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; - if( (RFLAG(lev+1, ni,nj,nk, dstFineSet) & reqType) && - (!(RFLAG(lev+1, ni,nj,nk, dstFineSet) & (notAllowed)) ) ){ - // ok - } else { - nbsok=false; - } - // FARBORD - } - // dont turn CFGrFromFine above interface cells into CFGrNorm - // now check nbs on same level - for(int l=1; l<this->cDirNum && nbsok; l++) { - int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l]; - if(RFLAG(lev, ni,nj,nk, srcSet)&(CFFluid)) { //ok - } else { - nbsok = false; - } - } // l - - if(nbsok) { - // conversion to coarse fluid cell - change = true; - mNumFsgrChanges++; - RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrNorm; - // dfs are already ok... - //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine changed to CFGrNorm at lev"<<lev<<" " <<PRINT_IJK ); - if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); - - // only check complete cubes - for(int dx=-1;dx<=1;dx+=2) { - for(int dy=-1;dy<=1;dy+=2) { - for(int dz=-1*(LBMDIM&1);dz<=1*(LBMDIM&1);dz+=2) { // 2d/3d - // check for norm and from coarse, as the coarse level might just have been refined... - if( - // we now the flag of the current cell! ( RFLAG(lev, i , j , k , srcSet)&(CFGrNorm)) && - ( RFLAG(lev, i+dx, j , k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - - ( RFLAG(lev, i+dx, j+dy, k , srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i+dx, j , k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i , j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) && - ( RFLAG(lev, i+dx, j+dy, k+dz, srcSet)&(CFGrNorm|CFGrFromCoarse)) - ) { - // middle source node on higher level - int dstx = (2*i)+dx; - int dsty = (2*j)+dy; - int dstz = (2*k)+dz; - - mNumFsgrChanges++; - RFLAG(dstlev, dstx,dsty,dstz, dstFineSet) = CFUnused; - RFLAG(dstlev, dstx,dsty,dstz, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init center unused set l"<<dstlev<<" at "<<PRINT_VEC(dstx,dsty,dstz) ); - - for(int l=1; l<this->cDirNum; l++) { - int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; - if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFFluid)) { - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; - } - if(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFInter)) { - //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init CHECK Warning - deleting interface cell..."); - this->mFixMass += QCELL( dstlev, dstni,dstnj,dstnk, dstFineSet, dMass); - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFFluid|CFGrFromCoarse; - } - } // l - - // again check nb flags of all surrounding cells to see if any from coarse - // can be convted to unused - for(int l=1; l<this->cDirNum; l++) { - int dstni=dstx+this->dfVecX[l], dstnj=dsty+this->dfVecY[l], dstnk=dstz+this->dfVecZ[l]; - // have to be at least from coarse here... - //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" "<< convertCellFlagType2String(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)) ); - if(!(RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet)&(CFUnused) )) { - bool delok = true; - // careful long range here... check domain bounds? - for(int m=1; m<this->cDirNum; m++) { - int chkni=dstni+this->dfVecX[m], chknj=dstnj+this->dfVecY[m], chknk=dstnk+this->dfVecZ[m]; - if(RFLAG(dstlev, chkni,chknj,chknk, dstFineSet)&(CFUnused|CFGrFromCoarse)) { - // this nb cell is ok for deletion - } else { - delok=false; // keep it! - } - //errMsg("performCoarsening"," CHECK "<<PRINT_VEC(dstni,dstnj,dstnk)<<" to "<<PRINT_VEC( chkni,chknj,chknk )<<" f:"<< convertCellFlagType2String( RFLAG(dstlev, chkni,chknj,chknk, dstFineSet))<<" nbsok"<<delok ); - } - //errMsg("performCoarsening","CFGrFromFine subcube init unused check l"<<dstlev<<" at "<<PRINT_VEC(dstni,dstnj,dstnk)<<" ok"<<delok ); - if(delok) { - mNumFsgrChanges++; - RFLAG(dstlev, dstni,dstnj,dstnk, dstFineSet) = CFUnused; - RFLAG(dstlev, dstni,dstnj,dstnk, mLevel[dstlev].setOther) = CFUnused; // FLAGTEST - if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(dstlev,dstni,dstnj,dstnk); - } - } - } // l - // treat subcube - //ebugMarkCell(lev,i+dx,j+dy,k+dz); - //if(this->mInitDone) errMsg("performCoarsening","CFGrFromFine subcube init, dir:"<<PRINT_VEC(dx,dy,dz) ); - } - } } } - - } // ? - } // convert regions of from fine - }}} // TEST! - // PASS 4 */ - - // reinit cell area value - /*if( RFLAG(lev, i,j,k,srcSet) & CFFluid) { - if( RFLAG(lev+1, i*2,j*2,k*2,dstFineSet) & CFGrFromCoarse) { - LbmFloat totArea = mFsgrCellArea[0]; // for l=0 - for(int l=1; l<this->cDirNum; l++) { - int ni=(2*i)+this->dfVecX[l], nj=(2*j)+this->dfVecY[l], nk=(2*k)+this->dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)& - (CFGrFromCoarse|CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - //(CFUnused|CFEmpty) //? (CFBnd|CFEmpty|CFGrFromCoarse|CFUnused) - ) { - //LbmFloat area = 0.25; if(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 - QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = - QCELL(lev, i,j,k,srcSet, dFlux) = totArea; - } else { - QCELL(lev, i,j,k,mLevel[lev].setOther, dFlux) = - QCELL(lev, i,j,k,srcSet, dFlux) = 1.0; - } - //errMsg("DFINI"," at l"<<lev<<" "<<PRINT_IJK<<" v:"<<QCELL(lev, i,j,k,srcSet, dFlux) ); - } - // */ - - - // PASS 5 org - /*if(strstr(this->getName().c_str(),"Debug")) - if((changeToFromFine)&&(lev+1==mMaxRefine)) { // mixborder - for(int l=0;((l<this->cDirNum) && (changeToFromFine)); l++) { // FARBORD - int ni=2*i+2*this->dfVecX[l], nj=2*j+2*this->dfVecY[l], nk=2*k+2*this->dfVecZ[l]; - if(RFLAG(lev+1, ni,nj,nk, dstFineSet)&CFBnd) { // NEWREFT - changeToFromFine=false; } - } - }// FARBORD */ - //if(!this->mInitDone) { - for(int k= getForZMin1(); k< getForZMax1(lev); ++k) { - for(int j=1;j<mLevel[lev].lSizey-1;++j) { - for(int i=1;i<mLevel[lev].lSizex-1;++i) { - - - if(RFLAG(lev, i,j,k, srcSet) & CFEmpty) { - // check empty -> from fine conversion - bool changeToFromFine = false; - const CellFlagType notAllowed = (CFInter|CFGrFromFine|CFGrToFine); - CellFlagType reqType = CFGrNorm; - if(lev+1==mMaxRefine) reqType = CFNoBndFluid; - - if( (RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & reqType) && - (!(RFLAG(lev+1, (2*i),(2*j),(2*k), dstFineSet) & (notAllowed)) ) ){ - // DEBUG - changeToFromFine=true; - } - - // FARBORD - - if(changeToFromFine) { - change = true; - mNumFsgrChanges++; - RFLAG(lev, i,j,k, srcSet) = CFFluid|CFGrFromFine; - if((LBMDIM==2)&&(debugCoarsening)) debugMarkCell(lev,i,j,k); - // same as restr from fine func! not necessary ?! - // coarseRestrictFromFine part - } - } // only check empty cells - - }}} // TEST! - //} // init done - // PASS 5 */ - } // coarsening, PASS 4,5 - - if(!this->mSilent){ errMsg("adaptGrid"," for l"<<lev<<" done " ); } - return change; -#endif //! LBM_NOADCOARSENING==1 -} - -/*****************************************************************************/ -//! cell restriction and prolongation -/*****************************************************************************/ - -void LbmFsgrSolver::coarseRestrictCell(int lev, int i,int j,int k, int srcSet, int dstSet) -{ -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - i=j=k=srcSet=dstSet=lev =0; // get rid of warnings... -#else - LbmFloat *ccel = RACPNT(lev+1, 2*i,2*j,2*k,srcSet); - LbmFloat *tcel = RACPNT(lev , i,j,k ,dstSet); - - LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; - //LbmFloat *ccel = NULL; - //LbmFloat *tcel = NULL; -#if OPT3D==1 - LbmFloat m[LBM_DFNUM]; - // for macro add - LbmFloat usqr; - //LbmFloat *addfcel, *dstcell; - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; - LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; -#else // OPT3D==true - LbmFloat df[LBM_DFNUM]; - LbmFloat omegaDst, omegaSrc; - LbmFloat feq[LBM_DFNUM]; - LbmFloat dfScale = mDfScaleUp; -#endif // OPT3D==true - -# if OPT3D==0 - // add up weighted dfs - FORDF0{ df[l] = 0.0;} - for(int n=0;(n<this->cDirNum); n++) { - int ni=2*i+1*this->dfVecX[n], nj=2*j+1*this->dfVecY[n], nk=2*k+1*this->dfVecZ[n]; - ccel = RACPNT(lev+1, ni,nj,nk,srcSet);// CFINTTEST - const LbmFloat weight = mGaussw[n]; - FORDF0{ - LbmFloat cdf = weight * RAC(ccel,l); -# if FSGR_STRICT_DEBUG==1 - if( cdf<-1.0 ){ errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]); } -# endif - //errMsg("INVDFCREST_DFCHECK", PRINT_IJK<<" s"<<dstSet<<" from "<<PRINT_VEC(2*i,2*j,2*k)<<" s"<<srcSet<<" df"<<l<<":"<< df[l]<<" = "<<cdf<<" , w"<<weight); - df[l] += cdf; - } - } - - // calc rho etc. from weighted dfs - rho = ux = uy = uz = 0.0; - FORDF0{ - LbmFloat cdf = df[l]; - rho += cdf; - ux += (this->dfDvecX[l]*cdf); - uy += (this->dfDvecY[l]*cdf); - uz += (this->dfDvecZ[l]*cdf); - } - - FORDF0{ feq[l] = this->getCollideEq(l, rho,ux,uy,uz); } - if(mLevel[lev ].lcsmago>0.0) { - 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 ].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; - } -# else // OPT3D - // similar to OPTIMIZED_STREAMCOLLIDE_UNUSED - - //rho = ux = uy = uz = 0.0; - MSRC_C = CCELG_C(0) ; - MSRC_N = CCELG_N(0) ; - MSRC_S = CCELG_S(0) ; - MSRC_E = CCELG_E(0) ; - MSRC_W = CCELG_W(0) ; - MSRC_T = CCELG_T(0) ; - MSRC_B = CCELG_B(0) ; - MSRC_NE = CCELG_NE(0); - MSRC_NW = CCELG_NW(0); - MSRC_SE = CCELG_SE(0); - MSRC_SW = CCELG_SW(0); - MSRC_NT = CCELG_NT(0); - MSRC_NB = CCELG_NB(0); - MSRC_ST = CCELG_ST(0); - MSRC_SB = CCELG_SB(0); - MSRC_ET = CCELG_ET(0); - MSRC_EB = CCELG_EB(0); - MSRC_WT = CCELG_WT(0); - MSRC_WB = CCELG_WB(0); - for(int n=1;(n<this->cDirNum); n++) { - ccel = RACPNT(lev+1, 2*i+1*this->dfVecX[n], 2*j+1*this->dfVecY[n], 2*k+1*this->dfVecZ[n] ,srcSet); - MSRC_C += CCELG_C(n) ; - MSRC_N += CCELG_N(n) ; - MSRC_S += CCELG_S(n) ; - MSRC_E += CCELG_E(n) ; - MSRC_W += CCELG_W(n) ; - MSRC_T += CCELG_T(n) ; - MSRC_B += CCELG_B(n) ; - MSRC_NE += CCELG_NE(n); - MSRC_NW += CCELG_NW(n); - MSRC_SE += CCELG_SE(n); - MSRC_SW += CCELG_SW(n); - MSRC_NT += CCELG_NT(n); - MSRC_NB += CCELG_NB(n); - MSRC_ST += CCELG_ST(n); - MSRC_SB += CCELG_SB(n); - MSRC_ET += CCELG_ET(n); - MSRC_EB += CCELG_EB(n); - MSRC_WT += CCELG_WT(n); - MSRC_WB += CCELG_WB(n); - } - rho = MSRC_C + MSRC_N + MSRC_S + MSRC_E + MSRC_W + MSRC_T - + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT - + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; - ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW - + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB; - uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW - + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB; - uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB - + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB; - usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ - \ - lcsmeq[dC] = EQC ; \ - COLL_CALCULATE_DFEQ(lcsmeq); \ - COLL_CALCULATE_NONEQTENSOR(lev+0, MSRC_ )\ - COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \ - COLL_CALCULATE_CSMOMEGAVAL(lev+1, lcsmSrcOmega); \ - \ - 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); - RAC(tcel, dE ) = (lcsmeq[dE ] + (MSRC_E -lcsmeq[dE ] )*lcsmdfscale); - RAC(tcel, dW ) = (lcsmeq[dW ] + (MSRC_W -lcsmeq[dW ] )*lcsmdfscale); - RAC(tcel, dT ) = (lcsmeq[dT ] + (MSRC_T -lcsmeq[dT ] )*lcsmdfscale); - RAC(tcel, dB ) = (lcsmeq[dB ] + (MSRC_B -lcsmeq[dB ] )*lcsmdfscale); - RAC(tcel, dNE) = (lcsmeq[dNE] + (MSRC_NE-lcsmeq[dNE] )*lcsmdfscale); - RAC(tcel, dNW) = (lcsmeq[dNW] + (MSRC_NW-lcsmeq[dNW] )*lcsmdfscale); - RAC(tcel, dSE) = (lcsmeq[dSE] + (MSRC_SE-lcsmeq[dSE] )*lcsmdfscale); - RAC(tcel, dSW) = (lcsmeq[dSW] + (MSRC_SW-lcsmeq[dSW] )*lcsmdfscale); - RAC(tcel, dNT) = (lcsmeq[dNT] + (MSRC_NT-lcsmeq[dNT] )*lcsmdfscale); - RAC(tcel, dNB) = (lcsmeq[dNB] + (MSRC_NB-lcsmeq[dNB] )*lcsmdfscale); - RAC(tcel, dST) = (lcsmeq[dST] + (MSRC_ST-lcsmeq[dST] )*lcsmdfscale); - RAC(tcel, dSB) = (lcsmeq[dSB] + (MSRC_SB-lcsmeq[dSB] )*lcsmdfscale); - RAC(tcel, dET) = (lcsmeq[dET] + (MSRC_ET-lcsmeq[dET] )*lcsmdfscale); - RAC(tcel, dEB) = (lcsmeq[dEB] + (MSRC_EB-lcsmeq[dEB] )*lcsmdfscale); - RAC(tcel, dWT) = (lcsmeq[dWT] + (MSRC_WT-lcsmeq[dWT] )*lcsmdfscale); - RAC(tcel, dWB) = (lcsmeq[dWB] + (MSRC_WB-lcsmeq[dWB] )*lcsmdfscale); -# endif // OPT3D==0 -#endif //! LBM_NOADCOARSENING==1 -} - -void LbmFsgrSolver::interpolateCellFromCoarse(int lev, int i, int j,int k, int dstSet, LbmFloat t, CellFlagType flagSet, bool markNbs) { -#if LBM_NOADCOARSENING==1 - if(mMaxRefine>0) errMsg("LbmFsgrSolver","Adaptive Coarsening not compiled, but refinement switched on ("<<mMaxRefine<<")!"); - i=j=k=dstSet=lev =0; // get rid of warnings... - t=0.0; flagSet=0; markNbs=false; -#else - LbmFloat rho=0.0, ux=0.0, uy=0.0, uz=0.0; - LbmFloat intDf[19] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; - -#if OPT3D==1 - // for macro add - LbmFloat addDfFacT, addVal, usqr; - LbmFloat *addfcel, *dstcell; - LbmFloat lcsmqadd, lcsmqo, lcsmeq[LBM_DFNUM]; - LbmFloat lcsmDstOmega, lcsmSrcOmega, lcsmdfscale; -#endif // OPT3D==true - - // SET required nbs to from coarse (this might overwrite flag several times) - // this is not necessary for interpolateFineFromCoarse - if(markNbs) { - FORDF1{ - 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); - } - } } - - // change flag of cell to be interpolated - RFLAG(lev,i,j,k, dstSet) = flagSet; - mNumInterdCells++; - - // interpolation lines... - int betx = i&1; - int bety = j&1; - int betz = k&1; - - if((!betx) && (!bety) && (!betz)) { - ADD_INT_DFS(lev-1, i/2 ,j/2 ,k/2 , 0.0, 1.0); - } - else if(( betx) && (!bety) && (!betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D1); - } - else if((!betx) && ( bety) && (!betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D1); - } - else if((!betx) && (!bety) && ( betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D1); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D1); - } - else if(( betx) && ( bety) && (!betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D2); - } - else if((!betx) && ( bety) && ( betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D2); - } - else if(( betx) && (!bety) && ( betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D2); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D2); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D2); - } - else if(( betx) && ( bety) && ( betz)) { - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2) ,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2) ,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2) , t, WO1D3); - ADD_INT_DFS(lev-1, (i/2) ,(j/2)+1,(k/2)+1, t, WO1D3); - ADD_INT_DFS(lev-1, (i/2)+1,(j/2)+1,(k/2)+1, t, WO1D3); - } - else { - CAUSE_PANIC; - errFatal("interpolateCellFromCoarse","Invalid!?", SIMWORLD_GENERICERROR); - } - - IDF_WRITEBACK; - return; -#endif //! LBM_NOADCOARSENING==1 -} - - - -/*****************************************************************************/ -/*! change the size of the LBM time step */ -/*****************************************************************************/ -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].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 = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity - LbmFloat nextmax = this->mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity); - - //newdt = this->mpParam->getTimestep() * (allowMax/nextmax); - LbmFloat newdt = this->mpParam->getTimestep(); // newtr - if(nextmax > allowMax/fac) { - mTimeMaxvelStepCnt++; } - else { mTimeMaxvelStepCnt=0; } - - // emergency, or 10 steps with high vel - if((mTimeMaxvelStepCnt>5) || (nextmax> (1.0/3.0) ) ) { - //if(nextmax > allowMax/fac) { - newdt = this->mpParam->getTimestep() * fac; - } else { - if(nextmax<allowMax*fac) { - newdt = this->mpParam->getTimestep() / fac; - } - } // newtr - //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<fac<<" simmaxv="<< this->mpParam->getSimulationMaxSpeed() ); - - bool minCutoff = false; - LbmFloat desireddt = newdt; - if(newdt>this->mpParam->getMaxTimestep()){ newdt = this->mpParam->getMaxTimestep(); } - if(newdt<this->mpParam->getMinTimestep()){ - newdt = this->mpParam->getMinTimestep(); - if(nextmax>allowMax/fac){ minCutoff=true; } // only if really large vels... - } - - LbmFloat dtdiff = fabs(newdt - this->mpParam->getTimestep()); - if(!this->mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "new"<<newdt<<" max"<<this->mpParam->getMaxTimestep()<<" min"<<this->mpParam->getMinTimestep()<<" diff"<<dtdiff<< - " simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxTimestep)<<" maxsteps:"<<(mSimulationTime/mMinTimestep) , 10); } - - // in range, and more than X% change? - //if( newdt < this->mpParam->getTimestep() ) // DEBUG - LbmFloat rhoAvg = mCurrentMass/mCurrentVolume; - if( (newdt<=this->mpParam->getMaxTimestep()) && (newdt>=this->mpParam->getMinTimestep()) - && (dtdiff>(this->mpParam->getTimestep()*diffPercent)) ) { - if((newdt>levOldStepsize[mMaxRefine])&&(mTimestepReduceLock)) { - // wait some more... - //debMsgNnl("LbmFsgrSolver::TAdp",DM_NOTIFY," Delayed... "<<mTimestepReduceLock<<" ",10); - debMsgDirect("D"); - } else { - this->mpParam->setDesiredTimestep( newdt ); - rescale = true; - if(!this->mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"\n\n\n\n",10); - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: new="<<newdt<<" old="<<this->mpParam->getTimestep()<<" maxSpeed:"<<this->mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<this->mStepCnt, 10 ); - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep change: "<< - "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10); - } - } // really change dt - } - - if(mTimestepReduceLock>0) mTimestepReduceLock--; - - - // forced back and forth switchting (for testing) - /*const int tadtogInter = 100; - const double tadtogSwitch = 0.66; - errMsg("TIMESWITCHTOGGLETEST","warning enabled "<< tadtogSwitch<<","<<tadtogSwitch<<" !!!!!!!!!!!!!!!!!!!"); - if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) || - ((this->mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){ - rescale = true; minCutoff = false; - newdt = tadtogSwitch * this->mpParam->getTimestep(); - this->mpParam->setDesiredTimestep( newdt ); - } else - if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) || - ((this->mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){ - rescale = true; minCutoff = false; - newdt = this->mpParam->getTimestep()/tadtogSwitch ; - this->mpParam->setDesiredTimestep( newdt ); - } else { - rescale = false; minCutoff = false; - } - // */ - - // test mass rescale - - scaleFac = newdt/this->mpParam->getTimestep(); - if(rescale) { - // 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++; - this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent ); - recalculateObjectSpeeds(); - // calc omega, force for all levels - mLastOmega=1e10; mLastGravity=1e10; - initLevelOmegas(); - if(this->mpParam->getTimestep()<mMinTimestep) mMinTimestep = this->mpParam->getTimestep(); - if(this->mpParam->getTimestep()>mMaxTimestep) mMaxTimestep = this->mpParam->getTimestep(); - - // this might be called during init, before we have any particles - if(mpParticles) { mpParticles->adaptPartTimestep(scaleFac); } -#if LBM_INCLUDE_TESTSOLVERS==1 - if((mUseTestdata)&&(mpTest)) { - mpTest->adaptTimestep(scaleFac, mLevel[mMaxRefine].omega, mLevel[mMaxRefine].timestep, vec2L( mpParam->calculateGravity(mSimulationTime)) ); - } -#endif // LBM_INCLUDE_TESTSOLVERS!=1 - - for(int lev=mMaxRefine; lev>=0 ; lev--) { - LbmFloat newSteptime = mLevel[lev].timestep; - LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); - - if(!this->mSilent) { - debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<<lev<<" Timestep change: "<< - " scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10); - } - if(lev!=mMaxRefine) coarseCalculateFluxareas(lev); - - int wss = 0, wse = 1; - // only change currset (necessary for compressed grids, better for non-compr.gr.) - wss = wse = mLevel[lev].setCurr; - for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT - // warning - check sets for higher levels...? - FSGR_FORIJK1(lev) { - if( (RFLAG(lev,i,j,k, workSet) & CFBndMoving) ) { - /* - // paranoid check - shouldnt be necessary! - if(QCELL(lev, i, j, k, workSet, dFlux)!=mSimulationTime) { - errMsg("TTTT","found invalid bnd cell.... removing at "<<PRINT_IJK); - RFLAG(lev,i,j,k, workSet) = CFInter; - // init empty zero vel interface cell... - initVelocityCell(lev, i,j,k, CFInter, 1.0, 0.01, LbmVec(0.) ); - } else {// */ - for(int l=0; l<this->cDfNum; l++) { - QCELL(lev, i, j, k, workSet, l) = QCELL(lev, i, j, k, workSet, l)* scaleFac; - } - //} // ok - continue; - } - if( - (RFLAG(lev,i,j,k, workSet) & CFFluid) || - (RFLAG(lev,i,j,k, workSet) & CFInter) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || - (RFLAG(lev,i,j,k, workSet) & CFGrNorm) - ) { - // these cells have to be scaled... - } else { - continue; - } - - // collide on current set - LbmFloat rhoOld; - LbmVec velOld; - LbmFloat rho, ux,uy,uz; - rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l<this->cDfNum; l++) { - LbmFloat m = QCELL(lev, i, j, k, workSet, l); - rho += m; - ux += (this->dfDvecX[l]*m); - uy += (this->dfDvecY[l]*m); - uz += (this->dfDvecZ[l]*m); - } - rhoOld = rho; - velOld = LbmVec(ux,uy,uz); - - LbmFloat rhoNew = (rhoOld-rhoAvg)*scaleFac +rhoAvg; - LbmVec velNew = velOld * scaleFac; - - LbmFloat df[LBM_DFNUM]; - LbmFloat feqOld[LBM_DFNUM]; - LbmFloat feqNew[LBM_DFNUM]; - for(int l=0; l<this->cDfNum; l++) { - feqOld[l] = this->getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] ); - feqNew[l] = this->getCollideEq(l,rhoNew, velNew[0],velNew[1],velNew[2] ); - df[l] = QCELL(lev, i,j,k,workSet, l); - } - const LbmFloat Qo = this->getLesNoneqTensorCoeff(df,feqOld); - const LbmFloat oldOmega = this->getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo); - const LbmFloat newOmega = this->getLesOmega(mLevel[lev].omega,mLevel[lev].lcsmago,Qo); - //newOmega = mLevel[lev].omega; // FIXME debug test - - //LbmFloat dfScaleFac = (newSteptime/1.0)/(levOldStepsize[lev]/levOldOmega[lev]); - const LbmFloat dfScale = (newSteptime/newOmega)/(levOldStepsize[lev]/oldOmega); - //dfScale = dfScaleFac/newOmega; - - for(int l=0; l<this->cDfNum; l++) { - // org scaling - //df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important - // new scaling - LbmFloat dfn = feqNew[l] + (df[l]-feqOld[l])*dfScale*feqNew[l]/feqOld[l]; // non-eq. scaling, important - //df = eqNew + (df-eqOld)*dfScale; // modified ig scaling, no real difference? - QCELL(lev, i,j,k,workSet, l) = dfn; - } - - if(RFLAG(lev,i,j,k, workSet) & CFInter) { - //if(workSet==mLevel[lev].setCurr) - LbmFloat area = 1.0; - if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux); - massTOld += QCELL(lev, i,j,k,workSet, dMass) * area; - volTOld += QCELL(lev, i,j,k,workSet, dFfrac); - - // wrong... QCELL(i,j,k,workSet, dMass] = (QCELL(i,j,k,workSet, dFfrac]*rhoNew); - QCELL(lev, i,j,k,workSet, dMass) = (QCELL(lev, i,j,k,workSet, dMass)/rhoOld*rhoNew); - QCELL(lev, i,j,k,workSet, dFfrac) = (QCELL(lev, i,j,k,workSet, dMass)/rhoNew); - - //if(workSet==mLevel[lev].setCurr) - massTNew += QCELL(lev, i,j,k,workSet, dMass); - volTNew += QCELL(lev, i,j,k,workSet, dFfrac); - } - if(RFLAG(lev,i,j,k, workSet) & CFFluid) { // DEBUG - if(RFLAG(lev,i,j,k, workSet) & (CFGrFromFine|CFGrFromCoarse)) { // DEBUG - // dont include - } else { - LbmFloat area = 1.0; - if(lev!=mMaxRefine) area = QCELL(lev, i,j,k,workSet, dFlux) * mLevel[lev].lcellfactor; - //if(workSet==mLevel[lev].setCurr) - massTOld += rhoOld*area; - //if(workSet==mLevel[lev].setCurr) - massTNew += rhoNew*area; - volTOld += area; - volTNew += area; - } - } - - } // IJK - } // workSet - - } // lev - - if(!this->mSilent) { - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<this->mStepCnt<< - " no"<<mTimeSwitchCounts<<" maxdt"<<mMaxTimestep<< - " mindt"<<mMinTimestep<<" currdt"<<mLevel[mMaxRefine].timestep, 10); - debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE masst:"<<massTNew<<","<<massTOld<<" org:"<<mCurrentMass<<"; "<< - " volt:"<<volTNew<<","<<volTOld<<" org:"<<mCurrentVolume, 10); - } else { - debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep change by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt - <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<this->mOmega<<" gStar:"<<this->mpParam->getCurrentGStar() , 10); - } - } // rescale? - //NEWDEBCHECK("tt2"); - - //errMsg("adaptTimestep","Warning - brute force rescale off!"); minCutoff = false; // DEBUG - if(minCutoff) { - errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<this->mName<<" step:"<<this->mStepCnt<<" newdt="<<desireddt<<" mindt="<<this->mpParam->getMinTimestep()<<") " ); - //brute force resacle all the time? - - for(int lev=mMaxRefine; lev>=0 ; lev--) { - int rescs=0; - int wss = 0, wse = 1; -#if COMPRESSGRIDS==1 - if(lev== mMaxRefine) wss = wse = mLevel[lev].setCurr; -#endif // COMPRESSGRIDS==1 - for(int workSet = wss; workSet<=wse; workSet++) { // COMPRT - //for(int workSet = 0; workSet<=1; workSet++) { - FSGR_FORIJK1(lev) { - - //if( (RFLAG(lev, i,j,k, workSet) & CFFluid) || (RFLAG(lev, i,j,k, workSet) & CFInter) ) { - if( - (RFLAG(lev,i,j,k, workSet) & CFFluid) || - (RFLAG(lev,i,j,k, workSet) & CFInter) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromCoarse) || - (RFLAG(lev,i,j,k, workSet) & CFGrFromFine) || - (RFLAG(lev,i,j,k, workSet) & CFGrNorm) - ) { - // these cells have to be scaled... - } else { - continue; - } - - // collide on current set - LbmFloat rho, ux,uy,uz; - rho=0.0; ux = uy = uz = 0.0; - for(int l=0; l<this->cDfNum; l++) { - LbmFloat m = QCELL(lev, i, j, k, workSet, l); - rho += m; - ux += (this->dfDvecX[l]*m); - uy += (this->dfDvecY[l]*m); - uz += (this->dfDvecZ[l]*m); - } -#ifndef WIN32 - if (!finite(rho)) { - errMsg("adaptTimestep","Brute force non-finite rho at"<<PRINT_IJK); // DEBUG! - rho = 1.0; - ux = uy = uz = 0.0; - QCELL(lev, i, j, k, workSet, dMass) = 1.0; - QCELL(lev, i, j, k, workSet, dFfrac) = 1.0; - } -#endif // WIN32 - - if( (ux*ux+uy*uy+uz*uz)> (allowMax*allowMax) ) { - LbmFloat cfac = allowMax/sqrt(ux*ux+uy*uy+uz*uz); - ux *= cfac; - uy *= cfac; - uz *= cfac; - for(int l=0; l<this->cDfNum; l++) { - QCELL(lev, i, j, k, workSet, l) = this->getCollideEq(l, rho, ux,uy,uz); } - rescs++; - debMsgDirect("B"); - } - - } } - //if(rescs>0) { errMsg("adaptTimestep","!!!!! Brute force rescaling was necessary !!!!!!!"); } - debMsgStd("adaptTimestep",DM_MSG,"Brute force rescale done. level:"<<lev<<" rescs:"<<rescs, 1); - //TTT mNumProblems += rescs; // add to problem display... - } // lev,set,ijk - - } // try brute force rescale? - - // time adap done... -} - - /****************************************************************************** @@ -2424,13 +1173,13 @@ void LbmFsgrSolver::addToNewInterList( int ni, int nj, int nk ) { } */ #endif // FSGR_STRICT_DEBUG==1 // store point - LbmPoint newinter; + LbmPoint newinter; newinter.flag = 0; newinter.x = ni; newinter.y = nj; newinter.z = nk; mListNewInter.push_back(newinter); } -void LbmFsgrSolver::reinitFlags( int workSet ) { - // OLD mods: +void LbmFsgrSolver::reinitFlags( int workSet ) { + // reinitCellFlags OLD mods: // add all to intel list? // check ffrac for new cells // new if cell inits (last loop) @@ -2507,9 +1256,6 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { /* remove empty interface cells that are not allowed to be removed anyway * this is important, otherwise the dreaded cell-type-flickering can occur! */ - //for( vector<LbmPoint>::iterator iter=mListEmpty.begin(); iter != mListEmpty.end(); iter++ ) { - //int i=iter->x, j=iter->y, k=iter->z; - //iter = mListEmpty.erase(iter); iter--; // and continue with next... for(int n=0; n<(int)mListEmpty.size(); n++) { int i=mListEmpty[n].x, j=mListEmpty[n].y, k=mListEmpty[n].z; if((RFLAG(workLev,i,j,k, workSet)&(CFInter|CFNoDelete)) == (CFInter|CFNoDelete)) { @@ -2555,7 +1301,6 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { } /* for symmetry, set our flag right now */ - //RFLAG(workLev,i,j,k, workSet) = CFEmpty; changeFlag(workLev,i,j,k, workSet, CFEmpty); // mark cell not be changed mass... - not necessary, not in list anymore anyway! } // emptylist @@ -2564,7 +1309,7 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { // precompute weights to get rid of order dependancies vector<lbmFloatSet> vWeights; - vWeights.reserve( mListFull.size() + mListEmpty.size() ); + vWeights.resize( mListFull.size() + mListEmpty.size() ); int weightIndex = 0; int nbCount = 0; LbmFloat nbWeights[LBM_DFNUM]; @@ -2577,7 +1322,8 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { 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); + if(iter->flag&1) nbWeights[l] = 1.; // NEWSURFT + else nbWeights[l] = getMassdWeight(1,i,j,k,workSet,l); // NEWSURFT nbTotWeights += nbWeights[l]; } else { nbWeights[l] = -100.0; // DEBUG; @@ -2601,7 +1347,8 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { 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); + if(iter->flag&1) nbWeights[l] = 1.; // NEWSURFT + else nbWeights[l] = getMassdWeight(0,i,j,k,workSet,l); // NEWSURFT nbTotWeights += nbWeights[l]; } else { nbWeights[l] = -100.0; // DEBUG; @@ -2629,17 +1376,6 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { FORDF1 { myrho += QCELL(workLev,i,j,k, workSet, l); } // QCELL.rho LbmFloat massChange = QCELL(workLev,i,j,k, workSet, dMass) - myrho; - /*int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - FORDF1 { - 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 { } - }*/ - - //errMsg("FDIST", PRINT_IJK<<" mss"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM if(vWeights[weightIndex].numNbs>0.0) { const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("FF I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); @@ -2668,8 +1404,6 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { // already done? RFLAG(workLev,i,j,k, workSet) = CFFluid; QCELL(workLev,i,j,k, workSet, dMass) = myrho; // should be rho... but unused? QCELL(workLev,i,j,k, workSet, dFfrac) = 1.0; // should be rho... but unused? - /*QCELL(workLev,i,j,k, otherSet, dMass) = myrho; // NEW? - QCELL(workLev,i,j,k, otherSet, dFfrac) = 1.0; // NEW? COMPRT */ } // fulllist @@ -2680,20 +1414,6 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { int i=iter->x, j=iter->y, k=iter->z; LbmFloat massChange = QCELL(workLev, i,j,k, workSet, dMass); - /*int nbCount = 0; - LbmFloat nbWeights[LBM_DFNUM]; - FORDF1 { - 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 { - nbWeights[l] = -100.0; // DEBUG; - } - }*/ - - //errMsg("EDIST", PRINT_IJK<<" mss"<<massChange <<" nb"<< nbCount ); // DEBUG SYMM - //if(nbCount>0) { if(vWeights[weightIndex].numNbs>0.0) { const LbmFloat nbTotWeightsp = vWeights[weightIndex].val[0]; //errMsg("EE I", PRINT_IJK<<" "<<weightIndex<<" "<<nbTotWeightsp); @@ -2726,10 +1446,7 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { for( vector<LbmPoint>::iterator iter=mListEmpty.begin(); iter != mListEmpty.end(); iter++ ) { int i=iter->x, j=iter->y, k=iter->z; - //RFLAG(workLev,i,j,k, otherSet) = CFEmpty; changeFlag(workLev,i,j,k, otherSet, CFEmpty); - /*QCELL(workLev,i,j,k, otherSet, dMass) = 0.0; - QCELL(workLev,i,j,k, otherSet, dFfrac) = 0.0; // COMPRT OFF */ } @@ -2750,6 +1467,7 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { } // redistribute mass, reinit flags + if(debugFlagreinit) errMsg("NEWIF", "total:"<<mListNewInter.size()); float newIfFac = 1.0/(LbmFloat)numNewIf; for( vector<LbmPoint>::iterator iter=mListNewInter.begin(); iter != mListNewInter.end(); iter++ ) { @@ -2766,17 +1484,17 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { } // */ QCELL(workLev,i,j,k, workSet, dMass) += (this->mFixMass * newIfFac); - + int nbored = 0; FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); } - if((nbored & CFBnd)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoBndFluid; } - if((nbored & CFFluid)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbFluid; } - if((nbored & CFEmpty)==0) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbEmpty; } + if(!(nbored & CFBndNoslip)) { RFLAG(workLev,i,j,k, workSet) |= CFNoBndFluid; } + if(!(nbored & CFFluid)) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbFluid; } + if(!(nbored & CFEmpty)) { RFLAG(workLev,i,j,k, workSet) |= CFNoNbEmpty; } if(!(RFLAG(workLev,i,j,k, otherSet)&CFInter)) { RFLAG(workLev,i,j,k, workSet) = (CellFlagType)(RFLAG(workLev,i,j,k, workSet) | CFNoDelete); } - if(debugFlagreinit) errMsg("NEWIF", PRINT_IJK<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" f"<< RFLAG(workLev,i,j,k, workSet)<<" wl"<<workLev ); + if(debugFlagreinit) errMsg("NEWIF", PRINT_IJK<<" mss"<<QCELL(workLev, i,j,k, workSet, dMass) <<" f"<< convertCellFlagType2String(RFLAG(workLev,i,j,k, workSet))<<" wl"<<workLev ); } // reinit fill fraction @@ -2803,10 +1521,4 @@ void LbmFsgrSolver::reinitFlags( int workSet ) { } // reinitFlags -/****************************************************************************** - * instantiation - *****************************************************************************/ - -//! lbm factory functions -LbmSolverInterface* createSolver() { return new LbmFsgrSolver(); } diff --git a/intern/elbeem/intern/solver_relax.h b/intern/elbeem/intern/solver_relax.h index 2a618ce00bf..eba6742169e 100644 --- a/intern/elbeem/intern/solver_relax.h +++ b/intern/elbeem/intern/solver_relax.h @@ -17,8 +17,19 @@ +#if LBM_INCLUDE_TESTSOLVERS!=1 + // off for non testing -#define PRECOLLIDE_MODS(rho,ux,uy,uz) +#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \ + ux += (grav)[0]; \ + uy += (grav)[1]; \ + uz += (grav)[2]; \ + +#else // LBM_INCLUDE_TESTSOLVERS!=1 + +// defined in test.h + +#endif // LBM_INCLUDE_TESTSOLVERS!=1 /****************************************************************************** @@ -269,7 +280,6 @@ if(nbf & CFBndNoslip) { \ /* no slip, default */ \ m[l] = RAC(ccel, this->dfInv[l] ); /* noslip */ \ - if(nbf&CFBndMoving) m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \ STREAMCHECK(2, i,j,k, l); \ } else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \ /* free slip */ \ @@ -284,6 +294,7 @@ else {\ errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<this->dfInv[l] ); \ } \ + if(nbf&CFBndMoving) m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \ } else { \ m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \ STREAMCHECK(4, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \ @@ -292,8 +303,8 @@ // careful ux,uy,uz need to be inited before! -#define DEFAULT_COLLIDE \ - this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \ +#define DEFAULT_COLLIDEG(grav) \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), grav, mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -307,8 +318,8 @@ 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]; \ - this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ + /* ux = mLevel[lev].gravity[0]; uy = [1]; uz = mLevel[lev].gravity[2]; */ \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].gravity, mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -352,18 +363,18 @@ if(nbflag[dT ]&CFBnd) { m[dB ] = RAC(ccel,dT ); LBMDS_ADDMOV(dT ,dB ); } else { m[dB ] = CSRC_B ; } \ \ /* also treat free slip here */ \ - if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); LBMDS_ADDMOV(dSW,dNE); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} } else { m[dNE] = CSRC_NE; } \ - if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); LBMDS_ADDMOV(dSE,dNW); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} } else { m[dNW] = CSRC_NW; } \ - if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); LBMDS_ADDMOV(dNW,dSE); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} } else { m[dSE] = CSRC_SE; } \ - if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); LBMDS_ADDMOV(dNE,dSW); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} } else { m[dSW] = CSRC_SW; } \ - if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); LBMDS_ADDMOV(dSB,dNT); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} } else { m[dNT] = CSRC_NT; } \ - if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); LBMDS_ADDMOV(dST,dNB); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} } else { m[dNB] = CSRC_NB; } \ - if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); LBMDS_ADDMOV(dNB,dST); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} } else { m[dST] = CSRC_ST; } \ - if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); LBMDS_ADDMOV(dNT,dSB); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} } else { m[dSB] = CSRC_SB; } \ - if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); LBMDS_ADDMOV(dWB,dET); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} } else { m[dET] = CSRC_ET; } \ - if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); LBMDS_ADDMOV(dWT,dEB); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} } else { m[dEB] = CSRC_EB; } \ - if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); LBMDS_ADDMOV(dEB,dWT); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} } else { m[dWT] = CSRC_WT; } \ - if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); LBMDS_ADDMOV(dET,dWB); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} } else { m[dWB] = CSRC_WB; } \ + if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); LBMDS_ADDMOV(dSW,dNE); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} LBMDS_ADDMOV(dSW,dNE); } else { m[dNE] = CSRC_NE; } \ + if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); LBMDS_ADDMOV(dSE,dNW); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} LBMDS_ADDMOV(dSE,dNW); } else { m[dNW] = CSRC_NW; } \ + if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); LBMDS_ADDMOV(dNW,dSE); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} LBMDS_ADDMOV(dNW,dSE); } else { m[dSE] = CSRC_SE; } \ + if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); LBMDS_ADDMOV(dNE,dSW); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} LBMDS_ADDMOV(dNE,dSW); } else { m[dSW] = CSRC_SW; } \ + if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); LBMDS_ADDMOV(dSB,dNT); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} LBMDS_ADDMOV(dSB,dNT); } else { m[dNT] = CSRC_NT; } \ + if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); LBMDS_ADDMOV(dST,dNB); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} LBMDS_ADDMOV(dST,dNB); } else { m[dNB] = CSRC_NB; } \ + if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); LBMDS_ADDMOV(dNB,dST); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} LBMDS_ADDMOV(dNB,dST); } else { m[dST] = CSRC_ST; } \ + if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); LBMDS_ADDMOV(dNT,dSB); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} LBMDS_ADDMOV(dNT,dSB); } else { m[dSB] = CSRC_SB; } \ + if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); LBMDS_ADDMOV(dWB,dET); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} LBMDS_ADDMOV(dWB,dET); } else { m[dET] = CSRC_ET; } \ + if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); LBMDS_ADDMOV(dWT,dEB); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} LBMDS_ADDMOV(dWT,dEB); } else { m[dEB] = CSRC_EB; } \ + if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); LBMDS_ADDMOV(dEB,dWT); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} LBMDS_ADDMOV(dEB,dWT); } else { m[dWT] = CSRC_WT; } \ + if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); LBMDS_ADDMOV(dET,dWB); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} LBMDS_ADDMOV(dET,dWB); } else { m[dWB] = CSRC_WB; } \ } @@ -437,7 +448,7 @@ / (6.0*mLevel[(csolev)].lcsmago_sqr)) \ ) +0.5 ); -#define DEFAULT_COLLIDE_LES \ +#define DEFAULT_COLLIDE_LES(grav) \ rho = + MSRC_C + MSRC_N \ + MSRC_S + MSRC_E \ + MSRC_W + MSRC_T \ @@ -449,24 +460,24 @@ + MSRC_EB + MSRC_WT \ + MSRC_WB; \ \ - ux += MSRC_E - MSRC_W \ + ux = MSRC_E - MSRC_W \ + MSRC_NE - MSRC_NW \ + MSRC_SE - MSRC_SW \ + MSRC_ET + MSRC_EB \ - MSRC_WT - MSRC_WB ; \ \ - uy += MSRC_N - MSRC_S \ + uy = MSRC_N - MSRC_S \ + MSRC_NE + MSRC_NW \ - MSRC_SE - MSRC_SW \ + MSRC_NT + MSRC_NB \ - MSRC_ST - MSRC_SB ; \ \ - uz += MSRC_T - MSRC_B \ + uz = MSRC_T - MSRC_B \ + MSRC_NT - MSRC_NB \ + MSRC_ST - MSRC_SB \ + MSRC_ET - MSRC_EB \ + MSRC_WT - MSRC_WB ; \ - PRECOLLIDE_MODS(rho,ux,uy,uz); \ + PRECOLLIDE_MODS(rho,ux,uy,uz, grav); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ COLL_CALCULATE_NONEQTENSOR(lev, MSRC_); \ @@ -495,7 +506,7 @@ RAC(tcel,dWT) = (1.0-lcsmomega)*MSRC_WT + lcsmomega*lcsmeq[ dWT]; \ RAC(tcel,dWB) = (1.0-lcsmomega)*MSRC_WB + lcsmomega*lcsmeq[ dWB]; -#define DEFAULT_COLLIDE_NOLES \ +#define DEFAULT_COLLIDE_NOLES(grav) \ rho = + MSRC_C + MSRC_N \ + MSRC_S + MSRC_E \ + MSRC_W + MSRC_T \ @@ -507,24 +518,24 @@ + MSRC_EB + MSRC_WT \ + MSRC_WB; \ \ - ux += MSRC_E - MSRC_W \ + ux = MSRC_E - MSRC_W \ + MSRC_NE - MSRC_NW \ + MSRC_SE - MSRC_SW \ + MSRC_ET + MSRC_EB \ - MSRC_WT - MSRC_WB ; \ \ - uy += MSRC_N - MSRC_S \ + uy = MSRC_N - MSRC_S \ + MSRC_NE + MSRC_NW \ - MSRC_SE - MSRC_SW \ + MSRC_NT + MSRC_NB \ - MSRC_ST - MSRC_SB ; \ \ - uz += MSRC_T - MSRC_B \ + uz = MSRC_T - MSRC_B \ + MSRC_NT - MSRC_NB \ + MSRC_ST - MSRC_SB \ + MSRC_ET - MSRC_EB \ + MSRC_WT - MSRC_WB ; \ - PRECOLLIDE_MODS(rho,ux,uy,uz); \ + PRECOLLIDE_MODS(rho, ux,uy,uz, grav); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ \ RAC(tcel,dC ) = (1.0-OMEGA(lev))*MSRC_C + OMEGA(lev)*EQC ; \ @@ -565,12 +576,12 @@ + MSRC_B + MSRC_NE + MSRC_NW + MSRC_SE + MSRC_SW + MSRC_NT \ + MSRC_NB + MSRC_ST + MSRC_SB + MSRC_ET + MSRC_EB + MSRC_WT + MSRC_WB; \ ux = MSRC_E - MSRC_W + MSRC_NE - MSRC_NW + MSRC_SE - MSRC_SW \ - + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB + mLevel[lev].gravity[0]; \ + + MSRC_ET + MSRC_EB - MSRC_WT - MSRC_WB; \ uy = MSRC_N - MSRC_S + MSRC_NE + MSRC_NW - MSRC_SE - MSRC_SW \ - + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB + mLevel[lev].gravity[1]; \ + + MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB; \ uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB \ - + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB + mLevel[lev].gravity[2]; \ - PRECOLLIDE_MODS(rho,ux,uy,uz); \ + + MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB; \ + PRECOLLIDE_MODS(rho, ux,uy,uz, mLevel[lev].gravity); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ COLL_CALCULATE_NONEQTENSOR(lev, MSRC_) \ @@ -606,12 +617,12 @@ + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ - + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ + + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB; \ uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ - + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ + + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB; \ uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ - + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ - PRECOLLIDE_MODS(rho,ux,uy,uz); \ + + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB; \ + PRECOLLIDE_MODS(rho, ux,uy,uz, mLevel[lev].gravity); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ COLL_CALCULATE_DFEQ(lcsmeq); \ COLL_CALCULATE_NONEQTENSOR(lev, CSRC_) \ @@ -646,12 +657,12 @@ + CSRC_B + CSRC_NE + CSRC_NW + CSRC_SE + CSRC_SW + CSRC_NT \ + CSRC_NB + CSRC_ST + CSRC_SB + CSRC_ET + CSRC_EB + CSRC_WT + CSRC_WB; \ ux = CSRC_E - CSRC_W + CSRC_NE - CSRC_NW + CSRC_SE - CSRC_SW \ - + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB + mLevel[lev].gravity[0]; \ + + CSRC_ET + CSRC_EB - CSRC_WT - CSRC_WB; \ uy = CSRC_N - CSRC_S + CSRC_NE + CSRC_NW - CSRC_SE - CSRC_SW \ - + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \ + + CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB; \ uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \ - + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \ - PRECOLLIDE_MODS(rho,ux,uy,uz); \ + + CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB; \ + PRECOLLIDE_MODS(rho, ux,uy,uz, mLevel[lev].gravity); \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ RAC(tcel,dC ) = (1.0-OMEGA(lev))*CSRC_C + OMEGA(lev)*EQC ; \ RAC(tcel,dN ) = (1.0-OMEGA(lev))*CSRC_N + OMEGA(lev)*EQN ; \ @@ -687,8 +698,8 @@ } else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \ STREAMCHECK(9, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \ } \ - rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \ - this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ + /* rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; */ \ + this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].gravity, mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \ CSMOMEGA_STATS(lev,mDebugOmegaRet); \ FORDF0 { RAC(tcel,l) = m[l]; } \ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \ @@ -709,10 +720,10 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc CSMOMEGA_STATS(lev,mDebugOmegaRet); \ */ #if USE_LES==1 -#define DEFAULT_COLLIDE DEFAULT_COLLIDE_LES +#define DEFAULT_COLLIDEG(grav) DEFAULT_COLLIDE_LES(grav) #define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_LES #else -#define DEFAULT_COLLIDE DEFAULT_COLLIDE_NOLES +#define DEFAULT_COLLIDEG(grav) DEFAULT_COLLIDE_NOLES(grav) #define OPTIMIZED_STREAMCOLLIDE OPTIMIZED_STREAMCOLLIDE_NOLES #endif @@ -1060,11 +1071,11 @@ inline LbmFloat LbmFsgrSolver::getLesOmega(LbmFloat omega, LbmFloat csmago, LbmF #define DEBUG_CALCPRINTCELL(str,df) {\ LbmFloat prho=df[0], pux=0., puy=0., puz=0.; \ - for(int ll=1; ll<this->cDfNum; ll++) { \ - prho += df[ll]; \ - pux += (this->dfDvecX[ll]*df[ll]); \ - puy += (this->dfDvecY[ll]*df[ll]); \ - puz += (this->dfDvecZ[ll]*df[ll]); \ + for(int dfl=1; dfl<this->cDfNum; dfl++) { \ + prho += df[dfl]; \ + pux += (this->dfDvecX[dfl]*df[dfl]); \ + puy += (this->dfDvecY[dfl]*df[dfl]); \ + puz += (this->dfDvecZ[dfl]*df[dfl]); \ } \ errMsg("DEBUG_CALCPRINTCELL",">"<<str<<" rho="<<prho<<" vel="<<ntlVec3Gfx(pux,puy,puz) ); \ } /* END DEBUG_CALCPRINTCELL */ @@ -1076,17 +1087,19 @@ inline void LbmFsgrSolver::collideArrays( LbmFloat &outrho, // out only! // velocity modifiers (returns actual velocity!) LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, - LbmFloat omega, LbmFloat csmago, + LbmFloat omega, + LbmVec gravity, + LbmFloat csmago, LbmFloat *newOmegaRet, LbmFloat *newQoRet ) { + int l; LbmFloat rho=df[0]; - LbmFloat ux = mux; - LbmFloat uy = muy; - LbmFloat uz = muz; + LbmFloat ux = 0; //mux; + LbmFloat uy = 0; //muy; + LbmFloat uz = 0; //muz; LbmFloat feq[19]; LbmFloat omegaNew; LbmFloat Qo = 0.0; - int l; for(l=1; l<this->cDfNum; l++) { rho += df[l]; @@ -1095,7 +1108,7 @@ inline void LbmFsgrSolver::collideArrays( uz += (this->dfDvecZ[l]*df[l]); } - PRECOLLIDE_MODS(rho,ux,uy,uz); + PRECOLLIDE_MODS(rho,ux,uy,uz, gravity); for(l=0; l<this->cDfNum; l++) { feq[l] = getCollideEq(l,rho,ux,uy,uz); } diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp index 00734864b6f..8346299b39a 100644 --- a/intern/elbeem/intern/solver_util.cpp +++ b/intern/elbeem/intern/solver_util.cpp @@ -46,68 +46,79 @@ void LbmFsgrSolver::prepareVisualization( void ) { #endif // LBMDIM==2 - + LbmFloat minval = this->mIsoValue*1.1; // / mIsoWeight[13]; // add up... float val = 0.0; for(int k= getForZMin1(); k< getForZMax1(lev); ++k) for(int j=1;j<mLevel[lev].lSizey-1;j++) for(int i=1;i<mLevel[lev].lSizex-1;i++) { + const CellFlagType cflag = RFLAG(lev, i,j,k,workSet); + //continue; // OFF DEBUG + if(cflag&(CFBnd|CFEmpty)) { + continue; + + } else if( (cflag&CFInter) ) { + //} else if( (cflag&CFInter) && (!(cflag&CFNoBndFluid)) && (cflag&CFNoNbFluid) ) { + //} else if( (cflag&CFInter) && (!(cflag&CFNoBndFluid)) ) { + int noslipbnd = 0; + FORDF1 { + const CellFlagType nbflag = RFLAG_NB(lev, i,j,k, workSet,l); + if((nbflag&CFBnd)&&(nbflag&CFBnd)&&(CFBndNoslip)){ noslipbnd=1; l=100; } + } + val = (QCELL(lev, i,j,k,workSet, dFfrac)); + if(noslipbnd) { + //errMsg("NEWVAL", PRINT_IJK<<" val"<<val <<" f"<< convertCellFlagType2String(cflag)<<" "<<noslipbnd); //" nbfl"<<convertCellFlagType2String(nbored) ); + if(val<minval) val = minval; + *this->mpIso->lbmGetData( i , j ,ZKOFF ) += minval-( val * mIsoWeight[13] ); + } + // */ + + // no empty nb interface cells are treated as full + if(cflag&CFNoNbEmpty) { + val=1.0; + } - //continue; // OFF DEBUG - if(RFLAG(lev, i,j,k,workSet)&(CFBnd|CFEmpty)) { - continue; - } else - if( (RFLAG(lev, i,j,k,workSet)&CFInter) && (!(RFLAG(lev, i,j,k,workSet)&CFNoNbEmpty)) ){ - // no empty nb interface cells are treated as full - val = (QCELL(lev, i,j,k,workSet, dFfrac)); - /* // flicker-test-fix: no real difference - if( (!(RFLAG(lev, i,j,k,workSet)&CFNoBndFluid)) && - (RFLAG(lev, i,j,k,workSet)&CFNoNbFluid) && - (val<this->mIsoValue) ){ - val = this->mIsoValue*1.1; } - // */ - } else { - // fluid? - val = 1.0; ///27.0; - } // */ + } else { // fluid? + val = 1.0; + } // */ + + *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] ); + + *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] ); + + *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] ); - *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] ); - - *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] ); - - *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] ); - - - *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] ); - - *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] ); - - *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] ); - - - *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] ); - - *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] ); - - *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] ); + + *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] ); + + *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] ); + + *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] ); + + + *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] ); + + *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] ); + + *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] ); } @@ -200,12 +211,28 @@ void LbmFsgrSolver::recalculateObjectSpeeds() { // also reinit part slip values here mObjectPartslips.resize(numobjs+1); - for(int i=0; i<(int)(numobjs+0); i++) { - mObjectPartslips[i] = (LbmFloat)(*this->mpGiObjects)[i]->getGeoPartSlipValue(); + for(int i=0; i<=(int)(numobjs+0); i++) { + if(i<numobjs) { + mObjectPartslips[i] = (LbmFloat)(*this->mpGiObjects)[i]->getGeoPartSlipValue(); + } else { + // domain setting + mObjectPartslips[i] = this->mDomainPartSlipValue; + } + LbmFloat set = mObjectPartslips[i]; + + // as in setInfluenceVelocity + const LbmFloat dt = mLevel[mMaxRefine].timestep; + const LbmFloat dtInter = 0.01; + //LbmFloat facFv = 1.-set; + // mLevel[mMaxRefine].timestep + LbmFloat facNv = (LbmFloat)( 1.-pow( (double)(set), (double)(dt/dtInter)) ); + errMsg("mObjectPartslips","id:"<<i<<"/"<<numobjs<<" ts:"<<dt<< " its:"<<(dt/dtInter) <<" set"<<set<<" nv"<<facNv<<" test:"<< + pow( (double)(1.-facNv),(double)(dtInter/dt)) ); + mObjectPartslips[i] = facNv; + if(debugRecalc) errMsg("recalculateObjectSpeeds","id"<<i<<" parts "<< mObjectPartslips[i] ); } - mObjectPartslips[numobjs] = this->mDomainPartSlipValue; if(debugRecalc) errMsg("recalculateObjectSpeeds","done, domain:"<<mObjectPartslips[numobjs]<<" n"<<numobjs); } @@ -247,10 +274,7 @@ int LbmFsgrSolver::initParticles() { partt->setSimEnd ( ntlVec3Gfx(this->mSizex, this->mSizey, getForZMaxBnd(mMaxRefine)) ); while( (num<partt->getNumInitialParticles()) && (tries<100*partt->getNumInitialParticles()) ) { - 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)) ); + LbmFloat x,y,z,t; x = 1.0+(( (LbmFloat)(this->mSizex-3.) ) * (rand()/(RAND_MAX+1.0)) ); y = 1.0+(( (LbmFloat)(this->mSizey-3.) ) * (rand()/(RAND_MAX+1.0)) ); z = 1.0+(( (LbmFloat) getForZMax1(mMaxRefine)-2. )* (rand()/(RAND_MAX+1.0)) ); @@ -258,27 +282,49 @@ int LbmFsgrSolver::initParticles() { 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 + 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), CFInter ) ) { // only fluid cells? - if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) - //&& TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFNoNbFluid ) - ) { // inner fluid only + //if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), (CFFluid) ) + //&& TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFNoNbFluid ) + //if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFInter|CFMbndInflow) ) { + if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFNoBndFluid) ) { bool cellOk = true; - FORDF1 { if(!(RFLAG_NB(mMaxRefine,i,j,k,workSet, l) & CFFluid)) cellOk = false; } + //? FORDF1 { if(!(RFLAG_NB(mMaxRefine,i,j,k,workSet, l) & CFFluid)) cellOk = false; } if(!cellOk) continue; // in fluid... partt->addParticle(x,y,z); partt->getLast()->setStatus(PART_IN); partt->getLast()->setType(PART_TRACER); - partt->getLast()->setSize(1.0); + + partt->getLast()->setSize(1.); + // randomize size + partt->getLast()->setSize(0.5 + (rand()/(RAND_MAX+1.0))); + + if( ( partt->getInitStart()>0.) + && ( partt->getInitEnd()>0.) + && ( partt->getInitEnd()>partt->getInitStart() )) { + t = partt->getInitStart()+ (partt->getInitEnd()-partt->getInitStart())*(rand()/(RAND_MAX+1.0)); + partt->getLast()->setLifeTime( -t ); + } num++; } tries++; - } + } // */ + + /*FSGR_FORIJK1(mMaxRefine) { + if( (RFLAG(mMaxRefine,i,j,k, workSet) & (CFNoBndFluid)) ) { + LbmFloat rndn = (rand()/(RAND_MAX+1.0)); + if(rndn>0.0) { + ntlVec3Gfx pos( (LbmFloat)(i)-0.5, (LbmFloat)(j)-0.5, (LbmFloat)(k)-0.5 ); + if(LBMDIM==2) { pos[2]=0.5; } + partt->addParticle( pos[0],pos[1],pos[2] ); + partt->getLast()->setStatus(PART_IN); + partt->getLast()->setType(PART_TRACER); + partt->getLast()->setSize(1.0); + } + } + } // */ // DEBUG TEST @@ -321,13 +367,13 @@ int LbmFsgrSolver::initParticles() { 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.3);j<(int)(1.3*sy);++j) { for(int i=-(int)(sx*0.3);i<(int)(1.3*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 = mLevel[lev].lSizez/10.0*2.5 - 1.0; - z = mLevel[lev].lSizez/20.0*7.5 - 1.0; + z = mLevel[lev].lSizez/20.0*9.5 - 1.0; //z = mLevel[lev].lSizez/20.0*4.5 - 1.0; partt->addParticle(x,y,z); //if( (i>0)&&(i<sx) && (j>0)&&(j<sy) ) { partt->getLast()->setStatus(PART_IN); } else { partt->getLast()->setStatus(PART_OUT); } @@ -349,7 +395,7 @@ int LbmFsgrSolver::initParticles() { } #define P_CHANGETYPE(p, newtype) \ - p->setLifeTime(0); \ + p->setLifeTime(0.); \ /* errMsg("PIT","U pit"<<(p)->getId()<<" pos:"<< (p)->getPos()<<" status:"<<convertFlags2String((p)->getFlags())<<" to "<< (newtype) ); */ \ p->setType(newtype); @@ -389,13 +435,18 @@ void LbmFsgrSolver::advanceParticles() { if(this->mStepCnt%50==49) { mpParticles->cleanup(); } for(vector<ParticleObject>::iterator pit= mpParticles->getParticlesBegin(); pit!= mpParticles->getParticlesEnd(); pit++) { - //errMsg("PIT"," pit"<<(*pit)->getId()<<" pos:"<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags())<<" vel:"<< (*pit).getVel() ); - //errMsg("PIT"," pit pos:"<< (*pit).getPos()<<" vel:"<< (*pit).getVel()<<" status:"<<convertFlags2String((*pit).getFlags()) <<" " <<mpParticles->getStart()<<" "<<mpParticles->getEnd() ); + //errMsg("PIT"," pit"<<(*pit).getId()<<" pos:"<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags())<<" vel:"<< (*pit).getVel() ); + //errMsg("PIT"," pit pos:"<< (*pit)->getPos()<<" vel:"<< (*pit)->getVel()<<" status:"<<convertFlags2String((*pit)->getFlags()) <<" " <<mpParticles->getStart()<<" "<<mpParticles->getEnd() ); //int flag = (*pit).getFlags(); if( (*pit).getActive()==false ) continue; - int i,j,k; + // skip until reached ParticleObject *p = &(*pit); - p->setLifeTime(p->getLifeTime()+1); + if(p->getLifeTime()<0.){ + if(p->getLifeTime()<-this->mSimulationTime) continue; + else p->setLifeTime(-mLevel[mMaxRefine].timestep); // zero for following update + } + int i,j,k; + p->setLifeTime(p->getLifeTime()+mLevel[mMaxRefine].timestep); // nearest neighbor, particle positions don't include empty bounds ntlVec3Gfx pos = p->getPos(); @@ -406,7 +457,7 @@ void LbmFsgrSolver::advanceParticles() { // only testdata handling, all for sws #if LBM_INCLUDE_TESTSOLVERS==1 - if(useff) { + if(useff && (mpTest->mDebugvalue1>0.)) { p->setStatus(PART_OUT); mpTest->handleParticle(p, i,j,k); continue; } @@ -518,27 +569,64 @@ void LbmFsgrSolver::advanceParticles() { v = ntlVec3Gfx(vx,vy,vz)+vec2G(fd2); } else if(p->getType()==PART_TRACER) { v = ntlVec3Gfx(vx,vy,vz); - if( RFLAG(mMaxRefine, i,j,k, workSet)&(CFFluid) ) { + CellFlagType fflag = RFLAG(mMaxRefine, i,j,k, workSet); + + if(fflag&(CFFluid|CFInter) ) { p->setInFluid(true); + } else { p->setInFluid(false); } + + //if(( fflag&CFFluid ) && ( fflag&CFNoBndFluid )) { + if( (( fflag&CFFluid ) && ( fflag&CFNoBndFluid )) || + (( fflag&CFInter ) && (!(fflag&CFNoNbFluid)) ) ) { + // only real fluid +#define TRACE_JITTER 0.025 +#define TRACE_RAND (rand()/(RAND_MAX+1.0))*TRACE_JITTER-(TRACE_JITTER*0.5) +#define __TRACE_RAND 0. +#if LBMDIM==3 + p->advance( TRACE_RAND,TRACE_RAND,TRACE_RAND); +#else + p->advance( TRACE_RAND,TRACE_RAND, 0.); +#endif + + //} // test!? + //if( fflag&(CFNoBndFluid) ) { // ok + //} else if( fflag&(CFEmpty|CFNoNbFluid) ) { + //} else if( fflag&(CFEmpty) ) { + //v = p->getVel() + vec2G(mLevel[mMaxRefine].gravity); } else { + // move inwards along normal, make sure normal is valid first const int lev = mMaxRefine; - LbmFloat nx,ny,nz, nv1,nv2; + LbmFloat nx=0.,ny=0.,nz=0., nv1,nv2; + bool nonorm = false; + if(i<=0) { nx = -1.; nonorm = true; } + if(i>=this->mSizex-1) { nx = 1.; nonorm = true; } + if(j<=0) { ny = -1.; nonorm = true; } + if(j>=this->mSizey-1) { ny = 1.; nonorm = true; } +#if LBMDIM==3 + if(k<=0) { nz = -1.; nonorm = true; } + if(k>=this->mSizez-1) { nz = 1.; nonorm = true; } +#endif // LBMDIM==3 //mynbfac = QCELL_NB(lev, i,j,k,SRCS(lev),l, dFlux) / QCELL(lev, i,j,k,SRCS(lev), dFlux); - if(RFLAG_NB(lev,i,j,k,workSet, dE) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dE,dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(lev,i,j,k,workSet, dW) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dW,dFfrac); } else nv2 = 0.0; - nx = 0.5* (nv2-nv1); - if(RFLAG_NB(lev,i,j,k,workSet, dN) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dN,dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(lev,i,j,k,workSet, dS) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dS,dFfrac); } else nv2 = 0.0; - ny = 0.5* (nv2-nv1); + if(!nonorm) { + if(RFLAG_NB(lev,i,j,k,workSet, dE) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dE,dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(lev,i,j,k,workSet, dW) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dW,dFfrac); } else nv2 = 0.0; + nx = 0.5* (nv2-nv1); + if(RFLAG_NB(lev,i,j,k,workSet, dN) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dN,dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(lev,i,j,k,workSet, dS) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dS,dFfrac); } else nv2 = 0.0; + ny = 0.5* (nv2-nv1); #if LBMDIM==3 - if(RFLAG_NB(lev,i,j,k,workSet, dT) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dT,dFfrac); } else nv1 = 0.0; - if(RFLAG_NB(lev,i,j,k,workSet, dB) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dB,dFfrac); } else nv2 = 0.0; - nz = 0.5* (nv2-nv1); + if(RFLAG_NB(lev,i,j,k,workSet, dT) &(CFFluid|CFInter)){ nv1 = QCELL_NB(lev,i,j,k,workSet,dT,dFfrac); } else nv1 = 0.0; + if(RFLAG_NB(lev,i,j,k,workSet, dB) &(CFFluid|CFInter)){ nv2 = QCELL_NB(lev,i,j,k,workSet,dB,dFfrac); } else nv2 = 0.0; + nz = 0.5* (nv2-nv1); #else //LBMDIM==3 - nz = 0.0; + nz = 0.0; #endif //LBMDIM==3 + } else { + v = p->getVel() + vec2G(mLevel[mMaxRefine].gravity); + } - v = (ntlVec3Gfx(nx,ny,nz)) * -0.025; + p->advanceVec( (ntlVec3Gfx(nx,ny,nz)) * -0.1 ); // + vec2G(mLevel[mMaxRefine].gravity); + //if(normNoSqrt(v)<LBM_EPSILON) v = mLevel[mMaxRefine].gravity; } } @@ -595,11 +683,10 @@ void LbmFsgrSolver::advanceParticles() { // shipt3 } else if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFInter) ){ } else if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid) ){ // FIXME make fsgr treatment - //if(p->getLifeTime()>50) { P_CHANGETYPE(p, PART_FLOAT ); continue; // jitter in cell to prevent stacking when hitting a steep surface - LbmVec posi = p->getPos(); posi[0] += (rand()/(RAND_MAX+1.0))-0.5; - posi[1] += (rand()/(RAND_MAX+1.0))-0.5; p->setPos(posi); + ntlVec3Gfx cpos = p->getPos(); cpos[0] += (rand()/(RAND_MAX+1.0))-0.5; + cpos[1] += (rand()/(RAND_MAX+1.0))-0.5; p->setPos(cpos); //} else DEL_PART; } else { DEL_PART; @@ -636,16 +723,10 @@ void LbmFsgrSolver::advanceParticles() { P_CHANGETYPE(p, PART_FLOAT ); continue; } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) { //errMsg("PIT","NEWDROP pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) ); - //? if(p->getLifeTime()>50) { - // only use drops that really flew for a while...? - //? } else DEL_PART; - //if( (i<=cutval)||(i>=this->mSizex-1-cutval)|| - //(j<=cutval)||(j>=this->mSizey-1-cutval)) { - //} else - //if(p->getLifeTime()>10) { P_CHANGETYPE(p, PART_DROP ); continue; - //} else DEL_PART; - + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFBnd ) ) { + // 060423 new test + P_CHANGETYPE(p, PART_FLOAT ); continue; } } else { // OUT // undecided particle outside... remove? @@ -659,8 +740,8 @@ void LbmFsgrSolver::advanceParticles() { // 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 + /*LbmFloat prob = 1.0; // vanishing prob = (rand()/(RAND_MAX+1.0)); // increse del prob. up to max height by given factor @@ -670,15 +751,18 @@ void LbmFsgrSolver::advanceParticles() { LbmFloat fac = (LbmFloat)(k-fhCheckh)/(LbmFloat)(fhProbh*(mLevel[mMaxRefine].lSizez-fhCheckh)); prob /= fac; } - if(prob<mLevel[mMaxRefine].timestep*0.1) DEL_PART; + //if(prob<mLevel[mMaxRefine].timestep*0.1) DEL_PART; // forced vanishing //? if(k>this->mSizez*3/4) { if(prob<3.0*mLevel[mMaxRefine].timestep*0.1) DEL_PART;} + // */ #else // LBM_INCLUDE_TESTSOLVERS==1 #endif // LBM_INCLUDE_TESTSOLVERS==1 if(p->getStatus()&PART_IN) { // IN - if((k<cutval)||(k>this->mSizez-1-cutval)) DEL_PART; + //if((k<cutval)||(k>this->mSizez-1-cutval)) DEL_PART; + if(k<cutval) DEL_PART; + if(k>this->mSizez-1-cutval) { P_CHANGETYPE(p, PART_DROP ); continue; } // create new drop //ntlVec3Gfx v = getVelocityAt(i,j,k); rho = vx = vy = vz = 0.0; @@ -709,13 +793,13 @@ void LbmFsgrSolver::advanceParticles() { #else // MOVE_FLOATS==1 vx=vy=0.; //p->setVel(ntlVec3Gfx(0.) ); // static_float #endif // MOVE_FLOATS==1 - vx += (rand()/(RAND_MAX+1.0))*FLOAT_JITTER-(FLOAT_JITTER*0.5); - vy += (rand()/(RAND_MAX+1.0))*FLOAT_JITTER-(FLOAT_JITTER*0.5); + vx += (rand()/(RAND_MAX+1.0))*(FLOAT_JITTER*0.2)-(FLOAT_JITTER*0.2*0.5); + vy += (rand()/(RAND_MAX+1.0))*(FLOAT_JITTER*0.2)-(FLOAT_JITTER*0.2*0.5); - bool delfloat = false; + //bool delfloat = false; if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFFluid ) ) { // in fluid cell - if((1) && (k<this->mSizez-3) && + /*if((1) && (k<this->mSizez-3) && ( TESTFLAG( RFLAG(mMaxRefine, i,j,k+1, workSet), CFInter ) || TESTFLAG( RFLAG(mMaxRefine, i,j,k+2, workSet), CFInter ) @@ -726,20 +810,29 @@ void LbmFsgrSolver::advanceParticles() { // keep below obstacles if((delfloat) && (TESTFLAG( RFLAG(mMaxRefine, i,j,k+1, workSet), CFBnd )) ) { delfloat=false; vz=0.0; - } + } // */ + vz = p->getVel()[2]-1.0*mLevel[mMaxRefine].gravity[2]; // simply rise... + if(vz<0.) vz=0.; + } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFBnd ) ) { + //vz = p->getVel()[2]-0.2; // force downwards movement, move below obstacle... + vz = p->getVel()[2]+1.0*mLevel[mMaxRefine].gravity[2]; // fall... + if(vz>0.) vz=0.; } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) { // keep in interface , one grid cell offset is added in part. gen } else { //if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) { // shipt?, was all else before + vz = p->getVel()[2]+1.0*mLevel[mMaxRefine].gravity[2]; // fall... + if(vz>0.) vz=0.; // check if above inter, remove otherwise - if((1) && (k>2) && ( + /*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 delfloat=true; // */ + //P_CHANGETYPE(p, PART_DROP ); continue; // create new drop } - if(delfloat) DEL_PART; + //if(delfloat) DEL_PART; /* // move down from empty else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) { @@ -764,7 +857,7 @@ void LbmFsgrSolver::advanceParticles() { } // additional bnd jitter - if((1) && (useff) && (p->getLifeTime()<3)) { + if((0) && (useff) && (p->getLifeTime()<3.*mLevel[mMaxRefine].timestep)) { // use half butoff border 1/8 int maxdw = (int)(mLevel[mMaxRefine].lSizex*0.125*0.5); if(maxdw<3) maxdw=3; @@ -780,7 +873,7 @@ void LbmFsgrSolver::advanceParticles() { #undef FLOAT_JITTBNDRAND //if( (i<cutval)||(i>this->mSizex-1-cutval)|| //(j<cutval)||(j>this->mSizey-1-cutval) } - } + } // PART_FLOAT // unknown particle type else { @@ -788,7 +881,7 @@ void LbmFsgrSolver::advanceParticles() { } } myTime_t parttend = getTime(); - debMsgStd("LbmFsgrSolver::advanceParticles",DM_MSG,"Time for particle update:"<< getTimeString(parttend-parttstart)<<" "<<mpParticles->getNumParticles() , 10 ); + debMsgStd("LbmFsgrSolver::advanceParticles",DM_MSG,"Time for particle update:"<< getTimeString(parttend-parttstart)<<", #particles:"<<mpParticles->getNumParticles() , 10 ); } void LbmFsgrSolver::notifySolverOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) { @@ -819,6 +912,8 @@ void LbmFsgrSolver::notifySolverOfDump(int dumptype, int frameNr,char *frameNrSt } // file } // */ + + dumptype = 0; frameNr = 0; // get rid of warning } /*****************************************************************************/ @@ -1009,9 +1104,9 @@ LbmFloat LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int s 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].timestep) +1.0; // ORG - if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&CFInter) { // test + 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].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; int lev = cid->level; @@ -1033,8 +1128,8 @@ LbmFloat LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int s //rho = Qo*100.0; //if(cid->x==24){ errMsg("MODOMT"," at "<<PRINT_VEC(cid->x,cid->y,cid->z)<<" = "<<rho<<" "<<Qo); } //else{ rho=0.0; } - } // test - return rho; // test + } // test + return rho; // test */ } LbmVec LbmFsgrSolver::getCellVelocity ( CellIdentifierInterface* basecid,int set) { @@ -1091,7 +1186,7 @@ ntlVec3Gfx LbmFsgrSolver::getVelocityAt (float xp, float yp, float zp) { // taken from getCellAt! const int level = mMaxRefine; const int workSet = mLevel[level].setCurr; - LbmFloat nsize = mLevel[level].nodeSize; + const 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 ); @@ -1101,9 +1196,9 @@ ntlVec3Gfx LbmFsgrSolver::getVelocityAt (float xp, float yp, float zp) { // return fluid/if/border cells // search neighborhood, do smoothing FORDF0{ - int i=x+this->dfVecX[l]; - int j=y+this->dfVecY[l]; - int k=z+this->dfVecZ[l]; + const int i = x+this->dfVecX[l]; + const int j = y+this->dfVecY[l]; + const int k = z+this->dfVecZ[l]; if( (i<0) || (j<0) || (k<0) || (i>=mLevel[level].lSizex) diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp index 7cb4dd50577..1aee43fe8bd 100644 --- a/intern/elbeem/intern/utilities.cpp +++ b/intern/elbeem/intern/utilities.cpp @@ -19,20 +19,6 @@ #include <sys/times.h> #endif -// blender interface -#if ELBEEM_BLENDER==1 -// warning - for MSVC this has to be included -// _before_ ntl_vector3dim -#include "SDL.h" -#include "SDL_thread.h" -#include "SDL_mutex.h" -extern "C" void simulateThreadIncreaseFrame(void); -extern "C" SDL_mutex *globalBakeLock; -// global state variables -extern "C" int globalBakeState; -//extern "C" int globalBakeFrame; not needed...? -#endif // ELBEEM_PLUGIN==1 - #include "utilities.h" #ifndef NOPNG @@ -50,11 +36,29 @@ int gDebugLevel = DEBUG; int gDebugLevel = 0; #endif // DEBUG -// global world state +// global world state, acces with get/setElbeemState int gElbeemState = SIMWORLD_INVALID; -// last error as string + +// access global state of elbeem simulator +void setElbeemState(int set) { + gElbeemState = set; +} +int getElbeemState(void) { + return gElbeemState; +} +int isSimworldOk(void) { + return (getElbeemState>=0); +} + +// last error as string, acces with get/setElbeemErrorString char gElbeemErrorString[256] = {'-','\0' }; +// access elbeem simulator error string +void setElbeemErrorString(char* set) { + strncpy(gElbeemErrorString, set, 256); +} +char* getElbeemErrorString(void) { return gElbeemErrorString; } + //! for interval debugging output myTime_t globalIntervalTime = 0; @@ -66,6 +70,9 @@ int globalColorSetting = 1; #endif // WIN32 int globalFirstEnvCheck = 0; +// global string for formatting vector output, TODO test!? +char *globVecFormatStr = "V[%f,%f,%f]"; + //----------------------------------------------------------------------------- // helper function that converts a string to integer, @@ -370,24 +377,5 @@ double elbeemEstimateMemreq(int res, return memreq; } -//----------------------------------------------------------------------------- -// bake state mutex handling - - -#if ELBEEM_BLENDER==1 -// Blender state sync -void setGlobalBakeState(int set) { - SDL_mutexP(globalBakeLock); - globalBakeState = set; - SDL_mutexV(globalBakeLock); -} -int getGlobalBakeState(void) { - SDL_mutexP(globalBakeLock); - int ret = globalBakeState; - SDL_mutexV(globalBakeLock); - return ret; -} -#endif // ELBEEM_BLENDER==1 - diff --git a/intern/elbeem/intern/utilities.h b/intern/elbeem/intern/utilities.h index 3ba023e4730..57a956c64d9 100644 --- a/intern/elbeem/intern/utilities.h +++ b/intern/elbeem/intern/utilities.h @@ -9,50 +9,45 @@ #ifndef UTILITIES_H #include "ntl_vector3dim.h" -typedef unsigned long myTime_t; - -//! helper function that converts a string to integer -int convertString2Int(const char *str, int alt); - -//! helper function that converts a flag field to a readable integer -string convertFlags2String(int flags); - -//! get the current system time -myTime_t getTime(); -//! convert time to readable string -string getTimeString(myTime_t usecs); - -//! helper to check if a bounding box was specified in the right way -bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker); - /* debugging outputs , debug level 0 (off) to 10 (max) */ #ifdef ELBEEM_PLUGIN #define DEBUG 0 -void setGlobalBakeState(int set); -int getGlobalBakeState(void); #else // ELBEEM_PLUGIN #define DEBUG 10 #endif // ELBEEM_PLUGIN extern "C" int gDebugLevel; + +// time measurements +typedef unsigned long myTime_t; + + // state of the simulation world // default -#define SIMWORLD_INVALID 0 +#define SIMWORLD_INVALID 0 +// performing init +#define SIMWORLD_INITIALIZING 1 // after init, before starting simulation -#define SIMWORLD_INITED 1 +#define SIMWORLD_INITED 2 +// stop of the simulation run, can be continued later +#define SIMWORLD_STOP 3 // error during init #define SIMWORLD_INITERROR -1 // error during simulation #define SIMWORLD_PANIC -2 // general error #define SIMWORLD_GENERICERROR -3 -// global world state -extern "C" int gElbeemState; -// last error as string -extern "C" char gElbeemErrorString[]; -// check world status macro -#define SIMWORLD_OK() (gElbeemState>=0) + +// access global state of elbeem simulator +void setElbeemState(int set); +int getElbeemState(void); +int isSimworldOk(void); + +// access elbeem simulator error string +void setElbeemErrorString(char* set); +char* getElbeemErrorString(void); + /* debug output function */ #define DM_MSG 1 @@ -100,11 +95,28 @@ void messageOutputFunc(string from, int id, string msg, myTime_t interval); // fatal errors - have to be handled #define errFatal(from,mStr,errCode) { \ - gElbeemState = errCode; \ + setElbeemState(errCode); \ MSGSTREAM; msg << mStr; \ messageOutputFunc(from, DM_FATAL, msg.str(), 0); \ } + +//! helper function that converts a string to integer +int convertString2Int(const char *str, int alt); + +//! helper function that converts a flag field to a readable integer +string convertFlags2String(int flags); + +//! get the current system time +myTime_t getTime(); +//! convert time to readable string +string getTimeString(myTime_t usecs); + +//! helper to check if a bounding box was specified in the right way +bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker); + + + /*! print some vector from 3 values e.g. for ux,uy,uz */ #define PRINT_VEC(x,y,z) " ["<<(x)<<","<<(y)<<","<<(z)<<"] " |