yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01509
[svn] r1870 - in trunk: core extra pkg/common/Engine/MetaEngine pkg/common/Engine/StandAloneEngine pkg/dem
Author: eudoxos
Date: 2009-07-16 12:16:39 +0200 (Thu, 16 Jul 2009)
New Revision: 1870
Modified:
trunk/core/Body.hpp
trunk/core/InteractionContainer.cpp
trunk/core/InteractionContainer.hpp
trunk/core/PhysicalParameters.hpp
trunk/extra/SConscript
trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
trunk/pkg/dem/ConcretePM.cpp
Log:
1. Remove mutex from requestErase (should be verified to compile on non-openMP machine!)
2. Add mutex to PhysicalParameters, so that body state can be locked while updating from the interaction loop.
3. Add linking with EngineUnits to Tetra (thans Emanuelle)
Modified: trunk/core/Body.hpp
===================================================================
--- trunk/core/Body.hpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/core/Body.hpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -21,6 +21,8 @@
#include<yade/lib-serialization/Serializable.hpp>
#include<yade/lib-multimethods/Indexable.hpp>
+#define ISDYNAMIC_REDEFINED
+
class MetaBody;
/*! \brief Abstract interface for bodies stored in BodyContainer, Body represents the atomic element of simulation.
Modified: trunk/core/InteractionContainer.cpp
===================================================================
--- trunk/core/InteractionContainer.cpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/core/InteractionContainer.cpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -9,18 +9,31 @@
*************************************************************************/
#include "InteractionContainer.hpp"
+#include<omp.h>
void InteractionContainer::requestErase(body_id_t id1, body_id_t id2){
- find(id1,id2)->reset(); bodyIdPair v(id1,id2); //v.push_back(id1); v.push_back(id2);
+ find(id1,id2)->reset(); bodyIdPair v(id1,id2);
#ifdef YADE_OPENMP
- boost::mutex::scoped_lock lock(pendingEraseMutex);
+ threadsPendingErase[omp_get_thread_num()].push_back(v);
+ #else
+ pendingErase.push_back(v);
#endif
- pendingErase.push_back(v);
}
-void InteractionContainer::unconditionalErasePending(){
- FOREACH(const bodyIdPair& p, pendingErase){ erase(p[0],p[1]); }
- pendingErase.clear();
+int InteractionContainer::unconditionalErasePending(){
+ int ret=0;
+ #ifdef YADE_OPENMP
+ // shadow this->pendingErase by the local variable, to share code
+ FOREACH(list<bodyIdPair>& pendingErase, threadsPendingErase){
+ #endif
+ if(pendingErase.size()>0){
+ FOREACH(const bodyIdPair& p, pendingErase){ ret++; erase(p[0],p[1]); }
+ pendingErase.clear();
+ }
+ #ifdef YADE_OPENMP
+ }
+ #endif
+ return ret;
}
@@ -44,6 +57,10 @@
for( ; i!=iEnd ; ++i )
interaction.push_back(*i);
if(serializeSorted) std::sort(interaction.begin(),interaction.end(),compPtrInteraction());
+ #ifdef YADE_OPENMP
+ // copy per-thread erasable pairs to the global attribute that will be serialized
+ FOREACH(const list<bodyIdPair>& threadPendingErase, threadsPendingErase){ pendingErase.insert(pendingErase.end(),threadPendingErase.begin(),threadPendingErase.end()); }
+ #endif
}
}
@@ -58,6 +75,10 @@
for( ; it != itEnd ; ++it)
this->insert(*it);
interaction.clear();
+ #ifdef YADE_OPENMP
+ // copy global deserialized pairs to be erased to the list of thread #0
+ threadsPendingErase[0].insert(threadsPendingErase[0].end(),pendingErase.begin(),pendingErase.end());
+ #endif
}
else
{
Modified: trunk/core/InteractionContainer.hpp
===================================================================
--- trunk/core/InteractionContainer.hpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/core/InteractionContainer.hpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -14,6 +14,7 @@
#include<boost/thread/mutex.hpp>
#include<iostream>
#include<boost/range.hpp>
+#include<omp.h>
// BOOST_FOREACH compatibility
#ifndef FOREACH
@@ -86,7 +87,11 @@
public :
boost::mutex drawloopmutex;
- InteractionContainer(): serializeSorted(false) { };
+ InteractionContainer(): serializeSorted(false) {
+ #ifdef YADE_OPENMP
+ threadsPendingErase.resize(omp_get_max_threads());
+ #endif
+ }
virtual ~InteractionContainer() {};
virtual bool insert(body_id_t /*id1*/,body_id_t /*id2*/) {throw;};
@@ -117,6 +122,9 @@
If accessed from within a parallel section, pendingEraseMutex must be locked (this is done inside requestErase for you)
If there is, at one point, a multi-threaded collider, pendingEraseMutex should be moved to the public part and used from there as well.
*/
+ #ifdef YADE_OPENMP
+ vector<list<bodyIdPair> > threadsPendingErase;
+ #endif
list<bodyIdPair> pendingErase;
/*! Erase all pending interactions unconditionally.
@@ -126,7 +134,7 @@
This function doesn't lock pendingEraseMutex, as it is (supposedly) called from no-parallel sections only once per iteration
*/
- void unconditionalErasePending();
+ int unconditionalErasePending();
/*! Traverse all pending interactions and erase them if the (T*)->shouldBeErased(id1,id2) return true
and keep it if it return false; finally, pendingErase will be clear()'ed.
@@ -135,16 +143,23 @@
bool shouldBeErased(body_id_t, body_id_t) const
method which will be called for every interaction.
+
+ Returns number of interactions, have they been erased or not (this is useful to check if there were some erased, after traversing those)
*/
- template<class T> void erasePending(const T& t){
- FOREACH(const Vector2<body_id_t>& p, pendingErase){ if(t.shouldBeErased(p[0],p[1])) erase(p[0],p[1]); }
- pendingErase.clear();
+ template<class T> int erasePending(const T& t){
+ int ret=0;
+ #ifdef YADE_OPENMP
+ // shadow the this->pendingErase by the local variable, to share the code
+ FOREACH(list<bodyIdPair>& pendingErase, threadsPendingErase){
+ #endif
+ FOREACH(const Vector2<body_id_t>& p, pendingErase){ ret++; if(t.shouldBeErased(p[0],p[1])) erase(p[0],p[1]); }
+ pendingErase.clear();
+ #ifdef YADE_OPENMP
+ }
+ #endif
+ return ret;
}
private :
- #ifdef YADE_OPENMP
- // This is used only from within requestErase() for now, therefore it can be private
- boost::mutex pendingEraseMutex;
- #endif
// used only during serialization/deserialization
vector<shared_ptr<Interaction> > interaction;
protected :
Modified: trunk/core/PhysicalParameters.hpp
===================================================================
--- trunk/core/PhysicalParameters.hpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/core/PhysicalParameters.hpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -19,6 +19,10 @@
bool isDisplayed; //! False if the body is not displayed in this cycle (clipped, for instance)
unsigned blockedDOFs; //! Bitmask for degrees of freedom where velocity will be always zero, regardless of applied forces
+
+ // mutex for updating the parameters from within the interaction loop
+ boost::mutex updateMutex;
+
enum {DOF_NONE=0,DOF_X=1,DOF_Y=2,DOF_Z=4,DOF_RX=8,DOF_RY=16,DOF_RZ=32};
static const unsigned DOF_ALL=DOF_X|DOF_Y|DOF_Z|DOF_RX|DOF_RY|DOF_RZ; //! shorthand for all DOFs blocked
static const unsigned DOF_XYZ=DOF_X|DOF_Y|DOF_Z; //! shorthand for all displacements blocked
Modified: trunk/extra/SConscript
===================================================================
--- trunk/extra/SConscript 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/extra/SConscript 2009-07-16 10:16:39 UTC (rev 1870)
@@ -10,7 +10,9 @@
'RigidBodyParameters',
'ElasticBodyParameters',
'BodyMacroParameters',
- 'AABB']),
+ 'AABB',
+ 'EngineUnits',
+ ]),
env.SharedLibrary('TetraTestGen',['tetra/TetraTestGen.cpp'],LIBS=env['LIBS']+['Shop','Tetra']),
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -3,22 +3,36 @@
YADE_PLUGIN("InteractionDispatchers");
CREATE_LOGGER(InteractionDispatchers);
+// #define IDISP_TIMING
+
+#ifdef IDISP_TIMING
+ #define IDISP_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
+#else
+ #define IDISP_CHECKPOINT(cpt)
+#endif
+
+
+
+
InteractionDispatchers::InteractionDispatchers(){
geomDispatcher=shared_ptr<InteractionGeometryMetaEngine>(new InteractionGeometryMetaEngine);
physDispatcher=shared_ptr<InteractionPhysicsMetaEngine>(new InteractionPhysicsMetaEngine);
constLawDispatcher=shared_ptr<ConstitutiveLawDispatcher>(new ConstitutiveLawDispatcher);
alreadyWarnedNoCollider=false;
+ #ifdef IDISP_TIMING
+ timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
+ #endif
}
#define DISPATCH_CACHE
void InteractionDispatchers::action(MetaBody* rootBody){
- if(rootBody->interactions->pendingErase.size()>0){
- if(!alreadyWarnedNoCollider){
- LOG_WARN("Interactions pending erase found, no collider being used?");
- alreadyWarnedNoCollider=true;
- }
- rootBody->interactions->unconditionalErasePending();
+ #ifdef IDISP_TIMING
+ timingDeltas->start();
+ #endif
+ if(rootBody->interactions->unconditionalErasePending()>0 && !alreadyWarnedNoCollider){
+ LOG_WARN("Interactions pending erase found (erased), no collider being used?");
+ alreadyWarnedNoCollider=true;
}
#ifdef YADE_OPENMP
const long size=rootBody->interactions->size();
@@ -29,6 +43,7 @@
FOREACH(shared_ptr<Interaction> I, *rootBody->interactions){
#endif
#ifdef DISPATCH_CACHE
+
const shared_ptr<Body>& b1_=Body::byId(I->getId1(),rootBody);
const shared_ptr<Body>& b2_=Body::byId(I->getId2(),rootBody);
@@ -63,6 +78,7 @@
continue; // in any case don't care about this one anymore
}
+
// InteractionPhysicsMetaEngine
if(!I->functorCache.phys){
I->functorCache.phys=physDispatcher->getFunctor2D(b1->physicalParameters,b2->physicalParameters,swap);
@@ -74,7 +90,6 @@
if(!wasReal) I->iterMadeReal=rootBody->currentIteration; // mark the interaction as created right now
-
// 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.
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -45,12 +45,9 @@
void InteractionGeometryMetaEngine::action(MetaBody* ncb)
{
// Erase interaction that were requested for erase, but not processed by the collider, if any (and warn once about that, as it is suspicious)
- if(ncb->interactions->pendingErase.size()>0){
- if(!alreadyWarnedNoCollider){
- LOG_WARN("Interactions pending erase found, no collider being used?");
- alreadyWarnedNoCollider=true;
- }
- ncb->interactions->unconditionalErasePending();
+ if(ncb->interactions->unconditionalErasePending()>0 && !alreadyWarnedNoCollider){
+ LOG_WARN("Interactions pending erase found, no collider being used?");
+ alreadyWarnedNoCollider=true;
}
shared_ptr<BodyContainer>& bodies = ncb->bodies;
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -132,15 +132,9 @@
ISC_CHECKPOINT("init");
#ifdef COLLIDE_STRIDED
- // get us ready for strides
- if(!strideActive && sweepLength>0){
- if(newton->maxVelocitySq>=0){ // maxVelocitySq is a really computed value
- strideActive=true;
- if(nBins>=1){
- if(!newton->velocityBins){ newton->velocityBins=shared_ptr<VelocityBins>(new VelocityBins(nBins,newton->maxVelocitySq,binCoeff,binOverlap)); }
- if(!boundDispatcher->velocityBins) boundDispatcher->velocityBins=newton->velocityBins;
- }
- }
+ // get us ready for strides, if they were deactivated
+ if(!strideActive && sweepLength>0 && newton->maxVelocitySq>=0){ // maxVelocitySq is a really computed value
+ strideActive=true;
}
if(strideActive){
assert(sweepLength>0);
@@ -158,7 +152,10 @@
LOG_DEBUG(rb->simulationTime<<"s: stride ≈"<<stride<<"; maxVelocity="<<sqrt(newton->maxVelocitySq)<<", sweepDist="<<boundDispatcher->sweepDist);
fastestBodyMaxDist=0; // reset
} else { // nBins>=1
- assert(newton->velocityBins); assert(boundDispatcher->velocityBins);
+ if(!newton->velocityBins){ newton->velocityBins=shared_ptr<VelocityBins>(new VelocityBins(nBins,newton->maxVelocitySq,binCoeff,binOverlap)); }
+ if(!boundDispatcher->velocityBins) boundDispatcher->velocityBins=newton->velocityBins;
+ newton->velocityBins->nBins=nBins; newton->velocityBins->binCoeff=binCoeff; newton->velocityBins->binOverlap=binOverlap; // update things
+ boundDispatcher->sweepDist=0;
// re-bin bodies
newton->velocityBins->setBins(rb,newton->maxVelocitySq,sweepLength);
}
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -20,7 +20,7 @@
//#define ISC_TIMING
#ifdef ISC_TIMING
- #define ISC_CHECKPOINT(cpt) timingDeltas->checkPoint(cpt)
+ #define ISC_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
#else
#define ISC_CHECKPOINT(cpt)
#endif
Modified: trunk/pkg/dem/ConcretePM.cpp
===================================================================
--- trunk/pkg/dem/ConcretePM.cpp 2009-07-15 16:46:34 UTC (rev 1869)
+++ trunk/pkg/dem/ConcretePM.cpp 2009-07-16 10:16:39 UTC (rev 1870)
@@ -197,8 +197,8 @@
const shared_ptr<Body>& body1=Body::byId(I->getId1(),rootBody), body2=Body::byId(I->getId2(),rootBody); assert(body1); assert(body2);
const shared_ptr<CpmMat>& rbp1=YADE_PTR_CAST<CpmMat>(body1->physicalParameters), rbp2=YADE_PTR_CAST<CpmMat>(body2->physicalParameters);
// nice article about openMP::critical vs. scoped locks: http://www.thinkingparallel.com/2006/08/21/scoped-locking-vs-critical-in-openmp-a-personal-shootout/
- #pragma omp critical
- { rbp1->numBrokenCohesive+=1; rbp2->numBrokenCohesive+=1; rbp1->epsPlBroken+=epsPlSum; rbp2->epsPlBroken+=epsPlSum; }
+ { boost::mutex::scoped_lock lock(rbp1->updateMutex); rbp1->numBrokenCohesive+=1; rbp1->epsPlBroken+=epsPlSum; }
+ { boost::mutex::scoped_lock lock(rbp2->updateMutex); rbp2->numBrokenCohesive+=1; rbp2->epsPlBroken+=epsPlSum; }
}
rootBody->interactions->requestErase(I->getId1(),I->getId2());
return;