← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2767: 1. Invalidate persistent collider data when interactions are cleared (not tested yet)

 

------------------------------------------------------------
revno: 2767
committer: Václav Šmilauer <eu@xxxxxxxx>
branch nick: yade
timestamp: Sun 2011-02-27 14:54:43 +0100
message:
  1. Invalidate persistent collider data when interactions are cleared (not tested yet)
  2. Add renderer pointer to scene, so that functors can find display attributes
  3. Gl1_NormPhys honors displacement scaling now
  4. Fix scalarOnColorScale bug
  5. Add RadialForceEngine, fix AxialGravityEngine
modified:
  core/InteractionContainer.cpp
  core/InteractionContainer.hpp
  core/Scene.cpp
  core/Scene.hpp
  gui/qt4/GLViewer.cpp
  lib/base/Logging.hpp
  lib/serialization/Serializable.hpp
  pkg/common/ForceEngine.cpp
  pkg/common/ForceEngine.hpp
  pkg/common/GLDrawFunctors.hpp
  pkg/common/Gl1_NormPhys.cpp
  pkg/common/GravityEngines.cpp
  pkg/common/InsertionSortCollider.cpp
  pkg/common/InteractionLoop.cpp
  pkg/dem/Shop.cpp
  py/wrapper/yadeWrapper.cpp
  scripts/test/beam-l6geom.py


--
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/InteractionContainer.cpp'
--- core/InteractionContainer.cpp	2010-12-01 11:09:53 +0000
+++ core/InteractionContainer.cpp	2011-02-27 13:54:43 +0000
@@ -33,6 +33,7 @@
 	linIntrs.clear(); // clear the linear container
 	pendingErase.clear();
 	currSize=0;
+	dirty=true;
 }
 
 

=== modified file 'core/InteractionContainer.hpp'
--- core/InteractionContainer.hpp	2010-11-24 22:42:15 +0000
+++ core/InteractionContainer.hpp	2011-02-27 13:54:43 +0000
@@ -60,8 +60,10 @@
 		// used only during serialization/deserialization
 		vector<shared_ptr<Interaction> > interaction;
 	public:
+		// flag for notifying the collider that persistent data should be invalidated
+		bool dirty;
 		// required by the class factory... :-|
-		InteractionContainer(): currSize(0),serializeSorted(false),iterColliderLastRun(-1){
+		InteractionContainer(): currSize(0),dirty(false),serializeSorted(false),iterColliderLastRun(-1){
 			bodies=NULL;
 			#ifdef YADE_OPENMP
 				threadsPendingErase.resize(omp_get_max_threads());
@@ -159,7 +161,7 @@
 	void postSave(InteractionContainer&);
 
 
-	REGISTER_ATTRIBUTES(Serializable,(interaction)(serializeSorted));
+	REGISTER_ATTRIBUTES(Serializable,(interaction)(serializeSorted)(dirty));
 	REGISTER_CLASS_AND_BASE(InteractionContainer,Serializable);
 };
 REGISTER_SERIALIZABLE(InteractionContainer);

=== modified file 'core/Scene.cpp'
--- core/Scene.cpp	2011-01-20 14:55:15 +0000
+++ core/Scene.cpp	2011-02-27 13:54:43 +0000
@@ -74,10 +74,14 @@
 		checkStateTypes();
 		forces.resize(bodies->size()); // optimization, not necessary
 	}
-	// substepping or not, update engines from _nextEngines, if defined
-	if(!_nextEngines.empty() && subStep<0){
+	// substepping or not, update engines from _nextEngines, if defined, at the beginning of step
+	// subStep can be 0, which happens if simulations is saved in the middle of step (without substepping)
+	// this assumes that prologue will not set _nextEngines, which is safe hopefully
+	if(!_nextEngines.empty() && (subStep<0 || (subStep<=0 && !subStepping))){
 		engines=_nextEngines;
 		_nextEngines.clear();
+		// hopefully this will not break in some margin cases (subStepping with setting _nextEngines and such)
+		subStep=-1;
 	}
 	if(likely(!subStepping && subStep<0)){
 		/* set substep to 0 during the loop, so that engines/nextEngines handler know whether we are inside the loop currently */

=== modified file 'core/Scene.hpp'
--- core/Scene.hpp	2011-01-29 22:47:18 +0000
+++ core/Scene.hpp	2011-02-27 13:54:43 +0000
@@ -26,6 +26,9 @@
 
 
 class Bound;
+#ifdef YADE_OPENGL
+	class OpenGLRenderer;
+#endif
 
 class Scene: public Serializable{
 	public:
@@ -54,6 +57,10 @@
 
 		shared_ptr<Engine> engineByName(const string& s);
 
+		#ifdef YADE_OPENGL
+			shared_ptr<OpenGLRenderer> renderer;
+		#endif
+
 		void postLoad(Scene&);
 
 		// bits for Scene::flags

=== modified file 'gui/qt4/GLViewer.cpp'
--- gui/qt4/GLViewer.cpp	2011-01-12 12:01:03 +0000
+++ gui/qt4/GLViewer.cpp	2011-02-27 13:54:43 +0000
@@ -515,13 +515,16 @@
 			}
 			renderer->clipPlaneSe3[manipulatedClipPlane]=newSe3;
 		}
-		renderer->render(Omega::instance().getScene(), selectedName());
+		const shared_ptr<Scene>& scene=Omega::instance().getScene();
+		scene->renderer=renderer;
+		renderer->render(scene, selectedName());
 	}
 }
 
 void GLViewer::drawWithNames(){
 	qglviewer::Vec vd=camera()->viewDirection(); renderer->viewDirection=Vector3r(vd[0],vd[1],vd[2]);
 	const shared_ptr<Scene> scene(Omega::instance().getScene());
+	scene->renderer=renderer;
 	renderer->scene=scene;
 	renderer->renderShape();
 }

=== modified file 'lib/base/Logging.hpp'
--- lib/base/Logging.hpp	2011-02-15 16:52:24 +0000
+++ lib/base/Logging.hpp	2011-02-27 13:54:43 +0000
@@ -61,8 +61,8 @@
 #	define _LOG_HEAD __FILE__ ":"<<__LINE__<<" "<<__FUNCTION__<<": "
 #	define LOG_TRACE(msg) // _POOR_MANS_LOG("TRACE",msg)
 #	define LOG_DEBUG(msg) // _POOR_MANS_LOG("DEBUG",msg)
-#	define LOG_INFO(msg) // _POOR_MANS_LOG("INFO ",msg)
-#	define LOG_WARN(msg) // _POOR_MANS_LOG("WARN ",msg)
+#	define LOG_INFO(msg)  // _POOR_MANS_LOG("INFO ",msg)
+#	define LOG_WARN(msg)  _POOR_MANS_LOG("WARN ",msg)
 #	define LOG_ERROR(msg) _POOR_MANS_LOG("ERROR",msg)
 #	define LOG_FATAL(msg) _POOR_MANS_LOG("FATAL",msg)
 

=== modified file 'lib/serialization/Serializable.hpp'
--- lib/serialization/Serializable.hpp	2010-12-05 17:10:06 +0000
+++ lib/serialization/Serializable.hpp	2011-02-27 13:54:43 +0000
@@ -50,7 +50,7 @@
 namespace yade{
 	namespace Attr{
 		// keep in sync with py/wrapper/yadeWrapper.cpp !
-		enum flags { noSave=1, readonly=2, triggerPostLoad=4, hidden=8, noResize=16, };
+		enum flags { noSave=1, readonly=2, triggerPostLoad=4, hidden=8, noResize=16 };
 	};
 };
 using namespace yade;

=== modified file 'pkg/common/ForceEngine.cpp'
--- pkg/common/ForceEngine.cpp	2010-12-21 12:19:50 +0000
+++ pkg/common/ForceEngine.cpp	2011-02-27 13:54:43 +0000
@@ -10,7 +10,7 @@
 #include<yade/core/IGeom.hpp>
 #include<yade/core/IPhys.hpp>
 
-YADE_PLUGIN((ForceEngine)(InterpolatingDirectedForceEngine));
+YADE_PLUGIN((ForceEngine)(InterpolatingDirectedForceEngine)(RadialForceEngine));
 
 void ForceEngine::action(){
 	FOREACH(Body::id_t id, ids){
@@ -26,4 +26,14 @@
 	ForceEngine::action();
 }
 
+void RadialForceEngine::postLoad(RadialForceEngine&){ axisDir.normalize(); }
 
+void RadialForceEngine::action(){
+	FOREACH(Body::id_t id, ids){
+		assert(scene->bodies->exists(id));
+		const Vector3r& pos=Body::byId(id,scene)->state->pos;
+		Vector3r radial=(pos - (axisPt+axisDir * /* t */ ((pos-axisPt).dot(axisDir)))).normalized();
+		if(radial.squaredNorm()==0) continue;
+		scene->forces.addForce(id,fNorm*radial);
+	}
+}

=== modified file 'pkg/common/ForceEngine.hpp'
--- pkg/common/ForceEngine.hpp	2010-10-13 16:23:08 +0000
+++ pkg/common/ForceEngine.hpp	2011-02-27 13:54:43 +0000
@@ -38,4 +38,13 @@
 };
 REGISTER_SERIALIZABLE(InterpolatingDirectedForceEngine);
 
-
+struct RadialForceEngine: public PartialEngine{
+	virtual void action();
+	virtual void postLoad(RadialForceEngine&);
+	YADE_CLASS_BASE_DOC_ATTRS(RadialForceEngine,PartialEngine,"Apply force of given magnitude directed away from spatial axis.",
+		((Vector3r,axisPt,Vector3r::Zero(),,"Point on axis"))
+		((Vector3r,axisDir,Vector3r::UnitX(),Attr::triggerPostLoad,"Axis direction (normalized automatically)"))
+		((Real,fNorm,0,,"Applied force magnitude"))
+	);
+};
+REGISTER_SERIALIZABLE(RadialForceEngine);

=== modified file 'pkg/common/GLDrawFunctors.hpp'
--- pkg/common/GLDrawFunctors.hpp	2010-11-07 11:46:20 +0000
+++ pkg/common/GLDrawFunctors.hpp	2011-02-27 13:54:43 +0000
@@ -22,6 +22,8 @@
 	Real sceneRadius;
 };
 
+class OpenGLRenderer;
+
 #define GL_FUNCTOR(Klass,typelist,renderedType) class Klass: public Functor1D<renderedType,void,typelist>{public:\
 	virtual ~Klass(){};\
 	virtual string renders() const { throw std::runtime_error(#Klass ": unregistered gldraw class.\n"); };\

=== modified file 'pkg/common/Gl1_NormPhys.cpp'
--- pkg/common/Gl1_NormPhys.cpp	2011-02-07 09:00:07 +0000
+++ pkg/common/Gl1_NormPhys.cpp	2011-02-27 13:54:43 +0000
@@ -2,10 +2,12 @@
 
 #include<yade/core/Scene.hpp>
 #include<yade/pkg/common/Gl1_NormPhys.hpp>
+#include<yade/pkg/common/OpenGLRenderer.hpp>
 #include<yade/pkg/common/NormShearPhys.hpp>
 #include<yade/pkg/dem/DemXDofGeom.hpp>
 #include<yade/pkg/dem/Shop.hpp>
 
+
 YADE_PLUGIN((Gl1_NormPhys));
 
 GLUquadric* Gl1_NormPhys::gluQuadric=NULL;
@@ -68,8 +70,15 @@
 		// max(r,0) handles r<0 which is the case for "radius" of the facet in Dem3DofGeom_FacetSphere
 		Vector3r cp=scene->isPeriodic? scene->cell->wrapShearedPt(geom->contactPoint) : geom->contactPoint;
 		Vector3r p1=cp-max(geom->refR1,0.)*geom->normal;
-		Vector3r relPos=/*p2*/(cp+max(geom->refR2,0.)*geom->normal)-p1;
-		Real dist=max(geom->refR1,0.)+max(geom->refR2,0.);
+		Vector3r p2=cp+max(geom->refR2,0.)*geom->normal;
+		const Vector3r& dispScale=scene->renderer ? scene->renderer->dispScale : Vector3r::Ones(); 
+		if(dispScale!=Vector3r::Ones()){
+			// move p1 and p2 by the same amounts as particles themselves would be moved
+			p1+=dispScale.cwise()*Vector3r(b1->state->pos-b1->state->refPos);
+			p2+=dispScale.cwise()*Vector3r(b2->state->pos-b2->state->refPos);
+		}
+		Vector3r relPos=p2-p1;
+		Real dist=relPos.norm(); //max(geom->refR1,0.)+max(geom->refR2,0.);
 	#endif
 
 

=== modified file 'pkg/common/GravityEngines.cpp'
--- pkg/common/GravityEngines.cpp	2010-11-30 13:51:41 +0000
+++ pkg/common/GravityEngines.cpp	2011-02-27 13:54:43 +0000
@@ -44,8 +44,9 @@
 		const Vector3r& x0=b->state->pos;
 		const Vector3r& x1=axisPoint;
 		const Vector3r x2=axisPoint+axisDirection;
-		Vector3r closestAxisPoint=(x2-x1) * /* t */ (-(x1-x0).dot(x2-x1))/((x2-x1).squaredNorm());
+		Vector3r closestAxisPoint=x1+(x2-x1) * /* t */ (-(x1-x0).dot(x2-x1))/((x2-x1).squaredNorm());
 		Vector3r toAxis=closestAxisPoint-x0; toAxis.normalize();
+		if(toAxis.squaredNorm()==0) continue;
 		scene->forces.addForce(b->getId(),acceleration*b->state->mass*toAxis);
 	}
 }

=== modified file 'pkg/common/InsertionSortCollider.cpp'
--- pkg/common/InsertionSortCollider.cpp	2011-02-20 10:28:40 +0000
+++ pkg/common/InsertionSortCollider.cpp	2011-02-27 13:54:43 +0000
@@ -106,6 +106,7 @@
 			if(fastestBodyMaxDist>=verletDist) return true;
 		}
 		if((size_t)BB[0].size!=2*scene->bodies->size()) return true;
+		if(scene->interactions->dirty) return true;
 		// we wouldn't run in this step; in that case, just delete pending interactions
 		// this is done in ::action normally, but it would make the call counters not reflect the stride
 		scene->interactions->erasePending(*this,scene);
@@ -162,6 +163,12 @@
 		boundDispatcher->scene=scene;
 		boundDispatcher->action();
 
+		// if interactions are dirty, force reinitialization
+		if(scene->interactions->dirty){
+			doInitSort=true;
+			scene->interactions->dirty=false;
+		}
+
 		if(verletDist<0){
 			Real minR=std::numeric_limits<Real>::infinity();
 			FOREACH(const shared_ptr<Body>& b, *scene->bodies){

=== modified file 'pkg/common/InteractionLoop.cpp'
--- pkg/common/InteractionLoop.cpp	2011-01-29 22:47:18 +0000
+++ pkg/common/InteractionLoop.cpp	2011-02-27 13:54:43 +0000
@@ -35,6 +35,9 @@
 		LOG_WARN("Interactions pending erase found (erased), no collider being used?");
 		alreadyWarnedNoCollider=true;
 	}
+	if(scene->interactions->dirty){
+		throw std::logic_error("InteractionContainer::dirty is true; the collider should re-initialize in such case and clear the dirty flag.");
+	}
 	// update Scene* of the dispatchers
 	geomDispatcher->scene=physDispatcher->scene=lawDispatcher->scene=scene;
 	// ask dispatchers to update Scene* of their functors

=== modified file 'pkg/dem/Shop.cpp'
--- pkg/dem/Shop.cpp	2011-02-09 11:58:56 +0000
+++ pkg/dem/Shop.cpp	2011-02-27 13:54:43 +0000
@@ -428,9 +428,9 @@
  */
 Vector3r Shop::scalarOnColorScale(Real x, Real xmin, Real xmax){
 	Real xnorm=min((Real)1.,max((x-xmin)/(xmax-xmin),(Real)0.));
-	if(xnorm<.25) return Vector3r(0,.4*xnorm,1);
+	if(xnorm<.25) return Vector3r(0,4.*xnorm,1);
 	if(xnorm<.5)  return Vector3r(0,1,1.-4.*(xnorm-.25));
-	if(xnorm<.75) return Vector3r(4*(xnorm-.5),1.,0);
+	if(xnorm<.75) return Vector3r(4.*(xnorm-.5),1.,0);
 	return Vector3r(1,1-4*(xnorm-.75),0);
 }
 

=== modified file 'py/wrapper/yadeWrapper.cpp'
--- py/wrapper/yadeWrapper.cpp	2011-01-31 19:09:24 +0000
+++ py/wrapper/yadeWrapper.cpp	2011-02-27 13:54:43 +0000
@@ -605,7 +605,7 @@
 		.def("eraseNonReal",&pyInteractionContainer::eraseNonReal,"Erase all interactions that are not :yref:`real <InteractionContainer.isReal>`.")
 		.def("erase",&pyInteractionContainer::erase,"Erase one interaction, given by id1, id2 (internally, ``requestErase`` is called -- the interaction might still exist as potential, if the :yref:`Collider` decides so).")
 		.add_property("serializeSorted",&pyInteractionContainer::serializeSorted_get,&pyInteractionContainer::serializeSorted_set)
-		.def("clear",&pyInteractionContainer::clear,"Remove all interactions");
+		.def("clear",&pyInteractionContainer::clear,"Remove all interactions, and invalidate persistent collider data (if the collider supports it).");
 	python::class_<pyInteractionIterator>("InteractionIterator",python::init<pyInteractionIterator&>())
 		.def("__iter__",&pyInteractionIterator::pyIter)
 		.def("next",&pyInteractionIterator::pyNext);

=== modified file 'scripts/test/beam-l6geom.py'
--- scripts/test/beam-l6geom.py	2011-01-29 22:47:18 +0000
+++ scripts/test/beam-l6geom.py	2011-02-27 13:54:43 +0000
@@ -33,9 +33,9 @@
 	rr=qt.Renderer()
 	rr.intrGeom=True
 	Gl1_L6Geom.phiScale=30; Gl1_L3Geom.uScale=20
-	O.engines=O.engines+[
-		qt.SnapshotEngine(fileBase=O.tmpFilename(),label='snapper',iterPeriod=300,deadTimeout=20),
-		PyRunner(iterPeriod=330000,command='utils.makeVideo(snapper.snapshots,out="beam-l6geom.avi"); snapper.dead=True; O.pause()')
-	]
+	#O.engines=O.engines+[
+	#	qt.SnapshotEngine(fileBase=O.tmpFilename(),label='snapper',iterPeriod=300,deadTimeout=20),
+	#	PyRunner(iterPeriod=330000,command='utils.makeVideo(snapper.snapshots,out="beam-l6geom.avi"); snapper.dead=True; O.pause()')
+	#]
 except ImportError: pass
 O.run()