yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01202
[svn] r1757 - in trunk: extra pkg/common/DataClass/InteractingGeometry pkg/dem pkg/dem/DataClass/InteractionGeometry pkg/dem/Engine/EngineUnit pkg/dem/Engine/StandAloneEngine scripts/test
Author: eudoxos
Date: 2009-04-22 08:57:45 +0200 (Wed, 22 Apr 2009)
New Revision: 1757
Added:
trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.cpp
Modified:
trunk/extra/Brefcom.cpp
trunk/extra/Brefcom.hpp
trunk/extra/SConscript
trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.cpp
trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.hpp
trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp
trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.hpp
trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp
trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp
trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.hpp
trunk/pkg/dem/DataClass/InteractionGeometry/SpheresContactGeometry.hpp
trunk/pkg/dem/Engine/EngineUnit/InteractingFacet2InteractingSphere4SpheresContactGeometry.cpp
trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.cpp
trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.hpp
trunk/pkg/dem/SConscript
trunk/scripts/test/facet-topo.py
Log:
1. Finish implementation of Dof3DofGeom_FacetSphere (with plastic slip as well)
2. Adapt Brefcom optionally to Dem3DofGeom
3. Add d0fixup to SpheresContactGeometry to get correct normal strain in sphere-facet contact with fictive sphere
(zero for sphere-sphere)
4. Finish FacetTopologyAnalyzer; angle usage in Dem4DofGeom_FacetSphere not yet tested.
Modified: trunk/extra/Brefcom.cpp
===================================================================
--- trunk/extra/Brefcom.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/extra/Brefcom.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -5,6 +5,7 @@
#include<yade/pkg-common/Sphere.hpp>
#include<yade/lib-QGLViewer/qglviewer.h>
#include<yade/lib-opengl/GLUtils.hpp>
+#include<yade/pkg-dem/DemXDofGeom.hpp>
YADE_PLUGIN("BrefcomMakeContact","BrefcomContact","BrefcomLaw","GLDrawBrefcomContact","BrefcomDamageColorizer", "BrefcomPhysParams", "BrefcomGlobalCharacteristics", "ef2_Spheres_Brefcom_BrefcomLaw" /* ,"BrefcomStiffnessComputer"*/ );
@@ -66,7 +67,11 @@
//! @todo Formulas in the following should be verified
void BrefcomMakeContact::go(const shared_ptr<PhysicalParameters>& pp1, const shared_ptr<PhysicalParameters>& pp2, const shared_ptr<Interaction>& interaction){
- const shared_ptr<SpheresContactGeometry>& contGeom=YADE_PTR_CAST<SpheresContactGeometry>(interaction->interactionGeometry);
+ #ifdef BREFCOM_DEM3DOF
+ const Dem3DofGeom* contGeom=YADE_CAST<Dem3DofGeom*>(interaction->interactionGeometry.get());
+ #else
+ const SpheresContactGeometry* contGeom=YADE_CAST<SpheresContactGeometry*>(interaction->interactionGeometry.get());
+ #endif
assert(contGeom); // for now, don't handle anything other than SpheresContactGeometry
if(!interaction->isNew && interaction->interactionPhysics){ /* relax */ }
@@ -78,7 +83,12 @@
Real E12=2*elast1->young*elast2->young/(elast1->young+elast2->young); // harmonic Young's modulus average
//Real nu12=2*elast1->poisson*elast2->poisson/(elast1->poisson+elast2->poisson); // dtto for Poisson ratio
- Real S12=Mathr::PI*pow(min(contGeom->radius1,contGeom->radius2),2); // "surface" of interaction
+ #ifdef BREFCOM_DEM3DOF
+ Real minRad=(contGeom->refR1<=0?contGeom->refR2:(contGeom->refR2<=0?contGeom->refR1:min(contGeom->refR1,contGeom->refR2)));
+ Real S12=Mathr::PI*pow(minRad,2); // "surface" of interaction
+ #else
+ Real S12=Mathr::PI*pow(min(contGeom->radius1,contGeom->radius2),2); // "surface" of interaction
+ #endif
//Real E=(E12 /* was here for Kn: *S12/d0 */)*((1+alpha)/(beta*(1+nu12)+gamma*(1-alpha*nu12)));
//Real E=E12; // apply alpha, beta, gamma: garbage values of E !?
@@ -189,7 +199,12 @@
void ef2_Spheres_Brefcom_BrefcomLaw::go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, MetaBody* rootBody){
//timingDeltas->start();
- SpheresContactGeometry* contGeom=static_cast<SpheresContactGeometry*>(_geom.get());
+ #ifdef BREFCOM_DEM3DOF
+ Dem3DofGeom* contGeom=static_cast<Dem3DofGeom*>(_geom.get());
+ #else
+ SpheresContactGeometry* contGeom=static_cast<SpheresContactGeometry*>(_geom.get());
+ assert(contGeom->hasShear);
+ #endif
BrefcomContact* BC=static_cast<BrefcomContact*>(_phys.get());
/* kept fully damaged contacts; note that normally the contact is deleted _after_ the BREFCOM_MATERIAL_MODEL,
@@ -206,11 +221,17 @@
#define NNAN(a) assert(!isnan(a));
#define NNANV(v) assert(!isnan(v[0])); assert(!isnan(v[1])); assert(!isnan(v[2]));
- assert(contGeom->hasShear);
//timingDeltas->checkpoint("setup");
- epsN=contGeom->epsN(); epsT=contGeom->epsT();
+ #ifdef BREFCOM_DEM3DOF
+ epsN=contGeom->strainN(); epsT=contGeom->strainT();
+ #else
+ epsN=contGeom->epsN(); epsT=contGeom->epsT();
+ #endif
if(isnan(epsN)){
- LOG_ERROR("d0="<<contGeom->d0<<", d1,d2="<<contGeom->d1<<","<<contGeom->d2<<"; pos1,pos2="<<contGeom->pos1<<","<<contGeom->pos2);
+ #ifndef BREFCOM_DEM3DOF
+ LOG_ERROR("d0="<<contGeom->d0<<", d1,d2="<<contGeom->d1<<","<<contGeom->d2<<"; pos1,pos2="<<contGeom->pos1<<","<<contGeom->pos2);
+ #endif
+ throw;
}
NNAN(epsN); NNANV(epsT);
// already in SpheresContactGeometry:
@@ -237,7 +258,11 @@
Fn=sigmaN*crossSection; BC->normalForce=Fn*contGeom->normal;
Fs=sigmaT*crossSection; BC->shearForce=Fs;
- applyForceAtContactPoint(BC->normalForce+BC->shearForce, contGeom->contactPoint, I->getId1(), contGeom->pos1, I->getId2(), contGeom->pos2, rootBody);
+ #ifdef BREFCOM_DEM3DOF
+ applyForceAtContactPoint(BC->normalForce+BC->shearForce, contGeom->contactPoint, I->getId1(), contGeom->se31.position, I->getId2(), contGeom->se32.position, rootBody);
+ #else
+ applyForceAtContactPoint(BC->normalForce+BC->shearForce, contGeom->contactPoint, I->getId1(), contGeom->pos1, I->getId2(), contGeom->pos2, rootBody);
+ #endif
//timingDeltas->checkpoint("rest");
}
Modified: trunk/extra/Brefcom.hpp
===================================================================
--- trunk/extra/Brefcom.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/extra/Brefcom.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -174,6 +174,8 @@
};
REGISTER_SERIALIZABLE(BrefcomPhysParams);
+//#define BREFCOM_DEM3DOF
+
class ef2_Spheres_Brefcom_BrefcomLaw: public ConstitutiveLaw{
public:
/*! Damage evolution law */
@@ -184,7 +186,11 @@
bool logStrain;
ef2_Spheres_Brefcom_BrefcomLaw(): logStrain(false){ /*timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);*/ }
void go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, MetaBody* rootBody);
- FUNCTOR2D(SpheresContactGeometry,BrefcomContact);
+ #ifdef BREFCOM_DEM3DOF
+ FUNCTOR2D(Dem3DofGeom,BrefcomContact);
+ #else
+ FUNCTOR2D(SpheresContactGeometry,BrefcomContact);
+ #endif
REGISTER_CLASS_AND_BASE(ef2_Spheres_Brefcom_BrefcomLaw,ConstitutiveLaw);
REGISTER_ATTRIBUTES(ConstitutiveLaw,(logStrain));
DECLARE_LOGGER;
Modified: trunk/extra/SConscript
===================================================================
--- trunk/extra/SConscript 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/extra/SConscript 2009-04-22 06:57:45 UTC (rev 1757)
@@ -42,9 +42,9 @@
env.SharedLibrary('UniaxialStrainControlledTest',['usct/UniaxialStrainControlledTest.cpp'],LIBS=env['LIBS']+['Shop','GlobalStiffnessTimeStepper','Brefcom','PositionOrientationRecorder']),
- env.SharedLibrary('Brefcom',['Brefcom.cpp'],CXXFLAGS=env['CXXFLAGS']+brefcomInclude,LIBS=env['LIBS']+['Shop','InteractingSphere2InteractingSphere4SpheresContactGeometry']),
+ env.SharedLibrary('Brefcom',['Brefcom.cpp'],CXXFLAGS=env['CXXFLAGS']+brefcomInclude,LIBS=env['LIBS']+['Shop','InteractingSphere2InteractingSphere4SpheresContactGeometry','DemXDofGeom']),
- env.SharedLibrary('BrefcomTestGen',['BrefcomTestGen.cpp'],LIBS=env['LIBS']+['Shop','UniaxialStrainControlledTest','PositionOrientationRecorder']),
+ env.SharedLibrary('BrefcomTestGen',['BrefcomTestGen.cpp'],LIBS=env['LIBS']+['Shop','UniaxialStrainControlledTest','PositionOrientationRecorder','Brefcom']),
env.SharedLibrary('SimpleScene',['SimpleScene.cpp'],LIBS=env['LIBS']+['Shop','SimpleElasticRelationships']),
Modified: trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.cpp
===================================================================
--- trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -12,7 +12,7 @@
createIndex();
#ifdef FACET_TOPO
edgeAdjIds.resize(3,Body::ID_NONE);
- edgeAdjAngle.resize(3,0);
+ edgeAdjHalfAngle.resize(3,0);
#endif
}
@@ -26,7 +26,7 @@
REGISTER_ATTRIBUTE(vertices);
#ifdef FACET_TOPO
REGISTER_ATTRIBUTE(edgeAdjIds);
- REGISTER_ATTRIBUTE(edgeAdjAngle);
+ REGISTER_ATTRIBUTE(edgeAdjHalfAngle);
#endif
}
Modified: trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.hpp
===================================================================
--- trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/common/DataClass/InteractingGeometry/InteractingFacet.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -41,8 +41,8 @@
#ifdef FACET_TOPO
//! facet id's that are adjacent to respective edges
vector<body_id_t> edgeAdjIds;
- //! angle between normals of this facet and the adjacent facet
- vector<body_id_t> edgeAdjAngle;
+ //! half angle between normals of this facet and the adjacent facet
+ vector<Real> edgeAdjHalfAngle;
#endif
protected:
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -7,7 +7,6 @@
Dem3DofGeom_FacetSphere::~Dem3DofGeom_FacetSphere(){}
void Dem3DofGeom_FacetSphere::setTgPlanePts(const Vector3r& p1new, const Vector3r& p2new){
- // FIXME: not tested yet
TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());
cp1pt=se31.orientation.Conjugate()*(turnPlanePt(p1new,normal,se31.orientation*localFacetNormal)+contactPoint-se31.position);
cp2rel=se32.orientation.Conjugate()*Dem3DofGeom_SphereSphere::rollPlanePtToSphere(p2new,effR2,-normal);
@@ -21,6 +20,19 @@
}
}
+Real Dem3DofGeom_FacetSphere::slipToDisplacementTMax(Real displacementTMax){
+ //FIXME: not yet tested
+ // negative or zero: reset shear
+ if(displacementTMax<=0.){ setTgPlanePts(Vector3r(0,0,0),Vector3r(0,0,0)); return displacementTMax;}
+ // otherwise
+ Vector3r p1=contPtInTgPlane1(), p2=contPtInTgPlane2();
+ Real currDistSq=(p2-p1).SquaredLength();
+ if(currDistSq<pow(displacementTMax,2)) return 0; // close enough, no slip needed
+ //Vector3r diff=.5*(sqrt(currDistSq)/displacementTMax-1)*(p2-p1); setTgPlanePts(p1+diff,p2-diff);
+ Real scale=displacementTMax/sqrt(currDistSq); setTgPlanePts(scale*p1,scale*p2);
+ return (displacementTMax/scale)*(1-scale);
+}
+
CREATE_LOGGER(ef2_Facet_Sphere_Dem3DofGeom);
bool ef2_Facet_Sphere_Dem3DofGeom::go(const shared_ptr<InteractingGeometry>& cm1, const shared_ptr<InteractingGeometry>& cm2, const Se3r& se31, const Se3r& se32, const shared_ptr<Interaction>& c){
InteractingFacet* facet=static_cast<InteractingFacet*>(cm1.get());
@@ -49,12 +61,29 @@
normal.Normalize();
} else { // contact with the edge
contactPt+=edgeNormals[edgeMax]*(inCircleR-distMax);
+ bool noVertexContact=false;
//TRVAR3(edgeNormals[edgeMax],inCircleR,distMax);
// contact with vertex no. edgeMax
- if (contactPt.Dot(edgeNormals[(edgeMax-1)%3])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
+ // FIXME: this is the original version, but why (edgeMax-1)%3? IN that case, edgeNormal to edgeMax would never be tried
+ // if (contactPt.Dot(edgeNormals[ (edgeMax-1)%3])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
+ if (contactPt.Dot(edgeNormals[ edgeMax ])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
// contact with vertex no. edgeMax+1
else if(contactPt.Dot(edgeNormals[edgeMax=(edgeMax+1)%3])>inCircleR) contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
+ // contact with edge no. edgeMax
+ else noVertexContact=true;
normal=contactLine-contactPt;
+ #ifdef FACET_TOPO
+ if(noVertexContact && facet->edgeAdjIds[edgeMax]!=Body::ID_NONE){
+ // find angle between our normal and the facet's normal (still local coords)
+ Quaternionr q; q.Align(facet->nf,normal); Vector3r axis; Real angle; q.ToAxisAngle(axis,angle);
+ assert(angle>=0 && angle<=Mathr::PI);
+ if(edgeNormals[edgeMax].Dot(axis)<0) angle*=-1.;
+ bool negFace=normal.Dot(facet->nf)<0; // contact in on the negative facet's face
+ Real halfAngle=(negFace?-1.:1.)*facet->edgeAdjHalfAngle[edgeMax];
+ if(halfAngle<0 && angle>halfAngle) return false; // on concave boundary, and if in the other facet's sector, no contact
+ // otherwise the contact will be created
+ }
+ #endif
//TRVAR4(contactLine,contactPt,normal,normal.Length());
//TRVAR3(se31.orientation*contactLine,se31.position+se31.orientation*contactPt,se31.orientation*normal);
penetrationDepth=sphereRadius-normal.Normalize();
@@ -71,6 +100,7 @@
fs=shared_ptr<Dem3DofGeom_FacetSphere>(new Dem3DofGeom_FacetSphere());
c->interactionGeometry=fs;
fs->effR2=sphereRadius-penetrationDepth;
+ fs->refR1=-1; fs->refR2=sphereRadius;
fs->refLength=fs->effR2;
fs->cp1pt=contactPt; // facet-local intial contact point
fs->localFacetNormal=normal;
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.hpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -16,7 +16,7 @@
/******* API ********/
virtual Real displacementN(){ return (se32.position-contactPoint).Length()-refLength;}
virtual Vector3r displacementT(){ relocateContactPoints(); return contPtInTgPlane2()-contPtInTgPlane1(); }
- virtual Real slipToDisplacementTMax(Real displacementTMax){ LOG_FATAL("Not implemented yet."); throw; }
+ virtual Real slipToDisplacementTMax(Real displacementTMax);
/***** end API ******/
void setTgPlanePts(const Vector3r&, const Vector3r&);
@@ -26,13 +26,11 @@
Vector3r cp1pt;
//! orientation between +x and the reference contact point (on the sphere) in sphere-local coords
Quaternionr cp2rel;
- //! positions and orientations of both bodies; updated at every iteration
- Se3r se31, se32;
//! unit normal of the facet plane in facet-local coordinates
Vector3r localFacetNormal;
// effective radius of sphere
Real effR2;
- REGISTER_ATTRIBUTES(Dem3DofGeom,(cp1pt)(cp2rel)(se31)(se32)(localFacetNormal)(effR2) );
+ REGISTER_ATTRIBUTES(Dem3DofGeom,(cp1pt)(cp2rel)(localFacetNormal)(effR2) );
REGISTER_CLASS_AND_BASE(Dem3DofGeom_FacetSphere,Dem3DofGeom);
DECLARE_LOGGER;
friend class GLDraw_Dem3DofGeom_FacetSphere;
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -161,6 +161,7 @@
c->interactionGeometry=ss;
// constants
ss->refLength=dist;
+ ss->refR1=s1->radius; ss->refR2=s2->radius;
Real penetrationDepth=s1->radius+s2->radius-ss->refLength;
ss->effR1=s1->radius-.5*penetrationDepth; ss->effR2=s2->radius-.5*penetrationDepth;
// for bending only: ss->initRelOri12=se31.orientation.Conjugate()*se32.orientation;
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -13,8 +13,6 @@
void relocateContactPoints();
void relocateContactPoints(const Vector3r& tgPlanePt1, const Vector3r& tgPlanePt2);
public:
- //! Positions and orientations of both spheres; must be updated at every iteration by the geom functor
- Se3r se31, se32;
//! relative orientation of the contact point with regards to sphere-local +x axis (quasi-constant)
Quaternionr cp1rel, cp2rel;
//! shorthands
@@ -37,7 +35,7 @@
Real slipToDisplacementTMax(Real displacementTMax);
/********* end API ***********/
- REGISTER_ATTRIBUTES(Dem3DofGeom,(se31)(se32)(effR1)(effR2)(cp1rel)(cp2rel));
+ REGISTER_ATTRIBUTES(Dem3DofGeom,(effR1)(effR2)(cp1rel)(cp2rel));
REGISTER_CLASS_AND_BASE(Dem3DofGeom_SphereSphere,Dem3DofGeom);
friend class GLDraw_Dem3DofGeom_SphereSphere;
friend class ef2_Sphere_Sphere_Dem3DofGeom;
Added: trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.cpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -0,0 +1,3 @@
+#include"DemXDofGeom.hpp"
+YADE_PLUGIN("Dem3DofGeom");
+Real Dem3DofGeom::displacementN(){throw;}
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.hpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/DemXDofGeom.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -15,11 +15,16 @@
Vector3r contactPoint;
//! make strain go to -∞ for length going to zero
bool logCompression;
+ //! se3 of both bodies (needed to compute torque from the contact, strains etc). Must be updated at every step.
+ Se3r se31, se32;
+ //! reference radii of particles (for initial contact stiffness computation)
+ Real refR1, refR2;
// API that needs to be implemented in derived classes
- virtual Real displacementN(){throw;}
+ virtual Real displacementN();
virtual Vector3r displacementT(){throw;}
virtual Real slipToDisplacementTMax(Real displacementTMax){throw;}; // plasticity
+ // reference radii, for contact stiffness computation; set to negative for nonsense values
// end API
Real strainN(){
@@ -31,7 +36,7 @@
Real slipToStrainTMax(Real strainTMax){return slipToDisplacementTMax(strainTMax*refLength)/refLength;}
REGISTER_CLASS_AND_BASE(Dem3DofGeom,InteractionGeometry);
- REGISTER_ATTRIBUTES(InteractionGeometry,(refLength)(normal)(contactPoint));
+ REGISTER_ATTRIBUTES(InteractionGeometry,(refLength)(normal)(contactPoint)(se31)(se32)(refR1)(refR2));
};
REGISTER_SERIALIZABLE(Dem3DofGeom);
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/SpheresContactGeometry.hpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/SpheresContactGeometry.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/SpheresContactGeometry.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -49,7 +49,8 @@
// interaction "radii" and total length; this is _really_ constant throughout the interaction life
// d1 is really distance from the sphere1 center to the contact plane, it may not correspond to the sphere radius!
// therefore, d1+d2=d0 (distance at which the contact was created)
- Real d1, d2, d0;
+ // d0fixup is added to d0 when computing normal strain; it should fix problems with sphere-facet interactions never getting enough compressed
+ Real d1, d2, d0, d0fixup;
// initial relative orientation, used for bending and torsion computation
Quaternionr initRelOri12;
@@ -64,7 +65,7 @@
Vector3r contPt() const {return contactPoint; /*pos1+(d1/d0)*(pos2-pos1)*/}
Real displacementN() const {assert(hasShear); return (pos2-pos1).Length()-d0;}
- Real epsN() const {return displacementN()*(1./d0);}
+ Real epsN() const {return displacementN()*(1./(d0+d0fixup));}
Vector3r displacementT() { assert(hasShear);
// enabling automatic relocation decreases overall simulation speed by about 3%
// perhaps: bool largeStrains ... ?
@@ -76,11 +77,11 @@
return contPtInTgPlane2()-contPtInTgPlane1();
#endif
}
- Vector3r epsT() {return displacementT()*(1./d0);}
+ Vector3r epsT() {return displacementT()*(1./(d0+d0fixup));}
Real slipToDisplacementTMax(Real displacementTMax);
//! slip to epsTMax if current epsT is greater; return the relative slip magnitude
- Real slipToEpsTMax(Real epsTMax){ return (1/d0)*slipToDisplacementTMax(epsTMax*d0);}
+ Real slipToStrainTMax(Real epsTMax){ return (1/d0)*slipToDisplacementTMax(epsTMax*d0);}
void relocateContactPoints();
void relocateContactPoints(const Vector3r& tgPlanePt1, const Vector3r& tgPlanePt2);
@@ -90,7 +91,7 @@
Vector3r relRotVector() const;
- SpheresContactGeometry():contactPoint(Vector3r::ZERO),radius1(0),radius2(0),facetContactFace(0.),hasShear(false),pos1(Vector3r::ZERO),pos2(Vector3r::ZERO),ori1(Quaternionr::IDENTITY),ori2(Quaternionr::IDENTITY),cp1rel(Quaternionr::IDENTITY),cp2rel(Quaternionr::IDENTITY),d1(0),d2(0),d0(0),initRelOri12(Quaternionr::IDENTITY){createIndex();
+ SpheresContactGeometry():contactPoint(Vector3r::ZERO),radius1(0),radius2(0),facetContactFace(0.),hasShear(false),pos1(Vector3r::ZERO),pos2(Vector3r::ZERO),ori1(Quaternionr::IDENTITY),ori2(Quaternionr::IDENTITY),cp1rel(Quaternionr::IDENTITY),cp2rel(Quaternionr::IDENTITY),d1(0),d2(0),d0(0),d0fixup(0),initRelOri12(Quaternionr::IDENTITY){createIndex();
#ifdef SCG_SHEAR
shear=Vector3r::ZERO; prevNormal=Vector3r::ZERO /*initialized to proper value by geom functor*/;
#endif
@@ -120,6 +121,7 @@
(d1)
(d2)
(d0)
+ (d0fixup)
(initRelOri12));
REGISTER_CLASS_AND_BASE(SpheresContactGeometry,InteractionGeometry);
REGISTER_CLASS_INDEX(SpheresContactGeometry,InteractionGeometry);
Modified: trunk/pkg/dem/Engine/EngineUnit/InteractingFacet2InteractingSphere4SpheresContactGeometry.cpp
===================================================================
--- trunk/pkg/dem/Engine/EngineUnit/InteractingFacet2InteractingSphere4SpheresContactGeometry.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/Engine/EngineUnit/InteractingFacet2InteractingSphere4SpheresContactGeometry.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -95,7 +95,6 @@
if (bm<icr) // contact with facet's surface
{
- assert(contactFace!=0);
penetrationDepth = sphereRadius - L;
normal.Normalize();
}
@@ -145,6 +144,7 @@
if(c->isNew){
scm->d0=scm->radius1+scm->radius2-penetrationDepth;
scm->d1=scm->radius1-.5*penetrationDepth; scm->d2=scm->radius2-.5*penetrationDepth;
+ scm->d0fixup=-scm->radius1-.5*penetrationDepth;
// quasi-constants
scm->cp1rel.Align(Vector3r::UNIT_X,se31.orientation.Conjugate()*normal);
scm->cp2rel.Align(Vector3r::UNIT_X,se32.orientation.Conjugate()*(-normal));
Modified: trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.cpp
===================================================================
--- trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.cpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.cpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -40,7 +40,7 @@
abs(vi->pos[2]-vj->pos[2])<=tolerance &&
(vi->pos-vj->pos).SquaredLength()<=tolerance*tolerance){
// OK, these two vertices touch
- LOG_TRACE("Vertices "<<vi->id<<"/"<<vi->vertexNo<<" and "<<vj->id<<"/"<<vj->vertexNo<<" close enough.");
+ // LOG_TRACE("Vertices "<<vi->id<<"/"<<vi->vertexNo<<" and "<<vj->id<<"/"<<vj->vertexNo<<" close enough.");
// add vertex to the nextIndetical of the one that has lower index; the one that is added will have isLowestIndex=false
if(vi->index<vj->index){ vi->nextIdentical.push_back(vj); vj->isLowestIndex=false; }
else{ vj->nextIdentical.push_back(vi); vi->isLowestIndex=false; }
@@ -81,11 +81,18 @@
}
topo1.push_back(t);
}
+ std::sort(topo1.begin(),topo1.end(),FacetTopology::MinVertexComparator());
size_t nTopo=topo1.size();
for(size_t i=0; i<nTopo; i++){
size_t j=i;
+ const shared_ptr<FacetTopology>& ti(topo1[i]);
+ long tiMaxVertex=ti->maxVertex();
while(++j<nTopo){
- const shared_ptr<FacetTopology>& ti(topo1[i]), &tj(topo1[j]);
+ const shared_ptr<FacetTopology> &tj(topo1[j]);
+ /* since facets are sorted by their min vertex id,
+ we know that it is safe to skip all the rest
+ as soon as max vertex of ti one is smaller than min vertex of tj, as i<=j */
+ if(tj->minVertex()>tiMaxVertex) break;
vector<size_t> vvv; // array of common vertices
for(size_t k=0; k<3; k++){
if (ti->vertices[k]==tj->vertices[0]) vvv.push_back(ti->vertices[k]);
@@ -93,9 +100,9 @@
else if(ti->vertices[k]==tj->vertices[2]) vvv.push_back(ti->vertices[k]);
}
if(vvv.size()<2) continue;
- assert(vvv.size()!=3); // same coords? nonsense
- assert(vvv.size()==2);
- vector<int> edge(2,0);
+ assert(vvv.size()!=3 /* same coords? nonsense*/ ); assert(vvv.size()==2);
+ // from here, we know ti and tj are adjacent
+ vector<int> edge(2,0); int &ei(edge[0]),&ej(edge[1]);
// identify what edge are we at, for both facets
for(int k=0; k<2; k++){
for(edge[k]=0; edge[k]<3; edge[k]++){
@@ -109,10 +116,25 @@
}
}
// add adjacency information to the facet itself
- YADE_PTR_CAST<InteractingFacet>((*rb->bodies)[ti->id]->interactingGeometry)->edgeAdjIds[edge[0]]=tj->id;
- YADE_PTR_CAST<InteractingFacet>((*rb->bodies)[tj->id]->interactingGeometry)->edgeAdjIds[edge[1]]=ti->id;
+ InteractingFacet *f1=YADE_CAST<InteractingFacet*>((*rb->bodies)[ti->id]->interactingGeometry.get()), *f2=YADE_CAST<InteractingFacet*>((*rb->bodies)[tj->id]->interactingGeometry.get());
+ f1->edgeAdjIds[ei]=ti->id; f2->edgeAdjIds[ej]=tj->id;
+ // normals are in the sense of vertex rotation (right-hand rule); therefore, if vertices of the adjacent edge are opposite on each facet, normals are in the same direction
+ bool invNormals=(ti->vertices[ei]==tj->vertices[ej]);
+ assert(
+ ( invNormals && (ti->vertices[ ei ]==tj->vertices[ej]) && (ti->vertices[(ei+1)%3]==tj->vertices[(ej+1)%3]) ) ||
+ (!invNormals && (ti->vertices[(ei+1)%3]==tj->vertices[ej]) && (ti->vertices[ ei ]==tj->vertices[(ej+1)%3]) ));
+ // angle between normals
+ PhysicalParameters *pp1=(*rb->bodies)[ti->id]->physicalParameters.get(), *pp2=(*rb->bodies)[tj->id]->physicalParameters.get();
+ Vector3r n1g=pp1->se3.orientation*f1->nf, n2g=pp2->se3.orientation*f2->nf;
+ //TRVAR2(n1g,n2g);
+ Vector3r contEdge1g=pp1->se3.orientation*(f1->vertices[(ei+1)%3]-f1->vertices[ei]); // vector of the edge of contact in global coords
+ Quaternionr q12; q12.Align(n1g,(invNormals?-1.:1.)*n2g); Real halfAngle; Vector3r axis; q12.ToAxisAngle(axis,halfAngle); halfAngle*=.5;
+ assert(halfAngle>=0 && halfAngle<=Mathr::HALF_PI);
+ if(axis.Dot(contEdge1g)<0 /* convex contact from the side of +n1 */ ) halfAngle*=-1.;
+ f1->edgeAdjHalfAngle[ei]=halfAngle;
+ f2->edgeAdjHalfAngle[ej]=(invNormals ? -halfAngle : halfAngle);
commonEdgesFound++;
- LOG_TRACE("Added adjacency information for #"<<ti->id<<"+#"<<tj->id<<" (common edges "<<edge[0]<<"+"<<edge[1]<<")");
+ LOG_TRACE("Found adjacent #"<<ti->id<<"+#"<<tj->id<<"; common edges "<<ei<<"+"<<ej<<", normals "<<(invNormals?"inversed":"congruent")<<", halfAngle "<<halfAngle<<")");
}
}
}
Modified: trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.hpp
===================================================================
--- trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.hpp 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/Engine/StandAloneEngine/FacetTopologyAnalyzer.hpp 2009-04-22 06:57:45 UTC (rev 1757)
@@ -39,6 +39,11 @@
long vertices[3];
//! facet id, for back reference
body_id_t id;
+ long minVertex(){return min(vertices[0],min(vertices[1],vertices[2]));}
+ long maxVertex(){return max(vertices[0],max(vertices[1],vertices[2]));}
+ struct MinVertexComparator{
+ bool operator()(const shared_ptr<FacetTopology>& t1, const shared_ptr<FacetTopology>& t2){ return t1->minVertex()<t2->minVertex();}
+ };
};
public:
//! Axis along which to do the initial vertex sort
Modified: trunk/pkg/dem/SConscript
===================================================================
--- trunk/pkg/dem/SConscript 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/pkg/dem/SConscript 2009-04-22 06:57:45 UTC (rev 1757)
@@ -26,10 +26,11 @@
])
env.Install('$PREFIX/lib/yade$SUFFIX/pkg-dem',[
+
+ env.SharedLibrary('DemXDofGeom',['DataClass/InteractionGeometry/DemXDofGeom.cpp']),
+ env.SharedLibrary('Dem3DofGeom_SphereSphere',['DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp'],LIBS=env['LIBS']+['RigidBodyParameters','InteractingSphere','yade-opengl','DemXDofGeom']),
+ env.SharedLibrary('Dem3DofGeom_FacetSphere',['DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp'],LIBS=env['LIBS']+['RigidBodyParameters','InteractingSphere','InteractingFacet','yade-opengl','Dem3DofGeom_SphereSphere','DemXDofGeom']),
- env.SharedLibrary('Dem3DofGeom_SphereSphere',['DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp'],LIBS=env['LIBS']+['RigidBodyParameters','InteractingSphere','yade-opengl']),
- env.SharedLibrary('Dem3DofGeom_FacetSphere',['DataClass/InteractionGeometry/Dem3DofGeom_FacetSphere.cpp'],LIBS=env['LIBS']+['RigidBodyParameters','InteractingSphere','InteractingFacet','yade-opengl','Dem3DofGeom_SphereSphere']),
-
env.SharedLibrary('FacetTopologyAnalyzer',['Engine/StandAloneEngine/FacetTopologyAnalyzer.cpp'],LIBS=env['LIBS']+['InteractingFacet']),
Modified: trunk/scripts/test/facet-topo.py
===================================================================
--- trunk/scripts/test/facet-topo.py 2009-04-17 15:11:23 UTC (rev 1756)
+++ trunk/scripts/test/facet-topo.py 2009-04-22 06:57:45 UTC (rev 1757)
@@ -1,5 +1,5 @@
import yade.log
-#yade.log.setLevel('FacetTopologyAnalyzer',yade.log.TRACE)
+yade.log.setLevel('FacetTopologyAnalyzer',yade.log.TRACE)
# Note: FacetTopologyAnalyzer is normally run as an initializer;
# it is only for testing sake that it is in O.engines here.
@@ -24,6 +24,17 @@
assert(topo['commonEdgesFound']==1)
if 1:
O.bodies.clear()
+ O.bodies.append([
+ utils.facet([(0,0,0),(1,0,0),(0,1,0)]),
+ utils.facet([(1,1,1),(1,0,0),(0,1,0)]),
+ ])
+ O.step()
+ assert(O.bodies[0].phys['edgeAdjIds'][1]==1 and O.bodies[1].phys['edgeAdjIds'][0]==1)
+ assert(topo['commonEdgesFound']==1)
+ assert(abs(O.bodies[0].mold['edgeAdjHalfAngle'][1]-(-5*atan(2/sqrt(2))))<1e-6)
+
+if 1:
+ O.bodies.clear()
r=.5 # radius of the sphere
nPoly=12; # try 128, it is still quite fast
def sphPt(i,j):