yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01454
[svn] r1854 - in trunk: core pkg/common/Engine/MetaEngine pkg/common/Engine/StandAloneEngine pkg/dem/Engine/DeusExMachina py/yadeWrapper scripts/test
Author: eudoxos
Date: 2009-07-11 15:52:26 +0200 (Sat, 11 Jul 2009)
New Revision: 1854
Modified:
trunk/core/Interaction.hpp
trunk/core/InteractionContainer.cpp
trunk/core/InteractionContainer.hpp
trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp
trunk/py/yadeWrapper/yadeWrapper.cpp
trunk/scripts/test/collider-stride-triax.py
trunk/scripts/test/compare-identical.py
trunk/scripts/test/regular-sphere-pack.py
Log:
1. Handle clumps in a better way in NewtonsDampedLaw (only if asked by the clump itself) -- future parallelization work. (related to bug #398086)
2. InsertionSortCollider now knows when to run based on maximum distance the fastest body could have travelled. (It is actually the physical meaning of sweepDistance). Handle varying maxVelocitySq in a constitent way.
3. Add InteractionContainer::serializeSorted to sort interactions by id1 and id2 before serializing (useful for comparing XML files). Added Interaction::operator< to compare 2 interactions in that way.
4. Fix openMP strategy in InteractionDispatchers to "guided" (as per https://blueprints.launchpad.net/yade/+spec/omp-schedule-strategy)
Modified: trunk/core/Interaction.hpp
===================================================================
--- trunk/core/Interaction.hpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/core/Interaction.hpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -44,12 +44,14 @@
Interaction ();
Interaction(body_id_t newId1,body_id_t newId2);
- body_id_t getId1() {return id1;};
- body_id_t getId2() {return id2;};
+ const body_id_t& getId1() const {return id1;};
+ const body_id_t& getId2() const {return id2;};
//! swaps order of bodies within the interaction
void swapOrder();
+ bool operator<(const Interaction& other) const { return getId1()<other.getId1() || (getId1()==other.getId1() && getId2()<other.getId2()); }
+
//! cache functors that are called for this interaction. Currently used by InteractionDispatchers.
struct {
// Whether geometry dispatcher exists at all; this is different from !geom, since that can mean we haven't populated the cache yet.
Modified: trunk/core/InteractionContainer.cpp
===================================================================
--- trunk/core/InteractionContainer.cpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/core/InteractionContainer.cpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -24,6 +24,12 @@
}
+struct compPtrInteraction{
+ bool operator() (const shared_ptr<Interaction>& i1, const shared_ptr<Interaction>& i2) const {
+ return (*i1)<(*i2);
+ }
+};
+
void InteractionContainer::preProcessAttributes(bool deserializing)
{
if(deserializing)
@@ -37,6 +43,7 @@
InteractionContainer::iterator iEnd = this->end();
for( ; i!=iEnd ; ++i )
interaction.push_back(*i);
+ if(serializeSorted) std::sort(interaction.begin(),interaction.end(),compPtrInteraction());
}
}
Modified: trunk/core/InteractionContainer.hpp
===================================================================
--- trunk/core/InteractionContainer.hpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/core/InteractionContainer.hpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -86,7 +86,7 @@
public :
boost::mutex drawloopmutex;
- InteractionContainer() { };
+ InteractionContainer(): serializeSorted(false) { };
virtual ~InteractionContainer() {};
virtual bool insert(body_id_t /*id1*/,body_id_t /*id2*/) {throw;};
@@ -104,6 +104,9 @@
virtual shared_ptr<Interaction>& operator[] (unsigned int) {throw;};
virtual const shared_ptr<Interaction>& operator[] (unsigned int) const {throw;};
+ // sort interactions before serializations; useful if comparing XML files from different runs (false by default)
+ bool serializeSorted;
+
// std::pair is not handled by yade::serialization, use vector<body_id_t> instead
typedef Vector2<body_id_t> bodyIdPair;
//! Ask for erasing the interaction given (from the constitutive law); this resets the interaction (to the initial=potential state)
@@ -147,7 +150,7 @@
protected :
virtual void preProcessAttributes(bool deserializing);
virtual void postProcessAttributes(bool deserializing);
- REGISTER_ATTRIBUTES(/*no base*/,(interaction)(pendingErase));
+ REGISTER_ATTRIBUTES(/*no base*/,(interaction)(pendingErase)(serializeSorted));
REGISTER_CLASS_AND_BASE(InteractionContainer,Serializable);
};
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -22,7 +22,7 @@
}
#ifdef YADE_OPENMP
const long size=rootBody->interactions->size();
- #pragma omp parallel for
+ #pragma omp parallel for schedule(guided)
for(long i=0; i<size; i++){
const shared_ptr<Interaction>& I=(*rootBody->interactions)[i];
#else
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -65,25 +65,16 @@
bool InsertionSortCollider::isActivated(MetaBody* rb){
// 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;
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;
+ if(!newton || newton->maxVelocitySq<0 || sweepVelocity<0) return true; // we wouldn't be able to find the max velocity, or it has not been computed yet, or there were no data available last time
+ if(XX.size()!=2*rb->bodies->size()) return true;
+ if(fastestBodyMaxDist<0){fastestBodyMaxDist=0; return true;}
+ fastestBodyMaxDist+=sqrt(newton->maxVelocitySq)*rb->dt;
+ if(fastestBodyMaxDist>=sweepLength) return true;
// 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;
+ rb->interactions->erasePending(*this);
+ return false;
}
#endif
@@ -146,21 +137,17 @@
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; }
+ } else { /* no valid data yet, run next time again */ boundDispatcher->sweepDist=0; sweepVelocity=-1; stride=1; }
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; }
+ fastestBodyMaxDist=0; // reset
+ } else { boundDispatcher->sweepTime=-1; boundDispatcher->sweepDist=0; }
boundDispatcher->action(rb);
#endif
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;
@@ -191,10 +178,14 @@
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
{
- std::sort(XX.begin(),XX.end());
- std::sort(YY.begin(),YY.end());
- std::sort(ZZ.begin(),ZZ.end());
+ #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
insertionSort(XX,interactions,rb,false); insertionSort(YY,interactions,rb,false); insertionSort(ZZ,interactions,rb,false);
@@ -214,7 +205,7 @@
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
- // if(jid<iid) { /* LOG_TRACE("Skip #"<<V[j].id<<(V[j].flags.isMin?"(min)":"(max)")<<" with "<<iid<<" (smaller id)"); */ continue; }
+ //if(jid<iid) { /* LOG_TRACE("Skip #"<<V[j].id<<(V[j].flags.isMin?"(min)":"(max)")<<" with "<<iid<<" (smaller id)"); */ continue; }
/* abuse the same function here; since it does spatial overlap check first, it is OK to use it */
handleBoundInversion(iid,jid,interactions,rb);
// now we are at the last element, but we still have not met the upper bound of V[i].id
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.hpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -46,12 +46,8 @@
shared_ptr<BoundingVolumeMetaEngine> boundDispatcher;
// 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).
+ // interval at which we will run (informative only, is updated automatically)
int stride;
- //! 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))
@@ -63,6 +59,8 @@
/// Has no influence on sweepLength, only on the computed stride.
/// Default 1.05
Real sweepFactor;
+ //! maximum distance that the fastest body could have travelled since the last run; if >= sweepLength, we could get out of bboxes and will trigger full run
+ Real fastestBodyMaxDist;
#endif
//! storage for bounds
std::vector<Bound> XX,YY,ZZ;
@@ -92,7 +90,7 @@
InsertionSortCollider():
#ifdef COLLIDE_STRIDED
- stride(0), lastRun(-1), scheduledRun(-1), sweepLength(-1), sweepVelocity(-1), sweepFactor(1.05),
+ stride(0), sweepLength(-1), sweepVelocity(-1), sweepFactor(1.05), fastestBodyMaxDist(-1),
#endif
sortAxis(0), sortThenCollide(false){
#ifdef ISC_TIMING
@@ -103,7 +101,7 @@
REGISTER_CLASS_AND_BASE(InsertionSortCollider,Collider);
REGISTER_ATTRIBUTES(Collider,(sortAxis)(sortThenCollide)
#ifdef COLLIDE_STRIDED
- (stride)(lastRun)(scheduledRun)(sweepLength)(sweepFactor)(sweepVelocity)
+ (stride)(sweepLength)(sweepFactor)(sweepVelocity)(fastestBodyMaxDist)
#endif
);
DECLARE_LOGGER;
Modified: trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -21,6 +21,22 @@
}
}
+void NewtonsDampedLaw::handleClumpMember(MetaBody* ncb, const body_id_t memberId, RigidBodyParameters* clumpRBP){
+ const shared_ptr<Body>& b=Body::byId(memberId,ncb);
+ assert(b->isClumpMember());
+ RigidBodyParameters* rb=YADE_CAST<RigidBodyParameters*>(b->physicalParameters.get());
+ const Vector3r& m=ncb->bex.getTorque(memberId); const Vector3r& f=ncb->bex.getForce(memberId);
+ Vector3r diffClumpAccel=f/clumpRBP->mass;
+ // angular acceleration from: normal torque + torque generated by the force WRT particle centroid on the clump centroid
+ Vector3r diffClumpAngularAccel=diagDiv(m,clumpRBP->inertia)+diagDiv((rb->se3.position-clumpRBP->se3.position).Cross(f),clumpRBP->inertia);
+ // damp increment of accels on the clump, using velocities of the clump MEMBER
+ cundallDamp(ncb->dt,f,rb->velocity,diffClumpAccel,m,rb->angularVelocity,diffClumpAngularAccel);
+ // clumpRBP->{acceleration,angularAcceleration} are reset byt Clump::moveMembers, it is ok to just increment here
+ clumpRBP->acceleration+=diffClumpAccel;
+ clumpRBP->angularAcceleration+=diffClumpAngularAccel;
+ maxVelocitySq=max(maxVelocitySq,rb->velocity.SquaredLength());
+}
+
void NewtonsDampedLaw::applyCondition ( MetaBody * ncb )
{
ncb->bex.sync();
@@ -29,44 +45,28 @@
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
- if (!b->isDynamic && !b->isClumpMember()) continue;
-
+ if (!b->isDynamic || b->isClumpMember()) continue;
RigidBodyParameters* rb = YADE_CAST<RigidBodyParameters*>(b->physicalParameters.get());
const body_id_t& id=b->getId();
- const Vector3r& m=ncb->bex.getTorque(id);
- const Vector3r& f=ncb->bex.getForce(id);
+ const Vector3r& m=ncb->bex.getTorque(id); const Vector3r& f=ncb->bex.getForce(id);
- //Newtons mometum law :
if (b->isStandalone()){
- rb->angularAcceleration=diagDiv(m,rb->inertia);
rb->acceleration=f/rb->mass;
+ rb->angularAcceleration=diagDiv(m,rb->inertia);
+ cundallDamp(dt,f,rb->velocity,rb->acceleration,m,rb->angularVelocity,rb->angularAcceleration);
}
else if (b->isClump()){
- // at this point, forces from clump members are already summed up, this is just for forces applied to clump proper, if there are such (does it have some physical meaning?)
- rb->angularAcceleration+=diagDiv(m,rb->inertia);
- rb->acceleration+=f/rb->mass; // accel for clump will be reset in Clump::moveMembers, called from the clump itself
+ rb->acceleration=rb->angularAcceleration=Vector3r::ZERO; // to make sure; should be reset in Clump::moveMembers
+ FOREACH(Clump::memberMap::value_type mm, static_cast<Clump*>(b.get())->members){
+ handleClumpMember(ncb,mm.first,rb);
+ }
+ // at this point, forces from clump members are already summed up, this is just for forces applied to clump proper, if there are such
+ Vector3r dLinAccel=f/rb->mass, dAngAccel=diagDiv(m,rb->inertia);
+ cundallDamp(dt,f,rb->velocity,dLinAccel,m,rb->angularVelocity,dAngAccel);
+ rb->acceleration+=dLinAccel;
+ rb->angularAcceleration+=dAngAccel;
}
- else {
- assert(b->isClumpMember());
- assert(b->clumpId>b->id);
- const shared_ptr<Body>& clump=Body::byId(b->clumpId,ncb);
- RigidBodyParameters* clumpRBP=YADE_CAST<RigidBodyParameters*> ( clump->physicalParameters.get() );
- Vector3r diffClumpAccel=f/clumpRBP->mass;
- // angular acceleration from: normal torque + torque generated by the force WRT particle centroid on the clump centroid
- Vector3r diffClumpAngularAccel=diagDiv(m,clumpRBP->inertia)+diagDiv((rb->se3.position-clumpRBP->se3.position).Cross(f),clumpRBP->inertia);
- // damp increment of accels on the clump, using velocities of the clump MEMBER
- cundallDamp(dt,f,rb->velocity,diffClumpAccel,m,rb->angularVelocity,diffClumpAngularAccel);
- // clumpRBP->{acceleration,angularAcceleration} are reset byt Clump::moveMembers, it is ok to just increment here
- clumpRBP->acceleration+=diffClumpAccel;
- clumpRBP->angularAcceleration+=diffClumpAngularAccel;
- maxVelocitySq=max(maxVelocitySq,rb->velocity.SquaredLength());
- continue;
- }
- assert(!b->isClumpMember());
- // damping: applied to non-clumps only, as clumps members were already damped above
- if(!b->isClump()) cundallDamp(dt,f,rb->velocity,rb->acceleration,m,rb->angularVelocity,rb->angularAcceleration);
-
maxVelocitySq=max(maxVelocitySq,rb->velocity.SquaredLength());
// blocking DOFs
@@ -96,14 +96,3 @@
}
}
-/*
-:09:37] eudoxos2: enum {LOOP1,LOOP2,END}
-[16:09:37] eudoxos2: for(int state=LOOP1; state!=END; state++){
-[16:09:37] eudoxos2: FOREACH(const shared_ptr<Body>& b, rootBody->bodies){
-[16:09:38] eudoxos2: if(b->isClumpMember() && LOOP1){ [[apply that on b->clumpId]] }
-[16:09:38] eudoxos2: if((b->isStandalone && LOOP1) || (b->isClump && LOOP2){ [[damping, newton, integrate]]; b->moveClumpMembers(); }
-[16:09:40] eudoxos2: }
-[16:09:42] eudoxos2: }
-[16:09:44] eudoxos2: }*/
-
-
Modified: trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.hpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -31,10 +31,12 @@
NOTE: Cundall damping affected dynamic simulation! See examples/dynamic_simulation_tests
*/
+class RigidBodyParameters;
-
class NewtonsDampedLaw : public DeusExMachina{
inline void cundallDamp(const Real& dt, const Vector3r& f, const Vector3r& velocity, Vector3r& acceleration, const Vector3r& m, const Vector3r& angularVelocity, Vector3r& angularAcceleration);
+ void handleClumpMember(MetaBody* ncb, const body_id_t memberId, RigidBodyParameters* clumpRBP);
+
public:
///damping coefficient for Cundall's non viscous damping
Real damping;
Modified: trunk/py/yadeWrapper/yadeWrapper.cpp
===================================================================
--- trunk/py/yadeWrapper/yadeWrapper.cpp 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/py/yadeWrapper/yadeWrapper.cpp 2009-07-11 13:52:26 UTC (rev 1854)
@@ -422,6 +422,8 @@
python::list withBody(long id){ python::list ret; FOREACH(const shared_ptr<Interaction>& I, *proxee){ if(I->isReal() && (I->getId1()==id || I->getId2()==id)) ret.append(pyInteraction(I));} return ret;}
python::list withBodyAll(long id){ python::list ret; FOREACH(const shared_ptr<Interaction>& I, *proxee){ if(I->getId1()==id || I->getId2()==id) ret.append(pyInteraction(I));} return ret; }
long countReal(){ long ret=0; FOREACH(const shared_ptr<Interaction>& I, *proxee){ if(I->isReal()) ret++; } return ret; }
+ bool serializeSorted_get(){return proxee->serializeSorted;}
+ void serializeSorted_set(bool ss){proxee->serializeSorted=ss;}
};
Vector3r tuple2vec(const python::tuple& t){return Vector3r(python::extract<double>(t[0])(),python::extract<double>(t[1])(),python::extract<double>(t[2])());}
@@ -763,6 +765,7 @@
.def("nth",&pyInteractionContainer::pyNth)
.def("withBody",&pyInteractionContainer::withBody)
.def("withBodyAll",&pyInteractionContainer::withBodyAll)
+ .add_property("serializeSorted",&pyInteractionContainer::serializeSorted_get,&pyInteractionContainer::serializeSorted_set)
.def("nth",&pyInteractionContainer::pyNth)
.def("clear",&pyInteractionContainer::clear);
boost::python::class_<pyInteractionIterator>("InteractionIterator",python::init<pyInteractionIterator&>())
Modified: trunk/scripts/test/collider-stride-triax.py
===================================================================
--- trunk/scripts/test/collider-stride-triax.py 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/scripts/test/collider-stride-triax.py 2009-07-11 13:52:26 UTC (rev 1854)
@@ -4,18 +4,20 @@
import os.path
loadFrom='/tmp/triax.xml'
if not os.path.exists(loadFrom):
- TriaxialTest(numberOfGrains=8000,fast=True,noFiles=True).generate(loadFrom)
+ TriaxialTest(numberOfGrains=8000,fast=True,noFiles=True).load()
+ #O.run(500)
+ O.save(loadFrom)
O.load(loadFrom)
log.setLevel('TriaxialCompressionEngine',log.WARN) # shut up
-log.setLevel('InsertionSortCollider',log.DEBUG) # shut up
+log.setLevel('InsertionSortCollider',log.DEBUG)
collider=utils.typedEngine('InsertionSortCollider')
newton=utils.typedEngine('NewtonsDampedLaw')
# use striding; say "if 0:" to disable striding and compare to regular runs
-if 1:
+if 0:
# length by which bboxes will be made larger
- collider['sweepLength']=.05*O.bodies[100].shape['radius']
+ collider['sweepLength']=0.05*O.bodies[100].shape['radius']
O.step() # filter out initialization
O.timingEnabled=True
@@ -29,6 +31,14 @@
print 'Number of interactions: %d (real ratio: %g)'%(len(O.interactions),float(O.interactions.countReal())/len(O.interactions))
print '======================================================='
timing.reset()
+ # plot velocity histogram
+ if 0:
+ import pylab
+ pylab.hist([sqrt(sum([v**2 for v in b.phys['velocity']])) for b in O.bodies])
+ pylab.title('step %d; max speed %g'%(O.iter,sqrt(newton['maxVelocitySq'])))
+ pylab.grid()
+ pylab.savefig('%s-%05d.png'%(loadFrom,O.iter),dpi=40)
+ pylab.cla()
print 'Total time: %g s'%(totalTime/1e9)
-quit()
+#quit()
Modified: trunk/scripts/test/compare-identical.py
===================================================================
--- trunk/scripts/test/compare-identical.py 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/scripts/test/compare-identical.py 2009-07-11 13:52:26 UTC (rev 1854)
@@ -30,7 +30,8 @@
if O.numThreads>1:
print "WARNING: You should run single-threaded with OMP_NUM_THREADS=1; interaction order will be probably different otherwise!"
-O.load(initFile); O.switchWorld(); O.load(initFile); O.switchWorld()
+for world in 0,1:
+ O.load(initFile); O.interactions.serializeSorted=True; O.switchWorld();
from hashlib import md5; import difflib,sys
print "Identical at steps ",
for i in xrange(0,stopIter/nSteps):
Modified: trunk/scripts/test/regular-sphere-pack.py
===================================================================
--- trunk/scripts/test/regular-sphere-pack.py 2009-07-10 19:16:01 UTC (rev 1853)
+++ trunk/scripts/test/regular-sphere-pack.py 2009-07-11 13:52:26 UTC (rev 1854)
@@ -16,7 +16,7 @@
rad,gap=.15,.02
rho=1e3
-kw={'density':rho}
+kw={'density':rho,'frictionAngle':.1}
O.bodies.append(
pack.regularHexa(