← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2416: 1. Add foce, torque etc display in the body tab of the inspector

 

------------------------------------------------------------
revno: 2416
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Fri 2010-08-27 10:28:50 +0200
message:
  1. Add foce, torque etc display in the body tab of the inspector
  2. Make force, torque etc access from python not require thread synchronization (sums up threads on demand)
modified:
  core/ForceContainer.hpp
  gui/qt4/Inspector.py
  py/wrapper/yadeWrapper.cpp


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'core/ForceContainer.hpp'
--- core/ForceContainer.hpp	2010-08-26 16:56:07 +0000
+++ core/ForceContainer.hpp	2010-08-27 08:28:50 +0000
@@ -64,11 +64,13 @@
 
 		inline void ensureSynced(){ if(!synced) throw runtime_error("ForceContainer not thread-synchronized; call sync() first!"); }
 
-		/*! Function to allow friend classes to get force even if not synced.
-		* Dangerous! The caller must know what it is doing! (i.e. don't read after write
-		* for a particular body id. */
-		const Vector3r& getForceUnsynced (Body::id_t id){ensureSize(id); return _force[id];}
-		const Vector3r& getTorqueUnsynced(Body::id_t id){ensureSize(id); return _force[id];}
+		#if 0
+			/*! Function to allow friend classes to get force even if not synced.
+			* Dangerous! The caller must know what it is doing! (i.e. don't read after write
+			* for a particular body id. */
+			const Vector3r& getForceUnsynced (Body::id_t id){ensureSize(id); return _force[id];}
+			const Vector3r& getTorqueUnsynced(Body::id_t id){ensureSize(id); return _force[id];}
+		#endif
 		// dummy function to avoid template resolution failure
 		friend class boost::serialization::access; template<class ArchiveT> void serialize(ArchiveT & ar, unsigned int version){}
 	public:
@@ -80,7 +82,6 @@
 			}
 		}
 
-		/* To be benchmarked: sum thread data in getForce/getTorque upon request for each body individually instead of by the sync() function globally */
 		const Vector3r& getForce(Body::id_t id)         { ensureSize(id); ensureSynced(); return _force[id]; }
 		void  addForce(Body::id_t id, const Vector3r& f){ ensureSize(id); synced=false;   _forceData[omp_get_thread_num()][id]+=f;}
 		const Vector3r& getTorque(Body::id_t id)        { ensureSize(id); ensureSynced(); return _torque[id]; }
@@ -89,6 +90,13 @@
 		void  addMove(Body::id_t id, const Vector3r& m) { ensureSize(id); synced=false; moveRotUsed=true; _moveData[omp_get_thread_num()][id]+=m;}
 		const Vector3r& getRot(Body::id_t id)           { ensureSize(id); ensureSynced(); return _rot[id]; }
 		void  addRot(Body::id_t id, const Vector3r& r)  { ensureSize(id); synced=false; moveRotUsed=true; _rotData[omp_get_thread_num()][id]+=r;}
+		/* To be benchmarked: sum thread data in getForce/getTorque upon request for each body individually instead of by the sync() function globally */
+		// this function is used from python so that running simulation is not slowed down by sync'ing on occasions
+		// since Vector3r writes are not atomic, it might (rarely) return wrong value, if the computation is running meanwhile
+		Vector3r getForceSingle (Body::id_t id){ ensureSize(id); Vector3r ret(Vector3r::Zero()); for(int t=0; t<nThreads; t++){ ret+=_forceData [t][id]; } return ret; }
+		Vector3r getTorqueSingle(Body::id_t id){ ensureSize(id); Vector3r ret(Vector3r::Zero()); for(int t=0; t<nThreads; t++){ ret+=_torqueData[t][id]; } return ret; }
+		Vector3r getMoveSingle  (Body::id_t id){ ensureSize(id); Vector3r ret(Vector3r::Zero()); for(int t=0; t<nThreads; t++){ ret+=_moveData  [t][id]; } return ret; }
+		Vector3r getRotSingle   (Body::id_t id){ ensureSize(id); Vector3r ret(Vector3r::Zero()); for(int t=0; t<nThreads; t++){ ret+=_rotData   [t][id]; } return ret; }
 
 		/* Sum contributions from all threads, save to _force&_torque.
 		 * Locks globalMutex, since one thread modifies common data (_force&_torque).
@@ -164,8 +172,10 @@
 		std::vector<Vector3r> _rot;
 		size_t size;
 		inline void ensureSize(Body::id_t id){ if(size<=(size_t)id) resize(min((size_t)1.5*(id+100),(size_t)(id+2000)));}
-		const Vector3r& getForceUnsynced (Body::id_t id){ return getForce(id);}
-		const Vector3r& getTorqueUnsynced(Body::id_t id){ return getForce(id);}
+		#if 0
+			const Vector3r& getForceUnsynced (Body::id_t id){ return getForce(id);}
+			const Vector3r& getTorqueUnsynced(Body::id_t id){ return getForce(id);}
+		#endif
 		bool moveRotUsed;
 		// dummy function to avoid template resolution failure
 		friend class boost::serialization::access; template<class ArchiveT> void serialize(ArchiveT & ar, unsigned int version){}
@@ -179,6 +189,12 @@
 		void  addMove(Body::id_t id,const Vector3r& f){ensureSize(id); moveRotUsed=true; _move[id]+=f;}
 		const Vector3r& getRot(Body::id_t id){ensureSize(id); return _rot[id];}
 		void  addRot(Body::id_t id,const Vector3r& f){ensureSize(id); moveRotUsed=true; _rot[id]+=f;}
+		// single getters do the same as globally synced ones in the non-parallel flavor
+		const Vector3r& getForceSingle (Body::id_t id){ ensureSize(id); return _force [id]; }
+		const Vector3r& getTorqueSingle(Body::id_t id){ ensureSize(id); return _torque[id]; }
+		const Vector3r& getMoveSingle  (Body::id_t id){ ensureSize(id); return _move  [id]; }
+		const Vector3r& getRotSingle   (Body::id_t id){ ensureSize(id); return _rot   [id]; }
+
 		//! Set all forces to zero
 		void reset(){
 			memset(&_force [0],0,sizeof(Vector3r)*size);

=== modified file 'gui/qt4/Inspector.py'
--- gui/qt4/Inspector.py	2010-08-13 15:18:16 +0000
+++ gui/qt4/Inspector.py	2010-08-27 08:28:50 +0000
@@ -79,19 +79,30 @@
 		self.intrWithCombo=QComboBox(self);
 		self.gotoBodyButton=QPushButton(u'→ #',self)
 		self.gotoIntrButton=QPushButton(u'→ #+#',self)
-		topBoxWidget=QWidget(self)
-		topBox=QHBoxLayout(topBoxWidget)
-		hashLabel=QLabel('#',self); hashLabel.setFixedWidth(10)
+		# id selector
+		topBoxWidget=QWidget(self); topBox=QHBoxLayout(topBoxWidget); topBox.setMargin(0); #topBox.setSpacing(0); 
+		hashLabel=QLabel('#',self); hashLabel.setFixedWidth(8)
 		topBox.addWidget(hashLabel)
 		topBox.addWidget(self.bodyIdBox)
-		self.plusLabel=QLabel('+',self)
-		topBox.addWidget(self.plusLabel)
+		self.plusLabel=QLabel('+',self); topBox.addWidget(self.plusLabel)
+		hashLabel2=QLabel('#',self); hashLabel2.setFixedWidth(8); topBox.addWidget(hashLabel2)
 		topBox.addWidget(self.intrWithCombo)
+		topBox.addStretch()
 		topBox.addWidget(self.gotoBodyButton)
 		topBox.addWidget(self.gotoIntrButton)
 		topBoxWidget.setLayout(topBox)
+		# forces display
+		forcesWidget=QFrame(self); forcesWidget.setFrameShape(QFrame.Box); self.forceGrid=QGridLayout(forcesWidget); 
+		self.forceGrid.setVerticalSpacing(0); self.forceGrid.setHorizontalSpacing(9); self.forceGrid.setMargin(4);
+		for i,j in itertools.product((0,1,2,3),(-1,0,1,2)):
+			lab=QLabel('<small>'+('force','torque','move','rot')[i]+'</small>' if j==-1 else ''); self.forceGrid.addWidget(lab,i,j+1);
+			if j>=0: lab.setAlignment(Qt.AlignRight)
+			if i>1: lab.hide() # do not show forced moves and rotations by default (they will appear if non-zero)
+		self.showMovRot=False
+		#
 		self.grid=QGridLayout(self); self.grid.setSpacing(0); self.grid.setMargin(0)
 		self.grid.addWidget(topBoxWidget)
+		self.grid.addWidget(forcesWidget)
 		self.scroll=QScrollArea(self)
 		self.scroll.setWidgetResizable(True)
 		self.grid.addWidget(self.scroll)
@@ -106,6 +117,20 @@
 		self.intrWithCombo.setMinimumWidth(80)
 		self.setWindowTitle('Body #%d'%self.bodyId)
 		self.gotoBodySlot()
+	def displayForces(self):
+		if self.bodyId<0: return
+		try:
+			val=[O.forces.f(self.bodyId),O.forces.t(self.bodyId),O.forces.move(self.bodyId),O.forces.rot(self.bodyId)]
+			hasMovRot=(val[2]!=Vector3.Zero or val[3]!=Vector3.Zero)
+			if hasMovRot!=self.showMovRot:
+				for i,j in itertools.product((2,3),(-1,0,1,2)):
+					if hasMovRot: self.forceGrid.itemAtPosition(i,j+1).widget().show()
+					else: self.forceGrid.itemAtPosition(i,j+1).widget().hide()
+				self.showMovRot=hasMovRot
+			rows=((0,1,2,3) if hasMovRot else (0,1))
+			for i,j in itertools.product(rows,(0,1,2)):
+				self.forceGrid.itemAtPosition(i,j+1).widget().setText('<small>'+str(val[i][j])+'</small>')
+		except IndexError:pass
 	def tryShowBody(self):
 		try:
 			b=O.bodies[self.bodyId]
@@ -169,6 +194,7 @@
 			self.gotoBodyButton.setEnabled(True); self.gotoIntrButton.setEnabled(True)
 		self.gotoBodyButton.setText(u'→ %s'%other)
 		self.gotoIntrButton.setText(u'→ %s + %s'%(meLabel,other))
+		self.displayForces()
 		
 class InteractionInspector(QWidget):
 	def __init__(self,ids=None,parent=None,bodyLinkCallback=None):

=== modified file 'py/wrapper/yadeWrapper.cpp'
--- py/wrapper/yadeWrapper.cpp	2010-08-26 16:56:07 +0000
+++ py/wrapper/yadeWrapper.cpp	2010-08-27 08:28:50 +0000
@@ -219,10 +219,10 @@
 	public:
 		pyForceContainer(shared_ptr<Scene> _scene): scene(_scene) { }
 		void checkId(long id){ if(id<0 || (size_t)id>=scene->bodies->size()){ PyErr_SetString(PyExc_IndexError, "Body id out of range."); python::throw_error_already_set(); /* never reached */ throw; } }
-		Vector3r force_get(long id){  checkId(id); scene->forces.sync(); return scene->forces.getForce(id); }
-		Vector3r torque_get(long id){ checkId(id); scene->forces.sync(); return scene->forces.getTorque(id); }
-		Vector3r move_get(long id){   checkId(id); scene->forces.sync(); return scene->forces.getMove(id); }
-		Vector3r rot_get(long id){    checkId(id); scene->forces.sync(); return scene->forces.getRot(id); }
+		Vector3r force_get(long id){  checkId(id); return scene->forces.getForceSingle(id); /* scene->forces.sync(); return scene->forces.getForce(id); */}
+		Vector3r torque_get(long id){ checkId(id); return scene->forces.getTorqueSingle(id); }
+		Vector3r move_get(long id){   checkId(id); return scene->forces.getMoveSingle(id); }
+		Vector3r rot_get(long id){    checkId(id); return scene->forces.getRotSingle(id); }
 		void force_add(long id, const Vector3r& f){  checkId(id); scene->forces.addForce (id,f); }
 		void torque_add(long id, const Vector3r& t){ checkId(id); scene->forces.addTorque(id,t);}
 		void move_add(long id, const Vector3r& t){   checkId(id); scene->forces.addMove(id,t);}