yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #12095
[Branch ~yade-pkg/yade/git-trunk] Rev 3683: Non invasive refactoring of InsertionSortCollider
------------------------------------------------------------
revno: 3683
committer: Anton Gladky <gladky.anton@xxxxxxxxx>
timestamp: Sat 2015-06-13 09:40:38 +0200
message:
Non invasive refactoring of InsertionSortCollider
Remove unneeded struct, replace by a simple variables to
escape overhead.
Some implementations are moved from header to cpp-file.
modified:
pkg/common/InsertionSortCollider.cpp
pkg/common/InsertionSortCollider.hpp
pkg/dem/GeneralIntegratorInsertionSortCollider.cpp
--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== modified file 'pkg/common/InsertionSortCollider.cpp'
--- pkg/common/InsertionSortCollider.cpp 2014-10-15 06:44:01 +0000
+++ pkg/common/InsertionSortCollider.cpp 2015-06-13 07:40:38 +0000
@@ -30,22 +30,28 @@
assert(!periodic);
assert(v.size==(long)v.vec.size());
for(long i=1; 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 bool isMin=viInit.flags.isMin;
+ const Bounds viInit=v[i];
+ long j=i-1;
+ /* cache hasBB; otherwise 1% overall performance hit */ const bool viInitBB=viInit.hasBB;
+ const bool isMin=viInit.isMin;
while(j>=0 && v[j]>viInit){
v[j+1]=v[j];
#ifdef PISC_DEBUG
if(watchIds(v[j].id,viInit.id)) cerr<<"Swapping #"<<v[j].id<<" with #"<<viInit.id<<" ("<<setprecision(80)<<v[j].coord<<">"<<setprecision(80)<<viInit.coord<<" along axis "<<v.axis<<")"<<endl;
- if(v[j].id==viInit.id){ cerr<<"Inversion of body #"<<v[j].id<<" with itself, "<<v[j].flags.isMin<<" & "<<viInit.flags.isMin<<", isGreater "<<(v[j]>viInit)<<", "<<(v[j].coord>viInit.coord)<<endl; j--; continue; }
+ if(v[j].id==viInit.id){
+ cerr<<"Inversion of body #"<<v[j].id<<" with itself, "<<v[j].isMin<<" & "<<
+ viInit.isMin<<", isGreater "<<(v[j]>viInit)<<", "<<(v[j].coord>viInit.coord)<<endl;
+ j--;
+ continue;
+ }
#endif
// 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
// skip bounds with same isMin flags, since inversion doesn't imply anything in that case
- if(isMin && !v[j].flags.isMin && doCollide && viInitBB && v[j].flags.hasBB && (viInit.id!=v[j].id)) {
- /*if (isMin)*/ handleBoundInversion(viInit.id,v[j].id,interactions,scene);
-// else handleBoundSplit(viInit.id,v[j].id,interactions,scene);
+ if(isMin && !v[j].isMin && doCollide && viInitBB && v[j].hasBB && (viInit.id!=v[j].id)) {
+ handleBoundInversion(viInit.id,v[j].id,interactions,scene);
}
j--;
}
@@ -89,11 +95,13 @@
for (unsigned k=0; k<nChunks;k++) {
int threadNum = omp_get_thread_num();
for(long i=chunks[k]+1; i<chunks[k+1]; i++){
- const Bounds viInit=v[i]; long j=i-1; const bool viInitBB=viInit.flags.hasBB;
- const bool isMin=viInit.flags.isMin;
+ const Bounds viInit=v[i];
+ long j=i-1;
+ const bool viInitBB=viInit.hasBB;
+ const bool isMin=viInit.isMin;
while(j>=chunks[k] && v[j]>viInit){
v[j+1]=v[j];
- if(isMin && !v[j].flags.isMin && doCollide && viInitBB && v[j].flags.hasBB && (viInit.id!=v[j].id)) {
+ if(isMin && !v[j].isMin && doCollide && viInitBB && v[j].hasBB && (viInit.id!=v[j].id)) {
const Body::id_t& id1 = v[j].id; const Body::id_t& id2 = viInit.id;
if (spatialOverlap(id1,id2) && Collider::mayCollide(Body::byId(id1,scene).get(),Body::byId(id2,scene).get()) && !interactions->found(id1,id2))
newInteractions[threadNum].push_back(std::pair<Body::id_t,Body::id_t>(v[j].id,viInit.id));
@@ -115,12 +123,14 @@
long halfChunkEnd = long(i+chunkSize*0.5);
for(; i<halfChunkEnd; i++){
if (!(v[i]<v[i-1])) break; //contiguous chunks now connected consistently
- 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;
+ const Bounds viInit=v[i];
+ long j=i-1;
+ /* cache hasBB; otherwise 1% overall performance hit */ const bool viInitBB=viInit.hasBB;
+ const bool isMin=viInit.isMin;
while(j>=halfChunkStart && viInit<v[j]){
v[j+1]=v[j];
- if(isMin && !v[j].flags.isMin && doCollide && viInitBB && v[j].flags.hasBB && (viInit.id!=v[j].id)) {
+ if(isMin && !v[j].isMin && doCollide && viInitBB && v[j].hasBB && (viInit.id!=v[j].id)) {
const Body::id_t& id1 = v[j].id; const Body::id_t& id2 = viInit.id;
//FIXME: do we need the check with found(id1,id2) here? It is checked again below...
if (spatialOverlap(id1,id2) && Collider::mayCollide(Body::byId(id1,scene).get(),Body::byId(id2,scene).get()) && !interactions->found(id1,id2))
@@ -150,7 +160,7 @@
it=BB[0].vec.begin(),et=BB[0].vec.end(); it < et; ++it)
{
if (it->coord > bv.max[0]) break;
- if (!it->flags.isMin || !it->flags.hasBB) continue;
+ if (!it->isMin || !it->hasBB) continue;
int offset = 3*it->id;
const shared_ptr<Body>& b=Body::byId(it->id,scene);
if(!b || !b->bound) continue;
@@ -293,15 +303,16 @@
const shared_ptr<Bound>& bv=b->bound;
// 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!)
- BBji.coord=((BBji.flags.hasBB=((bool)bv)) ? (BBji.flags.isMin ? bv->min[j] : bv->max[j]) : (b->state->pos[j])) - (periodic ? BBj.cellDim*BBji.period : 0.);
+ BBji.coord=((BBji.hasBB=((bool)bv)) ? (BBji.isMin ? bv->min[j] : bv->max[j]) : (b->state->pos[j])) - (periodic ? BBj.cellDim*BBji.period : 0.);
// if initializing periodic, shift coords & record the period into BBj[i].period
if(doInitSort && periodic) BBji.coord=cellWrap(BBji.coord,0,BBj.cellDim,BBji.period);
// for each body, copy its minima and maxima, for quick checks of overlaps later
//bounds have been all updated when j==0, we can safely copy them here when j==1
- if (BBji.flags.isMin && j==1 &&bv) {
- memcpy(&minima[3*id],&bv->min,3*sizeof(Real)); memcpy(&maxima[3*id],&bv->max,3*sizeof(Real));
- }
- } else { BBj[i].flags.hasBB=false; /* for vanished body, keep the coordinate as-is, to minimize inversions. */ }
+ if (BBji.isMin && j==1 &&bv) {
+ memcpy(&minima[3*id],&bv->min,3*sizeof(Real));
+ memcpy(&maxima[3*id],&bv->max,3*sizeof(Real));
+ }
+ } else { BBj[i].hasBB=false; /* for vanished body, keep the coordinate as-is, to minimize inversions. */ }
}
}
@@ -352,13 +363,13 @@
for(long i=0; i<2*nBodies; i++){
// start from the lower bound (i.e. skipping upper bounds)
// skip bodies without bbox, because they don't collide
- if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
+ if(!(V[i].isMin && V[i].hasBB)) continue;
const Body::id_t& iid=V[i].id;
// go up until we meet the upper bound
for(long j=i+1; /* handle case 2. of swapped min/max */ j<2*nBodies && V[j].id!=iid; j++){
const Body::id_t& jid=V[j].id;
// take 2 of the same condition (only handle collision [min_i..max_i]+min_j, not [min_i..max_i]+min_i (symmetric)
- if(!(V[j].flags.isMin && V[j].flags.hasBB)) continue;
+ if(!(V[j].isMin && V[j].hasBB)) continue;
if (spatialOverlap(iid,jid) && Collider::mayCollide(Body::byId(iid,scene).get(),Body::byId(jid,scene).get()) ){
#ifdef YADE_OPENMP
unsigned int threadNum = omp_get_thread_num();
@@ -378,13 +389,13 @@
#endif
} else { // periodic case: see comments above
for(long i=0; i<2*nBodies; i++){
- if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
+ if(!(V[i].isMin && V[i].hasBB)) continue;
const Body::id_t& iid=V[i].id;
long cnt=0;
// we might wrap over the periodic boundary here; that's why the condition is different from the aperiodic case
for(long j=V.norm(i+1); V[j].id!=iid; j=V.norm(j+1)){
const Body::id_t& jid=V[j].id;
- if(!(V[j].flags.isMin && V[j].flags.hasBB)) continue;
+ if(!(V[j].isMin && V[j].hasBB)) continue;
handleBoundInversionPeri(iid,jid,interactions,scene);
if(cnt++>2*(long)nBodies){ LOG_FATAL("Uninterrupted loop in the initial sort?"); throw std::logic_error("loop??"); }
}
@@ -424,8 +435,11 @@
if(v[i_1].coord<=iCmpCoord) continue;
// vi is the copy that will travel down the list, while other elts go up
// if will be placed in the list only at the end, to avoid extra copying
- int j=i_1; Bounds vi=v[i]; const bool viHasBB=vi.flags.hasBB;
- const bool isMin=v[i].flags.isMin;
+ int j=i_1;
+ Bounds vi=v[i];
+ const bool viHasBB=vi.hasBB;
+ const bool isMin=v[i].isMin;
+
while(v[j].coord>vi.coord + /* wrap for elt just below split */ (v.norm(j+1)==loIdx ? v.cellDim : 0)){
long j1=v.norm(j+1);
// OK, now if many bodies move at the same pace through the cell and at one point, there is inversion,
@@ -441,14 +455,8 @@
// inversions close the the split need special care
if(j==loIdx && vi.coord<0) { vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
else if(j1==loIdx) { vNew.period+=1; vNew.coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
- if(isMin && !v[j].flags.isMin && (doCollide && viHasBB && v[j].flags.hasBB)){
+ if(isMin && !v[j].isMin && (doCollide && viHasBB && v[j].hasBB)){
// see https://bugs.launchpad.net/yade/+bug/669095 and similar problem in aperiodic insertionSort
- #if 0
- if(vi.id==vNew.id){
- LOG_FATAL("Inversion of body's #"<<vi.id<<" boundary with its other boundary, "<<v[j].coord<<" meets "<<vi.coord);
- throw runtime_error(__FILE__ ": Body's boundary metting its opposite boundary.");
- }
- #endif
if((vi.id!=vNew.id)) handleBoundInversionPeri(vi.id,vNew.id,interactions,scene);
}
j=v.norm(j-1);
@@ -537,6 +545,81 @@
return true;
}
+inline bool InsertionSortCollider::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]);
+}
+
+bool InsertionSortCollider::shouldBeErased(Body::id_t id1, Body::id_t id2, Scene* rb) const {
+ if(!periodic) {
+ return !spatialOverlap(id1,id2);
+ } else {
+ Vector3i periods;
+ return !spatialOverlapPeri(id1,id2,rb,periods);
+ }
+}
+
+void InsertionSortCollider::invalidatePersistentData() {
+ for(int i=0; i<3; i++) {
+ BB[i].vec.clear();
+ BB[i].size=0;
+ }
+}
+
+bool InsertionSortCollider::Bounds::operator<(const Bounds& b) const {
+ /* handle special case of zero-width bodies, which could otherwise get min/max swapped in the unstable std::sort */
+ if(id==b.id && coord==b.coord) return isMin;
+ return coord<b.coord;
+}
+
+bool InsertionSortCollider::Bounds::operator>(const Bounds& b) const {
+ if(id==b.id && coord==b.coord) return !isMin;
+ return coord>b.coord;
+}
+
+#ifdef PISC_DEBUG
+bool InsertionSortCollider::Bounds::watchIds(Body::id_t id1,Body::id_t id2) const {
+ return (watch1<0 &&(watch2==id1||watch2==id2))||
+ (watch2<0 && (watch1==id1||watch1==id2))||
+ (watch1==id1 && watch2==id2)||
+ (watch1==id2 && watch2==id1);
+}
+#endif
+
+void InsertionSortCollider::VecBounds::updatePeriodicity(Scene* scene){
+ assert(scene->isPeriodic);
+ assert(axis>=0 && axis <=2);
+ cellDim=scene->cell->getSize()[axis];
+}
+
+long InsertionSortCollider::VecBounds::norm(long i) const {
+ if(i<0) i+=size;
+ long ret=i%size;
+ assert(ret>=0 && ret<size);
+ return ret;
+}
+
+void InsertionSortCollider::VecBounds::dump(ostream& os) {
+ string ret;
+ for(size_t i=0; i<vec.size(); i++) {
+ os<<((long)i==loIdx?"@@ ":"")<<vec[i].coord<<"(id="<<vec[i].id
+ <<","<<(vec[i].isMin?"min":"max")<<",p"<<vec[i].period<<") ";
+ }
+ os<<endl;
+}
+
+InsertionSortCollider::Bounds& InsertionSortCollider::VecBounds::operator[](long idx) {
+ assert(idx<size && idx>=0);
+ return vec[idx];
+}
+
+const InsertionSortCollider::Bounds& InsertionSortCollider::VecBounds::operator[](long idx) const {
+ assert(idx<size && idx>=0);
+ return vec[idx];
+}
+
boost::python::tuple InsertionSortCollider::dumpBounds(){
boost::python::list bl[3]; // 3 bound lists, inserted into the tuple at the end
for(int axis=0; axis<3; axis++){
@@ -544,11 +627,11 @@
if(periodic){
for(long i=0; i<V.size; i++){
long ii=V.norm(i); // start from the period boundary
- bl[axis].append(boost::python::make_tuple(V[ii].coord,(V[ii].flags.isMin?-1:1)*V[ii].id,V[ii].period));
+ bl[axis].append(boost::python::make_tuple(V[ii].coord,(V[ii].isMin?-1:1)*V[ii].id,V[ii].period));
}
} else {
for(long i=0; i<V.size; i++){
- bl[axis].append(boost::python::make_tuple(V[i].coord,(V[i].flags.isMin?-1:1)*V[i].id));
+ bl[axis].append(boost::python::make_tuple(V[i].coord,(V[i].isMin?-1:1)*V[i].id));
}
}
}
=== modified file 'pkg/common/InsertionSortCollider.hpp'
--- pkg/common/InsertionSortCollider.hpp 2015-05-22 05:46:49 +0000
+++ pkg/common/InsertionSortCollider.hpp 2015-06-13 07:40:38 +0000
@@ -86,30 +86,24 @@
friend class GeneralIntegratorInsertionSortCollider;
- //! struct for storing bounds of bodies
+ // struct for storing bounds of bodies
struct Bounds{
- //! coordinate along the given sortAxis
+ // coordinate along the given sortAxis
Real coord;
//! id of the body this bound belongs to
Body::id_t id;
- //! periodic cell coordinate
+ // periodic cell coordinate
int period;
- //! is it the minimum (true) or maximum (false) bound?
- struct{ unsigned hasBB:1; unsigned isMin:1; } flags;
- Bounds(Real coord_, Body::id_t id_, bool isMin): coord(coord_), id(id_), period(0){ flags.isMin=isMin; }
- bool operator<(const Bounds& b) const {
- /* handle special case of zero-width bodies, which could otherwise get min/max swapped in the unstable std::sort */
- if(id==b.id && coord==b.coord) return flags.isMin;
- return coord<b.coord;
- }
- bool operator>(const Bounds& b) const {
- if(id==b.id && coord==b.coord) return !flags.isMin;
- return coord>b.coord;
- }
+ // is it the minimum (true) or maximum (false) bound?
+ bool hasBB=true;
+ bool isMin=true;
+ Bounds(Real coord_, Body::id_t id_, bool _isMin): coord(coord_), id(id_), period(0), isMin(_isMin){};
+ bool operator<(const Bounds& b) const;
+ bool operator>(const Bounds& b) const;
};
#ifdef PISC_DEBUG
int watch1, watch2;
- bool watchIds(Body::id_t id1,Body::id_t id2) const { return (watch1<0 &&(watch2==id1||watch2==id2))||(watch2<0 && (watch1==id1||watch1==id2))||(watch1==id1 && watch2==id2)||(watch1==id2 && watch2==id1); }
+ bool watchIds(Body::id_t,Body::id_t) const;
#endif
// we need this to find out about current maxVelocitySq
shared_ptr<NewtonIntegrator> newton;
@@ -125,37 +119,32 @@
long size;
// index of the lowest coordinate element, before which the container wraps
long loIdx;
- Bounds& operator[](long idx){ assert(idx<size && idx>=0); return vec[idx]; }
- const Bounds& operator[](long idx) const { assert(idx<size && idx>=0); return vec[idx]; }
+ Bounds& operator[](long);
+ const Bounds& operator[](long idx) const;
// update number of bodies, periodic properties and size from Scene
- void updatePeriodicity(Scene* scene){
- assert(scene->isPeriodic);
- assert(axis>=0 && axis <=2);
- cellDim=scene->cell->getSize()[axis];
- }
+ void updatePeriodicity(Scene*);
// normalize given index to the right range (wraps around)
- long norm(long i) const { if(i<0) i+=size; long ret=i%size; assert(ret>=0 && ret<size); return ret;}
+ long norm(long) const;
VecBounds(): axis(-1), size(0), loIdx(0){}
- void dump(ostream& os){ string ret; for(size_t i=0; i<vec.size(); i++) os<<((long)i==loIdx?"@@ ":"")<<vec[i].coord<<"(id="<<vec[i].id<<","<<(vec[i].flags.isMin?"min":"max")<<",p"<<vec[i].period<<") "; os<<endl;}
+ void dump(ostream&);
};
private:
- //! storage for bounds
+ // storage for bounds
VecBounds BB[3];
- //! storage for bb maxima and minima
+ // storage for bb maxima and minima
std::vector<Real> maxima, minima;
- //! Whether the Scene was periodic (to detect the change, which shouldn't happen, but shouldn't crash us either)
+ // Whether the Scene was periodic (to detect the change, which shouldn't happen, but shouldn't crash us either)
bool periodic;
// return python representation of the BB struct, as ([...],[...],[...]).
boost::python::tuple dumpBounds();
- /*! sorting routine; insertion sort is very fast for strongly pre-sorted lists, which is our case
- http://en.wikipedia.org/wiki/Insertion_sort has the algorithm and other details
+ /* sorting routine; insertion sort is very fast for strongly pre-sorted lists, which is our case
+ http://en.wikipedia.org/wiki/Insertion_sort has the algorithm and other details
*/
void insertionSort(VecBounds& v,InteractionContainer*,Scene*,bool doCollide=true);
void insertionSortParallel(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;
// periodic variants
void insertionSortPeri(VecBounds& v,InteractionContainer*,Scene*,bool doCollide=true);
@@ -163,27 +152,18 @@
void handleBoundSplit(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]);
- }
+ bool spatialOverlap(const Body::id_t& id1, const Body::id_t& id2) const;
static Real cellWrap(const Real, const Real, const Real, int&);
static Real cellWrapRel(const Real, const Real, const Real);
-
public:
- //! Predicate called from loop within InteractionContainer::erasePending
- bool shouldBeErased(Body::id_t id1, Body::id_t id2, Scene* rb) const {
- if(!periodic) return !spatialOverlap(id1,id2);
- else { Vector3i periods; return !spatialOverlapPeri(id1,id2,rb,periods); }
- }
+ // Predicate called from loop within InteractionContainer::erasePending
+ bool shouldBeErased(Body::id_t, Body::id_t, Scene*) const;
virtual bool isActivated();
// force reinitialization at next run
- virtual void invalidatePersistentData(){ for(int i=0; i<3; i++){ BB[i].vec.clear(); BB[i].size=0; }}
+ virtual void invalidatePersistentData();
vector<Body::id_t> probeBoundingVolume(const Bound&);
=== modified file 'pkg/dem/GeneralIntegratorInsertionSortCollider.cpp'
--- pkg/dem/GeneralIntegratorInsertionSortCollider.cpp 2014-10-15 06:44:01 +0000
+++ pkg/dem/GeneralIntegratorInsertionSortCollider.cpp 2015-06-13 07:40:38 +0000
@@ -141,9 +141,9 @@
// 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.);
+ BBj[i].coord=((BBj[i].hasBB=((bool)bv)) ? (BBj[i].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. */ }
+ } else { BBj[i].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) {
BBj[i].coord=cellWrap(BBj[i].coord,0,BBj.cellDim,BBj[i].period);
@@ -195,13 +195,13 @@
for(long i=0; i<2*nBodies; i++){
// start from the lower bound (i.e. skipping upper bounds)
// skip bodies without bbox, because they don't collide
- if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
+ if(!(V[i].isMin && V[i].hasBB)) continue;
const Body::id_t& iid=V[i].id;
// go up until we meet the upper bound
for(long j=i+1; /* handle case 2. of swapped min/max */ j<2*nBodies && V[j].id!=iid; j++){
const Body::id_t& jid=V[j].id;
// take 2 of the same condition (only handle collision [min_i..max_i]+min_j, not [min_i..max_i]+min_i (symmetric)
- if(!V[j].flags.isMin) continue;
+ if(!V[j].isMin) continue;
/* abuse the same function here; since it does spatial overlap check first, it is OK to use it */
handleBoundInversion(iid,jid,interactions,scene);
assert(j<2*nBodies-1);
@@ -209,13 +209,13 @@
}
} else { // periodic case: see comments above
for(long i=0; i<2*nBodies; i++){
- if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
+ if(!(V[i].isMin && V[i].hasBB)) continue;
const Body::id_t& iid=V[i].id;
long cnt=0;
// we might wrap over the periodic boundary here; that's why the condition is different from the aperiodic case
for(long j=V.norm(i+1); V[j].id!=iid; j=V.norm(j+1)){
const Body::id_t& jid=V[j].id;
- if(!V[j].flags.isMin) continue;
+ if(!V[j].isMin) continue;
handleBoundInversionPeri(iid,jid,interactions,scene);
if(cnt++>2*(long)nBodies){ LOG_FATAL("Uninterrupted loop in the initial sort?"); throw std::logic_error("loop??"); }
}
Follow ups