← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2616: 1. Make batch accept multiple scripts on the command line (see --help)

 

------------------------------------------------------------
revno: 2616
committer: Václav Šmilauer <eu@xxxxxxxx>
branch nick: yade
timestamp: Wed 2010-12-15 13:48:11 +0100
message:
  1. Make batch accept multiple scripts on the command line (see --help)
  2. Change syntax for blockedDOFs to be 'xyZ' rather than ['x','y','rz'] (assigning is backwards-compatible with warning)
  3. Remove rests of devirt-functors; I thought I've done it already...
modified:
  core/Interaction.hpp
  core/State.cpp
  core/State.hpp
  core/main/yade-batch.in
  pkg/dem/Ig2_Box_Sphere_ScGeom.cpp
  pkg/dem/Ig2_Box_Sphere_ScGeom.hpp
  pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp
  pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp


--
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 'core/Interaction.hpp'
--- core/Interaction.hpp	2010-11-19 12:30:08 +0000
+++ core/Interaction.hpp	2010-12-15 12:48:11 +0000
@@ -35,11 +35,6 @@
 			// Whether geometry dispatcher exists at all; this is different from !geom, since that can mean we haven't populated the cache yet.
 			// Therefore, geomExists must be initialized to true first (done in Interaction::reset() called from ctor).
 			bool geomExists;
-			#ifdef YADE_DEVIRT_FUNCTORS
-				// is a IGeomFunctor::StaticFuncPtr, but we would have to #include a file from pkg/common here
-				// cast at those few places instead, for now
-				void* geomPtr;
-			#endif
 			// shared_ptr's are initialized to NULLs automagically
 			shared_ptr<IGeomFunctor> geom;
 			shared_ptr<IPhysFunctor> phys;

=== modified file 'core/State.cpp'
--- core/State.cpp	2009-11-21 10:21:57 +0000
+++ core/State.cpp	2010-12-15 12:48:11 +0000
@@ -6,24 +6,51 @@
 	#define FOREACH BOOST_FOREACH
 #endif
 
+CREATE_LOGGER(State);
+
 void State::setDOFfromVector3r(Vector3r disp,Vector3r rot){
 	blockedDOFs=((disp[0]==1.0)?DOF_X :0)|((disp[1]==1.0)?DOF_Y :0)|((disp[2]==1.0)?DOF_Z :0)|
 		((rot [0]==1.0)?DOF_RX:0)|((rot [1]==1.0)?DOF_RY:0)|((rot [2]==1.0)?DOF_RZ:0);
 }
 
-std::vector<std::string> State::blockedDOFs_vec_get() const {
-	std::vector<std::string> ret;
-	#define _SET_DOF(DOF_ANY,str) if((blockedDOFs & State::DOF_ANY)!=0) ret.push_back(str);
-	_SET_DOF(DOF_X,"x"); _SET_DOF(DOF_Y,"y"); _SET_DOF(DOF_Z,"z"); _SET_DOF(DOF_RX,"rx"); _SET_DOF(DOF_RY,"ry"); _SET_DOF(DOF_RZ,"rz");
+std::string State::blockedDOFs_vec_get() const {
+	std::string ret;
+	#define _SET_DOF(DOF_ANY,ch) if((blockedDOFs & State::DOF_ANY)!=0) ret.push_back(ch);
+	_SET_DOF(DOF_X,'x'); _SET_DOF(DOF_Y,'y'); _SET_DOF(DOF_Z,'z'); _SET_DOF(DOF_RX,'X'); _SET_DOF(DOF_RY,'Y'); _SET_DOF(DOF_RZ,'Z');
 	#undef _SET_DOF
 	return ret;
 }
-void State::blockedDOFs_vec_set(const std::vector<std::string>& dofs){
-	FOREACH(const std::string s, dofs){
-		#define _GET_DOF(DOF_ANY,str) if(s==str) { blockedDOFs|=State::DOF_ANY; continue; }
-		_GET_DOF(DOF_X,"x"); _GET_DOF(DOF_Y,"y"); _GET_DOF(DOF_Z,"z"); _GET_DOF(DOF_RX,"rx"); _GET_DOF(DOF_RY,"ry"); _GET_DOF(DOF_RZ,"rz");
-		#undef _GET_DOF
-		throw std::invalid_argument("Invalid  DOF specification `"+s+"', must be ∈{x,y,z,rx,ry,rz}.");
+
+#ifdef YADE_DEPREC_DOF_LIST
+// support deprecated syntax, later take std::string arg directly (more efficient)
+void State::blockedDOFs_vec_set(const python::object& dofs0){
+	python::extract<std::string> dofStr(dofs0);
+	python::extract<std::vector<std::string> > dofLst(dofs0);
+	blockedDOFs=0;
+	if(dofStr.check()){
+		string dofs(dofStr());
+#else
+	void State::blockedDOFs_vec_set(const std::string& dofs){
+		blockedDOFs=0;
+#endif
+		FOREACH(char c, dofs){
+			#define _GET_DOF(DOF_ANY,ch) if(c==ch) { blockedDOFs|=State::DOF_ANY; continue; }
+			_GET_DOF(DOF_X,'x'); _GET_DOF(DOF_Y,'y'); _GET_DOF(DOF_Z,'z'); _GET_DOF(DOF_RX,'X'); _GET_DOF(DOF_RY,'Y'); _GET_DOF(DOF_RZ,'Z');
+			#undef _GET_DOF
+			throw std::invalid_argument("Invalid  DOF specification `"+lexical_cast<string>(c)+"' in '"+dofs+"', characters must be ∈{x,y,z,X,Y,Z}.");
+		}
+#ifdef YADE_DEPREC_DOF_LIST
+	} else 
+	if(dofLst.check()){
+		LOG_WARN("Specifying State.blockedDOFs as list ['x','y','rx','rz'] is deprecated, use string 'xyXZ' instead.");
+		FOREACH(const std::string s, dofLst()){
+			#define _GET_DOF(DOF_ANY,str) if(s==str) { blockedDOFs|=State::DOF_ANY; continue; }
+			_GET_DOF(DOF_X,"x"); _GET_DOF(DOF_Y,"y"); _GET_DOF(DOF_Z,"z"); _GET_DOF(DOF_RX,"rx"); _GET_DOF(DOF_RY,"ry"); _GET_DOF(DOF_RZ,"rz");
+			#undef _GET_DOF
+			throw std::invalid_argument("Invalid  DOF specification `"+s+"', must be ∈{x,y,z,rx,ry,rz}.");
+		}
+	} else {
+		throw std::invalid_argument("Invalid type: State.blockedDOFs must be either list of strings or string.");
 	}
+#endif
 }
-

=== modified file 'core/State.hpp'
--- core/State.hpp	2010-11-07 11:46:20 +0000
+++ core/State.hpp	2010-12-15 12:48:11 +0000
@@ -3,6 +3,10 @@
 #include<yade/lib/serialization/Serializable.hpp>
 #include<yade/lib/multimethods/Indexable.hpp>
 #include<yade/core/Dispatcher.hpp>
+
+// delete later and remove relevant code, to not support old State.blockedDOFs=['x','y','rz'] syntax anymore
+#define YADE_DEPREC_DOF_LIST
+
 /*! State (internal & spatial variables) of a body.
 
 For now, I put position, orientation, velocity and angular velocity here,
@@ -40,10 +44,14 @@
 		static unsigned axisDOF(int axis, bool rotationalDOF=false){return 1<<(axis+(rotationalDOF?3:0));}		
 		//! set DOFs according to two Vector3r arguments (blocked is when disp[i]==1.0 or rot[i]==1.0)
 		void setDOFfromVector3r(Vector3r disp,Vector3r rot=Vector3r::Zero());
-		//! Getter of blockedDOFs for list of strings (e.g. DOF_X | DOR_RX | DOF_RZ → ['x','rx','rz'])
-		std::vector<std::string> blockedDOFs_vec_get() const;
-		//! Setter of blockedDOFs from list of strings (['x','rx','rz'] → DOF_X | DOR_RX | DOF_RZ)
-		void blockedDOFs_vec_set(const std::vector<std::string>& dofs);
+		//! Getter of blockedDOFs for list of strings (e.g. DOF_X | DOR_RX | DOF_RZ → 'xXZ')
+		std::string blockedDOFs_vec_get() const;
+		//! Setter of blockedDOFs from string ('xXZ' → DOF_X | DOR_RX | DOF_RZ)
+		#ifdef YADE_DEPREC_DOF_LIST
+			void blockedDOFs_vec_set(const python::object&);
+		#else
+			void blockedDOFs_vec_set(const std::string& dofs);
+		#endif
 
 		//! Return displacement (current-reference position)
 		Vector3r displ() const {return pos-refPos;}
@@ -78,11 +86,12 @@
 		/* ctor */,
 		/*py*/
 		YADE_PY_TOPINDEXABLE(State)
-		.add_property("blockedDOFs",&State::blockedDOFs_vec_get,&State::blockedDOFs_vec_set,"Degress of freedom where linear/angular velocity will be always constant (equal to zero, or to an user-defined value), regardless of applied force/torque. List of any combination of 'x','y','z','rx','ry','rz'.")
+		.add_property("blockedDOFs",&State::blockedDOFs_vec_get,&State::blockedDOFs_vec_set,"Degress of freedom where linear/angular velocity will be always constant (equal to zero, or to an user-defined value), regardless of applied force/torque. String that may contain 'xyzXYZ' (translations and rotations).")
 		// references must be set using wrapper funcs
 		.add_property("pos",&State::pos_get,&State::pos_set,"Current position.")
 		.add_property("ori",&State::ori_get,&State::ori_set,"Current orientation.") 
 	);
 	REGISTER_INDEX_COUNTER(State);
+	DECLARE_LOGGER;
 };
 REGISTER_SERIALIZABLE(State);

=== modified file 'core/main/yade-batch.in'
--- core/main/yade-batch.in	2010-12-09 15:02:38 +0000
+++ core/main/yade-batch.in	2010-12-15 12:48:11 +0000
@@ -297,11 +297,11 @@
 numCores=getNumCores()
 maxOmpThreads=numCores if 'openmp' in yade.config.features else 1
 
-parser=optparse.OptionParser(usage='%prog [options] [TABLE] SIMULATION.py',description='%prog runs yade simulation multiple times with different parameters.\n\nSee https://yade-dem.org/sphinx/user.html#batch-queuing-and-execution-yade-batch for details.')
+parser=optparse.OptionParser(usage='%prog [options] [ TABLE [SIMULATION.py] | SIMULATION.py[/nCores] [...] ]',description='%prog runs yade simulation multiple times with different parameters.\n\nSee https://yade-dem.org/sphinx/user.html#batch-queuing-and-execution-yade-batch for details.\n\nBatch can be specified either with parameter table TABLE (must not end in .py), which is either followed by exactly one SIMULATION.py (must end in .py), or contains !SCRIPT column specifying the simulation to be run. The second option is to specify multiple scripts, which can optionally have /nCores suffix to specify number of cores for that particular simulation (corresponds to !THREADS column in the parameter table), e.g. sim.py/3.')
 parser.add_option('-j','--jobs',dest='maxJobs',type='int',help="Maximum number of simultaneous threads to run (default: number of cores, further limited by OMP_NUM_THREADS if set by the environment: %d)"%numCores,metavar='NUM',default=numCores)
 parser.add_option('--job-threads',dest='defaultThreads',type='int',help="Default number of threads for one job; can be overridden by per-job with !THREADS (or !OMP_NUM_THREADS) column. Defaults to allocate all available cores (%d, which might be further limited with --jobs) for each job when built with OpenMP, otherwise to 1."%maxOmpThreads,metavar='NUM',default=-1)
 parser.add_option('--force-threads',action='store_true',dest='forceThreads',help='Force jobs to not use more cores than the maximum (see -j), even if !THREADS colums specifies more.')
-parser.add_option('--log',dest='logFormat',help='Format of job log files -- must contain a % or @, which will be replaced by line number or by description column respectively (default: SIMULATION.@.log)',metavar='FORMAT')
+parser.add_option('--log',dest='logFormat',help='Format of job log files -- must contain a $, % or @, which will be replaced by script name, line number or by description column respectively (default: $.@.log)',metavar='FORMAT',default='$.@.log')
 parser.add_option('--global-log',dest='globalLog',help='Filename where to redirect output of yade-batch itself (as opposed to --log); if not specified (default), stdout/stderr are used',metavar='FILE')
 parser.add_option('-l','--lines',dest='lineList',help='Lines of TABLE to use, in the format 2,3-5,8,11-13 (default: all available lines in TABLE)',metavar='LIST')
 parser.add_option('--nice',dest='nice',type='int',help='Nice value of spawned jobs (default: 10)',default=10)
@@ -331,22 +331,22 @@
 	sys.exit(0)
 
 if globalLog:
+	print 'Redirecting all output to',globalLog
 	sys.stderr=open(globalLog,"w")
 	sys.stdout=sys.stderr
 
-if len(args) not in (1,2):
+if len([1 for a in args if re.match('.*\.py(/[0-9]+)?',a)])==len(args) and len(args)!=0:
+	# if all args end in .py, they are simulations that we will run
+	table=None; scripts=args
+elif len(args)==2:
+	table,scripts=args[0],[args[1]]
+elif len(args)==1:
+	table,scripts=args[0],[]
+else:
 	parser.print_help()
 	sys.exit(1)
-elif len(args)==2:
-	table,simul=args[0:2]
-else:
-	assert(len(args)==1);
-	table=None; simul=args[0]
-
-if not logFormat: logFormat=(simul[:-3] if simul[-3:]=='.py' else simul)+".@.log"
-if (not '%' in logFormat) and ('@' not in logFormat): raise StandardError("Log string must contain at least one of `%', `@'")
-
-print "Will run `%s' on `%s' with nice value %d, output redirected to `%s', using max %d cores."%(executable,simul,nice,logFormat,maxJobs)
+
+print "Will run simulation(s) %s using `%s', nice value %d, using max %d cores."%(scripts,executable,nice,maxJobs)
 
 if table:
 	reader=yade.utils.TableParamReader(table)
@@ -370,15 +370,23 @@
 	else: useLines=availableLines
 	print "Will use lines ",', '.join([str(i)+' (%s)'%params[i]['description'] for i in useLines])+'.'
 else:
-	print "Running stand-alone simulation in batch mode."
-	useLines=[-1]
-	params={-1:{'description':'default'}}
-
+	print "Running %d stand-alone simulation(s) in batch mode."%(len(scripts))
+	useLines=[]
+	params={}
+	for i,s in enumerate(scripts):
+		fakeLineNo=-i-1
+		useLines.append(fakeLineNo)
+		params[fakeLineNo]={'description':'default','!SCRIPT':s}
+		# fix script and set threads if script.py/num
+		m=re.match('(.*)(/[0-9]+)$',s)
+		if m:
+			params[fakeLineNo]['!SCRIPT']=m.group(1)
+			params[fakeLineNo]['!THREADS']=int(m.group(2)[1:])
 jobs=[]
 executables=set()
+logFiles=[]
 for i,l in enumerate(useLines):
-	logFile=logFormat.replace('%',str(l))
-	logFile=logFile.replace('@',params[l]['description'])
+	script=scripts[0] if len(scripts)>0 else None
 	envVars=[]
 	nCores=opts.defaultThreads if opts.defaultThreads>0 else opts.maxJobs
 	jobExecutable=executable
@@ -390,10 +398,14 @@
 		val=params[l][col]
 		if col=='!OMP_NUM_THREADS' or col=='!THREADS': nCores=int(val)
 		elif col=='!EXEC': jobExecutable=val
+		elif col=='!SCRIPT': script=val
 		elif col=='!AFFINITY': jobAffinity=eval(val)
 		elif col=='!DEBUG': jobDebug=eval(val)
 		elif col=='!COUNT': jobCount=eval(val)
 		else: envVars+=['%s=%s'%(head[1:],values[l][col])]
+	if not script:
+		raise ValueError('When only batch table is given without script to run, it must contain !SCRIPT column with simulation to be run.')
+	logFile=logFormat.replace('$',script).replace('%',str(l)).replace('@',params[l]['description'])
 	if nCores>maxJobs:
 		if opts.forceThreads:
 			logging.info('Forcing job #%d to use only %d cores (max available) instead of %d requested'%(i,maxJobs,nCores))
@@ -406,17 +418,24 @@
 	# compose command-line: build the hyper-linked variant, then strip HTML tags (ugly, but ensures consistency)
 	for j in range(0,opts.timing if opts.timing>0 else 1):
 		jobNum=len(jobs)
-		logFileNumbered=logFile+('.%d'%j if opts.timing>0 else '')
+		logFile2=logFile+('.%d'%j if opts.timing>0 else '')
+		# append numbers to log file if it already exists, to prevent overwriting
+		if logFile2 in logFiles:
+			i=0;
+			while logFile2+'.%d'%i in logFiles: i+=1
+			logFile2+='.%d'%i
+		logFiles.append(logFile2)
 		env='YADE_BATCH='
 		if table: env+='<a href="jobs/%d/table">%s:%d</a>'%(jobNum,table,l) # keep YADE_BATCH empty (but still defined) if running a single simulation
 		env+=' DISPLAY= %s '%(' '.join(envVars))
-		cmd='%s%s [threadspec] %s -x <a href="jobs/%d/script">%s</a>'%(jobExecutable,' --debug' if jobDebug else '','--nice=%s'%nice if nice!=None else '',i,simul)
-		log='> <a href="jobs/%d/log">%s</a> 2>&1'%(jobNum,pipes.quote(logFileNumbered))
+		cmd='%s%s [threadspec] %s -x <a href="jobs/%d/script">%s</a>'%(jobExecutable,' --debug' if jobDebug else '','--nice=%s'%nice if nice!=None else '',i,script)
+		log='> <a href="jobs/%d/log">%s</a> 2>&1'%(jobNum,pipes.quote(logFile2))
 		hrefCmd=env+cmd+log
 		fullCmd=re.sub('(<a href="[^">]+">|</a>)','',hrefCmd)
 		desc=params[l]['description']
+		if '!SCRIPT' in params[l].keys(): desc=script+'.'+desc # prepend filename if script is specified explicitly
 		if opts.timing>0: desc+='[%d]'%j
-		jobs.append(JobInfo(jobNum,desc,fullCmd,hrefCmd,logFileNumbered,nCores,script=simul,table=table,lineNo=l,affinity=jobAffinity))
+		jobs.append(JobInfo(jobNum,desc,fullCmd,hrefCmd,logFile2,nCores,script=script,table=table,lineNo=l,affinity=jobAffinity))
 
 print "Master process pid",os.getpid()
 

=== modified file 'pkg/dem/Ig2_Box_Sphere_ScGeom.cpp'
--- pkg/dem/Ig2_Box_Sphere_ScGeom.cpp	2010-12-06 19:24:20 +0000
+++ pkg/dem/Ig2_Box_Sphere_ScGeom.cpp	2010-12-15 12:48:11 +0000
@@ -19,10 +19,6 @@
 
 
 
-#ifdef YADE_DEVIRT_FUNCTORS
-bool Ig2_Box_Sphere_ScGeom::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Box_Sphere_ScGeom::go, use getStaticFunctorPtr and call that function instead."); }
-bool Ig2_Box_Sphere_ScGeom::goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
-#else
 bool Ig2_Box_Sphere_ScGeom::go(
 		const shared_ptr<Shape>& cm1,
 		const shared_ptr<Shape>& cm2,
@@ -32,7 +28,6 @@
 		const bool& force,
 		const shared_ptr<Interaction>& c)
 {
-#endif
 	const Se3r& se31=state1.se3; const Se3r& se32=state2.se3;
 
 	bool inside=true;
@@ -170,10 +165,6 @@
 YADE_PLUGIN((Ig2_Box_Sphere_ScGeom));
 
 
-#ifdef YADE_DEVIRT_FUNCTORS
-bool Ig2_Box_Sphere_ScGeom6D::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Box_Sphere_ScGeom6D::go, use getStaticFunctorPtr and call that function instead."); }
-bool Ig2_Box_Sphere_ScGeom6D::goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
-#else
 bool Ig2_Box_Sphere_ScGeom6D::go(
 		const shared_ptr<Shape>& cm1,
 		const shared_ptr<Shape>& cm2,
@@ -183,7 +174,6 @@
 		const bool& force,
 		const shared_ptr<Interaction>& c)
 {
-#endif
 	bool isNew = !c->geom;
 	if (Ig2_Box_Sphere_ScGeom::go(cm1,cm2,state1,state2,shift2,force,c)) {
 		if (isNew) {//generate a 6DOF interaction from the 3DOF one generated by Ig2_Box_Sphere_ScGeom

=== modified file 'pkg/dem/Ig2_Box_Sphere_ScGeom.hpp'
--- pkg/dem/Ig2_Box_Sphere_ScGeom.hpp	2010-12-06 19:24:20 +0000
+++ pkg/dem/Ig2_Box_Sphere_ScGeom.hpp	2010-12-15 12:48:11 +0000
@@ -33,11 +33,6 @@
 					const bool& force,
 					const shared_ptr<Interaction>& c);
 
-	#ifdef YADE_DEVIRT_FUNCTORS
-		void* getStaticFuncPtr(){ return (void*)&Ig2_Box_Sphere_ScGeom::goStatic; }
-		static bool goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#endif
-
 	YADE_CLASS_BASE_DOC(Ig2_Box_Sphere_ScGeom,IGeomFunctor,"Create an interaction geometry :yref:`ScGeom` from :yref:`Box` and :yref:`Sphere`")
 	FUNCTOR2D(Box,Sphere);
 	DEFINE_FUNCTOR_ORDER_2D(Box,Sphere);
@@ -63,11 +58,6 @@
 					const bool& force,
 					const shared_ptr<Interaction>& c);
 
-	#ifdef YADE_DEVIRT_FUNCTORS
-		void* getStaticFuncPtr(){ return (void*)&Ig2_Box_Sphere_ScGeom6D::goStatic; }
-		static bool goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#endif
-
 	YADE_CLASS_BASE_DOC(Ig2_Box_Sphere_ScGeom6D,Ig2_Box_Sphere_ScGeom,"Create an interaction geometry :yref:`ScGeom6D` from :yref:`Box` and :yref:`Sphere`")
 	FUNCTOR2D(Box,Sphere);
 	DEFINE_FUNCTOR_ORDER_2D(Box,Sphere);

=== modified file 'pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp'
--- pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp	2010-11-25 12:16:32 +0000
+++ pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp	2010-12-15 12:48:11 +0000
@@ -9,18 +9,11 @@
 #include<yade/lib/base/Math.hpp>
 #include<yade/core/Omega.hpp>
 
-#ifdef YADE_DEVIRT_FUNCTORS
-bool Ig2_Sphere_Sphere_ScGeom::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Sphere_Sphere_ScGeom::go, use getStaticFunctorPtr and call that function instead."); }
-bool Ig2_Sphere_Sphere_ScGeom::goStatic(IGeomFunctor* _self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
-	const Ig2_Sphere_Sphere_ScGeom* self=static_cast<Ig2_Sphere_Sphere_ScGeom*>(_self);
-	const Real& interactionDetectionFactor=self->interactionDetectionFactor;
-#else
 bool Ig2_Sphere_Sphere_ScGeom::go(	const shared_ptr<Shape>& cm1,
 							const shared_ptr<Shape>& cm2,
 							const State& state1, const State& state2, const Vector3r& shift2, const bool& force,
 							const shared_ptr<Interaction>& c)
 {
-#endif
 	const Se3r& se31=state1.se3; const Se3r& se32=state2.se3;
 	const Sphere *s1=static_cast<Sphere*>(cm1.get()), *s2=static_cast<Sphere*>(cm2.get());
 	Vector3r normal=(se32.position+shift2)-se31.position;
@@ -57,18 +50,11 @@
 
 YADE_PLUGIN((Ig2_Sphere_Sphere_ScGeom));
 
-#ifdef YADE_DEVIRT_FUNCTORS
-bool Ig2_Sphere_Sphere_ScGeom6D::go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){ throw runtime_error("Do not call Ig2_Sphere_Sphere_ScGeom6D::go, use getStaticFunctorPtr and call that function instead."); }
-bool Ig2_Sphere_Sphere_ScGeom6D::goStatic(IGeomFunctor* _self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
-	const Ig2_Sphere_Sphere_ScGeom6D* self=static_cast<Ig2_Sphere_Sphere_ScGeom6D*>(_self);
-	const Real& interactionDetectionFactor=self->interactionDetectionFactor;
-#else
 bool Ig2_Sphere_Sphere_ScGeom6D::go(	const shared_ptr<Shape>& cm1,
 							const shared_ptr<Shape>& cm2,
 							const State& state1, const State& state2, const Vector3r& shift2, const bool& force,
 							const shared_ptr<Interaction>& c)
 {
-#endif
 	bool isNew = !c->geom;
 	if (Ig2_Sphere_Sphere_ScGeom::go(cm1,cm2,state1,state2,shift2,force,c)){//the 3 DOFS from ScGeom are updated here
  		if (isNew) {//generate a 6DOF interaction from the 3DOF one generated by Ig2_Sphere_Sphere_ScGeom

=== modified file 'pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp'
--- pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp	2010-11-12 18:44:15 +0000
+++ pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp	2010-12-15 12:48:11 +0000
@@ -10,10 +10,6 @@
 	public:
 		virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
 		virtual bool goReverse(	const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#ifdef YADE_DEVIRT_FUNCTORS
-		void* getStaticFuncPtr(){ return (void*)&Ig2_Sphere_Sphere_ScGeom::goStatic; }
-		static bool goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#endif
 	YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_Sphere_ScGeom,IGeomFunctor,"Create/update a :yref:`ScGeom` instance representing intersection of two :yref:`Spheres<Sphere>`.",
 		((Real,interactionDetectionFactor,1,,"Enlarge both radii by this factor (if >1), to permit creation of distant interactions.\n\nInteractionGeometry will be computed when interactionDetectionFactor*(rad1+rad2) > distance.\n\n.. note::\n\t This parameter is functionally coupled with :yref:`Bo1_Sphere_Aabb::aabbEnlargeFactor`, which will create larger bounding boxes and should be of the same value.\n\n.. warning::\n\tFunctionally equal class :yref:`Ig2_Sphere_Sphere_Dem3DofGeom` (which creates :yref:`Dem3DofGeom` rather than :yref:`ScGeom`) calls this parameter :yref:`distFactor<Ig2_Sphere_Sphere_Dem3DofGeom::distFactor>`, but its semantics is *different* in some aspects."))
 		((bool,avoidGranularRatcheting,true,,"Granular ratcheting is mentioned in [GarciaRojo2004]_, [Alonso2004]_, [McNamara2008]_.\n\n"
@@ -38,10 +34,6 @@
 	public:
 		virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
 		virtual bool goReverse(	const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#ifdef YADE_DEVIRT_FUNCTORS
-		void* getStaticFuncPtr(){ return (void*)&Ig2_Sphere_Sphere_ScGeom6D::goStatic; }
-		static bool goStatic(IGeomFunctor* self, const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& se32, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-	#endif
 	YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_Sphere_ScGeom6D,Ig2_Sphere_Sphere_ScGeom,"Create/update a :yref:`ScGeom6D` instance representing intersection of two :yref:`Spheres<Sphere>`.",
 		((bool,updateRotations,true,,"Precompute relative rotations. Turning this false can speed up simulations when rotations are not needed in constitutive laws (e.g. when spheres are compressed without cohesion and moment in early stage of a triaxial test), but is not foolproof. Change this value only if you know what you are doing."))
 		((bool,creep,false,,"Substract rotational creep from relative rotation. The rotational creep :yref:`ScGeom6D::twistCreep` is a quaternion and has to be updated inside a constitutive law, see for instance :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`."