Hi, Bruno! Please, do not hurry up with merging. Let's test it.
Thanks. Anton On Tue, Apr 26, 2011 at 10:47 AM, Chareyre <[email protected]> wrote: > Chareyre has proposed merging lp:~bruno-chareyre/yade/collide into lp:yade. > > Requested reviews: > Yade developers (yade-dev) > > For more details, see: > https://code.launchpad.net/~bruno-chareyre/yade/collide/+merge/59029 > > Improved colliding (only implemented for non-periodic BCs at the moment). > - Some useless operations are removed (see diff). > - The behaviour with nBins=0 tracks displacements (while nBins>0 tracks max > velocity) to update bounds > - Experimental features: targetInterval (adjust bound sizes so that they will > be updated each N iterations), updatingDispFactor (only update bounds where > the body's motion is at least boundSize/factor, hence saving sorting time). > > Overall CPU time reduced by a factor 0.6 (average). > > -- > https://code.launchpad.net/~bruno-chareyre/yade/collide/+merge/59029 > Your team Yade developers is requested to review the proposed merge of > lp:~bruno-chareyre/yade/collide into lp:yade. > > === modified file 'core/Bound.hpp' > --- core/Bound.hpp 2010-11-30 13:51:41 +0000 > +++ core/Bound.hpp 2011-04-26 08:47:23 +0000 > @@ -22,6 +22,13 @@ > class Bound: public Serializable, public Indexable{ > public: > > YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(Bound,Serializable,"Object > bounding part of space taken by associated body; might be larger, used to > optimalize collision detection", > + #define ORI_VERLET > + #ifdef ORI_VERLET > + ((int,lastUpdateIter,0,Attr::readonly,"record iteration of > last reference position update |yupdate|")) > + > ((Vector3r,refPos,Vector3r(NaN,NaN,NaN),Attr::readonly,"Reference position, > updated at current body position each time the bound dispatcher update bounds > - only used if Verlet striding is active |yupdate|")) > + ((bool,isBounding,false,Attr::readonly,"A flag used to tell > when the body moves out of bounds - only used if Verlet striding is active > |yupdate|")) > + ((Real,sweepLength,0, Attr::readonly,"The length used to > increase the bounding boxe size - only used if Verlet striding is active > |yupdate|")) > + #endif > ((Vector3r,color,Vector3r(1,1,1),,"Color for rendering this > object")) > ((Vector3r,min,Vector3r(NaN,NaN,NaN),(Attr::noSave | > Attr::readonly),"Lower corner of box containing this bound (and the > :yref:`Body` as well)")) > ((Vector3r,max,Vector3r(NaN,NaN,NaN),(Attr::noSave | > Attr::readonly),"Lower corner of box containing this bound (and the > :yref:`Body` as well)")) > > === modified file 'core/InteractionContainer.hpp' > --- core/InteractionContainer.hpp 2011-02-27 13:54:43 +0000 > +++ core/InteractionContainer.hpp 2011-04-26 08:47:23 +0000 > @@ -82,6 +82,9 @@ > bool insert(const shared_ptr<Interaction>& i); > bool erase(Body::id_t id1,Body::id_t id2); > const shared_ptr<Interaction>& find(Body::id_t id1,Body::id_t > id2); > +// bool found(Body::id_t id1,Body::id_t id2); > + inline bool found(const Body::id_t& id1,const Body::id_t& > id2){ > + assert(bodies); return > (id1>id2)?(*bodies)[id2]->intrs.count(id1):(*bodies)[id1]->intrs.count(id2);} > // index access > shared_ptr<Interaction>& operator[](size_t id){return > linIntrs[id];} > const shared_ptr<Interaction>& operator[](size_t id) const { > return linIntrs[id];} > > === modified file 'pkg/common/Dispatching.cpp' > --- pkg/common/Dispatching.cpp 2011-02-20 10:28:40 +0000 > +++ pkg/common/Dispatching.cpp 2011-04-26 08:47:23 +0000 > @@ -21,12 +21,33 @@ > const long numBodies=(long)bodies->size(); > bool haveBins=(bool)velocityBins; > if(sweepDist!=0 && haveBins){ LOG_FATAL("Only one of sweepDist or > velocityBins can used!"); abort(); } > - //#pragma omp parallel for > +// #pragma omp parallel for > for(int id=0; id<numBodies; id++){ > if(!bodies->exists(id)) continue; // don't delete this check > - Janek > const shared_ptr<Body>& b=(*bodies)[id]; > shared_ptr<Shape>& shape=b->shape; > if(!shape || !b->isBounded()) continue; > + > + #ifdef ORI_VERLET > + if(oriVerlet && b->bound) { > + Real& sweepLength = b->bound->sweepLength; > + Vector3r disp = b->state->pos-b->bound->refPos; > + Real dist = > max(abs(disp[0]),max(abs(disp[1]),abs(disp[2]))); > + if (updatingDispFactor<=0 || > (dist*updatingDispFactor)>sweepLength) { > + if (targetInterv>=0) { > + > assert(b->bound->lastUpdateIter<scene->iter); > + Real sweepMult = > dist*targetInterv/((scene->iter-b->bound->lastUpdateIter)*sweepLength); > + sweepMult = max(0.9,sweepMult); > + > sweepLength=max(0.1*sweepDist,min(sweepLength*sweepMult,sweepDist)); > + } else { > + sweepLength=sweepDist; > + } > + b->bound->isBounding=false; > + } > + else continue; > + } > + #endif > + > #ifdef BV_FUNCTOR_CACHE > if(!shape->boundFunctor){ > shape->boundFunctor=this->getFunctor1D(shape); if(!shape->boundFunctor) > continue; } > // > LOG_DEBUG("shape->boundFunctor.get()=="<<shape->boundFunctor.get()<<" for > "<<b->shape->getClassName()<<", #"<<id); > @@ -37,9 +58,18 @@ > #endif > if(!b->bound) continue; // the functor did not create new bound > if(sweepDist>0){ > + #ifdef ORI_VERLET > + b->bound->refPos=b->state->pos; > + b->bound->lastUpdateIter=scene->iter; > + const Real& sweepLength = b->bound->sweepLength; > + Aabb* aabb=YADE_CAST<Aabb*>(b->bound.get()); > + > aabb->min-=Vector3r(sweepLength,sweepLength,sweepLength); > + > aabb->max+=Vector3r(sweepLength,sweepLength,sweepLength); > + #else > Aabb* aabb=YADE_CAST<Aabb*>(b->bound.get()); > aabb->min-=Vector3r(sweepDist,sweepDist,sweepDist); > aabb->max+=Vector3r(sweepDist,sweepDist,sweepDist); > + #endif > } > if(haveBins){ > Aabb* aabb=YADE_CAST<Aabb*>(b->bound.get()); > > === modified file 'pkg/common/Dispatching.hpp' > --- pkg/common/Dispatching.hpp 2011-01-29 22:47:18 +0000 > +++ pkg/common/Dispatching.hpp 2011-04-26 08:47:23 +0000 > @@ -89,6 +89,11 @@ > /*additional attrs*/ > ((bool,activated,true,,"Whether the engine is activated (only > should be changed by the collider)")) > ((Real,sweepDist,0,,"Distance by which enlarge all bounding > boxes, to prevent collider from being run at every step (only should be > changed by the collider).")) > + #ifdef ORI_VERLET > + ((Real,updatingDispFactor,-1,,"see > :yref:`InsertionSortCollider::updatingDispFactor` |yupdate|")) > + ((Real,targetInterv,-1,,"see > :yref:`InsertionSortCollider::targetInterv` |yupdate|")) > + ((bool,oriVerlet,false,,"Compare Verlet distance with > displacement instead of velocity (only should be changed by the collider)")) > + #endif > ,/*ctor*/,/*py*/ > ); > }; > > === modified file 'pkg/common/InsertionSortCollider.cpp' > --- pkg/common/InsertionSortCollider.cpp 2011-02-27 13:54:43 +0000 > +++ pkg/common/InsertionSortCollider.cpp 2011-04-26 08:47:23 +0000 > @@ -18,44 +18,59 @@ > YADE_PLUGIN((InsertionSortCollider)) > CREATE_LOGGER(InsertionSortCollider); > > +// inlined > // return true if bodies bb overlap in all 3 dimensions > -bool InsertionSortCollider::spatialOverlap(Body::id_t id1, Body::id_t id2) > const { > - assert(!periodic); > - return > - (minima[3*id1+0]<=maxima[3*id2+0]) && > (maxima[3*id1+0]>=minima[3*id2+0]) && > - (minima[3*id1+1]<=maxima[3*id2+1]) && > (maxima[3*id1+1]>=minima[3*id2+1]) && > - (minima[3*id1+2]<=maxima[3*id2+2]) && > (maxima[3*id1+2]>=minima[3*id2+2]); > -} > +// bool InsertionSortCollider::spatialOverlap(Body::id_t id1, Body::id_t > id2) const { > +// assert(!periodic); > +// return > +// (minima[3*id1+0]<=maxima[3*id2+0]) && > (maxima[3*id1+0]>=minima[3*id2+0]) && > +// (minima[3*id1+1]<=maxima[3*id2+1]) && > (maxima[3*id1+1]>=minima[3*id2+1]) && > +// (minima[3*id1+2]<=maxima[3*id2+2]) && > (maxima[3*id1+2]>=minima[3*id2+2]); > +// } > > // called by the insertion sort if 2 bodies swapped their bounds > void InsertionSortCollider::handleBoundInversion(Body::id_t id1, Body::id_t > id2, InteractionContainer* interactions, Scene*){ > assert(!periodic); > assert(id1!=id2); > // do bboxes overlap in all 3 dimensions? > - bool overlap=spatialOverlap(id1,id2); > - // existing interaction? > - const shared_ptr<Interaction>& I=interactions->find(id1,id2); > - bool hasInter=(bool)I; > - // interaction doesn't exist and shouldn't, or it exists and should > - if(likely(!overlap && !hasInter)) return; > - if(overlap && hasInter){ return; } > - // create interaction if not yet existing > - if(overlap && !hasInter){ // second condition only for readability > - > if(!Collider::mayCollide(Body::byId(id1,scene).get(),Body::byId(id2,scene).get())) > return; > - // LOG_TRACE("Creating new interaction #"<<id1<<"+#"<<id2); > - shared_ptr<Interaction> newI=shared_ptr<Interaction>(new > Interaction(id1,id2)); > - interactions->insert(newI); > - return; > - } > - if(!overlap && hasInter){ if(!I->isReal()) > interactions->erase(id1,id2); return; } > - assert(false); // unreachable > +// bool overlap=spatialOverlap(id1,id2); > +// // existing interaction? > +// bool hasInter=interactions->found(id1,id2); > +// // interaction doesn't exist and shouldn't, or it exists and should > +// if(likely(overlap == hasInter)) return; > +// // create interaction if not yet existing > +// if(overlap && !hasInter){ // second condition only for readability > +// > if(!Collider::mayCollide(Body::byId(id1,scene).get(),Body::byId(id2,scene).get())) > return; > +// // LOG_TRACE("Creating new interaction #"<<id1<<"+#"<<id2); > +// shared_ptr<Interaction> newI=shared_ptr<Interaction>(new > Interaction(id1,id2)); > +// interactions->insert(newI); > +// return; > +// } > +// if(!overlap && hasInter){ if(!interactions->find(id1,id2)->isReal()) > interactions->erase(id1,id2); return; } > +// assert(false); // unreachable > + > + //existing interaction? > + bool hasInter=interactions->found(id1,id2); > + if (hasInter && !interactions->find(id1,id2)->isReal() && > !spatialOverlap(id1,id2)){ interactions->erase(id1,id2); return;} > + if (!hasInter && spatialOverlap(id1,id2) && > Collider::mayCollide(Body::byId(id1,scene).get(),Body::byId(id2,scene).get())) > + interactions->insert(shared_ptr<Interaction>(new > Interaction(id1,id2))); > } > > void InsertionSortCollider::insertionSort(VecBounds& v, > InteractionContainer* interactions, Scene*, bool doCollide){ > assert(!periodic); > assert(v.size==(long)v.vec.size()); > + #ifdef ORI_VERLET > + bool foundUpdatedBound=true; > + #endif > for(long i=0; i<v.size; i++){ > - const Bounds viInit=v[i]; long j=i-1; /* cache hasBB; > otherwise 1% overall performance hit */ const bool > viInitBB=viInit.flags.hasBB; > + const Bounds viInit=v[i]; long j=i-1; /* cache hasBB; > otherwise 1% overall performance hit */ const bool > viInitBB=viInit.flags.hasBB; const bool isMin=viInit.flags.isMin; > + #ifdef ORI_VERLET > + if (verletDist>0 && nBins<=0 && viInitBB){ > + if (viInit.isBounding && !foundUpdatedBound) continue; > + else foundUpdatedBound=true; > + } > + #endif > + > while(j>=0 && v[j]>viInit){ > v[j+1]=v[j]; > #ifdef PISC_DEBUG > @@ -65,10 +80,16 @@ > // no collisions without bounding boxes > // also, do not collide body with itself; it sometimes > happens for facets aligned perpendicular to an axis, for reasons that are not > very clear > // see https://bugs.launchpad.net/yade/+bug/669095 > - if(likely(doCollide && viInitBB && v[j].flags.hasBB > && (viInit.id!=v[j].id))) > handleBoundInversion(viInit.id,v[j].id,interactions,scene); > + // skip bounds with same isMin flags, since inversion > doesn't imply anything in that case > + if(likely(doCollide && viInitBB && v[j].flags.hasBB > && isMin!=v[j].flags.isMin && (viInit.id!=v[j].id))) > handleBoundInversion(viInit.id,v[j].id,interactions,scene); > j--; > } > + #ifdef ORI_VERLET > + if (j==(i-1) && viInit.isBounding) foundUpdatedBound=false; > + #endif > v[j+1]=viInit; > + > + > } > } > > @@ -94,6 +115,7 @@ > } > > // STRIDE > + > bool InsertionSortCollider::isActivated(){ > // 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 > @@ -102,8 +124,18 @@ > if(nBins>=1 && > newton->velocityBins->checkSize_incrementDists_shouldCollide(scene)) return > true; > if(nBins<=0){ > if(fastestBodyMaxDist<0){fastestBodyMaxDist=0; return > true;} > + #ifdef ORI_VERLET > + if (!oriVerlet){ > + > fastestBodyMaxDist+=sqrt(newton->maxVelocitySq)*scene->dt; > + if(fastestBodyMaxDist>=verletDist) return > true; > + } else { > + fastestBodyMaxDist=newton->maxVelocitySq; > + if(fastestBodyMaxDist>=1 || > fastestBodyMaxDist==0) return true;} > + #else > > fastestBodyMaxDist+=sqrt(newton->maxVelocitySq)*scene->dt; > if(fastestBodyMaxDist>=verletDist) return true; > + #endif > + > } > if((size_t)BB[0].size!=2*scene->bodies->size()) return true; > if(scene->interactions->dirty) return true; > @@ -159,16 +191,6 @@ > // compatibility block, can be removed later > findBoundDispatcherInEnginesIfNoFunctorsAndWarn(); > > - // update bounds via boundDispatcher > - boundDispatcher->scene=scene; > - boundDispatcher->action(); > - > - // if interactions are dirty, force reinitialization > - if(scene->interactions->dirty){ > - doInitSort=true; > - scene->interactions->dirty=false; > - } > - > if(verletDist<0){ > Real minR=std::numeric_limits<Real>::infinity(); > FOREACH(const shared_ptr<Body>& b, *scene->bodies){ > @@ -181,15 +203,32 @@ > verletDist=isinf(minR) ? 0 : abs(verletDist)*minR; > } > > + // update bounds via boundDispatcher > + boundDispatcher->scene=scene; > + #ifdef ORI_VERLET > + if (oriVerlet) { > + nBins=0; > + boundDispatcher->oriVerlet=true; > + boundDispatcher->sweepDist=verletDist; > + boundDispatcher->targetInterv=targetInterv; > + > boundDispatcher->updatingDispFactor=updatingDispFactor;} > + #endif > + boundDispatcher->action(); > > + // if interactions are dirty, force reinitialization > + if(scene->interactions->dirty){ > + doInitSort=true; > + scene->interactions->dirty=false; > + } > + > // STRIDE > - if(verletDist>0){ > - // get NewtonIntegrator, to ask for the > maximum velocity value > - if(!newton){ > - FOREACH(shared_ptr<Engine>& e, > scene->engines){ newton=dynamic_pointer_cast<NewtonIntegrator>(e); if(newton) > break; } > - if(!newton){ throw > runtime_error("InsertionSortCollider.verletDist>0, but unable to locate > NewtonIntegrator within O.engines."); } > - } > + if(verletDist>0){ > + // get NewtonIntegrator, to ask for the maximum > velocity value > + if(!newton){ > + FOREACH(shared_ptr<Engine>& e, > scene->engines){ newton=dynamic_pointer_cast<NewtonIntegrator>(e); if(newton) > break; } > + if(!newton){ throw > runtime_error("InsertionSortCollider.verletDist>0, but unable to locate > NewtonIntegrator within O.engines."); } > } > + } > ISC_CHECKPOINT("init"); > > // STRIDE > @@ -203,6 +242,18 @@ > // reset bins, in case they were > active but are not anymore > if(newton->velocityBins) > newton->velocityBins=shared_ptr<VelocityBins>(); > if(boundDispatcher->velocityBins) > boundDispatcher->velocityBins=shared_ptr<VelocityBins>(); > assert(strideActive); > assert(newton->maxVelocitySq>=0); assert(sweepFactor>1.); > + #ifdef ORI_VERLET > + newton->oriVerlet=oriVerlet; > + if (!oriVerlet){ > + Real > sweepVelocity=sqrt(newton->maxVelocitySq)*sweepFactor; int stride=-1; > + if(sweepVelocity>0) { > + > stride=max(1,int((verletDist/sweepVelocity)/scene->dt)); > + > boundDispatcher->sweepDist=scene->dt*(stride-1)*sweepVelocity; > + } else { // no motion > + > boundDispatcher->sweepDist=0; // nothing moves, no need to make bboxes larger > + } > + } > + #else > Real > sweepVelocity=sqrt(newton->maxVelocitySq)*sweepFactor; int stride=-1; > if(sweepVelocity>0) { > > stride=max(1,int((verletDist/sweepVelocity)/scene->dt)); > @@ -212,6 +263,9 @@ > } > LOG_DEBUG(scene->time<<"s: stride > ≈"<<stride<<"; maxVelocity="<<sqrt(newton->maxVelocitySq)<<", > sweepDist="<<boundDispatcher->sweepDist); > fastestBodyMaxDist=0; // reset > + #endif > + > + > } else { // nBins>=1 > if(!newton->velocityBins){ > newton->velocityBins=shared_ptr<VelocityBins>(new > VelocityBins(nBins,newton->maxVelocitySq,binCoeff,binOverlap)); } > if(!boundDispatcher->velocityBins) > boundDispatcher->velocityBins=newton->velocityBins; > @@ -235,9 +289,16 @@ > const shared_ptr<Body>& b=Body::byId(id,scene); > if(likely(b)){ > const shared_ptr<Bound>& bv=b->bound; > + #ifdef ORI_VERLET > + if (oriVerlet){ > + if (bv && bv->isBounding) > {BBj[i].isBounding=true; continue;} > + else BBj[i].isBounding=false;} > + #endif > // coordinate is min/max if has > bounding volume, otherwise both are the position. Add periodic shift so that > we are inside the cell > // watch out for the parentheses > around ?: within ?: (there was unwanted conversion of the Reals to bools!) > + > > BBj[i].coord=((BBj[i].flags.hasBB=((bool)bv)) ? (BBj[i].flags.isMin ? > bv->min[j] : bv->max[j]) : (b->state->pos[j])) - (periodic ? > BBj.cellDim*BBj[i].period : 0.); > + > } else { BBj[i].flags.hasBB=false; /* for > vanished body, keep the coordinate as-is, to minimize inversions. */ } > // if initializing periodic, shift coords & > record the period into BBj[i].period > if(doInitSort && periodic) { > @@ -251,6 +312,9 @@ > const shared_ptr<Body>& b=Body::byId(id,scene); > if(likely(b)){ > const shared_ptr<Bound>& bv=b->bound; > + #ifdef ORI_VERLET > + if (oriVerlet && bv && bv->isBounding) continue; > + #endif > if(likely(bv)) { > memcpy(&minima[3*id],&bv->min,3*sizeof(Real)); > memcpy(&maxima[3*id],&bv->max,3*sizeof(Real)); } // ⇐ faster than 6 > assignments > else{ const Vector3r& pos=b->state->pos; > memcpy(&minima[3*id],&pos,3*sizeof(Real)); > memcpy(&maxima[3*id],&pos,3*sizeof(Real)); } > } else { memset(&minima[3*id],0,3*sizeof(Real)); > memset(&maxima[3*id],0,3*sizeof(Real)); } > > === modified file 'pkg/common/InsertionSortCollider.hpp' > --- pkg/common/InsertionSortCollider.hpp 2011-01-09 16:34:50 +0000 > +++ pkg/common/InsertionSortCollider.hpp 2011-04-26 08:47:23 +0000 > @@ -68,7 +68,7 @@ > > > // #define this macro to enable timing within this engine > -//#define ISC_TIMING > +// #define ISC_TIMING > > // #define to turn on some tracing information for the periodic part > // all code under this can be probably removed at some point, when the > collider will have been tested thoroughly > @@ -90,6 +90,9 @@ > Real coord; > //! id of the body this bound belongs to > Body::id_t id; > + #ifdef ORI_VERLET > + bool isBounding; > + #endif > //! periodic cell coordinate > int period; > //! is it the minimum (true) or maximum (false) bound? > @@ -152,12 +155,19 @@ > */ > void insertionSort(VecBounds& v,InteractionContainer*,Scene*,bool > doCollide=true); > void > handleBoundInversion(Body::id_t,Body::id_t,InteractionContainer*,Scene*); > - bool spatialOverlap(Body::id_t,Body::id_t) const; > +// bool spatialOverlap(Body::id_t,Body::id_t) const; > > // periodic variants > void insertionSortPeri(VecBounds& v,InteractionContainer*,Scene*,bool > doCollide=true); > void > handleBoundInversionPeri(Body::id_t,Body::id_t,InteractionContainer*,Scene*); > bool spatialOverlapPeri(Body::id_t,Body::id_t,Scene*,Vector3i&) const; > + inline bool spatialOverlap(const Body::id_t& id1, const Body::id_t& > id2) const { > + assert(!periodic); > + return (minima[3*id1+0]<=maxima[3*id2+0]) && > (maxima[3*id1+0]>=minima[3*id2+0]) && > + (minima[3*id1+1]<=maxima[3*id2+1]) && > (maxima[3*id1+1]>=minima[3*id2+1]) && > + (minima[3*id1+2]<=maxima[3*id2+2]) && > (maxima[3*id1+2]>=minima[3*id2+2]); > +} > + > static Real cellWrap(const Real, const Real, const Real, int&); > static Real cellWrapRel(const Real, const Real, const Real); > > @@ -199,7 +209,12 @@ > ", > ((int,sortAxis,0,,"Axis for the initial contact detection.")) > ((bool,sortThenCollide,false,,"Separate sorting and colliding > phase; it is MUCH slower, but all interactions are processed at every step; > this effectively makes the collider non-persistent, not remembering last > state. (The default behavior relies on the fact that inversions during > insertion sort are overlaps of bounding boxes that just started/ceased to > exist, and only processes those; this makes the collider much more > efficient.)")) > - ((Real,verletDist,((void)"Automatically > initialized",-.05),,"Length by which to enlarge particle bounds, to avoid > running collider at every step. Stride disabled if zero. Negative value will > trigger automatic computation, so that the real value will be |verletDist| × > minimum spherical particle radius; if there are no spherical particles, it > will be disabled.")) > + #ifdef ORI_VERLET > + ((bool,oriVerlet,true,,"Compare Verlet distance with > displacement instead of velocity (only used if nBins<=0)")) > + ((int,targetInterv,-1,,"(experimental) Target number of > iterations between bound update, used to define a smaller sweep distance for > slower grains if >0, else always use 1*verletDist. Only used if > oriVerlet=true.")) > + ((Real,updatingDispFactor,-1,,"(experimental) Displacement > factor used to trigger bound update when oriVerlet=true: the bound is updated > only if updatingDispFactor*disp>sweepDist when >0, else all bounds are > updated.")) > + #endif > + ((Real,verletDist,((void)"Automatically > initialized",-.15),,"Length by which to enlarge particle bounds, to avoid > running collider at every step. Stride disabled if zero. Negative value will > trigger automatic computation, so that the real value will be |verletDist| × > minimum spherical particle radius; if there are no spherical particles, it > will be disabled.")) > ((Real,sweepFactor,1.05,,"Overestimation factor for the sweep > velocity; must be >=1.0. Has no influence on verletDist, only on the computed > stride. [DEPRECATED, is used only when bins are not used].")) > ((Real,fastestBodyMaxDist,-1,,"Maximum displacement of the > fastest body since last run; if >= verletDist, we could get out of bboxes and > will trigger full run. DEPRECATED, was only used without bins. |yupdate|")) > ((int,nBins,5,,"Number of velocity bins for striding. If <=0, > bin-less strigin is used (this is however DEPRECATED).")) > > === modified file 'pkg/common/InteractionLoop.cpp' > --- pkg/common/InteractionLoop.cpp 2011-02-27 14:26:15 +0000 > +++ pkg/common/InteractionLoop.cpp 2011-04-26 08:47:23 +0000 > @@ -103,7 +103,11 @@ > > bool swap=false; > // IGeomDispatcher > + #ifdef ORI_VERLET > + if(unlikely(!I->functorCache.geom)){ > + #else > if(unlikely(!I->functorCache.geom || !I->functorCache.phys)){ > + #endif > > I->functorCache.geom=geomDispatcher->getFunctor2D(b1_->shape,b2_->shape,swap); > // returns NULL ptr if no functor exists; remember > that and shortcut > if(!I->functorCache.geom) > {I->functorCache.geomExists=false; continue; } > @@ -112,10 +116,10 @@ > // arguments for the geom functor are in the reverse order > (dispatcher would normally call goReverse). > // we don't remember the fact that is reverse, so we swap > bodies within the interaction > // and can call go in all cases > - if(unlikely(swap)){I->swapOrder(); } > + if(unlikely(swap)){I->swapOrder();} > // body pointers must be updated, in case we swapped > - const shared_ptr<Body>& b1=Body::byId(I->getId1(),scene); > - const shared_ptr<Body>& b2=Body::byId(I->getId2(),scene); > + const shared_ptr<Body>& b1=swap?b2_:b1_; > + const shared_ptr<Body>& b2=swap?b1_:b2_; > > assert(I->functorCache.geom); > bool wasReal=I->isReal(); > > === modified file 'pkg/dem/NewtonIntegrator.cpp' > --- pkg/dem/NewtonIntegrator.cpp 2011-04-22 09:01:59 +0000 > +++ pkg/dem/NewtonIntegrator.cpp 2011-04-26 08:47:23 +0000 > @@ -9,7 +9,6 @@ > #include<yade/pkg/dem/NewtonIntegrator.hpp> > #include<yade/core/Scene.hpp> > #include<yade/pkg/dem/Clump.hpp> > -#include<yade/pkg/common/VelocityBins.hpp> > #include<yade/lib/base/Math.hpp> > > YADE_PLUGIN((NewtonIntegrator)); > @@ -66,7 +65,19 @@ > maxVelocitySq=max(maxVelocitySq,state->vel.squaredNorm()); > #endif > } > - > +#ifdef ORI_VERLET > +void NewtonIntegrator::saveMaximaDisplacement(const shared_ptr<Body>& b){ > + Vector3r disp=b->state->pos-b->bound->refPos; > + Real > maxDisp=max(abs(disp[0]),max(abs(disp[1]),abs(disp[2])));//b->bound->sweepLength; > + if (maxDisp<=b->bound->sweepLength) b->bound->isBounding = true; else > b->bound->isBounding = false; > + if (b->bound->sweepLength>0) maxDisp/=b->bound->sweepLength; else > maxDisp=(maxDisp>0)?2:0; > + #ifdef YADE_OPENMP > + Real& thrMaxVSq=threadMaxVelocitySq[omp_get_thread_num()]; > thrMaxVSq=max(thrMaxVSq,maxDisp); > + #else > + maxVelocitySq=max(maxVelocitySq,maxDisp); > + #endif > +} > +#endif > void NewtonIntegrator::action() > { > scene->forces.sync(); > @@ -108,21 +119,7 @@ > if(unlikely(!b || b->isClumpMember())) continue; > > State* state=b->state.get(); const Body::id_t& > id=b->getId(); > - Vector3r f=Vector3r::Zero(), m=Vector3r::Zero(); > - // clumps forces > - if(b->isClump()) { > - > b->shape->cast<Clump>().addForceTorqueFromMembers(state,scene,f,m); > - #ifdef YADE_OPENMP > - //it is safe here, since onky one thread will > read/write > - scene->forces.getTorqueUnsynced(id)+=m; > - scene->forces.getForceUnsynced(id)+=f; > - #else > - scene->forces.addTorque(id,m); > - scene->forces.addForce(id, f); > - #endif > - } > - //in most cases, the initial force on clumps will > zero and next line is not changing f and m, but make sure we don't miss > something (e.g. user defined forces on clumps) > - f=scene->forces.getForce(id); > m=scene->forces.getTorque(id); > + Vector3r f=scene->forces.getForce(id), > m=scene->forces.getTorque(id); > #ifdef YADE_DEBUG > if(isnan(f[0])||isnan(f[1])||isnan(f[2])) > throw runtime_error(("NewtonIntegrator: NaN force acting on > #"+lexical_cast<string>(id)+".").c_str()); > if(isnan(m[0])||isnan(m[1])||isnan(m[2])) > throw runtime_error(("NewtonIntegrator: NaN torque acting on > #"+lexical_cast<string>(id)+".").c_str()); > @@ -134,8 +131,6 @@ > // in aperiodic boundaries, it is equal to absolute > velocity > Vector3r > fluctVel=isPeriodic?scene->cell->bodyFluctuationVel(b->state->pos,b->state->vel):state->vel; > > - > - > // numerical damping & kinetic energy > if(unlikely(trackEnergy)) > updateEnergy(b,state,fluctVel,f,m); > > @@ -144,6 +139,8 @@ > > // for particles not totally blocked, compute > accelerations; otherwise, the computations would be useless > if (state->blockedDOFs!=State::DOF_ALL) { > + // forces > + if(b->isClump()) > b->shape->cast<Clump>().addForceTorqueFromMembers(state,scene,f,m); > // linear acceleration > Vector3r > linAccel=computeAccel(f,state->mass,state->blockedDOFs); > cundallDamp2nd(dt,f,fluctVel,linAccel); > @@ -163,7 +160,10 @@ > leapfrogTranslate(state,id,dt); > if(!useAspherical) > leapfrogSphericalRotate(state,id,dt); > else leapfrogAsphericalRotate(state,id,dt,m); > - > + #ifdef ORI_VERLET > + if (oriVerlet) saveMaximaDisplacement(b); > + else > + #endif > saveMaximaVelocity(id,state); > // move individual members of the clump, save maxima > velocity (for collider stride) > if(b->isClump()) Clump::moveMembers(b,scene,this); > > === modified file 'pkg/dem/NewtonIntegrator.hpp' > --- pkg/dem/NewtonIntegrator.hpp 2011-04-22 09:01:59 +0000 > +++ pkg/dem/NewtonIntegrator.hpp 2011-04-26 08:47:23 +0000 > @@ -11,6 +11,7 @@ > #include<yade/core/Interaction.hpp> > #include<yade/lib/base/Math.hpp> > #include<yade/pkg/common/Callbacks.hpp> > +#include<yade/pkg/common/VelocityBins.hpp> > #ifdef YADE_OPENMP > #include<omp.h> > #endif > @@ -46,6 +47,9 @@ > public: > // function to save maximum velocity, for the verlet-distance > optimization > void saveMaximaVelocity(const Body::id_t& id, State* state); > + #ifdef ORI_VERLET > + void saveMaximaDisplacement(const shared_ptr<Body>& b); > + #endif > #ifdef YADE_OPENMP > vector<Real> threadMaxVelocitySq; > #endif > @@ -56,6 +60,7 @@ > ((Real,damping,0.2,,"damping coefficient for Cundall's non > viscous damping (see [Chareyre2005]_) [-]")) > ((Real,maxVelocitySq,NaN,,"store square of max. velocity, for > informative purposes; computed again at every step. |yupdate|")) > ((bool,exactAsphericalRot,true,,"Enable more exact body > rotation integrator for :yref:`aspherical bodies<Body.aspherical>` *only*, > using formulation from [Allen1989]_, pg. 89.")) > + ((bool,oriVerlet,false,,"Compare Verlet distance with > displacement instead of velocity (updated by the collider)")) > ((Matrix3r,prevVelGrad,Matrix3r::Zero(),,"Store previous > velocity gradient (:yref:`Cell::velGrad`) to track acceleration. |yupdate|")) > #ifdef YADE_BODY_CALLBACK > ((vector<shared_ptr<BodyCallback> >,callbacks,,,"List > (std::vector in c++) of :yref:`BodyCallbacks<BodyCallback>` which will be > called for each body as it is being processed.")) > > > _______________________________________________ > Mailing list: https://launchpad.net/~yade-dev > Post to : [email protected] > Unsubscribe : https://launchpad.net/~yade-dev > More help : https://help.launchpad.net/ListHelp > > _______________________________________________ Mailing list: https://launchpad.net/~yade-dev Post to : [email protected] Unsubscribe : https://launchpad.net/~yade-dev More help : https://help.launchpad.net/ListHelp

