← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 1796: 1. virtual facets don't have a BoundingVolume (flag noBoundingVolume in utils.facet)

 

------------------------------------------------------------
revno: 1796
committer: Sergei D. <sega@think>
branch nick: trunk
timestamp: Thu 2009-11-19 09:44:50 +0300
message:
  1. virtual facets don't have a BoundingVolume (flag noBoundingVolume in utils.facet)
  2. new engine ResetRandomPosition (another name?). This engine reset the body position to a random position in specifed (by virtual facets) region.
  3. example of using of ResetRandomPosition engine: scripts/test/ResetRandomPosition.py
added:
  pkg/common/Engine/StandAloneEngine/ResetRandomPosition.cpp
  pkg/common/Engine/StandAloneEngine/ResetRandomPosition.hpp
  scripts/test/ResetRandomPosition.py
modified:
  pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
  py/utils.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 'pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp'
--- pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp	2009-11-14 12:32:32 +0000
+++ pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp	2009-11-19 06:44:50 +0000
@@ -68,7 +68,7 @@
 			it=XX.begin(),et=XX.end(); it < et; ++it)
 	{
 		if (it->coord > bv.max[0]) break;
-		if (!it->flags.isMin) continue;
+		if (!it->flags.isMin || !it->flags.hasBB) continue;
 		int offset = 3*it->id;
 		if (!(maxima[offset] < bv.min[0] ||
 				minima[offset+1] > bv.max[1] ||

=== added file 'pkg/common/Engine/StandAloneEngine/ResetRandomPosition.cpp'
--- pkg/common/Engine/StandAloneEngine/ResetRandomPosition.cpp	1970-01-01 00:00:00 +0000
+++ pkg/common/Engine/StandAloneEngine/ResetRandomPosition.cpp	2009-11-19 06:44:50 +0000
@@ -0,0 +1,176 @@
+/*************************************************************************
+*  Copyright (C) 2009 by Sergei Dorofeenko				 				 *
+*  sega@xxxxxxxxxxxxxxxx                                                 *
+*                                                                        *
+*  This program is free software; it is licensed under the terms of the  *
+*  GNU General Public License v2 or later. See file LICENSE for details. *
+*************************************************************************/
+
+#include<boost/random.hpp>
+#include<yade/core/Body.hpp>
+#include<yade/pkg-common/AABB.hpp>
+#include<yade/pkg-common/InteractingSphere.hpp>
+#include<yade/pkg-common/InteractingFacet.hpp>
+#include<yade/pkg-common/InteractionDispatchers.hpp>
+#include<yade/pkg-dem/BodyMacroParameters.hpp>
+#include"ResetRandomPosition.hpp"
+#include<sstream>
+
+YADE_PLUGIN((ResetRandomPosition));
+YADE_REQUIRE_FEATURE(PYTHON)
+CREATE_LOGGER(ResetRandomPosition);
+
+namespace {
+boost::variate_generator<boost::mt19937,boost::uniform_real<> > 
+	randomUnit(boost::mt19937(),boost::uniform_real<>(0,1));
+boost::variate_generator<boost::mt19937,boost::uniform_real<> >
+	randomSymmetricUnit(boost::mt19937(),boost::uniform_real<>(-1,1));
+}
+
+ResetRandomPosition::ResetRandomPosition() 
+{
+	factoryFacets.clear();
+	point=Vector3r(0,0,0);
+	normal=Vector3r(0,1,0);
+    volumeSection=false;
+	maxAttempts=20;
+	velocity=Vector3r(0,0,0);
+	velocityRange=Vector3r(0,0,0);
+	angularVelocity=Vector3r(0,0,0);
+	angularVelocityRange=Vector3r(0,0,0);
+	first_run = true;
+}
+
+ResetRandomPosition::~ResetRandomPosition()
+{
+	
+}
+
+void ResetRandomPosition::action(MetaBody* ncb)
+{
+	if (first_run)
+	{
+		FOREACH(shared_ptr<Engine> eng, ncb->engines)
+		{
+			bI=dynamic_cast<Collider*>(eng.get());
+			if (bI) break;
+		}
+		if (!bI) 
+		{
+			LOG_FATAL("Can't find Collider." );
+			return;
+		}
+		iGME=dynamic_cast<InteractionGeometryMetaEngine*>(ncb->engineByName("InteractionGeometryMetaEngine").get());
+		if (!iGME) 
+		{
+			InteractionDispatchers* iDsp=dynamic_cast<InteractionDispatchers*>(ncb->engineByName("InteractionDispatchers").get());
+			if (!iDsp)
+			{
+				LOG_FATAL("Can't find nor InteractionGeometryMetaEngine nor InteractionDispatchers." );
+				return;
+			}
+			iGME=dynamic_cast<InteractionGeometryMetaEngine*>(iDsp->geomDispatcher.get());
+			if (!iGME)
+			{
+				LOG_FATAL("Can't find InteractionGeometryMetaEngine." );
+				return;
+			}
+		}
+		first_run=false;
+		randomFacet= shared_ptr<RandomInt>(new RandomInt(boost::minstd_rand(),boost::uniform_int<>(0,factoryFacets.size()-1)));
+	}
+
+	shiftedBodies.clear();
+
+	FOREACH(int id, subscribedBodies)
+	{
+		shared_ptr<Body> b = Body::byId(id);
+		RigidBodyParameters* rb = YADE_CAST<RigidBodyParameters*>(b->physicalParameters.get());
+		Vector3r& position = rb->se3.position;
+
+		if ( (position-point).Dot(normal) < 0 )
+		{
+			Vector3r backup_pos = position;
+
+			bool is_overlap;
+
+			for (int attempt=0; attempt<maxAttempts; ++attempt)
+			{
+				position = (volumeSection) ? generatePositionInVolume():generatePositionOnSurface();
+
+				const Real r = YADE_CAST<InteractingSphere*>(b->interactingGeometry.get())->radius;
+				BoundingVolume bv;
+				bv.min = Vector3r(position[0]-r, position[1]-r, position[2]-r);
+				bv.max = Vector3r(position[0]+r, position[1]+r, position[2]+r);
+
+				is_overlap=false;
+
+				// Test overlap with already shifted bodies
+				FOREACH(shared_ptr<Body> sb, shiftedBodies)
+				{
+					if (iGME->explicitAction(b,sb)->interactionGeometry)
+					{
+						is_overlap=true;
+						break;
+					}
+				}
+				if (is_overlap) continue; // new attempt
+
+				// Test overlap with other bodies
+				if (bI->probeBoundingVolume(bv)) 
+				{
+					for( unsigned int i=0, e=bI->probedBodies.size(); i<e; ++i)
+					{
+						if (iGME->explicitAction(b,Body::byId(bI->probedBodies[i]))->interactionGeometry)
+						{
+							is_overlap=true;
+							break;
+						}
+					}
+					if (is_overlap) continue; // new attempt
+				}
+				break;
+			}
+			if (is_overlap)
+			{
+				LOG_WARN("Can't placing sphere during " << maxAttempts << " attemps.");
+				position=backup_pos;
+				return;
+			}
+
+			rb->velocity		= Vector3r(//
+					velocity[0]+velocityRange[0]*randomSymmetricUnit(),
+					velocity[1]+velocityRange[1]*randomSymmetricUnit(),
+					velocity[2]+velocityRange[2]*randomSymmetricUnit());
+			rb->angularVelocity= Vector3r(//
+					angularVelocity[0]+angularVelocityRange[0]*randomSymmetricUnit(),
+					angularVelocity[1]+angularVelocityRange[1]*randomSymmetricUnit(),
+					angularVelocity[2]+angularVelocityRange[2]*randomSymmetricUnit());
+
+			shiftedBodies.push_back(b);
+		} 
+	} // next sphere
+}
+
+Vector3r ResetRandomPosition::generatePositionOnSurface()
+{
+    body_id_t facetId = factoryFacets[(*randomFacet)()];
+    Real t1 = randomUnit();
+    Real t2 = randomUnit()*(1-t1);
+
+    shared_ptr<Body> facet = Body::byId(facetId);
+	InteractingFacet* ifacet = static_cast<InteractingFacet*>(facet->interactingGeometry.get());
+
+	return t1*(ifacet->vertices[1]-ifacet->vertices[0])+t2*(ifacet->vertices[2]-ifacet->vertices[0])+ifacet->vertices[0]+facet->physicalParameters->se3.position;
+    
+}
+
+Vector3r ResetRandomPosition::generatePositionInVolume()
+{
+    Vector3r p1 = generatePositionOnSurface();
+    Vector3r p2 = generatePositionOnSurface();
+    Real t = randomUnit();
+    return p1+t*(p2-p1);
+    
+}
+

=== added file 'pkg/common/Engine/StandAloneEngine/ResetRandomPosition.hpp'
--- pkg/common/Engine/StandAloneEngine/ResetRandomPosition.hpp	1970-01-01 00:00:00 +0000
+++ pkg/common/Engine/StandAloneEngine/ResetRandomPosition.hpp	2009-11-19 06:44:50 +0000
@@ -0,0 +1,96 @@
+/*************************************************************************
+*  Copyright (C) 2009 by Sergei Dorofeenko				 				 *
+*  sega@xxxxxxxxxxxxxxxx                                                 *
+*                                                                        *
+*  This program is free software; it is licensed under the terms of the  *
+*  GNU General Public License v2 or later. See file LICENSE for details. *
+*************************************************************************/
+#pragma once
+
+#include <yade/pkg-common/PeriodicEngines.hpp>
+#include <yade/pkg-common/InteractionGeometryMetaEngine.hpp>
+#include <yade/core/Collider.hpp>
+#include <yade/core/MetaBody.hpp>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+/// @brief Produces spheres over the course of a simulation. 
+class ResetRandomPosition : public PeriodicEngine {
+public:
+
+	ResetRandomPosition();
+	virtual ~ResetRandomPosition();
+
+	/// @brief Create one sphere per call.
+	virtual void action(MetaBody*);
+
+	/// @brief The geometry of the section on which spheres will be placed. 
+	vector<body_id_t> factoryFacets; 
+
+    /// @brief Factory section may be a surface or volume (convex). 
+    /// By default it is a surface. To make its a volume set volumeSection=true
+    bool volumeSection;
+
+	/// @brief Max attemps to place sphere.
+	/// If placing the sphere in certain random position would cause an overlap with any other physical body in the model, SpheresFactory will try to find another position. Default 20 attempts allow.
+	int maxAttempts;
+
+	/// @brief Mean velocity of spheres.
+	Vector3r velocity;
+
+	/// @brief Half size of a velocities distribution interval.
+	/// New sphere will have random velocity within the range velocity±velocityRange.
+	Vector3r velocityRange;
+	
+	/// @brief Mean angularVelocity of spheres.
+	Vector3r angularVelocity;
+
+	/// @brief Half size of a angularVelocity distribution interval.
+	/// New sphere will have random angularVelocity within the range angularVelocity±angularVelocityRange.
+	Vector3r angularVelocityRange;
+
+	Vector3r point;
+	Vector3r normal;
+
+	std::vector< int >   subscribedBodies;
+
+private:
+	/// @brief Pointer to Collider.
+	/// It is necessary in order to probe the bounding volume for new sphere.
+	Collider* bI;
+	
+	/// @brief Pointer to InteractionGeometryMetaEngine.
+	/// It is necessary in order to detect a real overlap with other bodies.
+	InteractionGeometryMetaEngine* iGME;
+
+	std::vector<shared_ptr<Body> > shiftedBodies;
+
+	bool first_run;
+
+	//bool generateNewPosition(const shared_ptr<Body>& b, Vector3r& new_position);
+    Vector3r generatePositionOnSurface();
+    Vector3r generatePositionInVolume();
+
+	typedef	boost::variate_generator<boost::minstd_rand,boost::uniform_int<> > RandomInt;
+	shared_ptr<RandomInt> randomFacet;
+
+	DECLARE_LOGGER;
+
+	REGISTER_ATTRIBUTES(PeriodicEngine,
+			(factoryFacets)
+			(subscribedBodies)
+			(point)
+			(normal)
+			(volumeSection)
+			(maxAttempts)
+			(velocity)
+			(velocityRange)
+			(angularVelocity)
+			(angularVelocityRange))
+	REGISTER_CLASS_AND_BASE(ResetRandomPosition, StandAloneEngine);
+};
+REGISTER_SERIALIZABLE(ResetRandomPosition);
+
+

=== modified file 'py/utils.py'
--- py/utils.py	2009-11-17 12:26:35 +0000
+++ py/utils.py	2009-11-19 06:44:50 +0000
@@ -124,7 +124,7 @@
 	b.dynamic=False
 	return b
 
-def facet(vertices,dynamic=False,wire=True,color=None,density=1,highlight=False,noInteractingGeometry=False,physParamsClass='BodyMacroParameters',**physParamsAttr):
+def facet(vertices,dynamic=False,wire=True,color=None,density=1,highlight=False,noBoundingVolume=False,physParamsClass='BodyMacroParameters',**physParamsAttr):
 	"""Create default facet with given parameters. Vertices are given as sequence of 3 3-tuple and they, all in global coordinates."""
 	b=Body()
 	if not color: color=randomColor()
@@ -134,12 +134,11 @@
 	pp.update({'se3':[center[0],center[1],center[2],1,0,0,0],'refSe3':[center[0],center[1],center[2],1,0,0,0],'inertia':[0,0,0]})
 	b.phys=PhysicalParameters(physParamsClass)
 	b.phys.updateExistingAttrs(pp)
-	b.bound=BoundingVolume('AABB',diffuseColor=[0,1,0])
+	if not noBoundingVolume: b.bound=BoundingVolume('AABB',diffuseColor=[0,1,0])
 	b['isDynamic']=dynamic
-	if not noInteractingGeometry: 
-		b.mold=InteractingGeometry('InteractingFacet',diffuseColor=color,wire=wire,highlight=highlight)
-		b.mold['vertices']=vertices
-		b.mold.postProcessAttributes(True)
+	b.mold=InteractingGeometry('InteractingFacet',diffuseColor=color,wire=wire,highlight=highlight)
+	b.mold['vertices']=vertices
+	b.mold.postProcessAttributes(True)
 	return b
 
 def facetBox(center,extents,orientation=[1,0,0,0],wallMask=63,**kw):

=== added file 'scripts/test/ResetRandomPosition.py'
--- scripts/test/ResetRandomPosition.py	1970-01-01 00:00:00 +0000
+++ scripts/test/ResetRandomPosition.py	2009-11-19 06:44:50 +0000
@@ -0,0 +1,62 @@
+# -*- coding: utf-8
+
+from yade import utils,pack,export,qt
+import gts,os
+
+def Plane(v1,v2,v3,v4):
+	pts = [ [Vector3(v1),Vector3(v2),Vector3(v3),Vector3(v4)] ]
+	return pack.sweptPolylines2gtsSurface(pts,capStart=True,capEnd=True)
+
+# Parameters
+tc=0.001# collision time 
+en=0.3  # normal restitution coefficient
+es=0.3  # tangential restitution coefficient
+frictionAngle=radians(35)# 
+density=2700
+kw=utils.getViscoelasticFromSpheresInteraction(10e3,tc,en,es)
+
+O.dt=.2*tc # time step
+
+Rs=0.02 # mean particle radius
+Rf=0.01 # dispersion (Rs±Rf*Rs)
+nSpheres=1000# number of particles
+
+# Create geometry
+pln=Plane( (-.5, -.5, 0), (.5, -.5, -.05), (.5, .5, 0), (-.5, .5, -.05) ); 
+plnIds=O.bodies.append(pack.gtsSurface2Facets(pln.faces(),frictionAngle=frictionAngle,physParamsClass='SimpleViscoelasticBodyParameters',color=(0,1,0),**kw))
+
+fct=Plane( (-.25, -.25, .5), (.25, -.25, .5), (.25, .25, .5), (-.25, .25, .5) ); 
+fctIds=O.bodies.append(pack.gtsSurface2Facets(fct.faces(),frictionAngle=frictionAngle,physParamsClass='SimpleViscoelasticBodyParameters',color=(1,0,0),noBoundingVolume=True))
+
+# Create spheres
+sp=pack.SpherePack(); 
+sp.makeCloud(Vector3(-.5, -.5, 0),Vector3(.5, .5, .2), Rs, Rf, int(nSpheres), False)
+spheres=O.bodies.append([utils.sphere(s[0],s[1],color=(0.929,0.412,0.412),density=density,frictionAngle=frictionAngle,physParamsClass="SimpleViscoelasticBodyParameters") for s in sp])
+for id in spheres:
+	s=O.bodies[id]
+	p=utils.getViscoelasticFromSpheresInteraction(s.phys['mass'],tc,en,es)
+	s.phys['kn'],s.phys['cn'],s.phys['ks'],s.phys['cs']=p['kn'],p['cn'],p['ks'],p['cs']
+
+# Create engines
+O.initializers=[ BoundingVolumeMetaEngine([InteractingSphere2AABB(),InteractingFacet2AABB(),MetaInteractingGeometry2AABB()]) ]
+O.engines=[
+	BexResetter(),
+	BoundingVolumeMetaEngine([InteractingSphere2AABB(),InteractingFacet2AABB(), MetaInteractingGeometry2AABB()
+	]),
+	InsertionSortCollider(nBins=5,sweepLength=.1*Rs),
+	InteractionDispatchers(
+		[InteractingSphere2InteractingSphere4SpheresContactGeometry(), InteractingFacet2InteractingSphere4SpheresContactGeometry()],
+		[SimpleViscoelasticRelationships()],
+		[ef2_Spheres_Viscoelastic_SimpleViscoelasticContactLaw()],
+	),
+	GravityEngine(gravity=[0,0,-9.81]),
+	NewtonsDampedLaw(damping=0),
+	ResetRandomPosition(factoryFacets=fctIds,velocity=(0,0,-2),virtPeriod=0.01,subscribedBodies=spheres,point=(0,0,-.5),normal=(0,0,1),maxAttempts=100),
+]
+
+renderer = qt.Renderer()
+qt.View()
+O.saveTmp()
+O.run()
+
+