yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #05244
[Branch ~yade-dev/yade/trunk] Rev 2344: - miniEigen : memory leak source suspected (FIXME added)
------------------------------------------------------------
revno: 2344
committer: bchareyre <bchareyre@dt-rv020>
branch nick: trunk
timestamp: Mon 2010-07-12 10:50:35 +0200
message:
- miniEigen : memory leak source suspected (FIXME added)
- ScGeom : #define IGCACHE by default, and keep behaviour unchanged for older functions (still some cleaning to do in this class, after all Law2's have been adapted).
- CohFrictLaw : Eigen is returning nan quaternions after trivial operations, it is workarounded in the law.
- cylinder : a new shape, first step in experiments for tracking interactions jumping over chained elements.
- utils.py : a demo script for chained cylinders
added:
pkg/common/DataClass/Shape/Cylinder.cpp
pkg/common/DataClass/Shape/Cylinder.hpp
scripts/test/chained-cylinder-spring.py
modified:
pkg/dem/DataClass/InteractionGeometry/ScGeom.cpp
pkg/dem/DataClass/InteractionGeometry/ScGeom.hpp
pkg/dem/Engine/GlobalEngine/CohesiveFrictionalContactLaw.cpp
py/mathWrap/miniEigen.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
=== added file 'pkg/common/DataClass/Shape/Cylinder.cpp'
--- pkg/common/DataClass/Shape/Cylinder.cpp 1970-01-01 00:00:00 +0000
+++ pkg/common/DataClass/Shape/Cylinder.cpp 2010-07-12 08:50:35 +0000
@@ -0,0 +1,257 @@
+#include "Cylinder.hpp"
+#include<yade/pkg-common/Sphere.hpp>
+#include<yade/lib-opengl/OpenGLWrapper.hpp>
+#include<yade/pkg-common/Aabb.hpp>
+
+Cylinder::~Cylinder(){}
+ChainedCylinder::~ChainedCylinder(){}
+ChainedState::~ChainedState(){}
+CylScGeom::~CylScGeom(){}
+
+
+YADE_PLUGIN((Cylinder)(ChainedCylinder)(ChainedState)(CylScGeom)(Ig2_Sphere_ChainedCylinder_CylScGeom)(Ig2_ChainedCylinder_ChainedCylinder_ScGeom)(Gl1_Cylinder)(Bo1_Cylinder_Aabb)/*(Bo1_ChainedCylinder_Aabb)*/);
+YADE_REQUIRE_FEATURE(OPENGL)
+
+vector<vector<int> > ChainedState::chains;
+unsigned int ChainedState::currentChain=0;
+
+//!################## IG FUNCTORS #####################
+
+#ifdef YADE_DEVIRT_FUNCTORS
+bool Ig2_Sphere_ChainedCylinder_CylScGeom::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Sphere_ChainedCylinder_CylScGeom::go, use getStaticFunctorPtr and call that function instead."); }
+bool Ig2_Sphere_ChainedCylinder_CylScGeom::goStatic(InteractionGeometryFunctor* _self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
+ const Ig2_Sphere_ChainedCylinder_CylScGeom* self=static_cast<Ig2_Sphere_ChainedCylinder_CylScGeom*>(_self);
+ const Real& interactionDetectionFactor=self->interactionDetectionFactor;
+#else
+bool Ig2_Sphere_ChainedCylinder_CylScGeom::go( const shared_ptr<Shape>& cm1,
+ const shared_ptr<Shape>& cm2,
+ const State& state1, const State& state2, const Vector3r& shift2, const bool& force,
+ const shared_ptr<Interaction>& c)
+{
+#endif
+ const Se3r& se31=state1.se3; const Se3r& se32=state2.se3;
+
+ Sphere *s1=static_cast<Sphere*>(cm1.get()), *s2=static_cast<Sphere*>(cm2.get());
+ Vector3r normal=(se32.position+shift2)-se31.position;
+ Real penetrationDepthSq=pow(interactionDetectionFactor*(s1->radius+s2->radius),2) - normal.squaredNorm();
+ if (penetrationDepthSq>0 || c->isReal() || force){
+ shared_ptr<ScGeom> scm;
+ bool isNew = !c->interactionGeometry;
+ if(!isNew) scm=YADE_PTR_CAST<ScGeom>(c->interactionGeometry);
+ else { scm=shared_ptr<ScGeom>(new ScGeom()); c->interactionGeometry=scm; }
+
+ Real norm=normal.norm(); normal/=norm; // normal is unit vector now
+ Real penetrationDepth=s1->radius+s2->radius-norm;
+ scm->contactPoint=se31.position+(s1->radius-0.5*penetrationDepth)*normal;//0.5*(pt1+pt2);
+ if(isNew) scm->prevNormal=normal;
+ else scm->prevNormal=scm->normal;
+ scm->normal=normal;
+ scm->penetrationDepth=penetrationDepth;
+ scm->radius1=s1->radius;
+ scm->radius2=s2->radius;
+#ifdef IGCACHE
+ if (scene->isPeriodic) {
+ Vector3r shiftVel = scene->cell->velGrad*scene->cell->Hsize*c->cellDist.cast<Real>();
+ scm->precompute(state1,state2,scene->dt,shiftVel,true);}
+ else scm->precompute(state1,state2,scene->dt,true);
+#endif
+ return true;
+ }
+ return false;
+}
+
+
+bool Ig2_Sphere_ChainedCylinder_CylScGeom::goReverse( const shared_ptr<Shape>& cm1,
+ const shared_ptr<Shape>& cm2,
+ const State& state1,
+ const State& state2,
+ const Vector3r& shift2,
+ const bool& force,
+ const shared_ptr<Interaction>& c)
+{
+ return go(cm1,cm2,state2,state1,-shift2,force,c);
+}
+
+
+#ifdef YADE_DEVIRT_FUNCTORS
+bool Ig2_ChainedCylinder_ChainedCylinder_ScGeom::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Sphere_ChainedCylinder_CylScGeom::go, use getStaticFunctorPtr and call that function instead."); }
+bool Ig2_ChainedCylinder_ChainedCylinder_ScGeom::goStatic(InteractionGeometryFunctor* _self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
+ const Ig2_ChainedCylinder_ChainedCylinder_ScGeom* self=static_cast<Ig2_ChainedCylinder_ChainedCylinder_ScGeom*>(_self);
+ const Real& interactionDetectionFactor=self->interactionDetectionFactor;
+#else
+bool Ig2_ChainedCylinder_ChainedCylinder_ScGeom::go( const shared_ptr<Shape>& cm1,
+ const shared_ptr<Shape>& cm2,
+ const State& state1, const State& state2, const Vector3r& shift2, const bool& force,
+ const shared_ptr<Interaction>& c)
+{
+#endif
+ const ChainedState *pChain1, *pChain2;
+ pChain1=YADE_CAST<const ChainedState*>(&state1);
+ pChain2=YADE_CAST<const ChainedState*>(&state2);
+ const ChainedState& chain1 = *pChain1;
+ const ChainedState& chain2 = *pChain2;
+ if (!pChain1 || !pChain2) {
+ cerr <<"cast failed8567"<<endl;
+ }
+ bool revert = (pChain2->rank-chain1.rank == -1);
+
+ if (pChain2->chainNumber!=pChain1->chainNumber) {cerr<<"PROBLEM0124"<<endl; return false;}
+ else if (chain2.rank-chain1.rank != 1 && pChain2->rank-pChain1->rank != -1) {/*cerr<<"PROBLEM0123"<<endl;*/ return false;}
+ const ChainedState* pChain = revert ? pChain2 : pChain1;
+
+ ChainedCylinder *s1=static_cast<ChainedCylinder*>(cm1.get()), *s2=static_cast<ChainedCylinder*>(cm2.get());
+ ChainedCylinder *s = revert ? s2 : s1;
+ shared_ptr<ScGeom> scm;
+ bool isNew = !c->interactionGeometry;
+ if(!isNew) scm=YADE_PTR_CAST<ScGeom>(c->interactionGeometry);
+ else { scm=shared_ptr<ScGeom>(new ScGeom()); c->interactionGeometry=scm; }
+ Real length=abs((pChain->ori*Vector3r::UnitZ()).dot(chain2.pos-chain1.pos));
+ Vector3r segment =pChain->ori*Vector3r::UnitZ()*length;
+
+ if (revert) segment = -segment;
+ if(isNew) {scm->normal=scm->prevNormal=segment/length;s->initLength=length;}
+ else {scm->prevNormal=scm->normal; scm->normal=segment/length;}
+
+ if (!revert) {
+ scm->radius1=s->initLength;
+ scm->radius2=0;}
+ else {
+ scm->radius1=0;
+ scm->radius2=s->initLength;}
+
+ s->length=length;
+ scm->penetrationDepth=s->initLength-length;
+ scm->contactPoint=pChain->pos+pChain->ori*Vector3r::UnitZ()*length;
+#ifdef IGCACHE
+ if (scene->isPeriodic) {
+ Vector3r shiftVel = scene->cell->velGrad*scene->cell->Hsize*c->cellDist.cast<Real>();
+ scm->precompute(state1,state2,scene->dt,shiftVel,true);}
+ else {
+ scm->precompute(state1,state2,scene->dt,true);
+ }
+#else
+ cerr<<"this is not supposed to work without #define IGCACHE"<<endl;
+#endif
+ //Set values that will be considered in Ip2 functor, geometry (precomputed) is really defined with values above
+ scm->radius1=s->initLength*0.5;
+ scm->radius2=s->initLength*0.5;
+ return true;
+}
+
+
+bool Ig2_ChainedCylinder_ChainedCylinder_ScGeom::goReverse( const shared_ptr<Shape>& cm1,
+ const shared_ptr<Shape>& cm2,
+ const State& state1,
+ const State& state2,
+ const Vector3r& shift2,
+ const bool& force,
+ const shared_ptr<Interaction>& c)
+{
+ return go(cm2,cm1,state2,state1,-shift2,force,c);
+}
+
+//!################## RENDERING #####################
+
+bool Gl1_Cylinder::wire;
+bool Gl1_Cylinder::glutNormalize;
+int Gl1_Cylinder::glutSlices;
+int Gl1_Cylinder::glutStacks;
+int Gl1_Cylinder::glCylinderList=-1;
+
+void Gl1_Cylinder::go(const shared_ptr<Shape>& cm, const shared_ptr<State>& ,bool wire2, const GLViewInfo&)
+{
+ Real r=(static_cast<Cylinder*>(cm.get()))->radius;
+ Real length=(static_cast<Cylinder*>(cm.get()))->length;
+ //glMaterialv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Vector3f(cm->color[0],cm->color[1],cm->color[2]));
+ glColor3v(cm->color);
+ if(glutNormalize) glPushAttrib(GL_NORMALIZE); // as per http://lists.apple.com/archives/Mac-opengl/2002/Jul/msg00085.html
+// glPushMatrix();
+ if (wire || wire2) drawCylinder(true, r,length);
+ else drawCylinder(false, r,length);
+ if(glutNormalize) glPopAttrib();
+// glPopMatrix();
+ return;
+}
+
+
+void Gl1_Cylinder::drawCylinder(bool wire, Real radius, Real length) const
+{
+// GLERROR;
+/* if (glCylinderList<0) {
+ glCylinderList = glGenLists(1);
+ glNewList(glCylinderList,GL_COMPILE);*/
+ glPushMatrix();
+ GLUquadricObj *quadObj = gluNewQuadric();
+ gluQuadricDrawStyle(quadObj, (GLenum) (wire ? GLU_SILHOUETTE : GLU_FILL));
+ gluQuadricNormals(quadObj, (GLenum) GLU_SMOOTH);
+ gluQuadricOrientation(quadObj, (GLenum) GLU_OUTSIDE);
+// glTranslatef(0.0,0.0,-length*0.5);
+ //scaling needs to adapt spheres or they will be elipsoids. They actually seem to disappear when commented glList code is uncommented, the cylinders are displayed correclty.
+// glScalef(1,length,1);
+ gluCylinder(quadObj, radius, radius, length, glutSlices,glutStacks);
+ gluQuadricOrientation(quadObj, (GLenum) GLU_INSIDE);
+ glutSolidSphere(radius,glutSlices,glutStacks);
+ glTranslatef(0.0,0.0,length);
+// glRotatef(180,0.0,1.0,0.0);
+ glutSolidSphere(radius,glutSlices,glutStacks);
+// gluDisk(quadObj,0.0,radius,glutSlices,_loops);
+ gluDeleteQuadric(quadObj);
+ glPopMatrix();
+// GLERROR;
+
+// glEndList();}
+// glCallList(glCylinderList);
+
+}
+
+//!################## BOUNDS FUNCTOR #####################
+
+void Bo1_Cylinder_Aabb::go(const shared_ptr<Shape>& cm, shared_ptr<Bound>& bv, const Se3r& se3, const Body* b){
+ Cylinder* cylinder = static_cast<Cylinder*>(cm.get());
+ Aabb* aabb = static_cast<Aabb*>(bv.get());
+ if(!scene->isPeriodic){
+ const Vector3r& O = se3.position;
+ Vector3r O2 = se3.position+se3.orientation*cylinder->segment;
+ aabb->min=aabb->max=O;
+ for (int k=0;k<3;k++){
+ aabb->min[k]=min(aabb->min[k],min(O[k],O2[k])-cylinder->radius);
+ aabb->max[k]=max(aabb->max[k],max(O[k],O2[k])+cylinder->radius);
+ }
+ return;
+ }
+ // adjust box size along axes so that cylinder doesn't stick out of the box even if sheared (i.e. parallelepiped)
+// if(scene->cell->hasShear()) {
+// Vector3r refHalfSize(minkSize);
+// const Vector3r& cos=scene->cell->getCos();
+// for(int i=0; i<3; i++){
+// //cerr<<"cos["<<i<<"]"<<cos[i]<<" ";
+// int i1=(i+1)%3,i2=(i+2)%3;
+// minkSize[i1]+=.5*refHalfSize[i1]*(1/cos[i]-1);
+// minkSize[i2]+=.5*refHalfSize[i2]*(1/cos[i]-1);
+// }
+// }
+// //cerr<<" || "<<halfSize<<endl;
+// aabb->min = scene->cell->unshearPt(se3.position)-minkSize;
+// aabb->max = scene->cell->unshearPt(se3.position)+minkSize;
+}
+/*
+void Bo1_ChainedCylinder_Aabb::go(const shared_ptr<Shape>& cm, shared_ptr<Bound>& bv, const Se3r& se3, const Body* b){
+ Cylinder* cylinder = static_cast<Cylinder*>(cm.get());
+ Aabb* aabb = static_cast<Aabb*>(bv.get());
+ if(!scene->isPeriodic){
+ const Vector3r& O = se3.position-se3.positioncylinder->segment*0.5;
+ //In this case, segment will be updated by Ig2_ChainedCylinder_ChainedCylinder_ScGeom, no need to rotate it
+ Vector3r O2 = se3.position+cylinder->segment*0.5;
+// cerr << O<<" "<<O2<<endl;
+ aabb->min=aabb->max=O;
+ for (int k=0;k<3;k++){
+ aabb->min[k]=min(aabb->min[k],min(O[k],O2[k])-cylinder->radius);
+ aabb->max[k]=max(aabb->max[k],max(O[k],O2[k])+cylinder->radius);
+ }
+ return;
+ }
+}*/
+
+
+
+
=== added file 'pkg/common/DataClass/Shape/Cylinder.hpp'
--- pkg/common/DataClass/Shape/Cylinder.hpp 1970-01-01 00:00:00 +0000
+++ pkg/common/DataClass/Shape/Cylinder.hpp 2010-07-12 08:50:35 +0000
@@ -0,0 +1,167 @@
+#pragma once
+#include<yade/core/Shape.hpp>
+#include<yade/core/State.hpp>
+#include<yade/core/Body.hpp>
+#include<yade/pkg-dem/ScGeom.hpp>
+#include<yade/pkg-common/InteractionGeometryFunctor.hpp>
+#include<yade/core/Scene.hpp>
+#include<yade/pkg-common/GLDrawFunctors.hpp>
+#include<yade/pkg-common/BoundFunctor.hpp>
+
+
+class Cylinder: public Shape{
+ public:
+ Cylinder(Real _radius, Real _length): radius(_radius), length(_length), segment(Vector3r(0,0,1)*_length){ createIndex(); }
+ virtual ~Cylinder ();
+ YADE_CLASS_BASE_DOC_ATTRS_CTOR(Cylinder,Shape,"Geometry of a cylinder, as Minkowsky sum of line and sphere.",
+ ((Real,radius,NaN,"Radius [m]"))
+ ((Real,length,NaN,"Length [m]"))
+ ((Vector3r,segment,Vector3r::Zero(),"Length vector")),
+ createIndex(); /*ctor*/
+ );
+ REGISTER_CLASS_INDEX(Cylinder,Shape);
+};
+
+class ChainedCylinder: public Cylinder{
+ public:
+ ChainedCylinder(Real _radius, Real _length): Cylinder(_radius,_length){}
+ virtual ~ChainedCylinder ();
+ //Keep pointers or copies of connected states?
+// ChainedState st1, st2;
+
+
+ YADE_CLASS_BASE_DOC_ATTRS_CTOR(ChainedCylinder,Cylinder,"Geometry of a deformable chained cylinder, using geometry :yref:`MinkCylinder`.",
+ ((Real,initLength,0,"tensile-free length, used as reference for tensile strain"))
+ ,createIndex();/*ctor*/
+// state=shared_ptr<ChainedState>(new ChainedState);
+
+ );
+ REGISTER_CLASS_INDEX(ChainedCylinder,Cylinder);
+};
+
+class CylScGeom: public ScGeom{
+ public:
+ virtual ~CylScGeom ();
+ YADE_CLASS_BASE_DOC_ATTRS_CTOR(CylScGeom,ScGeom,"Geometry of a cylinder-sphere contact.",
+ ((bool,onNode,false,"contact on node")),
+ createIndex(); /*ctor*/
+ );
+ REGISTER_CLASS_INDEX(CylScGeom,ScGeom);
+};
+
+
+class ChainedState: public State{
+ public:
+ static vector<vector<int> > chains;
+ static unsigned int currentChain;
+ vector<int> barContacts;
+ vector<int> nodeContacts;
+
+ virtual ~ChainedState ();
+ void addToChain(int bodyId) {
+ if (chains.size()<=currentChain) chains.resize(currentChain+1);
+ chainNumber=currentChain;
+ rank=chains[currentChain].size();
+ chains[currentChain].push_back(rank);}
+
+ YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(ChainedState,State,"State of a chained bodies, containing information on connectivity in order to track contacts jumping over contiguous elements. Chains are 1D lists from which id of chained bodies are retrieved via :yref:rank<ChainedState::rank>` and :yref:chainNumber<ChainedState::chainNumber>`.",
+ ((int,rank,0,"rank in the chain"))
+ ((int,chainNumber,0,"chain id"))
+ ,
+ /* additional initializers */
+/* ((pos,se3.position))
+ ((ori,se3.orientation)),*/
+ /* ctor */,
+ /*py*/,
+// .def_readwrite("chains",&ChainedState::chains,"documentation")
+ .def_readwrite("currentChain",&ChainedState::currentChain,"Current active chain (where newly created chained bodies will be appended).")
+ .def("addToChain",&ChainedState::addToChain,(python::arg("bodyId")),"Add body to current active chain")
+ );
+};
+
+
+
+class Ig2_Sphere_ChainedCylinder_CylScGeom: public InteractionGeometryFunctor{
+ public:
+ virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ virtual bool goReverse( const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ #ifdef YADE_DEVIRT_FUNCTORS
+ void* getStaticFuncPtr(){ return (void*)&Ig2_Sphere_ChainedCylinder_CylScGeom::goStatic; }
+ static bool goStatic(InteractionGeometryFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ #endif
+ YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_ChainedCylinder_CylScGeom,InteractionGeometryFunctor,"Create/update a :yref:`ScGeom` instance representing intersection of two :yref:`Spheres<Sphere>`.",
+ ((Real,interactionDetectionFactor,1,"Enlarge both radii by this factor (if >1), to permit creation of distant interactions."))
+ );
+ FUNCTOR2D(Sphere,ChainedCylinder);
+ DEFINE_FUNCTOR_ORDER_2D(Sphere,ChainedCylinder);
+};
+
+class Ig2_ChainedCylinder_ChainedCylinder_ScGeom: public InteractionGeometryFunctor{
+ public:
+ virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ virtual bool goReverse( const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ #ifdef YADE_DEVIRT_FUNCTORS
+ void* getStaticFuncPtr(){ return (void*)&Ig2_Sphere_ChainedCylinder_CylScGeom::goStatic; }
+ static bool goStatic(InteractionGeometryFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
+ #endif
+ YADE_CLASS_BASE_DOC_ATTRS(Ig2_ChainedCylinder_ChainedCylinder_ScGeom,InteractionGeometryFunctor,"Create/update a :yref:`ScGeom` instance representing connexion between :yref:`chained cylinders<ChainedCylinder>`.",
+ ((Real,interactionDetectionFactor,1,"Enlarge both radii by this factor (if >1), to permit creation of distant interactions."))
+ );
+ FUNCTOR2D(ChainedCylinder,ChainedCylinder);
+ // needed for the dispatcher, even if it is symmetric
+ DEFINE_FUNCTOR_ORDER_2D(ChainedCylinder,ChainedCylinder);
+};
+
+
+
+
+class Gl1_Cylinder : public GlShapeFunctor{
+ private:
+ static int glCylinderList;
+ void subdivideTriangle(Vector3r& v1,Vector3r& v2,Vector3r& v3, int depth);
+ void drawCylinder(bool wire, Real radius, Real length) const;
+ void initGlLists(void);
+ public:
+ virtual void go(const shared_ptr<Shape>&, const shared_ptr<State>&,bool,const GLViewInfo&);
+ YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_Cylinder,GlShapeFunctor,"Renders :yref:`Cylinder` object",
+ ((bool,wire,false,"Only show wireframe (controlled by ``glutSlices`` and ``glutStacks``."))
+ ((bool,glutNormalize,true,"Fix normals for non-wire rendering"))
+ ((int,glutSlices,8,"Number of sphere slices."))
+ ((int,glutStacks,4,"Number of sphere stacks."))
+ );
+ RENDERS(Cylinder);
+};
+
+class Bo1_Cylinder_Aabb : public BoundFunctor
+{
+ public :
+ void go(const shared_ptr<Shape>& cm, shared_ptr<Bound>& bv, const Se3r&, const Body*);
+ FUNCTOR2D(Cylinder,Aabb);
+ YADE_CLASS_BASE_DOC_ATTRS(Bo1_Cylinder_Aabb,BoundFunctor,"Functor creating :yref:`Aabb` from :yref:`Cylinder`.",
+ ((Real,aabbEnlargeFactor,((void)"deactivated",-1),"Relative enlargement of the bounding box; deactivated if negative.\n\n.. note::\n\tThis attribute is used to create distant interaction, but is only meaningful with an :yref:`InteractionGeometryFunctor` which will not simply discard such interactions: :yref:`Ig2_Cylinder_Cylinder_Dem3DofGeom::distFactor` / :yref:`Ig2_Cylinder_Cylinder_ScGeom::interactionDetectionFactor` should have the same value as :yref:`aabbEnlargeFactor<Bo1_Cylinder_Aabb::aabbEnlargeFactor>`."))
+ );
+};
+
+// Keep this : Cylinders and ChainedCylinders will have different centers maybe.
+// class Bo1_ChainedCylinder_Aabb : public Bo1_Cylinder_Aabb
+// {
+// public :
+// void go(const shared_ptr<Shape>& cm, shared_ptr<Bound>& bv, const Se3r&, const Body*);
+// FUNCTOR2D(ChainedCylinder,Aabb);
+// YADE_CLASS_BASE_DOC_ATTRS(Bo1_ChainedCylinder_Aabb,Bo1_Cylinder_Aabb,"Functor creating :yref:`Aabb` from :yref:`Cylinder`.",
+// ((Real,aabbEnlargeFactor,((void)"deactivated",-1),"Relative enlargement of the bounding box; deactivated if negative.\n\n.. note::\n\tThis attribute is used to create distant interaction, but is only meaningful with an :yref:`InteractionGeometryFunctor` which will not simply discard such interactions: :yref:`Ig2_Cylinder_Cylinder_Dem3DofGeom::distFactor` / :yref:`Ig2_Cylinder_Cylinder_ScGeom::interactionDetectionFactor` should have the same value as :yref:`aabbEnlargeFactor<Bo1_Cylinder_Aabb::aabbEnlargeFactor>`."))
+// );
+// };
+
+
+
+
+REGISTER_SERIALIZABLE(Bo1_Cylinder_Aabb);
+// REGISTER_SERIALIZABLE(Bo1_ChainedCylinder_Aabb);
+REGISTER_SERIALIZABLE(Gl1_Cylinder);
+REGISTER_SERIALIZABLE(Cylinder);
+REGISTER_SERIALIZABLE(ChainedCylinder);
+REGISTER_SERIALIZABLE(ChainedState);
+REGISTER_SERIALIZABLE(CylScGeom);
+REGISTER_SERIALIZABLE(Ig2_Sphere_ChainedCylinder_CylScGeom);
+REGISTER_SERIALIZABLE(Ig2_ChainedCylinder_ChainedCylinder_ScGeom);
=== modified file 'pkg/dem/DataClass/InteractionGeometry/ScGeom.cpp'
--- pkg/dem/DataClass/InteractionGeometry/ScGeom.cpp 2010-07-08 18:37:01 +0000
+++ pkg/dem/DataClass/InteractionGeometry/ScGeom.cpp 2010-07-12 08:50:35 +0000
@@ -126,10 +126,10 @@
//Removing this function will need to adapt all laws
Vector3r ScGeom::rotateAndGetShear(Vector3r& shearForce, const Vector3r& prevNormal, const State* rbp1, const State* rbp2, Real dt, const Vector3r& shiftVel, bool avoidGranularRatcheting){
-#ifdef IGCACHE
- rotate(shearForce);
- return shearIncrement;
-#else
+// #ifdef IGCACHE
+// rotate(shearForce);
+// return shearIncrement;
+// #else
rotate(shearForce,prevNormal,rbp1,rbp2,dt);
Vector3r& x = contactPoint;
Vector3r c1x, c2x;
@@ -150,13 +150,13 @@
relativeVelocity = relativeVelocity-normal.dot(relativeVelocity)*normal;
Vector3r shearDisplacement = relativeVelocity*dt;
return shearDisplacement;
-#endif //IGCACHE
+// #endif //IGCACHE
}
Vector3r& ScGeom::rotate(Vector3r& shearForce, const Vector3r& prevNormal, const State* rbp1, const State* rbp2, Real dt){
-#ifdef IGCACHE
- return rotate(shearForce);
-#else
+// #ifdef IGCACHE
+// return rotate(shearForce);
+// #else
Vector3r axis;
Real angle;
// approximated rotations
@@ -178,7 +178,7 @@
// shearForce = q*shearForce;
return shearForce;
-#endif
+// #endif
}
Vector3r ScGeom::getIncidentVel(const State* rbp1, const State* rbp2, Real dt, const Vector3r& shiftVel, bool avoidGranularRatcheting){
=== modified file 'pkg/dem/DataClass/InteractionGeometry/ScGeom.hpp'
--- pkg/dem/DataClass/InteractionGeometry/ScGeom.hpp 2010-07-08 18:37:01 +0000
+++ pkg/dem/DataClass/InteractionGeometry/ScGeom.hpp 2010-07-12 08:50:35 +0000
@@ -14,7 +14,7 @@
*/
#define SCG_SHEAR
-// #define IGCACHE
+#define IGCACHE
class ScGeom: public GenericSpheresContact {
public:
=== modified file 'pkg/dem/Engine/GlobalEngine/CohesiveFrictionalContactLaw.cpp'
--- pkg/dem/Engine/GlobalEngine/CohesiveFrictionalContactLaw.cpp 2010-06-08 22:25:00 +0000
+++ pkg/dem/Engine/GlobalEngine/CohesiveFrictionalContactLaw.cpp 2010-07-12 08:50:35 +0000
@@ -74,6 +74,7 @@
if (un < 0 && (currentContactPhysics->normalForce.squaredNorm() > pow(currentContactPhysics->normalAdhesion,2)
|| currentContactPhysics->normalAdhesion==0)) {
// BREAK due to tension
+ cerr <<"requesterase";
ncb->interactions->requestErase(contact->getId1(),contact->getId2());
// contact->interactionPhysics was reset now; currentContactPhysics still hold the object, but is not associated with the interaction anymore
// currentContactPhysics->cohesionBroken = true;
@@ -85,7 +86,12 @@
///////////////////////// CREEP START ///////////
if (shear_creep) shearForce -= currentContactPhysics->ks*(shearForce*dt/creep_viscosity);
///////////////////////// CREEP END ////////////
+#ifdef IGCACHE
+ Vector3r& shearForce = currentContactGeometry->rotate(currentContactPhysics->shearForce);
+ const Vector3r& dus = currentContactGeometry->shearIncrement;
+#else
Vector3r dus = currentContactGeometry->rotateAndGetShear(shearForce,currentContactPhysics->prevNormal,de1,de2,dt);
+#endif
//Linear elasticity giving "trial" shear force
shearForce -= currentContactPhysics->ks*dus;
@@ -98,13 +104,13 @@
if (currentContactPhysics->fragile && !currentContactPhysics->cohesionBroken) {
currentContactPhysics->SetBreakingState();
maxFs = max((Real) 0, Fn*currentContactPhysics->tangensOfFrictionAngle);
+
}
maxFs = maxFs / Fs;
if (maxFs>1) cerr << "maxFs>1!!" << endl;
shearForce *= maxFs;
if (Fn<0) currentContactPhysics->normalForce = Vector3r::Zero();//Vector3r::Zero()
}
-
applyForceAtContactPoint(-currentContactPhysics->normalForce-shearForce, currentContactGeometry->contactPoint, id1, de1->se3.position, id2, de2->se3.position, ncb);
/// Moment law ///
@@ -116,16 +122,16 @@
// Quaternionr align(axis,angle);
// currentContactPhysics->currentContactOrientation = align * currentContactPhysics->currentContactOrientation;
//}
-
- Quaternionr delta(b1->state->ori * currentContactPhysics->initialOrientation1.conjugate() *
- currentContactPhysics->initialOrientation2 * b2->state->ori.conjugate());
+ Quaternionr delta((b1->state->ori * (currentContactPhysics->initialOrientation1.conjugate())) *
+ (currentContactPhysics->initialOrientation2 * (b2->state->ori.conjugate())));
if (twist_creep) {
delta = delta * currentContactPhysics->twistCreep;
}
AngleAxisr aa(delta); // axis of rotation - this is the Moment direction UNIT vector; // angle represents the power of resistant ELASTIC moment
+ //Eigen::AngleAxisr(q) returns nan's when q close to identity, next tline fixes the pb.
+ if (isnan(aa.angle())) aa.angle()=0;
if (aa.angle() > Mathr::PI) aa.angle() -= Mathr::TWO_PI; // angle is between 0 and 2*pi, but should be between -pi and pi
-
Real angle_twist(aa.angle() * aa.axis().dot(currentContactGeometry->normal));
Vector3r axis_twist(angle_twist * currentContactGeometry->normal);
=== modified file 'py/mathWrap/miniEigen.cpp'
--- py/mathWrap/miniEigen.cpp 2010-06-08 22:25:00 +0000
+++ py/mathWrap/miniEigen.cpp 2010-07-12 08:50:35 +0000
@@ -99,6 +99,7 @@
static Matrix3r* Matrix3r_fromElements(Real m00, Real m01, Real m02, Real m10, Real m11, Real m12, Real m20, Real m21, Real m22){ Matrix3r* m(new Matrix3r); (*m)<<m00,m01,m02,m10,m11,m12,m20,m21,m22; return m; }
static Quaternionr Quaternionr_setFromTwoVectors(Quaternionr& q, const Vector3r& u, const Vector3r& v){ return q.setFromTwoVectors(u,v); }
static Vector3r Quaternionr_Rotate(Quaternionr& q, const Vector3r& u){ return q*u; }
+//FIXME : risk of memory leak with these "new"?
static Quaternionr* Quaternionr_fromAxisAngle(const Vector3r& axis, const Real angle){ return new Quaternionr(AngleAxisr(angle,axis)); }
static Quaternionr* Quaternionr_fromAngleAxis(const Real angle, const Vector3r& axis){ return new Quaternionr(AngleAxisr(angle,axis)); }
static bp::tuple Quaternionr_toAxisAngle(const Quaternionr& self){ AngleAxisr aa(self); return bp::make_tuple(aa.axis(),aa.angle());}
=== modified file 'py/utils.py'
--- py/utils.py 2010-06-29 21:02:29 +0000
+++ py/utils.py 2010-07-12 08:50:35 +0000
@@ -208,6 +208,36 @@
b.mask=mask
return b
+
+def chCylinder(begin=Vector3(0,0,0),end=Vector3(1.,0.,0.),radius=0.2,dynamic=True,wire=False,color=None,highlight=False,material=-1,mask=1):
+ """Create and chain a MinkCylinder with given parameters. This shape is the Minkowsky sum of line and sphere.
+
+ :Parameters:
+ `radius`: Real
+ radius of sphere in the Minkowsky sum.
+ `begin`: Vector3
+ first point positioning the line in the Minkowsky sum
+ `last`: Vector3
+ last point positioning the line in the Minkowsky sum
+
+ In order to build a correct chain, last point of element of rank N must correspond to first point of element of rank N+1 in the same chain (with some tolerance, since bounding boxes will be used to create connections."""
+ segment=end-begin
+ b=Body()
+ b.shape=ChainedCylinder(radius=radius,length=segment.norm(),color=color if color else randomColor(),wire=wire,highlight=highlight)
+ b.shape.segment=b.shape.length*Vector3(0.,0.,1.)
+ V=2*(4./3)*math.pi*radius**3
+ geomInert=(2./5.)*V*radius**2+b.shape.length*b.shape.length*2*(4./3)*math.pi*radius**3
+ b.state=ChainedState()
+ b.state.addToChain(b.id)
+ #b.state.blockedDOFs=['rx','ry','rz']
+ _commonBodySetup(b,V,Vector3(geomInert,geomInert,geomInert),material,resetState=False)
+ b.state.pos=b.state.refPos=begin
+ b.dynamic=dynamic
+ b.mask=mask
+ b.bound=Aabb(diffuseColor=[0,1,0])
+ b.state.ori=b.state.ori.setFromTwoVectors(Vector3(0.,0.,1.),segment)
+ return b
+
def wall(position,axis,sense=0,color=None,material=-1,mask=1):
"""Return ready-made wall body.
=== added file 'scripts/test/chained-cylinder-spring.py'
--- scripts/test/chained-cylinder-spring.py 1970-01-01 00:00:00 +0000
+++ scripts/test/chained-cylinder-spring.py 2010-07-12 08:50:35 +0000
@@ -0,0 +1,72 @@
+#--- bruno.chareyre@xxxxxxxxxxx ---
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Experiment beam-like behaviour with chained cylinders + CohFrict connexions
+
+from yade import utils
+young=1.0e6
+poisson=10
+density=2.60e3
+frictionAngle=radians(30)
+O.materials.append(CohFrictMat(young=young,poisson=poisson,density=density,frictionAngle=frictionAngle,label='mat'))
+O.dt=9e-5
+
+O.initializers=[
+ ## Create bounding boxes. They are needed to zoom the 3d view properly before we start the simulation.
+ BoundDispatcher([Bo1_Sphere_Aabb(),Bo1_Cylinder_Aabb()])
+]
+
+O.engines=[
+ ForceResetter(),
+ BoundDispatcher([
+ Bo1_Cylinder_Aabb(),
+ Bo1_Sphere_Aabb()
+ ]),
+ InsertionSortCollider(),
+ InteractionDispatchers(
+ [Ig2_ChainedCylinder_ChainedCylinder_ScGeom(),Ig2_Sphere_ChainedCylinder_CylScGeom()],
+ [Ip2_2xCohFrictMat_CohFrictPhys(setCohesionNow=True,setCohesionOnNewContacts=True,normalCohesion=1e13,shearCohesion=1e13)],
+ [Law2_ScGeom_CohFrictPhys_ElasticPlastic(momentRotationLaw=True,label='law')]
+ ),
+ ## Apply gravity
+ GravityEngine(gravity=[0,-9.81,0]),
+ ## Motion equation
+ NewtonIntegrator(damping=0.15),
+ PeriodicPythonRunner(iterPeriod=500,command='history()'),
+ #PeriodicPythonRunner(iterPeriod=100,command='yade.qt.center()')
+]
+
+#Generate a spiral
+Ne=200
+for i in range(0, Ne):
+ omega=60.0/float(Ne); hy=0.10; hz=0.15;
+ px=float(i)*(omega/60.0); py=sin(float(i)*omega)*hy; pz=cos(float(i)*omega)*hz;
+ px2=float(i+1.)*(omega/60.0); py2=sin(float(i+1.)*omega)*hy; pz2=cos(float(i+1.)*omega)*hz;
+ O.bodies.append(utils.chCylinder(begin=Vector3(pz,py,px), radius=0.005,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5)))
+
+def outp(id=1):
+ for i in O.interactions:
+ if i.id1 == 1:
+ print i.phys.shearForce
+ print i.phys.normalForce
+ return i
+
+O.bodies[Ne-1].state.blockedDOFs=['x','y','z','rx','ry','rz']
+yade.qt.View();
+
+
+ #plot some results
+from math import *
+from yade import plot
+plot.plots={'t':('pos1','|||','vel1')}
+def history():
+ plot.addData(pos1=O.bodies[0].state.pos[1], # potential elastic energy
+ vel1=O.bodies[0].state.vel[1],
+ t=O.time)
+
+#yade.qt.Renderer().bound=True
+#O.run(1,True)
+plot.plot()
+#O.bodies[0].state.angVel=Vector3(0.05,0,0)
+
Follow ups