yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01338
[svn] r1815 - trunk/pkg/common/Engine/StandAloneEngine
Author: eudoxos
Date: 2009-06-25 22:54:20 +0200 (Thu, 25 Jun 2009)
New Revision: 1815
Modified:
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
Log:
1. Fix corner case in InsertionSortCollider related to instability of std::sort (quicksort) and bodies having the same upper and lower bounds (facet in the xy plane, for example). Thanks to Anton for providing the crasher.
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-06-24 22:06:24 UTC (rev 1814)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp 2009-06-25 20:54:20 UTC (rev 1815)
@@ -130,7 +130,7 @@
#pragma omp section
std::sort(ZZ.begin(),ZZ.end());
}
- } else {
+ } else { // sortThenCollide
insertionSort(XX,interactions,rb,false); insertionSort(YY,interactions,rb,false); insertionSort(ZZ,interactions,rb,false);
}
// traverse the container along requested axis
@@ -151,6 +151,19 @@
// 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
+ // that means that the upper bound is before the upper one; that can only happen if they
+ // are equal and the unstable std::sort has swapped them. In that case, we need to go reverse
+ // from V[i] until we meet the upper bound and swap the isMin flag
+ if(j==2*nBodies-1){
+ size_t k=i-1;
+ while(V[k].id!=iid && k>0) k--;
+ assert(V[k].id==iid); // if this fails, we didn't meet the other bound in the downwards sense either; that should never happen
+ assert(!V[k].flags.isMin); // the lower bound should be maximum in this (exceptional) case; we will fix that now
+ V[k].flags.isMin=true; V[i].flags.isMin=false;
+ LOG_DEBUG("Swapping coincident min/max of #"<<iid<<" at positions "<<k<<" and "<<i<<"(coords: "<<V[k].coord<<" and "<<V[i].coord);
+ break; // would happen anyways
+ }
}
}
}