yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01631
[svn] r1932 - in trunk: core extra gui/qt3 lib/serialization pkg/dem/DataClass/InteractionGeometry scripts/test
Author: eudoxos
Date: 2009-08-09 19:17:53 +0200 (Sun, 09 Aug 2009)
New Revision: 1932
Modified:
trunk/core/Interaction.cpp
trunk/core/Interaction.hpp
trunk/extra/PeriodicInsertionSortCollider.cpp
trunk/extra/PeriodicInsertionSortCollider.hpp
trunk/gui/qt3/SimulationController.cpp
trunk/lib/serialization/Archive.tpp
trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp
trunk/scripts/test/periodic-grow.py
Log:
1. Working periodic collider, yay!! scripts/test/periodic-grow.py shows that
2. A few changes related to that.
Modified: trunk/core/Interaction.cpp
===================================================================
--- trunk/core/Interaction.cpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/core/Interaction.cpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -12,8 +12,8 @@
#include<yade/core/MetaBody.hpp>
-Interaction::Interaction(): id1(0), id2(0){ init(); }
-Interaction::Interaction(body_id_t newId1,body_id_t newId2): id1(newId1), id2(newId2){ reset(); }
+Interaction::Interaction(): id1(0), id2(0), cellDist(Vector3<int>(0,0,0)) { init(); }
+Interaction::Interaction(body_id_t newId1,body_id_t newId2): id1(newId1), id2(newId2), cellDist(Vector3<int>(0,0,0)){ reset(); }
bool Interaction::isFresh(MetaBody* rb){ return iterMadeReal==rb->currentIteration;}
@@ -21,7 +21,6 @@
isNeighbor = true;//NOTE : TriangulationCollider needs that
iterMadeReal=-1;
functorCache.geomExists=true;
- cellDist=Vector3<int>(0,0,0);
//functorCache.geom=shared_ptr<InteractionGeometryEngineUnit>(); functorCache.phys=shared_ptr<InteractionPhysicsEngineUnit>(); functorCache.constLaw=shared_ptr<ConstitutiveLaw>();
}
Modified: trunk/core/Interaction.hpp
===================================================================
--- trunk/core/Interaction.hpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/core/Interaction.hpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -38,8 +38,14 @@
//! NOTE : TriangulationCollider needs this (nothing else)
bool isNeighbor;
- //! relative distance between bodies, given in (MetaBody::cellMax-MetaBody::cellMin) units
- //! Position of id1 must be incremented by that distance so that there is spatial interaction
+ /*! relative distance between bodies, given in (MetaBody::cellMax-MetaBody::cellMin) units
+ Position of id1 must be incremented by that distance so that there is spatial interaction
+
+ NOTE (tricky): cellDist must survive Interaction::reset(), it is only initialized in ctor
+ Interaction that was cancelled by the constitutive law, was reset() and became only potential
+ must have the priod information if the geometric functor again makes it real. Good to know after
+ few days of debugging that :-)
+ */
Vector3<int> cellDist;
shared_ptr<InteractionGeometry> interactionGeometry;
Modified: trunk/extra/PeriodicInsertionSortCollider.cpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -12,48 +12,77 @@
#include<algorithm>
#include<vector>
#include<boost/static_assert.hpp>
+#include<stdexcept>
using namespace std;
YADE_PLUGIN((PeriodicInsertionSortCollider))
CREATE_LOGGER(PeriodicInsertionSortCollider);
+// return floating value wrapped between x0 and x1 and saving period number to period
Real PeriodicInsertionSortCollider::cellWrap(const Real x, const Real x0, const Real x1, int& period){
Real xNorm=(x-x0)/(x1-x0);
- period=(int)floor(xNorm); // FIXME: some people say this is very slow
+ period=(int)floor(xNorm); // some people say this is very slow; probably optimized by gcc, however (google suggests)
return x0+(xNorm-period)*(x1-x0);
}
+// return coordinate wrapped to x0…x1, relative to x0; don't care about period
Real PeriodicInsertionSortCollider::cellWrapRel(const Real x, const Real x0, const Real x1){
Real xNorm=(x-x0)/(x1-x0);
return (xNorm-floor(xNorm))*(x1-x0);
}
-// return true if bodies bb overlap in all 3 dimensions
+/* Performance hint
+ ================
+
+ Since this function is called (most the time) from insertionSort,
+ we actually already know what is the overlap status in that one dimension, including
+ periodicity information; both values could be passed down as a parameters, avoiding 1 of 3 loops here.
+ We do some floats math here, so the speedup could noticeable; doesn't concertn the non-periodic variant,
+ where it is only plain comparisons taking place.
+
+ In the same way, handleBoundInversion is passed only id1 and id2, but again insertionSort already knows in which sense
+ the inversion happens; if the boundaries get apart (min getting up over max), it wouldn't have to check for overlap
+ at all, for instance.
+*/
+//! return true if bodies bb overlap in all 3 dimensions
bool PeriodicInsertionSortCollider::spatialOverlap(body_id_t id1, body_id_t id2,MetaBody* rb, Vector3<int>& periods) const {
assert(id1!=id2); // programming error, or weird bodies (too large?)
for(int axis=0; axis<3; axis++){
Real dim=rb->cellMax[axis]-rb->cellMin[axis];
// too big bodies in interaction
assert(maxima[3*id1+axis]-minima[3*id1+axis]<.99*dim); assert(maxima[3*id2+axis]-minima[3*id2+axis]<.99*dim);
- // different way: find body of which when taken as period start will make the gap smaller
+ // find body of which when taken as period start will make the gap smaller
Real m1=minima[3*id1+axis],m2=minima[3*id2+axis];
Real wMn=(cellWrapRel(m1,m2,m2+dim)<cellWrapRel(m2,m1,m1+dim)) ? m2 : m1;
- //TRVAR3(id1,id2,axis);
- //TRVAR4(minima[3*id1+axis],maxima[3*id1+axis],minima[3*id2+axis],maxima[3*id2+axis]);
- //TRVAR2(cellWrapRel(m1,m2,m2+dim),cellWrapRel(m2,m1,m1+dim));
- //TRVAR3(m1,m2,wMn);
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)){
+ TRVAR3(id1,id2,axis);
+ TRVAR4(minima[3*id1+axis],maxima[3*id1+axis],minima[3*id2+axis],maxima[3*id2+axis]);
+ TRVAR2(cellWrapRel(m1,m2,m2+dim),cellWrapRel(m2,m1,m1+dim));
+ TRVAR3(m1,m2,wMn);
+ }
+ #endif
int pmn1,pmx1,pmn2,pmx2;
Real mn1=cellWrap(minima[3*id1+axis],wMn,wMn+dim,pmn1), mx1=cellWrap(maxima[3*id1+axis],wMn,wMn+dim,pmx1);
Real mn2=cellWrap(minima[3*id2+axis],wMn,wMn+dim,pmn2), mx2=cellWrap(maxima[3*id2+axis],wMn,wMn+dim,pmx2);
- //TRVAR4(mn1,mx1,mn2,mx2);
- //TRVAR4(pmn1,pmx1,pmn2,pmx2);
- assert(pmn1==pmx1); assert(pmn2==pmx2);
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)){
+ TRVAR4(mn1,mx1,mn2,mx2);
+ TRVAR4(pmn1,pmx1,pmn2,pmx2);
+ }
+ #endif
+ if((pmn1!=pmx1) || (pmn2!=pmx2)){
+ LOG_FATAL("Body #"<<(pmn1!=pmx1?id1:id2)<<" spans over half of the cell size!");
+ throw runtime_error(__FILE__ ": Body larger than half of the cell size encountered.");
+ }
periods[axis]=(int)(pmn1-pmn2);
if(!(mn1<=mx2 && mx1 >= mn2)) return false;
}
- //LOG_TRACE("Returning true for #"<<id1<<"+#"<<id2<<", periods "<<periods);
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)) LOG_INFO("Overlap #"<<id1<<"+#"<<id2<<", periods "<<periods);
+ #endif
return true;
}
@@ -65,15 +94,24 @@
// existing interaction?
const shared_ptr<Interaction>& I=interactions->find(id1,id2);
bool hasInter=(bool)I;
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)) LOG_INFO("Inversion #"<<id1<<"+#"<<id2<<", overlap=="<<overlap<<", hasInter=="<<hasInter);
+ #endif
// interaction doesn't exist and shouldn't, or it exists and should
if(!overlap && !hasInter) return;
if(overlap && hasInter){ return; }
// create interaction if not yet existing
if(overlap && !hasInter){ // second condition only for readability
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)) LOG_INFO("Attemtping collision of #"<<id1<<"+#"<<id2);
+ #endif
if(!Collider::mayCollide(Body::byId(id1,rb).get(),Body::byId(id2,rb).get())) return;
// LOG_TRACE("Creating new interaction #"<<id1<<"+#"<<id2);
shared_ptr<Interaction> newI=shared_ptr<Interaction>(new Interaction(id1,id2));
newI->cellDist=periods;
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)) LOG_INFO("Created intr #"<<id1<<"+#"<<id2<<", periods="<<periods);
+ #endif
interactions->insert(newI);
return;
}
@@ -81,6 +119,50 @@
assert(false); // unreachable
}
+void PeriodicInsertionSortCollider::insertionSort(VecBounds& v, InteractionContainer* interactions, MetaBody*rb, bool doCollide){
+ long &loIdx=v.loIdx; const long &size=v.size;
+ for(long _i=0; _i<size; _i++){
+ const long i=v.norm(_i);
+ const long i_1=v.norm(i-1);
+ //switch period of (i) if the coord is below the lower edge cooridnate-wise and just above the split
+ if(i==loIdx && v[i].coord<v.cellMin){ v[i].period-=1; v[i].coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
+ // coordinate of v[i] used to check inversions
+ // if crossing the split, adjust by cellDim;
+ // if we get below the loIdx however, the v[i].coord will have been adjusted already, no need to do that here
+ const Real iCmpCoord=v[i].coord+(i==loIdx ? v.cellDim : 0);
+ // no inversion
+ if(v[i_1].coord<=iCmpCoord) continue;
+ // vi is the copy that will travel down the list, while other elts go up
+ // if will be placed in the list only at the end, to avoid extra copying
+ int j=i_1; Bound vi=v[i]; const bool viHasBB=vi.flags.hasBB;
+ while(v[j].coord>vi.coord + /* wrap for elt just below split */ (v.norm(j+1)==loIdx ? v.cellDim : 0)){
+ long j1=v.norm(j+1);
+ if (v[j].coord>v.cellMax+v.cellDim){
+ // this condition is not strictly necessary, but the loop of insertionSort would have to run more times.
+ // Since size of particle is required to be < .5*cellDim, this would mean simulation explosion anyway
+ LOG_FATAL("Body #"<<v[j].id<<" going faster than 1 cell in one step? Not handled.");
+ throw runtime_error(__FILE__ ": body mmoving too fast (skipped 1 cell).");
+ }
+ Bound& vNew(v[j1]); // elt at j+1 being overwritten by the one at j and adjusted
+ vNew=v[j];
+ // inversions close the the split need special care
+ if(j==loIdx && vi.coord<v.cellMin) { vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
+ else if(j1==loIdx) { vNew.period+=1; vNew.coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
+ if(doCollide && viHasBB && v[j].flags.hasBB){
+ if(vi.id==vNew.id){ // BUG!!
+ LOG_FATAL("Inversion of body's #"<<vi.id<<" boundary with its other boundary.");
+ throw runtime_error(__FILE__ "Body's boundary metting its opposite boundary.");
+ }
+ handleBoundInversion(vi.id,vNew.id,interactions,rb);
+ }
+ j=v.norm(j-1);
+ }
+ v[v.norm(j+1)]=vi;
+ }
+}
+
+// old code, can be removed later
+#if 0
void PeriodicInsertionSortCollider::insertionSort(VecBounds& v, InteractionContainer* interactions, MetaBody* rb, bool doCollide){
// It seems that due to wrapping, it is not predetermined, how many times should we traverse the container
// We therefore add one blank traversal at the end that finds no inversions; then stop
@@ -89,9 +171,9 @@
hadInversion=false;
long cnt=0; //loIdx
for(long i=v.norm(loIdx-1); cnt++<size; i=v.norm(i-1)){
- long i_1=v.norm(i-1), loIdx_1=v.norm(loIdx-1);
+ long i_1=v.norm(i-1);
// fast test, if the first pair is inverted
- if(v[i].coord<v[i_1].coord-(i_1==loIdx_1 ? v.cellDim : 0) ){
+ if(v[i].coord<v[i_1].coord-(i_1==v.norm(loIdx-1) ? v.cellDim : 0) ){
//v.dump(cerr);
if(i==loIdx && v[i].coord<v.cellMin){ v[i].period-=1; v[i].coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
hadInversion=true; Bound vi=v[i]; int j; const bool viBB=vi.flags.hasBB;
@@ -104,7 +186,21 @@
//if(v[j1].coord>v.cellMax && j2==loIdx){ v[j1].period+=1; v[j1].coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
if(j1==loIdx) { assert(v[j1].coord>=v.cellMax); v[j1].period+=1; v[j1].coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
else if (vi.coord<v.cellMin && j==loIdx){ vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
- if(doCollide && viBB && v[j].flags.hasBB) handleBoundInversion(vi.id,v[j].id,interactions,rb);
+ if(doCollide && viBB && v[j].flags.hasBB){
+ if(vi.id==v[j].id){ // BUG!!
+ ofstream of("/tmp/dump");
+ Omega::instance().saveSimulation("/tmp/dump.xml");
+ v.dump(of);
+ LOG_FATAL("Inversion of a body's boundary with itself, id="<<vi.id);
+ body_id_t id=vi.id;
+ TRVAR4(vi.coord,vi.id,vi.period,vi.flags.isMin);
+ TRVAR4(v[j].coord,v[j].id,v[j].period,v[j].flags.isMin);
+ TRVAR2(*(Vector3r*)(&minima[3*id]),*(Vector3r*)(&maxima[3*id]));
+ TRVAR3(i,j,v.loIdx);
+ abort();
+ }
+ handleBoundInversion(vi.id,v[j].id,interactions,rb);
+ }
//v.dump(cerr);
}
v[v.norm(j+1)]=vi;
@@ -113,12 +209,13 @@
}
}
}
+#endif
void PeriodicInsertionSortCollider::VecBounds::update(MetaBody* rb, int axis){
assert(axis>=0 && axis<3);
if(!rb->isPeriodic){
// maybe just set cell from -inf to +inf and go ahead?
- LOG_FATAL("MetaBody::isPeriodic is false, unable to continue!"); throw;
+ LOG_FATAL("MetaBody::isPeriodic is false, unable to continue!"); throw runtime_error("Non-periodic MetaBody for periodic collider.");
}
cellMin=rb->cellMin[axis]; cellMax=rb->cellMax[axis]; cellDim=cellMax-cellMin;
size=vec.size();
@@ -151,7 +248,7 @@
}
if(minima.size()!=3*(size_t)nBodies){ minima.resize(3*nBodies); maxima.resize(3*nBodies); }
assert(XX.vec.size()==2*rb->bodies->size());
- //PERI: copy periodiciy information
+ //PERI: copy periodicity information
XX.update(rb,0); YY.update(rb,1); ZZ.update(rb,2);
// copy bounds along given axis into our arrays
@@ -177,17 +274,11 @@
memcpy(&minima[3*idXX],&bvXX->min,3*sizeof(Real)); memcpy(&maxima[3*idXX],&bvXX->max,3*sizeof(Real)); // ⇐ faster than 6 assignments
}
else{ const Vector3r& pos=Body::byId(idXX,rb)->physicalParameters->se3.position; memcpy(&minima[3*idXX],pos,3*sizeof(Real)); memcpy(&maxima[3*idXX],pos,3*sizeof(Real)); }
- // PERI: add periods, but such that both minimum and maximum is within the cell!
- //Vector3r period(XX[i].period*XX.cellDim,YY[i].period*YY.cellDim,ZZ[i].period*ZZ.cellDim);
- //*(Vector3r*)(&minima[3*idXX])+=period; *(Vector3r*)(&maxima[3*idXX])+=period; //ugh
}
}
// process interactions that the constitutive law asked to be erased
interactions->erasePending(*this,rb);
- //LOG_TRACE("Step "<<Omega::instance().getCurrentIteration());
- //ZZ.dump(cerr);
- // XX.dump(cerr); YY.dump(cerr); ZZ.dump(cerr);
// sort
if(!doInitSort){
@@ -223,7 +314,8 @@
*/
// TRVAR3(i,iid,V[i].coord);
// go up until we meet the upper bound
- for(size_t j=i+1; /* handle case 2. of swapped min/max */ j<2*(size_t)nBodies && V[j].id!=iid; j++){
+ size_t cnt=0;
+ for(size_t j=V.norm(i+1); V[j].id!=iid; j=V.norm(j+1)){
const body_id_t& jid=V[j].id;
/// Not sure why this doesn't work. If this condition is commented out, we have exact same interactions as from SpatialQuickSort. Otherwise some interactions are missing!
// skip bodies with smaller (arbitrary, could be greater as well) id, since they will detect us when their turn comes
@@ -236,6 +328,11 @@
// that means that the upper bound is before the upper one; that can only happen if they
// are equal and the unstable std::sort has swapped them. In that case, we need to go reverse
// from V[i] until we meet the upper bound and swap the isMin flag
+
+ // PERI: this can happen if each boundary wraps to different period. That is OK.
+ // PERI: this should however be somehow distinguished from the case that they are in the same period...
+ // PERI: perhaps check that when periods are assigned and add some hair distance to the maximum...?
+ #if 0
if(j==2*(size_t)nBodies-1){ /* handle case 1. of swapped min/max */
size_t k=i-1;
while(V[k].id!=iid && k>0) k--;
@@ -245,6 +342,8 @@
LOG_DEBUG("Swapping coincident min/max of #"<<iid<<" at positions "<<k<<" and "<<i<<" (coords: "<<V[k].coord<<" and "<<V[i].coord<<")");
break; // would happen anyways
}
+ #endif
+ if(cnt++>2*(size_t)nBodies){ LOG_FATAL("Uninterrupted loop in the initial sort?"); throw std::logic_error("loop??"); }
}
}
}
Modified: trunk/extra/PeriodicInsertionSortCollider.hpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -17,9 +17,9 @@
Architecture
============
-Bounding boxes carry information about period in which they are. Their container (VecBounds)
-holds position of where the space wraps. The sorting algorithm is changed in such way that
-periods are changed when body crosses cell boundary.
+Values from bounding boxes are added information about period in which they are.
+Their container (VecBounds) holds position of where the space wraps.
+The sorting algorithm is changed in such way that periods are changed when body crosses cell boundary.
Interaction::cellDist holds information about relative cell coordinates of the 2nd body
relative to the 1st one. Dispatchers (InteractionGeometryMetaEngine and InteractionDispatchers)
@@ -27,8 +27,8 @@
Since properly behaving InteractionGeometryEngineUnit's and ConstitutiveLaw's do not take positions
directly from Body::physicalParameters, the interaction is computed with the periodic positions.
-Positions of bodies (in the sense of Body::physicalParameters) are not wrapped to the periodic cell,
-they can be anywhere (but not "too far" in the sense of int overflow).
+Positions of bodies (in the sense of Body::physicalParameters) and their natural bboxes are not wrapped
+to the periodic cell, they can be anywhere (but not "too far" in the sense of int overflow).
Since Interaction::cellDists holds cell coordinates, it is possible to change the cell boundaries
at runtime. This should make it easy to implement some stress control on the top.
@@ -40,6 +40,8 @@
OpenGLRenderingEngine renders GeometricalModel at all periodic positions that touch the
periodic cell (i.e. BoundingVolume crosses its boundary).
+It seems to affect body selection somehow, but that is perhaps not related at all.
+
Periodicity control
===================
c++:
@@ -50,28 +52,29 @@
Requirements
============
-* No body can have AABB larger than about .499*cellSize. This is currently not checked, only asserted.
-* Constitutive law must not get body positions from Body::physicalParameters.
+* No body can have AABB larger than about .499*cellSize. Exception is thrown if that is false.
+* Constitutive law must not get body positions from Body::physicalParameters directly.
If it does, it uses Interaction::cellDist to compute periodic position.
Dem3Dof family of Ig2 functors and Law2_* engines are known to behave well.
-* No body can get further away than MAXINT periods. It will do horrible things if there is overflow.
+* No body can get further away than MAXINT periods. It will do horrible things if there is overflow. Not checked at the moment.
+* Body cannot move over distance > cellSize in one step. Since body size is limited as well, that would mean simulation explosion.
+ Exception is thrown if the movement is upwards. If downwards, it is not handled at all.
Possible performance improvements & bugs
========================================
-This collider was not at all tuned to give decent performance (yet?)
-* We don't enforce that bounding boxes are inside the cell; that means that every
- spatialOverlap call has to wrap values, and that is probably quite slow.
* PeriodicInsertionSortCollider::{cellWrap,cellWrapRel} OpenGLRenderingEngine::{wrapCell,wrapCellPt} Shop::PeriodicWrap
are all very similar functions. They should be put into separate header and included from all those places.
-* The aforementioned functions might not be the fastest implementations. In particular, I heard that (int) is
- rather low-performance for making conversion of floating-point to integer.
+
* Until this code is integrated with plain InsertionSortCollider, it will not support striding via VelocityBins
Those 2 features are orthogonal, the integration shouldn't be diffucult.
-
*/
+// #define to turn on some tracing information
+// all code under this can be probably removed at some point, when the collider will have been tested thoroughly
+// #define PISC_DEBUG
+
class PeriodicInsertionSortCollider: public Collider{
//! struct for storing bounds of bodies
struct Bound{
@@ -113,13 +116,20 @@
bool spatialOverlap(body_id_t,body_id_t, MetaBody*, Vector3<int>&) const;
static Real cellWrap(const Real, const Real, const Real, int&);
static Real cellWrapRel(const Real, const Real, const Real);
+ #ifdef PISC_DEBUG
+ bool watchIds(body_id_t id1, body_id_t id2) const { body_id_t i1=2,i2=14; return ((id1==i1)&&(id2==i2))||((id1==i2)&&(id2==i1)); }
+ #endif
public:
//! axis for the initial sort
int sortAxis;
//! Predicate called from loop within InteractionContainer::erasePending
- bool shouldBeErased(body_id_t id1, body_id_t id2, MetaBody* rb) const { Vector3<int> foo; return !spatialOverlap(id1,id2,rb,foo); }
+ bool shouldBeErased(body_id_t id1, body_id_t id2, MetaBody* rb) const { Vector3<int> foo;
+ #ifdef PISC_DEBUG
+ if(watchIds(id1,id2)) LOG_INFO("Requesting erase of #"<<id1<<"+#"<<id2<<", result: "<<!spatialOverlap(id1,id2,rb,foo));
+ #endif
+ return !spatialOverlap(id1,id2,rb,foo); }
PeriodicInsertionSortCollider(): sortAxis(0) { }
virtual void action(MetaBody*);
Modified: trunk/gui/qt3/SimulationController.cpp
===================================================================
--- trunk/gui/qt3/SimulationController.cpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/gui/qt3/SimulationController.cpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -292,7 +292,7 @@
void SimulationController::timerEvent( QTimerEvent* )
{
doUpdate(); /* update the controller, like iteration number etc */
- if(hasSimulation && (Omega::instance().isRunning() || syncRunning || lastRenderedIteration!=Omega::instance().getCurrentIteration()))
+ if(hasSimulation) // && (Omega::instance().isRunning() || syncRunning || lastRenderedIteration!=Omega::instance().getCurrentIteration()))
{
/* update GLViews */
YadeQtMainWindow::self->redrawAll(true);
Modified: trunk/lib/serialization/Archive.tpp
===================================================================
--- trunk/lib/serialization/Archive.tpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/lib/serialization/Archive.tpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -48,13 +48,17 @@
typeid(Type)==typeid(Vector2f) ||
typeid(Type)==typeid(Vector2d) ||
typeid(Type)==typeid(Vector2<long double>) ||
- typeid(Type)==typeid(Vector2<signed int>) ||
+ typeid(Type)==typeid(Vector2<signed int>) ||
typeid(Type)==typeid(Vector2<unsigned int>) ||
typeid(Type)==typeid(Vector2<signed long>) ||
typeid(Type)==typeid(Vector2<unsigned long>) ||
typeid(Type)==typeid(Vector3f) ||
typeid(Type)==typeid(Vector3d) ||
typeid(Type)==typeid(Vector3<long double>) ||
+ typeid(Type)==typeid(Vector3<signed int>) ||
+ typeid(Type)==typeid(Vector3<unsigned int>) ||
+ typeid(Type)==typeid(Vector3<signed long>) ||
+ typeid(Type)==typeid(Vector3<unsigned long>) ||
typeid(Type)==typeid(Vector4f) ||
typeid(Type)==typeid(Vector4d) ||
typeid(Type)==typeid(Vector4<long double>) ||
Modified: trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp
===================================================================
--- trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp 2009-08-09 17:17:53 UTC (rev 1932)
@@ -153,7 +153,9 @@
InteractingSphere *s1=static_cast<InteractingSphere*>(cm1.get()), *s2=static_cast<InteractingSphere*>(cm2.get());
Vector3r normal=se32.position-se31.position;
Real penetrationDepthSq=pow(distanceFactor*(s1->radius+s2->radius),2)-normal.SquaredLength();
- if (penetrationDepthSq<0 && !c->isReal()) return false;
+ if (penetrationDepthSq<0 && !c->isReal()){
+ return false;
+ }
Real dist=normal.Normalize(); /* Normalize() works in-place and returns length before normalization; from here, normal is unit vector */
shared_ptr<Dem3DofGeom_SphereSphere> ss;
Modified: trunk/scripts/test/periodic-grow.py
===================================================================
--- trunk/scripts/test/periodic-grow.py 2009-08-07 19:11:33 UTC (rev 1931)
+++ trunk/scripts/test/periodic-grow.py 2009-08-09 17:17:53 UTC (rev 1932)
@@ -1,13 +1,12 @@
-"""Script that either grows spheres inside the cell or shrinks
-the cell progressively. It prints the total volume force once in a while.
-This script also shows that the collider misses some interactions as spheres
-are getting one over another. That is not acceptable, of course. """
+"""Script that shrinks the periodic cell progressively.
+It prints strain and average stress (computed from total volume force)
+once in a while."""
from yade import log,timing
-
+log.setLevel("PeriodicInsertionSortCollider",log.TRACE)
O.engines=[
BexResetter(),
BoundingVolumeMetaEngine([InteractingSphere2AABB(),MetaInteractingGeometry2AABB()]),
- PeriodicInsertionSortCollider(label='collider'),
+ PeriodicInsertionSortCollider(), # this is important, obviously
InteractionDispatchers(
[ef2_Sphere_Sphere_Dem3DofGeom()],
[SimpleElasticRelationships()],
@@ -16,32 +15,25 @@
NewtonsDampedLaw(damping=.6)
]
import random
-O.bodies.append(utils.sphere((0,0,0),.5,dynamic=False,density=1000)) # stable point
-for i in xrange(150):
- O.bodies.append(utils.sphere(Vector3(10*random.random(),10*random.random(),10*random.random()),.2+.2*random.random(),density=1000))
-O.periodicCell=((-5,-5,0),(5,5,10))
-O.dt=.8*utils.PWaveTimeStep()
+for i in xrange(250):
+ O.bodies.append(utils.sphere(Vector3(10*random.random(),10*random.random(),10*random.random()),.5+random.random(),density=1000))
+cubeSize=20
+# absolute positioning of the cell is not important
+O.periodicCell=((-.5*cubeSize,-.5*cubeSize,0),(.5*cubeSize,.5*cubeSize,cubeSize))
+O.dt=utils.PWaveTimeStep()
O.saveTmp()
from yade import qt
qt.Controller(); qt.View()
step=.01
O.run(200,True)
-if 0:
- for i in range(0,500):
- O.run(500,True)
- for b in O.bodies:
- b.shape['radius']=b.shape['radius']+step
- b.mold['radius']=b.mold['radius']+step
- for i in O.interactions:
- if not i.isReal: continue
- i.geom['effR1']=i.geom['effR1']+step
- i.geom['effR2']=i.geom['effR2']+step
- print O.iter,utils.totalForceInVolume()
-else:
- for i in range(0,500):
- O.run(100,True)
- mn,mx=O.periodicCell
- step=(mx-mn); step=Vector3(.002*step[0],.002*step[1],.002*step[2])
- O.periodicCell=mn+step,mx-step
- if (i%10==0): print O.iter,utils.totalForceInVolume()
+for i in range(0,250):
+ O.run(200,True)
+ mn,mx=O.periodicCell
+ step=(mx-mn); step=Vector3(.002*step[0],.002*step[1],.002*step[2])
+ O.periodicCell=mn+step,mx-step
+ if (i%10==0):
+ F=utils.totalForceInVolume()
+ dim=mx-mn; A=Vector3(dim[1]*dim[2],dim[0]*dim[2],dim[0]*dim[1])
+ avgStress=sum([F[i]/A[i] for i in 0,1,2])/3.
+ print 'strain',(cubeSize-dim[0])/cubeSize,'avg. stress ',avgStress,'unbalanced ',utils.unbalancedForce()
#O.timingEnabled=True; timing.reset(); O.run(200000,True); timing.stats()