Author: eudoxos
Date: 2009-07-10 21:16:01 +0200 (Fri, 10 Jul 2009)
New Revision: 1853

Modified:
   trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
   trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
   trunk/pkg/common/SConscript
   trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
   trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp
   trunk/scripts/test/collider-stride-triax.py
Log:
1. Make NewtonsDampedLaw compute maxVlocitySq at every step anew.
2. Make InsertionSortCollider find NewtonsDampedLaw and get max speed from 
there. Together with InsertionSortColider::sweepLength, this makes stride 
adapted automatically to maxVelocitySq; this will described at 
http://yade.wikia.com/wiki/Insertion_Sort_Collider_Stride. 
3. Update test script for that.


Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp  
2009-07-10 09:52:33 UTC (rev 1852)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp  
2009-07-10 19:16:01 UTC (rev 1853)
@@ -5,6 +5,7 @@
 #include<yade/core/Interaction.hpp>
 #include<yade/core/InteractionContainer.hpp>
 #include<yade/pkg-common/BoundingVolumeMetaEngine.hpp>
+#include<yade/pkg-dem/NewtonsDampedLaw.hpp>
 
 #include<algorithm>
 #include<vector>
@@ -65,16 +66,31 @@
                // activated if number of bodies changes (hence need to refresh 
collision information)
                // or the time of scheduled run already came, or we were never 
scheduled yet
                if(stride<=1) return true;
-               bool ret=XX.size()!=2*rb->bodies->size() || scheduledRun<0 || 
rb->simulationTime>=scheduledRun;
-               // we wouldn't run in this step; just delete pending 
interactions
-               // this could be done in ::action, but it would make the call 
counters not reflect the stride
+               if(sweepLength<=0) return true;
+               if(!newton) return true; // we wouldn't be able to find the max 
velocity
+               bool ret=rb->simulationTime>=scheduledRun ||
+                       // if the max velocity is bigger than the one that we 
used for bb computation last time
+                       // and the distance bodies would travel with this 
bigger velocity since last run (rb->simulationTime-lastRun)
+                       // would be the same or greater than the one that would 
be traveled with the original velocity
+                       // over the stride time (scheduledRun-lastRun)
+                       (newton->maxVelocitySq<0) || // no valid data about max 
velocity, run always
+                       (sweepVelocity==0 && newton->maxVelocitySq>0) || 
+                       (sweepVelocity<sqrt(newton->maxVelocitySq) && 
rb->simulationTime-lastRun>=(sweepVelocity/sqrt(newton->maxVelocitySq)/* we 
know maxVelocitySq>0 from the first condition */)*(scheduledRun-lastRun)) ||
+                       // number of bodies changed
+                       XX.size()!=2*rb->bodies->size() ||
+                       // we've never run yet (this should never happen as per 
if(!newton) above)
+                       scheduledRun<0;
+               // we wouldn't run in this step; in that case, just delete 
pending interactions
+               // this is done in ::action normally, but it would make the 
call counters not reflect the stride
                if(!ret) rb->interactions->erasePending(*this);
                return ret;
        }
 #endif
 
 void InsertionSortCollider::action(MetaBody* rb){
-       // timingDeltas->start();
+       #ifdef ISC_TIMING
+               timingDeltas->start();
+       #endif
 
        size_t nBodies=rb->bodies->size();
        InteractionContainer* interactions=rb->interactions.get();
@@ -107,28 +123,44 @@
                        // get the BoundingVolumeMetaEngine and turn it off; we 
will call it ourselves
                        if(!boundDispatcher){
                                FOREACH(shared_ptr<Engine>& e, rb->engines){ 
boundDispatcher=dynamic_pointer_cast<BoundingVolumeMetaEngine>(e); 
if(boundDispatcher) break; }
-                               if(!boundDispatcher){ LOG_FATAL("Unable to 
locate BoundingVolumeMetaEngine within engines, aborting."); throw 
runtime_error("Explanation above"); }
+                               if(!boundDispatcher){ LOG_FATAL("Unable to 
locate BoundingVolumeMetaEngine within engines, aborting."); abort(); }
                                boundDispatcher->activated=false; // deactive 
the engine, we will call it ourselves from now (just when needed)
                        }
+                       if(sweepLength>0){
+                               // get NewtonsDampedLaw, to ask for the maximum 
velocity value
+                               if(!newton){
+                                       FOREACH(shared_ptr<Engine>& e, 
rb->engines){ newton=dynamic_pointer_cast<NewtonsDampedLaw>(e); if(newton) 
break; }
+                                       if(!newton){ LOG_FATAL("Unable to 
locate NewtonsDampedLaw within engines, aborting."); abort(); }
+                               }
+                       }
                #endif
-       // timingDeltas->checkpoint("init");
+       ISC_CHECKPOINT("init");
 
                #ifdef COLLIDE_STRIDED
-                       // FIXME: should be able to adapt stride based on the 
potential_interaction_count_increase/stride_speedup tradeoff
-                       // this depends on the packing density, for instance, 
maximum velocities/accels etc.
-                       if(stride>1 && sweepTimeFactor<1 && sweepVelocity<=0){ 
LOG_WARN("Stride is "<<stride<<", but no sweeping effective!! Setting stride 
back to 1."); stride=1; }
-                       if(stride>1){
-                               //schedule next run
-                               
scheduledRun=rb->simulationTime+rb->dt*(stride-.5); // -.5 to avoid rounding 
issues
-                               if(sweepTimeFactor>=1) 
boundDispatcher->sweepTime=rb->dt*stride*sweepTimeFactor;
-                               if(sweepVelocity>0) 
boundDispatcher->sweepDist=rb->dt*stride*sweepVelocity;
+                       if(sweepLength>0){
+                               if(newton->maxVelocitySq>=0){ // non-negative, 
i.e. a really computed value
+                                       // compute new stride value
+                                       assert(sweepFactor>1.);
+                                       
sweepVelocity=sqrt(newton->maxVelocitySq)*sweepFactor;
+                                       if(sweepVelocity>0) {
+                                               
stride=max(1,int((sweepLength/sweepVelocity)/rb->dt));
+                                               
boundDispatcher->sweepDist=rb->dt*(stride-1)*sweepVelocity;
+                                       } else { // no motion
+                                               stride=1000; // shouldn't this 
be some saner value? Infinity? How to decide?
+                                               boundDispatcher->sweepDist=0; 
// nothing moves, no need to make bboxes larger
+                                       }
+                                       
scheduledRun=rb->simulationTime+rb->dt*(stride-.5); // -.5 to avoid rounding 
issues
+                               } else { /* no valid data yet, run next time 
again */ boundDispatcher->sweepDist=0; stride=1; 
scheduledRun=rb->simulationTime+rb->dt; }
+                               LOG_DEBUG(rb->simulationTime<<"s: stride 
adapted to "<<stride<<"; sweepVelocity="<<sweepVelocity<<", 
maxVelocity="<<sqrt(newton->maxVelocitySq)<<", 
sweepDist="<<boundDispatcher->sweepDist);
+                               newton->maxVelocitySq=-1; // reset to invalid 
value again
                        } else { scheduledRun=-1; 
boundDispatcher->sweepTime=-1; boundDispatcher->sweepDist=0; }
                        boundDispatcher->action(rb);
                #endif
-       // timingDeltas->checkpoint("bound");
 
+       ISC_CHECKPOINT("bound");
 
 
+
        // copy bounds along given axis into our arrays
                for(size_t i=0; i<2*nBodies; i++){
                        const body_id_t& idXX=XX[i].id; const body_id_t& 
idYY=YY[i].id; const body_id_t& idZZ=ZZ[i].id;
@@ -144,11 +176,11 @@
                                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)); }
                        }
                }
+       ISC_CHECKPOINT("copy");
 
-       // timingDeltas->checkpoint("copy");
-
        // process interactions that the constitutive law asked to be erased
-       interactions->erasePending(*this);
+               interactions->erasePending(*this);
+       ISC_CHECKPOINT("erase");
 
        // sort
                if(!doInitSort && !sortThenCollide){
@@ -159,13 +191,9 @@
                        if(doInitSort){
                                // the initial sort is in independent in 3 
dimensions, may be run in parallel
                                // it seems that there is no time gain running 
this in parallel, though
-                               #pragma omp parallel sections
                                {
-                                       #pragma omp section
                                                std::sort(XX.begin(),XX.end());
-                                       #pragma omp section     
                                                std::sort(YY.begin(),YY.end());
-                                       #pragma omp section
                                                std::sort(ZZ.begin(),ZZ.end());
                                }
                        } else { // sortThenCollide
@@ -205,5 +233,5 @@
                                }
                        }
                }
-       // timingDeltas->checkpoint("sort&collide");
+       ISC_CHECKPOINT("sort&collide");
 }

Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp  
2009-07-10 09:52:33 UTC (rev 1852)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp  
2009-07-10 19:16:01 UTC (rev 1853)
@@ -15,7 +15,18 @@
 */
 
 #define COLLIDE_STRIDED
+
+// #define this macro to enable timing whichin this engine
+//#define ISC_TIMING
+
+#ifdef ISC_TIMING
+       #define ISC_CHECKPOINT(cpt) timingDeltas->checkPoint(cpt)
+#else
+       #define ISC_CHECKPOINT(cpt)
+#endif
+
 class BoundingVolumeMetaEngine;
+class NewtonsDampedLaw;
 
 class InsertionSortCollider: public Collider{
        //! struct for storing bounds of bodies
@@ -33,16 +44,25 @@
        #ifdef COLLIDE_STRIDED
                // keep this dispatcher and call it ourselves as needed
                shared_ptr<BoundingVolumeMetaEngine> boundDispatcher;
-               // interval at which we will run; if <=1, we run always (as 
usual). 0 by default.
+               // we need this to find out about current maxVelocitySq
+               shared_ptr<NewtonsDampedLaw> newton;
+               // interval at which we will run; if 0, we run always (as 
usual).
                int stride;
-               // virtual time when we have to run the next time
-               Real scheduledRun;
-               //! If >1 and using stride, sweep time will be multiplied by 
this number; it should be >=1. to accomodate non-linearities in the system.
-               /// If deactivated (-1 by default), current-velocity-based 
sweeping will not be enabled.
-               Real sweepTimeFactor;
-               //! If >0 and using stride, all bodies will be swept as if 
having this velocity.
-               /// It should be the maximum (predicted or measured) velocity 
increased by some safety margin, otherwise bodies may get out of their AABB. 
Deactivated (-1) by default.
+               //! virtual time when we were run last time
+               Real lastRun;
+               //! virtual time when we have to run the next time
+               Real scheduledRun; 
+               /// Absolute length that will be added to bounding boxes at 
each side; it should be something like 1/5 of typical grain radius
+               /// this value is used to adapt stride; if too large, stride 
will be big, but the ratio of potential-only interactions will be very big, 
+               /// thus slowing down collider & interaction loops 
significantly (remember: O(addLength^3))
+               /// If non-positive, collider runs always, without stride 
adaptivity
+               Real sweepLength;
+               //! Current sweeping velocity; computed from 
maxVelocity*sweepVelocityFactor
                Real sweepVelocity;
+               //! Overestimation factor for the sweep velocity; must be >=1.0.
+               /// Has no influence on sweepLength, only on the computed 
stride.
+               /// Default 1.05
+               Real sweepFactor;
        #endif
        //! storage for bounds
        std::vector<Bound> XX,YY,ZZ;
@@ -72,14 +92,18 @@
 
        InsertionSortCollider():
        #ifdef COLLIDE_STRIDED
-               stride(0), scheduledRun(-1), sweepTimeFactor(-1), 
sweepVelocity(-1),
+               stride(0), lastRun(-1), scheduledRun(-1), sweepLength(-1), 
sweepVelocity(-1), sweepFactor(1.05),
        #endif
-                sortAxis(0), sortThenCollide(false){ /* 
timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas); */ }
+               sortAxis(0), sortThenCollide(false){
+                       #ifdef ISC_TIMING
+                               timingDeltas=shared_ptr<TimingDeltas>(new 
TimingDeltas);
+                       #endif 
+                }
        virtual void action(MetaBody*);
        REGISTER_CLASS_AND_BASE(InsertionSortCollider,Collider);
        REGISTER_ATTRIBUTES(Collider,(sortAxis)(sortThenCollide)
                #ifdef COLLIDE_STRIDED
-                       (stride)(scheduledRun)(sweepTimeFactor)(sweepVelocity)
+                       
(stride)(lastRun)(scheduledRun)(sweepLength)(sweepFactor)(sweepVelocity)
                #endif
        );
        DECLARE_LOGGER;

Modified: trunk/pkg/common/SConscript
===================================================================
--- trunk/pkg/common/SConscript 2009-07-10 09:52:33 UTC (rev 1852)
+++ trunk/pkg/common/SConscript 2009-07-10 19:16:01 UTC (rev 1853)
@@ -143,7 +143,7 @@
        
env.SharedLibrary('SpheresFactory',['Engine/StandAloneEngine/SpheresFactory.cpp'],
                
LIBS=env['LIBS']+['AABB','InteractingSphere','Facet','Sphere','BodyMacroParameters','InteractionGeometryMetaEngine']),
        
env.SharedLibrary('SpatialQuickSortCollider',['Engine/StandAloneEngine/SpatialQuickSortCollider.cpp']),
-       
env.SharedLibrary('InsertionSortCollider',['Engine/StandAloneEngine/InsertionSortCollider.cpp'],LIBS=env['LIBS']+['BoundingVolumeMetaEngine']),
+       
env.SharedLibrary('InsertionSortCollider',['Engine/StandAloneEngine/InsertionSortCollider.cpp'],LIBS=env['LIBS']+['BoundingVolumeMetaEngine','NewtonsDampedLaw']),
        
env.SharedLibrary('PersistentSAPCollider',['Engine/StandAloneEngine/PersistentSAPCollider.cpp']),
        
env.SharedLibrary('DistantPersistentSAPCollider',['Engine/StandAloneEngine/DistantPersistentSAPCollider.cpp']),
        
env.SharedLibrary('PhysicalActionContainerReseter',['Engine/StandAloneEngine/PhysicalActionContainerReseter.cpp']),

Modified: trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp     2009-07-10 
09:52:33 UTC (rev 1852)
+++ trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp     2009-07-10 
19:16:01 UTC (rev 1853)
@@ -25,6 +25,7 @@
 {
        ncb->bex.sync();
        Real dt=Omega::instance().getTimeStep();
+       maxVelocitySq=-1;
 
        FOREACH(const shared_ptr<Body>& b, *ncb->bodies){
                // clump members are non-dynamic; they skip the rest of loop 
once their forces are properly taken into account, however

Modified: trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp     2009-07-10 
09:52:33 UTC (rev 1852)
+++ trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp     2009-07-10 
19:16:01 UTC (rev 1853)
@@ -38,10 +38,10 @@
        public:
                ///damping coefficient for Cundall's non viscous damping
                Real damping;
-               /// store square of max. velocity, for informative purposes
+               /// store square of max. velocity, for informative purposes; 
computed again at every step
                Real maxVelocitySq;
                virtual void applyCondition(MetaBody *);                
-               NewtonsDampedLaw(): damping(0.2), maxVelocitySq(0){}
+               NewtonsDampedLaw(): damping(0.2), maxVelocitySq(-1){}
        REGISTER_ATTRIBUTES(DeusExMachina,(damping)(maxVelocitySq));
        REGISTER_CLASS_AND_BASE(NewtonsDampedLaw,DeusExMachina);
 };

Modified: trunk/scripts/test/collider-stride-triax.py
===================================================================
--- trunk/scripts/test/collider-stride-triax.py 2009-07-10 09:52:33 UTC (rev 
1852)
+++ trunk/scripts/test/collider-stride-triax.py 2009-07-10 19:16:01 UTC (rev 
1853)
@@ -4,30 +4,19 @@
 import os.path
 loadFrom='/tmp/triax.xml'
 if not os.path.exists(loadFrom):
-       
TriaxialTest(numberOfGrains=8000,fast=fast,noFiles=True).generate(loadFrom)
+       
TriaxialTest(numberOfGrains=8000,fast=True,noFiles=True).generate(loadFrom)
 O.load(loadFrom)
 log.setLevel('TriaxialCompressionEngine',log.WARN) # shut up
+log.setLevel('InsertionSortCollider',log.DEBUG) # shut up
 
 collider=utils.typedEngine('InsertionSortCollider')
 newton=utils.typedEngine('NewtonsDampedLaw')
 
 # use striding; say "if 0:" to disable striding and compare to regular runs
 if 1:
-       collider['stride']=4
-       collider['sweepVelocity']=16
-       # try to update maximum velocity dynamically:
-       if 1:
-               
O.engines=O.engines+[PeriodicPythonRunner(command='adjustMaxVelocity()',iterPeriod=50)]
+       # length by which bboxes will be made larger
+       collider['sweepLength']=.05*O.bodies[100].shape['radius']
 
-def adjustMaxVelocity():
-       newMax=sqrt(newton['maxVelocitySq']); newton['maxVelocitySq']=0
-       collider['sweepVelocity']=newMax
-       # try to adjust stride here; the 4 and 16 are original (reference) 
values for stride and sweepVelocity
-       # if this were inverse-proportional (without sqrt), stride is getting 
too high
-       collider['stride']=4*int(sqrt(16/newMax))
-       print 'step %d; new max velocity %g, stride 
%d'%(O.iter,newMax,collider['stride'])
-
-
 O.step() # filter out initialization
 O.timingEnabled=True
 totalTime=0


_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to