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()


_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help   : https://help.launchpad.net/ListHelp
_______________________________________________
yade-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/yade-dev

Reply via email to