yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01794
[Branch ~yade-dev/yade/trunk] Rev 1715: 1. Rewrite 2d dispatching code from scratch
------------------------------------------------------------
revno: 1715
committer: Václav Šmilauer <vaclav@flux>
branch nick: trunk
timestamp: Fri 2009-08-21 13:44:00 +0200
message:
1. Rewrite 2d dispatching code from scratch
2. Expose classIndex to python for indexable classes
3. scripts/test-sphere-facet.py shows how the dispatch matrix fills with data
modified:
gui/py/PythonUI_rc.py
lib/multimethods/DynLibDispatcher.hpp
py/yadeWrapper/yadeWrapper.cpp
scripts/test-sphere-facet.py
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription.
=== modified file 'gui/py/PythonUI_rc.py'
--- gui/py/PythonUI_rc.py 2009-08-18 12:24:49 +0000
+++ gui/py/PythonUI_rc.py 2009-08-21 11:44:00 +0000
@@ -31,7 +31,7 @@
_noPropsClasses=set(['InteractionContainer','BodyContainer','EngineUnit','Engine','MetaEngine'])
# classes that have special wrappers; only the most-bottom ones, with their names as it is in c++
_pyRootClasses=set([
- 'StandAloneEngine','DeusExMachina','GeometricalModel','InteractingGeometry','PhysicalParameters','BoundingVolume','InteractingGeometry','InteractionPhysics','FileGenerator',
+ 'StandAloneEngine','DeusExMachina','GeometricalModel','InteractingGeometry','PhysicalParameters','BoundingVolume','InteractionGeometry','InteractionPhysics','FileGenerator',
'BoundingVolumeEngineUnit','GeometricalModelEngineUnit','InteractingGeometryEngineUnit','InteractionGeometryEngineUnit','InteractionPhysicsEngineUnit','PhysicalParametersEngineUnit','PhysicalActionDamperUnit','PhysicalActionApplierUnit','ConstitutiveLaw'])
# classes for which proxies were already created
_proxiedClasses=set()
=== modified file 'lib/multimethods/DynLibDispatcher.hpp'
--- lib/multimethods/DynLibDispatcher.hpp 2009-08-21 10:06:00 +0000
+++ lib/multimethods/DynLibDispatcher.hpp 2009-08-21 11:44:00 +0000
@@ -456,86 +456,130 @@
return callBacks[ix1][ix2];
}
-
- std::ostream& dumpDispatchMatrix2D(std::ostream& out){
+ std::ostream& dumpDispatchMatrix2D(std::ostream& out, const string& prefix=""){
for(size_t i=0; i<callBacks.size(); i++){
for(size_t j=0; j<callBacks.size(); j++){
- if(callBacks[i][j]) out<<i<<"+"<<j<<" -> "<<callBacks[i][j]->getClassName()<<std::endl;
+ if(callBacks[i][j]) out<<prefix<<i<<"+"<<j<<" -> "<<callBacks[i][j]->getClassName()<<std::endl;
}
}
return out;
}
- std::ostream& dumpDispatchMatrix1D(std::ostream& out){
+ std::ostream& dumpDispatchMatrix1D(std::ostream& out, const string& prefix=""){
for(size_t i=0; i<callBacks.size(); i++){
- if(callBacks[i]) out<<i<<" -> "<<callBacks[i]->getClassName()<<std::endl;
+ if(callBacks[i]) out<<prefix<<i<<" -> "<<callBacks[i]->getClassName()<<std::endl;
}
return out;
}
bool locateMultivirtualFunctor2D(int& index1, int& index2, shared_ptr<BaseClass1>& base1,shared_ptr<BaseClass2>& base2)
{
- index1 = base1->getClassIndex();
- index2 = base2->getClassIndex();
- assert( index1 >= 0 );
- assert( index2 >= 0 );
- #if 0
- if((unsigned)index1>=callBacks.size()) cerr<<__FILE__<<":"<<__LINE__<<" FATAL: Index out of range for class "<<base1->getClassName()<<" (index=="<<index1<<", callBacks.size()=="<<callBacks.size()<<endl;
- if((unsigned)index2>=callBacks[index2].size()) cerr<<__FILE__<<":"<<__LINE__<<" FATAL: Index out of range for class "<<base2->getClassName()<<" (index=="<<index2<<", callBacks[index1].size()=="<<callBacks[index1].size()<<endl;
- #endif
- assert((unsigned int)( index1 ) < callBacks.size());
- assert((unsigned int)( index2 ) < callBacks[index1].size());
- //#define _DISP_TRACE(msg) cerr<<"@DT@"<<__LINE__<<" "<<a<<endl;
+ //#define _DISP_TRACE(msg) cerr<<"@DT@"<<__LINE__<<" "<<msg<<endl;
#define _DISP_TRACE(msg)
+ index1=base1->getClassIndex(); index2 = base2->getClassIndex();
+ assert(index1>=0); assert(index2>=0);
+ assert((unsigned int)(index1)<callBacks.size()); assert((unsigned int)(index2)<callBacks[index1].size());
_DISP_TRACE("arg1: "<<base1->getClassName()<<"="<<index1<<"; arg2: "<<base2->getClassName()<<"="<<index2)
-
- if(callBacks[index1][index2]){
- _DISP_TRACE("Direct hit at ["<<index1<<"]["<<index2<<"] â "<<callBacks[index1][index2]->getClassName());
- return true;
- }
-
- int depth1=1, depth2=1;
- int index1_tmp=base1->getBaseClassIndex(depth1), index2_tmp = base2->getBaseClassIndex(depth2);
- _DISP_TRACE("base classes: "<<base1->getBaseClassName()<<"="<<index1_tmp<<", "<<base2->getBaseClassName()<<"="<<index2_tmp);
- if(index1_tmp == -1) {
- while(1){
- if(index2_tmp == -1){
- _DISP_TRACE("Returning FALSE");
- return false;
- }
- if(callBacks[index1][index2_tmp]){ // FIXME - this is not working, when index1 or index2 is out-of-boundary. I have to resize callBacks and callBacksInfo tables. - this should be a separate function to resize stuff
- callBacksInfo[index1][index2] = callBacksInfo[index1][index2_tmp];
- callBacks [index1][index2] = callBacks [index1][index2_tmp];
-// index2 = index2_tmp;
- _DISP_TRACE("Found callback ["<<index1<<"]["<<index2_tmp<<"] â "<<callBacks[index1][index2_tmp]->getClassName());
- return true;
- }
- index2_tmp = base2->getBaseClassIndex(++depth2);
- _DISP_TRACE("index2_tmp="<<index2_tmp<<" (pushed up)");
- }
- }
- else if(index2_tmp == -1) {
- while(1){
- if(index1_tmp == -1){
- _DISP_TRACE("Returning FALSE");
- return false;
- }
- if(callBacks[index1_tmp][index2]){
- callBacksInfo[index1][index2] = callBacksInfo[index1_tmp][index2];
- callBacks [index1][index2] = callBacks [index1_tmp][index2];
-// index1 = index1_tmp;
- _DISP_TRACE("Found callback ["<<index1_tmp<<"]["<<index2<<"] â "<<callBacks[index1_tmp][index2]->getClassName());
- return true;
- }
- index1_tmp = base1->getBaseClassIndex(++depth1);
- _DISP_TRACE("index1_tmp="<<index1_tmp<<" (pushed up)");
- }
- }
- //else if( index1_tmp != -1 && index2_tmp != -1 )
- _DISP_TRACE("UNDEFINED/AMBIGUOUS, dumping dispatch matrix");
- dumpDispatchMatrix2D(cerr);
- _DISP_TRACE("end matrix dump.")
- throw std::runtime_error("DynLibDispatcher: ambiguous or undefined dispatch for 2d multivirtual function, classes: "+base1->getClassName()+" "+base2->getClassName());
- //return false;
+ #define _FIX_2D_DISPATCHES
+ #ifdef _FIX_2D_DISPATCHES
+ /* This is python pseudocode for the algorithm:
+
+ def ff(x,sum): print x,sum-x,sum
+ for dist in range(0,5):
+ for ix1 in range(0,dist+1): ff(ix1,dist)
+
+ Increase depth sum from 0 up and look for possible matches, of which sum of distances beween the argument and the declared functor arg type equals depth.
+
+ Two matches are considered euqally good (ambiguous) if they have the same depth. That raises exception.
+
+ If both indices are negative (reached the top of hierarchy for that indexable type) and nothing has been found for given depth, raise exception (undefined dispatch).
+
+ FIXME: by the original design, callBacks don't distinguish between dispatch that was already looked for,
+ but is undefined and dispatch that was never looked for before. This means that there can be lot of useless lookups;
+ e.g. if MetaInteractingGeometry2AABB is not in BoundingVoumeMetaEngine, it is looked up at every step.
+
+ */
+ if(callBacks[index1][index2]){ _DISP_TRACE("Direct hit at ["<<index1<<"]["<<index2<<"] â "<<callBacks[index1][index2]->getClassName()); return true; }
+ int foundIx1,foundIx2; int maxDp1=-1, maxDp2=-1;
+ // if(base1->getBaseClassIndex(0)<0) maxDp1=0; if(base2->getBaseClassIndex(0)<0) maxDp2=0;
+ for(int dist=1; ; dist++){
+ bool distTooBig=true;
+ foundIx1=foundIx2=-1; // found no dispatch at this depth yet
+ for(int dp1=0; dp1<=dist; dp1++){
+ int dp2=dist-dp1;
+ if((maxDp1>=0 && dp1>maxDp1) || (maxDp2>=0 && dp2>maxDp2)) continue;
+ _DISP_TRACE(" Trying indices with depths "<<dp1<<" and "<<dp2<<", dist="<<dist);
+ int ix1=dp1>0?base1->getBaseClassIndex(dp1):index1, ix2=dp2>0?base2->getBaseClassIndex(dp2):index2;
+ if(ix1<0) maxDp1=dp1; if(ix2<0) maxDp2=dp2;
+ if(ix1<0 || ix2<0) continue; // hierarchy height exceeded in either dimension
+ distTooBig=false;
+ if(callBacks[ix1][ix2]){
+ if(foundIx1!=-1 && callBacks[foundIx1][foundIx2]!=callBacks[ix1][ix2]){ // we found a callback, but there already was one at this distance and it was different from the current one
+ cerr<<__FILE__<<":"<<__LINE__<<": ambiguous 2d dispatch ("<<"arg1="<<base1->getClassName()<<", arg2="<<base2->getClassName()<<", distance="<<dist<<"), dispatch matrix:"<<endl;
+ dumpDispatchMatrix2D(cerr,"AMBIGUOUS: "); throw runtime_error("Ambiguous dispatch.");
+ }
+ foundIx1=ix1; foundIx2=ix2;
+ callBacks[index1][index2]=callBacks[ix1][ix2]; callBacksInfo[index1][index2]=callBacksInfo[ix1][ix2];
+ _DISP_TRACE("Found callback ["<<ix1<<"]["<<ix2<<"] â "<<callBacks[ix1][ix2]->getClassName());
+ }
+ }
+ if(foundIx1!=-1) return true;
+ if(distTooBig){ _DISP_TRACE("Undefined dispatch, dist="<<dist); return false; /* undefined dispatch */ }
+ }
+ #else
+ #if 0
+ if((unsigned)index1>=callBacks.size()) cerr<<__FILE__<<":"<<__LINE__<<" FATAL: Index out of range for class "<<base1->getClassName()<<" (index=="<<index1<<", callBacks.size()=="<<callBacks.size()<<endl;
+ if((unsigned)index2>=callBacks[index2].size()) cerr<<__FILE__<<":"<<__LINE__<<" FATAL: Index out of range for class "<<base2->getClassName()<<" (index=="<<index2<<", callBacks[index1].size()=="<<callBacks[index1].size()<<endl;
+ #endif
+
+ if(callBacks[index1][index2]){
+ _DISP_TRACE("Direct hit at ["<<index1<<"]["<<index2<<"] â "<<callBacks[index1][index2]->getClassName());
+ return true;
+ }
+
+ int depth1=1, depth2=1;
+ int index1_tmp=base1->getBaseClassIndex(depth1), index2_tmp = base2->getBaseClassIndex(depth2);
+ _DISP_TRACE("base classes: "<<base1->getBaseClassName()<<"="<<index1_tmp<<", "<<base2->getBaseClassName()<<"="<<index2_tmp);
+ if(index1_tmp == -1) {
+ while(1){
+ if(index2_tmp == -1){
+ _DISP_TRACE("Returning FALSE");
+ return false;
+ }
+ if(callBacks[index1][index2_tmp]){ // FIXME - this is not working, when index1 or index2 is out-of-boundary. I have to resize callBacks and callBacksInfo tables. - this should be a separate function to resize stuff
+ callBacksInfo[index1][index2] = callBacksInfo[index1][index2_tmp];
+ callBacks [index1][index2] = callBacks [index1][index2_tmp];
+ // index2 = index2_tmp;
+ _DISP_TRACE("Found callback ["<<index1<<"]["<<index2_tmp<<"] â "<<callBacks[index1][index2_tmp]->getClassName());
+ return true;
+ }
+ index2_tmp = base2->getBaseClassIndex(++depth2);
+ _DISP_TRACE("index2_tmp="<<index2_tmp<<" (pushed up)");
+ }
+ }
+ else if(index2_tmp == -1) {
+ while(1){
+ if(index1_tmp == -1){
+ _DISP_TRACE("Returning FALSE");
+ return false;
+ }
+ if(callBacks[index1_tmp][index2]){
+ callBacksInfo[index1][index2] = callBacksInfo[index1_tmp][index2];
+ callBacks [index1][index2] = callBacks [index1_tmp][index2];
+ // index1 = index1_tmp;
+ _DISP_TRACE("Found callback ["<<index1_tmp<<"]["<<index2<<"] â "<<callBacks[index1_tmp][index2]->getClassName());
+ return true;
+ }
+ index1_tmp = base1->getBaseClassIndex(++depth1);
+ _DISP_TRACE("index1_tmp="<<index1_tmp<<" (pushed up)");
+ }
+ }
+ //else if( index1_tmp != -1 && index2_tmp != -1 )
+ _DISP_TRACE("UNDEFINED/AMBIGUOUS, dumping dispatch matrix");
+ dumpDispatchMatrix2D(cerr);
+ _DISP_TRACE("end matrix dump.")
+ throw std::runtime_error("DynLibDispatcher: ambiguous or undefined dispatch for 2d multivirtual function, classes: "+base1->getClassName()+" "+base2->getClassName());
+ //return false;
+ #endif
};
=== modified file 'py/yadeWrapper/yadeWrapper.cpp'
--- py/yadeWrapper/yadeWrapper.cpp 2009-08-21 10:06:00 +0000
+++ py/yadeWrapper/yadeWrapper.cpp 2009-08-21 11:44:00 +0000
@@ -760,6 +760,8 @@
#define EXPOSE_CXX_CLASS_RENAMED(cxxName,pyName) python::class_<cxxName,shared_ptr<cxxName>, python::bases<Serializable>, noncopyable>(#pyName).def("__init__",python::raw_constructor(Serializable_ctor_kwAttrs<cxxName>))
#define EXPOSE_CXX_CLASS(className) EXPOSE_CXX_CLASS_RENAMED(className,className)
+ // expose indexable class, with access to the index
+ #define EXPOSE_CXX_CLASS_IX(className) EXPOSE_CXX_CLASS(className).add_property("classIndex",&Indexable_getClassIndex<className>)
EXPOSE_CXX_CLASS(Body)
.def_readwrite("shape",&Body::geometricalModel)
@@ -772,12 +774,12 @@
.add_property("isStandalone",&Body::isStandalone)
.add_property("isClumpMember",&Body::isClumpMember)
.add_property("isClump",&Body::isClump);
- EXPOSE_CXX_CLASS(InteractingGeometry);
- EXPOSE_CXX_CLASS(GeometricalModel);
- EXPOSE_CXX_CLASS(BoundingVolume)
+ EXPOSE_CXX_CLASS_IX(InteractingGeometry);
+ EXPOSE_CXX_CLASS_IX(GeometricalModel);
+ EXPOSE_CXX_CLASS_IX(BoundingVolume)
.def_readonly("min",&BoundingVolume::min)
.def_readonly("max",&BoundingVolume::max);
- EXPOSE_CXX_CLASS(PhysicalParameters)
+ EXPOSE_CXX_CLASS_IX(PhysicalParameters)
.add_property("blockedDOFs",&PhysicalParameters::blockedDOFs_vec_get,&PhysicalParameters::blockedDOFs_vec_set)
.add_property("pos",&PhysicalParameters_pos_get,&PhysicalParameters_pos_set)
.add_property("ori",&PhysicalParameters_ori_get,&PhysicalParameters_ori_set)
@@ -792,8 +794,8 @@
.add_property("id2",&Interaction_getId2)
.add_property("isReal",&Interaction::isReal)
.add_property("cellDist",&Interaction_getCellDist);
- EXPOSE_CXX_CLASS(InteractionPhysics).add_property("classIndex",&Indexable_getClassIndex<InteractionPhysics>);
- EXPOSE_CXX_CLASS(InteractionGeometry).add_property("classIndex",&Indexable_getClassIndex<InteractionGeometry>);
+ EXPOSE_CXX_CLASS_IX(InteractionPhysics);
+ EXPOSE_CXX_CLASS_IX(InteractionGeometry);
EXPOSE_CXX_CLASS(FileGenerator)
.def("generate",&FileGenerator_generate)
.def("load",&FileGenerator_load);
=== modified file 'scripts/test-sphere-facet.py'
--- scripts/test-sphere-facet.py 2009-08-21 10:06:00 +0000
+++ scripts/test-sphere-facet.py 2009-08-21 11:44:00 +0000
@@ -42,10 +42,15 @@
O.saveTmp()
O.dt=1e-4
-O.engines[3].constLawDispatcher.dump()
-#print Dem3DofGeom_SphereSphere().classIndex
-#print Dem3DofGeom_FacetSphere().classIndex
-#print Dem3DofGeom().classIndex
+print '** virgin dispatch matrix:'
+O.engines[3].constLawDispatcher.dump()
+print '** class indices'
+for c in 'Dem3DofGeom','Dem3DofGeom_FacetSphere','Dem3DofGeom_SphereSphere':
+ print eval(c)().classIndex,c
+O.run(1000,True)
+print '** used dispatch matrix'
+O.engines[3].constLawDispatcher.dump()
+
def setGravity():
gz=gravitator["gravity"][2]