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( _______________________________________________ Mailing list: https://launchpad.net/~yade-dev Post to : [email protected] Unsubscribe : https://launchpad.net/~yade-dev More help : https://help.launchpad.net/ListHelp

