yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01069
[svn] r1703 - in trunk: core examples/collider-perf extra/clump gui/py lib/multimethods pkg/common/Engine/MetaEngine pkg/dem/Engine/DeusExMachina pkg/dem/PreProcessor
Author: eudoxos
Date: 2009-03-01 14:29:51 +0100 (Sun, 01 Mar 2009)
New Revision: 1703
Modified:
trunk/core/Interaction.cpp
trunk/core/Interaction.hpp
trunk/examples/collider-perf/perf.py
trunk/extra/clump/Shop.cpp
trunk/gui/py/utils.py
trunk/gui/py/yade-multi
trunk/lib/multimethods/DynLibDispatcher.hpp
trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp
trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp
trunk/pkg/dem/PreProcessor/TriaxialTest.cpp
Log:
1. Fix collider-perf (TriaxialTest has hardcoded dt=0.001 !!!!), set timestep by hand at first
2. Fix Shop:: loading spheres from file (regression from yesterday)
3. Add functorCache to Interaction and to InteractionDispatchers. About 5% improvement, but not yet finished.
4. Add DynLibDispatcher::getFunctor2D
5. Add BexContainer::sync() to other places in triaxial (thrown otherwise)
Modified: trunk/core/Interaction.cpp
===================================================================
--- trunk/core/Interaction.cpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/core/Interaction.cpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -29,6 +29,7 @@
isReal = false;
isNeighbor = true;//NOTE : TriangulationCollider needs that
+ functorCache.geomExists=true;
}
Modified: trunk/core/Interaction.hpp
===================================================================
--- trunk/core/Interaction.hpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/core/Interaction.hpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -15,6 +15,8 @@
typedef int body_id_t;
class InteractionGeometryEngineUnit;
+class InteractionPhysicsEngineUnit;
+class ConstitutiveLaw;
class Interaction : public Serializable
{
@@ -39,6 +41,18 @@
//! swaps order of bodies within the interaction
void swapOrder();
+ //! cache functors that are called for this interaction. Currently used by InteractionDispatchers.
+ struct {
+ // Whether geometry dispatcher exists at all; this is different from !geom, since that can mean we haven't populated the cache yet.
+ // Therefore, geomExists must be initialized to true first (done in Interaction ctor).
+ bool geomExists;
+ // shared_ptr's are initialized to NULLs automagically
+ shared_ptr<InteractionGeometryEngineUnit> geom;
+ shared_ptr<InteractionPhysicsEngineUnit> phys;
+ shared_ptr<ConstitutiveLaw> constLaw;
+ } functorCache;
+
+
#if 0
//! Whether both bodies involved in interaction satisfies given mask; provide rootBody for faster lookup
bool maskBothOK(int mask, MetaBody* rootBody=NULL){return (mask==0) || (Body::byId(id1,rootBody)->maskOK(mask) && Body::byId(id2,rootBody)->maskOK(mask));}
Modified: trunk/examples/collider-perf/perf.py
===================================================================
--- trunk/examples/collider-perf/perf.py 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/examples/collider-perf/perf.py 2009-03-01 13:29:51 UTC (rev 1703)
@@ -17,6 +17,7 @@
O.timingEnabled=True
p=Preprocessor('TriaxialTest',{'importFilename':spheresFile}).load()
+O.dt=utils.PWaveTimeStep()
utils.replaceCollider(StandAloneEngine(collider))
O.step()
Modified: trunk/extra/clump/Shop.cpp
===================================================================
--- trunk/extra/clump/Shop.cpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/extra/clump/Shop.cpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -485,7 +485,7 @@
int i=0;
FOREACH(const string& s, toks){
if(i<3) C[i]=lexical_cast<Real>(s);
- if(i==4) r=lexical_cast<Real>(s);
+ if(i==3) r=lexical_cast<Real>(s);
i++;
}
if(i==0) continue; // empty line, skipped (can be the last one)
Modified: trunk/gui/py/utils.py
===================================================================
--- trunk/gui/py/utils.py 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/gui/py/utils.py 2009-03-01 13:29:51 UTC (rev 1703)
@@ -354,7 +354,6 @@
for i in range(len(names)):
if names[i]=='description': o.tags['description']=values[i]
else:
- print 'Parameter name:',names[i],names[i][0]
if names[i] not in kw.keys():
if (not unknownOk) and names[i][0]!='!': raise NameError("Parameter `%s' has no default value assigned"%names[i])
else: kw.pop(names[i])
Modified: trunk/gui/py/yade-multi
===================================================================
--- trunk/gui/py/yade-multi 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/gui/py/yade-multi 2009-03-01 13:29:51 UTC (rev 1703)
@@ -14,7 +14,7 @@
def saveInfo(self):
log=file(self.log,'a')
log.write("""
-=================== JOB SUMMARY ================
+=================== JOB SUMMARY ================
id : %s
status : %d (%s)
duration: %s
Modified: trunk/lib/multimethods/DynLibDispatcher.hpp
===================================================================
--- trunk/lib/multimethods/DynLibDispatcher.hpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/lib/multimethods/DynLibDispatcher.hpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -442,7 +442,21 @@
#endif
}
- public : bool locateMultivirtualFunctor2D(int& index1, int& index2, shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2)
+ public:
+ /* Return pointer to the functor for two base classes given. Swap is true if the dispatch objects
+ * should be swapped before calling Executor::go.
+ */
+ shared_ptr<Executor> getFunctor2D(shared_ptr<BaseClass1>& base1, shared_ptr<BaseClass2>& base2, bool& swap){
+ int ix1, ix2;
+ if(!locateMultivirtualFunctor2D(ix1,ix2,base1,base2)){
+ return shared_ptr<Executor>();
+ }
+ swap=(bool)(callBacksInfo[ix1][ix2]);
+ return callBacks[ix1][ix2];
+ }
+
+
+ bool locateMultivirtualFunctor2D(int& index1, int& index2, shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2)
{
index1 = base1->getClassIndex();
index2 = base2->getClassIndex();
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -8,6 +8,8 @@
constLawDispatcher=shared_ptr<ConstitutiveLawDispatcher>(new ConstitutiveLawDispatcher);
}
+#define DISPATCH_CACHE
+
void InteractionDispatchers::action(MetaBody* rootBody){
#ifdef YADE_OPENMP
const long size=rootBody->interactions->size();
@@ -17,16 +19,60 @@
#else
FOREACH(shared_ptr<Interaction> I, *rootBody->interactions){
#endif
+ #ifdef DISPATCH_CACHE
+ shared_ptr<Body>& b1=(*rootBody->bodies)[I->getId1()];
+ shared_ptr<Body>& b2=(*rootBody->bodies)[I->getId2()];
+ // we know there is no geometry functor already, take the short path
+ if(!I->functorCache.geomExists) { I->isReal=false; continue; }
+ // no interaction geometry for either of bodies; no interaction possible
+ if(!b1->interactingGeometry || !b2->interactingGeometry) { I->isReal=false; continue; }
+
// InteractionGeometryMetaEngine
+ if(!I->functorCache.geom || !I->functorCache.phys){
+ bool swap=false;
+ I->functorCache.geom=geomDispatcher->getFunctor2D(b1->interactingGeometry,b2->interactingGeometry,swap);
+ // returns NULL ptr if no functor exists; remember that and shortcut
+ if(!I->functorCache.geom) { I->functorCache.geomExists=false; continue; }
+ // arguments for the geom functor are in the reverse order (dispatcher would normally call goReverse).
+ // we don't remember the fact that is reverse, so we swap bodies within the interaction
+ // and can call go in all cases
+ if(swap) { I->swapOrder(); b1=(*rootBody->bodies)[I->getId1()]; b2=(*rootBody->bodies)[I->getId2()]; }
+ }
+ assert(I->functorCache.geom);
+ I->isReal=I->functorCache.geom->go(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3, b2->physicalParameters->se3,I);
+ if(!I->isReal) continue;
+
+ // InteractionPhysicsMetaEngine
+ if(!I->functorCache.phys){
+ bool swap=false; I->functorCache.phys=physDispatcher->getFunctor2D(b1->physicalParameters,b2->physicalParameters,swap);
+ assert(!swap); // InteractionPhysicsEngineUnits are symmetric
+ }
+ assert(I->functorCache.phys);
+ I->functorCache.phys->go(b1->physicalParameters,b2->physicalParameters,I);
+
+ // ConstitutiveLawDispatcher
+ // populating constLaw cache must be done after geom and physics dispatchers have been called, since otherwise the interaction
+ // would not have interactionGeometry and interactionPhysics yet.
+ if(!I->functorCache.constLaw){
+ bool swap=false; I->functorCache.constLaw=constLawDispatcher->getFunctor2D(I->interactionGeometry,I->interactionPhysics,swap);
+ assert(!swap); // reverse call would make no sense, as the arguments are of different types
+ }
+ assert(I->functorCache.constLaw);
+ I->functorCache.constLaw->go(I->interactionGeometry,I->interactionPhysics,I.get(),rootBody);
+
+ #else
const shared_ptr<Body>& b1=Body::byId(I->getId1(),rootBody);
const shared_ptr<Body>& b2=Body::byId(I->getId2(),rootBody);
+ // InteractionGeometryMetaEngine
I->isReal =
b1->interactingGeometry && b2->interactingGeometry && // some bodies do not have interactingGeometry
geomDispatcher->operator()(b1->interactingGeometry, b2->interactingGeometry, b1->physicalParameters->se3, b2->physicalParameters->se3,I);
if(!I->isReal) continue;
// InteractionPhysicsMetaEngine
- physDispatcher->operator()(b1->physicalParameters, b2->physicalParameters,I);
+ // geom may have swapped bodies, get bodies again
+ physDispatcher->operator()(Body::byId(I->getId1(),rootBody)->physicalParameters, Body::byId(I->getId2(),rootBody)->physicalParameters,I);
// ConstitutiveLawDispatcher
constLawDispatcher->operator()(I->interactionGeometry,I->interactionPhysics,I.get(),rootBody);
+ #endif
}
}
Modified: trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -400,6 +400,9 @@
*/
Real TriaxialStressController::ComputeUnbalancedForce(MetaBody * ncb, bool maxUnbalanced)
{
+ #ifdef BEX_CONTAINER
+ ncb->bex.sync();
+ #endif
//compute the mean contact force
Real MeanForce = 0.f;
long nForce = 0;
Modified: trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -104,7 +104,7 @@
void updateStiffness(MetaBody* ncb);
void computeStressStrain(MetaBody* ncb); //Compute stresses on walls as "Vector3r stress[6]", compute meanStress, strain[3] and mean strain
//! Compute the mean/max unbalanced force in the assembly (normalized by mean contact force)
- Real ComputeUnbalancedForce(MetaBody * ncb, bool maxUnbalanced=false);
+ Real ComputeUnbalancedForce(MetaBody * ncb, bool maxUnbalanced=false);
DECLARE_LOGGER;
Modified: trunk/pkg/dem/PreProcessor/TriaxialTest.cpp
===================================================================
--- trunk/pkg/dem/PreProcessor/TriaxialTest.cpp 2009-03-01 01:41:37 UTC (rev 1702)
+++ trunk/pkg/dem/PreProcessor/TriaxialTest.cpp 2009-03-01 13:29:51 UTC (rev 1703)
@@ -266,26 +266,32 @@
/* if _mean_radius is not given (i.e. <=0), then calculate it from box size;
* OTOH, if it is specified, scale the box preserving its ratio and lowerCorner so that the radius can be as requested
*/
- Vector3r dimensions=upperCorner-lowerCorner; Real volume=dimensions.X()*dimensions.Y()*dimensions.Z();
Real porosity=.75;
- Real really_radiusMean;
+
+ vector<BasicSphere> sphere_list;
- if(radiusMean<=0) really_radiusMean=pow(volume*(1-porosity)/(Mathr::PI*(4/3.)*numberOfGrains),1/3.);
+ if(importFilename==""){
+ Vector3r dimensions=upperCorner-lowerCorner; Real volume=dimensions.X()*dimensions.Y()*dimensions.Z();
+ Real really_radiusMean;
+ if(radiusMean<=0) really_radiusMean=pow(volume*(1-porosity)/(Mathr::PI*(4/3.)*numberOfGrains),1/3.);
+ else {
+ bool fixedDims[3];
+ fixedDims[0]=fixedBoxDims.find('x')!=string::npos; fixedDims[1]=fixedBoxDims.find('y')!=string::npos; fixedDims[2]=fixedBoxDims.find('z')!=string::npos;
+ int nScaled=(3-(int)fixedDims[0]+(int)fixedDims[1]+(int)fixedDims[2]);
+ if(nScaled==0) throw std::invalid_argument("At most 2 (not 3) axes can have fixed dimensions in fixedBoxDims if scaling for given radiusMean.");
+ Real boxScaleFactor=radiusMean*pow((4/3.)*Mathr::PI*numberOfGrains/(volume*(1-porosity)),1./nScaled);
+ LOG_INFO("Mean radius value of "<<radiusMean<<" requested, scaling "<<nScaled<<" dimensions by "<<boxScaleFactor);
+ dimensions[0]*=fixedDims[0]?1.:boxScaleFactor; dimensions[1]*=fixedDims[1]?1.:boxScaleFactor; dimensions[2]*=fixedDims[2]?1.:boxScaleFactor;
+ upperCorner=lowerCorner+dimensions;
+ really_radiusMean=radiusMean;
+ }
+ message+=GenerateCloud(sphere_list, lowerCorner, upperCorner, numberOfGrains, radiusStdDev, really_radiusMean, porosity);
+ }
else {
- bool fixedDims[3];
- fixedDims[0]=fixedBoxDims.find('x')!=string::npos; fixedDims[1]=fixedBoxDims.find('y')!=string::npos; fixedDims[2]=fixedBoxDims.find('z')!=string::npos;
- int nScaled=(3-(int)fixedDims[0]+(int)fixedDims[1]+(int)fixedDims[2]);
- if(nScaled==0) throw std::invalid_argument("At most 2 (not 3) axes can have fixed dimensions in fixedBoxDims if scaling for given radiusMean.");
- Real boxScaleFactor=radiusMean*pow((4/3.)*Mathr::PI*numberOfGrains/(volume*(1-porosity)),1./nScaled);
- LOG_INFO("Mean radius value of "<<radiusMean<<" requested, scaling "<<nScaled<<" dimensions by "<<boxScaleFactor);
- dimensions[0]*=fixedDims[0]?1.:boxScaleFactor; dimensions[1]*=fixedDims[1]?1.:boxScaleFactor; dimensions[2]*=fixedDims[2]?1.:boxScaleFactor;
- upperCorner=lowerCorner+dimensions;
- really_radiusMean=radiusMean;
+ if(radiusMean>0) LOG_WARN("radiusMean ignored, since importFilename specified.");
+ sphere_list=Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
}
-
-
-
if(boxWalls)
{
// bottom box
@@ -388,11 +394,7 @@
}
}
-
-
- vector<BasicSphere> sphere_list;
- if(importFilename!="") sphere_list=Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
- else message+=GenerateCloud(sphere_list, lowerCorner, upperCorner, numberOfGrains, radiusStdDev, really_radiusMean, porosity);
+
vector<BasicSphere>::iterator it = sphere_list.begin();
vector<BasicSphere>::iterator it_end = sphere_list.end();
FOREACH(const BasicSphere& it, sphere_list){
@@ -401,10 +403,8 @@
rootBody->bodies->insert(body);
}
-
-
+
return true;
-
}