Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Thuerey <nils@thuerey.de>2006-11-05 19:30:29 +0300
committerNils Thuerey <nils@thuerey.de>2006-11-05 19:30:29 +0300
commit3bea663ffa27cab0a60b3ed1ac41d431ce55cecc (patch)
treec58fa1f791654b0b5e0d4057a0ec38ce541038c5 /intern/elbeem
parent64b9cda68eb4cd25bc9ce37d710a603b2fc4c81d (diff)
- bugfixes
#4742 exported normals are now correct #4821 & 4956 for complex movements in/outflows can now also use the animated mesh option - new features * isosurface subdivision: directly creates a finer surface mesh from the simulation data. this increases simulation time and harddisk usage, though, so be careful - usually values of 2-4 should be enough. * fluidsim particles: extended model for particle simulation and generation. When isosurface subdivision is enabled, the particles are now included in the surface generation, giving a better impression of a single connected surface. Note - the particles are only included in the final surface mesh, so the preview surface shows none of the particle effects. * particle loading: different types of particles can now be selected for display: drops, floats and tracers. This is a bit obsolete due to the extensions mentioned above, but might still be useful. Floats are just particles floating on the fluid surface, could be used for e.g. foam. * moving objects impact factor: this is another tweaking option, as the handling of moving objects is still not conserving mass. setting this to zero simply deletes the fluid, 1 is the default, while larger values cause a stronger impact. For tweaking the simulation: if fluid disappears, try increasing this value, and if too much is appearing reduce it. You can even use negative values for some strange results :) - more code cleanup, e.g. removed config file writing in fluidsim.c, added additional safety checks for particles & fluidsim domains (these currently dont work together). I also removed the "build particles" debug message in effects.c (seemed to be unnecessary?). Some more info on the new features: Here are two test animations showing the difference between using the particle generation with isosurface subdivision. This is how it would look with the old solver version: http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid6_fl6manc4_1noparts.mpg and this with the new one: http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid6_fl6manc4_2wparts.mpg Both simulations use a resolution of 64, however, the version with particles takes significantly longer (almost twice as long). The .blend file for a similar setup can be found here: http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid6_testmanc4.blend (Minor Tips for this file: dont enable subdivions of characters until rendering, thus leave off for simulation, as it uses the rendering settings! For making nice pictures switch on subdivion, and OSA.) And here's a picture of old vs. new (for webpage or so): http://www10.informatik.uni-erlangen.de/~sinithue/blender/fluid6_manc4compare.png
Diffstat (limited to 'intern/elbeem')
-rw-r--r--intern/elbeem/COPYING6
-rw-r--r--intern/elbeem/extern/elbeem.h14
-rw-r--r--intern/elbeem/intern/attributes.cpp562
-rw-r--r--intern/elbeem/intern/attributes.h176
-rw-r--r--intern/elbeem/intern/elbeem.cpp10
-rw-r--r--intern/elbeem/intern/elbeem.h14
-rw-r--r--intern/elbeem/intern/isosurface.cpp728
-rw-r--r--intern/elbeem/intern/isosurface.h27
-rw-r--r--intern/elbeem/intern/loop_tools.h4
-rw-r--r--intern/elbeem/intern/ntl_blenderdumper.cpp69
-rw-r--r--intern/elbeem/intern/ntl_blenderdumper.h2
-rw-r--r--intern/elbeem/intern/ntl_bsptree.cpp2
-rw-r--r--intern/elbeem/intern/ntl_bsptree.h2
-rw-r--r--intern/elbeem/intern/ntl_geometryclass.h9
-rw-r--r--intern/elbeem/intern/ntl_geometrymodel.cpp2
-rw-r--r--intern/elbeem/intern/ntl_geometrymodel.h2
-rw-r--r--intern/elbeem/intern/ntl_geometryobject.cpp51
-rw-r--r--intern/elbeem/intern/ntl_geometryobject.h10
-rw-r--r--intern/elbeem/intern/ntl_geometryshader.h2
-rw-r--r--intern/elbeem/intern/ntl_lighting.cpp2
-rw-r--r--intern/elbeem/intern/ntl_lighting.h2
-rw-r--r--intern/elbeem/intern/ntl_matrices.h81
-rw-r--r--intern/elbeem/intern/ntl_ray.cpp2
-rw-r--r--intern/elbeem/intern/ntl_ray.h2
-rw-r--r--intern/elbeem/intern/ntl_vector3dim.h2
-rw-r--r--intern/elbeem/intern/ntl_world.cpp26
-rw-r--r--intern/elbeem/intern/ntl_world.h2
-rw-r--r--intern/elbeem/intern/parametrizer.cpp16
-rw-r--r--intern/elbeem/intern/parametrizer.h6
-rw-r--r--intern/elbeem/intern/particletracer.cpp22
-rw-r--r--intern/elbeem/intern/particletracer.h21
-rw-r--r--intern/elbeem/intern/simulation_object.cpp113
-rw-r--r--intern/elbeem/intern/simulation_object.h2
-rw-r--r--intern/elbeem/intern/solver_adap.cpp146
-rw-r--r--intern/elbeem/intern/solver_class.h78
-rw-r--r--intern/elbeem/intern/solver_init.cpp561
-rw-r--r--intern/elbeem/intern/solver_interface.cpp111
-rw-r--r--intern/elbeem/intern/solver_interface.h61
-rw-r--r--intern/elbeem/intern/solver_main.cpp658
-rw-r--r--intern/elbeem/intern/solver_relax.h13
-rw-r--r--intern/elbeem/intern/solver_util.cpp774
-rw-r--r--intern/elbeem/intern/utilities.cpp154
-rw-r--r--intern/elbeem/intern/utilities.h6
43 files changed, 2519 insertions, 2034 deletions
diff --git a/intern/elbeem/COPYING b/intern/elbeem/COPYING
index d876362de6c..2600c731161 100644
--- a/intern/elbeem/COPYING
+++ b/intern/elbeem/COPYING
@@ -1,7 +1,5 @@
- All code distributed as part of El'Bemm is covered by the following
- version of the GNU General Public License, expcept for excerpts of
- the trimesh2 package in src/isosurface.cpp (see COPYING_trimesh2
- for details).
+ All code distributed as part of El'Beem is covered by the following
+ version of the GNU General Public License.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h
index ea21e807a6f..b3feda8bbe8 100644
--- a/intern/elbeem/extern/elbeem.h
+++ b/intern/elbeem/extern/elbeem.h
@@ -3,7 +3,7 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* API header
*/
@@ -72,13 +72,14 @@ typedef struct elbeemSimulationSettings {
float *channelGravity; // vector
/* boundary types and settings for domain walls */
- short obstacleType;
- float obstaclePartslip;
+ short domainobsType;
+ float domainobsPartslip;
/* generate speed vectors for vertices (e.g. for image based motion blur)*/
short generateVertexVectors;
/* strength of surface smoothing */
float surfaceSmoothing;
- // TODO add surf gen flags
+ /* no. of surface subdivisions */
+ int surfaceSubdivs;
/* global transformation to apply to fluidsim mesh */
float surfaceTrafo[4*4];
@@ -147,6 +148,8 @@ typedef struct elbeemMesh {
/* boundary types and settings */
short obstacleType;
float obstaclePartslip;
+ /* amount of force transfer from fluid to obj, 0=off, 1=normal */
+ float obstacleImpactFactor;
/* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */
short volumeInitType;
@@ -230,5 +233,8 @@ double elbeemEstimateMemreq(int res,
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
+// all boundary types at once
+#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 b7f194582d1..0cf5315161a 100644
--- a/intern/elbeem/intern/attributes.cpp
+++ b/intern/elbeem/intern/attributes.cpp
@@ -1,290 +1,44 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
- * configuration attribute storage class and attribute class
+ * DEPRECATED - replaced by elbeem API, only channels are still used
*
*****************************************************************************/
#include "attributes.h"
#include "ntl_matrices.h"
#include "elbeem.h"
-#include <sstream>
-//! output attribute values? on=1/off=0
-#define DEBUG_ATTRIBUTES 0
-
-//! output channel values? on=1/off=0
-#define DEBUG_CHANNELS 0
-
/******************************************************************************
* attribute conversion functions
*****************************************************************************/
bool Attribute::initChannel(int elemSize) {
- if(!mIsChannel) return true;
- if(mChannelInited==elemSize) {
- // already inited... ok
- return true;
- } else {
- // sanity check
- if(mChannelInited>0) {
- errMsg("Attribute::initChannel","Duplicate channel init!? ("<<mChannelInited<<" vs "<<elemSize<<")...");
- return false;
- }
- }
-
- if((mValue.size() % (elemSize+1)) != 0) {
- errMsg("Attribute::initChannel","Invalid # elements in Attribute...");
- return false;
- }
-
- int numElems = mValue.size()/(elemSize+1);
- vector<string> newvalue;
- for(int i=0; i<numElems; i++) {
- //errMsg("ATTR"," i"<<i<<" "<<mName); // debug
-
- vector<string> elem(elemSize);
- for(int j=0; j<elemSize; j++) {
- //errMsg("ATTR"," j"<<j<<" "<<mValue[i*(elemSize+1)+j] ); // debug
- elem[j] = mValue[i*(elemSize+1)+j];
- }
- mChannel.push_back(elem);
- // use first value as default
- if(i==0) newvalue = elem;
-
- double t = 0.0; // similar to getAsFloat
- const char *str = mValue[i*(elemSize+1)+elemSize].c_str();
- char *endptr;
- t = strtod(str, &endptr);
- if((str!=endptr) && (*endptr != '\0')) return false;
- mTimes.push_back(t);
- //errMsg("ATTR"," t"<<t<<" "); // debug
- }
- for(int i=0; i<numElems-1; i++) {
- if(mTimes[i]>mTimes[i+1]) {
- errMsg("Attribute::initChannel","Invalid time at entry "<<i<<" setting to "<<mTimes[i]);
- mTimes[i+1] = mTimes[i];
- }
- }
-
- // dont change until done with parsing, and everythings ok
- mValue = newvalue;
-
- mChannelInited = elemSize;
- if(DEBUG_CHANNELS) print();
- return true;
+ return false;
}
-
-// get value as string
-string Attribute::getAsString(bool debug)
-{
- if(mIsChannel && (!debug)) {
- errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string is a channel! Not allowed...");
- print();
- return string("");
- }
- if(mValue.size()!=1) {
- // for directories etc. , this might be valid! cutoff "..." first
- string comp = getCompleteString();
- if(comp.size()<2) return string("");
- return comp.substr(1, comp.size()-2);
- }
- return mValue[0];
+string Attribute::getAsString(bool debug) {
+ return string("");
}
-
-// get value as integer value
-int Attribute::getAsInt()
-{
- bool success = true;
- int ret = 0;
-
- if(!initChannel(1)) success=false;
- if(success) {
- if(mValue.size()!=1) success = false;
- else {
- const char *str = mValue[0].c_str();
- char *endptr;
- ret = strtol(str, &endptr, 10);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
- }
- }
-
- if(!success) {
- errMsg("Attribute::getAsInt", "Attribute \"" << mName << "\" used as int has invalid value '"<< getCompleteString() <<"' ");
- errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
-#if ELBEEM_PLUGIN!=1
- setElbeemState( -4 ); // parse error
-#endif
- return 0;
- }
- return ret;
+int Attribute::getAsInt() {
+ return 0;
}
-
-
-// get value as integer value
-bool Attribute::getAsBool()
-{
- int val = getAsInt();
- if(val==0) return false;
- else return true;
+bool Attribute::getAsBool() {
+ return false;
}
-
-
-// get value as double value
-double Attribute::getAsFloat()
-{
- bool success = true;
- double ret = 0.0;
-
- if(!initChannel(1)) success=false;
- if(success) {
- if(mValue.size()!=1) success = false;
- else {
- const char *str = mValue[0].c_str();
- char *endptr;
- ret = strtod(str, &endptr);
- if((str!=endptr) && (*endptr != '\0')) success = false;
- }
- }
-
- if(!success) {
- print();
- errMsg("Attribute::getAsFloat", "Attribute \"" << mName << "\" used as double has invalid value '"<< getCompleteString() <<"' ");
- errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
-#if ELBEEM_PLUGIN!=1
- setElbeemState( -4 ); // parse error
-#endif
- return 0.0;
- }
- return ret;
+double Attribute::getAsFloat() {
+ return 0.;
}
-
-// get value as 3d vector
-ntlVec3d Attribute::getAsVec3d()
-{
- bool success = true;
- ntlVec3d ret(0.0);
-
- if(!initChannel(3)) success=false;
- if(success) {
- if(mValue.size()==1) {
- const char *str = mValue[0].c_str();
- char *endptr;
- double rval = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
- if(success) ret = ntlVec3d( rval );
- } else if(mValue.size()==3) {
- char *endptr;
- const char *str = NULL;
-
- str = mValue[0].c_str();
- double rval1 = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
-
- str = mValue[1].c_str();
- double rval2 = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
-
- str = mValue[2].c_str();
- double rval3 = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
-
- if(success) ret = ntlVec3d( rval1, rval2, rval3 );
- } else {
- success = false;
- }
- }
-
- if(!success) {
- errMsg("Attribute::getAsVec3d", "Attribute \"" << mName << "\" used as Vec3d has invalid value '"<< getCompleteString() <<"' ");
- errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
-#if ELBEEM_PLUGIN!=1
- setElbeemState( -4 ); // parse error
-#endif
- return ntlVec3d(0.0);
- }
- return ret;
+ntlVec3d Attribute::getAsVec3d() {
+ return ntlVec3d(0.);
}
-
-// get value as 4x4 matrix
-void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat)
-{
- bool success = true;
- ntlMat4Gfx ret(0.0);
- char *endptr;
-
- if(mValue.size()==1) {
- const char *str = mValue[0].c_str();
- double rval = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) )success = false;
- if(success) {
- ret = ntlMat4Gfx( 0.0 );
- ret.value[0][0] = rval;
- ret.value[1][1] = rval;
- ret.value[2][2] = rval;
- ret.value[3][3] = 1.0;
- }
- } else if(mValue.size()==9) {
- // 3x3
- for(int i=0; i<3;i++) {
- for(int j=0; j<3;j++) {
- const char *str = mValue[i*3+j].c_str();
- ret.value[i][j] = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) ) success = false;
- }
- }
- } else if(mValue.size()==16) {
- // 4x4
- for(int i=0; i<4;i++) {
- for(int j=0; j<4;j++) {
- const char *str = mValue[i*4+j].c_str();
- ret.value[i][j] = strtod(str, &endptr);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) ) success = false;
- }
- }
-
- } else {
- success = false;
- }
-
- if(!success) {
- errMsg("Attribute::getAsMat4Gfx", "Attribute \"" << mName << "\" used as Mat4x4 has invalid value '"<< getCompleteString() <<"' ");
- errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
-#if ELBEEM_PLUGIN!=1
- setElbeemState( -4 ); // parse error
-#endif
- *mat = ntlMat4Gfx(0.0);
- return;
- }
- *mat = ret;
+void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat) {
}
-
-
-// get the concatenated string of all value string
-string Attribute::getCompleteString()
-{
- string ret;
- for(size_t i=0;i<mValue.size();i++) {
- ret += mValue[i];
- if(i<mValue.size()-1) ret += " ";
- }
- return ret;
+string Attribute::getCompleteString() {
+ return string("");
}
@@ -292,266 +46,80 @@ string Attribute::getCompleteString()
* channel returns
*****************************************************************************/
-//! get channel as double value
AnimChannel<double> Attribute::getChannelFloat() {
- vector<double> timeVec;
- vector<double> valVec;
-
- if((!initChannel(1)) || (!mIsChannel)) {
- timeVec.push_back( 0.0 );
- valVec.push_back( getAsFloat() );
- } else {
- for(size_t i=0; i<mChannel.size(); i++) {
- mValue = mChannel[i];
- double val = getAsFloat();
- timeVec.push_back( mTimes[i] );
- valVec.push_back( val );
- }}
-
- return AnimChannel<double>(valVec,timeVec);
-}
-
-//! get channel as integer value
+ return AnimChannel<double>();
+}
AnimChannel<int> Attribute::getChannelInt() {
- vector<double> timeVec;
- vector<int> valVec;
-
- if((!initChannel(1)) || (!mIsChannel)) {
- timeVec.push_back( 0.0 );
- valVec.push_back( getAsInt() );
- } else {
- for(size_t i=0; i<mChannel.size(); i++) {
- mValue = mChannel[i];
- int val = getAsInt();
- timeVec.push_back( mTimes[i] );
- valVec.push_back( val );
- }}
-
- return AnimChannel<int>(valVec,timeVec);
-}
-
-//! get channel as integer value
+ return AnimChannel<int>();
+}
AnimChannel<ntlVec3d> Attribute::getChannelVec3d() {
- vector<double> timeVec;
- vector<ntlVec3d> valVec;
-
- if((!initChannel(3)) || (!mIsChannel)) {
- timeVec.push_back( 0.0 );
- valVec.push_back( getAsVec3d() );
- } else {
- for(size_t i=0; i<mChannel.size(); i++) {
- mValue = mChannel[i];
- ntlVec3d val = getAsVec3d();
- timeVec.push_back( mTimes[i] );
- valVec.push_back( val );
- }}
-
- return AnimChannel<ntlVec3d>(valVec,timeVec);
-}
-
-//! get channel as float vector set
+ return AnimChannel<ntlVec3d>();
+}
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);
+ return AnimChannel<ntlSetVec3f>();
}
/******************************************************************************
* check if there were unknown params
*****************************************************************************/
-bool AttributeList::checkUnusedParams()
-{
- bool found = false;
- for(map<string, Attribute*>::iterator i=mAttrs.begin();
- i != mAttrs.end(); i++) {
- if((*i).second) {
- if(!(*i).second->getUsed()) {
- errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString(true) <<"' ");
- found = true;
- }
- }
- }
- return found;
+bool AttributeList::checkUnusedParams() {
+ return false;
}
-//! set all params to used, for invisible objects
void AttributeList::setAllUsed() {
- for(map<string, Attribute*>::iterator i=mAttrs.begin();
- i != mAttrs.end(); i++) {
- if((*i).second) {
- (*i).second->setUsed(true);
- }
- }
}
/******************************************************************************
* Attribute list read functions
*****************************************************************************/
int AttributeList::readInt(string name, int defaultValue, string source,string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return defaultValue;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- return find(name)->getAsInt();
+ return defaultValue;
}
bool AttributeList::readBool(string name, bool defaultValue, string source,string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readBool","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return defaultValue;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- return find(name)->getAsBool();
+ return defaultValue;
}
double AttributeList::readFloat(string name, double defaultValue, string source,string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readFloat","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return defaultValue;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- return find(name)->getAsFloat();
+ return defaultValue;
}
string AttributeList::readString(string name, string defaultValue, string source,string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return defaultValue;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- return find(name)->getAsString(false);
+ return defaultValue;
}
ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return defaultValue;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- return find(name)->getAsVec3d();
+ return defaultValue;
}
void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed, ntlMat4Gfx *mat) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
- *mat = defaultValue;
- return;
- }
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
- find(name)->setUsed(true);
- find(name)->getAsMat4Gfx( mat );
- return;
}
// set that a parameter can be given, and will be ignored...
bool AttributeList::ignoreParameter(string name, string source) {
- if(!exists(name)) return false;
- find(name)->setUsed(true);
- if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Param '"<< name <<"' set but ignored... " , 3); }
- return true;
+ return false;
}
// read channels
AnimChannel<int> AttributeList::readChannelInt(string name, int defaultValue, string source, string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelInt","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return AnimChannel<int>(defaultValue); }
- AnimChannel<int> ret = find(name)->getChannelInt();
- find(name)->setUsed(true);
- channelSimplifyi(ret);
- return ret;
+ return AnimChannel<int>(defaultValue);
}
AnimChannel<double> AttributeList::readChannelFloat(string name, double defaultValue, string source, string target, bool needed ) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelFloat","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return AnimChannel<double>(defaultValue); }
- AnimChannel<double> ret = find(name)->getChannelFloat();
- find(name)->setUsed(true);
- channelSimplifyd(ret);
- return ret;
+ return AnimChannel<double>(defaultValue);
}
AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name, ntlVec3d defaultValue, string source, string target, bool needed ) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelVec3d","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return AnimChannel<ntlVec3d>(defaultValue); }
- AnimChannel<ntlVec3d> ret = find(name)->getChannelVec3d();
- find(name)->setUsed(true);
- channelSimplifyVd(ret);
- return ret;
+ return AnimChannel<ntlVec3d>(defaultValue);
}
AnimChannel<ntlSetVec3f> AttributeList::readChannelSetVec3f(string name, ntlSetVec3f defaultValue, string source, string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelSetVec3f","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return AnimChannel<ntlSetVec3f>(defaultValue); }
- AnimChannel<ntlSetVec3f> ret = find(name)->getChannelSetVec3f();
- find(name)->setUsed(true);
- //channelSimplifyVf(ret);
- return ret;
+ return AnimChannel<ntlSetVec3f>(defaultValue);
}
AnimChannel<float> AttributeList::readChannelSinglePrecFloat(string name, float defaultValue, string source, string target, bool needed ) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelSinglePrecFloat","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- 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;
+ return AnimChannel<float>(defaultValue);
}
AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name, ntlVec3f defaultValue, string source, string target, bool needed) {
- if(!exists(name)) {
- if(needed) { errFatal("AttributeList::readChannelVec3f","Required channel '"<<name<<"' for "<<target<<" from "<< source <<" not set! ", SIMWORLD_INITERROR); }
- return AnimChannel<ntlVec3f>(defaultValue); }
-
- AnimChannel<ntlVec3d> convert = find(name)->getChannelVec3d();
- // convert to float
- vector<ntlVec3f> vals;
- for(size_t i=0; i<convert.accessValues().size(); i++) {
- vals.push_back( vec2F(convert.accessValues()[i]) );
- }
- vector<double> times = convert.accessTimes();
- AnimChannel<ntlVec3f> ret(vals, times);
- find(name)->setUsed(true);
- channelSimplifyVf(ret);
- return ret;
+ return AnimChannel<ntlVec3f>(defaultValue);
}
/******************************************************************************
* destructor
*****************************************************************************/
AttributeList::~AttributeList() {
- for(map<string, Attribute*>::iterator i=mAttrs.begin();
- i != mAttrs.end(); i++) {
- if((*i).second) {
- delete (*i).second;
- (*i).second = NULL;
- }
- }
};
@@ -560,56 +128,18 @@ AttributeList::~AttributeList() {
*****************************************************************************/
//! debug function, prints value
-void Attribute::print()
-{
- std::ostringstream ostr;
- ostr << "ATTR "<< mName <<"= ";
- for(size_t i=0;i<mValue.size();i++) {
- ostr <<"'"<< mValue[i]<<"' ";
- }
- if(mIsChannel) {
- ostr << " CHANNEL: ";
- if(mChannelInited>0) {
- for(size_t i=0;i<mChannel.size();i++) {
- for(size_t j=0;j<mChannel[i].size();j++) {
- ostr <<"'"<< mChannel[i][j]<<"' ";
- }
- ostr << "@"<<mTimes[i]<<"; ";
- }
- } else {
- ostr <<" -nyi- ";
- }
- }
- ostr <<" (at line "<<mLine<<") "; //<< std::endl;
- debugOut( ostr.str(), 10);
+void Attribute::print() {
}
//! debug function, prints all attribs
-void AttributeList::print()
-{
- debugOut("Attribute "<<mName<<" values:", 10);
- for(map<string, Attribute*>::iterator i=mAttrs.begin();
- i != mAttrs.end(); i++) {
- if((*i).second) {
- (*i).second->print();
- }
- }
+void AttributeList::print() {
}
/******************************************************************************
* import attributes from other attribute list
*****************************************************************************/
-void AttributeList::import(AttributeList *oal)
-{
- for(map<string, Attribute*>::iterator i=oal->mAttrs.begin();
- i !=oal->mAttrs.end(); i++) {
- // FIXME - check freeing of copyied attributes
- if((*i).second) {
- Attribute *newAttr = new Attribute( *(*i).second );
- mAttrs[ (*i).first ] = newAttr;
- }
- }
+void AttributeList::import(AttributeList *oal) {
}
@@ -672,7 +202,6 @@ static bool channelSimplifyScalarT(AnimChannel<SCALAR> &channel) {
int size = channel.getSize();
if(size<=1) return false;
float *nchannel = new float[2*size];
- if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
// convert to array
for(size_t i=0; i<channel.accessValues().size(); i++) {
nchannel[i*2 + 0] = (float)channel.accessValues()[i];
@@ -687,7 +216,6 @@ static bool channelSimplifyScalarT(AnimChannel<SCALAR> &channel) {
times.push_back( (double)(nchannel[i*2 + 1]) );
}
channel = AnimChannel<SCALAR>(vals, times);
- if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
}
delete [] nchannel;
return ret;
@@ -700,7 +228,6 @@ static bool channelSimplifyVecT(AnimChannel<VEC> &channel) {
int size = channel.getSize();
if(size<=1) return false;
float *nchannel = new float[4*size];
- if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
// convert to array
for(size_t i=0; i<channel.accessValues().size(); i++) {
nchannel[i*4 + 0] = (float)channel.accessValues()[i][0];
@@ -717,7 +244,6 @@ static bool channelSimplifyVecT(AnimChannel<VEC> &channel) {
times.push_back( (double)(nchannel[i*4 + 3]) );
}
channel = AnimChannel<VEC>(vals, times);
- if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
}
delete [] nchannel;
return ret;
@@ -742,13 +268,7 @@ 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() ); }
-}
-
-
+// is now in header file: debugPrintChannel()
// hack to force instantiation
void __forceAnimChannelInstantiation() {
AnimChannel< float > tmp1;
diff --git a/intern/elbeem/intern/attributes.h b/intern/elbeem/intern/attributes.h
index 20e5341d5fc..19355095351 100644
--- a/intern/elbeem/intern/attributes.h
+++ b/intern/elbeem/intern/attributes.h
@@ -1,9 +1,9 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
- * configuration attribute storage class and attribute class
+ * DEPRECATED - replaced by elbeem API, only channels are still used
*
*****************************************************************************/
@@ -38,7 +38,7 @@ class AnimChannel
~AnimChannel() { };
// get interpolated value at time t
- Scalar get(double t) {
+ Scalar get(double t) const {
if(!mInited) { Scalar null; null=(Scalar)(0.0); return null; }
if(t<=mTimes[0]) { return mValue[0]; }
if(t>=mTimes[mTimes.size()-1]) { return mValue[mTimes.size()-1]; }
@@ -63,7 +63,7 @@ class AnimChannel
};
// get uninterpolated value at time t
- Scalar getConstant(double t) {
+ Scalar getConstant(double t) const {
//errMsg("DEBB","getc"<<t<<" ");
if(!mInited) { Scalar null; null=(Scalar)0.0; return null; }
if(t<=mTimes[0]) { return mValue[0]; }
@@ -90,10 +90,10 @@ class AnimChannel
//! debug function, prints to stdout if DEBUG_CHANNELS flag is enabled, used in constructors
void debugPrintChannel();
//! valid init?
- bool isInited() { return mInited; }
+ bool isInited() const { return mInited; }
//! get number of entries (value and time sizes have to be equal)
- int getSize() { return mValue.size(); };
+ int getSize() const { return mValue.size(); };
//! raw access of value vector
vector<Scalar> &accessValues() { return mValue; }
//! raw access of time vector
@@ -110,178 +110,84 @@ class AnimChannel
};
-//! A single 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;
+};
+
+
+// warning: DEPRECATED - replaced by elbeem API
class Attribute
{
public:
- //! Standard constructor
- Attribute(string mn, vector<string> &value, int setline,bool channel) :
- mName(mn), mValue(value),
- mLine(setline), mUsed(false), mIsChannel(channel),
- mChannelInited(-1) { };
- //! Copy constructor
- Attribute(Attribute &a) :
- mName(a.mName), mValue(a.mValue),
- mLine(a.mLine), mUsed(false), mIsChannel(a.mIsChannel),
- mChannelInited(a.mChannelInited),
- mChannel(a.mChannel), mTimes(a.mTimes) { };
- //! Destructor
- ~Attribute() { /* empty */ };
-
- //! set used flag
- void setUsed(bool set){ mUsed = set; }
- //! get used flag
- bool getUsed() { return mUsed; }
-
- //! set channel flag
- void setIsChannel(bool set){ mIsChannel = set; }
- //! get channel flag
- bool getIsChannel() { return mIsChannel; }
-
- //! get value as string
+ Attribute(string mn, vector<string> &value, int setline,bool channel) { };
+ Attribute(Attribute &a) { };
+ ~Attribute() { };
+
+ void setUsed(bool set){ }
+ bool getUsed() { return true; }
+ void setIsChannel(bool set){ }
+ bool getIsChannel() { return false; }
+
string getAsString(bool debug=false);
- //! get value as integer value
int getAsInt();
- //! get value as boolean
bool getAsBool();
- //! get value as double value
double getAsFloat();
- //! get value as 3d vector
ntlVec3d getAsVec3d();
- //! get value as 4x4 matrix
void getAsMat4Gfx(ntlMatrix4x4<gfxReal> *mat);
- //! get channel as integer value
AnimChannel<int> getChannelInt();
- //! get channel as double value
AnimChannel<double> getChannelFloat();
- //! get channel as double vector
AnimChannel<ntlVec3d> getChannelVec3d();
- //! get channel as float vector set
AnimChannel<ntlSetVec3f> getChannelSetVec3f();
- //! get the concatenated string of all value string
string getCompleteString();
-
- //! debug function, prints value
void print();
protected:
- /*! internal - init channel before access */
bool initChannel(int elemSize);
-
- /*! the attr name */
- string mName;
-
- /*! the attr value */
- vector<string> mValue;
-
- /*! line where the value was defined in the config file (for error messages) */
- int mLine;
-
- /*! was this attribute used? */
- bool mUsed;
-
- /*! does this attribute have a channel? */
- bool mIsChannel;
- /*! does this attribute have a channel? */
- int mChannelInited;
-
- /*! channel attribute values (first one equals mValue) */
- vector< vector< string > > mChannel;
- /*! channel attr times */
- vector< double > mTimes;
};
-// 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;
-};
-
+// warning: DEPRECATED - replaced by elbeem API
//! The list of configuration attributes
class AttributeList
{
public:
- //! Standard constructor
- AttributeList(string name) :
- mName(name), mAttrs() { };
- //! Destructor , delete all contained attribs
+ AttributeList(string name) { };
~AttributeList();
-
- /*! add an attribute to this list */
- void addAttr(string name, vector<string> &value, int line, bool isChannel) {
- if(exists(name)) delete mAttrs[name];
- mAttrs[name] = new Attribute(name,value,line, isChannel);
- }
-
- /*! check if an attribute is set */
- bool exists(string name) {
- if(mAttrs.find(name) == mAttrs.end()) return false;
- return true;
- }
-
- /*! get an attribute */
- Attribute *find(string name) {
- if(mAttrs.find(name) == mAttrs.end()) {
- errFatal("AttributeList::find","Invalid attribute '"<<name<<"' , not found...",SIMWORLD_INITERROR );
- // just create a new empty one (warning: small memory leak!), and exit as soon as possible
- vector<string> empty;
- return new Attribute(name,empty, -1, 0);
- }
- return mAttrs[name];
- }
-
- //! set all params to used, for invisible objects
+ void addAttr(string name, vector<string> &value, int line, bool isChannel) { }
+ bool exists(string name) { return false; }
void setAllUsed();
- //! check if there were unknown params
bool checkUnusedParams();
-
- //! import attributes from other attribute list
void import(AttributeList *oal);
-
- //! read attributes for object initialization
int readInt(string name, int defaultValue, string source,string target, bool needed);
bool readBool(string name, bool defaultValue, string source,string target, bool needed);
double readFloat(string name, double defaultValue, string source,string target, bool needed);
string readString(string name, string defaultValue, string source,string target, bool needed);
ntlVec3d readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed);
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, 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);
-
- //! debug function, prints all attribs
void print();
-
protected:
-
- /*! attribute name (form config file) */
- string mName;
-
- /*! the global attribute storage */
- map<string, Attribute*> mAttrs;
-
};
ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel);
@@ -297,6 +203,14 @@ bool channelSimplifyi (AnimChannel<int > &channel);
bool channelSimplifyf (AnimChannel<float > &channel);
bool channelSimplifyd (AnimChannel<double > &channel);
+//! output channel values? on=1/off=0
+#define DEBUG_PCHANNELS 0
+
+//! debug function, prints to stdout if DEBUG_PCHANNELS flag is enabled, used in constructors
+template<class Scalar>
+void AnimChannel<Scalar>::debugPrintChannel() { }
+
+
#define NTL_ATTRIBUTES_H
#endif
diff --git a/intern/elbeem/intern/elbeem.cpp b/intern/elbeem/intern/elbeem.cpp
index d4242da4d5e..b2779f51c3b 100644
--- a/intern/elbeem/intern/elbeem.cpp
+++ b/intern/elbeem/intern/elbeem.cpp
@@ -3,7 +3,7 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Main program functions
*/
@@ -64,10 +64,11 @@ void elbeemResetSettings(elbeemSimulationSettings *set) {
set->channelSizeGravity=0;
set->channelGravity=NULL;
- set->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP;
- set->obstaclePartslip= 0.;
+ set->domainobsType= FLUIDSIM_OBSTACLE_NOSLIP;
+ set->domainobsPartslip= 0.;
set->generateVertexVectors = 0;
set->surfaceSmoothing = 1.;
+ set->surfaceSubdivs = 1;
set->farFieldSize = 0.;
set->runsimCallback = NULL;
@@ -83,6 +84,7 @@ extern "C"
int elbeemInit() {
setElbeemState( SIMWORLD_INITIALIZING );
setElbeemErrorString("[none]");
+ resetGlobalColorSetting();
elbeemCheckDebugEnv();
debMsgStd("performElbeemSimulation",DM_NOTIFY,"El'Beem Simulation Init Start as Plugin, debugLevel:"<<gDebugLevel<<" ...\n", 2);
@@ -150,6 +152,7 @@ void elbeemResetMesh(elbeemMesh *mesh) {
mesh->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP;
mesh->obstaclePartslip= 0.;
+ mesh->obstacleImpactFactor= 1.;
mesh->volumeInitType= OB_VOLUMEINIT_VOLUME;
@@ -193,6 +196,7 @@ int elbeemAddMesh(elbeemMesh *mesh) {
obj->setGeoInitIntersect(true);
obj->setGeoInitType(initType);
obj->setGeoPartSlipValue(mesh->obstaclePartslip);
+ obj->setGeoImpactFactor(mesh->obstacleImpactFactor);
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]) );
diff --git a/intern/elbeem/intern/elbeem.h b/intern/elbeem/intern/elbeem.h
index ea21e807a6f..b3feda8bbe8 100644
--- a/intern/elbeem/intern/elbeem.h
+++ b/intern/elbeem/intern/elbeem.h
@@ -3,7 +3,7 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* API header
*/
@@ -72,13 +72,14 @@ typedef struct elbeemSimulationSettings {
float *channelGravity; // vector
/* boundary types and settings for domain walls */
- short obstacleType;
- float obstaclePartslip;
+ short domainobsType;
+ float domainobsPartslip;
/* generate speed vectors for vertices (e.g. for image based motion blur)*/
short generateVertexVectors;
/* strength of surface smoothing */
float surfaceSmoothing;
- // TODO add surf gen flags
+ /* no. of surface subdivisions */
+ int surfaceSubdivs;
/* global transformation to apply to fluidsim mesh */
float surfaceTrafo[4*4];
@@ -147,6 +148,8 @@ typedef struct elbeemMesh {
/* boundary types and settings */
short obstacleType;
float obstaclePartslip;
+ /* amount of force transfer from fluid to obj, 0=off, 1=normal */
+ float obstacleImpactFactor;
/* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */
short volumeInitType;
@@ -230,5 +233,8 @@ double elbeemEstimateMemreq(int res,
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
+// all boundary types at once
+#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 283fd17eb94..fdef04dc5c6 100644
--- a/intern/elbeem/intern/isosurface.cpp
+++ b/intern/elbeem/intern/isosurface.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Marching Cubes surface mesh generation
*
@@ -9,12 +9,10 @@
#include "isosurface.h"
#include "mcubes_tables.h"
-#include "ntl_ray.h"
-
+#include "particletracer.h"
#include <algorithm>
#include <stdio.h>
-
// sirdude fix for solaris
#if !defined(linux) && (defined (__sparc) || defined (__sparc__))
#include <ieeefp.h>
@@ -30,14 +28,17 @@ IsoSurface::IsoSurface(double iso) :
mpData(NULL),
mIsoValue( iso ),
mPoints(),
+ mUseFullEdgeArrays(false),
mpEdgeVerticesX(NULL), mpEdgeVerticesY(NULL), mpEdgeVerticesZ(NULL),
+ mEdgeArSize(-1),
mIndices(),
mStart(0.0), mEnd(0.0), mDomainExtent(0.0),
mInitDone(false),
mSmoothSurface(0.0), mSmoothNormals(0.0),
mAcrossEdge(), mAdjacentFaces(),
- mCutoff(-1), mCutArray(NULL),// off by default
+ mCutoff(-1), mCutArray(NULL), // off by default
+ mpIsoParts(NULL), mPartSize(0.), mSubdivs(0),
mFlagCnt(1),
mSCrad1(0.), mSCrad2(0.), mSCcenter(0.)
{
@@ -49,6 +50,10 @@ IsoSurface::IsoSurface(double iso) :
*****************************************************************************/
void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx extent)
{
+ // range 1-10 (max due to subd array in triangulate)
+ if(mSubdivs<1) mSubdivs=1;
+ if(mSubdivs>10) mSubdivs=10;
+
// init solver and size
mSizex = setx;
mSizey = sety;
@@ -74,14 +79,27 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e
for(int i=0;i<nodes;i++) { mpData[i] = 0.0; }
// allocate edge arrays (last slices are never used...)
- mpEdgeVerticesX = new int[nodes];
- mpEdgeVerticesY = new int[nodes];
- mpEdgeVerticesZ = new int[nodes];
- for(int i=0;i<nodes;i++) { mpEdgeVerticesX[i] = mpEdgeVerticesY[i] = mpEdgeVerticesZ[i] = -1; }
+ int initsize = -1;
+ if(mUseFullEdgeArrays) {
+ mEdgeArSize = nodes;
+ mpEdgeVerticesX = new int[nodes];
+ mpEdgeVerticesY = new int[nodes];
+ mpEdgeVerticesZ = new int[nodes];
+ initsize = 3*nodes;
+ } else {
+ int sliceNodes = 2*mSizex*mSizey*mSubdivs*mSubdivs;
+ mEdgeArSize = sliceNodes;
+ mpEdgeVerticesX = new int[sliceNodes];
+ mpEdgeVerticesY = new int[sliceNodes];
+ mpEdgeVerticesZ = new int[sliceNodes];
+ initsize = 3*sliceNodes;
+ }
+ for(int i=0;i<mEdgeArSize;i++) { mpEdgeVerticesX[i] = mpEdgeVerticesY[i] = mpEdgeVerticesZ[i] = -1; }
// WARNING - make sure this is consistent with calculateMemreqEstimate
// marching cubes are ready
mInitDone = true;
+ debMsgStd("IsoSurface::initializeIsosurface",DM_MSG,"Inited, edgenodes:"<<initsize<<" subdivs:"<<mSubdivs<<" fulledg:"<<mUseFullEdgeArrays , 10);
}
@@ -106,6 +124,10 @@ IsoSurface::~IsoSurface( void )
+//static inline getSubdivData(IsoSurface* iso,int ai,aj,ak, si,sj) {
+ //int srci =
+//}
+
/******************************************************************************
* triangulate the scalar field given by pointer
@@ -132,7 +154,7 @@ void IsoSurface::triangulate( void )
mPoints.clear();
// reset edge vertices
- for(int i=0;i<(mSizex*mSizey*mSizez);i++) {
+ for(int i=0;i<mEdgeArSize;i++) {
mpEdgeVerticesX[i] = -1;
mpEdgeVerticesY[i] = -1;
mpEdgeVerticesZ[i] = -1;
@@ -160,150 +182,473 @@ void IsoSurface::triangulate( void )
const int coAdd=2;
// let the cubes march
- pz = mStart[2]-gsz*0.5;
- for(int k=1;k<(mSizez-2);k++) {
- pz += gsz;
- py = mStart[1]-gsy*0.5;
- for(int j=1;j<(mSizey-2);j++) {
- py += gsy;
- px = mStart[0]-gsx*0.5;
- for(int i=1;i<(mSizex-2);i++) {
- px += gsx;
- int baseIn = ISOLEVEL_INDEX( i+0, j+0, k+0);
-
- value[0] = *getData(i ,j ,k );
- value[1] = *getData(i+1,j ,k );
- value[2] = *getData(i+1,j+1,k );
- value[3] = *getData(i ,j+1,k );
- value[4] = *getData(i ,j ,k+1);
- value[5] = *getData(i+1,j ,k+1);
- value[6] = *getData(i+1,j+1,k+1);
- value[7] = *getData(i ,j+1,k+1);
-
- /*int bndskip = 0; // BNDOFFT
- for(int s=0; s<8; s++) if(value[s]==-76.) bndskip++;
- if(bndskip>0) continue; // */
-
- // check intersections of isosurface with edges, and calculate cubie index
- cubeIndex = 0;
- if (value[0] < mIsoValue) cubeIndex |= 1;
- if (value[1] < mIsoValue) cubeIndex |= 2;
- if (value[2] < mIsoValue) cubeIndex |= 4;
- if (value[3] < mIsoValue) cubeIndex |= 8;
- if (value[4] < mIsoValue) cubeIndex |= 16;
- if (value[5] < mIsoValue) cubeIndex |= 32;
- if (value[6] < mIsoValue) cubeIndex |= 64;
- if (value[7] < mIsoValue) cubeIndex |= 128;
-
- // No triangles to generate?
- if (mcEdgeTable[cubeIndex] == 0) {
- continue;
- }
+ if(mSubdivs<=1) {
+
+ pz = mStart[2]-gsz*0.5;
+ for(int k=1;k<(mSizez-2);k++) {
+ pz += gsz;
+ py = mStart[1]-gsy*0.5;
+ for(int j=1;j<(mSizey-2);j++) {
+ py += gsy;
+ px = mStart[0]-gsx*0.5;
+ for(int i=1;i<(mSizex-2);i++) {
+ px += gsx;
+
+ value[0] = *getData(i ,j ,k );
+ value[1] = *getData(i+1,j ,k );
+ value[2] = *getData(i+1,j+1,k );
+ value[3] = *getData(i ,j+1,k );
+ value[4] = *getData(i ,j ,k+1);
+ value[5] = *getData(i+1,j ,k+1);
+ value[6] = *getData(i+1,j+1,k+1);
+ value[7] = *getData(i ,j+1,k+1);
+
+ // check intersections of isosurface with edges, and calculate cubie index
+ cubeIndex = 0;
+ if (value[0] < mIsoValue) cubeIndex |= 1;
+ if (value[1] < mIsoValue) cubeIndex |= 2;
+ if (value[2] < mIsoValue) cubeIndex |= 4;
+ if (value[3] < mIsoValue) cubeIndex |= 8;
+ if (value[4] < mIsoValue) cubeIndex |= 16;
+ if (value[5] < mIsoValue) cubeIndex |= 32;
+ if (value[6] < mIsoValue) cubeIndex |= 64;
+ if (value[7] < mIsoValue) cubeIndex |= 128;
+
+ // No triangles to generate?
+ if (mcEdgeTable[cubeIndex] == 0) {
+ continue;
+ }
- // where to look up if this point already exists
- eVert[ 0] = &mpEdgeVerticesX[ baseIn ];
- eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ];
- eVert[ 2] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+1, k+0) ];
- eVert[ 3] = &mpEdgeVerticesY[ baseIn ];
-
- eVert[ 4] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+0, k+1) ];
- eVert[ 5] = &mpEdgeVerticesY[ ISOLEVEL_INDEX( i+1, j+0, k+1) ];
- eVert[ 6] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+1, k+1) ];
- eVert[ 7] = &mpEdgeVerticesY[ ISOLEVEL_INDEX( i+0, j+0, k+1) ];
-
- eVert[ 8] = &mpEdgeVerticesZ[ baseIn ];
- eVert[ 9] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+1, j+0, k+0) ];
- eVert[10] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+1, j+1, k+0) ];
- eVert[11] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+0, j+1, k+0) ];
-
- // grid positions
- pos[0] = ntlVec3Gfx(px ,py ,pz);
- pos[1] = ntlVec3Gfx(px+gsx,py ,pz);
- pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz);
- pos[3] = ntlVec3Gfx(px ,py+gsy,pz);
- pos[4] = ntlVec3Gfx(px ,py ,pz+gsz);
- pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz);
- pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz);
- pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz);
-
- // check all edges
- for(int e=0;e<12;e++) {
-
- if (mcEdgeTable[cubeIndex] & (1<<e)) {
- // is the vertex already calculated?
- if(*eVert[ e ] < 0) {
- // interpolate edge
- const int e1 = mcEdges[e*2 ];
- const int e2 = mcEdges[e*2+1];
- const ntlVec3Gfx p1 = pos[ e1 ]; // scalar field pos 1
- const ntlVec3Gfx p2 = pos[ e2 ]; // scalar field pos 2
- const float valp1 = value[ e1 ]; // scalar field val 1
- const float valp2 = value[ e2 ]; // scalar field val 2
-
- float mu;
- if(valp1 < valp2) {
- mu = 1.0 - 1.0*(valp1 + valp2 - mIsoValue);
- } else {
- mu = 0.0 + 1.0*(valp1 + valp2 - mIsoValue);
+ // where to look up if this point already exists
+ int edgek = 0;
+ if(mUseFullEdgeArrays) edgek=k;
+ const int baseIn = ISOLEVEL_INDEX( i+0, j+0, edgek+0);
+ eVert[ 0] = &mpEdgeVerticesX[ baseIn ];
+ eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ];
+ eVert[ 2] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+1, edgek+0) ];
+ eVert[ 3] = &mpEdgeVerticesY[ baseIn ];
+
+ eVert[ 4] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+0, edgek+1) ];
+ eVert[ 5] = &mpEdgeVerticesY[ ISOLEVEL_INDEX( i+1, j+0, edgek+1) ];
+ eVert[ 6] = &mpEdgeVerticesX[ ISOLEVEL_INDEX( i+0, j+1, edgek+1) ];
+ eVert[ 7] = &mpEdgeVerticesY[ ISOLEVEL_INDEX( i+0, j+0, edgek+1) ];
+
+ eVert[ 8] = &mpEdgeVerticesZ[ baseIn ];
+ eVert[ 9] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+1, j+0, edgek+0) ];
+ eVert[10] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+1, j+1, edgek+0) ];
+ eVert[11] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+0, j+1, edgek+0) ];
+
+ // grid positions
+ pos[0] = ntlVec3Gfx(px ,py ,pz);
+ pos[1] = ntlVec3Gfx(px+gsx,py ,pz);
+ pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz);
+ pos[3] = ntlVec3Gfx(px ,py+gsy,pz);
+ pos[4] = ntlVec3Gfx(px ,py ,pz+gsz);
+ pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz);
+ pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz);
+ pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz);
+
+ // check all edges
+ for(int e=0;e<12;e++) {
+ if (mcEdgeTable[cubeIndex] & (1<<e)) {
+ // is the vertex already calculated?
+ if(*eVert[ e ] < 0) {
+ // interpolate edge
+ const int e1 = mcEdges[e*2 ];
+ const int e2 = mcEdges[e*2+1];
+ const ntlVec3Gfx p1 = pos[ e1 ]; // scalar field pos 1
+ const ntlVec3Gfx p2 = pos[ e2 ]; // scalar field pos 2
+ const float valp1 = value[ e1 ]; // scalar field val 1
+ const float valp2 = value[ e2 ]; // scalar field val 2
+ const float mu = (mIsoValue - valp1) / (valp2 - valp1);
+
+ // init isolevel vertex
+ ilv.v = p1 + (p2-p1)*mu;
+ ilv.n = getNormal( i+cubieOffsetX[e1], j+cubieOffsetY[e1], k+cubieOffsetZ[e1]) * (1.0-mu) +
+ getNormal( i+cubieOffsetX[e2], j+cubieOffsetY[e2], k+cubieOffsetZ[e2]) * ( mu) ;
+ mPoints.push_back( ilv );
+
+ triIndices[e] = (mPoints.size()-1);
+ // store vertex
+ *eVert[ e ] = triIndices[e];
+ } else {
+ // retrieve from vert array
+ triIndices[e] = *eVert[ e ];
}
+ } // along all edges
+ }
- //float isov2 = mIsoValue;
- //isov2 = (valp1+valp2)*0.5;
- //mu = (isov2 - valp1) / (valp2 - valp1);
- //mu = (isov2) / (valp2 - valp1);
- mu = (mIsoValue - valp1) / (valp2 - valp1);
-
- // init isolevel vertex
- ilv.v = p1 + (p2-p1)*mu;
- ilv.n = getNormal( i+cubieOffsetX[e1], j+cubieOffsetY[e1], k+cubieOffsetZ[e1]) * (1.0-mu) +
- getNormal( i+cubieOffsetX[e2], j+cubieOffsetY[e2], k+cubieOffsetZ[e2]) * ( mu) ;
- mPoints.push_back( ilv );
-
- triIndices[e] = (mPoints.size()-1);
- // store vertex
- *eVert[ e ] = triIndices[e];
- } else {
- // retrieve from vert array
- triIndices[e] = *eVert[ e ];
- }
- } // along all edges
+ if( (i<coAdd+mCutoff) || (j<coAdd+mCutoff) ||
+ ((mCutoff>0) && (k<coAdd)) ||// bottom layer
+ (i>mSizex-2-coAdd-mCutoff) ||
+ (j>mSizey-2-coAdd-mCutoff) ) {
+ if(mCutArray) {
+ if(k < mCutArray[j*this->mSizex+i]) continue;
+ } else { continue; }
+ }
+ // Create the triangles...
+ for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+0] ] );
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] );
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
+ }
+
+ }//i
+ }// j
+
+ // copy edge arrays
+ if(!mUseFullEdgeArrays) {
+ for(int j=0;j<(mSizey-0);j++)
+ for(int i=0;i<(mSizex-0);i++) {
+ //int edgek = 0;
+ const int dst = ISOLEVEL_INDEX( i+0, j+0, 0);
+ const int src = ISOLEVEL_INDEX( i+0, j+0, 1);
+ mpEdgeVerticesX[ dst ] = mpEdgeVerticesX[ src ];
+ mpEdgeVerticesY[ dst ] = mpEdgeVerticesY[ src ];
+ mpEdgeVerticesZ[ dst ] = mpEdgeVerticesZ[ src ];
+ mpEdgeVerticesX[ src ]=-1;
+ mpEdgeVerticesY[ src ]=-1;
+ mpEdgeVerticesZ[ src ]=-1;
}
+ } // */
+
+ } // k
+
+ // precalculate normals using an approximation of the scalar field gradient
+ for(int ni=0;ni<(int)mPoints.size();ni++) { normalize( mPoints[ni].n ); }
+
+ } else { // subdivs
+
+#define EDGEAR_INDEX(Ai,Aj,Ak, Bi,Bj) ((mSizex*mSizey*mSubdivs*mSubdivs*(Ak))+\
+ (mSizex*mSubdivs*((Aj)*mSubdivs+(Bj)))+((Ai)*mSubdivs)+(Bi))
+
+#define ISOTRILININT(fi,fj,fk) ( \
+ (1.-(fi))*(1.-(fj))*(1.-(fk))*orgval[0] + \
+ ( (fi))*(1.-(fj))*(1.-(fk))*orgval[1] + \
+ ( (fi))*( (fj))*(1.-(fk))*orgval[2] + \
+ (1.-(fi))*( (fj))*(1.-(fk))*orgval[3] + \
+ (1.-(fi))*(1.-(fj))*( (fk))*orgval[4] + \
+ ( (fi))*(1.-(fj))*( (fk))*orgval[5] + \
+ ( (fi))*( (fj))*( (fk))*orgval[6] + \
+ (1.-(fi))*( (fj))*( (fk))*orgval[7] )
+
+ // use subdivisions
+ gfxReal subdfac = 1./(gfxReal)(mSubdivs);
+ gfxReal orgGsx = gsx;
+ gfxReal orgGsy = gsy;
+ gfxReal orgGsz = gsz;
+ gsx *= subdfac;
+ gsy *= subdfac;
+ gsz *= subdfac;
+ if(mUseFullEdgeArrays) {
+ errMsg("IsoSurface::triangulate","Disabling mUseFullEdgeArrays!");
+ }
- if( (i<coAdd+mCutoff) ||
- (j<coAdd+mCutoff) ||
- ((mCutoff>0) && (k<coAdd)) ||// bottom layer
- (i>mSizex-2-coAdd-mCutoff) ||
- (j>mSizey-2-coAdd-mCutoff) ) {
- if(mCutArray) {
- if(k < mCutArray[j*this->mSizex+i]) continue;
- } else {
- continue;
+ // subdiv local arrays
+ gfxReal orgval[8];
+ gfxReal subdAr[2][11][11]; // max 10 subdivs!
+ ParticleObject* *arppnt = new ParticleObject*[mSizez*mSizey*mSizex];
+
+ // construct pointers
+ // part test
+ int pInUse = 0;
+ int pUsedTest = 0;
+ // reset particles
+ // reset list array
+ for(int k=0;k<(mSizez);k++)
+ for(int j=0;j<(mSizey);j++)
+ for(int i=0;i<(mSizex);i++) {
+ arppnt[ISOLEVEL_INDEX(i,j,k)] = NULL;
+ }
+ if(mpIsoParts) {
+ for(vector<ParticleObject>::iterator pit= mpIsoParts->getParticlesBegin();
+ pit!= mpIsoParts->getParticlesEnd(); pit++) {
+ if( (*pit).getActive()==false ) continue;
+ if( (*pit).getType()!=PART_DROP) continue;
+ (*pit).setNext(NULL);
+ }
+ // build per node lists
+ for(vector<ParticleObject>::iterator pit= mpIsoParts->getParticlesBegin();
+ pit!= mpIsoParts->getParticlesEnd(); pit++) {
+ if( (*pit).getActive()==false ) continue;
+ if( (*pit).getType()!=PART_DROP) continue;
+ // check lifetime ignored here
+ ParticleObject *p = &(*pit);
+ const ntlVec3Gfx ppos = p->getPos();
+ const int pi= (int)round(ppos[0])+0;
+ const int pj= (int)round(ppos[1])+0;
+ int pk= (int)round(ppos[2])+0;// no offset necessary
+ // 2d should be handled by solver. if(LBMDIM==2) { pk = 0; }
+
+ if(pi<0) continue;
+ if(pj<0) continue;
+ if(pk<0) continue;
+ if(pi>mSizex-1) continue;
+ if(pj>mSizey-1) continue;
+ if(pk>mSizez-1) continue;
+ ParticleObject* &pnt = arppnt[ISOLEVEL_INDEX(pi,pj,pk)];
+ if(pnt) {
+ // append
+ ParticleObject* listpnt = pnt;
+ while(listpnt) {
+ if(!listpnt->getNext()) {
+ listpnt->setNext(p); listpnt = NULL;
+ } else {
+ listpnt = listpnt->getNext();
+ }
}
+ } else {
+ // start new list
+ pnt = p;
}
+ pInUse++;
+ }
+ } // mpIsoParts
+
+ debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"<<pInUse<<", Subdivs:"<<mSubdivs, 9);
+ pz = mStart[2]-(double)(0.*gsz)-0.5*orgGsz;
+ for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) {
+ pz += gsz;
+ const int k = ok/mSubdivs;
+ if(k<=0) continue; // skip zero plane
+ for(int j=1;j<(mSizey-2);j++) {
+ for(int i=1;i<(mSizex-2);i++) {
+
+ orgval[0] = *getData(i ,j ,k );
+ orgval[1] = *getData(i+1,j ,k );
+ orgval[2] = *getData(i+1,j+1,k ); // with subdivs
+ orgval[3] = *getData(i ,j+1,k );
+ orgval[4] = *getData(i ,j ,k+1);
+ orgval[5] = *getData(i+1,j ,k+1);
+ orgval[6] = *getData(i+1,j+1,k+1); // with subdivs
+ orgval[7] = *getData(i ,j+1,k+1);
+
+ // prebuild subsampled array slice
+ const int sdkOffset = ok-k*mSubdivs;
+ for(int sdk=0; sdk<2; sdk++)
+ for(int sdj=0; sdj<mSubdivs+1; sdj++)
+ for(int sdi=0; sdi<mSubdivs+1; sdi++) {
+ subdAr[sdk][sdj][sdi] = ISOTRILININT(sdi*subdfac, sdj*subdfac, (sdkOffset+sdk)*subdfac);
+ }
+
+ const int poDistOffset=2;
+ for(int pok=-poDistOffset; pok<1+poDistOffset; pok++) {
+ if(k+pok<0) continue;
+ if(k+pok>=mSizez-1) continue;
+ for(int poj=-poDistOffset; poj<1+poDistOffset; poj++) {
+ if(j+poj<0) continue;
+ if(j+poj>=mSizey-1) continue;
+ for(int poi=-poDistOffset; poi<1+poDistOffset; poi++) {
+ if(i+poi<0) continue;
+ if(i+poi>=mSizex-1) continue;
+ ParticleObject *p;
+ p = arppnt[ISOLEVEL_INDEX(i+poi,j+poj,k+pok)];
+ while(p) { // */
+ /*
+ for(vector<ParticleObject>::iterator pit= mpIsoParts->getParticlesBegin();
+ pit!= mpIsoParts->getParticlesEnd(); pit++) { { { {
+ // debug test! , full list slow!
+ if(( (*pit).getActive()==false ) || ( (*pit).getType()!=PART_DROP)) continue;
+ ParticleObject *p;
+ p = &(*pit); // */
+
+ pUsedTest++;
+ ntlVec3Gfx ppos = p->getPos();
+ const int spi= (int)round( (ppos[0]+1.-(gfxReal)i) *(gfxReal)mSubdivs-1.5);
+ const int spj= (int)round( (ppos[1]+1.-(gfxReal)j) *(gfxReal)mSubdivs-1.5);
+ const int spk= (int)round( (ppos[2]+1.-(gfxReal)k) *(gfxReal)mSubdivs-1.5)-sdkOffset; // why -2?
+ // 2d should be handled by solver. if(LBMDIM==2) { spk = 0; }
+
+ gfxReal pfLen = p->getSize()*1.5*mPartSize; // test, was 1.1
+ const gfxReal minPfLen = subdfac*0.8;
+ if(pfLen<minPfLen) pfLen = minPfLen;
+ //errMsg("ISOPPP"," at "<<PRINT_IJK<<" pp"<<ppos<<" sp"<<PRINT_VEC(spi,spj,spk)<<" pflen"<<pfLen );
+ //errMsg("ISOPPP"," subdfac="<<subdfac<<" size"<<p->getSize()<<" ps"<<mPartSize );
+ const int icellpsize = (int)(1.*pfLen*(gfxReal)mSubdivs)+1;
+ for(int swk=-icellpsize; swk<=icellpsize; swk++) {
+ if(spk+swk< 0) { continue; }
+ if(spk+swk> 1) { continue; } // */
+ for(int swj=-icellpsize; swj<=icellpsize; swj++) {
+ if(spj+swj< 0) { continue; }
+ if(spj+swj>mSubdivs+0) { continue; } // */
+ for(int swi=-icellpsize; swi<=icellpsize; swi++) {
+ if(spi+swi< 0) { continue; }
+ if(spi+swi>mSubdivs+0) { continue; } // */
+ ntlVec3Gfx cellp = ntlVec3Gfx(
+ (1.5+(gfxReal)(spi+swi)) *subdfac + (gfxReal)(i-1),
+ (1.5+(gfxReal)(spj+swj)) *subdfac + (gfxReal)(j-1),
+ (1.5+(gfxReal)(spk+swk)+sdkOffset) *subdfac + (gfxReal)(k-1)
+ );
+ //if(swi==0 && swj==0 && swk==0) subdAr[spk][spj][spi] = 1.; // DEBUG
+ // clip domain boundaries again
+ if(cellp[0]<1.) { continue; }
+ if(cellp[1]<1.) { continue; }
+ if(cellp[2]<1.) { continue; }
+ if(cellp[0]>(gfxReal)mSizex-3.) { continue; }
+ if(cellp[1]>(gfxReal)mSizey-3.) { continue; }
+ if(cellp[2]>(gfxReal)mSizez-3.) { continue; }
+ gfxReal len = norm(cellp-ppos);
+ gfxReal isoadd = 0.;
+ const gfxReal baseIsoVal = mIsoValue*1.1;
+ if(len<pfLen) {
+ isoadd = baseIsoVal*1.;
+ } else {
+ // falloff linear with pfLen (kernel size=2pfLen
+ isoadd = baseIsoVal*(1. - (len-pfLen)/(pfLen));
+ }
+ if(isoadd<0.) { continue; }
+ //errMsg("ISOPPP"," at "<<PRINT_IJK<<" sp"<<PRINT_VEC(spi+swi,spj+swj,spk+swk)<<" cellp"<<cellp<<" pp"<<ppos << " l"<< len<< " add"<< isoadd);
+ const gfxReal arval = subdAr[spk+swk][spj+swj][spi+swi];
+ if(arval>1.) { continue; }
+ subdAr[spk+swk][spj+swj][spi+swi] = arval + isoadd;
+ } } }
+
+ p = p->getNext();
+ }
+ } } } // poDist loops */
+
+ py = mStart[1]+(((double)j-0.5)*orgGsy)-gsy;
+ for(int sj=0;sj<mSubdivs;sj++) {
+ py += gsy;
+ px = mStart[0]+(((double)i-0.5)*orgGsx)-gsx;
+ for(int si=0;si<mSubdivs;si++) {
+ px += gsx;
+ value[0] = subdAr[0+0][sj+0][si+0];
+ value[1] = subdAr[0+0][sj+0][si+1];
+ value[2] = subdAr[0+0][sj+1][si+1];
+ value[3] = subdAr[0+0][sj+1][si+0];
+ value[4] = subdAr[0+1][sj+0][si+0];
+ value[5] = subdAr[0+1][sj+0][si+1];
+ value[6] = subdAr[0+1][sj+1][si+1];
+ value[7] = subdAr[0+1][sj+1][si+0];
+
+ // check intersections of isosurface with edges, and calculate cubie index
+ cubeIndex = 0;
+ if (value[0] < mIsoValue) cubeIndex |= 1;
+ if (value[1] < mIsoValue) cubeIndex |= 2; // with subdivs
+ if (value[2] < mIsoValue) cubeIndex |= 4;
+ if (value[3] < mIsoValue) cubeIndex |= 8;
+ if (value[4] < mIsoValue) cubeIndex |= 16;
+ if (value[5] < mIsoValue) cubeIndex |= 32; // with subdivs
+ if (value[6] < mIsoValue) cubeIndex |= 64;
+ if (value[7] < mIsoValue) cubeIndex |= 128;
+
+ if (mcEdgeTable[cubeIndex] > 0) {
+
+ // where to look up if this point already exists
+ const int edgek = 0;
+ const int baseIn = EDGEAR_INDEX( i+0, j+0, edgek+0, si,sj);
+ eVert[ 0] = &mpEdgeVerticesX[ baseIn ];
+ eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ];
+ eVert[ 2] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ];
+ eVert[ 3] = &mpEdgeVerticesY[ baseIn ];
+
+ eVert[ 4] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ];
+ eVert[ 5] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+1,sj+0) ]; // with subdivs
+ eVert[ 6] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+1) ];
+ eVert[ 7] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ];
+
+ eVert[ 8] = &mpEdgeVerticesZ[ baseIn ];
+ eVert[ 9] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+0) ]; // with subdivs
+ eVert[10] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+1) ];
+ eVert[11] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ];
+
+ // grid positions
+ pos[0] = ntlVec3Gfx(px ,py ,pz);
+ pos[1] = ntlVec3Gfx(px+gsx,py ,pz);
+ pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz); // with subdivs
+ pos[3] = ntlVec3Gfx(px ,py+gsy,pz);
+ pos[4] = ntlVec3Gfx(px ,py ,pz+gsz);
+ pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz);
+ pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz); // with subdivs
+ pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz);
+
+ // check all edges
+ for(int e=0;e<12;e++) {
+ if (mcEdgeTable[cubeIndex] & (1<<e)) {
+ // is the vertex already calculated?
+ if(*eVert[ e ] < 0) {
+ // interpolate edge
+ const int e1 = mcEdges[e*2 ];
+ const int e2 = mcEdges[e*2+1];
+ const ntlVec3Gfx p1 = pos[ e1 ]; // scalar field pos 1
+ const ntlVec3Gfx p2 = pos[ e2 ]; // scalar field pos 2
+ const float valp1 = value[ e1 ]; // scalar field val 1
+ const float valp2 = value[ e2 ]; // scalar field val 2
+ const float mu = (mIsoValue - valp1) / (valp2 - valp1);
+
+ // init isolevel vertex
+ ilv.v = p1 + (p2-p1)*mu; // with subdivs
+ mPoints.push_back( ilv );
+ triIndices[e] = (mPoints.size()-1);
+ // store vertex
+ *eVert[ e ] = triIndices[e];
+ } else {
+ // retrieve from vert array
+ triIndices[e] = *eVert[ e ];
+ }
+ } // along all edges
+ }
+ // removed cutoff treatment...
+
+ // Create the triangles...
+ for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+0] ] );
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] ); // with subdivs
+ mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
+ //errMsg("TTT"," i1"<<mIndices[mIndices.size()-3]<<" "<< " i2"<<mIndices[mIndices.size()-2]<<" "<< " i3"<<mIndices[mIndices.size()-1]<<" "<< mIndices.size() );
+ }
- // Create the triangles...
- for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
- //errMsg("MC","tri "<<mIndices.size() <<" "<< triIndices[ mcTriTable[cubeIndex][e+0] ]<<" "<< triIndices[ mcTriTable[cubeIndex][e+1] ]<<" "<< triIndices[ mcTriTable[cubeIndex][e+2] ] );
- mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+0] ] );
- mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] );
- mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
+ } // triangles in edge table?
+
+ }//si
+ }// sj
+
+ }//i
+ }// j
+
+ // copy edge arrays
+ for(int j=0;j<(mSizey-0)*mSubdivs;j++)
+ for(int i=0;i<(mSizex-0)*mSubdivs;i++) {
+ //int edgek = 0;
+ const int dst = EDGEAR_INDEX( 0, 0, 0, i,j);
+ const int src = EDGEAR_INDEX( 0, 0, 1, i,j);
+ mpEdgeVerticesX[ dst ] = mpEdgeVerticesX[ src ];
+ mpEdgeVerticesY[ dst ] = mpEdgeVerticesY[ src ]; // with subdivs
+ mpEdgeVerticesZ[ dst ] = mpEdgeVerticesZ[ src ];
+ mpEdgeVerticesX[ src ]=-1;
+ mpEdgeVerticesY[ src ]=-1; // with subdivs
+ mpEdgeVerticesZ[ src ]=-1;
}
-
- }//i
- }// j
- } // k
-
- // precalculate normals using an approximation of the scalar field gradient
- for(int ni=0;ni<(int)mPoints.size();ni++) {
- // use triangle normals?, this seems better for File-IsoSurf
- normalize( mPoints[ni].n );
+ // */
+
+ } // ok, k subdiv loop
+
+ //delete [] subdAr;
+ delete [] arppnt;
+ computeNormals();
+ } // with subdivs
+
+ // perform smoothing
+ float smoSubdfac = 1.;
+ if(mSubdivs>0) {
+ //smoSubdfac = 1./(float)(mSubdivs);
+ smoSubdfac = powf(0.55,(float)mSubdivs); // slightly stronger
+ }
+ if(mSmoothSurface>0. || mSmoothNormals>0.) debMsgStd("IsoSurface::triangulate",DM_MSG,"Smoothing...",10);
+ if(mSmoothSurface>0.0) {
+ smoothSurface(mSmoothSurface*smoSubdfac, (mSmoothNormals<=0.0) );
+ }
+ if(mSmoothNormals>0.0) {
+ smoothNormals(mSmoothNormals*smoSubdfac);
}
- if(mSmoothSurface>0.0) { smoothSurface(mSmoothSurface, (mSmoothNormals<=0.0) ); }
- if(mSmoothNormals>0.0) { smoothNormals(mSmoothNormals); }
myTime_t tritimeend = getTime();
- debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<<mSmoothSurface<<","<<mSmoothNormals<<")" , 10 );
+ debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<<mSmoothSurface<<","<<mSmoothNormals<<"),"<<
+ " verts:"<<mPoints.size()<<" tris:"<<(mIndices.size()/3)<<" subdivs:"<<mSubdivs
+ , 10 );
+ if(mpIsoParts) debMsgStd("IsoSurface::triangulate",DM_MSG,"parts:"<<mpIsoParts->getNumParticles(), 10);
}
@@ -405,12 +750,8 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) {
/******************************************************************************
*
- * Surface improvement
- * makes use of trimesh2 library
- * http://www.cs.princeton.edu/gfx/proj/trimesh2/
- *
- * Copyright (c) 2004 Szymon Rusinkiewicz.
- * see COPYING_trimesh2
+ * Surface improvement, inspired by trimesh2 library
+ * (http://www.cs.princeton.edu/gfx/proj/trimesh2/)
*
*****************************************************************************/
@@ -420,9 +761,39 @@ void IsoSurface::setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc) {
mSCcenter = mscc;
}
+// compute normals for all generated triangles
+void IsoSurface::computeNormals() {
+ for(int i=0;i<(int)mPoints.size();i++) {
+ mPoints[i].n = ntlVec3Gfx(0.);
+ }
+
+ for(int i=0;i<(int)mIndices.size();i+=3) {
+ const int t1 = mIndices[i];
+ const int t2 = mIndices[i+1];
+ const int t3 = mIndices[i+2];
+ const ntlVec3Gfx p1 = mPoints[t1].v;
+ const ntlVec3Gfx p2 = mPoints[t2].v;
+ const ntlVec3Gfx p3 = mPoints[t3].v;
+ const ntlVec3Gfx n1=p1-p2;
+ const ntlVec3Gfx n2=p2-p3;
+ const ntlVec3Gfx n3=p3-p1;
+ const gfxReal len1 = normNoSqrt(n1);
+ const gfxReal len2 = normNoSqrt(n2);
+ const gfxReal len3 = normNoSqrt(n3);
+ const ntlVec3Gfx norm = cross(n1,n2);
+ mPoints[t1].n += norm * (1./(len1*len3));
+ mPoints[t2].n += norm * (1./(len1*len2));
+ mPoints[t3].n += norm * (1./(len2*len3));
+ }
+
+ for(int i=0;i<(int)mPoints.size();i++) {
+ normalize(mPoints[i].n);
+ }
+}
+
// Diffuse a vector field at 1 vertex, weighted by
// a gaussian of width 1/sqrt(invsigma2)
-bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int src, float invsigma2, ntlVec3Gfx &flt)
+bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int src, float invsigma2, ntlVec3Gfx &target)
{
if((neighbors[src].size()<1) || (pointareas[src]<=0.0)) return 0;
const ntlVec3Gfx srcp = mPoints[src].v;
@@ -431,31 +802,23 @@ bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, i
ntlVec3Gfx dp = mSCcenter-srcp; dp[2] = 0.0; // only xy-plane
float rd = normNoSqrt(dp);
if(rd > mSCrad2) {
- //errMsg("TRi","p"<<srcp<<" c"<<mSCcenter<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" ");
- //invsigma2 *= (rd*rd-mSCrad1);
- //flt = ntlVec3Gfx(100); return 1;
return 0;
} else if(rd > mSCrad1) {
// optimize?
float org = 1.0/sqrt(invsigma2);
org *= (1.0- (rd-mSCrad1) / (mSCrad2-mSCrad1));
invsigma2 = 1.0/(org*org);
- //flt = ntlVec3Gfx((rd-mSCrad1) / (mSCrad2-mSCrad1)); return 1;
//errMsg("TRi","p"<<srcp<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" org:"<<org<<" is:"<<invsigma2);
- //invsigma2 *= (rd*rd-mSCrad1);
- //return 0;
} else {
}
}
- flt = ntlVec3Gfx(0.0);
- flt += *(field+pointerScale*src) *pointareas[src];
- float sum_w = pointareas[src];
- //const ntlVec3Gfx &nv = mPoints[src].n;
+ target = ntlVec3Gfx(0.0);
+ target += *(field+pointerScale*src) *pointareas[src];
+ float smstrSum = pointareas[src];
int flag = mFlagCnt;
mFlagCnt++;
flags[src] = flag;
- //vector<int> mDboundary = neighbors[src];
mDboundary = neighbors[src];
while (!mDboundary.empty()) {
const int bbn = mDboundary.back();
@@ -465,33 +828,17 @@ bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, i
// normal check
const float nvdot = dot(srcn, mPoints[bbn].n); // faster than before d2 calc?
- if(nvdot <= 0.0f) continue; // faster than before d2 calc?
+ if(nvdot <= 0.0f) continue;
// gaussian weight of width 1/sqrt(invsigma2)
const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - srcp);
- if(d2 >= 9.0f) continue; // 25 also possible , slower
- //if(dot(srcn, mPoints[bbn].n) <= 0.0f) continue; // faster than before d2 calc?
-
- //float w = (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2);
- //float w = expf(-0.5f*d2);
-#if 0
- float w=1.0;
- // Downweight things pointing in different directions
- w *= nvdot; //dot(srcn , mPoints[bbn].n);
- // Surface area "belonging" to each point
- w *= pointareas[bbn];
- // Accumulate weight times field at neighbor
- flt += *(field+pointerScale*bbn)*w;
- sum_w += w;
- // */
-#else
- // more aggressive smoothing with: float w=1.0;
- float w=nvdot * pointareas[bbn];
+ if(d2 >= 9.0f) continue;
+
+ // aggressive smoothing factor
+ float smstr = nvdot * pointareas[bbn];
// Accumulate weight times field at neighbor
- flt += *(field+pointerScale*bbn)*w;
- sum_w += w;
-#endif
- // */
+ target += *(field+pointerScale*bbn)*smstr;
+ smstrSum += smstr;
for(int i = 0; i < (int)neighbors[bbn].size(); i++) {
const int nn = neighbors[bbn][i];
@@ -499,17 +846,12 @@ bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, i
mDboundary.push_back(nn);
}
}
- flt /= sum_w;
+ target /= smstrSum;
return 1;
}
-// REF
-// TestData::getTriangles message: Time for surface generation:3.75s, S(0.0390625,0.1171875)
- // ntlWorld::ntlWorld message: Time for start-sims:0s
- // TestData::getTriangles message: Time for surface generation:3.69s, S(0.0390625,0.1171875)
-
-
+// perform smoothing of the surface (and possible normals)
void IsoSurface::smoothSurface(float sigma, bool normSmooth)
{
int nv = mPoints.size();
@@ -670,8 +1012,8 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth)
//errMsg("SMSURF","done v:"<<sigma); // DEBUG
}
-void IsoSurface::smoothNormals(float sigma)
-{
+// only smoothen the normals
+void IsoSurface::smoothNormals(float sigma) {
// reuse from smoothSurface
if(neighbors.size() != mPoints.size()) {
// need neighbor
@@ -781,10 +1123,8 @@ void IsoSurface::smoothNormals(float sigma)
} else { nflt[i]=mPoints[i].n; }
}
- // copy back
+ // copy results
for (int i = 0; i < nv; i++) { mPoints[i].n = nflt[i]; }
-
- //errMsg("SMNRMLS","done v:"<<sigma); // DEBUG
}
diff --git a/intern/elbeem/intern/isosurface.h b/intern/elbeem/intern/isosurface.h
index 5b5198171f3..9902b40199c 100644
--- a/intern/elbeem/intern/isosurface.h
+++ b/intern/elbeem/intern/isosurface.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Marching Cubes "displayer"
*
@@ -18,6 +18,8 @@
/* access some 3d array */
#define ISOLEVEL_INDEX(ii,ij,ik) ((mSizex*mSizey*(ik))+(mSizex*(ij))+((ii)))
+class ParticleTracer;
+
/* struct for a small cube in the scalar field */
typedef struct {
ntlVec3Gfx pos[8];
@@ -53,6 +55,19 @@ class IsoSurface :
/*! triangulate the scalar field given by pointer*/
void triangulate( void );
+ /*! set particle pointer */
+ void setParticles(ParticleTracer *pnt,float psize){ mpIsoParts = pnt; mPartSize=psize; };
+ /*! set # of subdivisions, this has to be done before init! */
+ void setSubdivs(int s) {
+ if(mInitDone) errFatal("IsoSurface::setSubdivs","Changing subdivs after init!", SIMWORLD_INITERROR);
+ if(s<1) s=1; if(s>10) s=10;
+ mSubdivs = s; }
+ int getSubdivs() { return mSubdivs;}
+ /*! set full edge settings, this has to be done before init! */
+ void setUseFulledgeArrays(bool set) {
+ if(mInitDone) errFatal("IsoSurface::setUseFulledgeArrays","Changing usefulledge after init!", SIMWORLD_INITERROR);
+ mUseFullEdgeArrays = set;}
+
protected:
/* variables ... */
@@ -69,10 +84,13 @@ class IsoSurface :
//! Store all the triangles vertices
vector<IsoLevelVertex> mPoints;
+ //! use full arrays? (not for farfield)
+ bool mUseFullEdgeArrays;
//! Store indices of calculated points along the cubie edges
int *mpEdgeVerticesX;
int *mpEdgeVerticesY;
int *mpEdgeVerticesZ;
+ int mEdgeArSize;
//! vector for all the triangles (stored as 3 indices)
@@ -100,6 +118,12 @@ class IsoSurface :
int mCutoff;
//! cutoff heigh values
int *mCutArray;
+ //! particle pointer
+ ParticleTracer *mpIsoParts;
+ //! particle size
+ float mPartSize;
+ //! no of subdivisions
+ int mSubdivs;
//! trimesh vars
vector<int> flags;
@@ -186,6 +210,7 @@ class IsoSurface :
void setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc);
void smoothSurface(float val, bool smoothNorm);
void smoothNormals(float val);
+ void computeNormals();
protected:
diff --git a/intern/elbeem/intern/loop_tools.h b/intern/elbeem/intern/loop_tools.h
index 927263b1204..3c15a609210 100644
--- a/intern/elbeem/intern/loop_tools.h
+++ b/intern/elbeem/intern/loop_tools.h
@@ -30,6 +30,7 @@
#define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz);
#define LIST_EMPTY(x) mListEmpty.push_back( x );
#define LIST_FULL(x) mListFull.push_back( x );
+#define FSGR_ADDPART(x) mpParticles->addFullParticle( x );
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define GRID_REGION_START() \
@@ -90,6 +91,9 @@
int i=0; \
ADVANCE_POINTERS(2*gridLoopBound); \
} /* j */ \
+ /* COMPRESSGRIDS!=1 */ \
+ /* int i=0; */ \
+ /* ADVANCE_POINTERS(mLevel[lev].lSizex*2); */ \
} /* all cell loop k,j,i */ \
if(doReduce) { } /* dummy remove warning */ \
} /* main_region */ \
diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp
index 1bdea59f210..b1fece25890 100644
--- a/intern/elbeem/intern/ntl_blenderdumper.cpp
+++ b/intern/elbeem/intern/ntl_blenderdumper.cpp
@@ -1,13 +1,12 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Replaces std. raytracer, and only dumps time dep. objects to disc
*
*****************************************************************************/
-
#include <fstream>
#include <sys/types.h>
@@ -44,6 +43,10 @@ ntlBlenderDumper::~ntlBlenderDumper()
debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10);
}
+// required globals
+extern bool glob_mpactive;
+extern int glob_mpnum, glob_mpindex;
+
/******************************************************************************
* Only dump time dep. objects to file
*****************************************************************************/
@@ -52,7 +55,8 @@ int ntlBlenderDumper::renderScene( void )
char nrStr[5]; /* nr conversion */
ntlRenderGlobals *glob = mpGlob;
ntlScene *scene = mpGlob->getSimScene();
- bool debugOut = true;
+ bool debugOut = false;
+ bool debugRender = false;
#if ELBEEM_PLUGIN==1
debugOut = false;
#endif // ELBEEM_PLUGIN==1
@@ -63,8 +67,6 @@ int ntlBlenderDumper::renderScene( void )
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Dumping geometry data", 1);
long startTime = getTime();
-
- /* check if picture already exists... */
snprintf(nrStr, 5, "%04d", glob->getAniCount() );
// local scene vars
@@ -72,7 +74,7 @@ int ntlBlenderDumper::renderScene( void )
vector<ntlVec3Gfx> Vertices;
vector<ntlVec3Gfx> VertNormals;
- /* init geometry array, first all standard objects */
+ // check geo objects
int idCnt = 0; // give IDs to objects
for (vector<ntlGeometryClass*>::iterator iter = scene->getGeoClasses()->begin();
iter != scene->getGeoClasses()->end(); iter++) {
@@ -80,8 +82,7 @@ int ntlBlenderDumper::renderScene( void )
int tid = (*iter)->getTypeId();
if(tid & GEOCLASSTID_OBJECT) {
- // normal geom. objects dont change... -> ignore
- //if(buildInfo) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName(), 8 );
+ // normal geom. objects -> ignore
}
if(tid & GEOCLASSTID_SHADER) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
@@ -105,6 +106,11 @@ int ntlBlenderDumper::renderScene( void )
isPreview = true;
}
if(!doDump) continue;
+
+ // dont quit, some objects need notifyOfDump call
+ if((glob_mpactive) && (glob_mpindex>0)) {
+ continue; //return 0;
+ }
// only dump geo shader objects
Triangles.clear();
@@ -112,8 +118,12 @@ int ntlBlenderDumper::renderScene( void )
VertNormals.clear();
(*siter)->initialize( mpGlob );
(*siter)->getTriangles(this->mSimulationTime, &Triangles, &Vertices, &VertNormals, idCnt);
-
idCnt ++;
+
+ // WARNING - this is dirty, but simobjs are the only geoshaders right now
+ SimulationObject *sim = (SimulationObject *)geoshad;
+ LbmSolverInterface *lbm = sim->getSolver();
+
// always dump mesh, even empty ones...
@@ -127,9 +137,6 @@ int ntlBlenderDumper::renderScene( void )
gzFile gzf;
// output velocities if desired
- // WARNING - this is dirty, but simobjs are the only geoshaders right now
- SimulationObject *sim = (SimulationObject *)geoshad;
- LbmSolverInterface *lbm = sim->getSolver();
if((!isPreview) && (lbm->getDumpVelocities())) {
std::ostringstream bvelfilename;
bvelfilename << boutfilename.str();
@@ -155,24 +162,38 @@ int ntlBlenderDumper::renderScene( void )
// compress all bobj's
boutfilename << ".bobj.gz";
- //if(isPreview) { } else { }
gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
if (!gzf) {
errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
return 1; }
-
- //! current transform matrix
+
+ // dont transform velocity output, this is handled in blender
+ // 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];
}
}
+ // rotate vertnormals
+ ntlMatrix4x4<gfxReal> rottrafo;
+ rottrafo.initId();
+ if(lbm->getDomainTrafo()) {
+ // dont modifiy original!
+ rottrafo = *lbm->getDomainTrafo();
+ ntlVec3Gfx rTrans,rScale,rRot,rShear;
+ rottrafo.decompose(rTrans,rScale,rRot,rShear);
+ rottrafo.initRotationXYZ(rRot[0],rRot[1],rRot[2]);
+ // only rotate here...
+ for(size_t i=0; i<Vertices.size(); i++) {
+ VertNormals[i] = rottrafo * VertNormals[i];
+ normalize(VertNormals[i]); // remove scaling etc.
+ }
+ }
+
// write to file
int numVerts;
if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
@@ -215,18 +236,20 @@ int ntlBlenderDumper::renderScene( void )
if(numGMs>0) {
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Objects dumped: "<<numGMs, 10);
} else {
- errFatal("ntlBlenderDumper::renderScene","No objects to dump! Aborting...",SIMWORLD_INITERROR);
- return 1;
+ if((glob_mpactive) && (glob_mpindex>0)) {
+ // ok, nothing to do anyway...
+ } else {
+ errFatal("ntlBlenderDumper::renderScene","No objects to dump! Aborting...",SIMWORLD_INITERROR);
+ return 1;
+ }
}
- /* next frame */
- //glob->setAniCount( glob->getAniCount() +1 );
+ // debug timing
long stopTime = getTime();
debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);
// still render for preview...
-debugOut = false; // DEBUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- if(debugOut) {
+ if(debugRender) {
debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
ntlWorld::renderScene(); }
else {
diff --git a/intern/elbeem/intern/ntl_blenderdumper.h b/intern/elbeem/intern/ntl_blenderdumper.h
index 57f155fc5ff..df66ad7662e 100644
--- a/intern/elbeem/intern/ntl_blenderdumper.h
+++ b/intern/elbeem/intern/ntl_blenderdumper.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Replaces std. raytracer, and only dumps time dep. objects to disc, header
*
diff --git a/intern/elbeem/intern/ntl_bsptree.cpp b/intern/elbeem/intern/ntl_bsptree.cpp
index afa1fa5804c..743ea791d35 100644
--- a/intern/elbeem/intern/ntl_bsptree.cpp
+++ b/intern/elbeem/intern/ntl_bsptree.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Tree container for fast triangle intersects
*
diff --git a/intern/elbeem/intern/ntl_bsptree.h b/intern/elbeem/intern/ntl_bsptree.h
index face7c3aa7f..35bc7c61837 100644
--- a/intern/elbeem/intern/ntl_bsptree.h
+++ b/intern/elbeem/intern/ntl_bsptree.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Tree container for fast triangle intersects
*
diff --git a/intern/elbeem/intern/ntl_geometryclass.h b/intern/elbeem/intern/ntl_geometryclass.h
index 0b7a4e98388..9282371d183 100644
--- a/intern/elbeem/intern/ntl_geometryclass.h
+++ b/intern/elbeem/intern/ntl_geometryclass.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Base class for geometry shaders and objects
*
@@ -31,6 +31,7 @@ class ntlGeometryClass
mObjectId(-1), mpAttrs( NULL ), mGeoInitId(-1)
{
mpAttrs = new AttributeList("objAttrs");
+ mpSwsAttrs = new AttributeList("swsAttrs");
};
//! Default destructor
@@ -58,6 +59,10 @@ class ntlGeometryClass
/*! Returns the attribute list pointer */
inline AttributeList *getAttributeList() { return mpAttrs; }
+ /*! Get/Sets the attribute list pointer */
+ inline void setSwsAttributeList(AttributeList *set) { mpSwsAttrs=set; }
+ inline AttributeList *getSwsAttributeList() { return mpSwsAttrs; }
+
/*! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB */
virtual inline ntlVec3Gfx *getBBStart() { return NULL; }
virtual inline ntlVec3Gfx *getBBEnd() { return NULL; }
@@ -93,6 +98,8 @@ class ntlGeometryClass
/*! configuration attributes */
AttributeList *mpAttrs;
+ /*! sws configuration attributes */
+ AttributeList *mpSwsAttrs;
/* fluid init data */
/*! id of fluid init (is used in solver initialization), additional data stored only for objects */
diff --git a/intern/elbeem/intern/ntl_geometrymodel.cpp b/intern/elbeem/intern/ntl_geometrymodel.cpp
index ba6e638f507..0d769cf6ef8 100644
--- a/intern/elbeem/intern/ntl_geometrymodel.cpp
+++ b/intern/elbeem/intern/ntl_geometrymodel.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* A simple box object
*
diff --git a/intern/elbeem/intern/ntl_geometrymodel.h b/intern/elbeem/intern/ntl_geometrymodel.h
index 95cadc47925..572440f28dc 100644
--- a/intern/elbeem/intern/ntl_geometrymodel.h
+++ b/intern/elbeem/intern/ntl_geometrymodel.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* A model laoded from Wavefront .obj file
*
diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp
index d815fb55287..bc004b656f5 100644
--- a/intern/elbeem/intern/ntl_geometryobject.cpp
+++ b/intern/elbeem/intern/ntl_geometryobject.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* a geometry object
* all other geometry objects are derived from this one
@@ -16,6 +16,8 @@
// for FGI
#include "elbeem.h"
+#define TRI_UVOFFSET (1./4.)
+//#define TRI_UVOFFSET (1./3.)
/*****************************************************************************/
@@ -29,6 +31,7 @@ ntlGeometryObject::ntlGeometryObject() :
mInitialVelocity(0.0), mcInitialVelocity(0.0), mLocalCoordInivel(false),
mGeoInitIntersect(false),
mGeoPartSlipValue(0.0),
+ mcGeoImpactFactor(1.),
mVolumeInit(VOLUMEINIT_VOLUME),
mInitialPos(0.),
mcTrans(0.), mcRot(0.), mcScale(1.),
@@ -62,6 +65,7 @@ bool ntlGeometryObject::checkIsAnimated() {
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)
|| (mcGeoActive.accessValues().size()>1)
+ // mcGeoImpactFactor only needed when moving
|| (mcInitialVelocity.accessValues().size()>1)
) {
mIsAnimated = true;
@@ -71,6 +75,7 @@ bool ntlGeometryObject::checkIsAnimated() {
if(mGeoInitType==FGI_FLUID) {
mIsAnimated=false;
}
+ //errMsg("ntlGeometryObject::checkIsAnimated","obj="<<getName()<<" debug: trans:"<<mcTrans.accessValues().size()<<" rot:"<<mcRot.accessValues().size()<<" scale:"<<mcScale.accessValues().size()<<" active:"<<mcGeoActive.accessValues().size()<<" inivel:"<<mcInitialVelocity.accessValues().size()<<". isani?"<<mIsAnimated ); // DEBUG
return mIsAnimated;
}
@@ -139,6 +144,13 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
mVolumeInit = mpAttrs->readInt("geoinit_volumeinit", mVolumeInit,"ntlGeometryObject", "mVolumeInit", false);
if((mVolumeInit<VOLUMEINIT_VOLUME)||(mVolumeInit>VOLUMEINIT_BOTH)) mVolumeInit = VOLUMEINIT_VOLUME;
+ // moving obs correction factor
+ float impactfactor=1.;
+ impactfactor = (float)mpAttrs->readFloat("impactfactor", impactfactor,"ntlGeometryObject", "impactfactor", false);
+ if(getAttributeList()->exists("impactfactor") || (!mcGeoImpactFactor.isInited()) ) {
+ mcGeoImpactFactor = mpAttrs->readChannelSinglePrecFloat("impactfactor");
+ }
+
// override cfg types
mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false);
mReceiveShadows = mpAttrs->readBool("recv_shad", mReceiveShadows,"ntlGeometryObject", "mReceiveShadows", false);
@@ -162,12 +174,12 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
}
float geoactive=1.;
- geoactive = mpAttrs->readFloat("geoactive", geoactive,"ntlGeometryObject", "geoactive", false);
+ geoactive = (float)mpAttrs->readFloat("geoactive", geoactive,"ntlGeometryObject", "geoactive", false);
if(getAttributeList()->exists("geoactive") || (!mcGeoActive.isInited()) ) {
- mcGeoActive = mpAttrs->readChannelFloat("geoactive");
+ mcGeoActive = mpAttrs->readChannelSinglePrecFloat("geoactive");
}
// always use channel
- if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<double>(geoactive); }
+ if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<float>(geoactive); }
checkIsAnimated();
@@ -309,12 +321,12 @@ void ntlGeometryObject::sceneAddTriangleNoVert(int *trips,
(dst) = AnimChannel< ntlVec3Gfx >(vals,time);
#define ADD_CHANNEL_FLOAT(dst,nvals,val) \
- valsd.clear(); time.clear(); elbeemSimplifyChannelFloat(val,&nvals); \
+ valsfloat.clear(); time.clear(); elbeemSimplifyChannelFloat(val,&nvals); \
for(int i=0; i<(nvals); i++) { \
- valsd.push_back( (val)[i*2+0] ); \
+ valsfloat.push_back( (val)[i*2+0] ); \
time.push_back( (val)[i*2+1] ); \
} \
- (dst) = AnimChannel< double >(valsd,time);
+ (dst) = AnimChannel< float >(valsfloat,time);
void ntlGeometryObject::initChannels(
int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
@@ -324,7 +336,7 @@ void ntlGeometryObject::initChannels(
if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"nt:"<<nTrans<<" nr:"<<nRot<<" ns:"<<nScale, 10);
debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"na:"<<nAct<<" niv:"<<nIvel<<" ", 10); }
vector<ntlVec3Gfx> vals;
- vector<double> valsd;
+ vector<float> valsfloat;
vector<double> time;
if((trans)&&(nTrans>0)) { ADD_CHANNEL_VEC(mcTrans, nTrans, trans); }
if((rot)&&(nRot>0)) { ADD_CHANNEL_VEC(mcRot, nRot, rot); }
@@ -383,7 +395,7 @@ void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts,
ntlMat4Gfx rotMat;
rotMat.initRotationXYZ(rot[0],rot[1],rot[2]);
pos += mInitialPos;
- //errMsg("ntlGeometryObject::applyTransformation","obj="<<getName()<<" t"<<pos<<" r"<<rot<<" s"<<scale);
+ errMsg("ntlGeometryObject::applyTransformation","obj="<<getName()<<" t"<<pos<<" r"<<rot<<" s"<<scale);
for(int i=vstart; i<vend; i++) {
(*verts)[i] *= scale;
(*verts)[i] = rotMat * (*verts)[i];
@@ -397,7 +409,7 @@ 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 ");
}
}
@@ -473,8 +485,8 @@ void ntlGeometryObject::initMovingPoints(double time, gfxReal featureSize) {
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);
+ const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
+ const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
if(uf+vf>1.0) continue;
countp+=2;
}
@@ -500,7 +512,7 @@ void ntlGeometryObject::initMovingPoints(double time, gfxReal featureSize) {
}
mMovPoints.push_back(p);
mMovNormals.push_back(n);
- //errMsg("ntlGeometryObject::initMovingPoints","std"<<i<<" p"<<p<<" n"<<n<<" ");
+ if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","std"<<i<<" p"<<p<<" n"<<n<<" ");
}
// init points & refine...
for(size_t i=0; i<triangles.size(); i++) {
@@ -515,12 +527,12 @@ void ntlGeometryObject::initMovingPoints(double time, gfxReal 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(debugMoinit) 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);
+ const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
+ const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
if(uf+vf>1.0) continue;
ntlVec3Gfx p =
vertices[ trips[0] ] * (1.0-uf-vf)+
@@ -653,8 +665,8 @@ void ntlGeometryObject::initMovingPointsAnim(
//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);
+ const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
+ const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
if(uf+vf>1.0) continue;
ntlVec3Gfx srcp =
srcvertices[ srctrips[0] ] * (1.0-uf-vf)+
@@ -722,7 +734,7 @@ ntlVec3Gfx ntlGeometryObject::calculateMaxVel(double t1, double t2) {
applyTransformation(t2,&verts2,NULL, 0,verts2.size(), true);
vel = (verts2[0]-verts1[0]); // /(t2-t1);
- errMsg("ntlGeometryObject::calculateMaxVel","t1="<<t1<<" t2="<<t2<<" p1="<<verts1[0]<<" p2="<<verts2[0]<<" v="<<vel);
+ //errMsg("ntlGeometryObject::calculateMaxVel","t1="<<t1<<" t2="<<t2<<" p1="<<verts1[0]<<" p2="<<verts2[0]<<" v="<<vel);
return vel;
}
@@ -758,7 +770,6 @@ ntlVec3Gfx ntlGeometryObject::getTranslation(double t) {
}
/*! get active flag time t*/
float ntlGeometryObject::getGeoActive(double t) {
- //float act = mcGeoActive.getConstant(t);
float act = mcGeoActive.get(t); // if <= 0.0 -> off
return act;
}
diff --git a/intern/elbeem/intern/ntl_geometryobject.h b/intern/elbeem/intern/ntl_geometryobject.h
index a9a8109ba1b..a5afd6b2207 100644
--- a/intern/elbeem/intern/ntl_geometryobject.h
+++ b/intern/elbeem/intern/ntl_geometryobject.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* a geometry object
* all other geometry objects are derived from this one
@@ -82,6 +82,10 @@ class ntlGeometryObject : public ntlGeometryClass
inline float getGeoPartSlipValue() const { return mGeoPartSlipValue; }
inline void setGeoPartSlipValue(float set) { mGeoPartSlipValue=set; }
+ /*! Set/get the impact corr factor channel */
+ inline float getGeoImpactFactor(double t) { return mcGeoImpactFactor.get(t); }
+ inline void setGeoImpactFactor(float set) { mcGeoImpactFactor = AnimChannel<float>(set); }
+
/*! Set/get the part slip value*/
inline int getVolumeInit() const { return mVolumeInit; }
inline void setVolumeInit(int set) { mVolumeInit=set; }
@@ -170,6 +174,8 @@ class ntlGeometryObject : public ntlGeometryClass
bool mGeoInitIntersect;
/*! part slip bc value */
float mGeoPartSlipValue;
+ /*! obstacle impact correction factor */
+ AnimChannel<float> mcGeoImpactFactor;
/*! only init as thin object, dont fill? */
int mVolumeInit;
@@ -195,7 +201,7 @@ class ntlGeometryObject : public ntlGeometryClass
int mMaxMovPnt;
/*! animated channels for in/outflow on/off */
- AnimChannel<double> mcGeoActive;
+ AnimChannel<float> mcGeoActive;
public:
diff --git a/intern/elbeem/intern/ntl_geometryshader.h b/intern/elbeem/intern/ntl_geometryshader.h
index aba6b598e09..3ecb82e0556 100644
--- a/intern/elbeem/intern/ntl_geometryshader.h
+++ b/intern/elbeem/intern/ntl_geometryshader.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Interface for a geometry shader
*
diff --git a/intern/elbeem/intern/ntl_lighting.cpp b/intern/elbeem/intern/ntl_lighting.cpp
index d4eae7051e0..cc0e6db5ff9 100644
--- a/intern/elbeem/intern/ntl_lighting.cpp
+++ b/intern/elbeem/intern/ntl_lighting.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* a light object
*
diff --git a/intern/elbeem/intern/ntl_lighting.h b/intern/elbeem/intern/ntl_lighting.h
index af53a13ebc7..772f01ec195 100644
--- a/intern/elbeem/intern/ntl_lighting.h
+++ b/intern/elbeem/intern/ntl_lighting.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* a light object
* default omni light implementation
diff --git a/intern/elbeem/intern/ntl_matrices.h b/intern/elbeem/intern/ntl_matrices.h
index 7d27a6e7c7a..1dd61594857 100644
--- a/intern/elbeem/intern/ntl_matrices.h
+++ b/intern/elbeem/intern/ntl_matrices.h
@@ -2,7 +2,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Basic matrix utility include file
*
@@ -84,6 +84,9 @@ public:
//! from 16 value array (init id if all 0)
inline void initArrayCheck(Scalar *array);
+ //! decompose matrix
+ void decompose(ntlVector3Dim<Scalar> &trans,ntlVector3Dim<Scalar> &scale,ntlVector3Dim<Scalar> &rot,ntlVector3Dim<Scalar> &shear);
+
//! public to avoid [][] operators
Scalar value[4][4]; //< Storage of vector values
@@ -695,6 +698,82 @@ ntlMatrix4x4<Scalar>::initArrayCheck(Scalar *array)
if(allZero) this->initId();
}
+//! decompose matrix
+template<class Scalar>
+void
+ntlMatrix4x4<Scalar>::decompose(ntlVector3Dim<Scalar> &trans,ntlVector3Dim<Scalar> &scale,ntlVector3Dim<Scalar> &rot,ntlVector3Dim<Scalar> &shear) {
+ ntlVec3Gfx row[3],temp;
+
+ for(int i = 0; i < 3; i++) {
+ trans[i] = this->value[3][i];
+ }
+
+ for(int i = 0; i < 3; i++) {
+ row[i][0] = this->value[i][0];
+ row[i][1] = this->value[i][1];
+ row[i][2] = this->value[i][2];
+ }
+
+ scale[0] = norm(row[0]);
+ normalize (row[0]);
+
+ shear[0] = dot(row[0], row[1]);
+ row[1][0] = row[1][0] - shear[0]*row[0][0];
+ row[1][1] = row[1][1] - shear[0]*row[0][1];
+ row[1][2] = row[1][2] - shear[0]*row[0][2];
+
+ scale[1] = norm(row[1]);
+ normalize (row[1]);
+
+ if(scale[1] != 0.0)
+ shear[0] /= scale[1];
+
+ shear[1] = dot(row[0], row[2]);
+ row[2][0] = row[2][0] - shear[1]*row[0][0];
+ row[2][1] = row[2][1] - shear[1]*row[0][1];
+ row[2][2] = row[2][2] - shear[1]*row[0][2];
+
+ shear[2] = dot(row[1], row[2]);
+ row[2][0] = row[2][0] - shear[2]*row[1][0];
+ row[2][1] = row[2][1] - shear[2]*row[1][1];
+ row[2][2] = row[2][2] - shear[2]*row[1][2];
+
+ scale[2] = norm(row[2]);
+ normalize (row[2]);
+
+ if(scale[2] != 0.0) {
+ shear[1] /= scale[2];
+ shear[2] /= scale[2];
+ }
+
+ temp = cross(row[1], row[2]);
+ if(dot(row[0], temp) < 0.0) {
+ for(int i = 0; i < 3; i++) {
+ scale[i] *= -1.0;
+ row[i][0] *= -1.0;
+ row[i][1] *= -1.0;
+ row[i][2] *= -1.0;
+ }
+ }
+
+ if(row[0][2] < -1.0) row[0][2] = -1.0;
+ if(row[0][2] > +1.0) row[0][2] = +1.0;
+
+ rot[1] = asin(-row[0][2]);
+
+ if(fabs(cos(rot[1])) > VECTOR_EPSILON) {
+ rot[0] = atan2 (row[1][2], row[2][2]);
+ rot[2] = atan2 (row[0][1], row[0][0]);
+ }
+ else {
+ rot[0] = atan2 (row[1][0], row[1][1]);
+ rot[2] = 0.0;
+ }
+
+ rot[0] = (180.0/M_PI)*rot[0];
+ rot[1] = (180.0/M_PI)*rot[1];
+ rot[2] = (180.0/M_PI)*rot[2];
+}
#define NTL_MATRICES_H
#endif
diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp
index c838e6f6f84..a25f420fe58 100644
--- a/intern/elbeem/intern/ntl_ray.cpp
+++ b/intern/elbeem/intern/ntl_ray.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* main renderer class
*
diff --git a/intern/elbeem/intern/ntl_ray.h b/intern/elbeem/intern/ntl_ray.h
index 8c0188aee30..226c5f576fa 100644
--- a/intern/elbeem/intern/ntl_ray.h
+++ b/intern/elbeem/intern/ntl_ray.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* ray class
*
diff --git a/intern/elbeem/intern/ntl_vector3dim.h b/intern/elbeem/intern/ntl_vector3dim.h
index ba3ea68f364..d6a7557f69d 100644
--- a/intern/elbeem/intern/ntl_vector3dim.h
+++ b/intern/elbeem/intern/ntl_vector3dim.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Basic vector class used everywhere, either blitz or inlined GRAPA class
*
diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp
index befcbed21ae..835ca7d8876 100644
--- a/intern/elbeem/intern/ntl_world.cpp
+++ b/intern/elbeem/intern/ntl_world.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Main renderer class
*
@@ -421,6 +421,7 @@ int ntlWorld::advanceSims(int framenum)
//gstate = getGlobalBakeState();
//if(gstate<0) { allPanic = true; done = true; } // this means abort... cause panic
//#endif // ELBEEM_BLENDER==1
+ myTime_t advsstart = getTime();
// step all the sims, and check for panic
debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic<<" gstate:"<<gstate, 10); // debug // timedebug
@@ -453,6 +454,9 @@ int ntlWorld::advanceSims(int framenum)
return 1;
}
+ myTime_t advsend = getTime();
+ debMsgStd("ntlWorld::advanceSims",DM_MSG,"Overall steps so far took:"<< getTimeString(advsend-advsstart)<<" for sim time "<<targetTime, 4);
+
// finish step
for(size_t i=0;i<mpSims->size();i++) {
SimulationObject *sim = (*mpSims)[i];
@@ -496,6 +500,8 @@ void ntlWorld::singleStepSims(double targetTime) {
+extern bool glob_mpactive;
+extern int glob_mpindex;
/******************************************************************************
* Render the current scene
@@ -511,11 +517,19 @@ int ntlWorld::renderScene( void )
myTime_t rendStart,rendEnd; // measure user rendering time
glob = mpGlob;
+ // deactivate for all with index!=0
+ if((glob_mpactive)&&(glob_mpindex>0)) return(0);
+
/* check if picture already exists... */
if(!glob->getSingleFrameMode() ) {
snprintf(nrStr, 5, "%04d", glob->getAniCount() );
- //outfilename << glob->getOutFilename() <<"_" << nrStr << ".ppm";
- outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png";
+
+ if(glob_mpactive) {
+ outfn_conv << glob->getOutFilename() <<"_"<<glob_mpindex<<"_" << nrStr << ".png"; /// DEBUG!
+ } else {
+ // ORG
+ outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png";
+ }
//if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) {
if(mpGlob->getFrameSkip()) {
@@ -823,11 +837,7 @@ int ntlWorld::renderScene( void )
}
for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ];
-#ifndef NOPNG
writePng(outfn_conv.str().c_str(), rows, w, h);
-#else // NOPNG
- debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1);
-#endif // NOPNG
}
@@ -838,7 +848,7 @@ int ntlWorld::renderScene( void )
timeEnd = getTime();
char resout[1024];
- snprintf(resout,1024, "NTL Done %s, frame %d/%d (%s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n",
+ snprintf(resout,1024, "NTL Done %s, frame %d/%d (took %s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n",
outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1),
getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(),
glob->getCounterShades(),
diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h
index 18f388a5af4..9c5324cfe8f 100644
--- a/intern/elbeem/intern/ntl_world.h
+++ b/intern/elbeem/intern/ntl_world.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Main renderer class
*
diff --git a/intern/elbeem/intern/parametrizer.cpp b/intern/elbeem/intern/parametrizer.cpp
index b9dc1c36239..ae2bc7f3079 100644
--- a/intern/elbeem/intern/parametrizer.cpp
+++ b/intern/elbeem/intern/parametrizer.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Parameter calculator for the LBM Solver class
*
@@ -57,7 +57,7 @@ Parametrizer::Parametrizer( void ) :
mcAniFrameTime(0.0001),
mTimeStepScale(1.0),
mAniStart(0.0),
- mExtent(1.0, 1.0, 1.0), //mSurfaceTension( 0.0 ),
+ //mExtent(1.0, 1.0, 1.0), //mSurfaceTension( 0.0 ),
mDensity(1000.0), mGStar(0.0001), mFluidVolumeHeight(0.0),
mSimulationMaxSpeed(0.0),
mTadapMaxOmega(2.0), mTadapMaxSpeed(0.1), mTadapLevels(1),
@@ -184,6 +184,7 @@ ParamFloat Parametrizer::calculateCellSize(void)
int maxsize = mSizex; // get max size
if(mSizey>maxsize) maxsize = mSizey;
if(mSizez>maxsize) maxsize = mSizez;
+ maxsize = mSizez; // take along gravity dir for now!
ParamFloat cellSize = 1.0 / (ParamFloat)maxsize;
return cellSize;
}
@@ -252,9 +253,9 @@ int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) {
}
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
-ParamVec Parametrizer::calculateExtent( void ) {
- return mExtent;
-}
+//ParamVec Parametrizer::calculateExtent( void ) {
+ //return mExtent;
+//}
/*! get (scaled) surface tension */
//ParamFloat Parametrizer::calculateSurfaceTension( void ) { return mSurfaceTension; }
@@ -313,6 +314,7 @@ bool Parametrizer::calculateAllMissingValues( double time, bool silent )
int maxsize = mSizex; // get max size
if(mSizey>maxsize) maxsize = mSizey;
if(mSizez>maxsize) maxsize = mSizez;
+ maxsize = mSizez; // take along gravity dir for now!
mCellSize = ( mDomainSize * calculateCellSize() ); // sets mCellSize
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," max domain resolution="<<(maxsize)<<" cells , cellsize="<<mCellSize ,10);
@@ -424,8 +426,8 @@ errMsg("Warning","Used z-dir for gstar!");
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mcGravity.get(time))<<", scaled with "<<forceFactor<<" to "<<calculateGravity(time),1);
}
- mExtent = ParamVec( mCellSize*mSizex, mCellSize*mSizey, mCellSize*mSizez );
- if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m , gs:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<" cs:"<<mCellSize,1);
+ //mExtent = ParamVec( mCellSize*mSizex, mCellSize*mSizey, mCellSize*mSizez );
+ //if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m , gs:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<" cs:"<<mCellSize,1);
if(!checkSeenValues(PARAM_ANIFRAMETIME)) {
errFatal("Parametrizer::calculateAllMissingValues"," Warning no ani frame time given!", SIMWORLD_INITERROR);
diff --git a/intern/elbeem/intern/parametrizer.h b/intern/elbeem/intern/parametrizer.h
index c0df399b7ee..e05db129d77 100644
--- a/intern/elbeem/intern/parametrizer.h
+++ b/intern/elbeem/intern/parametrizer.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Parameter calculator for the LBM Solver class
*
@@ -104,7 +104,7 @@ class Parametrizer {
/*! get start time of animation */
int calculateAniStart( void );
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
- ParamVec calculateExtent( void );
+ //ParamVec calculateExtent( void );
/*! get (scaled) surface tension */
ParamFloat calculateSurfaceTension( void );
/*! get time step size for lbm (equals mTimeFactor) */
@@ -271,7 +271,7 @@ class Parametrizer {
ParamFloat mAniStart;
/*! extent of the domain in meters */
- ParamVec mExtent;
+ //ParamVec mExtent;
/*! fluid density [kg/m^3], default 1.0 g/cm^3 */
ParamFloat mDensity;
diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp
index 1d15cecfd66..c537a893c27 100644
--- a/intern/elbeem/intern/particletracer.cpp
+++ b/intern/elbeem/intern/particletracer.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Particle Viewer/Tracer
*
@@ -128,12 +128,14 @@ void ParticleTracer::adaptPartTimestep(float factor) {
/******************************************************************************
* add a particle at this position
*****************************************************************************/
-void ParticleTracer::addParticle(float x, float y, float z)
-{
+void ParticleTracer::addParticle(float x, float y, float z) {
ntlVec3Gfx p(x,y,z);
ParticleObject part( p );
mParts.push_back( part );
}
+void ParticleTracer::addFullParticle(ParticleObject &np) {
+ mParts.push_back( np );
+}
void ParticleTracer::cleanup() {
@@ -150,6 +152,9 @@ void ParticleTracer::cleanup() {
}
}
+extern bool glob_mpactive;
+extern int glob_mpindex,glob_mpnum;
+
/******************************************************************************
*! dump particles if desired
*****************************************************************************/
@@ -161,8 +166,13 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str
(mDumpParts>0)) {
// dump to binary file
std::ostringstream boutfilename("");
- boutfilename << outfilename <<"_particles_" << frameNrStr<< ".gz";
+ boutfilename << outfilename <<"_particles_" << frameNrStr;
+ if(glob_mpactive) {
+ if(glob_mpindex>0) { boutfilename << "mp"<<glob_mpindex; }
+ }
+ boutfilename << ".gz";
debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" #"<<frameNr , 7);
+ //debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: partgeodeb sim:"<<mSimStart<<","<<mSimEnd<<" geosize:"<<mStart<<","<<mEnd,2 );
// output to zipped file
gzFile gzf;
@@ -211,7 +221,9 @@ void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,str
void ParticleTracer::checkDumpTextPositions(double simtime) {
// dfor partial & full dump
- errMsg("ParticleTracer::checkDumpTextPositions","t="<<simtime<<" last:"<<mDumpTextLastTime<<" inter:"<<mDumpTextInterval);
+ if(mDumpTextInterval>0.) {
+ debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"t="<<simtime<<" last:"<<mDumpTextLastTime<<" inter:"<<mDumpTextInterval,7);
+ }
if((mDumpTextInterval>0.) && (simtime>mDumpTextLastTime+mDumpTextInterval)) {
// dump to binary file
diff --git a/intern/elbeem/intern/particletracer.h b/intern/elbeem/intern/particletracer.h
index f08bd58dc09..aae92aa1dea 100644
--- a/intern/elbeem/intern/particletracer.h
+++ b/intern/elbeem/intern/particletracer.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Particle Viewer/Tracer
*
@@ -37,12 +37,14 @@ class ParticleObject
public:
//! Standard constructor
inline ParticleObject(ntlVec3Gfx mp) :
- mPos(mp),mVel(0.0), mSize(1.0), mStatus(0),mLifeTime(0) { mId = ParticleObjectIdCnt++; };
+ mPos(mp),mVel(0.0), mSize(1.0), mStatus(0),mLifeTime(0),mpNext(NULL)
+ { mId = ParticleObjectIdCnt++; };
//! Copy constructor
inline ParticleObject(const ParticleObject &a) :
mPos(a.mPos), mVel(a.mVel), mSize(a.mSize),
mStatus(a.mStatus),
- mLifeTime(a.mLifeTime) { mId = ParticleObjectIdCnt++; };
+ mLifeTime(a.mLifeTime), mpNext(NULL)
+ { mId = ParticleObjectIdCnt++; };
//! Destructor
inline ~ParticleObject() { /* empty */ };
@@ -70,6 +72,10 @@ class ParticleObject
inline gfxReal getSize() { return mSize; }
inline void setSize(gfxReal set) { mSize=set; }
+ //! get/set next pointer
+ inline ParticleObject* getNext() { return mpNext; }
+ inline void setNext(ParticleObject* set) { mpNext=set; }
+
//! get whole flags
inline int getFlags() const { return mStatus; }
//! get status (higher byte)
@@ -101,6 +107,10 @@ class ParticleObject
inline int getId() const { return mId; }
+ static inline float getMass(float size) {
+ return 4.0/3.0 * M_PI* (size)*(size)*(size); // mass: 4/3 pi r^3 rho
+ }
+
protected:
/*! only for debugging */
@@ -115,6 +125,9 @@ class ParticleObject
int mStatus;
/*! count survived time steps */
float mLifeTime;
+
+ /* for list constructions */
+ ParticleObject *mpNext;
};
@@ -130,6 +143,8 @@ class ParticleTracer :
//! add a particle at this position
void addParticle(float x, float y, float z);
+ //! add/copy a particle from inited struct
+ void addFullParticle(ParticleObject &np);
//! draw the particle array
void draw();
diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp
index 3f954f1a4c7..fcec39810f9 100644
--- a/intern/elbeem/intern/simulation_object.cpp
+++ b/intern/elbeem/intern/simulation_object.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Basic interface for all simulation modules
*
@@ -102,6 +102,7 @@ void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) {
/******************************************************************************
* simluation interface: initialize simulation using the given configuration file
*****************************************************************************/
+extern int glob_mpnum;
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
{
if(! isSimworldOk() ) return 1;
@@ -129,6 +130,8 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
}
debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2);
+ mpParts = new ParticleTracer();
+
// for non-param simulations
mpLbm->setParametrizer( mpParam );
mpParam->setAttrList( getAttributeList() );
@@ -136,8 +139,8 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
mpParam->parseAttrList();
mpLbm->setAttrList( getAttributeList() );
+ mpLbm->setSwsAttrList( getSwsAttributeList() );
mpLbm->parseAttrList();
- mpParts = new ParticleTracer();
mpParts->parseAttrList( getAttributeList() );
if(! isSimworldOk() ) return 3;
@@ -163,6 +166,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath);
mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo );
mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing);
+ mpLbm->setIsoSubdivs(mpElbeemSettings->surfaceSubdivs);
mpLbm->setSizeX(mpElbeemSettings->resolutionxyz);
mpLbm->setSizeY(mpElbeemSettings->resolutionxyz);
mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz);
@@ -173,14 +177,14 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles);
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");
+ if (mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part");
+ else if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free");
+ else /*if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no");
mpLbm->setDomainBound(dinitType);
- mpLbm->setDomainPartSlip(mpElbeemSettings->obstaclePartslip);
+ mpLbm->setDomainPartSlip(mpElbeemSettings->domainobsPartslip);
mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors);
mpLbm->setFarFieldSize(mpElbeemSettings->farFieldSize);
- debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->obstaclePartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 );
+ debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->domainobsPartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 );
debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10);
}
@@ -193,63 +197,68 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
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;
- int totalCells = 0;
- int flagCount[jmax];
- for(int j=0; j<jmax ; j++) flagCount[j] = 0;
- int diffInits = 0;
- LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell();
- for(; mpLbm->noEndCell( cid );
- mpLbm->advanceCell( cid ) ) {
- int flag = mpLbm->getCellFlag(cid,0);
- int flag2 = mpLbm->getCellFlag(cid,1);
- if(flag != flag2) {
- diffInits++;
+ bool printStats = true;
+ if(glob_mpnum>0) printStats=false; // skip in this case
+ if(printStats) {
+ const int jmax = sizeof(CellFlagType)*8;
+ int totalCells = 0;
+ int flagCount[jmax];
+ for(int j=0; j<jmax ; j++) flagCount[j] = 0;
+ int diffInits = 0;
+ LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell();
+ for(; mpLbm->noEndCell( cid );
+ mpLbm->advanceCell( cid ) ) {
+ int flag = mpLbm->getCellFlag(cid,0);
+ int flag2 = mpLbm->getCellFlag(cid,1);
+ if(flag != flag2) {
+ diffInits++;
+ }
+ for(int j=0; j<jmax ; j++) {
+ if( flag&(1<<j) ) flagCount[j]++;
+ }
+ totalCells++;
}
+ mpLbm->deleteCellIterator( &cid );
+
+ char charNl = '\n';
+ debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5);
+ debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5);
for(int j=0; j<jmax ; j++) {
- if( flag&(1<<j) ) flagCount[j]++;
+ std::ostringstream out;
+ if(flagCount[j]>0) {
+ out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl;
+ debugOutNnl(out.str(), 5);
+ }
}
- totalCells++;
- }
- mpLbm->deleteCellIterator( &cid );
-
- char charNl = '\n';
- debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5);
- debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5);
- for(int j=0; j<jmax ; j++) {
- std::ostringstream out;
- if(flagCount[j]>0) {
- out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl;
+ // compute dist. of empty/bnd - fluid - if
+ // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11),
+ if(1){
+ std::ostringstream out;
+ out.precision(2); out.width(4);
+ int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8];
+ double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum;
+ double flFrac = (double)(flagCount[7]) / totNum;
+ double ifFrac = (double)(flagCount[8]) / totNum;
+ //???
+ out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl;
+
+ if(diffInits > 0) {
+ debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5);
+ }
debugOutNnl(out.str(), 5);
}
- }
- // compute dist. of empty/bnd - fluid - if
- // cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11),
- if(1){
- std::ostringstream out;
- out.precision(2); out.width(4);
- int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8];
- double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum;
- double flFrac = (double)(flagCount[7]) / totNum;
- double ifFrac = (double)(flagCount[8]) / totNum;
- //???
- out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl;
-
- if(diffInits > 0) {
- debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5);
- }
- debugOutNnl(out.str(), 5);
- }
+ } // cellstats
// might be modified by mpLbm
- mpParts->setStart( mGeoStart );
- mpParts->setEnd( mGeoEnd );
+ //mpParts->setStart( mGeoStart );? mpParts->setEnd( mGeoEnd );?
+ mpParts->setStart( mpLbm->getGeoStart() );
+ mpParts->setEnd( mpLbm->getGeoEnd() );
mpParts->setCastShadows( false );
mpParts->setReceiveShadows( false );
mpParts->searchMaterial( glob->getMaterials() );
// this has to be inited here - before, the values might be unknown
- ntlGeometryObject *surf = mpLbm->getSurfaceGeoObj();
+ IsoSurface *surf = mpLbm->getSurfaceGeoObj();
if(surf) {
surf->setName( "final" ); // final surface mesh
// warning - this might cause overwriting effects for multiple sims and geom dump...
diff --git a/intern/elbeem/intern/simulation_object.h b/intern/elbeem/intern/simulation_object.h
index 200cad85221..56d7f20e7cd 100644
--- a/intern/elbeem/intern/simulation_object.h
+++ b/intern/elbeem/intern/simulation_object.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Basic interface for all simulation modules
*
diff --git a/intern/elbeem/intern/solver_adap.cpp b/intern/elbeem/intern/solver_adap.cpp
index 99892081fca..ef516a578bd 100644
--- a/intern/elbeem/intern/solver_adap.cpp
+++ b/intern/elbeem/intern/solver_adap.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004,2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Adaptivity functions
*
@@ -925,6 +925,11 @@ void LbmFsgrSolver::interpolateCellFromCoarse(int lev, int i, int j,int k, int d
+// required globals
+extern bool glob_mpactive;
+extern int glob_mpnum, glob_mpindex;
+#define MPTADAP_INTERV 4
+
/*****************************************************************************/
/*! change the size of the LBM time step */
/*****************************************************************************/
@@ -934,7 +939,7 @@ void LbmFsgrSolver::adaptTimestep() {
bool rescale = false; // do any rescale at all?
LbmFloat scaleFac = -1.0; // timestep scaling
- if(this->mPanic) return;
+ if(mPanic) return;
LbmFloat levOldOmega[FSGR_MAXNOOFLEVELS];
LbmFloat levOldStepsize[FSGR_MAXNOOFLEVELS];
@@ -942,62 +947,71 @@ void LbmFsgrSolver::adaptTimestep() {
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);
+ LbmFloat allowMax = mpParam->getTadapMaxSpeed(); // maximum allowed velocity
+ LbmFloat nextmax = mpParam->getSimulationMaxSpeed() + norm(mLevel[mMaxRefine].gravity);
+
+ // sync nextmax
+#if LBM_INCLUDE_TESTSOLVERS==1
+ if(glob_mpactive) {
+ if(mLevel[mMaxRefine].lsteps % MPTADAP_INTERV != MPTADAP_INTERV-1) {
+ debMsgStd("LbmFsgrSolver::TAdp",DM_MSG, "mpact:"<<glob_mpactive<<","<<glob_mpindex<<"/"<<glob_mpnum<<" step:"<<mLevel[mMaxRefine].lsteps<<" skipping tadap...",8);
+ return;
+ }
+ nextmax = mrInitTadap(nextmax);
+ }
+#endif // LBM_INCLUDE_TESTSOLVERS==1
- //newdt = this->mpParam->getTimestep() * (allowMax/nextmax);
- LbmFloat newdt = this->mpParam->getTimestep(); // newtr
+ LbmFloat newdt = 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;
+ newdt = mpParam->getTimestep() * reduceFac;
} else {
if(nextmax<allowMax*reduceFac) {
- newdt = this->mpParam->getTimestep() / reduceFac;
+ newdt = mpParam->getTimestep() / reduceFac;
}
} // newtr
- //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<reduceFac<<" simmaxv="<< this->mpParam->getSimulationMaxSpeed() );
+ //errMsg("LbmFsgrSolver::adaptTimestep","nextmax="<<nextmax<<" allowMax="<<allowMax<<" fac="<<reduceFac<<" simmaxv="<< 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(newdt>mpParam->getMaxTimestep()){ newdt = mpParam->getMaxTimestep(); }
+ if(newdt<mpParam->getMinTimestep()){
+ newdt = mpParam->getMinTimestep();
if(nextmax>allowMax/reduceFac){ minCutoff=true; } // only if really large vels...
}
- LbmFloat dtdiff = fabs(newdt - this->mpParam->getTimestep());
- if(!this->mSilent) {
+ LbmFloat dtdiff = fabs(newdt - mpParam->getTimestep());
+ if(!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); }
+ <<" max"<<mpParam->getMaxTimestep()<<" min"<<mpParam->getMinTimestep()<<" diff"<<dtdiff
+ <<" simt:"<<mSimulationTime<<" minsteps:"<<(mSimulationTime/mMaxTimestep)<<" maxsteps:"<<(mSimulationTime/mMinTimestep)<<
+ " olddt"<<levOldStepsize[mMaxRefine]<<" redlock"<<mTimestepReduceLock
+ , 10); }
// in range, and more than X% change?
- //if( newdt < this->mpParam->getTimestep() ) // DEBUG
+ //if( newdt < mpParam->getTimestep() ) // DEBUG
LbmFloat rhoAvg = mCurrentMass/mCurrentVolume;
- if( (newdt<=this->mpParam->getMaxTimestep()) && (newdt>=this->mpParam->getMinTimestep())
- && (dtdiff>(this->mpParam->getTimestep()*diffPercent)) ) {
+ if( (newdt<=mpParam->getMaxTimestep()) && (newdt>=mpParam->getMinTimestep())
+ && (dtdiff>(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 );
+ mpParam->setDesiredTimestep( newdt );
rescale = true;
- if(!this->mSilent) {
+ if(!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);
+ debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep changing: new="<<newdt<<" old="<<mpParam->getTimestep()
+ <<" maxSpeed:"<<mpParam->getSimulationMaxSpeed()<<" next:"<<nextmax<<" step:"<<mStepCnt, 10 );
+ //debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Timestep changing: "<< "rhoAvg="<<rhoAvg<<" cMass="<<mCurrentMass<<" cVol="<<mCurrentVolume,10);
}
} // really change dt
}
@@ -1009,17 +1023,17 @@ void LbmFsgrSolver::adaptTimestep() {
/*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) ){
+ if( ((mStepCnt% tadtogInter)== (tadtogInter/4*1)-1) ||
+ ((mStepCnt% tadtogInter)== (tadtogInter/4*2)-1) ){
rescale = true; minCutoff = false;
- newdt = tadtogSwitch * this->mpParam->getTimestep();
- this->mpParam->setDesiredTimestep( newdt );
+ newdt = tadtogSwitch * mpParam->getTimestep();
+ mpParam->setDesiredTimestep( newdt );
} else
- if( ((this->mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) ||
- ((this->mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){
+ if( ((mStepCnt% tadtogInter)== (tadtogInter/4*3)-1) ||
+ ((mStepCnt% tadtogInter)== (tadtogInter/4*4)-1) ){
rescale = true; minCutoff = false;
- newdt = this->mpParam->getTimestep()/tadtogSwitch ;
- this->mpParam->setDesiredTimestep( newdt );
+ newdt = mpParam->getTimestep()/tadtogSwitch ;
+ mpParam->setDesiredTimestep( newdt );
} else {
rescale = false; minCutoff = false;
}
@@ -1027,23 +1041,25 @@ void LbmFsgrSolver::adaptTimestep() {
// test mass rescale
- scaleFac = newdt/this->mpParam->getTimestep();
+ scaleFac = newdt/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;
+ //mTimestepReduceLock = 4*(mLevel[mMaxRefine].lSizey+mLevel[mMaxRefine].lSizez+mLevel[mMaxRefine].lSizex)/3;
+ // use z as gravity direction
+ mTimestepReduceLock = 4*mLevel[mMaxRefine].lSizez;
mTimeSwitchCounts++;
- this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent );
+ mpParam->calculateAllMissingValues( mSimulationTime, 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();
+ if(mpParam->getTimestep()<mMinTimestep) mMinTimestep = mpParam->getTimestep();
+ if(mpParam->getTimestep()>mMaxTimestep) mMaxTimestep = mpParam->getTimestep();
// this might be called during init, before we have any particles
if(mpParticles) { mpParticles->adaptPartTimestep(scaleFac); }
@@ -1058,8 +1074,8 @@ void LbmFsgrSolver::adaptTimestep() {
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: "<<
+ if(!mSilent) {
+ debMsgStd("LbmFsgrSolver::TAdp",DM_NOTIFY,"Level: "<<lev<<" Timestep chlevel: "<<
" scaleFac="<<dfScaleFac<<" newDt="<<newSteptime<<" newOmega="<<mLevel[lev].omega,10);
}
if(lev!=mMaxRefine) coarseCalculateFluxareas(lev);
@@ -1079,7 +1095,7 @@ void LbmFsgrSolver::adaptTimestep() {
// 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++) {
+ for(int l=0; l<cDfNum; l++) {
QCELL(lev, i, j, k, workSet, l) = QCELL(lev, i, j, k, workSet, l)* scaleFac;
}
//} // ok
@@ -1102,12 +1118,12 @@ void LbmFsgrSolver::adaptTimestep() {
LbmVec velOld;
LbmFloat rho, ux,uy,uz;
rho=0.0; ux = uy = uz = 0.0;
- for(int l=0; l<this->cDfNum; l++) {
+ for(int l=0; l<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);
+ ux += (dfDvecX[l]*m);
+ uy += (dfDvecY[l]*m);
+ uz += (dfDvecZ[l]*m);
}
rhoOld = rho;
velOld = LbmVec(ux,uy,uz);
@@ -1118,21 +1134,21 @@ void LbmFsgrSolver::adaptTimestep() {
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] );
+ for(int l=0; l<cDfNum; l++) {
+ feqOld[l] = getCollideEq(l,rhoOld, velOld[0],velOld[1],velOld[2] );
+ feqNew[l] = 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);
+ const LbmFloat Qo = getLesNoneqTensorCoeff(df,feqOld);
+ const LbmFloat oldOmega = getLesOmega(levOldOmega[lev], mLevel[lev].lcsmago,Qo);
+ const LbmFloat newOmega = 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++) {
+ for(int l=0; l<cDfNum; l++) {
// org scaling
//df = eqOld + (df-eqOld)*dfScale; df *= (eqNew/eqOld); // non-eq. scaling, important
// new scaling
@@ -1176,22 +1192,22 @@ void LbmFsgrSolver::adaptTimestep() {
} // lev
- if(!this->mSilent) {
- debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<this->mStepCnt<<
+ if(!mSilent) {
+ debMsgStd("LbmFsgrSolver::step",DM_MSG,"REINIT DONE "<<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);
+ debMsgStd("\nLbmOptSolver::step",DM_MSG,"Timestep changed by "<< (newdt/levOldStepsize[mMaxRefine]) <<" newDt:"<<newdt
+ <<", oldDt:"<<levOldStepsize[mMaxRefine]<<" newOmega:"<<mOmega<<" gStar:"<<mpParam->getCurrentGStar()<<", step:"<<mStepCnt , 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()<<") " );
+ errMsg("adaptTimestep","Warning - performing Brute-Force rescale... (sim:"<<mName<<" step:"<<mStepCnt<<" newdt="<<desireddt<<" mindt="<<mpParam->getMinTimestep()<<") " );
//brute force resacle all the time?
for(int lev=mMaxRefine; lev>=0 ; lev--) {
@@ -1220,12 +1236,12 @@ void LbmFsgrSolver::adaptTimestep() {
// 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++) {
+ for(int l=0; l<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);
+ ux += (dfDvecX[l]*m);
+ uy += (dfDvecY[l]*m);
+ uz += (dfDvecZ[l]*m);
}
#ifndef WIN32
if (!finite(rho)) {
@@ -1242,8 +1258,8 @@ void LbmFsgrSolver::adaptTimestep() {
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); }
+ for(int l=0; l<cDfNum; l++) {
+ QCELL(lev, i, j, k, workSet, l) = getCollideEq(l, rho, ux,uy,uz); }
rescs++;
debMsgDirect("B");
}
diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h
index 578e1079cd7..e6b1ad4ed53 100644
--- a/intern/elbeem/intern/solver_class.h
+++ b/intern/elbeem/intern/solver_class.h
@@ -3,7 +3,7 @@
* El'Beem - the visual lattice boltzmann freesurface simulator
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Combined 2D/3D Lattice Boltzmann standard solver classes
*
@@ -259,13 +259,17 @@ class LbmFsgrSolver :
LBM_INLINED void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel);
LBM_INLINED void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag);
LBM_INLINED void forceChangeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag);
+ LBM_INLINED void initInterfaceVars(int level, int i,int j,int k,int workSet, bool initMass);
//! interpolate velocity and density at a given position
void interpolateCellValues(int level,int ei,int ej,int ek,int workSet, LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz);
/*! perform a single LBM step */
void stepMain();
+ //! advance fine grid
void fineAdvance();
+ //! advance coarse grid
void coarseAdvance(int lev);
+ //! update flux area values on coarse grids
void coarseCalculateFluxareas(int lev);
// adaptively coarsen grid
bool adaptGrid(int lev);
@@ -278,6 +282,11 @@ class LbmFsgrSolver :
virtual int initParticles();
/*! move all particles */
virtual void advanceParticles();
+ /*! move a particle at a boundary */
+ void handleObstacleParticle(ParticleObject *p);
+ /*! check whether to add particle
+ bool checkAddParticle();
+ void performAddParticle();*/
/*! debug object display (used e.g. for preview surface) */
@@ -294,9 +303,6 @@ class LbmFsgrSolver :
//! for raytracing, preprocess
void prepareVisualization( void );
- /*! type for cells */
- //typedef typename this->LbmCell LbmCell;
-
protected:
//! internal quick print function (for debugging)
@@ -316,6 +322,11 @@ class LbmFsgrSolver :
void reinitFlags( int workSet );
//! mass dist weights
LbmFloat getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l);
+ //! compute surface normals: fluid, fluid more accurate, and for obstacles
+ void computeFluidSurfaceNormal(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
+ void computeFluidSurfaceNormalAcc(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
+ void computeObstacleSurfaceNormal(LbmFloat *cell, CellFlagType *cellflag, LbmFloat *snret);
+ void computeObstacleSurfaceNormalAcc(int i,int j,int k, LbmFloat *snret);
//! add point to mListNewInter list
LBM_INLINED void addToNewInterList( int ni, int nj, int nk );
//! cell is interpolated from coarse level (inited into set, source sets are determined by t)
@@ -327,6 +338,8 @@ class LbmFsgrSolver :
LBM_INLINED int getForZMin1();
LBM_INLINED int getForZMaxBnd(int lev);
LBM_INLINED int getForZMax1(int lev);
+ LBM_INLINED bool checkDomainBounds(int lev,int i,int j,int k);
+ LBM_INLINED bool checkDomainBoundsPos(int lev,LbmVec pos);
// touch grid and flags once
void preinitGrids();
@@ -361,8 +374,6 @@ class LbmFsgrSolver :
LbmFloat mFVArea;
bool mUpdateFVHeight;
- //! require some geo setup from the viz?
- //int mGfxGeoSetup;
//! force quit for gfx
LbmFloat mGfxEndTime;
//! smoother surface initialization?
@@ -500,10 +511,21 @@ class LbmFsgrSolver :
void handleCpdata();
void cpDebugDisplay(int dispset);
- void testXchng();
+ int mMpNum,mMpIndex;
+ int mOrgSizeX;
+ LbmFloat mOrgStartX;
+ LbmFloat mOrgEndX;
+ void mrSetup();
+ void mrExchange();
+ void mrIsoExchange();
+ LbmFloat mrInitTadap(LbmFloat max);
+ void gcFillBuffer( LbmGridConnector *gc, int *retSizeCnt, const int *bdfs);
+ void gcUnpackBuffer(LbmGridConnector *gc, int *retSizeCnt, const int *bdfs);
public:
// needed for testdata
void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat *retux, LbmFloat *retuy, LbmFloat *retuz);
+ // mptest
+ int getMpIndex() { return mMpIndex; };
# endif // LBM_INCLUDE_TESTSOLVERS==1
// former LbmModelLBGK functions
@@ -615,7 +637,7 @@ class LbmFsgrSolver :
STCON LbmFloat dfLength[ 19 ];
/*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
- static LbmFloat dfEquil[ 19 ];
+ static LbmFloat dfEquil[ dTotalNum ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ];
@@ -701,7 +723,7 @@ class LbmFsgrSolver :
STCON LbmFloat dfLength[ 9 ];
/* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
- static LbmFloat dfEquil[ 9 ];
+ static LbmFloat dfEquil[ dTotalNum ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ];
@@ -784,7 +806,8 @@ class LbmFsgrSolver :
// general defines -----------------------------------------------------------------------------------------------
-#define TESTFLAG(flag, compflag) ((flag & compflag)==compflag)
+// replace TESTFLAG
+#define FLAGISEXACT(flag, compflag) ((flag & compflag)==compflag)
#if LBMDIM==2
#define dC 0
@@ -943,6 +966,41 @@ int LbmFsgrSolver::getForZMax1(int lev) {
return mLevel[lev].lSizez -1;
}
+bool LbmFsgrSolver::checkDomainBounds(int lev,int i,int j,int k) {
+ if(i<0) return false;
+ if(j<0) return false;
+ if(k<0) return false;
+ if(i>mLevel[lev].lSizex-1) return false;
+ if(j>mLevel[lev].lSizey-1) return false;
+ if(k>mLevel[lev].lSizez-1) return false;
+ return true;
+}
+bool LbmFsgrSolver::checkDomainBoundsPos(int lev,LbmVec pos) {
+ const int i= (int)pos[0];
+ if(i<0) return false;
+ if(i>mLevel[lev].lSizex-1) return false;
+ const int j= (int)pos[1];
+ if(j<0) return false;
+ if(j>mLevel[lev].lSizey-1) return false;
+ const int k= (int)pos[2];
+ if(k<0) return false;
+ if(k>mLevel[lev].lSizez-1) return false;
+ return true;
+}
+
+void LbmFsgrSolver::initInterfaceVars(int level, int i,int j,int k,int workSet, bool initMass) {
+ LbmFloat *ccel = &QCELL(level ,i,j,k, workSet,0);
+ LbmFloat nrho = 0.0;
+ FORDF0 { nrho += RAC(ccel,l); }
+ if(initMass) {
+ RAC(ccel,dMass) = nrho;
+ RAC(ccel, dFfrac) = 1.;
+ } else {
+ // preinited, e.g. from reinitFlags
+ RAC(ccel, dFfrac) = RAC(ccel, dMass)/nrho;
+ RAC(ccel, dFlux) = FLUX_INIT;
+ }
+}
#endif
diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp
index 1a19e1deabf..6f891310224 100644
--- a/intern/elbeem/intern/solver_init.cpp
+++ b/intern/elbeem/intern/solver_init.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004,2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Standard LBM Factory implementation
*
@@ -13,9 +13,6 @@
// 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 )
-
// helper for 2d init
#define SWAPYZ(vec) { \
const LbmFloat tmp = (vec)[2]; \
@@ -173,7 +170,7 @@
};
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
- LbmFloat LbmFsgrSolver::dfEquil[ cDfNum ];
+ LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ];
#else // end LBMDIM==3 , LBMDIM==2
@@ -290,12 +287,17 @@
};
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
- LbmFloat LbmFsgrSolver::dfEquil[ cDfNum ];
+ LbmFloat LbmFsgrSolver::dfEquil[ dTotalNum ];
// D2Q9 end
#endif // LBMDIM==2
+// required globals
+extern bool glob_mpactive;
+extern int glob_mpnum, glob_mpindex;
+
+
/******************************************************************************
* Lbm Constructor
*****************************************************************************/
@@ -318,7 +320,7 @@ LbmFsgrSolver::LbmFsgrSolver() :
mIsoWeightMethod(1),
mMaxRefine(1),
mDfScaleUp(-1.0), mDfScaleDown(-1.0),
- mInitialCsmago(0.03), // set to 0.02 for mMaxRefine==0 below
+ mInitialCsmago(0.02), // set to 0.02 for mMaxRefine==0 below and default for fine level, coarser ones are 0.03
mDebugOmegaRet(0.0),
mLastOmega(1e10), mLastGravity(1e10),
mNumInvIfTotal(0), mNumFsgrChanges(0),
@@ -329,38 +331,45 @@ LbmFsgrSolver::LbmFsgrSolver() :
// not much to do here...
#if LBM_INCLUDE_TESTSOLVERS==1
mpTest = new LbmTestdata();
-#endif // ELBEEM_PLUGIN!=1
- this->mpIso = new IsoSurface( this->mIsoValue );
+ mMpNum = mMpIndex = 0;
+ mOrgSizeX = 0;
+ mOrgStartX = 0.;
+ mOrgEndX = 0.;
+#endif // LBM_INCLUDE_TESTSOLVERS!=1
+ mpIso = new IsoSurface( mIsoValue );
// init equilibrium dist. func
LbmFloat rho=1.0;
FORDF0 {
- this->dfEquil[l] = this->getCollideEq( l,rho, 0.0, 0.0, 0.0);
+ dfEquil[l] = this->getCollideEq( l,rho, 0.0, 0.0, 0.0);
}
+ dfEquil[dMass] = 1.;
+ dfEquil[dFfrac] = 1.;
+ dfEquil[dFlux] = FLUX_INIT;
// init LES
int odm = 0;
for(int m=0; m<LBMDIM; m++) {
- for(int l=0; l<this->cDfNum; l++) {
+ for(int l=0; l<cDfNum; l++) {
this->lesCoeffDiag[m][l] =
this->lesCoeffOffdiag[m][l] = 0.0;
}
}
for(int m=0; m<LBMDIM; m++) {
for(int n=0; n<LBMDIM; n++) {
- for(int l=1; l<this->cDfNum; l++) {
+ for(int l=1; l<cDfNum; l++) {
LbmFloat em;
switch(m) {
- case 0: em = this->dfDvecX[l]; break;
- case 1: em = this->dfDvecY[l]; break;
- case 2: em = this->dfDvecZ[l]; break;
+ case 0: em = dfDvecX[l]; break;
+ case 1: em = dfDvecY[l]; break;
+ case 2: em = dfDvecZ[l]; break;
default: em = -1.0; errFatal("SMAGO1","err m="<<m, SIMWORLD_GENERICERROR);
}
LbmFloat en;
switch(n) {
- case 0: en = this->dfDvecX[l]; break;
- case 1: en = this->dfDvecY[l]; break;
- case 2: en = this->dfDvecZ[l]; break;
+ case 0: en = dfDvecX[l]; break;
+ case 1: en = dfDvecY[l]; break;
+ case 2: en = dfDvecZ[l]; break;
default: en = -1.0; errFatal("SMAGO2","err n="<<n, SIMWORLD_GENERICERROR);
}
const LbmFloat coeff = em*en;
@@ -383,7 +392,7 @@ LbmFsgrSolver::LbmFsgrSolver() :
mDvecNrm[0] = LbmVec(0.0);
FORDF1 {
mDvecNrm[l] = getNormalized(
- LbmVec(this->dfDvecX[this->dfInv[l]], this->dfDvecY[this->dfInv[l]], this->dfDvecZ[this->dfInv[l]] )
+ LbmVec(dfDvecX[dfInv[l]], dfDvecY[dfInv[l]], dfDvecZ[dfInv[l]] )
) * -1.0;
}
@@ -395,15 +404,15 @@ LbmFsgrSolver::LbmFsgrSolver() :
#if ELBEEM_PLUGIN!=1
errMsg("coarseRestrictFromFine", "TCRFF_DFDEBUG2 test df/dir num!");
#endif
- for(int n=0;(n<this->cDirNum); n++) { mGaussw[n] = 0.0; }
- //for(int n=0;(n<this->cDirNum); n++) {
- for(int n=0;(n<this->cDfNum); n++) {
- const LbmFloat d = norm(LbmVec(this->dfVecX[n], this->dfVecY[n], this->dfVecZ[n]));
+ for(int n=0;(n<cDirNum); n++) { mGaussw[n] = 0.0; }
+ //for(int n=0;(n<cDirNum); n++) {
+ for(int n=0;(n<cDfNum); n++) {
+ const LbmFloat d = norm(LbmVec(dfVecX[n], dfVecY[n], dfVecZ[n]));
LbmFloat w = expf( -alpha*d*d ) - expf( -alpha*gw*gw );
mGaussw[n] = w;
totGaussw += w;
}
- for(int n=0;(n<this->cDirNum); n++) {
+ for(int n=0;(n<cDirNum); n++) {
mGaussw[n] = mGaussw[n]/totGaussw;
}
@@ -414,7 +423,7 @@ LbmFsgrSolver::LbmFsgrSolver() :
/*****************************************************************************/
LbmFsgrSolver::~LbmFsgrSolver()
{
- if(!this->mInitDone){ debugOut("LbmFsgrSolver::LbmFsgrSolver : not inited...",0); return; }
+ if(!mInitDone){ debMsgStd("LbmFsgrSolver::LbmFsgrSolver",DM_MSG,"not inited...",0); return; }
#if COMPRESSGRIDS==1
delete [] mLevel[mMaxRefine].mprsCells[1];
mLevel[mMaxRefine].mprsCells[0] = mLevel[mMaxRefine].mprsCells[1] = NULL;
@@ -426,16 +435,13 @@ LbmFsgrSolver::~LbmFsgrSolver()
if(mLevel[i].mprsFlags[s]) delete [] mLevel[i].mprsFlags[s];
}
}
- delete this->mpIso;
+ delete mpIso;
if(mpPreviewSurface) delete mpPreviewSurface;
-
-#if LBM_INCLUDE_TESTSOLVERS==1
// cleanup done during scene deletion...
-#endif // ELBEEM_PLUGIN!=1
// always output performance estimate
debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG," Avg. MLSUPS:"<<(mAvgMLSUPS/mAvgMLSUPSCnt), 5);
- if(!this->mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10);
+ if(!mSilent) debMsgStd("LbmFsgrSolver::~LbmFsgrSolver",DM_MSG,"Deleted...",10);
}
@@ -449,19 +455,19 @@ void LbmFsgrSolver::parseAttrList()
LbmSolverInterface::parseStdAttrList();
string matIso("default");
- matIso = this->mpAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false );
- this->mpIso->setMaterialName( matIso );
- this->mOutputSurfacePreview = this->mpAttrs->readInt("surfacepreview", this->mOutputSurfacePreview, "SimulationLbm","this->mOutputSurfacePreview", false );
- mTimeAdap = this->mpAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false );
- this->mDomainBound = this->mpAttrs->readString("domainbound", this->mDomainBound, "SimulationLbm","mDomainBound", false );
- this->mDomainPartSlipValue = this->mpAttrs->readFloat("domainpartslip", this->mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false );
-
- mIsoWeightMethod= this->mpAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false );
- mInitSurfaceSmoothing = this->mpAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false );
- this->mSmoothSurface = this->mpAttrs->readFloat("smoothsurface", this->mSmoothSurface, "SimulationLbm","mSmoothSurface", false );
- this->mSmoothNormals = this->mpAttrs->readFloat("smoothnormals", this->mSmoothNormals, "SimulationLbm","mSmoothNormals", false );
-
- mFsSurfGenSetting = this->mpAttrs->readInt("fssurfgen", mFsSurfGenSetting, "SimulationLbm","mFsSurfGenSetting", false );
+ matIso = mpSifAttrs->readString("material_surf", matIso, "SimulationLbm","mpIso->material", false );
+ mpIso->setMaterialName( matIso );
+ mOutputSurfacePreview = mpSifAttrs->readInt("surfacepreview", mOutputSurfacePreview, "SimulationLbm","mOutputSurfacePreview", false );
+ mTimeAdap = mpSifAttrs->readBool("timeadap", mTimeAdap, "SimulationLbm","mTimeAdap", false );
+ mDomainBound = mpSifAttrs->readString("domainbound", mDomainBound, "SimulationLbm","mDomainBound", false );
+ mDomainPartSlipValue = mpSifAttrs->readFloat("domainpartslip", mDomainPartSlipValue, "SimulationLbm","mDomainPartSlipValue", false );
+
+ mIsoWeightMethod= mpSifAttrs->readInt("isoweightmethod", mIsoWeightMethod, "SimulationLbm","mIsoWeightMethod", false );
+ mInitSurfaceSmoothing = mpSifAttrs->readInt("initsurfsmooth", mInitSurfaceSmoothing, "SimulationLbm","mInitSurfaceSmoothing", false );
+ mSmoothSurface = mpSifAttrs->readFloat("smoothsurface", mSmoothSurface, "SimulationLbm","mSmoothSurface", false );
+ mSmoothNormals = mpSifAttrs->readFloat("smoothnormals", mSmoothNormals, "SimulationLbm","mSmoothNormals", false );
+
+ mFsSurfGenSetting = mpSifAttrs->readInt("fssurfgen", mFsSurfGenSetting, "SimulationLbm","mFsSurfGenSetting", false );
if(mFsSurfGenSetting==-1) {
// all on
mFsSurfGenSetting =
@@ -470,46 +476,61 @@ void LbmFsgrSolver::parseAttrList()
}
// refinement
- mMaxRefine = this->mRefinementDesired;
- mMaxRefine = this->mpAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false);
+ mMaxRefine = mRefinementDesired;
+ mMaxRefine = mpSifAttrs->readInt("maxrefine", mMaxRefine ,"LbmFsgrSolver", "mMaxRefine", false);
if(mMaxRefine<0) mMaxRefine=0;
if(mMaxRefine>FSGR_MAXNOOFLEVELS) mMaxRefine=FSGR_MAXNOOFLEVELS-1;
- mDisableStandingFluidInit = this->mpAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false);
- mInit2dYZ = this->mpAttrs->readBool("init2dyz", mInit2dYZ,"LbmFsgrSolver", "mInit2dYZ", false);
- mForceTadapRefine = this->mpAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false);
+ mDisableStandingFluidInit = mpSifAttrs->readInt("disable_stfluidinit", mDisableStandingFluidInit,"LbmFsgrSolver", "mDisableStandingFluidInit", false);
+ mInit2dYZ = mpSifAttrs->readBool("init2dyz", mInit2dYZ,"LbmFsgrSolver", "mInit2dYZ", false);
+ mForceTadapRefine = mpSifAttrs->readInt("forcetadaprefine", mForceTadapRefine,"LbmFsgrSolver", "mForceTadapRefine", false);
// demo mode settings
- mFVHeight = this->mpAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false );
+ mFVHeight = mpSifAttrs->readFloat("fvolheight", mFVHeight, "LbmFsgrSolver","mFVHeight", false );
// FIXME check needed?
- mFVArea = this->mpAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false );
+ mFVArea = mpSifAttrs->readFloat("fvolarea", mFVArea, "LbmFsgrSolver","mFArea", false );
// debugging - skip some time...
double starttimeskip = 0.;
- starttimeskip = this->mpAttrs->readFloat("forcestarttimeskip", starttimeskip, "LbmFsgrSolver","starttimeskip", false );
+ starttimeskip = mpSifAttrs->readFloat("forcestarttimeskip", starttimeskip, "LbmFsgrSolver","starttimeskip", false );
mSimulationTime += starttimeskip;
if(starttimeskip>0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<<starttimeskip<<", t="<<mSimulationTime, 1);
#if LBM_INCLUDE_TESTSOLVERS==1
mUseTestdata = 0;
- mUseTestdata = this->mpAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false);
- mpTest->parseTestdataAttrList(this->mpAttrs);
+ mUseTestdata = mpSifAttrs->readBool("use_testdata", mUseTestdata,"LbmFsgrSolver", "mUseTestdata", false);
+ mpTest->parseTestdataAttrList(mpSifAttrs);
#ifdef ELBEEM_PLUGIN
mUseTestdata=1; // DEBUG
#endif // ELBEEM_PLUGIN
- errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" ");
+ mMpNum = mpSifAttrs->readInt("mpnum", mMpNum ,"LbmFsgrSolver", "mMpNum", false);
+ mMpIndex = mpSifAttrs->readInt("mpindex", mMpIndex ,"LbmFsgrSolver", "mMpIndex", false);
+ if(glob_mpactive) {
+ // used instead...
+ mMpNum = glob_mpnum;
+ mMpIndex = glob_mpindex;
+ } else {
+ glob_mpnum = mMpNum;
+ glob_mpindex = 0;
+ }
+ errMsg("LbmFsgrSolver::parseAttrList"," mpactive:"<<glob_mpactive<<", "<<glob_mpindex<<"/"<<glob_mpnum);
+ if(mMpNum>0) {
+ mUseTestdata=1; // needed in this case...
+ }
+
+ errMsg("LbmFsgrSolver::LBM_INCLUDE_TESTSOLVERS","Active, mUseTestdata:"<<mUseTestdata<<" ");
#else // LBM_INCLUDE_TESTSOLVERS!=1
- // off by default
+ // not testsolvers, off by default
mUseTestdata = 0;
if(mFarFieldSize>=2.) mUseTestdata=1; // equiv. to test solver check
#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 );
+ mInitialCsmago = mpSifAttrs->readFloat("csmago", mInitialCsmago, "SimulationLbm","mInitialCsmago", false );
// deprecated!
float mInitialCsmagoCoarse = 0.0;
- mInitialCsmagoCoarse = this->mpAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false );
+ mInitialCsmagoCoarse = mpSifAttrs->readFloat("csmago_coarse", mInitialCsmagoCoarse, "SimulationLbm","mInitialCsmagoCoarse", false );
#if USE_LES==1
#else // USE_LES==1
debMsgStd("LbmFsgrSolver", DM_WARNING, "LES model switched off!",2);
@@ -524,15 +545,15 @@ void LbmFsgrSolver::parseAttrList()
void LbmFsgrSolver::initLevelOmegas()
{
// no explicit settings
- this->mOmega = this->mpParam->calculateOmega(mSimulationTime);
- this->mGravity = vec2L( this->mpParam->calculateGravity(mSimulationTime) );
- this->mSurfaceTension = 0.; //this->mpParam->calculateSurfaceTension(); // unused
+ mOmega = mpParam->calculateOmega(mSimulationTime);
+ mGravity = vec2L( mpParam->calculateGravity(mSimulationTime) );
+ mSurfaceTension = 0.; //mpParam->calculateSurfaceTension(); // unused
if(mInit2dYZ) { SWAPYZ(mGravity); }
// check if last init was ok
- LbmFloat gravDelta = norm(this->mGravity-mLastGravity);
- //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<this->mOmega<<" - lom:"<<mLastOmega<<" gv:"<<this->mGravity<<" - "<<mLastGravity<<" , "<<gravDelta );
- if((this->mOmega == mLastOmega) && (gravDelta<=0.0)) return;
+ LbmFloat gravDelta = norm(mGravity-mLastGravity);
+ //errMsg("ChannelAnimDebug","t:"<<mSimulationTime<<" om:"<<mOmega<<" - lom:"<<mLastOmega<<" gv:"<<mGravity<<" - "<<mLastGravity<<" , "<<gravDelta );
+ if((mOmega == mLastOmega) && (gravDelta<=0.0)) return;
if(mInitialCsmago<=0.0) {
if(OPT3D==1) {
@@ -544,47 +565,49 @@ void LbmFsgrSolver::initLevelOmegas()
// use Tau instead of Omega for calculations
{ // init base level
int i = mMaxRefine;
- mLevel[i].omega = this->mOmega;
- mLevel[i].timestep = this->mpParam->getTimestep();
+ mLevel[i].omega = mOmega;
+ mLevel[i].timestep = mpParam->getTimestep();
mLevel[i].lcsmago = mInitialCsmago; //CSMAGO_INITIAL;
mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
}
// init all sub levels
+ LbmFloat coarseCsmago = mInitialCsmago;
+ coarseCsmago = 0.04; // try stabilizing
for(int i=mMaxRefine-1; i>=0; i--) {
//mLevel[i].omega = 2.0 * (mLevel[i+1].omega-0.5) + 0.5;
double nomega = 0.5 * ( (1.0/(double)mLevel[i+1].omega) -0.5) + 0.5;
nomega = 1.0/nomega;
mLevel[i].omega = (LbmFloat)nomega;
mLevel[i].timestep = 2.0 * mLevel[i+1].timestep;
- mLevel[i].lcsmago = mInitialCsmago;
+ mLevel[i].lcsmago = coarseCsmago;
mLevel[i].lcsmago_sqr = mLevel[i].lcsmago*mLevel[i].lcsmago;
mLevel[i].lcnu = (2.0* (1.0/mLevel[i].omega)-1.0) * (1.0/6.0);
}
// for lbgk
- mLevel[ mMaxRefine ].gravity = this->mGravity / mLevel[ mMaxRefine ].omega;
+ mLevel[ mMaxRefine ].gravity = mGravity / mLevel[ mMaxRefine ].omega;
for(int i=mMaxRefine-1; i>=0; i--) {
// should be the same on all levels...
// for lbgk
mLevel[i].gravity = (mLevel[i+1].gravity * mLevel[i+1].omega) * 2.0 / mLevel[i].omega;
}
- mLastOmega = this->mOmega;
- mLastGravity = this->mGravity;
+ mLastOmega = mOmega;
+ mLastGravity = mGravity;
// debug? invalidate old values...
- this->mGravity = -100.0;
- this->mOmega = -100.0;
+ mGravity = -100.0;
+ mOmega = -100.0;
for(int i=0; i<=mMaxRefine; i++) {
- if(!this->mSilent) {
+ if(!mSilent) {
errMsg("LbmFsgrSolver", "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" offs:"<<mLevel[i].lOffsx<<","<<mLevel[i].lOffsy<<","<<mLevel[i].lOffsz
<<" omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity<< ", "
<<" cmsagp:"<<mLevel[i].lcsmago<<", "
<< " ss"<<mLevel[i].timestep<<" ns"<<mLevel[i].nodeSize<<" cs"<<mLevel[i].simCellSize );
} else {
- if(!this->mInitDone) {
+ if(!mInitDone) {
debMsgStd("LbmFsgrSolver", DM_MSG, "Level init "<<i<<" - sizes:"<<mLevel[i].lSizex<<","<<mLevel[i].lSizey<<","<<mLevel[i].lSizez<<" "
<<"omega:"<<mLevel[i].omega<<" grav:"<<mLevel[i].gravity , 5);
}
@@ -604,55 +627,75 @@ void LbmFsgrSolver::initLevelOmegas()
/*! finish the init with config file values (allocate arrays...) */
bool LbmFsgrSolver::initializeSolverMemory()
{
- debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<this->mInitDone<<" "<<(void*)this,1);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init start... "<<mInitDone<<" "<<(void*)this,1);
// init cppf stage
if(mCppfStage>0) {
- this->mSizex *= mCppfStage;
- this->mSizey *= mCppfStage;
- this->mSizez *= mCppfStage;
+ mSizex *= mCppfStage;
+ mSizey *= mCppfStage;
+ mSizez *= mCppfStage;
}
// size inits to force cubic cells and mult4 level dimensions
// and make sure we dont allocate too much...
bool memOk = false;
- int orgSx = this->mSizex;
- int orgSy = this->mSizey;
- int orgSz = this->mSizez;
+ int orgSx = mSizex;
+ int orgSy = mSizey;
+ int orgSz = mSizez;
double sizeReduction = 1.0;
double memEstFromFunc = -1.0;
string memreqStr("");
+ bool firstMInit = true;
+ int minitTries=0;
while(!memOk) {
- initGridSizes( this->mSizex, this->mSizey, this->mSizez,
- this->mvGeoStart, this->mvGeoEnd, mMaxRefine, PARALLEL);
- calculateMemreqEstimate( this->mSizex, this->mSizey, this->mSizez, mMaxRefine, &memEstFromFunc, &memreqStr );
+ minitTries++;
+ initGridSizes( mSizex, mSizey, mSizez,
+ mvGeoStart, mvGeoEnd, mMaxRefine, PARALLEL);
+
+ // MPT
+#if LBM_INCLUDE_TESTSOLVERS==1
+ if(firstMInit) {
+ mrSetup();
+ }
+#endif // LBM_INCLUDE_TESTSOLVERS==1
+ firstMInit=false;
+
+ calculateMemreqEstimate( mSizex, mSizey, mSizez,
+ mMaxRefine, mFarFieldSize, &memEstFromFunc, &memreqStr );
double memLimit;
+ string memLimStr("-");
if(sizeof(void*)==4) {
// 32bit system, limit to 2GB
memLimit = 2.0* 1024.0*1024.0*1024.0;
+ memLimStr = string("2GB");
} else {
// 64bit, just take 16GB as limit for now...
memLimit = 16.0* 1024.0*1024.0*1024.0;
+ memLimStr = string("16GB");
}
if(memEstFromFunc>memLimit) {
sizeReduction *= 0.9;
- this->mSizex = (int)(orgSx * sizeReduction);
- this->mSizey = (int)(orgSy * sizeReduction);
- this->mSizez = (int)(orgSz * sizeReduction);
- debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<memEstFromFunc<<"/"<<memLimit<<", retrying: "
- <<this->mSizex<<" Y:"<<this->mSizey<<" Z:"<<this->mSizez, 3 );
+ mSizex = (int)(orgSx * sizeReduction);
+ mSizey = (int)(orgSy * sizeReduction);
+ mSizez = (int)(orgSz * sizeReduction);
+ debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<<
+ //memEstFromFunc<<"/"<<memLimit<<", "<<
+ memreqStr<<"/"<<memLimStr<<", "<<
+ "retrying: "<<PRINT_VEC(mSizex,mSizey,mSizez)<<" org:"<<PRINT_VEC(orgSx,orgSy,orgSz)
+ , 3 );
} else {
memOk = true;
}
}
- 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*) <<
+ mPreviewFactor = (LbmFloat)mOutputSurfacePreview / (LbmFloat)mSizex;
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"initGridSizes: Final domain size X:"<<mSizex<<" Y:"<<mSizey<<" Z:"<<mSizez<<
+ ", Domain: "<<mvGeoStart<<":"<<mvGeoEnd<<", "<<(mvGeoEnd-mvGeoStart)<<
+ ", PointerSize: "<< sizeof(void*) << ", IntSize: "<< sizeof(int) <<
", est. Mem.Req.: "<<memreqStr ,2);
- this->mpParam->setSize(this->mSizex, this->mSizey, this->mSizez);
+ mpParam->setSize(mSizex, mSizey, mSizez);
+ if((minitTries>1)&&(glob_mpnum)) { errMsg("LbmFsgrSolver::initialize","Warning!!!!!!!!!!!!!!! Original gridsize changed........."); }
debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Definitions: "
<<"LBM_EPSILON="<<LBM_EPSILON <<" "
@@ -666,22 +709,20 @@ bool LbmFsgrSolver::initializeSolverMemory()
<<"FSGR_MAGICNR="<<FSGR_MAGICNR <<" "
<<"USE_LES="<<USE_LES <<" "
,10);
-#if ELBEEM_PLUGIN!=1
-#endif // ELBEEM_PLUGIN!=1
// perform 2D corrections...
- if(LBMDIM == 2) this->mSizez = 1;
+ if(LBMDIM == 2) mSizez = 1;
- this->mpParam->setSimulationMaxSpeed(0.0);
- if(mFVHeight>0.0) this->mpParam->setFluidVolumeHeight(mFVHeight);
- this->mpParam->setTadapLevels( mMaxRefine+1 );
+ mpParam->setSimulationMaxSpeed(0.0);
+ if(mFVHeight>0.0) mpParam->setFluidVolumeHeight(mFVHeight);
+ mpParam->setTadapLevels( mMaxRefine+1 );
if(mForceTadapRefine>mMaxRefine) {
- this->mpParam->setTadapLevels( mForceTadapRefine+1 );
+ mpParam->setTadapLevels( mForceTadapRefine+1 );
debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Forcing a t-adap refine level of "<<mForceTadapRefine, 6);
}
- if(!this->mpParam->calculateAllMissingValues(mSimulationTime, false)) {
+ if(!mpParam->calculateAllMissingValues(mSimulationTime, false)) {
errFatal("LbmFsgrSolver::initialize","Fatal: failed to init parameters! Aborting...",SIMWORLD_INITERROR);
return false;
}
@@ -706,9 +747,9 @@ bool LbmFsgrSolver::initializeSolverMemory()
}
// init sizes
- mLevel[mMaxRefine].lSizex = this->mSizex;
- mLevel[mMaxRefine].lSizey = this->mSizey;
- mLevel[mMaxRefine].lSizez = this->mSizez;
+ mLevel[mMaxRefine].lSizex = mSizex;
+ mLevel[mMaxRefine].lSizey = mSizey;
+ mLevel[mMaxRefine].lSizez = mSizez;
for(int i=mMaxRefine-1; i>=0; i--) {
mLevel[i].lSizex = mLevel[i+1].lSizex/2;
mLevel[i].lSizey = mLevel[i+1].lSizey/2;
@@ -722,8 +763,8 @@ bool LbmFsgrSolver::initializeSolverMemory()
}
double ownMemCheck = 0.0;
- mLevel[ mMaxRefine ].nodeSize = ((this->mvGeoEnd[0]-this->mvGeoStart[0]) / (LbmFloat)(this->mSizex));
- mLevel[ mMaxRefine ].simCellSize = this->mpParam->getCellSize();
+ mLevel[ mMaxRefine ].nodeSize = ((mvGeoEnd[0]-mvGeoStart[0]) / (LbmFloat)(mSizex));
+ mLevel[ mMaxRefine ].simCellSize = mpParam->getCellSize();
mLevel[ mMaxRefine ].lcellfactor = 1.0;
LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum);
// +4 for safety ?
@@ -759,8 +800,14 @@ bool LbmFsgrSolver::initializeSolverMemory()
ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4);
}
- // isosurface memory
- ownMemCheck += (3*sizeof(int)+sizeof(float)) * ((this->mSizex+2)*(this->mSizey+2)*(this->mSizez+2));
+ // isosurface memory, use orig res values
+ if(mFarFieldSize>0.) {
+ ownMemCheck += (double)( (3*sizeof(int)+sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
+ } else {
+ // ignore 3 int slices...
+ ownMemCheck += (double)( ( sizeof(float)) * ((mSizex+2)*(mSizey+2)*(mSizez+2)) );
+ }
+
// sanity check
#if ELBEEM_PLUGIN!=1
if(ABS(1.0-ownMemCheck/memEstFromFunc)>0.01) {
@@ -782,31 +829,31 @@ bool LbmFsgrSolver::initializeSolverMemory()
// calc omega, force for all levels
initLevelOmegas();
- mMinTimestep = this->mpParam->getTimestep();
- mMaxTimestep = this->mpParam->getTimestep();
+ mMinTimestep = mpParam->getTimestep();
+ mMaxTimestep = mpParam->getTimestep();
// init isosurf
- this->mpIso->setIsolevel( this->mIsoValue );
+ mpIso->setIsolevel( mIsoValue );
#if LBM_INCLUDE_TESTSOLVERS==1
if(mUseTestdata) {
- mpTest->setMaterialName( this->mpIso->getMaterialName() );
- delete this->mpIso;
- this->mpIso = mpTest;
- if(mpTest->mDebugvalue1>0.0) { // 3d off
+ mpTest->setMaterialName( mpIso->getMaterialName() );
+ delete mpIso;
+ mpIso = mpTest;
+ if(mpTest->mFarfMode>0) { // 3d off
mpTest->setIsolevel(-100.0);
} else {
- mpTest->setIsolevel( this->mIsoValue );
+ mpTest->setIsolevel( mIsoValue );
}
}
-#endif // ELBEEM_PLUGIN!=1
+#endif // LBM_INCLUDE_TESTSOLVERS!=1
// approximate feature size with mesh resolution
float featureSize = mLevel[ mMaxRefine ].nodeSize*0.5;
// smooth vars defined in solver_interface, set by simulation object
// reset for invalid values...
- if((this->mSmoothSurface<0.)||(this->mSmoothSurface>50.)) this->mSmoothSurface = 1.;
- if((this->mSmoothNormals<0.)||(this->mSmoothNormals>50.)) this->mSmoothNormals = 1.;
- this->mpIso->setSmoothSurface( this->mSmoothSurface * featureSize );
- this->mpIso->setSmoothNormals( this->mSmoothNormals * featureSize );
+ if((mSmoothSurface<0.)||(mSmoothSurface>50.)) mSmoothSurface = 1.;
+ if((mSmoothNormals<0.)||(mSmoothNormals>50.)) mSmoothNormals = 1.;
+ mpIso->setSmoothSurface( mSmoothSurface * featureSize );
+ mpIso->setSmoothNormals( mSmoothNormals * featureSize );
// init iso weight values mIsoWeightMethod
int wcnt = 0;
@@ -835,34 +882,54 @@ bool LbmFsgrSolver::initializeSolverMemory()
}
for(int i=0; i<27; i++) mIsoWeight[i] /= totw;
- LbmVec isostart = vec2L(this->mvGeoStart);
- LbmVec isoend = vec2L(this->mvGeoEnd);
+ LbmVec isostart = vec2L(mvGeoStart);
+ LbmVec isoend = vec2L(mvGeoEnd);
int twodOff = 0; // 2d slices
if(LBMDIM==2) {
LbmFloat sn,se;
- sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5;
- se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5;
+ sn = isostart[2]+(isoend[2]-isostart[2])*0.5 - ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
+ se = isostart[2]+(isoend[2]-isostart[2])*0.5 + ((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5;
isostart[2] = sn;
isoend[2] = se;
twodOff = 2;
}
- int isosx = this->mSizex+2;
- int isosy = this->mSizey+2;
- int isosz = this->mSizez+2+twodOff;
+ int isosx = mSizex+2;
+ int isosy = mSizey+2;
+ int isosz = mSizez+2+twodOff;
// MPT
#if LBM_INCLUDE_TESTSOLVERS==1
- if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) {
- int xfac = 2;
- isosx *= xfac;
- isoend[0] = isostart[0] + (isoend[0]-isostart[0])*(LbmFloat)xfac;
+ //if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) {
+ if( (mMpNum>0) && (mMpIndex==0) ) {
+ //? mpindex==0
+ // restore original value for node0
+ isosx = mOrgSizeX + 2;
+ isostart[0] = mOrgStartX;
+ isoend[0] = mOrgEndX;
}
+ errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMin.mSrcx,mpTest->mGCMin.mSrcy,mpTest->mGCMin.mSrcz)<<" dst"
+ << PRINT_VEC(mpTest->mGCMin.mDstx,mpTest->mGCMin.mDsty,mpTest->mGCMin.mDstz)<<" consize"
+ << PRINT_VEC(mpTest->mGCMin.mConSizex,mpTest->mGCMin.mConSizey,mpTest->mGCMin.mConSizez)<<" ");
+ errMsg("LbmFsgrSolver::initialize", "MPT: gcon "<<mMpNum<<","<<mMpIndex<<" src"<< PRINT_VEC(mpTest->mGCMax.mSrcx,mpTest->mGCMax.mSrcy,mpTest->mGCMax.mSrcz)<<" dst"
+ << PRINT_VEC(mpTest->mGCMax.mDstx,mpTest->mGCMax.mDsty,mpTest->mGCMax.mDstz)<<" consize"
+ << PRINT_VEC(mpTest->mGCMax.mConSizex,mpTest->mGCMax.mConSizey,mpTest->mGCMax.mConSizez)<<" ");
#endif // LBM_INCLUDE_TESTSOLVERS==1
- //errMsg(" SETISO ", " "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(this->mSizex+1.0))*0.5)<<" "<<(LbmFloat)(this->mSizex+1.0)<<" " );
+ errMsg(" SETISO ", "iso "<<isostart<<" - "<<isoend<<" "<<(((isoend[0]-isostart[0]) / (LbmFloat)(mSizex+1.0))*0.5)<<" "<<(LbmFloat)(mSizex+1.0) );
+ errMsg("LbmFsgrSolver::initialize", "MPT: geo "<< mvGeoStart<<","<<mvGeoEnd<<
+ " grid:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<",iso:"<< PRINT_VEC(isosx,isosy,isosz) );
mpIso->setStart( vec2G(isostart) );
mpIso->setEnd( vec2G(isoend) );
LbmVec isodist = isoend-isostart;
+
+ int isosubs = mIsoSubdivs;
+ if(mFarFieldSize>1.) {
+ errMsg("LbmFsgrSolver::initialize","Warning - resetting isosubdivs, using fulledge!");
+ isosubs = 1;
+ mpIso->setUseFulledgeArrays(true);
+ }
+ mpIso->setSubdivs(isosubs);
+
mpIso->initializeIsosurface( isosx,isosy,isosz, vec2G(isodist) );
// reset iso field
@@ -876,7 +943,7 @@ bool LbmFsgrSolver::initializeSolverMemory()
for(int lev=0; lev<=mMaxRefine; lev++) {
FSGR_FORIJK_BOUNDS(lev) {
RFLAG(lev,i,j,k,0) = RFLAG(lev,i,j,k,0) = 0; // reset for changeFlag usage
- if(!this->mAllfluid) {
+ if(!mAllfluid) {
initEmptyCell(lev, i,j,k, CFEmpty, -1.0, -1.0);
} else {
initEmptyCell(lev, i,j,k, CFFluid, 1.0, 1.0);
@@ -884,38 +951,43 @@ bool LbmFsgrSolver::initializeSolverMemory()
}
}
+
if(LBMDIM==2) {
- if(this->mOutputSurfacePreview) {
+ if(mOutputSurfacePreview) {
errMsg("LbmFsgrSolver::init","No preview in 2D allowed!");
- this->mOutputSurfacePreview = 0; }
+ mOutputSurfacePreview = 0; }
+ }
+ if((glob_mpactive) && (glob_mpindex>0)) {
+ mOutputSurfacePreview = 0;
}
+
#if LBM_USE_GUI==1
- if(this->mOutputSurfacePreview) {
+ if(mOutputSurfacePreview) {
errMsg("LbmFsgrSolver::init","No preview in GUI mode... mOutputSurfacePreview=0");
- this->mOutputSurfacePreview = 0; }
+ mOutputSurfacePreview = 0; }
#endif // LBM_USE_GUI==1
- if(this->mOutputSurfacePreview) {
+ if(mOutputSurfacePreview) {
// same as normal one, but use reduced size
- mpPreviewSurface = new IsoSurface( this->mIsoValue );
+ mpPreviewSurface = new IsoSurface( mIsoValue );
mpPreviewSurface->setMaterialName( mpPreviewSurface->getMaterialName() );
- mpPreviewSurface->setIsolevel( this->mIsoValue );
+ mpPreviewSurface->setIsolevel( 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" );
+ LbmFloat pfac = mPreviewFactor;
+ mpPreviewSurface->initializeIsosurface( (int)(pfac*mSizex)+2, (int)(pfac*mSizey)+2, (int)(pfac*mSizez)+2, vec2G(pisodist) );
+ //mpPreviewSurface->setName( getName() + "preview" );
mpPreviewSurface->setName( "preview" );
- debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*this->mSizex)<<","<<(pfac*this->mSizey)<<","<<(pfac*this->mSizez)<<" enabled",10);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Preview with sizes "<<(pfac*mSizex)<<","<<(pfac*mSizey)<<","<<(pfac*mSizez)<<" enabled",10);
}
// init defaults
mAvgNumUsedCells = 0;
- this->mFixMass= 0.0;
+ mFixMass= 0.0;
return true;
}
@@ -933,23 +1005,23 @@ bool LbmFsgrSolver::initializeSolverGrids() {
CellFlagType domainBoundType = CFInvalid;
// TODO use normal object types instad...
- if(this->mDomainBound.find(string("free")) != string::npos) {
+ if(mDomainBound.find(string("free")) != string::npos) {
domainBoundType = CFBnd | CFBndFreeslip;
- debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<this->mDomainBound,10);
- } else if(this->mDomainBound.find(string("part")) != string::npos) {
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: FreeSlip, value:"<<mDomainBound,10);
+ } else if(mDomainBound.find(string("part")) != string::npos) {
domainBoundType = CFBnd | CFBndPartslip; // part slip type
- debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<this->mDomainPartSlipValue<<"), value:"<<this->mDomainBound,10);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: PartSlip ("<<mDomainPartSlipValue<<"), value:"<<mDomainBound,10);
} else {
domainBoundType = CFBnd | CFBndNoslip;
- debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<this->mDomainBound,10);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Domain Boundary Type: NoSlip, value:"<<mDomainBound,10);
}
// use ar[numobjs] as entry for domain (used e.g. for mDomainPartSlipValue in mObjectPartslips)
- int domainobj = (int)(this->mpGiObjects->size());
+ int domainobj = (int)(mpGiObjects->size());
domainBoundType |= (domainobj<<24);
//for(int i=0; i<(int)(domainobj+0); i++) {
- //errMsg("GEOIN","i"<<i<<" "<<(*this->mpGiObjects)[i]->getName());
- //if((*this->mpGiObjects)[i] == this->mpIso) { //check...
+ //errMsg("GEOIN","i"<<i<<" "<<(*mpGiObjects)[i]->getName());
+ //if((*mpGiObjects)[i] == mpIso) { //check...
//}
//}
//errMsg("GEOIN"," dm "<<(domainBoundType>>24));
@@ -1050,19 +1122,19 @@ bool LbmFsgrSolver::initializeSolverGrids() {
mInitialMass = 0.0;
int inmCellCnt = 0;
FSGR_FORIJK1(mMaxRefine) {
- if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid) ) {
+ if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid) {
LbmFloat fluidRho = QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, 0);
FORDF1 { fluidRho += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, l); }
mInitialMass += fluidRho;
inmCellCnt ++;
- } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) {
+ } else if( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) {
mInitialMass += QCELL(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr, dMass);
inmCellCnt ++;
}
}
mCurrentVolume = mCurrentMass = mInitialMass;
- ParamVec cspv = this->mpParam->calculateCellSize();
+ ParamVec cspv = mpParam->calculateCellSize();
if(LBMDIM==2) cspv[2] = 1.0;
inmCellCnt = 1;
double nrmMass = (double)mInitialMass / (double)(inmCellCnt) *cspv[0]*cspv[1]*cspv[2] * 1000.0;
@@ -1071,7 +1143,7 @@ bool LbmFsgrSolver::initializeSolverGrids() {
//mStartSymm = false;
#if ELBEEM_PLUGIN!=1
- if((LBMDIM==2)&&(this->mSizex<200)) {
+ if((LBMDIM==2)&&(mSizex<200)) {
if(!checkSymmetry("init")) {
errMsg("LbmFsgrSolver::initialize","Unsymmetric init...");
} else {
@@ -1094,18 +1166,18 @@ bool LbmFsgrSolver::initializeSolverPostinit() {
adaptGrid(lev);
coarseRestrictFromFine(lev);
}
- this->markedClearList();
+ markedClearList();
myTime_t fsgrtend = getTime();
- if(!this->mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); }
+ if(!mSilent){ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"FSGR init done ("<< getTimeString(fsgrtend-fsgrtstart)<<"), changes:"<<mNumFsgrChanges , 10 ); }
mNumFsgrChanges = 0;
- for(int l=0; l<this->cDirNum; l++) {
+ for(int l=0; l<cDirNum; l++) {
LbmFloat area = 0.5 * 0.5 *0.5;
if(LBMDIM==2) area = 0.5 * 0.5;
- if(this->dfVecX[l]!=0) area *= 0.5;
- if(this->dfVecY[l]!=0) area *= 0.5;
- if(this->dfVecZ[l]!=0) area *= 0.5;
+ if(dfVecX[l]!=0) area *= 0.5;
+ if(dfVecY[l]!=0) area *= 0.5;
+ if(dfVecZ[l]!=0) area *= 0.5;
mFsgrCellArea[l] = area;
} // l
@@ -1123,6 +1195,8 @@ bool LbmFsgrSolver::initializeSolverPostinit() {
stepMain();
// prepare once...
+ mpIso->setParticles(mpParticles, mPartDropMassSub);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Iso Settings, subdivs="<<mpIso->getSubdivs()<<", partsize="<<mPartDropMassSub, 9);
prepareVisualization();
// copy again for stats counting
for(int lev=0; lev<=mMaxRefine; lev++) {
@@ -1132,9 +1206,9 @@ bool LbmFsgrSolver::initializeSolverPostinit() {
// now really done...
- 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;
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"SurfaceGen: SmsOrg("<<mSmoothSurface<<","<<mSmoothNormals<< /*","<<featureSize<<*/ "), Iso("<<mpIso->getSmoothSurface()<<","<<mpIso->getSmoothNormals()<<") ",10);
+ debMsgStd("LbmFsgrSolver::initialize",DM_MSG,"Init done ... ",10);
+ mInitDone = 1;
#if LBM_INCLUDE_TESTSOLVERS==1
initCpdata();
@@ -1201,8 +1275,8 @@ bool LbmFsgrSolver::initializeSolverPostinit() {
const LbmVec oldov=objvel; /*DEBUG*/ \
/* if((j==24)&&(n%5==2)) errMsg("FSBT","n"<<n<<" v"<<objvel<<" nn"<<(*pNormals)[n]<<" dp"<<dp<<" oldov"<<oldov ); */ \
const LbmFloat partv = mObjectPartslips[OId]; \
- /*errMsg("PARTSLIP_DEBUG","l="<<l<<" ccel="<<RAC(ccel, this->dfInv[l] )<<" partv="<<partv<<",id="<<(int)(mnbf>>24)<<" newval="<<newval ); / part slip debug */ \
- /* m[l] = (RAC(ccel, this->dfInv[l] ) ) * partv + newval * (1.-partv); part slip */ \
+ /*errMsg("PARTSLIP_DEBUG","l="<<l<<" ccel="<<RAC(ccel, dfInv[l] )<<" partv="<<partv<<",id="<<(int)(mnbf>>24)<<" newval="<<newval ); / part slip debug */ \
+ /* m[l] = (RAC(ccel, dfInv[l] ) ) * partv + newval * (1.-partv); part slip */ \
objvel = objvel*partv + vec2L((*pNormals)[n]) *dp*(1.-partv); \
}
@@ -1221,7 +1295,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
const int otherSet = mLevel[level].setOther;
LbmFloat sourceTime = mSimulationTime; // should be equal to mLastSimTime!
// for debugging - check targetTime check during DEFAULT STREAM
- LbmFloat targetTime = mSimulationTime + this->mpParam->getTimestep();
+ LbmFloat targetTime = mSimulationTime + mpParam->getTimestep();
if(mLastSimTime == targetTime) {
debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_WARNING,"Called for same time! (t="<<mSimulationTime<<" , targett="<<targetTime<<")", 1);
return;
@@ -1236,16 +1310,15 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
CellFlagType otype = CFInvalid; // verify type of last step, might be non moving obs!
CellFlagType ntype = CFInvalid;
// WARNING - copied from geo init!
- int numobjs = (int)(this->mpGiObjects->size());
+ int numobjs = (int)(mpGiObjects->size());
ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
// 2d display as rectangles
ntlVec3Gfx iniPos(0.0);
if(LBMDIM==2) {
dvec[2] = 1.0;
- iniPos = (this->mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ))-(dvec*0.0);
+ iniPos = (mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))-(dvec*0.0);
} else {
- iniPos = (this->mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0);
- //iniPos[2] = this->mvGeoStart[2] + dvec[2]*getForZMin1();
+ iniPos = (mvGeoStart + ntlVec3Gfx( 0.0 ))-(dvec*0.0);
}
if( (int)mObjectMassMovnd.size() < numobjs) {
@@ -1258,21 +1331,20 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
int monPoints=0, monObsts=0, monFluids=0, monTotal=0, monTrafo=0;
int nbored;
for(int OId=0; OId<numobjs; OId++) {
- ntlGeometryObject *obj = (*this->mpGiObjects)[OId];
+ ntlGeometryObject *obj = (*mpGiObjects)[OId];
bool skip = false;
- if(obj->getGeoInitId() != this->mLbmInitId) skip=true;
+ if(obj->getGeoInitId() != 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;
+ debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG," obj "<<obj->getName()<<" skip:"<<skip<<", static:"<<staticInit<<" anim:"<<obj->getIsAnimated()<<" gid:"<<obj->getGeoInitId()<<" simgid:"<<mLbmInitId, 10);
if( (obj->getGeoInitType()&FGI_ALLBOUNDS) ||
(obj->getGeoInitType()&FGI_FLUID) && staticInit ) {
otype = ntype = CFInvalid;
switch(obj->getGeoInitType()) {
- /*
- case FGI_BNDPART:
+ /* case FGI_BNDPART: // old, use noslip for moving part/free objs
case FGI_BNDFREE:
if(!staticInit) {
errMsg("LbmFsgrSolver::initMovingObstacles","Warning - moving free/part slip objects NYI "<<obj->getName() );
@@ -1311,8 +1383,8 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
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 );
+ mObjectSpeeds[OId] = vec2L(mpParam->calculateLattVelocityFromRw( vec2P( (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) )));
+ debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"id"<<OId<<" "<<obj->getName()<<" inivel set to "<< mObjectSpeeds[OId]<<", unscaled:"<< (*mpGiObjects)[OId]->getInitialVelocity(mSimulationTime) ,10 );
//vector<ntlVec3Gfx> tNormals;
vector<ntlVec3Gfx> *pNormals = NULL;
@@ -1324,7 +1396,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
// do two full update
// TODO tNormals handling!?
mMOIVerticesOld.clear();
- obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, pNormals, mLevel[mMaxRefine].nodeSize, this->mvGeoStart, this->mvGeoEnd);
+ obj->initMovingPointsAnim(sourceTime,mMOIVerticesOld, targetTime, mMOIVertices, pNormals, mLevel[mMaxRefine].nodeSize, mvGeoStart, mvGeoEnd);
monTrafo += mMOIVerticesOld.size();
obj->applyTransformation(sourceTime, &mMOIVerticesOld,pNormals, 0, mMOIVerticesOld.size(), false );
monTrafo += mMOIVertices.size();
@@ -1352,7 +1424,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
// FIXME?
if(normNoSqrt(objMaxVel)>0.0) { ntype |= CFBndMoving; }
// get old type - CHECK FIXME , timestep could have changed - cause trouble?
- ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - this->mpParam->getTimestep(),sourceTime);
+ ntlVec3Gfx oldobjMaxVel = obj->calculateMaxVel(sourceTime - mpParam->getTimestep(),sourceTime);
if(normNoSqrt(oldobjMaxVel)>0.0) { otype |= CFBndMoving; }
}
if(obj->getMeshAnimated()) { ntype |= CFBndMoving; otype |= CFBndMoving; }
@@ -1360,6 +1432,8 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
LbmFloat massCheck = 0.;
int massReinits=0;
bool fillCells = (mObjectMassMovnd[OId]<=-1.);
+ LbmFloat impactCorrFactor = obj->getGeoImpactFactor(targetTime);
+
// first pass - set new obs. cells
if(active) {
@@ -1397,30 +1471,19 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
// 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 *rhodstCell = RACPNT(level, i+dfVecX[l],j+dfVecY[l],k+dfVecZ[l],workSet);
- LbmFloat rhodst = RAC(rhodstCell,dC);
- for(int ll=1; ll<19; ll++) { rhodst += RAC(rhodstCell,ll); }
- rhodst = 1.; // DEBUG TEST! */
-
- LbmFloat factor = 2. * this->dfLength[l] * 3.0 * (ux+uy+uz); //
- /* FSTEST
- */
+ const LbmFloat ux = dfDvecX[l]*objvel[0];
+ const LbmFloat uy = dfDvecY[l]*objvel[1];
+ const LbmFloat uz = dfDvecZ[l]*objvel[2];
+
+ LbmFloat factor = 2. * dfLength[l] * 3.0 * (ux+uy+uz); //
if(ntype&(CFBndFreeslip|CFBndPartslip)) {
// missing, diag mass checks...
- //if(l<=LBMDIM*2) massCheck += factor;
-
//if(l<=LBMDIM*2) factor *= 1.4142;
- //if(l>LBMDIM*2) factor = 0.;
- //else
- //factor = 0.; // TODO, optimize
factor *= 2.0; // TODO, optimize
} else {
factor *= 1.2; // TODO, optimize
}
+ factor *= impactCorrFactor; // use manual tweaking channel
RAC(dstCell,l) = factor;
massCheck += factor;
} else {
@@ -1461,28 +1524,19 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
}
CellFlagType settype = CFInvalid;
if(nbored&CFFluid) {
- //if(nbored&(CFFluid|CFInter)) {
settype = CFInter|CFNoInterpolSrc;
rhomass = 1.5;
if(!fillCells) rhomass = 0.;
- //settype = CFFluid|CFNoInterpolSrc; rhomass=1.; // test
- //rhomass = 1.01; // DEBUGT
OBJVEL_CALC;
if(!(nbored&CFEmpty)) { settype=CFFluid|CFNoInterpolSrc; rhomass=1.; }
- //settype=CFFluid; // rhomass = 1.; objvel = LbmVec(0.); // DEBUG TEST
// new interpolate values
LbmFloat avgrho = 0.0;
LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
interpolateCellValues(level,i,j,k,workSet, avgrho,avgux,avguy,avguz);
- //objvel = LbmVec(avgux,avguy,avguz);
- //avgrho=1.;
initVelocityCell(level, i,j,k, settype, avgrho, rhomass, LbmVec(avgux,avguy,avguz) );
//errMsg("NMOCIT"," at "<<PRINT_IJK<<" "<<avgrho<<" "<<norm(LbmVec(avgux,avguy,avguz))<<" "<<LbmVec(avgux,avguy,avguz) );
-
- // old - fixed init
- //initVelocityCell(level, i,j,k, settype, 1., rhomass, objvel );
massCheck += rhomass;
} else {
settype = CFEmpty; rhomass = 0.0;
@@ -1495,7 +1549,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
} // wasactive
// only compute mass transfer when init is done
- if(this->mInitDone) {
+ if(mInitDone) {
errMsg("initMov","dccd\n\nMassd test "<<obj->getName()<<" dccd massCheck="<<massCheck<<" massReinits"<<massReinits<<
" fillCells"<<fillCells<<" massmovbnd:"<<mObjectMassMovnd[OId]<<" inim:"<<mInitialMass );
mObjectMassMovnd[OId] += massCheck;
@@ -1512,8 +1566,6 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
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); }
@@ -1628,7 +1680,7 @@ void LbmFsgrSolver::initMovingObstacles(bool staticInit) {
#undef POS2GRID_CHECK
myTime_t monend = getTime();
- debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7);
+ if(monend-monstart>0) debMsgStd("LbmFsgrSolver::initMovingObstacles",DM_MSG,"Total: "<<monTotal<<" Points :"<<monPoints<<" ObstInits:"<<monObsts<<" FlInits:"<<monFluids<<" Trafos:"<<monTotal<<", took "<<getTimeString(monend-monstart), 7);
mLastSimTime = targetTime;
}
@@ -1651,20 +1703,20 @@ bool LbmFsgrSolver::initGeometryFlags() {
myTime_t geotimestart = getTime();
ntlGeometryObject *pObj;
ntlVec3Gfx dvec = ntlVec3Gfx(mLevel[level].nodeSize); //dvec*1.0;
- debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< this->mLbmInitId <<") v"<<dvec,3);
+ debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing geometry init ("<< mLbmInitId <<") v"<<dvec,3);
// WARNING - copied to movobj init!
/* init object velocities, this has always to be called for init */
- this->initGeoTree();
- if(this->mAllfluid) {
- this->freeGeoTree();
+ initGeoTree();
+ if(mAllfluid) {
+ freeGeoTree();
return true; }
// make sure moving obstacles are inited correctly
// preinit moving obj points
- int numobjs = (int)(this->mpGiObjects->size());
+ int numobjs = (int)(mpGiObjects->size());
for(int o=0; o<numobjs; o++) {
- ntlGeometryObject *obj = (*this->mpGiObjects)[o];
+ ntlGeometryObject *obj = (*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())) ||
@@ -1677,20 +1729,20 @@ bool LbmFsgrSolver::initGeometryFlags() {
}
// max speed init
- ntlVec3Gfx maxMovobjVelRw = this->getGeoMaxMovementVelocity( mSimulationTime, this->mpParam->getTimestep() );
- ntlVec3Gfx maxMovobjVel = vec2G( this->mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) );
- this->mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) );
- LbmFloat allowMax = this->mpParam->getTadapMaxSpeed(); // maximum allowed velocity
+ ntlVec3Gfx maxMovobjVelRw = getGeoMaxMovementVelocity( mSimulationTime, mpParam->getTimestep() );
+ ntlVec3Gfx maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P( maxMovobjVelRw )) );
+ mpParam->setSimulationMaxSpeed( norm(maxMovobjVel) + norm(mLevel[level].gravity) );
+ LbmFloat allowMax = mpParam->getTadapMaxSpeed(); // maximum allowed velocity
debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Maximum Velocity from geo init="<< maxMovobjVel <<" from mov. obj.="<<maxMovobjVelRw<<" , allowed Max="<<allowMax ,5);
- if(this->mpParam->getSimulationMaxSpeed() > allowMax) {
+ if(mpParam->getSimulationMaxSpeed() > allowMax) {
// similar to adaptTimestep();
- LbmFloat nextmax = this->mpParam->getSimulationMaxSpeed();
- LbmFloat newdt = this->mpParam->getTimestep() * (allowMax / nextmax); // newtr
- debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< this->mpParam->getTimestep() <<" ",5);
- this->mpParam->setDesiredTimestep( newdt );
- this->mpParam->calculateAllMissingValues( mSimulationTime, this->mSilent );
- maxMovobjVel = vec2G( this->mpParam->calculateLattVelocityFromRw( vec2P(this->getGeoMaxMovementVelocity(
- mSimulationTime, this->mpParam->getTimestep() )) ));
+ LbmFloat nextmax = mpParam->getSimulationMaxSpeed();
+ LbmFloat newdt = mpParam->getTimestep() * (allowMax / nextmax); // newtr
+ debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Performing reparametrization, newdt="<< newdt<<" prevdt="<< mpParam->getTimestep() <<" ",5);
+ mpParam->setDesiredTimestep( newdt );
+ mpParam->calculateAllMissingValues( mSimulationTime, mSilent );
+ maxMovobjVel = vec2G( mpParam->calculateLattVelocityFromRw( vec2P(getGeoMaxMovementVelocity(
+ mSimulationTime, mpParam->getTimestep() )) ));
debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"New maximum Velocity from geo init="<< maxMovobjVel,5);
}
recalculateObjectSpeeds();
@@ -1710,24 +1762,25 @@ bool LbmFsgrSolver::initGeometryFlags() {
// 2d display as rectangles
if(LBMDIM==2) {
dvec[2] = 0.0;
- iniPos =(this->mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (this->mvGeoEnd[2]-this->mvGeoStart[2])*0.5 ))+(dvec*0.5);
+ iniPos =(mvGeoStart + ntlVec3Gfx( 0.0, 0.0, (mvGeoEnd[2]-mvGeoStart[2])*0.5 ))+(dvec*0.5);
//if(mInit2dYZ) { SWAPYZ(mGravity); for(int lev=0; lev<=mMaxRefine; lev++){ SWAPYZ( mLevel[lev].gravity ); } }
} else {
- iniPos =(this->mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5);
+ iniPos =(mvGeoStart + ntlVec3Gfx( 0.0 ))+(dvec*0.5);
}
// first init boundary conditions
// invalid cells are set to empty afterwards
+ // TODO use floop macros!?
for(int k= getForZMin1(); k< getForZMax1(level); ++k) {
for(int j=1;j<mLevel[level].lSizey-1;j++) {
for(int i=1;i<mLevel[level].lSizex-1;i++) {
ntype = CFInvalid;
GETPOS(i,j,k);
- const bool inside = this->geoInitCheckPointInside( ggpos, FGI_ALLBOUNDS, OId, distance);
+ const bool inside = geoInitCheckPointInside( ggpos, FGI_ALLBOUNDS, OId, distance);
if(inside) {
- pObj = (*this->mpGiObjects)[OId];
+ pObj = (*mpGiObjects)[OId];
switch( pObj->getGeoInitType() ){
case FGI_MBNDINFLOW:
if(! pObj->getIsAnimated() ) {
@@ -1795,7 +1848,7 @@ bool LbmFsgrSolver::initGeometryFlags() {
ntype = CFInvalid;
int inits = 0;
GETPOS(i,j,k);
- const bool inside = this->geoInitCheckPointInside( ggpos, FGI_FLUID, OId, distance);
+ const bool inside = geoInitCheckPointInside( ggpos, FGI_FLUID, OId, distance);
if(inside) {
ntype = CFFluid;
}
@@ -1838,13 +1891,15 @@ bool LbmFsgrSolver::initGeometryFlags() {
}
}
- this->freeGeoTree();
+ freeGeoTree();
myTime_t geotimeend = getTime();
debMsgStd("LbmFsgrSolver::initGeometryFlags",DM_MSG,"Geometry init done ("<< getTimeString(geotimeend-geotimestart)<<","<<savedNodes<<") " , 10 );
//errMsg(" SAVED "," "<<savedNodes<<" of "<<(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez));
return true;
}
+#undef GETPOS
+
/*****************************************************************************/
/* init part for all freesurface testcases */
void LbmFsgrSolver::initFreeSurfaces() {
@@ -1853,10 +1908,10 @@ void LbmFsgrSolver::initFreeSurfaces() {
// set interface cells
FSGR_FORIJK1(mMaxRefine) {
- if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFFluid )) {
+ if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFFluid )) {
FORDF1 {
- 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 ) ) {
+ int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
+ if( ( 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) );
@@ -1870,13 +1925,13 @@ void LbmFsgrSolver::initFreeSurfaces() {
// remove invalid interface cells
FSGR_FORIJK1(mMaxRefine) {
// remove invalid interface cells
- if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr), CFInter) ) {
+ if( ( RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr)& CFInter) ) {
int delit = 0;
int NBs = 0; // neighbor flags or'ed
int noEmptyNB = 1;
FORDF1 {
- if( TESTFLAG( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l ), CFEmpty ) ) {
+ if( ( RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr,l )& CFEmpty ) ) {
noEmptyNB = 0;
}
NBs |= RFLAG_NBINV(mMaxRefine, i, j, k, mLevel[mMaxRefine].setCurr, l);
@@ -1941,12 +1996,12 @@ void LbmFsgrSolver::initFreeSurfaces() {
#endif // COMPRESSGRIDS==0
for(int j=1;j<mLevel[lev].lSizey-1;++j) {
for(int i=1;i<mLevel[lev].lSizex-1;++i) {
- if( TESTFLAG( RFLAG(lev, i,j,k, mLevel[lev].setCurr), CFInter) ) {
+ if( ( RFLAG(lev, i,j,k, mLevel[lev].setCurr)& CFInter) ) {
LbmFloat mass = 0.0;
//LbmFloat nbdiv;
//FORDF0 {
- for(int l=0;(l<this->cDirNum); l++) {
- int ni=i+this->dfVecX[l], nj=j+this->dfVecY[l], nk=k+this->dfVecZ[l];
+ for(int l=0;(l<cDirNum); l++) {
+ int ni=i+dfVecX[l], nj=j+dfVecY[l], nk=k+dfVecZ[l];
if( RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr) & CFFluid ){
mass += 1.0;
}
@@ -1957,7 +2012,7 @@ void LbmFsgrSolver::initFreeSurfaces() {
}
//errMsg(" I ", PRINT_IJK<<" m"<<mass );
- QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)this->cDirNum) );
+ QCELL(lev, i,j,k, mLevel[lev].setOther, dMass) = (mass/ ((LbmFloat)cDirNum) );
QCELL(lev, i,j,k, mLevel[lev].setOther, dFfrac) = QCELL(lev, i,j,k, mLevel[lev].setOther, dMass);
}
}}}
@@ -2186,7 +2241,7 @@ bool LbmFsgrSolver::checkSymmetry(string idstring)
LbmFloat maxdiv =0.0;
if(erro) {
errMsg("SymCheck Failed!", idstring<<" rho maxdiv:"<< maxdiv );
- //if(LBMDIM==2) this->mPanic = true;
+ //if(LBMDIM==2) mPanic = true;
//return false;
} else {
errMsg("SymCheck OK!", idstring<<" rho maxdiv:"<< maxdiv );
@@ -2205,17 +2260,17 @@ LbmFsgrSolver::interpolateCellValues(
LbmFloat avgux = 0.0, avguy = 0.0, avguz = 0.0;
LbmFloat cellcnt = 0.0;
- for(int nbl=1; nbl< this->cDfNum ; ++nbl) {
+ for(int nbl=1; nbl< cDfNum ; ++nbl) {
if(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) continue;
if( (RFLAG_NB(level,ei,ej,ek,workSet,nbl) & (CFFluid|CFInter)) ){
//((!(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFNoInterpolSrc) ) &&
//(RFLAG_NB(level,ei,ej,ek,workSet,nbl) & CFInter) ) {
cellcnt += 1.0;
- for(int rl=0; rl< this->cDfNum ; ++rl) {
+ for(int rl=0; rl< cDfNum ; ++rl) {
LbmFloat nbdf = QCELL_NB(level,ei,ej,ek, workSet,nbl, rl);
- avgux += (this->dfDvecX[rl]*nbdf);
- avguy += (this->dfDvecY[rl]*nbdf);
- avguz += (this->dfDvecZ[rl]*nbdf);
+ avgux += (dfDvecX[rl]*nbdf);
+ avguy += (dfDvecY[rl]*nbdf);
+ avguz += (dfDvecZ[rl]*nbdf);
avgrho += nbdf;
}
}
@@ -2227,7 +2282,7 @@ LbmFsgrSolver::interpolateCellValues(
avgux = avguy = avguz = 0.0;
//TTT mNumProblems++;
#if ELBEEM_PLUGIN!=1
- //this->mPanic=1;
+ //mPanic=1;
// this can happen for worst case moving obj scenarios...
errMsg("LbmFsgrSolver::interpolateCellValues","Cellcnt<=0.0 at "<<PRINT_VEC(ei,ej,ek));
#endif // ELBEEM_PLUGIN
diff --git a/intern/elbeem/intern/solver_interface.cpp b/intern/elbeem/intern/solver_interface.cpp
index e9db2a10db7..8dcfa495b95 100644
--- a/intern/elbeem/intern/solver_interface.cpp
+++ b/intern/elbeem/intern/solver_interface.cpp
@@ -3,7 +3,7 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Combined 2D/3D Lattice Boltzmann Interface Class
* contains stuff to be statically compiled
@@ -35,7 +35,7 @@ LbmSolverInterface::LbmSolverInterface() :
mBoundarySouth( (CellFlagType)(CFBnd) ),mBoundaryTop( (CellFlagType)(CFBnd) ),mBoundaryBottom( (CellFlagType)(CFBnd) ),
mInitDone( false ),
mInitDensityGradient( false ),
- mpAttrs( NULL ), mpParam( NULL ), mpParticles(NULL),
+ mpSifAttrs( NULL ), mpSifSwsAttrs(NULL), mpParam( NULL ), mpParticles(NULL),
mNumParticlesLost(0),
mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0),
mDebugVelScale( 0.01 ), mNodeInfoString("+"),
@@ -50,17 +50,34 @@ LbmSolverInterface::LbmSolverInterface() :
mRefinementDesired(0),
mOutputSurfacePreview(0), mPreviewFactor(0.25),
mSmoothSurface(1.0), mSmoothNormals(1.0),
- mPartGenProb(0.),
+ mIsoSubdivs(1), mPartGenProb(0.),
mDumpVelocities(false),
mMarkedCells(), mMarkedCellIndex(0),
mDomainBound("noslip"), mDomainPartSlipValue(0.1),
- mTForceStrength(0.0), mFarFieldSize(0.), mCppfStage(0)
+ mFarFieldSize(0.),
+ mPartDropMassSub(0.1), // good default
+ mPartUsePhysModel(false),
+ mTForceStrength(0.0),
+ mCppfStage(0),
+ mDumpRawText(false),
+ mDumpRawBinary(false),
+ mDumpRawBinaryZip(true)
{
#if ELBEEM_PLUGIN==1
- if(gDebugLevel<=1) mSilent = true;
+ if(gDebugLevel<=1) setSilent(true);
#endif
mpSimTrafo = new ntlMat4Gfx(0.0);
mpSimTrafo->initId();
+
+ if(getenv("ELBEEM_RAWDEBUGDUMP")) {
+ debMsgStd("LbmSolverInterface",DM_MSG,"Using env var ELBEEM_RAWDEBUGDUMP, mDumpRawText on",2);
+ mDumpRawText = true;
+ }
+
+ if(getenv("ELBEEM_BINDEBUGDUMP")) {
+ debMsgStd("LbmSolverInterface",DM_MSG,"Using env var ELBEEM_RAWDEBUGDUMP, mDumpRawText on",2);
+ mDumpRawBinary = true;
+ }
}
LbmSolverInterface::~LbmSolverInterface()
@@ -79,8 +96,8 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
int mMaxRefine, bool parallel)
{
// fix size inits to force cubic cells and mult4 level dimensions
- const int debugGridsizeInit = 0;
- if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Called - size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" " ,10);
+ const int debugGridsizeInit = 1;
+ if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Called - size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" "<<geoStart<<","<<geoEnd ,10);
int maxGridSize = sizex; // get max size
if(sizey>maxGridSize) maxGridSize = sizey;
@@ -102,16 +119,19 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
for(int i=0; i<maskBits; i++) { sizeMask |= (1<<i); }
// at least size 4 on coarsest level
- int minSize = 2<<(maskBits+2);
+ int minSize = 4<<mMaxRefine; //(maskBits+2);
if(sizex<minSize) sizex = minSize;
if(sizey<minSize) sizey = minSize;
if(sizez<minSize) sizez = minSize;
sizeMask = ~sizeMask;
- if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" m"<<convertFlags2String(sizeMask) ,10);
+ if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" m"<<convertFlags2String(sizeMask)<<", maskBits:"<<maskBits<<",minSize:"<<minSize ,10);
sizex &= sizeMask;
sizey &= sizeMask;
sizez &= sizeMask;
+ // debug
+ int nextinc = (~sizeMask)+1;
+ debMsgStd("initGridSizes",DM_MSG,"MPTeffMLtest, curr size:"<<PRINT_VEC(sizex,sizey,sizez)<<", next size:"<<PRINT_VEC(sizex+nextinc,sizey+nextinc,sizez+nextinc) ,10);
// force geom size to match rounded/modified grid sizes
geoEnd[0] = geoStart[0] + cellSize*(LbmFloat)sizex;
@@ -119,10 +139,11 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
geoEnd[2] = geoStart[2] + cellSize*(LbmFloat)sizez;
}
-void calculateMemreqEstimate( int resx,int resy,int resz, int refine,
+void calculateMemreqEstimate( int resx,int resy,int resz,
+ int refine, float farfield,
double *reqret, string *reqstr) {
// debug estimation?
- const bool debugMemEst = false;
+ const bool debugMemEst = true;
// COMPRESSGRIDS define is not available here, make sure it matches
const bool useGridComp = true;
// make sure we can handle bid numbers here... all double
@@ -153,10 +174,17 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine,
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"refine "<<i<<", mc:"<<memCnt, 10);
}
- // isosurface memory
- memCnt += (double)( (3*sizeof(int)+sizeof(float)) * ((resx+2)*(resy+2)*(resz+2)) );
+ // isosurface memory, use orig res values
+ if(farfield>0.) {
+ memCnt += (double)( (3*sizeof(int)+sizeof(float)) * ((resx+2)*(resy+2)*(resz+2)) );
+ } else {
+ // ignore 3 int slices...
+ memCnt += (double)( ( sizeof(float)) * ((resx+2)*(resy+2)*(resz+2)) );
+ }
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"iso, mc:"<<memCnt, 10);
+ // cpdata init check missing...
+
double memd = memCnt;
char *sizeStr = "";
const double sfac = 1024.0;
@@ -187,7 +215,7 @@ void LbmSolverInterface::initDomainTrafo(float *mat) {
/*******************************************************************************/
/*! parse a boundary flag string */
CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed) {
- string val = mpAttrs->readString(name, "", source, target, needed);
+ string val = mpSifAttrs->readString(name, "", source, target, needed);
if(!strcmp(val.c_str(),"")) {
// no value given...
return CFEmpty;
@@ -212,12 +240,11 @@ CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultVal
/*******************************************************************************/
/*! parse standard attributes */
void LbmSolverInterface::parseStdAttrList() {
- if(!mpAttrs) {
- errFatal("LbmSolverInterface::parseAttrList","mpAttrs pointer not initialized!",SIMWORLD_INITERROR);
+ if(!mpSifAttrs) {
+ errFatal("LbmSolverInterface::parseAttrList","mpSifAttrs pointer not initialized!",SIMWORLD_INITERROR);
return; }
// st currently unused
- //mSurfaceTension = mpAttrs->readFloat("d_surfacetension", mSurfaceTension, "LbmSolverInterface", "mSurfaceTension", false);
mBoundaryEast = readBoundaryFlagInt("boundary_east", mBoundaryEast, "LbmSolverInterface", "mBoundaryEast", false);
mBoundaryWest = readBoundaryFlagInt("boundary_west", mBoundaryWest, "LbmSolverInterface", "mBoundaryWest", false);
mBoundaryNorth = readBoundaryFlagInt("boundary_north", mBoundaryNorth,"LbmSolverInterface", "mBoundaryNorth", false);
@@ -225,10 +252,10 @@ 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 );
+ mpSifAttrs->readMat4Gfx("domain_trafo" , (*mpSimTrafo), "ntlBlenderDumper","mpSimTrafo", false, mpSimTrafo );
LbmVec sizeVec(mSizex,mSizey,mSizez);
- sizeVec = vec2L( mpAttrs->readVec3d("size", vec2P(sizeVec), "LbmSolverInterface", "sizeVec", false) );
+ sizeVec = vec2L( mpSifAttrs->readVec3d("size", vec2P(sizeVec), "LbmSolverInterface", "sizeVec", false) );
mSizex = (int)sizeVec[0];
mSizey = (int)sizeVec[1];
mSizez = (int)sizeVec[2];
@@ -236,13 +263,13 @@ void LbmSolverInterface::parseStdAttrList() {
// test solvers might not have mpPara, though
if(mpParam) mpParam->setSize(mSizex, mSizey, mSizez );
- mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmSolverInterface", "mInitDensityGradient", false);
- mIsoValue = mpAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false );
+ mInitDensityGradient = mpSifAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmSolverInterface", "mInitDensityGradient", false);
+ mIsoValue = mpSifAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false );
- mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmSolverInterface", "mDebugVelScale", false);
- mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false );
+ mDebugVelScale = mpSifAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmSolverInterface", "mDebugVelScale", false);
+ mNodeInfoString = mpSifAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false );
- mDumpVelocities = mpAttrs->readBool("dump_velocities", mDumpVelocities, "SimulationLbm","mDumpVelocities", false );
+ mDumpVelocities = mpSifAttrs->readBool("dump_velocities", mDumpVelocities, "SimulationLbm","mDumpVelocities", false );
if(getenv("ELBEEM_DUMPVELOCITIES")) {
int get = atoi(getenv("ELBEEM_DUMPVELOCITIES"));
if((get==0)||(get==1)) {
@@ -252,14 +279,18 @@ void LbmSolverInterface::parseStdAttrList() {
}
// new test vars
- mTForceStrength = 0.; // set from test solver mpAttrs->readFloat("tforcestrength", mTForceStrength,"LbmSolverInterface", "mTForceStrength", false);
- mFarFieldSize = mpAttrs->readFloat("farfieldsize", mFarFieldSize,"LbmSolverInterface", "mFarFieldSize", false);
+ // mTForceStrength set from test solver
+ mFarFieldSize = mpSifAttrs->readFloat("farfieldsize", mFarFieldSize,"LbmSolverInterface", "mFarFieldSize", false);
// old compat
- float sizeScale = mpAttrs->readFloat("test_scale", 0.,"LbmTestdata", "mSizeScale", false);
+ float sizeScale = mpSifAttrs->readFloat("test_scale", 0.,"LbmTestdata", "mSizeScale", false);
if((mFarFieldSize<=0.)&&(sizeScale>0.)) { mFarFieldSize=sizeScale; errMsg("LbmTestdata","Warning - using mSizeScale..."); }
- mCppfStage = mpAttrs->readInt("cppfstage", mCppfStage,"LbmSolverInterface", "mCppfStage", false);
- mPartGenProb = mpAttrs->readFloat("partgenprob", mPartGenProb,"LbmFsgrSolver", "mPartGenProb", false);
+ mPartDropMassSub = mpSifAttrs->readFloat("part_dropmass", mPartDropMassSub,"LbmSolverInterface", "mPartDropMassSub", false);
+
+ mCppfStage = mpSifAttrs->readInt("cppfstage", mCppfStage,"LbmSolverInterface", "mCppfStage", false);
+ mPartGenProb = mpSifAttrs->readFloat("partgenprob", mPartGenProb,"LbmFsgrSolver", "mPartGenProb", false);
+ mPartUsePhysModel = mpSifAttrs->readBool("partusephysmodel", mPartUsePhysModel,"LbmFsgrSolver", "mPartUsePhysModel", false);
+ mIsoSubdivs = mpSifAttrs->readInt("isosubdivs", mIsoSubdivs,"LbmFsgrSolver", "mIsoSubdivs", false);
}
@@ -278,9 +309,10 @@ void LbmSolverInterface::initGeoTree() {
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,"id:"<<mLbmInitId<<" obj:"<< (*mpGiObjects)[i]->getName() <<" gid:"<<(*mpGiObjects)[i]->getGeoInitId(), 9 );
}
debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Accurate geo init: "<<mAccurateGeoinit, 9)
+ debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Objects: "<<mpGiObjects->size() ,10);
if(mpGiTree != NULL) delete mpGiTree;
char treeFlag = (1<<(this->mLbmInitId+4));
@@ -307,15 +339,22 @@ int globGeoInitDebug = 0;
int globGICPIProblems = 0;
/*****************************************************************************/
/*! check for a certain flag type at position org */
-bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance) {
+bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance, int shootDir) {
// shift ve ctors to avoid rounding errors
org += ntlVec3Gfx(0.0001);
- ntlVec3Gfx dir = ntlVec3Gfx(1.0, 0.0, 0.0);
OId = -1;
+
+ // select shooting direction
+ ntlVec3Gfx dir = ntlVec3Gfx(1., 0., 0.);
+ if(shootDir==1) dir = ntlVec3Gfx(0., 1., 0.);
+ else if(shootDir==2) dir = ntlVec3Gfx(0., 0., 1.);
+ else if(shootDir==-2) dir = ntlVec3Gfx(0., 0., -1.);
+ else if(shootDir==-1) dir = ntlVec3Gfx(0., -1., 0.);
+
ntlRay ray(org, dir, 0, 1.0, mpGlob);
- //int insCnt = 0;
bool done = false;
bool inside = false;
+
vector<int> giObjFirstHistSide;
giObjFirstHistSide.resize( mpGiObjects->size() );
for(size_t i=0; i<mGiObjInside.size(); i++) {
@@ -335,7 +374,8 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int
ntlTriangle *triIns = NULL;
distance = -1.0;
ntlVec3Gfx normal(0.0);
- mpGiTree->intersectX(ray,distance,normal, triIns, flags, true);
+ if(shootDir==0) mpGiTree->intersectX(ray,distance,normal, triIns, flags, true);
+ else mpGiTree->intersect(ray,distance,normal, triIns, flags, true);
if(triIns) {
ntlVec3Gfx norg = ray.getOrigin() + ray.getDirection()*distance;
LbmFloat orientation = dot(normal, dir);
@@ -408,7 +448,8 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int
ntlTriangle *triIns = NULL;
distance = -1.0;
ntlVec3Gfx normal(0.0);
- mpGiTree->intersectX(ray,distance,normal, triIns, flags, true);
+ if(shootDir==0) mpGiTree->intersectX(ray,distance,normal, triIns, flags, true);
+ else mpGiTree->intersect(ray,distance,normal, triIns, flags, true);
if(triIns) {
// check outside intersect
LbmFloat orientation = dot(normal, dir);
diff --git a/intern/elbeem/intern/solver_interface.h b/intern/elbeem/intern/solver_interface.h
index b95ce0358cb..e3bc06a284c 100644
--- a/intern/elbeem/intern/solver_interface.h
+++ b/intern/elbeem/intern/solver_interface.h
@@ -3,7 +3,7 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Header for Combined 2D/3D Lattice Boltzmann Interface Class
*
@@ -33,6 +33,7 @@
#include "attributes.h"
#include "isosurface.h"
class ParticleTracer;
+class ParticleObject;
// use which fp-precision for LBM? 1=float, 2=double
#ifdef PRECISION_LBM_SINGLE
@@ -135,12 +136,13 @@ typedef int BubbleId;
#define CFInvalid (CellFlagType)(1<<31)
// use 32bit flag types
-#ifdef __x86_64__
- typedef int cfINT32;
-#else
- typedef long cfINT32;
-#endif // defined (_IA64)
-#define CellFlagType cfINT32
+//#ifdef __x86_64__
+ //typedef int cfINT32;
+//#else
+ //typedef long cfINT32;
+//#endif // defined (_IA64)
+//#define CellFlagType cfINT32
+#define CellFlagType int
#define CellFlagTypeSize 4
@@ -261,7 +263,7 @@ class LbmSolverInterface
virtual int initParticles() = 0;
virtual void advanceParticles() = 0;
/*! get surface object (NULL if no surface) */
- ntlGeometryObject* getSurfaceGeoObj() { return mpIso; }
+ IsoSurface* getSurfaceGeoObj() { return mpIso; }
/*! debug object display */
virtual vector<ntlGeometryObject*> getDebugObjects() { vector<ntlGeometryObject*> empty(0); return empty; }
@@ -276,7 +278,7 @@ class LbmSolverInterface
/*! destroy tree etc. when geometry init done */
void freeGeoTree();
/*! check for a certain flag type at position org (needed for e.g. quadtree refinement) */
- bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance);
+ bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance,int shootDir=0);
bool geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir, int flags, int &OId, gfxReal &distance,
const gfxReal halfCellsize, bool &thinHit, bool recurse);
/*! set render globals, for scene/tree access */
@@ -306,9 +308,12 @@ class LbmSolverInterface
bool getAllfluid() { return mAllfluid; }
/*! set attr list pointer */
- void setAttrList(AttributeList *set) { mpAttrs = set; }
+ void setAttrList(AttributeList *set) { mpSifAttrs = set; }
/*! Returns the attribute list pointer */
- inline AttributeList *getAttributeList() { return mpAttrs; }
+ inline AttributeList *getAttributeList() { return mpSifAttrs; }
+ /*! set sws attr list pointer */
+ void setSwsAttrList(AttributeList *set) { mpSifSwsAttrs = set; }
+ inline AttributeList *getSwsAttributeList() { return mpSifSwsAttrs; }
/*! set parametrizer pointer */
inline void setParametrizer(Parametrizer *set) { mpParam = set; }
@@ -353,6 +358,8 @@ class LbmSolverInterface
//! set amount of surface/normal smoothing
inline void setSmoothing(float setss,float setns){ mSmoothSurface=setss; mSmoothNormals=setns; }
+ //! set amount of iso subdivisions
+ inline void setIsoSubdivs(int s){ mIsoSubdivs=s; }
//! set desired refinement
inline void setPreviewSize(int set){ mOutputSurfacePreview = set; }
//! set desired refinement
@@ -378,6 +385,13 @@ class LbmSolverInterface
//! set/get cp stage
inline void setCpStage(int set) { mCppfStage = set; }
inline int getCpStage() const { return mCppfStage; }
+ //! set/get dump modes
+ inline void setDumpRawText(bool set) { mDumpRawText = set; }
+ inline bool getDumpRawText() const { return mDumpRawText; }
+ inline void setDumpRawBinary(bool set) { mDumpRawBinary = set; }
+ inline bool getDumpRawBinary() const { return mDumpRawBinary; }
+ inline void setDumpRawBinaryZip(bool set) { mDumpRawBinaryZip = set; }
+ inline bool getDumpRawBinaryZip() const { return mDumpRawBinaryZip; }
// cell iterator interface
@@ -468,8 +482,9 @@ class LbmSolverInterface
/*! init density gradient? */
bool mInitDensityGradient;
- /*! pointer to the attribute list */
- AttributeList *mpAttrs;
+ /*! pointer to the attribute list, only pointer to obj attrs */
+ AttributeList *mpSifAttrs;
+ AttributeList *mpSifSwsAttrs;
/*! get parameters from this parametrize in finishInit */
Parametrizer *mpParam;
@@ -534,9 +549,11 @@ class LbmSolverInterface
int mOutputSurfacePreview;
LbmFloat mPreviewFactor;
- /* enable surface and normals smoothing? */
+ /*! enable surface and normals smoothing? */
float mSmoothSurface;
float mSmoothNormals;
+ /*! isosurface subdivisions */
+ int mIsoSubdivs;
//! particle generation probability
LbmFloat mPartGenProb;
@@ -553,14 +570,22 @@ class LbmSolverInterface
//! part slip value for domain
LbmFloat mDomainPartSlipValue;
+ // size of far field area
+ LbmFloat mFarFieldSize;
+ // amount of drop mass to subtract
+ LbmFloat mPartDropMassSub;
+ // use physical drop model for particles?
+ bool mPartUsePhysModel;
+
//! test vars
// strength of applied force
LbmFloat mTForceStrength;
- //
- LbmFloat mFarFieldSize;
- //
int mCppfStage;
+ //! dumping modes
+ bool mDumpRawText;
+ bool mDumpRawBinary;
+ bool mDumpRawBinaryZip;
};
@@ -569,7 +594,7 @@ void initGridSizes(int &mSizex, int &mSizey, int &mSizez,
ntlVec3Gfx &mvGeoStart, ntlVec3Gfx &mvGeoEnd,
int mMaxRefine, bool parallel);
void calculateMemreqEstimate(int resx,int resy,int resz, int refine,
- double *reqret, string *reqstr);
+ float farfieldsize, double *reqret, string *reqstr);
//! helper function to convert flag to string (for debuggin)
string convertCellFlagType2String( CellFlagType flag );
diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp
index 964192420e4..bced75ab444 100644
--- a/intern/elbeem/intern/solver_main.cpp
+++ b/intern/elbeem/intern/solver_main.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004,2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Standard LBM Factory implementation
*
@@ -20,65 +20,30 @@ double globdfcnt;
double globdfavg[19];
double globdfmax[19];
double globdfmin[19];
+extern int glob_mpindex,glob_mpnum;
+extern bool globOutstrForce;
+// simulation object interface
void LbmFsgrSolver::step() {
- initLevelOmegas();
- stepMain();
-
- // intlbm test
- if(0) {
- if(this->mStepCnt<5) {
- // init
- globdfcnt=0.;
- FORDF0{
- globdfavg[l] = 0.;
- globdfmax[l] = -1000.; //this->dfEquil[l];
- globdfmin[l] = 1000.; // this->dfEquil[l];
- }
- } else {
-
- int workSet = mLevel[mMaxRefine].setCurr;
- for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) {
- for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) {
- for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) {
- //float val = 0.;
- if(RFLAG(mMaxRefine, i,j,k, workSet) & CFFluid) {
- //val = QCELL(mMaxRefine,i,j,k, workSet,dFfrac);
- FORDF0{
- const double df = (double)QCELL(mMaxRefine,i,j,k, workSet,l);
- globdfavg[l] += df;
- if(df>globdfmax[l]) globdfmax[l] = df;
- //if(df<=0.01) { errMsg("GLOBDFERR"," at "<<PRINT_IJK<<" "<<l); }
- if(df<globdfmin[l]) globdfmin[l] = df;
- //errMsg("GLOBDFERR"," at "<<PRINT_IJK<<" "<<l<<" "<<df<<" "<<globdfmin[l]);
- }
- globdfcnt+=1.;
- }
- }
- }
- }
- if(this->mStepCnt%10==0) {
- FORDF0{ errMsg("GLOBDF","l="<<l<<" avg="<<(globdfavg[l]/globdfcnt)<<" max="<<globdfmax[l]<<" min="<<globdfmin[l]<<" "<<globdfcnt); }
- }
-
- }
- }
- // intlbm test */
+ stepMain();
}
-void LbmFsgrSolver::stepMain()
-{
- this->markedClearList(); // DMC clearMarkedCellsList
+// lbm main step
+void messageOutputForce(string from);
+void LbmFsgrSolver::stepMain() {
+ myTime_t timestart = getTime();
+
+ initLevelOmegas();
+ markedClearList(); // DMC clearMarkedCellsList
// safety check, counter reset
- this->mNumUsedCells = 0;
+ mNumUsedCells = 0;
mNumInterdCells = 0;
mNumInvIfCells = 0;
- //debugOutNnl("LbmFsgrSolver::step : "<<this->mStepCnt, 10);
- if(!this->mSilent){ debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<<this->mStepCnt<<" t:"<<mSimulationTime, 10); }
- //debMsgDirect( "LbmFsgrSolver::step : "<<this->mStepCnt<<" ");
- myTime_t timestart = getTime();
+ //debugOutNnl("LbmFsgrSolver::step : "<<mStepCnt, 10);
+ if(!mSilent){ debMsgStd("LbmFsgrSolver::step", DM_MSG, mName<<" cnt:"<<mStepCnt<<" t:"<<mSimulationTime, 10); }
+ //debMsgDirect( "LbmFsgrSolver::step : "<<mStepCnt<<" ");
//myTime_t timestart = 0;
//if(mStartSymm) { checkSymmetry("step1"); } // DEBUG
@@ -93,15 +58,15 @@ void LbmFsgrSolver::stepMain()
// important - keep for tadap
LbmFloat lastMass = mCurrentMass;
- mCurrentMass = this->mFixMass; // reset here for next step
+ mCurrentMass = mFixMass; // reset here for next step
mCurrentVolume = 0.0;
//change to single step advance!
int levsteps = 0;
- int dsbits = this->mStepCnt ^ (this->mStepCnt-1);
- //errMsg("S"," step:"<<this->mStepCnt<<" s-1:"<<(this->mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits));
+ int dsbits = mStepCnt ^ (mStepCnt-1);
+ //errMsg("S"," step:"<<mStepCnt<<" s-1:"<<(mStepCnt-1)<<" xf:"<<convertCellFlagType2String(dsbits));
for(int lev=0; lev<=mMaxRefine; lev++) {
- //if(! (this->mStepCnt&(1<<lev)) ) {
+ //if(! (mStepCnt&(1<<lev)) ) {
if( dsbits & (1<<(mMaxRefine-lev)) ) {
//errMsg("S"," l"<<lev);
@@ -124,50 +89,44 @@ void LbmFsgrSolver::stepMain()
}
// prepare next step
- this->mStepCnt++;
+ mStepCnt++;
// some dbugging output follows
// calculate MLSUPS
myTime_t timeend = getTime();
- this->mNumUsedCells += mNumInterdCells; // count both types for MLSUPS
- mAvgNumUsedCells += this->mNumUsedCells;
- this->mMLSUPS = (this->mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000);
- if(this->mMLSUPS>10000){ this->mMLSUPS = -1; }
- else { mAvgMLSUPS += this->mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups
+ mNumUsedCells += mNumInterdCells; // count both types for MLSUPS
+ mAvgNumUsedCells += mNumUsedCells;
+ mMLSUPS = ((double)mNumUsedCells / ((timeend-timestart)/(double)1000.0) ) / (1000000.0);
+ if(mMLSUPS>10000){ mMLSUPS = -1; }
+ //else { mAvgMLSUPS += mMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups
LbmFloat totMLSUPS = ( ((mLevel[mMaxRefine].lSizex-2)*(mLevel[mMaxRefine].lSizey-2)*(getForZMax1(mMaxRefine)-getForZMin1())) / ((timeend-timestart)/(double)1000.0) ) / (1000000);
if(totMLSUPS>10000) totMLSUPS = -1;
mNumInvIfTotal += mNumInvIfCells; // debug
// do some formatting
- if(!this->mSilent){
- string sepStr(""); // DEBUG
- int avgcls = (int)(mAvgNumUsedCells/(LONGINT)this->mStepCnt);
- debMsgStd("LbmFsgrSolver::step", DM_MSG, this->mName<<" cnt:"<<this->mStepCnt<<" t:"<<mSimulationTime<<
- //debMsgDirect(
- " mlsups(curr:"<<this->mMLSUPS<<
- " avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<< sepStr<<
- " totcls:"<<(this->mNumUsedCells)<< sepStr<<
- " avgcls:"<< avgcls<< sepStr<<
- " intd:"<<mNumInterdCells<< sepStr<<
- " invif:"<<mNumInvIfCells<< sepStr<<
- " invift:"<<mNumInvIfTotal<< sepStr<<
- " fsgrcs:"<<mNumFsgrChanges<< sepStr<<
- " filled:"<<this->mNumFilledCells<<", emptied:"<<this->mNumEmptiedCells<< sepStr<<
- " mMxv:"<<mMxvx<<","<<mMxvy<<","<<mMxvz<<", tscnts:"<<mTimeSwitchCounts<< sepStr<<
- " RWmxv:"<<ntlVec3Gfx(mMxvx,mMxvy,mMxvz)*(mLevel[mMaxRefine].simCellSize / mLevel[mMaxRefine].timestep)<<" "<< /* realworld vel output */
- " probs:"<<mNumProblems<< sepStr<<
- " simt:"<<mSimulationTime<< sepStr<<
- " for '"<<this->mName<<"' " , 10);
+ if(!mSilent){
+ int avgcls = (int)(mAvgNumUsedCells/(LONGINT)mStepCnt);
+ debMsgStd("LbmFsgrSolver::step", DM_MSG, mName<<" cnt:"<<mStepCnt<<" t:"<<mSimulationTime<<
+ " cur-mlsups:"<<mMLSUPS<< //" avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "<<
+ " totcls:"<<mNumUsedCells<< " avgcls:"<< avgcls<<
+ " intd:"<<mNumInterdCells<< " invif:"<<mNumInvIfCells<<
+ " invift:"<<mNumInvIfTotal<< " fsgrcs:"<<mNumFsgrChanges<<
+ " filled:"<<mNumFilledCells<<", emptied:"<<mNumEmptiedCells<<
+ " mMxv:"<<PRINT_VEC(mMxvx,mMxvy,mMxvz)<<", tscnts:"<<mTimeSwitchCounts<<
+ //" RWmxv:"<<ntlVec3Gfx(mMxvx,mMxvy,mMxvz)*(mLevel[mMaxRefine].simCellSize / mLevel[mMaxRefine].timestep)<<" "<< /* realworld vel output */
+ " probs:"<<mNumProblems<< " simt:"<<mSimulationTime<<
+ " took:"<< getTimeString(timeend-timestart)<<
+ " for '"<<mName<<"' " , 10);
} else { debMsgDirect("."); }
- if(this->mStepCnt==1) {
- mMinNoCells = mMaxNoCells = this->mNumUsedCells;
+ if(mStepCnt==1) {
+ mMinNoCells = mMaxNoCells = mNumUsedCells;
} else {
- if(this->mNumUsedCells>mMaxNoCells) mMaxNoCells = this->mNumUsedCells;
- if(this->mNumUsedCells<mMinNoCells) mMinNoCells = this->mNumUsedCells;
+ if(mNumUsedCells>mMaxNoCells) mMaxNoCells = mNumUsedCells;
+ if(mNumUsedCells<mMinNoCells) mMinNoCells = mNumUsedCells;
}
// mass scale test
@@ -191,7 +150,7 @@ void LbmFsgrSolver::stepMain()
errMsg("MDTDD","\n\n");
errMsg("MDTDD","FORCE RESCALE MASS! "
<<"ini:"<<mInitialMass<<", cur:"<<mCurrentMass<<", f="<<ABS(mInitialMass/mCurrentMass)
- <<" step:"<<this->mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" "
+ <<" step:"<<mStepCnt<<" levstep:"<<mLevel[0].lsteps<<" msc:"<<mscount<<" "
);
errMsg("MDTDD","\n\n");
@@ -233,8 +192,8 @@ void LbmFsgrSolver::stepMain()
}
#if LBM_INCLUDE_TESTSOLVERS==1
- if((mUseTestdata)&&(this->mInitDone)) { handleTestdata(); }
- testXchng();
+ if((mUseTestdata)&&(mInitDone)) { handleTestdata(); }
+ mrExchange();
#endif
// advance positions with current grid
@@ -258,18 +217,28 @@ void LbmFsgrSolver::stepMain()
#endif // WIN32
// output total step time
- timeend = getTime();
+ myTime_t timeend2 = getTime();
double mdelta = (lastMass-mCurrentMass);
if(ABS(mdelta)<1e-12) mdelta=0.;
- debMsgStd("LbmFsgrSolver::stepMain",DM_MSG,"step:"<<this->mStepCnt
- <<": dccd="<< mCurrentMass
- <<",d"<<mdelta
- <<",ds"<<(mCurrentMass-mObjectMassMovnd[1])
- <<"/"<<mCurrentVolume<<"(fix="<<this->mFixMass<<",ini="<<mInitialMass<<"), "
- <<" totst:"<<getTimeString(timeend-timestart), 3);
+ double effMLSUPS = ((double)mNumUsedCells / ((timeend2-timestart)/(double)1000.0) ) / (1000000.0);
+ if(mInitDone) {
+ if(effMLSUPS>10000){ effMLSUPS = -1; }
+ else { mAvgMLSUPS += effMLSUPS; mAvgMLSUPSCnt += 1.0; } // track average mlsups
+ }
+
+ debMsgStd("LbmFsgrSolver::stepMain", DM_MSG, "mmpid:"<<glob_mpindex<<" step:"<<mStepCnt
+ <<" dccd="<< mCurrentMass
+ //<<",d"<<mdelta
+ //<<",ds"<<(mCurrentMass-mObjectMassMovnd[1])
+ //<<"/"<<mCurrentVolume<<"(fix="<<mFixMass<<",ini="<<mInitialMass<<"), "
+ <<" effMLSUPS=("<< effMLSUPS
+ <<",avg:"<<(mAvgMLSUPS/mAvgMLSUPSCnt)<<"), "
+ <<" took totst:"<< getTimeString(timeend2-timestart), 3);
// nicer output
- debMsgDirect(std::endl);
+ //debMsgDirect(std::endl);
+ // */
+ messageOutputForce("");
//#endif // ELBEEM_PLUGIN!=1
}
@@ -291,15 +260,15 @@ void LbmFsgrSolver::fineAdvance()
// warning assume -Y gravity...
mFVHeight = mCurrentMass*mFVArea/((LbmFloat)(mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizez));
if(mFVHeight<1.0) mFVHeight = 1.0;
- this->mpParam->setFluidVolumeHeight(mFVHeight);
+ mpParam->setFluidVolumeHeight(mFVHeight);
}
// advance time before timestep change
- mSimulationTime += this->mpParam->getTimestep();
+ mSimulationTime += mpParam->getTimestep();
// time adaptivity
- this->mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) );
+ mpParam->setSimulationMaxSpeed( sqrt(mMaxVlen / 1.5) );
//if(mStartSymm) { checkSymmetry("step2"); } // DEBUG
- if(!this->mSilent){ debMsgStd("fineAdvance",DM_NOTIFY," stepped from "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps), 3 ); }
+ if(!mSilent){ debMsgStd("fineAdvance",DM_NOTIFY," stepped from "<<mLevel[mMaxRefine].setCurr<<" to "<<mLevel[mMaxRefine].setOther<<" step"<< (mLevel[mMaxRefine].lsteps), 3 ); }
// update other set
mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr;
@@ -308,7 +277,7 @@ void LbmFsgrSolver::fineAdvance()
// flag init... (work on current set, to simplify flag checks)
reinitFlags( mLevel[mMaxRefine].setCurr );
- if(!this->mSilent){ debMsgStd("fineAdvance",DM_NOTIFY," flags reinit on set "<< mLevel[mMaxRefine].setCurr, 3 ); }
+ if(!mSilent){ debMsgStd("fineAdvance",DM_NOTIFY," flags reinit on set "<< mLevel[mMaxRefine].setCurr, 3 ); }
// DEBUG VEL CHECK
if(0) {
@@ -370,10 +339,10 @@ void LbmFsgrSolver::fineAdvance()
#define RWVEL_WINDTHRESH (RWVEL_THRESH*0.5)
#if LBMDIM==3
- // normal
-#define SLOWDOWNREGION (this->mSizez/4)
+// normal
+#define SLOWDOWNREGION (mSizez/4)
#else // LBMDIM==2
- // off
+// off
#define SLOWDOWNREGION 10
#endif // LBMDIM==2
#define P_LCSMQO 0.01
@@ -397,7 +366,7 @@ LbmFsgrSolver::mainLoop(int lev)
# if LBM_INCLUDE_TESTSOLVERS==1
// 3d region off... quit
- if((mUseTestdata)&&(mpTest->mDebugvalue1>0.0)) { return; }
+ if((mUseTestdata)&&(mpTest->mFarfMode>0)) { return; }
# endif // ELBEEM_PLUGIN!=1
// main loop region
@@ -448,16 +417,16 @@ LbmFsgrSolver::mainLoop(int lev)
errMsg("LbmFsgrSolver::mainLoop","Err flagp "<<PRINT_IJK<<"="<<
RFLAG(lev, i,j,k,mLevel[lev].setCurr)<<","<<RFLAG(lev, i,j,k,mLevel[lev].setOther)<<" but is "<<
(*pFlagSrc)<<","<<(*pFlagDst) <<", pointers "<<
- (int)(&RFLAG(lev, i,j,k,mLevel[lev].setCurr))<<","<<(int)(&RFLAG(lev, i,j,k,mLevel[lev].setOther))<<" but is "<<
- (int)(pFlagSrc)<<","<<(int)(pFlagDst)<<" "
+ (long)(&RFLAG(lev, i,j,k,mLevel[lev].setCurr))<<","<<(long)(&RFLAG(lev, i,j,k,mLevel[lev].setOther))<<" but is "<<
+ (long)(pFlagSrc)<<","<<(long)(pFlagDst)<<" "
);
CAUSE_PANIC;
}
if( (&QCELL(lev, i,j,k,mLevel[lev].setCurr,0) != ccel) ||
(&QCELL(lev, i,j,k,mLevel[lev].setOther,0) != tcel) ) {
errMsg("LbmFsgrSolver::mainLoop","Err cellp "<<PRINT_IJK<<"="<<
- (int)(&QCELL(lev, i,j,k,mLevel[lev].setCurr,0))<<","<<(int)(&QCELL(lev, i,j,k,mLevel[lev].setOther,0))<<" but is "<<
- (int)(ccel)<<","<<(int)(tcel)<<" "
+ (long)(&QCELL(lev, i,j,k,mLevel[lev].setCurr,0))<<","<<(long)(&QCELL(lev, i,j,k,mLevel[lev].setOther,0))<<" but is "<<
+ (long)(ccel)<<","<<(long)(tcel)<<" "
);
CAUSE_PANIC;
}
@@ -466,7 +435,7 @@ LbmFsgrSolver::mainLoop(int lev)
// old INTCFCOARSETEST==1
if( (oldFlag & (CFGrFromCoarse)) ) {
- if(( this->mStepCnt & (1<<(mMaxRefine-lev)) ) ==1) {
+ if(( 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);
@@ -731,27 +700,14 @@ LbmFsgrSolver::mainLoop(int lev)
} // l
// normal interface, no if empty/fluid
- LbmFloat nv1,nv2;
- LbmFloat nx,ny,nz;
-
- if(nbflag[dE] &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); } else nv1 = 0.0;
- if(nbflag[dW] &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); } else nv2 = 0.0;
- nx = 0.5* (nv2-nv1);
- if(nbflag[dN] &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[lev].lOffsx*QCELLSTEP)),dFfrac); } else nv1 = 0.0;
- if(nbflag[dS] &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[lev].lOffsx*QCELLSTEP)),dFfrac); } else nv2 = 0.0;
- ny = 0.5* (nv2-nv1);
-# if LBMDIM==3
- if(nbflag[dT] &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[lev].lOffsy*QCELLSTEP)),dFfrac); } else nv1 = 0.0;
- if(nbflag[dB] &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[lev].lOffsy*QCELLSTEP)),dFfrac); } else nv2 = 0.0;
- nz = 0.5* (nv2-nv1);
-# else // LBMDIM==3
- nz = 0.0;
-# endif // LBMDIM==3
-
- if( (ABS(nx)+ABS(ny)+ABS(nz)) > LBM_EPSILON) {
+ // computenormal
+ LbmFloat surfaceNormal[3];
+ computeFluidSurfaceNormal(ccel,pFlagSrc, surfaceNormal);
+
+ if( (ABS(surfaceNormal[0])+ABS(surfaceNormal[1])+ABS(surfaceNormal[2])) > LBM_EPSILON) {
// normal ok and usable...
FORDF1 {
- if( (this->dfDvecX[l]*nx + this->dfDvecY[l]*ny + this->dfDvecZ[l]*nz) // dot Dvec,norml
+ if( (this->dfDvecX[l]*surfaceNormal[0] + this->dfDvecY[l]*surfaceNormal[1] + this->dfDvecZ[l]*surfaceNormal[2]) // dot Dvec,norml
> LBM_EPSILON) {
recons[l] = 2;
numRecons++;
@@ -781,7 +737,8 @@ LbmFsgrSolver::mainLoop(int lev)
- MYDF( l );
}
}
- usqr = 1.5 * (oldUx*oldUx + oldUy*oldUy + oldUz*oldUz); // needed later on
+ ux=oldUx, uy=oldUy, uz=oldUz; // no local vars, only for usqr
+ usqr = 1.5 * (ux*ux + uy*uy + uz*uz); // needed later on
# else // OPT3D==0
oldRho = + RAC(ccel,dC) + RAC(ccel,dN )
+ RAC(ccel,dS ) + RAC(ccel,dE )
@@ -864,11 +821,15 @@ LbmFsgrSolver::mainLoop(int lev)
}
FORDF0 { RAC(tcel, l) = this->getCollideEq(l, rho,ux,uy,uz); }
} else {// NEWSURFT */
+ if(usqr>0.3*0.3) {
+ // force reset! , warning causes distortions...
+ FORDF0 { RAC(tcel, l) = this->getCollideEq(l, rho,0.,0.,0.); }
+ } else {
// normal collide
// mass streaming done... do normal collide
LbmVec grav = mLevel[lev].gravity*mass;
DEFAULT_COLLIDEG(grav);
- PERFORM_USQRMAXCHECK;
+ PERFORM_USQRMAXCHECK; }
// rho init from default collide necessary for fill/empty check below
} // test
}
@@ -876,87 +837,111 @@ LbmFsgrSolver::mainLoop(int lev)
// testing..., particle generation
// also check oldFlag for CFNoNbFluid, test
// for inflow no pargen test // NOBUBBB!
- if((this->mInitDone) //&&(mUseTestdata)
- //&& (!((oldFlag|newFlag)&CFNoNbEmpty))
- && (!((oldFlag|newFlag)&CFNoDelete))
- && (this->mPartGenProb>0.0)) {
+ if((mInitDone)
+ // dont allow new if cells, or submerged ones
+ && (!((oldFlag|newFlag)& (CFNoDelete|CFNoNbEmpty) ))
+ // dont try to subtract from empty cells
+ && (mass>0.) && (mPartGenProb>0.0)) {
bool doAdd = true;
bool bndOk=true;
- if( (i<cutMin)||(i>this->mSizex-cutMin)||
- (j<cutMin)||(j>this->mSizey-cutMin)||
- (k<cutMin)||(k>this->mSizez-cutMin) ) { bndOk=false; }
+ if( (i<cutMin)||(i>mSizex-cutMin)||
+ (j<cutMin)||(j>mSizey-cutMin)||
+ (k<cutMin)||(k>mSizez-cutMin) ) { bndOk=false; }
if(!bndOk) doAdd=false;
- LbmFloat realWorldFac = (mLevel[lev].simCellSize / mLevel[lev].timestep);
- LbmFloat rux = (ux * realWorldFac);
- LbmFloat ruy = (uy * realWorldFac);
- LbmFloat ruz = (uz * realWorldFac);
- LbmFloat rl = norm(ntlVec3Gfx(rux,ruy,ruz));
- // WHMOD
-
LbmFloat prob = (rand()/(RAND_MAX+1.0));
- LbmFloat basethresh = this->mPartGenProb*lcsmqo*rl;
-
- // reduce probability in outer region?
- 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.;
-
- //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...
- }
-
- // "wind" disturbance
- // use realworld relative velocity here instead?
- if( (doAdd &&
- ((rl>RWVEL_WINDTHRESH) && (lcsmqo<P_LCSMQO)) )// normal checks
- ||(k>this->mSizez-SLOWDOWNREGION) ) {
- LbmFloat nuz = uz;
- if(k>this->mSizez-SLOWDOWNREGION) {
- // special case
- LbmFloat zfac = (LbmFloat)( k-(this->mSizez-SLOWDOWNREGION) );
- zfac /= (LbmFloat)(SLOWDOWNREGION);
- nuz += (1.0) * zfac; // check max speed? OFF?
- //errMsg("TOPT"," at "<<PRINT_IJK<<" zfac"<<zfac);
+ LbmFloat basethresh = mPartGenProb*lcsmqo*(LbmFloat)(mSizez+mSizey+mSizex)*0.5*0.333;
+
+ // physical drop model
+ if(mPartUsePhysModel) {
+ LbmFloat realWorldFac = (mLevel[lev].simCellSize / mLevel[lev].timestep);
+ LbmFloat rux = (ux * realWorldFac);
+ LbmFloat ruy = (uy * realWorldFac);
+ LbmFloat ruz = (uz * realWorldFac);
+ LbmFloat rl = norm(ntlVec3Gfx(rux,ruy,ruz));
+ basethresh *= rl;
+
+ // reduce probability in outer region?
+ 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.;
+
+ //if( (prob< (basethresh*rl)) && (lcsmqo>0.0095) && (rl>RWVEL_THRESH) ) {
+ if( (prob< (basethresh*rl*pifac*pjfac)) && (lcsmqo>0.0095) && (rl>RWVEL_THRESH) ) {
+ // add
} else {
- // normal probability
- //? LbmFloat fac = P_LCSMQO-lcsmqo;
- //? jdf *= fac;
- }
- FORDF1 {
- const LbmFloat jdf = 0.05 * (rand()/(RAND_MAX+1.0));
- // TODO use wind velocity?
- if(jdf>0.025) {
- const LbmFloat add = this->dfLength[l]*(-ux*this->dfDvecX[l]-uy*this->dfDvecY[l]-nuz*this->dfDvecZ[l])*jdf;
- RAC(tcel,l) += add; }
+ doAdd = false; // dont...
}
- //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<norm(LbmVec(ux,uy,nuz))<<" rwv"<<norm(LbmVec(rux,ruy,ruz)) );
- } // wind disturbance
+ // "wind" disturbance
+ // use realworld relative velocity here instead?
+ if( (doAdd &&
+ ((rl>RWVEL_WINDTHRESH) && (lcsmqo<P_LCSMQO)) )// normal checks
+ ||(k>mSizez-SLOWDOWNREGION) ) {
+ LbmFloat nuz = uz;
+ if(k>mSizez-SLOWDOWNREGION) {
+ // special case
+ LbmFloat zfac = (LbmFloat)( k-(mSizez-SLOWDOWNREGION) );
+ zfac /= (LbmFloat)(SLOWDOWNREGION);
+ nuz += (1.0) * zfac; // check max speed? OFF?
+ //errMsg("TOPT"," at "<<PRINT_IJK<<" zfac"<<zfac);
+ } else {
+ // normal probability
+ //? LbmFloat fac = P_LCSMQO-lcsmqo;
+ //? jdf *= fac;
+ }
+ FORDF1 {
+ const LbmFloat jdf = 0.05 * (rand()/(RAND_MAX+1.0));
+ // TODO use wind velocity?
+ if(jdf>0.025) {
+ const LbmFloat add = this->dfLength[l]*(-ux*this->dfDvecX[l]-uy*this->dfDvecY[l]-nuz*this->dfDvecZ[l])*jdf;
+ RAC(tcel,l) += add; }
+ }
+ //errMsg("TOPDOWNCORR"," jdf:"<<jdf<<" rl"<<rl<<" vel "<<norm(LbmVec(ux,uy,nuz))<<" rwv"<<norm(LbmVec(rux,ruy,ruz)) );
+ } // wind disturbance
+ } // mPartUsePhysModel
+ else {
+ // empirical model
+ //if((prob<basethresh) && (lcsmqo>0.0095)) { // add
+ if((prob<basethresh) && (lcsmqo>0.012)) { // add
+ } else { doAdd = false; }// dont...
+ }
+
+
+ // remove noise
if(usqr<0.0001) doAdd=false; // TODO check!?
- // if outside, and 20% above sea level, delete, TODO really check level?
- //if((!bndOk)&&((LbmFloat)k>pTest->mFluidHeight*1.5)) { doAdd=true; } // FORCEDISSOLVE
- //if(this->mStepCnt>700) errMsg("DFJITT"," at "<<PRINT_IJK<<"rwl:"<<rl<<" usqr:"<<usqr <<" qo:"<<lcsmqo<<" add="<<doAdd );
-
- if( (doAdd) ) { // ADD DROP
- LbmFloat len = norm(LbmVec(ux,uy,uz));
- // WHMOD
- //for(int s=0; s<10; s++) { // multiple parts
+
+ // dont try to subtract from empty cells
+ // ensure cell has enough mass for new drop
+ LbmFloat newPartsize = 1.0;
+ if(mPartUsePhysModel) {
+ // 1-10
+ newPartsize += 9.0* (rand()/(RAND_MAX+1.0));
+ } else {
+ // 1-5, overall size has to be less than
+ // .62 (ca. 0.5) to make drops significantly smaller
+ // than a full cell!
+ newPartsize += 4.0* (rand()/(RAND_MAX+1.0));
+ }
+ LbmFloat dropmass = ParticleObject::getMass(mPartDropMassSub*newPartsize); //PARTMASS(mPartDropMassSub*newPartsize); // mass: 4/3 pi r^3 rho
+ while(dropmass>mass) {
+ newPartsize -= 0.2;
+ dropmass = ParticleObject::getMass(mPartDropMassSub*newPartsize);
+ }
+ if(newPartsize<=1.) doAdd=false;
+
+ if( (doAdd) ) { // init new particle
for(int s=0; s<1; s++) { // one part!
- //LbmFloat prob = this->mPartGenProb * 0.02* (rand()/(RAND_MAX+1.0));
- const LbmFloat posjitter = 1.0;
+ const LbmFloat posjitter = 0.05;
const LbmFloat posjitteroffs = posjitter*-0.5;
LbmFloat jpx = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0));
LbmFloat jpy = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0));
LbmFloat jpz = posjitteroffs+ posjitter* (rand()/(RAND_MAX+1.0));
- const LbmFloat jitterstr = 0.1;
+ const LbmFloat jitterstr = 1.0;
const LbmFloat jitteroffs = jitterstr*-0.5;
LbmFloat jx = jitteroffs+ jitterstr* (rand()/(RAND_MAX+1.0));
LbmFloat jy = jitteroffs+ jitterstr* (rand()/(RAND_MAX+1.0));
@@ -964,40 +949,46 @@ LbmFsgrSolver::mainLoop(int lev)
// average normal & velocity
// -> mostly along velocity dir, many into surface
- LbmVec pv = (LbmVec(nx+jx,ny+jy,nz+jz)*0.75 + getNormalized(LbmVec(ux,uy,uz)) )*0.35;
- normalize(pv);
-
- LbmFloat srci = i+0.5+jpx; // TEST? + (pv[0]*1.41);
- LbmFloat srcj = j+0.5+jpy; // TEST? + (pv[1]*1.41);
- LbmFloat srck = k+0.5+jpz; // TEST? + (pv[2]*1.41);
+ // fluid velocity (not normalized!)
+ LbmVec flvelVel = LbmVec(ux,uy,uz);
+ LbmFloat flvelLen = norm(flvelVel);
+ // surface normal
+ LbmVec normVel = LbmVec(surfaceNormal[0],surfaceNormal[1],surfaceNormal[2]);
+ normalize(normVel);
+ LbmFloat normScale = (0.01+flvelLen);
+ // jitter vector, 0.2 * flvel
+ LbmVec jittVel = LbmVec(jx,jy,jz)*(0.05+flvelLen)*0.1;
+ // weighten velocities
+ const LbmFloat flvelWeight = 0.9;
+ LbmVec newpartVel = normVel*normScale*(1.-flvelWeight) + flvelVel*(flvelWeight) + jittVel;
+
+ // offset towards surface (hide popping)
+ jpx += -normVel[0]*0.4;
+ jpy += -normVel[1]*0.4;
+ jpz += -normVel[2]*0.4;
+
+ LbmFloat srci=i+0.5+jpx, srcj=j+0.5+jpy, srck=k+0.5+jpz;
int type=0;
- //if((s%3)!=2) {} else { type=PART_FLOAT; }
- //type = PART_DROP;
- type = PART_INTER;
- // drop
- /*srci += (pv[0]*1.41);
- srcj += (pv[1]*1.41);
- srck += (pv[2]*1.41);
- if(!(RFLAG(lev, (int)(srci),(int)(srcj),(int)(srck),SRCS(lev)) &CFEmpty)) continue; // only add in good direction */
-
- pv *= len;
- LbmFloat size = 1.0+ 9.0* (rand()/(RAND_MAX+1.0));
-
- mpParticles->addParticle(srci, srcj, srck); //i+0.5+jpx,j+0.5+jpy,k+0.5+jpz);
- mpParticles->getLast()->setVel(pv[0],pv[1],pv[2]);
- //? mpParticles->getLast()->advanceVel(); // advance a bit outwards
- mpParticles->getLast()->setStatus(PART_IN);
- mpParticles->getLast()->setType(type);
- //if((s%3)==2) mpParticles->getLast()->setType(PART_FLOAT);
- mpParticles->getLast()->setSize(size);
- //errMsg("NEWPART"," at "<<PRINT_IJK<<" u="<<norm(LbmVec(ux,uy,uz)) <<" RWu="<<norm(LbmVec(rux,ruy,ruz))<<" add"<<doAdd<<" pvel="<<norm(pv) );
- //mass -= size*0.001; // NTEST!
- mass -= size*0.0020; // NTEST!
+ type = PART_DROP;
+
# if LBMDIM==2
- mpParticles->getLast()->setVel(pv[0],pv[1],0.0);
- mpParticles->getLast()->setPos(ntlVec3Gfx(srci,srcj,0.5));
+ newpartVel[2]=0.; srck=0.5;
# endif // LBMDIM==2
- //errMsg("PIT","NEW pit"<<mpParticles->getLast()->getId()<<" pos:"<< mpParticles->getLast()->getPos()<<" status:"<<convertFlags2String(mpParticles->getLast()->getFlags())<<" vel:"<< mpParticles->getLast()->getVel() );
+ // subtract drop mass
+ mass -= dropmass;
+ // init new particle
+ {
+ ParticleObject np( ntlVec3Gfx(srci,srcj,srck) );
+ np.setVel(newpartVel[0],newpartVel[1],newpartVel[2]);
+ np.setStatus(PART_IN);
+ np.setType(type);
+ //if((s%3)==2) np.setType(PART_FLOAT);
+ np.setSize(newPartsize);
+ //errMsg("NEWPART"," at "<<PRINT_IJK<<" u="<<norm(LbmVec(ux,uy,uz)) <<" add"<<doAdd<<" pvel="<<norm(newpartVel)<<" size="<<newPartsize );
+ //errMsg("NEWPT","u="<<newpartVel<<" norm="<<normVel<<" flvel="<<flvelVel<<" jitt="<<jittVel );
+ FSGR_ADDPART(np);
+ } // new part
+ //errMsg("PIT","NEW pit"<<np.getId()<<" pos:"<< np.getPos()<<" status:"<<convertFlags2String(np.getFlags())<<" vel:"<< np.getVel() );
} // multiple parts
} // doAdd
} // */
@@ -1047,7 +1038,7 @@ LbmFsgrSolver::mainLoop(int lev)
if(!(newFlag&CFNoBndFluid)) filledp.flag |= 1; // NEWSURFT
filledp.x = i; filledp.y = j; filledp.z = k;
LIST_FULL(filledp);
- //this->mNumFilledCells++; // DEBUG
+ //mNumFilledCells++; // DEBUG
calcCellsFilled++;
}
else if(ifemptied) {
@@ -1055,7 +1046,7 @@ LbmFsgrSolver::mainLoop(int lev)
if(!(newFlag&CFNoBndFluid)) emptyp.flag |= 1; // NEWSURFT
emptyp.x = i; emptyp.y = j; emptyp.z = k;
LIST_EMPTY(emptyp);
- //this->mNumEmptiedCells++; // DEBUG
+ //mNumEmptiedCells++; // DEBUG
calcCellsEmptied++;
}
// dont cutoff values -> better cell conversions
@@ -1092,13 +1083,6 @@ LbmFsgrSolver::mainLoop(int lev)
// interface cell handling done...
-//#if PARALLEL==1
-//#include "paraloopend.h"
- //GRID_REGION_END();
-//#else // PARALLEL==1
- //GRID_LOOPREG_END();
- //GRID_REGION_END();
-//#endif // PARALLEL==1
#if PARALLEL!=1
GRID_LOOPREG_END();
#else // PARALLEL==1
@@ -1108,9 +1092,9 @@ LbmFsgrSolver::mainLoop(int lev)
// write vars from computations to class
mLevel[lev].lmass = calcCurrentMass;
mLevel[lev].lvolume = calcCurrentVolume;
- this->mNumFilledCells = calcCellsFilled;
- this->mNumEmptiedCells = calcCellsEmptied;
- this->mNumUsedCells = calcNumUsedCells;
+ mNumFilledCells = calcCellsFilled;
+ mNumEmptiedCells = calcCellsEmptied;
+ mNumUsedCells = calcNumUsedCells;
}
@@ -1122,34 +1106,32 @@ LbmFsgrSolver::preinitGrids()
const bool doReduce = false;
const int gridLoopBound=0;
- // touch both grids
+ // preinit both grids
for(int s=0; s<2; s++) {
- GRID_REGION_INIT();
+ GRID_REGION_INIT();
#if PARALLEL==1
#include "paraloopstart.h"
#endif // PARALLEL==1
- GRID_REGION_START();
- GRID_LOOP_START();
- FORDF0{ RAC(ccel,l) = 0.; }
- *pFlagSrc =0;
- *pFlagDst =0;
- //errMsg("l1"," at "<<PRINT_IJK<<" id"<<id);
+ GRID_REGION_START();
+ GRID_LOOP_START();
+ for(int l=0; l<dTotalNum; l++) { RAC(ccel,l) = 0.; }
+ *pFlagSrc =0;
+ *pFlagDst =0;
+ //errMsg("l1"," at "<<PRINT_IJK<<" id"<<id);
#if PARALLEL!=1
- GRID_LOOPREG_END();
+ GRID_LOOPREG_END();
#else // PARALLEL==1
#include "paraloopend.h" // = GRID_LOOPREG_END();
#endif // PARALLEL==1
- //GRID_REGION_END();
- // TEST! */
- /* dummy remove warnings */
- calcCurrentMass = calcCurrentVolume = 0.;
- calcCellsFilled = calcCellsEmptied = calcNumUsedCells = 0;
-
- // change grid
- mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr;
- mLevel[mMaxRefine].setCurr ^= 1;
+ /* dummy, remove warnings */
+ calcCurrentMass = calcCurrentVolume = 0.;
+ calcCellsFilled = calcCellsEmptied = calcNumUsedCells = 0;
+
+ // change grid
+ mLevel[mMaxRefine].setOther = mLevel[mMaxRefine].setCurr;
+ mLevel[mMaxRefine].setCurr ^= 1;
}
}
@@ -1176,14 +1158,9 @@ LbmFsgrSolver::standingFluidPreinit()
# endif // OPT3D==true
GRID_LOOP_START();
- //FORDF0{ RAC(ccel,l) = 0.; }
- //*pFlagSrc =0;
- //*pFlagDst =0;
//errMsg("l1"," at "<<PRINT_IJK<<" id"<<id);
const CellFlagType currFlag = *pFlagSrc; //RFLAG(lev, i,j,k,workSet);
if( (currFlag & (CFEmpty|CFBnd)) ) continue;
- //ccel = RACPNT(lev, i,j,k,workSet);
- //tcel = RACPNT(lev, i,j,k,otherSet);
if( (currFlag & (CFInter)) ) {
// copy all values
@@ -1198,7 +1175,6 @@ LbmFsgrSolver::standingFluidPreinit()
nbflag[l] = RFLAG_NB(lev, i,j,k, SRCS(lev),l);
}
DEFAULT_STREAM;
- //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); }
@@ -1207,8 +1183,6 @@ LbmFsgrSolver::standingFluidPreinit()
#else // PARALLEL==1
#include "paraloopend.h" // = GRID_LOOPREG_END();
#endif // PARALLEL==1
- //GRID_REGION_END();
- // TEST! */
/* dummy remove warnings */
calcCurrentMass = calcCurrentVolume = 0.;
@@ -1227,23 +1201,13 @@ LbmFsgrSolver::standingFluidPreinit()
LbmFloat LbmFsgrSolver::getMassdWeight(bool dirForw, int i,int j,int k,int workSet, int l) {
//return 0.0; // test
int level = mMaxRefine;
- LbmFloat *ccel = RACPNT(level, i,j,k, workSet);
+ LbmFloat *ccel = RACPNT(level, i,j,k, workSet);
- LbmFloat nx,ny,nz, nv1,nv2;
- if(RFLAG_NB(level,i,j,k,workSet, dE) &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); } else nv1 = 0.0;
- if(RFLAG_NB(level,i,j,k,workSet, dW) &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); } else nv2 = 0.0;
- nx = 0.5* (nv2-nv1);
- if(RFLAG_NB(level,i,j,k,workSet, dN) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv1 = 0.0;
- if(RFLAG_NB(level,i,j,k,workSet, dS) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); } else nv2 = 0.0;
- ny = 0.5* (nv2-nv1);
-#if LBMDIM==3
- if(RFLAG_NB(level,i,j,k,workSet, dT) &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv1 = 0.0;
- if(RFLAG_NB(level,i,j,k,workSet, dB) &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); } else nv2 = 0.0;
- nz = 0.5* (nv2-nv1);
-#else //LBMDIM==3
- nz = 0.0;
-#endif //LBMDIM==3
- LbmFloat scal = mDvecNrm[l][0]*nx + mDvecNrm[l][1]*ny + mDvecNrm[l][2]*nz;
+ // computenormal
+ CellFlagType *cflag = &RFLAG(level, i,j,k, workSet);
+ LbmFloat n[3];
+ computeFluidSurfaceNormal(ccel,cflag, n);
+ LbmFloat scal = mDvecNrm[l][0]*n[0] + mDvecNrm[l][1]*n[1] + mDvecNrm[l][2]*n[2];
LbmFloat ret = 1.0;
// forward direction, add mass (for filling cells):
@@ -1259,6 +1223,115 @@ LbmFloat LbmFsgrSolver::getMassdWeight(bool dirForw, int i,int j,int k,int workS
return ret;
}
+// warning - normal compuations are without
+// boundary checks &
+// normalization
+void LbmFsgrSolver::computeFluidSurfaceNormal(LbmFloat *ccel, CellFlagType *cflagpnt,LbmFloat *snret) {
+ const int level = mMaxRefine;
+ LbmFloat nx,ny,nz, nv1,nv2;
+ const CellFlagType flagE = *(cflagpnt+1);
+ const CellFlagType flagW = *(cflagpnt-1);
+ if(flagE &(CFFluid|CFInter)){ nv1 = RAC((ccel+QCELLSTEP ),dFfrac); }
+ else if(flagE &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagW &(CFFluid|CFInter)){ nv2 = RAC((ccel-QCELLSTEP ),dFfrac); }
+ else if(flagW &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ nx = 0.5* (nv2-nv1);
+
+ const CellFlagType flagN = *(cflagpnt+mLevel[level].lOffsx);
+ const CellFlagType flagS = *(cflagpnt-mLevel[level].lOffsx);
+ if(flagN &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); }
+ else if(flagN &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagS &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsx*QCELLSTEP)),dFfrac); }
+ else if(flagS &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ ny = 0.5* (nv2-nv1);
+
+#if LBMDIM==3
+ const CellFlagType flagT = *(cflagpnt+mLevel[level].lOffsy);
+ const CellFlagType flagB = *(cflagpnt-mLevel[level].lOffsy);
+ if(flagT &(CFFluid|CFInter)){ nv1 = RAC((ccel+(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); }
+ else if(flagT &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagB &(CFFluid|CFInter)){ nv2 = RAC((ccel-(mLevel[level].lOffsy*QCELLSTEP)),dFfrac); }
+ else if(flagB &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ nz = 0.5* (nv2-nv1);
+#else //LBMDIM==3
+ nz = 0.0;
+#endif //LBMDIM==3
+
+ // return vals
+ snret[0]=nx; snret[1]=ny; snret[2]=nz;
+}
+void LbmFsgrSolver::computeFluidSurfaceNormalAcc(LbmFloat *ccel, CellFlagType *cflagpnt, LbmFloat *snret) {
+ LbmFloat nx=0.,ny=0.,nz=0.;
+ ccel = NULL; cflagpnt=NULL; // remove warning
+ snret[0]=nx; snret[1]=ny; snret[2]=nz;
+}
+void LbmFsgrSolver::computeObstacleSurfaceNormal(LbmFloat *ccel, CellFlagType *cflagpnt, LbmFloat *snret) {
+ const int level = mMaxRefine;
+ LbmFloat nx,ny,nz, nv1,nv2;
+ ccel = NULL; // remove warning
+
+ const CellFlagType flagE = *(cflagpnt+1);
+ const CellFlagType flagW = *(cflagpnt-1);
+ if(flagE &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagW &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ nx = 0.5* (nv2-nv1);
+
+ const CellFlagType flagN = *(cflagpnt+mLevel[level].lOffsx);
+ const CellFlagType flagS = *(cflagpnt-mLevel[level].lOffsx);
+ if(flagN &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagS &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ ny = 0.5* (nv2-nv1);
+
+#if LBMDIM==3
+ const CellFlagType flagT = *(cflagpnt+mLevel[level].lOffsy);
+ const CellFlagType flagB = *(cflagpnt-mLevel[level].lOffsy);
+ if(flagT &(CFBnd)){ nv1 = 1.; }
+ else nv1 = 0.0;
+ if(flagB &(CFBnd)){ nv2 = 1.; }
+ else nv2 = 0.0;
+ nz = 0.5* (nv2-nv1);
+#else //LBMDIM==3
+ nz = 0.0;
+#endif //LBMDIM==3
+
+ // return vals
+ snret[0]=nx; snret[1]=ny; snret[2]=nz;
+}
+void LbmFsgrSolver::computeObstacleSurfaceNormalAcc(int i,int j,int k, LbmFloat *snret) {
+ bool nonorm = false;
+ LbmFloat nx=0.,ny=0.,nz=0.;
+ if(i<=0) { nx = 1.; nonorm = true; }
+ if(i>=mSizex-1) { nx = -1.; nonorm = true; }
+ if(j<=0) { ny = 1.; nonorm = true; }
+ if(j>=mSizey-1) { ny = -1.; nonorm = true; }
+# if LBMDIM==3
+ if(k<=0) { nz = 1.; nonorm = true; }
+ if(k>=mSizez-1) { nz = -1.; nonorm = true; }
+# endif // LBMDIM==3
+ if(!nonorm) {
+ // in domain, revert to helper, use setCurr&mMaxRefine
+ LbmVec bnormal;
+ CellFlagType *bflag = &RFLAG(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr);
+ LbmFloat *bcell = RACPNT(mMaxRefine, i,j,k, mLevel[mMaxRefine].setCurr);
+ computeObstacleSurfaceNormal(bcell,bflag, &bnormal[0]);
+ // TODO check if there is a normal near here?
+ // use wider range otherwise...
+ snret[0]=bnormal[0]; snret[1]=bnormal[0]; snret[2]=bnormal[0];
+ return;
+ }
+ snret[0]=nx; snret[1]=ny; snret[2]=nz;
+}
+
void LbmFsgrSolver::addToNewInterList( int ni, int nj, int nk ) {
#if FSGR_STRICT_DEBUG==10
// dangerous, this can change the simulation...
@@ -1494,9 +1567,9 @@ void LbmFsgrSolver::reinitFlags( int workSet ) {
massChange = 0.0;
} else {
// Problem! no interface neighbors
- this->mFixMass += massChange;
+ mFixMass += massChange;
//TTT mNumProblems++;
- //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<<this->mFixMass);
+ //errMsg(" FULL PROBLEM ", PRINT_IJK<<" "<<mFixMass);
}
weightIndex++;
@@ -1531,9 +1604,9 @@ void LbmFsgrSolver::reinitFlags( int workSet ) {
massChange = 0.0;
} else {
// Problem! no interface neighbors
- this->mFixMass += massChange;
+ mFixMass += massChange;
//TTT mNumProblems++;
- //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<<this->mFixMass);
+ //errMsg(" EMPT PROBLEM ", PRINT_IJK<<" "<<mFixMass);
}
weightIndex++;
@@ -1582,7 +1655,7 @@ void LbmFsgrSolver::reinitFlags( int workSet ) {
continue;
} // */
- QCELL(workLev,i,j,k, workSet, dMass) += (this->mFixMass * newIfFac);
+ QCELL(workLev,i,j,k, workSet, dMass) += (mFixMass * newIfFac);
int nbored = 0;
FORDF1 { nbored |= RFLAG_NB(workLev, i,j,k, workSet,l); }
@@ -1602,15 +1675,16 @@ void LbmFsgrSolver::reinitFlags( int workSet ) {
int i=iter->x, j=iter->y, k=iter->z;
if(!(RFLAG(workLev,i,j,k, workSet)&CFInter)) { continue; }
- LbmFloat nrho = 0.0;
- FORDF0 { nrho += QCELL(workLev, i,j,k, workSet, l); }
- QCELL(workLev,i,j,k, workSet, dFfrac) = QCELL(workLev,i,j,k, workSet, dMass)/nrho;
- QCELL(workLev,i,j,k, workSet, dFlux) = FLUX_INIT;
+ initInterfaceVars(workLev, i,j,k, workSet, false); //int level, int i,int j,int k,int workSet, bool initMass) {
+ //LbmFloat nrho = 0.0;
+ //FORDF0 { nrho += QCELL(workLev, i,j,k, workSet, l); }
+ //QCELL(workLev,i,j,k, workSet, dFfrac) = QCELL(workLev,i,j,k, workSet, dMass)/nrho;
+ //QCELL(workLev,i,j,k, workSet, dFlux) = FLUX_INIT;
}
if(mListNewInter.size()>0){
- //errMsg("FixMassDisted"," fm:"<<this->mFixMass<<" nif:"<<mListNewInter.size() );
- this->mFixMass = 0.0;
+ //errMsg("FixMassDisted"," fm:"<<mFixMass<<" nif:"<<mListNewInter.size() );
+ mFixMass = 0.0;
}
// empty lists for next step
diff --git a/intern/elbeem/intern/solver_relax.h b/intern/elbeem/intern/solver_relax.h
index 2c99a853c62..287b73c77b2 100644
--- a/intern/elbeem/intern/solver_relax.h
+++ b/intern/elbeem/intern/solver_relax.h
@@ -3,7 +3,7 @@
* El'Beem - the visual lattice boltzmann freesurface simulator
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
- * Copyright 2003-2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Combined 2D/3D Lattice Boltzmann relaxation macros
*
@@ -378,6 +378,15 @@
} \
} else { \
m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \
+ if(RFLAG(lev, i,j,k, mLevel[lev].setCurr)&CFFluid) { \
+ if(!(nbf&(CFFluid|CFInter)) ) { \
+ int ni=i+this->dfVecX[this->dfInv[l]], nj=j+this->dfVecY[this->dfInv[l]], nk=k+this->dfVecZ[this->dfInv[l]]; \
+ errMsg("STREAMCHECK"," Invalid nbflag, streamed DF l"<<l<<" value:"<<m[l]<<" at "<<PRINT_IJK<<" from "<< \
+ PRINT_VEC(ni,nj,nk) <<" l"<<(l)<< \
+ " nfc"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr)<<" nfo"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setOther) ); \
+ \
+ \
+ } } \
STREAMCHECK(4, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \
} \
} \
@@ -1198,5 +1207,7 @@ inline void LbmFsgrSolver::collideArrays(
muy = uy;
muz = uz;
outrho = rho;
+
+ lev=i=j=k; // debug, remove warnings
};
diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp
index 6b7f6f2ed9c..d11ae6c6b40 100644
--- a/intern/elbeem/intern/solver_util.cpp
+++ b/intern/elbeem/intern/solver_util.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004,2005 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Standard LBM Factory implementation
*
@@ -15,6 +15,7 @@
#include "ntl_world.h"
#include "simulation_object.h"
+#include <zlib.h>
/******************************************************************************
* helper functions
@@ -23,6 +24,10 @@
// try to enhance surface?
#define SURFACE_ENH 2
+extern bool glob_mpactive;
+extern bool glob_mpnum;
+extern bool glob_mpindex;
+
//! for raytracing
void LbmFsgrSolver::prepareVisualization( void ) {
int lev = mMaxRefine;
@@ -36,10 +41,8 @@ void LbmFsgrSolver::prepareVisualization( void ) {
mainGravLen = thisGravLen;
mainGravDir = l;
}
- //errMsg("GRAVT","l"<<l<<" dfv"<<LbmVec(dfVecX[l],dfVecY[l],dfVecZ[l])<<" g"<< mLevel[mMaxRefine].gravity<< " mgl"<<mainGravLen<<" mgd"<<mainGravDir);
}
- //make same prepareVisualization and getIsoSurface...
#if LBMDIM==2
// 2d, place in the middle of isofield slice (k=2)
# define ZKD1 0
@@ -49,7 +52,7 @@ void LbmFsgrSolver::prepareVisualization( void ) {
for(int k= 0; k< 5; ++k)
for(int j=0;j<mLevel[lev].lSizey-0;j++)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,j,ZKOFF)=0.0;
+ *mpIso->lbmGetData(i,j,ZKOFF)=0.0;
}
#else // LBMDIM==2
// 3d, use normal bounds
@@ -59,21 +62,17 @@ void LbmFsgrSolver::prepareVisualization( void ) {
for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k)
for(int j=0;j<mLevel[lev].lSizey-0;j++)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,j,ZKOFF)=0.0;
+ *mpIso->lbmGetData(i,j,ZKOFF)=0.0;
}
#endif // LBMDIM==2
// MPT, ignore
- //if( strstr( this->getName().c_str(), "mpfluid2" ) != NULL) {
- //errMsg("MPT TESTX","skipping mpfluid2");
- //return;
- //}
- if( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) {
+ if((glob_mpactive) && (glob_mpnum>1) && (glob_mpindex==0)) {
mpIso->resetAll(0.);
}
- LbmFloat minval = this->mIsoValue*1.05; // / mIsoWeight[13];
+ LbmFloat minval = mIsoValue*1.05; // / mIsoWeight[13];
// add up...
float val = 0.0;
for(int k= getForZMin1(); k< getForZMax1(lev); ++k)
@@ -117,10 +116,10 @@ void LbmFsgrSolver::prepareVisualization( void ) {
if(cflag&CFEmpty) {
// special empty treatment
if((noslipbnd)&&(intercnt>6)) {
- *this->mpIso->lbmGetData(i,j,ZKOFF) += minval;
+ *mpIso->lbmGetData(i,j,ZKOFF) += minval;
} else if((noslipbnd)&&(intercnt>0)) {
// necessary?
- *this->mpIso->lbmGetData(i,j,ZKOFF) += this->mIsoValue*0.9;
+ *mpIso->lbmGetData(i,j,ZKOFF) += mIsoValue*0.9;
} else {
// nothing to do...
}
@@ -135,7 +134,7 @@ void LbmFsgrSolver::prepareVisualization( void ) {
if(noslipbnd) {
if(val<minval) val = minval;
- *this->mpIso->lbmGetData(i,j,ZKOFF) += minval-( val * mIsoWeight[13] );
+ *mpIso->lbmGetData(i,j,ZKOFF) += minval-( val * mIsoWeight[13] );
}
#endif // SURFACE_ENH>0
@@ -143,43 +142,43 @@ void LbmFsgrSolver::prepareVisualization( void ) {
continue;
}
- *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] );
+ *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[0] );
+ *mpIso->lbmGetData( i , j-1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[1] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[3] );
+ *mpIso->lbmGetData( i , j ,ZKOFF-ZKD1) += ( val * mIsoWeight[4] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[6] );
+ *mpIso->lbmGetData( i , j+1 ,ZKOFF-ZKD1) += ( val * mIsoWeight[7] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF ) += ( val * mIsoWeight[9] );
+ *mpIso->lbmGetData( i , j-1 ,ZKOFF ) += ( val * mIsoWeight[10] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j ,ZKOFF ) += ( val * mIsoWeight[12] );
+ *mpIso->lbmGetData( i , j ,ZKOFF ) += ( val * mIsoWeight[13] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF ) += ( val * mIsoWeight[15] );
+ *mpIso->lbmGetData( i , j+1 ,ZKOFF ) += ( val * mIsoWeight[16] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[18] );
+ *mpIso->lbmGetData( i , j-1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[19] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j ,ZKOFF+ZKD1) += ( val * mIsoWeight[21] );
+ *mpIso->lbmGetData( i , j ,ZKOFF+ZKD1)+= ( val * mIsoWeight[22] );
+ *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] );
+ *mpIso->lbmGetData( i-1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[24] );
+ *mpIso->lbmGetData( i , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[25] );
+ *mpIso->lbmGetData( i+1 , j+1 ,ZKOFF+ZKD1) += ( val * mIsoWeight[26] );
}
// TEST!?
@@ -194,9 +193,9 @@ void LbmFsgrSolver::prepareVisualization( void ) {
CellFlagType nbored=0;
LbmFloat avgfill=0.,avgfcnt=0.;
FORDF1 {
- const int ni = i+this->dfVecX[l];
- const int nj = j+this->dfVecY[l];
- const int nk = ZKOFF+this->dfVecZ[l];
+ const int ni = i+dfVecX[l];
+ const int nj = j+dfVecY[l];
+ const int nk = ZKOFF+dfVecZ[l];
const CellFlagType nbflag = RFLAG(lev, ni,nj,nk, workSet);
nbored |= nbflag;
@@ -216,10 +215,10 @@ void LbmFsgrSolver::prepareVisualization( void ) {
if(nbored&CFInter) {
if(avgfcnt>0.) avgfill/=avgfcnt;
- *this->mpIso->lbmGetData(i,j,ZKOFF) = avgfill; continue;
+ *mpIso->lbmGetData(i,j,ZKOFF) = avgfill; continue;
}
else if(nbored&CFFluid) {
- *this->mpIso->lbmGetData(i,j,ZKOFF) = 1.; continue;
+ *mpIso->lbmGetData(i,j,ZKOFF) = 1.; continue;
}
}
@@ -232,16 +231,16 @@ void LbmFsgrSolver::prepareVisualization( void ) {
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);
- if( (cflag&(CFBnd)) && (*this->mpIso->lbmGetData(i,j,ZKOFF)==0.)) {
+ if( (cflag&(CFBnd)) && (*mpIso->lbmGetData(i,j,ZKOFF)==0.)) {
int bndnbcnt=0;
FORDF1 {
- const int ni = i+this->dfVecX[l];
- const int nj = j+this->dfVecY[l];
- const int nk = ZKOFF+this->dfVecZ[l];
+ const int ni = i+dfVecX[l];
+ const int nj = j+dfVecY[l];
+ const int nk = ZKOFF+dfVecZ[l];
const CellFlagType nbflag = RFLAG(lev, ni,nj,nk, workSet);
if(nbflag&CFBnd) bndnbcnt++;
}
- if(bndnbcnt>0) *this->mpIso->lbmGetData(i,j,ZKOFF)=this->mIsoValue*0.95;
+ if(bndnbcnt>0) *mpIso->lbmGetData(i,j,ZKOFF)=mIsoValue*0.95;
}
}
}
@@ -250,70 +249,70 @@ void LbmFsgrSolver::prepareVisualization( void ) {
if(mFsSurfGenSetting&fssgNoNorth)
for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k)
for(int j=0;j<mLevel[lev].lSizey-0;j++) {
- *this->mpIso->lbmGetData(0, j,ZKOFF) = *this->mpIso->lbmGetData(1, j,ZKOFF);
+ *mpIso->lbmGetData(0, j,ZKOFF) = *mpIso->lbmGetData(1, j,ZKOFF);
}
if(mFsSurfGenSetting&fssgNoEast)
for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,0, ZKOFF) = *this->mpIso->lbmGetData(i,1, ZKOFF);
+ *mpIso->lbmGetData(i,0, ZKOFF) = *mpIso->lbmGetData(i,1, ZKOFF);
}
if(mFsSurfGenSetting&fssgNoSouth)
for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k)
for(int j=0;j<mLevel[lev].lSizey-0;j++) {
- *this->mpIso->lbmGetData(mLevel[lev].lSizex-1,j,ZKOFF) = *this->mpIso->lbmGetData(mLevel[lev].lSizex-2,j,ZKOFF);
+ *mpIso->lbmGetData(mLevel[lev].lSizex-1,j,ZKOFF) = *mpIso->lbmGetData(mLevel[lev].lSizex-2,j,ZKOFF);
}
if(mFsSurfGenSetting&fssgNoWest)
for(int k= getForZMinBnd(); k< getForZMaxBnd(lev); ++k)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,mLevel[lev].lSizey-1,ZKOFF) = *this->mpIso->lbmGetData(i,mLevel[lev].lSizey-2,ZKOFF);
+ *mpIso->lbmGetData(i,mLevel[lev].lSizey-1,ZKOFF) = *mpIso->lbmGetData(i,mLevel[lev].lSizey-2,ZKOFF);
}
if(LBMDIM>2) {
if(mFsSurfGenSetting&fssgNoBottom)
for(int j=0;j<mLevel[lev].lSizey-0;j++)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,j,0 ) = *this->mpIso->lbmGetData(i,j,1 );
+ *mpIso->lbmGetData(i,j,0 ) = *mpIso->lbmGetData(i,j,1 );
}
if(mFsSurfGenSetting&fssgNoTop)
for(int j=0;j<mLevel[lev].lSizey-0;j++)
for(int i=0;i<mLevel[lev].lSizex-0;i++) {
- *this->mpIso->lbmGetData(i,j,mLevel[lev].lSizez-1) = *this->mpIso->lbmGetData(i,j,mLevel[lev].lSizez-2);
+ *mpIso->lbmGetData(i,j,mLevel[lev].lSizez-1) = *mpIso->lbmGetData(i,j,mLevel[lev].lSizez-2);
}
}
#endif // SURFACE_ENH>=2
// update preview, remove 2d?
- if((this->mOutputSurfacePreview)&&(LBMDIM==3)) {
- int pvsx = (int)(this->mPreviewFactor*this->mSizex);
- int pvsy = (int)(this->mPreviewFactor*this->mSizey);
- int pvsz = (int)(this->mPreviewFactor*this->mSizez);
- //float scale = (float)this->mSizex / previewSize;
- LbmFloat scalex = (LbmFloat)this->mSizex/(LbmFloat)pvsx;
- LbmFloat scaley = (LbmFloat)this->mSizey/(LbmFloat)pvsy;
- LbmFloat scalez = (LbmFloat)this->mSizez/(LbmFloat)pvsz;
+ if((mOutputSurfacePreview)&&(LBMDIM==3)) {
+ int pvsx = (int)(mPreviewFactor*mSizex);
+ int pvsy = (int)(mPreviewFactor*mSizey);
+ int pvsz = (int)(mPreviewFactor*mSizez);
+ //float scale = (float)mSizex / previewSize;
+ LbmFloat scalex = (LbmFloat)mSizex/(LbmFloat)pvsx;
+ LbmFloat scaley = (LbmFloat)mSizey/(LbmFloat)pvsy;
+ LbmFloat scalez = (LbmFloat)mSizez/(LbmFloat)pvsz;
for(int k= 0; k< (pvsz-1); ++k)
for(int j=0;j< pvsy;j++)
for(int i=0;i< pvsx;i++) {
- *mpPreviewSurface->lbmGetData(i,j,k) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) );
+ *mpPreviewSurface->lbmGetData(i,j,k) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley), (int)(k*scalez) );
}
// set borders again...
for(int k= 0; k< (pvsz-1); ++k) {
for(int j=0;j< pvsy;j++) {
- *mpPreviewSurface->lbmGetData(0,j,k) = *this->mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) );
- *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *this->mpIso->lbmGetData( this->mSizex-1, (int)(j*scaley), (int)(k*scalez) );
+ *mpPreviewSurface->lbmGetData(0,j,k) = *mpIso->lbmGetData( 0, (int)(j*scaley), (int)(k*scalez) );
+ *mpPreviewSurface->lbmGetData(pvsx-1,j,k) = *mpIso->lbmGetData( mSizex-1, (int)(j*scaley), (int)(k*scalez) );
}
for(int i=0;i< pvsx;i++) {
- *mpPreviewSurface->lbmGetData(i,0,k) = *this->mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) );
- *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *this->mpIso->lbmGetData( (int)(i*scalex), this->mSizey-1, (int)(k*scalez) );
+ *mpPreviewSurface->lbmGetData(i,0,k) = *mpIso->lbmGetData( (int)(i*scalex), 0, (int)(k*scalez) );
+ *mpPreviewSurface->lbmGetData(i,pvsy-1,k) = *mpIso->lbmGetData( (int)(i*scalex), mSizey-1, (int)(k*scalez) );
}
}
for(int j=0;j<pvsy;j++)
for(int i=0;i<pvsx;i++) {
- *mpPreviewSurface->lbmGetData(i,j,0) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0);
- *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *this->mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , this->mSizez-1);
+ *mpPreviewSurface->lbmGetData(i,j,0) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , 0);
+ *mpPreviewSurface->lbmGetData(i,j,pvsz-1) = *mpIso->lbmGetData( (int)(i*scalex), (int)(j*scaley) , mSizez-1);
}
- if(mFarFieldSize>=2.) {
+ if(mFarFieldSize>=1.2) {
// also remove preview border
for(int k= 0; k< (pvsz-1); ++k) {
for(int j=0;j< pvsy;j++) {
@@ -349,45 +348,9 @@ void LbmFsgrSolver::prepareVisualization( void ) {
}
// MPT
-#if LBM_INCLUDE_TESTSOLVERS==1
- if( ( strstr( this->getName().c_str(), "mpfluid1" ) != NULL) && (mInitDone) ) {
- errMsg("MPT TESTX","special mpfluid1");
- vector<SimulationObject*> *sims = mpGlob->getSims();
- for(int simi=0; simi<(int)(sims->size()); simi++) {
- SimulationObject *sim = (*sims)[simi];
- if( strstr( sim->getName().c_str(), "mpfluid2" ) != NULL) {
- LbmFsgrSolver *fsgr = (LbmFsgrSolver *)(sim->getSolver());
- int msyLev = mMaxRefine;
- int simLev = fsgr->mMaxRefine;
-
- IsoSurface* simIso = fsgr->mpIso;
- int idst = mLevel[msyLev].lSizex-2 -1; // start at boundary
- int isrc = 0 +2;
- if((simIso)&&(fsgr->mInitDone)) {
- fsgr->prepareVisualization();
-
- for(int k=0;k<=mLevel[simLev].lSizez-1;++k) {
- for(int j=0;j<=mLevel[simLev].lSizey-1;++j) {
- for(int i=isrc; i<mLevel[simLev].lSizex-1; i++) {
- //LbmFloat *cceldst = &QCELL( msyLev ,idst+i,j,k, msySet,0);
- //LbmFloat *ccelsrc = &SIM_QCELL(fsgr, simLev ,isrc+i,j,k, simSet,0);
- //for(int l=0; l<dTotalNum; l++) {
- //RAC(cceldst,l) = RAC(ccelsrc,l);
- //}
- // both flag sets, make sure curr/other are same!?
- //RFLAG(msyLev ,idst+i,j,k, 0) = SIM_RFLAG(fsgr, simLev ,isrc+i,j,k, 0);
- //RFLAG(msyLev ,idst+i,j,k, 1) = SIM_RFLAG(fsgr, simLev ,isrc+i,j,k, 1);
- errMsg("TESTX"," "<<PRINT_VEC(idst+i,j,k)<<" < "<<PRINT_VEC(i,j,k) );
- *mpIso->lbmGetData(idst+i,j,k) = *simIso->lbmGetData(i,j,k);
- }
- }
- }
-
- } // simIso
- }
- }
- }
-#endif // LBM_INCLUDE_TESTSOLVERS==1
+ #if LBM_INCLUDE_TESTSOLVERS==1
+ mrIsoExchange();
+ #endif // LBM_INCLUDE_TESTSOLVERS==1
return;
}
@@ -471,12 +434,12 @@ int LbmFsgrSolver::initParticles() {
partt->setEnd ( this->mvGeoEnd + ntlVec3Gfx(mLevel[mMaxRefine].nodeSize*0.5) );
partt->setSimStart( ntlVec3Gfx(0.0) );
- partt->setSimEnd ( ntlVec3Gfx(this->mSizex, this->mSizey, getForZMaxBnd(mMaxRefine)) );
+ partt->setSimEnd ( ntlVec3Gfx(mSizex, mSizey, getForZMaxBnd(mMaxRefine)) );
while( (num<partt->getNumInitialParticles()) && (tries<100*partt->getNumInitialParticles()) ) {
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)) );
+ x = 1.0+(( (LbmFloat)(mSizex-3.) ) * (rand()/(RAND_MAX+1.0)) );
+ y = 1.0+(( (LbmFloat)(mSizey-3.) ) * (rand()/(RAND_MAX+1.0)) );
z = 1.0+(( (LbmFloat) getForZMax1(mMaxRefine)-2. )* (rand()/(RAND_MAX+1.0)) );
int i = (int)(x+0.5);
int j = (int)(y+0.5);
@@ -485,8 +448,8 @@ int LbmFsgrSolver::initParticles() {
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), CFNoNbFluid )
+ //if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFFluid) )
+ //&& ( 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|CFUnused) ) {
bool cellOk = true;
@@ -531,8 +494,8 @@ int LbmFsgrSolver::initParticles() {
#if LBM_INCLUDE_TESTSOLVERS==1
if(mUseTestdata) {
const bool partDebug=false;
- if(mpTest->mDebugvalue2!=0.0){ errMsg("LbmTestdata"," part init "<<mpTest->mDebugvalue2); }
- if(mpTest->mDebugvalue2==-12.0){
+ if(mpTest->mPartTestcase==0){ errMsg("LbmTestdata"," part init "<<mpTest->mPartTestcase); }
+ if(mpTest->mPartTestcase==-12){
const int lev = mMaxRefine;
for(int i=5;i<15;i++) {
LbmFloat x,y,z;
@@ -546,7 +509,7 @@ int LbmFsgrSolver::initParticles() {
if(partDebug) errMsg("PARTTT","SET "<<PRINT_VEC(x,y,z)<<" p"<<partt->getLast()->getPos() <<" s"<<partt->getLast()->getSize() );
}
}
- if(mpTest->mDebugvalue2==-11.0){
+ if(mpTest->mPartTestcase==-11){
const int lev = mMaxRefine;
for(int i=5;i<15;i++) {
LbmFloat x,y,z;
@@ -561,7 +524,7 @@ int LbmFsgrSolver::initParticles() {
}
}
// place floats on rectangular region FLOAT_JITTER_BND
- if(mpTest->mDebugvalue2==-10.0){
+ if(mpTest->mPartTestcase==-10){
const int lev = mMaxRefine;
const int sx = mLevel[lev].lSizex;
const int sy = mLevel[lev].lSizey;
@@ -594,6 +557,22 @@ int LbmFsgrSolver::initParticles() {
return 0;
}
+// helper function for particle debugging
+/*static string getParticleStatusString(int state) {
+ std::ostringstream out;
+ if(state&PART_DROP) out << "dropp ";
+ if(state&PART_TRACER) out << "tracr ";
+ if(state&PART_BUBBLE) out << "bubbl ";
+ if(state&PART_FLOAT) out << "float ";
+ if(state&PART_INTER) out << "inter ";
+
+ if(state&PART_IN) out << "inn ";
+ if(state&PART_OUT) out << "out ";
+ if(state&PART_INACTIVE) out << "INACT ";
+ if(state&PART_OUTFLUID) out << "outfluid ";
+ return out.str();
+} // */
+
#define P_CHANGETYPE(p, newtype) \
p->setLifeTime(0.); \
/* errMsg("PIT","U pit"<<(p)->getId()<<" pos:"<< (p)->getPos()<<" status:"<<convertFlags2String((p)->getFlags())<<" to "<< (newtype) ); */ \
@@ -610,21 +589,22 @@ int LbmFsgrSolver::initParticles() {
#define FLOAT_JITTER_BND (FLOAT_JITTER*2.0)
#define FLOAT_JITTBNDRAND(x) ((rand()/(RAND_MAX+1.0))*FLOAT_JITTER_BND*(1.-(x/(LbmFloat)maxdw))-(FLOAT_JITTER_BND*(1.-(x)/(LbmFloat)maxdw)*0.5))
-
-void LbmFsgrSolver::advanceParticles() {
- int workSet = mLevel[mMaxRefine].setCurr;
- LbmFloat vx=0.0,vy=0.0,vz=0.0;
- //LbmFloat df[27]; //feq[27];
#define DEL_PART { \
/*errMsg("PIT","DEL AT "<< __LINE__<<" type:"<<p->getType()<<" "); */ \
p->setActive( false ); \
continue; }
+void LbmFsgrSolver::advanceParticles() {
+ const int level = mMaxRefine;
+ const int workSet = mLevel[level].setCurr;
+ LbmFloat vx=0.0,vy=0.0,vz=0.0;
+ //int debugOutCounter=0; // debug output counter
+
myTime_t parttstart = getTime();
const LbmFloat cellsize = this->mpParam->getCellSize();
const LbmFloat timestep = this->mpParam->getTimestep();
//const LbmFloat viscAir = 1.79 * 1e-5; // RW2L kin. viscosity, mu
- const LbmFloat viscWater = 1.0 * 1e-6; // RW2L kin. viscosity, mu
+ //const LbmFloat viscWater = 1.0 * 1e-6; // RW2L kin. viscosity, mu
const LbmFloat rhoAir = 1.2; // [kg m^-3] RW2L
const LbmFloat rhoWater = 1000.0; // RW2L
const LbmFloat minDropSize = 0.0005; // [m], = 2mm RW2L
@@ -635,65 +615,56 @@ void LbmFsgrSolver::advanceParticles() {
const LbmFloat v1 = 9.0; // v max
const LbmFloat v2 = 2.0; // v min
const LbmVec rwgrav = vec2L( this->mpParam->getGravity(mSimulationTime) );
- const bool useff = (mFarFieldSize>2.); // if(mpTest->mDebugvalue1>0.0){
+ const bool useff = (mFarFieldSize>1.2); // if(mpTest->mFarfMode>0){
- // TODO use timestep size
+ // TODO scale bubble/part damping dep. on timestep, also drop bnd rev damping
const int cutval = mCutoff; // use full border!?
- int actCnt=0;
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() );
- //int flag = (*pit).getFlags();
+ //if((*pit).getPos()[2]>10.) errMsg("PIT"," pit"<<(*pit).getId()<<" pos:"<< (*pit).getPos()<<" status:["<<getParticleStatusString((*pit).getFlags())<<"] vel:"<< (*pit).getVel() );
if( (*pit).getActive()==false ) continue;
// skip until reached
ParticleObject *p = &(*pit);
if(p->getLifeTime()<0.){
- if(p->getLifeTime()<-this->mSimulationTime) continue;
- else p->setLifeTime(-mLevel[mMaxRefine].timestep); // zero for following update
+ if(p->getLifeTime() < -mSimulationTime) continue;
+ else p->setLifeTime(-mLevel[level].timestep); // zero for following update
}
int i,j,k;
- p->setLifeTime(p->getLifeTime()+mLevel[mMaxRefine].timestep);
+ p->setLifeTime(p->getLifeTime()+mLevel[level].timestep);
// nearest neighbor, particle positions don't include empty bounds
ntlVec3Gfx pos = p->getPos();
- i= (int)(pos[0]+0.5);
- j= (int)(pos[1]+0.5);
- k= (int)(pos[2]+0.5);
+ i= (int)pos[0]; j= (int)pos[1]; k= (int)pos[2];// no offset necessary
if(LBMDIM==2) { k = 0; }
// only testdata handling, all for sws
#if LBM_INCLUDE_TESTSOLVERS==1
- if(useff && (mpTest->mDebugvalue1>0.)) {
+ if(useff && (mpTest->mFarfMode>0)) {
p->setStatus(PART_OUT);
mpTest->handleParticle(p, i,j,k); continue;
}
#endif // LBM_INCLUDE_TESTSOLVERS==1
- // FIXME , add k tests again, remove per type ones...
+ // in out tests
if(p->getStatus()&PART_IN) { // IN
- if( (i<cutval)||(i>this->mSizex-1-cutval)||
- (j<cutval)||(j>this->mSizey-1-cutval)
- //||(k<cutval)||(k>this->mSizez-1-cutval)
+ if( (i<cutval)||(i>mSizex-1-cutval)||
+ (j<cutval)||(j>mSizey-1-cutval)
+ //||(k<cutval)||(k>mSizez-1-cutval)
) {
if(!useff) { DEL_PART;
} else {
p->setStatus(PART_OUT);
- /* del? */ //if((rand()/(RAND_MAX+1.0))<0.5) DEL_PART;
}
}
} else { // OUT rough check
// check in again?
- if( (i>=cutval)&&(i<=this->mSizex-1-cutval)&&
- (j>=cutval)&&(j<=this->mSizey-1-cutval)
- //&&(k>=cutval)&&(k<=this->mSizez-1-cutval)
+ if( (i>=cutval)&&(i<=mSizex-1-cutval)&&
+ (j>=cutval)&&(j<=mSizey-1-cutval)
) {
p->setStatus(PART_IN);
- /* del? */ //if((rand()/(RAND_MAX+1.0))<0.5) DEL_PART;
}
}
- //p->setStatus(PART_OUT);// DEBUG always out!
if( (p->getType()==PART_BUBBLE) ||
(p->getType()==PART_TRACER) ) {
@@ -702,11 +673,11 @@ void LbmFsgrSolver::advanceParticles() {
vx = vy = vz = 0.0;
if(p->getStatus()&PART_IN) { // IN
if(k>=cutval) {
- if(k>this->mSizez-1-cutval) DEL_PART;
+ if(k>mSizez-1-cutval) DEL_PART;
- if( RFLAG(mMaxRefine, i,j,k, workSet)&(CFFluid|CFUnused) ) {
+ if( RFLAG(level, i,j,k, workSet)&(CFFluid|CFUnused) ) {
// still ok
- int partLev = mMaxRefine;
+ int partLev = level;
int si=i, sj=j, sk=k;
while(partLev>0 && RFLAG(partLev, si,sj,sk, workSet)&(CFUnused)) {
partLev--;
@@ -714,23 +685,22 @@ void LbmFsgrSolver::advanceParticles() {
sj/=2;
sk/=2;
}
- //LbmFloat cdf = QCELL(mMaxRefine, i,j,k, workSet, l);
- LbmFloat *ccel = RACPNT(partLev, si,sj,sk, workSet);
- FORDF1{
- //LbmFloat cdf = QCELL(mMaxRefine, i,j,k, workSet, l);
- LbmFloat cdf = RAC(ccel, l);
- // TODO update below
- //df[l] = cdf;
- vx += (this->dfDvecX[l]*cdf);
- vy += (this->dfDvecY[l]*cdf);
- vz += (this->dfDvecZ[l]*cdf);
- }
-
- // remove gravity influence
- const LbmFloat lesomega = mLevel[mMaxRefine].omega; // no les
- vx -= mLevel[mMaxRefine].gravity[0] * lesomega*0.5;
- vy -= mLevel[mMaxRefine].gravity[1] * lesomega*0.5;
- vz -= mLevel[mMaxRefine].gravity[2] * lesomega*0.5;
+ // get velocity from fluid cell
+ if( RFLAG(partLev, si,sj,sk, workSet)&(CFFluid) ) {
+ LbmFloat *ccel = RACPNT(partLev, si,sj,sk, workSet);
+ FORDF1{
+ LbmFloat cdf = RAC(ccel, l);
+ // TODO update below
+ vx += (this->dfDvecX[l]*cdf);
+ vy += (this->dfDvecY[l]*cdf);
+ vz += (this->dfDvecZ[l]*cdf);
+ }
+ // remove gravity influence
+ const LbmFloat lesomega = mLevel[level].omega; // no les
+ vx -= mLevel[level].gravity[0] * lesomega*0.5;
+ vy -= mLevel[level].gravity[1] * lesomega*0.5;
+ vz -= mLevel[level].gravity[2] * lesomega*0.5;
+ } // fluid vel
} else { // OUT
// out of bounds, deactivate...
@@ -753,39 +723,41 @@ void LbmFsgrSolver::advanceParticles() {
ntlVec3Gfx v = p->getVel(); // dampen...
if( (useff)&& (p->getType()==PART_BUBBLE) ) {
// test rise
- //O vz = p->getVel()[2]-0.5*mLevel[mMaxRefine].gravity[2];
- LbmFloat radius = p->getSize() * minDropSize;
- LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity
- LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity
- LbmVec velRel = velWater - velPart;
- LbmFloat velRelNorm = norm(velRel);
- // TODO calculate values in lattice units, compute CD?!??!
- LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3
- //const LbmFloat cd =
-
- LbmVec fb = -rwgrav* pvolume *rhoWater;
- LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater;
- LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize);
- //LbmVec change = (fb+fd) *timestep / (pvolume*rhoAir) *(timestep/cellsize);
- //actCnt++; // should be after active test
- if(actCnt<0) {
- errMsg("PIT","BTEST1 vol="<<pvolume<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel);
- errMsg("PIT","BTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscW="<<viscWater<<" ss/mb="<<(timestep/(pvolume*rhoAir)));
- errMsg("PIT","BTEST2 grav="<<rwgrav<<" " );
- errMsg("PIT","BTEST2 change="<<(change)<<" fb="<<(fb)<<" fd="<<(fd)<<" ");
- errMsg("PIT","BTEST2 change="<<norm(change)<<" fb="<<norm(fb)<<" fd="<<norm(fd)<<" ");
+ if(mPartUsePhysModel) {
+ LbmFloat radius = p->getSize() * minDropSize;
+ LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity
+ LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity
+ LbmVec velRel = velWater - velPart;
+ //LbmFloat velRelNorm = norm(velRel);
+ LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3
+
+ LbmVec fb = -rwgrav* pvolume *rhoWater;
+ LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater;
+ LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize);
+ /*if(debugOutCounter<0) {
+ errMsg("PIT","BTEST1 vol="<<pvolume<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel);
+ errMsg("PIT","BTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscW="<<viscWater<<" ss/mb="<<(timestep/(pvolume*rhoAir)));
+ errMsg("PIT","BTEST2 grav="<<rwgrav<<" " );
+ errMsg("PIT","BTEST2 change="<<(change)<<" fb="<<(fb)<<" fd="<<(fd)<<" ");
+ errMsg("PIT","BTEST2 change="<<norm(change)<<" fb="<<norm(fb)<<" fd="<<norm(fd)<<" ");
+ } // DEBUG */
+
+ LbmVec fd2 = (LbmVec(vx,vy,vz)-vec2L(p->getVel())) * 6.0*M_PI*radius* (1e-3); //viscWater;
+ LbmFloat w = 0.99;
+ vz = (1.0-w)*vz + w*(p->getVel()[2]-0.5*(p->getSize()/5.0)*mLevel[level].gravity[2]);
+ v = ntlVec3Gfx(vx,vy,vz)+vec2G(fd2);
+ p->setVel( v );
+ } else {
+ // non phys, half old, half fluid, use slightly slower acc
+ v = v*0.5 + ntlVec3Gfx(vx,vy,vz)* 0.5-vec2G(mLevel[level].gravity)*0.5;
+ p->setVel( v * 0.99 );
}
-
- //v += change;
- //v += ntlVec3Gfx(vx,vy,vz);
- LbmVec fd2 = (LbmVec(vx,vy,vz)-vec2L(p->getVel())) * 6.0*M_PI*radius* (1e-3); //viscWater;
- LbmFloat w = 0.99;
- vz = (1.0-w)*vz + w*(p->getVel()[2]-0.5*(p->getSize()/5.0)*mLevel[mMaxRefine].gravity[2]);
- v = ntlVec3Gfx(vx,vy,vz)+vec2G(fd2);
+ p->advanceVel();
+
} else if(p->getType()==PART_TRACER) {
v = ntlVec3Gfx(vx,vy,vz);
- CellFlagType fflag = RFLAG(mMaxRefine, i,j,k, workSet);
+ CellFlagType fflag = RFLAG(level, i,j,k, workSet);
if(fflag&(CFFluid|CFInter) ) { p->setInFluid(true);
} else { p->setInFluid(false); }
@@ -801,16 +773,17 @@ void LbmFsgrSolver::advanceParticles() {
} else {
// move inwards along normal, make sure normal is valid first
- const int lev = mMaxRefine;
+ // todo use class funcs!
+ const int lev = level;
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(i>=mSizex-1) { nx = 1.; nonorm = true; }
if(j<=0) { ny = -1.; nonorm = true; }
- if(j>=this->mSizey-1) { ny = 1.; nonorm = true; }
+ if(j>=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; }
+ if(k>=mSizez-1) { nz = 1.; nonorm = true; }
# endif // LBMDIM==3
if(!nonorm) {
FFGET_NORM(nv1,dE); FFGET_NORM(nv2,dW);
@@ -824,24 +797,21 @@ void LbmFsgrSolver::advanceParticles() {
nz = 0.;
# endif // LBMDIM==3
} else {
- v = p->getVel() + vec2G(mLevel[mMaxRefine].gravity);
+ v = p->getVel() + vec2G(mLevel[level].gravity);
}
-
- p->advanceVec( (ntlVec3Gfx(nx,ny,nz)) * -0.1 ); // + vec2G(mLevel[mMaxRefine].gravity);
- //if(normNoSqrt(v)<LBM_EPSILON) v = mLevel[mMaxRefine].gravity;
+ p->advanceVec( (ntlVec3Gfx(nx,ny,nz)) * -0.1 ); // + vec2G(mLevel[level].gravity);
}
}
p->setVel( v );
p->advanceVel();
- //errMsg("PPPP"," pos"<<p->getPos()<<" "<<p->getVel() );
}
// drop handling
else if(p->getType()==PART_DROP) {
ntlVec3Gfx v = p->getVel(); // dampen...
- if(1) {
+ if(mPartUsePhysModel) {
LbmFloat radius = p->getSize() * minDropSize;
LbmVec velPart = vec2L(p->getVel()) *cellsize /timestep; // * cellsize / timestep; // L2RW, lattice velocity
LbmVec velRel = velAir - velPart;
@@ -857,39 +827,98 @@ void LbmFsgrSolver::advanceParticles() {
LbmVec fg = rwgrav * mb;// * (1.0-rhoAir/rhoWater);
LbmVec fd = velRel* velRelNorm* cd*M_PI *rhoAir *0.5 *radius*radius;
LbmVec change = (fg+ fd ) *timestep / mb *(timestep/cellsize);
-
- //actCnt++; // should be after active test
- if(actCnt<0) {
- errMsg("\nPIT","NTEST1 mb="<<mb<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel<<" pgetVel="<<p->getVel() );
- //errMsg("PIT","NTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscAir="<<viscAir<<" ss/mb="<<(timestep/mb));
- //errMsg("PIT","NTEST2 grav="<<rwgrav<<" mb="<<mb<<" "<<" cd="<<cd );
- //errMsg("PIT","NTEST2 change="<<norm(change)<<" fg="<<norm(fg)<<" fd="<<norm(fd)<<" ");
- }
+ //if(k>0) { errMsg("\nPIT","NTEST1 mb="<<mb<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel<<" pgetVel="<<p->getVel() ); }
v += vec2G(change);
p->setVel(v);
// NEW
} else {
- p->setVel( v * 0.999 ); // dampen...
- p->setVel( v ); // DEBUG!
- p->addToVel( vec2G(mLevel[mMaxRefine].gravity) );\
+ p->setVel( v );
+ int gravk = (int)(p->getPos()[2]+mLevel[level].gravity[2]);
+ if(gravk>=0 && gravk<mSizez && RFLAG(level, i,j,gravk, workSet)&CFBnd) {
+ // dont add for "resting" parts
+ v[2] = 0.;
+ p->setVel( v*0.9 ); // restdamping
+ } else {
+ p->addToVel( vec2G(mLevel[level].gravity) );
+ }
} // OLD
p->advanceVel();
if(p->getStatus()&PART_IN) { // IN
if(k<cutval) { DEL_PART; continue; }
- if(k<=this->mSizez-1-cutval){
- //if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFEmpty|CFInter)) {
- if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFEmpty|CFInter|CFBnd)) {
+ if(k<=mSizez-1-cutval){
+ CellFlagType pflag = RFLAG(level, i,j,k, workSet);
+ //errMsg("PIT move"," at "<<PRINT_IJK<<" flag"<<convertCellFlagType2String(pflag) );
+ if(pflag & (CFBnd)) {
+ handleObstacleParticle(p);
+ continue;
+ } else if(pflag & (CFEmpty)) {
// still ok
- // shipt3 } else if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFInter) ){
- } else if( RFLAG(mMaxRefine, i,j,k, workSet) & (CFFluid|CFUnused) ){
+ } else if((pflag & CFInter)
+ //&&(!(RFLAG(level, i,j,k, workSet)& CFNoNbFluid))
+ ) {
+ // add to no nb fluid i.f.'s, so skip if interface with fluid nb
+ } else if(pflag & (CFFluid|CFUnused|CFInter) ){
+ // add dropmass again, (these are only interf. with nonbfl.)
+ int oi= (int)(pos[0]-1.25*v[0]+0.5);
+ int oj= (int)(pos[1]-1.25*v[1]+0.5);
+ int ok= (int)(pos[2]-1.25*v[2]+0.5);
+ const LbmFloat size = p->getSize();
+ const LbmFloat dropmass = ParticleObject::getMass(mPartDropMassSub*size);
+ bool orgcellok = false;
+ if( RFLAG(level, oi,oj,ok, workSet) & (CFInter) ){
+ orgcellok = true;
+ } else {
+ // search upward for interface
+ oi=i; oj=j; ok=k;
+ for(int kk=0; kk<5 && ok<=mSizez-1; kk++) {
+ ok++;
+ if( RFLAG(level, oi,oj,ok, workSet) & (CFInter) ){
+ kk = 5; orgcellok = true;
+ }
+ }
+ }
+
+ //errMsg("PTIMPULSE"," new v"<<v<<" at "<<PRINT_VEC(oi,oj,ok)<<" , was "<<PRINT_VEC(i,j,k)<<" ok "<<orgcellok );
+ if(orgcellok) {
+ QCELL(level, oi,oj,ok, workSet, dMass) += dropmass;
+ QCELL(level, oi,oj,ok, workSet, dFfrac) += dropmass; // assume rho=1?
+
+ if(RFLAG(level, oi,oj,ok, workSet) & CFNoBndFluid){
+ // check speed, perhaps normalize
+ gfxReal vlensqr = normNoSqrt(v);
+ if(vlensqr > 0.166*0.166) {
+ v *= 1./sqrtf(vlensqr)*0.166;
+ }
+ // compute cell velocity
+ LbmFloat cellVelSqr = 0.;
+ LbmFloat *tcel = RACPNT(level, oi,oj,ok, workSet);
+ LbmFloat velUx=0., velUy=0., velUz=0.;
+ FORDF0 {
+ velUx += (this->dfDvecX[l]*RAC(tcel,l));
+ velUy += (this->dfDvecY[l]*RAC(tcel,l));
+ velUz += (this->dfDvecZ[l]*RAC(tcel,l));
+ }
+ // add impulse
+ /*cellVelSqr = velUx*velUx+ velUy*velUy+ velUz*velUz;
+ //errMsg("PTIMPULSE"," new v"<<v<<" cvs"<<cellVelSqr<<"="<<sqrt(cellVelSqr));
+ if(cellVelSqr< 0.166*0.166) {
+ FORDF1 {
+ const LbmFloat add = 3. * dropmass * this->dfLength[l]*(v[0]*this->dfDvecX[l]+v[1]*this->dfDvecY[l]+v[2]*this->dfDvecZ[l]);
+ RAC(tcel,l) += add;
+ } } // */
+ } // only add impulse away from obstacles!
+ } // orgcellok
+
// FIXME make fsgr treatment
P_CHANGETYPE(p, PART_FLOAT ); continue;
// jitter in cell to prevent stacking when hitting a steep surface
- 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;
+ ntlVec3Gfx cpos = p->getPos();
+ cpos[0] += (rand()/(RAND_MAX+1.0))-0.5;
+ cpos[1] += (rand()/(RAND_MAX+1.0))-0.5;
+ cpos[2] += (rand()/(RAND_MAX+1.0))-0.5;
+ p->setPos(cpos);
} else {
DEL_PART;
this->mNumParticlesLost++;
@@ -900,7 +929,7 @@ void LbmFsgrSolver::advanceParticles() {
if(useff) { mpTest->handleParticle(p, i,j,k); }
else{ DEL_PART; }
# else // LBM_INCLUDE_TESTSOLVERS==1
- { DEL_PART; }
+ DEL_PART;
# endif // LBM_INCLUDE_TESTSOLVERS==1
}
@@ -908,63 +937,35 @@ void LbmFsgrSolver::advanceParticles() {
// inter particle
else if(p->getType()==PART_INTER) {
+ // unused!?
if(p->getStatus()&PART_IN) { // IN
- if((k<cutval)||(k>this->mSizez-1-cutval)) {
+ if((k<cutval)||(k>mSizez-1-cutval)) {
// undecided particle above or below... remove?
DEL_PART;
}
- if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFInter ) ) {
+ CellFlagType pflag = RFLAG(level, i,j,k, workSet);
+ if(pflag& CFInter ) {
// still ok
- } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), (CFFluid|CFUnused) ) ) {
- //errMsg("PIT","NEWBUB pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) );
-
- //P_CHANGETYPE(p, PART_BUBBLE ); continue;
- // currently bubbles off! DEBUG!
- //DEL_PART; // DEBUG bubbles off for siggraph
+ } else if(pflag& (CFFluid|CFUnused) ) {
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()) );
+ } else if(pflag& CFEmpty ) {
P_CHANGETYPE(p, PART_DROP ); continue;
- } else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFBnd ) ) {
- // 060423 new test
+ } else if(pflag& CFBnd ) {
P_CHANGETYPE(p, PART_FLOAT ); continue;
}
} else { // OUT
// undecided particle outside... remove?
DEL_PART;
- //P_CHANGETYPE(p, PART_FLOAT ); continue;
}
}
// float particle
else if(p->getType()==PART_FLOAT) {
- // test - delte on boundary!?
- //if( (i<=cutval)||(i>=this->mSizex-1-cutval)|| (j<=cutval)||(j>=this->mSizey-1-cutval)) { DEL_PART; } // DEBUG TEST
-
-# 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
- const int fhCheckh = (int)(mpTest->mFluidHeight*1.25);
- const LbmFloat fhProbh = 25.;
- if((useff)&&(k>fhCheckh)) {
- LbmFloat fac = (LbmFloat)(k-fhCheckh)/(LbmFloat)(fhProbh*(mLevel[mMaxRefine].lSizez-fhCheckh));
- prob /= fac;
- }
- //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;}
- // */
-
-# endif // LBM_INCLUDE_TESTSOLVERS==1
if(p->getStatus()&PART_IN) { // IN
- //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);
+ // not valid for mass...
vx = vy = vz = 0.0;
// define from particletracer.h
@@ -973,11 +974,10 @@ void LbmFsgrSolver::advanceParticles() {
int ccnt=0;
for(int kk=0;kk<DEPTH_AVG;kk+=1) {
if((k-kk)<1) continue;
- if(RFLAG(mMaxRefine, i,j,k, workSet)&(CFInter)) {} else continue;
+ if(RFLAG(level, i,j,k, workSet)&(CFInter)) {} else continue;
ccnt++;
FORDF1{
- LbmFloat cdf = QCELL(mMaxRefine, i,j,k-kk, workSet, l);
- //df[l] = cdf;
+ LbmFloat cdf = QCELL(level, i,j,k-kk, workSet, l);
vx += (this->dfDvecX[l]*cdf);
vy += (this->dfDvecY[l]*cdf);
vz += (this->dfDvecZ[l]*cdf);
@@ -995,55 +995,26 @@ void LbmFsgrSolver::advanceParticles() {
vy += (rand()/(RAND_MAX+1.0))*(FLOAT_JITTER*0.2)-(FLOAT_JITTER*0.2*0.5);
//bool delfloat = false;
- if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), (CFFluid|CFUnused) ) ) {
+ if( ( RFLAG(level, i,j,k, workSet)& (CFFluid|CFUnused) ) ) {
// in fluid cell
- /*if((1) && (k<this->mSizez-3) &&
- (
- TESTFLAG( RFLAG(mMaxRefine, i,j,k+1, workSet), CFInter ) ||
- TESTFLAG( RFLAG(mMaxRefine, i,j,k+2, workSet), CFInter )
- ) ) {
- vz = p->getVel()[2]-0.5*mLevel[mMaxRefine].gravity[2];
- if(vz<0.0) vz=0.0;
- } else delfloat=true;
- // 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...
+ vz = p->getVel()[2]-1.0*mLevel[level].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 ) ) {
+ } else if( ( RFLAG(level, i,j,k, workSet)& CFBnd ) ) {
+ // force downwards movement, move below obstacle...
+ //vz = p->getVel()[2]+1.0*mLevel[level].gravity[2]; // fall...
+ //if(vz>0.) vz=0.;
+ DEL_PART;
+ } else if( ( RFLAG(level, 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) && (
- 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
+ } else { // all else...
+ if( ( RFLAG(level, i,j,k-1, workSet)& (CFFluid|CFInter) ) ) {
+ vz = p->getVel()[2]+2.0*mLevel[level].gravity[2]; // fall...
+ if(vz>0.) vz=0.; }
+ else { DEL_PART; }
}
- //if(delfloat) DEL_PART;
- /*
- // move down from empty
- else if( TESTFLAG( RFLAG(mMaxRefine, i,j,k, workSet), CFEmpty ) ) {
- vz = p->getVel()[2]+0.5*mLevel[mMaxRefine].gravity[2];
- if(vz>0.0) vz=0.0;
- //DEL_PART; // ????
- } else { DEL_PART; } // */
- //vz = 0.0; // DEBUG
p->setVel( vec2G( ntlVec3Gfx(vx,vy,vz) ) ); //?
- //p->setVel( vec2G(v)*0.75 + p->getVel()*0.25 ); //?
p->advanceVel();
- //errMsg("PIT","IN pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) );
} else {
#if LBM_INCLUDE_TESTSOLVERS==1
if(useff) { mpTest->handleParticle(p, i,j,k); }
@@ -1051,19 +1022,17 @@ void LbmFsgrSolver::advanceParticles() {
#else // LBM_INCLUDE_TESTSOLVERS==1
DEL_PART;
#endif // LBM_INCLUDE_TESTSOLVERS==1
- //errMsg("PIT","OUT pit "<< (*pit).getPos()<<" status:"<<convertFlags2String((*pit).getFlags()) );
}
// additional bnd jitter
- if((0) && (useff) && (p->getLifeTime()<3.*mLevel[mMaxRefine].timestep)) {
+ if((0) && (useff) && (p->getLifeTime()<3.*mLevel[level].timestep)) {
// use half butoff border 1/8
- int maxdw = (int)(mLevel[mMaxRefine].lSizex*0.125*0.5);
+ int maxdw = (int)(mLevel[level].lSizex*0.125*0.5);
if(maxdw<3) maxdw=3;
- if((j>=0)&&(j<=this->mSizey-1)) {
+ if((j>=0)&&(j<=mSizey-1)) {
if(ABS(i-( cutval))<maxdw) { p->advance( FLOAT_JITTBNDRAND( ABS(i-( cutval))), 0.,0.); }
- if(ABS(i-(this->mSizex-1-cutval))<maxdw) { p->advance( FLOAT_JITTBNDRAND( ABS(i-(this->mSizex-1-cutval))), 0.,0.); }
+ if(ABS(i-(mSizex-1-cutval))<maxdw) { p->advance( FLOAT_JITTBNDRAND( ABS(i-(mSizex-1-cutval))), 0.,0.); }
}
- //if( (i<cutval)||(i>this->mSizex-1-cutval)|| //(j<cutval)||(j>this->mSizey-1-cutval)
}
} // PART_FLOAT
@@ -1080,9 +1049,8 @@ void LbmFsgrSolver::notifySolverOfDump(int dumptype, int frameNr,char *frameNrSt
int workSet = mLevel[mMaxRefine].setCurr;
std::ostringstream name;
- // debug - raw dump of ffrac values
- if(getenv("ELBEEM_RAWDEBUGDUMP")) {
- //name <<"fill_" << this->mStepCnt <<".dump";
+ // debug - raw dump of ffrac values, as text!
+ if(mDumpRawText) {
name << outfilename<< frameNrStr <<".dump";
FILE *file = fopen(name.str().c_str(),"w");
if(file) {
@@ -1108,29 +1076,154 @@ void LbmFsgrSolver::notifySolverOfDump(int dumptype, int frameNr,char *frameNrSt
} // file
} // */
- if(getenv("ELBEEM_BINDEBUGDUMP")) {
- name << outfilename<< frameNrStr <<".bdump";
- FILE *file = fopen(name.str().c_str(),"w");
- if(file) {
- for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) {
- for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) {
- for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) {
- float val = 0.;
- if(RFLAG(mMaxRefine, i,j,k, workSet) & CFInter) {
- val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac);
- if(val<0.) val=0.;
- if(val>1.) val=1.;
+
+ if(mDumpRawBinary) {
+ if(!mDumpRawBinaryZip) {
+ // unzipped, only fill
+ name << outfilename<< frameNrStr <<".bdump";
+ FILE *file = fopen(name.str().c_str(),"w");
+ if(file) {
+ for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) {
+ for(int j=0;j<mLevel[mMaxRefine].lSizey-0;j++) {
+ for(int i=0;i<mLevel[mMaxRefine].lSizex-0;i++) {
+ float val = 0.;
+ if(RFLAG(mMaxRefine, i,j,k, workSet) & CFInter) {
+ val = QCELL(mMaxRefine,i,j,k, mLevel[mMaxRefine].setCurr,dFfrac);
+ if(val<0.) val=0.;
+ if(val>1.) val=1.;
+ }
+ if(RFLAG(mMaxRefine, i,j,k, workSet) & CFFluid) val = 1.;
+ fwrite( &val, sizeof(val), 1, file); // binary
+ }
+ }
+ }
+ fclose(file);
+ } // file
+ } // unzipped
+ else {
+ // zipped, use iso values
+ prepareVisualization();
+ name << outfilename<< frameNrStr <<".bdump.gz";
+ gzFile gzf = gzopen(name.str().c_str(),"wb9");
+ if(gzf) {
+ // write size
+ int s;
+ s=mSizex; gzwrite(gzf, &s, sizeof(s));
+ s=mSizey; gzwrite(gzf, &s, sizeof(s));
+ s=mSizez; gzwrite(gzf, &s, sizeof(s));
+
+ // write isovalues
+ for(int k= getForZMinBnd(); k< getForZMaxBnd(mMaxRefine); ++k) {
+ for(int j=0;j<mLevel[mMaxRefine].lSizey;j++) {
+ for(int i=0;i<mLevel[mMaxRefine].lSizex;i++) {
+ float val = 0.;
+ val = *mpIso->lbmGetData( i,j,k );
+ gzwrite(gzf, &val, sizeof(val));
}
- if(RFLAG(mMaxRefine, i,j,k, workSet) & CFFluid) val = 1.;
- fwrite( &val, sizeof(val), 1, file); // binary
}
}
+ gzclose(gzf);
+ } // gzf
+ } // zip
+ } // bin dump
+
+ dumptype = 0; frameNr = 0; // get rid of warning
+}
+
+/*! move a particle at a boundary */
+void LbmFsgrSolver::handleObstacleParticle(ParticleObject *p) {
+ //if(normNoSqrt(v)<=0.) continue; // skip stuck
+ /*
+ p->setVel( v * -1. ); // revert
+ p->advanceVel(); // move back twice...
+ if( RFLAG(mMaxRefine, i,j,k, workSet)& (CFBndNoslip)) {
+ p->setVel( v * -0.5 ); // revert & dampen
+ }
+ p->advanceVel();
+ // */
+ // TODO mark/remove stuck parts!?
+
+ const int level = mMaxRefine;
+ const int workSet = mLevel[level].setCurr;
+ LbmVec v = vec2L( p->getVel() );
+ if(normNoSqrt(v)<=0.) {
+ p->setVel(vec2G(mLevel[level].gravity));
+ }
+
+ CellFlagType pflag = CFBnd;
+ ntlVec3Gfx posOrg(p->getPos());
+ ntlVec3Gfx npos(0.);
+ int ni=1,nj=1,nk=1;
+ int tries = 0;
+
+ // try to undo movement
+ p->advanceVec( (p->getVel()-vec2G(mLevel[level].gravity)) * -2.);
+
+ npos = p->getPos(); ni= (int)npos[0];
+ nj= (int)npos[1]; nk= (int)npos[2];
+ if(LBMDIM==2) { nk = 0; }
+ //errMsg("BOUNDCPAR"," t"<<PRINT_VEC(ni,nj,nk)<<" v"<<v<<" p"<<npos);
+
+ // delete out of domain
+ if(!checkDomainBounds(level,ni,nj,nk)) {
+ //errMsg("BOUNDCPAR"," DEL! ");
+ p->setActive( false );
+ return;
+ }
+ pflag = RFLAG(level, ni,nj,nk, workSet);
+
+ // try to force particle out of boundary
+ bool haveNorm = false;
+ LbmVec bnormal;
+ if(pflag&CFBnd) {
+ npos = posOrg; ni= (int)npos[0];
+ nj= (int)npos[1]; nk= (int)npos[2];
+ if(LBMDIM==2) { nk = 0; }
+
+ computeObstacleSurfaceNormalAcc(ni,nj,nk, &bnormal[0]);
+ haveNorm = true;
+ normalize(bnormal);
+ bnormal *= 0.25;
+
+ tries = 1;
+ while(pflag&CFBnd && tries<=5) {
+ // use increasing step sizes
+ p->advanceVec( vec2G( bnormal *0.5 *(gfxReal)tries ) );
+ npos = p->getPos();
+ ni= (int)npos[0];
+ nj= (int)npos[1];
+ nk= (int)npos[2];
+
+ // delete out of domain
+ if(!checkDomainBounds(level,ni,nj,nk)) {
+ //errMsg("BOUNDCPAR"," DEL! ");
+ p->setActive( false );
+ return;
}
- fclose(file);
- } // file
+ pflag = RFLAG(level, ni,nj,nk, workSet);
+ tries++;
+ }
+
+ // really stuck, delete...
+ if(pflag&CFBnd) {
+ p->setActive( false );
+ return;
+ }
}
- dumptype = 0; frameNr = 0; // get rid of warning
+ // not in bound anymore!
+ if(!haveNorm) {
+ CellFlagType *bflag = &RFLAG(level, ni,nj,nk, workSet);
+ LbmFloat *bcell = RACPNT(level, ni,nj,nk, workSet);
+ computeObstacleSurfaceNormal(bcell,bflag, &bnormal[0]);
+ }
+ normalize(bnormal);
+ LbmVec normComp = bnormal * dot(vec2L(v),bnormal);
+ //errMsg("BOUNDCPAR","bnormal"<<bnormal<<" normComp"<<normComp<<" newv"<<(v-normComp) );
+ v = (v-normComp)*0.9; // only move tangential
+ v *= 0.9; // restdamping , todo use timestep
+ p->setVel(vec2G(v));
+ p->advanceVel();
}
/*****************************************************************************/
@@ -1320,6 +1413,13 @@ ntlVec3Gfx LbmFsgrSolver::getCellSize ( CellIdentifierInterface* basecid)
LbmFloat LbmFsgrSolver::getCellDensity ( CellIdentifierInterface* basecid,int set) {
stdCellId *cid = convertBaseCidToStdCid(basecid);
+ // skip non-fluid cells
+ if(RFLAG(cid->level, cid->x,cid->y,cid->z, set)&(CFFluid|CFInter)) {
+ // ok go on...
+ } else {
+ return 0.;
+ }
+
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
@@ -1744,7 +1844,7 @@ void LbmFsgrSolver::lbmDebugDisplay(int dispset) {
glDisable( GL_LIGHTING ); // dont light lines
#if LBM_INCLUDE_TESTSOLVERS==1
- if((!mUseTestdata)|| (mUseTestdata)&&(mpTest->mDebugvalue1<=0.0)) {
+ if((!mUseTestdata)|| (mUseTestdata)&&(mpTest->mFarfMode<=0)) {
#endif // LBM_INCLUDE_TESTSOLVERS==1
LbmFsgrSolver::CellIdentifier cid = this->getFirstCell();
diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp
index 1aee43fe8bd..ad827efa2fc 100644
--- a/intern/elbeem/intern/utilities.cpp
+++ b/intern/elbeem/intern/utilities.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Global C style utility funcions
*
@@ -28,6 +28,7 @@
#include <png.h>
#endif
#endif // NOPNG
+#include <zlib.h>
// global debug level
#ifdef DEBUG
@@ -64,16 +65,28 @@ char* getElbeemErrorString(void) { return gElbeemErrorString; }
myTime_t globalIntervalTime = 0;
//! color output setting for messages (0==off, else on)
#ifdef WIN32
-int globalColorSetting = 0;
+// switch off first call
+#define DEF_globalColorSetting -1
#else // WIN32
-int globalColorSetting = 1;
+// linux etc., on by default
+#define DEF_globalColorSetting 1
#endif // WIN32
+int globalColorSetting = DEF_globalColorSetting; // linux etc., on by default
int globalFirstEnvCheck = 0;
+void resetGlobalColorSetting() { globalColorSetting = DEF_globalColorSetting; }
// global string for formatting vector output, TODO test!?
char *globVecFormatStr = "V[%f,%f,%f]";
+// global mp on/off switch
+bool glob_mpactive = false;
+// global access to mpi index, for debugging (e.g. in utilities.cpp)
+int glob_mpnum = -1;
+int glob_mpindex = -1;
+int glob_mppn = -1;
+
+
//-----------------------------------------------------------------------------
// helper function that converts a string to integer,
// and returns an alternative value if the conversion fails
@@ -126,7 +139,7 @@ int writePng(const char *fileName, unsigned char **rowsp, int w, int h)
//FILE *fp = fopen(fileName, "wb");
FILE *fp = NULL;
- char *doing = "open for writing";
+ string doing = "open for writing";
if (!(fp = fopen(fileName, "wb"))) goto fail;
if(!png_ptr) {
@@ -162,6 +175,40 @@ fail:
if(png_ptr || info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
return -1;
}
+#else // NOPNG
+// fallback - write ppm
+int writePng(const char *fileName, unsigned char **rowsp, int w, int h)
+{
+ gzFile gzf;
+ string filentemp(fileName);
+ // remove suffix
+ if((filentemp.length()>4) && (filentemp[filentemp.length()-4]=='.')) {
+ filentemp[filentemp.length()-4] = '\0';
+ }
+ std::ostringstream filennew;
+ filennew << filentemp.c_str();
+ filennew << ".ppm.gz";
+
+ gzf = gzopen(filennew.str().c_str(), "wb9");
+ if(!gzf) goto fail;
+
+ gzprintf(gzf,"P6\n%d %d\n255\n",w,h);
+ // output binary pixels
+ for(int j=0;j<h;j++) {
+ for(int i=0;i<h;i++) {
+ // remove alpha values
+ gzwrite(gzf,&rowsp[j][i*4],3);
+ }
+ }
+
+ gzclose( gzf );
+ errMsg("writePng/ppm","Write_png/ppm: wrote to "<<filennew.str()<<".");
+ return 0;
+
+fail:
+ errMsg("writePng/ppm","Write_png/ppm: could not write to "<<filennew.str()<<" !");
+ return -1;
+}
#endif // NOPNG
@@ -243,7 +290,21 @@ static string col_purple ( "\033[0;35m");
static string col_bright_purple ( "\033[1;35m");
static string col_neutral ( "\033[0m");
static string col_std = col_bright_gray;
+
+std::ostringstream globOutstr;
+bool globOutstrForce=false;
+#define DM_NONE 100
+void messageOutputForce(string from) {
+ bool org = globOutstrForce;
+ globOutstrForce = true;
+ messageOutputFunc(from, DM_NONE, "\n", 0);
+ globOutstrForce = org;
+}
+
void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
+ // fast skip
+ if((id!=DM_FATAL)&&(gDebugLevel<=0)) return;
+
if(interval>0) {
myTime_t currTime = getTime();
if((currTime - globalIntervalTime)>interval) {
@@ -254,14 +315,16 @@ void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
}
// colors off?
- if((globalColorSetting==0) || (id==DM_FATAL) ){
+ if( (globalColorSetting == -1) || // off for e.g. win32
+ ((globalColorSetting==1) && ((id==DM_FATAL)||( getenv("ELBEEM_NOCOLOROUT") )) )
+ ) {
// only reset once
col_std = col_black = col_dark_gray = col_bright_gray =
col_red = col_bright_red = col_green =
col_bright_green = col_bright_yellow =
col_yellow = col_cyan = col_bright_cyan =
col_purple = col_bright_purple = col_neutral = "";
- globalColorSetting=1;
+ globalColorSetting = 0;
}
std::ostringstream sout;
@@ -288,6 +351,9 @@ void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
case DM_FATAL:
sout << col_red << " fatal("<<gElbeemState<<"):" << col_red;
break;
+ case DM_NONE:
+ // only internal debugging msgs
+ break;
default:
// this shouldnt happen...
sout << col_red << " --- messageOutputFunc error: invalid id ("<<id<<") --- aborting... \n\n" << col_std;
@@ -303,19 +369,61 @@ void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
sout << "\n"; // add newline for output
}
-#ifdef WIN32
- // debug level is >0 anyway, so write to file...
- // TODO generate some reasonable path?
- FILE *logf = fopen("elbeem_debug_log.txt","a+");
- // dont complain anymore here...
- if(logf) {
- fprintf(logf, "%s",sout.str().c_str() );
- fclose(logf);
+ // determine output - file==1/stdout==0 / globstr==2
+ char filen[256];
+ strcpy(filen,"debug_unini.txt");
+ int fileout = false;
+#if ELBEEM_MPI==1
+ std::ostringstream mpin;
+ if(glob_mpindex>=0) {
+ mpin << "elbeem_log_"<< glob_mpindex <<".txt";
+ } else {
+ mpin << "elbeem_log_ini.txt";
}
-#else // WIN32
- fprintf(stdout, "%s",sout.str().c_str() );
- if(id!=DM_DIRECT) fflush(stdout);
+ fileout = 1;
+ strncpy(filen, mpin.str().c_str(),255); filen[255]='\0';
+#else
+ strncpy(filen, "elbeem_debug_log.txt",255);
+#endif
+
+#ifdef WIN32
+ // windows causes trouble with direct output
+ fileout = 1;
#endif // WIN32
+
+#if PARALLEL==1
+ fileout = 2;// buffer out, switch off again...
+ if(globOutstrForce) fileout=1;
+#endif
+ if(getenv("ELBEEM_FORCESTDOUT")) {
+ fileout = 0;// always direct out
+ }
+ //fprintf(stdout,"out deb %d, %d, '%s',l%d \n",globOutstrForce,fileout, filen, globOutstr.str().size() );
+
+#if PARALLEL==1
+#pragma omp critical
+#endif // PARALLEL==1
+ {
+ if(fileout==1) {
+ // debug level is >0 anyway, so write to file...
+ FILE *logf = fopen(filen,"a+");
+ // dont complain anymore here...
+ if(logf) {
+ if(globOutstrForce) {
+ fprintf(logf, "%s",globOutstr.str().c_str() );
+ globOutstr.str(""); // reset
+ }
+ fprintf(logf, "%s",sout.str().c_str() );
+ fclose(logf);
+ }
+ } else if(fileout==2) {
+ globOutstr << sout.str();
+ } else {
+ // normal stdout output
+ fprintf(stdout, "%s",sout.str().c_str() );
+ if(id!=DM_DIRECT) fflush(stdout);
+ }
+ } // omp crit
}
// helper functions from external program using elbeem lib (e.g. Blender)
@@ -323,14 +431,19 @@ void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
extern "C"
void elbeemCheckDebugEnv(void) {
const char *strEnvName = "BLENDER_ELBEEMDEBUG";
+ const char *strEnvName2 = "ELBEEM_DEBUGLEVEL";
if(globalFirstEnvCheck) return;
if(getenv(strEnvName)) {
gDebugLevel = atoi(getenv(strEnvName));
- if(gDebugLevel< 0) gDebugLevel = 0;
- if(gDebugLevel>10) gDebugLevel = 0; // only use valid values
if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName<<"'='"<<getenv(strEnvName)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1);
}
+ if(getenv(strEnvName2)) {
+ gDebugLevel = atoi(getenv(strEnvName2));
+ if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName2<<"'='"<<getenv(strEnvName2)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1);
+ }
+ if(gDebugLevel< 0) gDebugLevel = 0;
+ if(gDebugLevel>10) gDebugLevel = 0; // only use valid values
globalFirstEnvCheck = 1;
}
@@ -367,7 +480,8 @@ double elbeemEstimateMemreq(int res,
double memreq = -1.0;
string memreqStr("");
- calculateMemreqEstimate(resx,resy,resz, refine, &memreq, &memreqStr );
+ // ignore farfield for now...
+ calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, &memreqStr );
if(retstr) {
// copy at max. 32 characters
diff --git a/intern/elbeem/intern/utilities.h b/intern/elbeem/intern/utilities.h
index 57a956c64d9..4d887c3f99b 100644
--- a/intern/elbeem/intern/utilities.h
+++ b/intern/elbeem/intern/utilities.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
*
* Global C style utility funcions
*
@@ -115,6 +115,8 @@ 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);
+//! reset color output for elbeem init
+void resetGlobalColorSetting();
/*! print some vector from 3 values e.g. for ux,uy,uz */
@@ -144,10 +146,8 @@ bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker);
PRINT_VEC( (mpV[(t).getPoints()[2]][0]),(mpV[(t).getPoints()[2]][1]),(mpV[(t).getPoints()[2]][2]) )<<" } "
-#ifndef NOPNG
// write png image
int writePng(const char *fileName, unsigned char **rowsp, int w, int h);
-#endif // NOPNG
/* some useful templated functions
* may require some operators for the classes