← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 1937: 1. Add clone function to python objects, taking optinal python dictionary with changed attributes

 

------------------------------------------------------------
revno: 1937
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Mon 2010-01-04 11:34:53 +0100
message:
  1. Add clone function to python objects, taking optinal python dictionary with changed attributes
  2. Fix PeriIsoCompressor for examples/concrete/periodic.py 
  3. GaussAverage relThreshold argument is now optional in python, as it is in c++ (again)
modified:
  examples/concrete/periodic.py
  pkg/dem/Engine/GlobalEngine/PeriIsoCompressor.cpp
  py/WeightedAverage2d.cpp
  py/yadeWrapper/yadeWrapper.cpp


--
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 'examples/concrete/periodic.py'
--- examples/concrete/periodic.py	2009-12-25 14:46:48 +0000
+++ examples/concrete/periodic.py	2010-01-04 10:34:53 +0000
@@ -70,7 +70,7 @@
 # load the packing (again);
 #
 import cPickle as pickle
-concreteId=O.materials.append(CpmMat(young=young,frictionAngle=frictionAngle,poisson=poisson,density=4800))
+concreteId=O.materials.append(CpmMat(young=young,frictionAngle=frictionAngle,poisson=poisson,density=4800,sigmaT=sigmaT,relDuctility=relDuctility,epsCrackOnset=epsCrackOnset,G_over_E=G_over_E,isoPrestress=isoPrestress))
 sphDict=pickle.load(open(packingFile))
 from yade import pack
 sp=pack.SpherePack()
@@ -80,7 +80,8 @@
 import numpy
 avgRadius=numpy.average([r for c,r in sp])
 O.bodies.append([utils.sphere(c,r,color=utils.randomColor()) for c,r in sp])
-O.cellSize=sp.cellSize
+O.periodic=True
+O.cell.refSize=sp.cellSize
 axis=2
 ax1=(axis+1)%3
 ax2=(axis+2)%3
@@ -96,7 +97,7 @@
 	InsertionSortCollider(sweepLength=.05*avgRadius,nBins=5,binCoeff=5),
 	InteractionDispatchers(
 		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg')],
-		[Ip2_CpmMat_CpmMat_CpmPhys(sigmaT=sigmaT,relDuctility=relDuctility,epsCrackOnset=epsCrackOnset,G_over_E=G_over_E,isoPrestress=isoPrestress)],
+		[Ip2_CpmMat_CpmMat_CpmPhys()],
 		[Law2_Dem3DofGeom_CpmPhys_Cpm()],
 	),
 	NewtonIntegrator(damping=damping,label='newton'),
@@ -104,7 +105,7 @@
 	#
 	#UniaxialStrainer(strainRate=strainRateTension,axis=axis,asymmetry=0,posIds=posIds,negIds=negIds,crossSectionArea=crossSectionArea,blockDisplacements=False,blockRotations=False,setSpeeds=setSpeeds,label='strainer'),
 	#
-	PeriTriaxController(goal=[1,1,1],stressMask=( (7^(1<<axis | 1<<ax1)) if biaxial else (7^(1<<axis)) ),maxStrainRate=Vector3(1,1,1),label='strainer',reversedForces=False,globUpdate=2),
+	PeriTriaxController(goal=[1,1,1],stressMask=( (7^(1<<axis | 1<<ax1)) if biaxial else (7^(1<<axis)) ),maxStrainRate=Vector3(5,5,5),label='strainer',reversedForces=False,globUpdate=2),
 	PeriodicPythonRunner(virtPeriod=1e-5/strainRateTension,realLim=2,command='addPlotData()',label='plotDataCollector'),
 	PeriodicPythonRunner(realPeriod=4,command='stopIfDamaged()',label='damageChecker'),
 ]

=== modified file 'pkg/dem/Engine/GlobalEngine/PeriIsoCompressor.cpp'
--- pkg/dem/Engine/GlobalEngine/PeriIsoCompressor.cpp	2010-01-03 20:30:24 +0000
+++ pkg/dem/Engine/GlobalEngine/PeriIsoCompressor.cpp	2010-01-04 10:34:53 +0000
@@ -101,7 +101,7 @@
 	//"Natural" strain, correct for large deformations, only used for comparison with goals
 	// → no logarithm here, I have code for strain-stress test that needs regular linear strain.
 	//	Why not set goals as logarithm, if you need it?
-	for ( int i=0; i<3; i++ ) strain[i]=(scene->cell->trsf[i][i]);
+	for(int i=0; i<3; i++) strain[i]=(scene->cell->getSize()[i]-scene->cell->refSize[i])/(scene->cell->refSize[i]);
 
 	//stress tensor and stiffness
 	
@@ -233,14 +233,15 @@
 		// either prescribe velocity gradient
 		//NOTE (2) : ... and don't divide here
 		scene->cell->velGrad[axis][axis]=cellGrow[axis]/(scene->dt*refSize[axis]);
-		// or strain increment (but NOT both)
-		// strain[axis]+=cellGrow[axis]/refSize[axis];
+		// used only for goal comparisons...
+		strain[axis]+=cellGrow[axis]/refSize[axis];
 
 		// take in account something like poisson's effect here…
 		//Real bogusPoisson=0.25; int ax1=(axis+1)%3,ax2=(axis+2)%3;
 		//don't modify stress if dynCell, testing only stiff[axis]>0 would not allow switching the control mode in simulations,
 		///NOTE : this one uses size and is hard to generalize to 9 components as well, how can we predict the full stress tensor? It would need a 9x9 stifness matrix!! At the end, I wonder if the implementation of independant control on the 9 components would not be easier and cleaner in a different engine... This stiffness approach is not a piece of cake. Controlling arbitrary components using inertia and comparing Fkk vs. goal[k][k] is really a different (and easier) problem. I feel like I'm mixing two different things, with a lot of complication to preserve a few specific features that will not be generalised at the end, just for the sake of avoiding a few duplicated lines. What do you think?
-		if ( stiff[axis]>0 && !dynCell ) stress[axis]+= ( cellGrow[axis]/refSize[axis] ) * ( stiff[axis]/cellArea[axis] ); //-bogusPoisson*(cellGrow[ax1]/refSize[ax1])*(stiff[ax1]/cellArea[ax1])-bogusPoisson*(cellGrow[ax2]/refSize[ax2])*(stiff[ax2]/cellArea[ax2]);
+		if (stiff[axis]>0 && !dynCell) stress[axis]+=(cellGrow[axis]/refSize[axis])*(stiff[axis]/cellArea[axis]);
+			//-bogusPoisson*(cellGrow[ax1]/refSize[ax1])*(stiff[ax1]/cellArea[ax1])-bogusPoisson*(cellGrow[ax2]/refSize[ax2])*(stiff[ax2]/cellArea[ax2]);
 	}
 	// change cell size now
 	// scene->cell->refSize+=cellGrow;

=== modified file 'py/WeightedAverage2d.cpp'
--- py/WeightedAverage2d.cpp	2009-11-13 11:27:22 +0000
+++ py/WeightedAverage2d.cpp	2010-01-04 10:34:53 +0000
@@ -17,7 +17,7 @@
 BOOST_PYTHON_MODULE(WeightedAverage2d)
 {
 	boost::python::scope().attr("__doc__")="Smoothing (2d gauss-weighted average) for postprocessing scalars in 2d.";
-	boost::python::class_<pyGaussAverage>("GaussAverage",python::init<python::tuple,python::tuple,python::tuple,Real,Real>(python::args("min","max","nCells","stDev","relThreshold"),"Create empty container for data, which can be added using add and later retrieved using avg."))
+	boost::python::class_<pyGaussAverage>("GaussAverage",python::init<python::tuple,python::tuple,python::tuple,Real,python::optional<Real> >(python::args("min","max","nCells","stDev","relThreshold"),"Create empty container for data, which can be added using add and later retrieved using avg."))
 		.def("add",&pyGaussAverage::addPt)
 		.def("avg",&pyGaussAverage::avg)
 		.add_property("stDev",&pyGaussAverage::stDev_get,&pyGaussAverage::stDev_set)

=== modified file 'py/yadeWrapper/yadeWrapper.cpp'
--- py/yadeWrapper/yadeWrapper.cpp	2010-01-03 20:30:24 +0000
+++ py/yadeWrapper/yadeWrapper.cpp	2010-01-04 10:34:53 +0000
@@ -575,6 +575,18 @@
 	return instance;
 }
 
+template <typename T>
+shared_ptr<T> Serializable_clone(const shared_ptr<T>& self, const python::dict& d){
+	shared_ptr<Factorable> inst0=ClassFactory::instance().createShared(self->getClassName());
+	if(!inst0) throw runtime_error("Invalid class `"+self->getClassName()+"' (not created by ClassFactory).");
+	shared_ptr<T> inst=dynamic_pointer_cast<T>(inst0);
+	if(!inst) throw runtime_error("Invalid class `"+self->getClassName()+"' (unable to cast to typeid `"+typeid(T).name()+"')");
+	inst->pyUpdateAttrs(self->pyDict());
+	// if d not empty (how to test that?)
+	inst->pyUpdateAttrs(d);
+	inst->postProcessAttributes(/*deserializing*/true);
+	return inst;
+}
 
 // stupid; Dispatcher is not a template, hence converting this into a real constructor would be complicated; keep it here.
 template<typename DispatcherT>
@@ -751,6 +763,7 @@
 		.add_property("name",&Serializable::getClassName).def("__str__",&Serializable::pyStr).def("__repr__",&Serializable::pyStr).def("postProcessAttributes",&Serializable::postProcessAttributes,(python::arg("deserializing")=true))
 		.def("dict",&Serializable::pyDict).def("__getitem__",&Serializable::pyGetAttr).def("__setitem__",&Serializable::pySetAttr).def("has_key",&Serializable::pyHasKey).def("keys",&Serializable::pyKeys)
 		.def("updateAttrs",&Serializable::pyUpdateAttrs).def("updateExistingAttrs",&Serializable::pyUpdateExistingAttrs)
+		.def("clone",&Serializable_clone<Serializable>,python::arg("attrs")=python::dict())
 		.def("__init__",python::raw_constructor(Serializable_ctor_kwAttrs<Serializable>))
 		// aliases for __getitem__ and __setitem__, but they are used by the property generator code and can be useful if we deprecate the object['attr'] type of access
 		.def("_prop_get",&Serializable::pyGetAttr).def("_prop_set",&Serializable::pySetAttr)
@@ -800,7 +813,7 @@
 		EXPOSE_FUNCTOR(LawFunctor)
 	#undef EXPOSE_FUNCTOR
 		
-	#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_RENAMED(cxxName,pyName) python::class_<cxxName,shared_ptr<cxxName>, python::bases<Serializable>, noncopyable>(#pyName).def("__init__",python::raw_constructor(Serializable_ctor_kwAttrs<cxxName>)).def("clone",&Serializable_clone<cxxName>,python::arg("attrs")=python::dict())
 	#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("dispIndex",&Indexable_getClassIndex<className>,"Return class index of this instance.").def("dispHierarchy",&Indexable_getClassIndices<className>,(python::arg("names")=true),"Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.")


Follow ups