← Back to team overview

yade-dev team mailing list archive

[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;