← Back to team overview

yade-dev team mailing list archive

[svn] r1788 - in trunk: core gui/py lib/serialization pkg/dem pkg/dem/Engine/StandAloneEngine

 

Author: eudoxos
Date: 2009-06-03 00:02:25 +0200 (Wed, 03 Jun 2009)
New Revision: 1788

Modified:
   trunk/core/InteractionContainer.cpp
   trunk/core/InteractionContainer.hpp
   trunk/gui/py/_utils.cpp
   trunk/gui/py/utils.py
   trunk/lib/serialization/Archive.tpp
   trunk/pkg/dem/ConcretePM.cpp
   trunk/pkg/dem/ConcretePM.hpp
   trunk/pkg/dem/Engine/StandAloneEngine/UniaxialStrainer.cpp
Log:
1. Add epsNPl to Cpm
2. Replace vector<body_id_t> by Vector2<body_id_t> and make it properly serializable (should be faster)
3. Add function to compute forces on interactions crossing plane.
4. Replace custom xcombine function by itertools.product in grid sphere packing


Modified: trunk/core/InteractionContainer.cpp
===================================================================
--- trunk/core/InteractionContainer.cpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/core/InteractionContainer.cpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -11,7 +11,7 @@
 #include "InteractionContainer.hpp"
 
 void InteractionContainer::requestErase(body_id_t id1, body_id_t id2){
-	find(id1,id2)->reset(); bodyIdPair v(0,2); v.push_back(id1); v.push_back(id2); 
+	find(id1,id2)->reset(); bodyIdPair v(id1,id2); //v.push_back(id1); v.push_back(id2); 
 	#ifdef YADE_OPENMP
 		boost::mutex::scoped_lock lock(pendingEraseMutex);
 	#endif

Modified: trunk/core/InteractionContainer.hpp
===================================================================
--- trunk/core/InteractionContainer.hpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/core/InteractionContainer.hpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -104,8 +104,8 @@
 		virtual shared_ptr<Interaction>& operator[] (unsigned int) {throw;};
 		virtual const shared_ptr<Interaction>& operator[] (unsigned int) const {throw;};
 
-		// std::pair is not handle by yade::serialization, use vector<body_id_t> instead
-		typedef vector<body_id_t> bodyIdPair;
+		// std::pair is not handled by yade::serialization, use vector<body_id_t> instead
+		typedef Vector2<body_id_t> bodyIdPair;
 		//! Ask for erasing the interaction given (from the constitutive law); this resets the interaction (to the initial=potential state)
 		//! and collider should traverse pendingErase to decide whether to delete the interaction completely or keep it potential
 		void requestErase(body_id_t id1, body_id_t id2);
@@ -134,7 +134,7 @@
 			method which will be called for every interaction.
 		*/
 		template<class T> void erasePending(const T& t){
-			FOREACH(const vector<body_id_t>& p, pendingErase){ if(t.shouldBeErased(p[0],p[1])) erase(p[0],p[1]); }
+			FOREACH(const Vector2<body_id_t>& p, pendingErase){ if(t.shouldBeErased(p[0],p[1])) erase(p[0],p[1]); }
 			pendingErase.clear();
 		}
 	private :

Modified: trunk/gui/py/_utils.cpp
===================================================================
--- trunk/gui/py/_utils.cpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/gui/py/_utils.cpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -316,8 +316,41 @@
 	vector<Vector2r> hull=ch2d();
 	return simplePolygonArea2d(hull);
 }
+/* Find all interactions deriving from NormalShearInteraction that cross plane given by a point and normal
+	(the normal may not be normalized in this case, though) and sum forces (both normal and shear) on them.
+	
+	Return a 3-tuple with the components along global x,y,z axes.
 
+	(This could be easily extended to return sum of only normal forces or only of shear forces.)
+*/
+python::tuple forcesOnPlane(python::tuple _planePt, python::tuple _normal){
+	Vector3r ret(Vector3r::ZERO), planePt(tuple2vec(_planePt)), normal(tuple2vec(_normal));
+	MetaBody* rootBody=Omega::instance().getRootBody().get();
+	FOREACH(const shared_ptr<Interaction>&I, *rootBody->interactions){
+		if(!I->isReal()) continue;
+		NormalShearInteraction* nsi=dynamic_cast<NormalShearInteraction*>(I->interactionPhysics.get());
+		if(!nsi) continue;
+		Vector3r pos1,pos2;
+		Dem3DofGeom* d3dg=dynamic_cast<Dem3DofGeom*>(I->interactionGeometry.get()); // Dem3DofGeom has copy of se3 in itself, otherwise we have to look up the bodies
+		if(d3dg){ pos1=d3dg->se31.position; pos2=d3dg->se32.position; }
+		else{ pos1=Body::byId(I->getId1(),rootBody)->physicalParameters->se3.position; pos2=Body::byId(I->getId2(),rootBody)->physicalParameters->se3.position; }
+		Real dot1=(pos1-planePt).Dot(normal), dot2=(pos2-planePt).Dot(normal);
+		if(dot1*dot2>0) continue; // both interaction points on the same side of the plane
+		// if pt1 is on the negative plane side, d3dg->normal.Dot(normal)>0, the force is well oriented;
+		// otherwise, reverse its contribution
+		ret+=(dot1<0.?1.:-1.)*(nsi->normalForce+nsi->shearForce);
+	}
+	return vec2tuple(ret);
+}
 
+/* Less general than forcesOnPlane, computes force on plane perpendicular to axis, passing through coordinate coord. */
+python::tuple forcesOnCoordPlane(Real coord, int axis){
+	Vector3r planePt(Vector3r::ZERO); planePt[axis]=coord;
+	Vector3r normal(Vector3r::ZERO); normal[axis]=1;
+	return forcesOnPlane(vec2tuple(planePt),vec2tuple(normal));
+}
+
+
 /* Project 3d point into 2d using spiral projection along given axis;
  * the returned tuple is
  * 	
@@ -383,6 +416,8 @@
 	def("kineticEnergy",Shop__kineticEnergy);
 	def("sumBexForces",sumBexForces);
 	def("sumBexTorques",sumBexTorques);
+	def("forcesOnPlane",forcesOnPlane);
+	def("forcesOnCoordPlane",forcesOnCoordPlane);
 	def("createInteraction",Shop__createExplicitInteraction);
 	def("spiralProject",spiralProject,spiralProject_overloads(args("axis","periodStart","theta0")));
 	def("pointInsidePolygon",pointInsidePolygon);

Modified: trunk/gui/py/utils.py
===================================================================
--- trunk/gui/py/utils.py	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/gui/py/utils.py	2009-06-02 22:02:25 UTC (rev 1788)
@@ -404,42 +404,20 @@
 	l=procStatus('VmData'); ll=l.split(); assert(ll[2]=='kB')
 	return int(ll[1])
 
-
-
-def xcombine(*seqin):
-	'''returns a generator which returns combinations of argument sequences
-for example xcombine((1,2),(3,4)) returns a generator; calling the next()
-method on the generator will return [1,3], [1,4], [2,3], [2,4] and
-StopIteration exception.  This will not create the whole list of 
-combinations in memory at once.
-
-Source: http://code.activestate.com/recipes/302478/'''
-	def rloop(seqin,comb):
-		'''recursive looping function'''
-		if seqin:				   # any more sequences to process?
-			for item in seqin[0]:
-				newcomb=comb+[item]	 # add next item to current combination
-				# call rloop w/ remaining seqs, newcomb
-				for item in rloop(seqin[1:],newcomb):   
-					yield item		  # seqs and newcomb
-		else:						   # processing last sequence
-			yield comb				  # comb finished, add to list
-	return rloop(seqin,[])
-
-
 def regularSphereOrthoPack(center,extents,radius,gap,**kw):
 	"""Return set of spheres regularly spaced in either a box or sphere centered around center.
 	If extents is a number, it is taken for sphere radius; if it is a sequence, it is 3 extents of the box.
 	Created spheres will have given radius and will be separated by gap space.
 	"""
 	from numpy import arange; from math import sqrt
+	import itertools
 	ret=[]
 	try: # extents is a single number, do sphere
 		doSphere=True; dim=float(extents),float(extents),float(extents)
 	except TypeError: # extents is a list, do box
 		doSphere=False; dim=extents
 	xx,yy,zz=[arange(center[i]-dim[i],center[i]+dim[i],2*radius+gap) for i in 0,1,2]
-	for xyz in xcombine(xx,yy,zz):
+	for xyz in itertools.product(xx,yy,zz):
 		if doSphere and sqrt(sum([(xyz[i]-center[i])**2 for i in 0,1,2]))>extents: continue
 		ret+=[sphere(xyz,radius=radius,**kw)]
 	return ret
@@ -461,7 +439,7 @@
 	dim=aabbDim(); axis=dim.index(max(dim))
 	import numpy
 	areas=[approxSectionArea(coord,axis) for coord in numpy.linspace(mm[axis],mx[axis],num=10)[1:-1]]
-	negIds,posIds=negPosExtremeIds(axis=axis)
+	negIds,posIds=negPosExtremeIds(axis=axis,distFactor=2.2)
 	return {'negIds':negIds,'posIds':posIds,'axis':axis,'area':min(areas)}
 
 

Modified: trunk/lib/serialization/Archive.tpp
===================================================================
--- trunk/lib/serialization/Archive.tpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/lib/serialization/Archive.tpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -48,6 +48,10 @@
 			typeid(Type)==typeid(Vector2f)		||
 			typeid(Type)==typeid(Vector2d)		||
 			typeid(Type)==typeid(Vector2<long double>)		||
+			typeid(Type)==typeid(Vector2<signed int>)		||
+			typeid(Type)==typeid(Vector2<unsigned int>)		||
+			typeid(Type)==typeid(Vector2<signed long>)		||
+			typeid(Type)==typeid(Vector2<unsigned long>)		||
 			typeid(Type)==typeid(Vector3f)		||
 			typeid(Type)==typeid(Vector3d)		||
 			typeid(Type)==typeid(Vector3<long double>)		||

Modified: trunk/pkg/dem/ConcretePM.cpp
===================================================================
--- trunk/pkg/dem/ConcretePM.cpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/pkg/dem/ConcretePM.cpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -116,13 +116,14 @@
 }
 
 
-
 /********************** Law2_Dem3DofGeom_CpmPhys_Cpm ****************************/
 
 Real Law2_Dem3DofGeom_CpmPhys_Cpm::minStrain_moveBody2=1.; /* deactivated if > 0 */
 Real Law2_Dem3DofGeom_CpmPhys_Cpm::yieldLogSpeed=1.;
 Real Law2_Dem3DofGeom_CpmPhys_Cpm::yieldEllipseShift=0.;
-Real Law2_Dem3DofGeom_CpmPhys_Cpm::omegaThreshold=0.;
+Real Law2_Dem3DofGeom_CpmPhys_Cpm::omegaThreshold=1.;
+Real Law2_Dem3DofGeom_CpmPhys_Cpm::epsSoft=0.;
+Real Law2_Dem3DofGeom_CpmPhys_Cpm::relKnSoft=.5;
 
 void Law2_Dem3DofGeom_CpmPhys_Cpm::go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, MetaBody* rootBody){
 	//timingDeltas->start();
@@ -130,10 +131,12 @@
 	CpmPhys* BC=static_cast<CpmPhys*>(_phys.get());
 
 	// shorthands
-	Real& epsN(BC->epsN); Vector3r& epsT(BC->epsT); Real& kappaD(BC->kappaD); Real& epsPlSum(BC->epsPlSum); const Real& E(BC->E); const Real& undamagedCohesion(BC->undamagedCohesion); const Real& tanFrictionAngle(BC->tanFrictionAngle); const Real& G(BC->G); const Real& crossSection(BC->crossSection); const Real& omegaThreshold(Law2_Dem3DofGeom_CpmPhys_Cpm::omegaThreshold); const Real& epsCrackOnset(BC->epsCrackOnset); Real& relResidualStrength(BC->relResidualStrength); const Real& dt=Omega::instance().getTimeStep();  const Real& epsFracture(BC->epsFracture); const bool& neverDamage(BC->neverDamage); const Real& dmgTau(BC->dmgTau); const Real& plTau(BC->plTau); const bool& isCohesive(BC->isCohesive);
+	Real& epsN(BC->epsN); Real& epsNPl(BC->epsNPl); Vector3r& epsT(BC->epsT); Real& kappaD(BC->kappaD); Real& epsPlSum(BC->epsPlSum); const Real& E(BC->E); const Real& undamagedCohesion(BC->undamagedCohesion); const Real& tanFrictionAngle(BC->tanFrictionAngle); const Real& G(BC->G); const Real& crossSection(BC->crossSection); const Real& omegaThreshold(Law2_Dem3DofGeom_CpmPhys_Cpm::omegaThreshold); const Real& epsCrackOnset(BC->epsCrackOnset); Real& relResidualStrength(BC->relResidualStrength); const Real& dt=Omega::instance().getTimeStep();  const Real& epsFracture(BC->epsFracture); const bool& neverDamage(BC->neverDamage); const Real& dmgTau(BC->dmgTau); const Real& plTau(BC->plTau); const bool& isCohesive(BC->isCohesive);
 	Real& omega(BC->omega); Real& sigmaN(BC->sigmaN);  Vector3r& sigmaT(BC->sigmaT); Real& Fn(BC->Fn); Vector3r& Fs(BC->Fs); // for python access
 	const Real& yieldLogSpeed(Law2_Dem3DofGeom_CpmPhys_Cpm::yieldLogSpeed); const int& yieldSurfType(Law2_Dem3DofGeom_CpmPhys_Cpm::yieldSurfType);
 	const Real& yieldEllipseShift(Law2_Dem3DofGeom_CpmPhys_Cpm::yieldEllipseShift); 
+	const Real& epsSoft(Law2_Dem3DofGeom_CpmPhys_Cpm::epsSoft); 
+	const Real& relKnSoft(Law2_Dem3DofGeom_CpmPhys_Cpm::relKnSoft); 
 
 	#define YADE_VERIFY(condition) if(!(condition)){LOG_FATAL("Verification `"<<#condition<<"' failed!"); throw;}
 	

Modified: trunk/pkg/dem/ConcretePM.hpp
===================================================================
--- trunk/pkg/dem/ConcretePM.hpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/pkg/dem/ConcretePM.hpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -120,13 +120,15 @@
 			isoPrestress;
 		/*! Up to now maximum normal strain (semi-norm), non-decreasing in time. */
 		Real kappaD;
+		//! normal plastic strain (initially zero)
+		Real epsNPl;
 		/*! Transversal strain (perpendicular to the contact axis) */
 		Real epsTrans;
 		/*! if not cohesive, interaction is deleted when distance is greater than zero. */
 		bool isCohesive;
 		/*! the damage evlution function will always return virgin state */
 		bool neverDamage;
-		/*! cummulative plastic strain measure (scalar) on this contact */
+		/*! cummulative shear plastic strain measure (scalar) on this contact */
 		Real epsPlSum;
 		//! debugging, to see convergence rate
 		static long cummBetaIter, cummBetaCount;
@@ -142,7 +144,7 @@
 
 
 
-		CpmPhys(): NormalShearInteraction(),E(0), G(0), tanFrictionAngle(0), undamagedCohesion(0), crossSection(0), dmgTau(-1), dmgRateExp(0), dmgStrain(0), plTau(-1), plRateExp(0), isoPrestress(0.), kappaD(0.), epsTrans(0.), epsPlSum(0.) { createIndex(); epsT=Vector3r::ZERO; isCohesive=false; neverDamage=false; omega=0; Fn=0; Fs=Vector3r::ZERO; epsPlSum=0; dmgOverstress=0; }
+		CpmPhys(): NormalShearInteraction(),E(0), G(0), tanFrictionAngle(0), undamagedCohesion(0), crossSection(0), dmgTau(-1), dmgRateExp(0), dmgStrain(0), plTau(-1), plRateExp(0), isoPrestress(0.), kappaD(0.), epsNPl(0.), epsTrans(0.), epsPlSum(0.) { createIndex(); epsT=Vector3r::ZERO; isCohesive=false; neverDamage=false; omega=0; Fn=0; Fs=Vector3r::ZERO; epsPlSum=0; dmgOverstress=0; }
 		virtual ~CpmPhys();
 
 		REGISTER_ATTRIBUTES(NormalShearInteraction,
@@ -165,6 +167,7 @@
 			(cummBetaCount)
 
 			(kappaD)
+			(epsNPl)
 			(neverDamage)
 			(epsT)
 			(epsTrans)
@@ -256,11 +259,15 @@
 		static Real omegaThreshold;
 		//! HACK: limit strain on some contacts by moving body #2 in the contact; only if refR1<0 (facet); deactivated if > 0
 		static Real minStrain_moveBody2;
+		//! Strain at which softening in compression starts (set to 0. (default) or positive value to deactivate)
+		static Real epsSoft;
+		//! Relative rigidity of the softening branch in compression (0=perfect elastic-plastic, 1=no softening, >1=hardening)
+		static Real relKnSoft;
 		Law2_Dem3DofGeom_CpmPhys_Cpm(): logStrain(false), yieldSurfType(0) { /*timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);*/ }
 		void go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, MetaBody* rootBody);
 	FUNCTOR2D(Dem3DofGeom,CpmPhys);
 	REGISTER_CLASS_AND_BASE(Law2_Dem3DofGeom_CpmPhys_Cpm,ConstitutiveLaw);
-	REGISTER_ATTRIBUTES(ConstitutiveLaw,(logStrain)(yieldSurfType)(yieldLogSpeed)(yieldEllipseShift)(minStrain_moveBody2)(omegaThreshold));
+	REGISTER_ATTRIBUTES(ConstitutiveLaw,(logStrain)(yieldSurfType)(yieldLogSpeed)(yieldEllipseShift)(minStrain_moveBody2)(omegaThreshold)(epsSoft)(relKnSoft));
 	DECLARE_LOGGER;
 };
 REGISTER_SERIALIZABLE(Law2_Dem3DofGeom_CpmPhys_Cpm);

Modified: trunk/pkg/dem/Engine/StandAloneEngine/UniaxialStrainer.cpp
===================================================================
--- trunk/pkg/dem/Engine/StandAloneEngine/UniaxialStrainer.cpp	2009-05-31 10:09:14 UTC (rev 1787)
+++ trunk/pkg/dem/Engine/StandAloneEngine/UniaxialStrainer.cpp	2009-06-02 22:02:25 UTC (rev 1788)
@@ -81,7 +81,7 @@
 			YADE_CAST<ParticleParameters*>(b->physicalParameters.get())->velocity[axis]=pNormalized*(v1-v0)+v0;
 		}
 	}
-	stressUpdateInterval=max(1,(int)(1e-5/(abs(strainRate)*Omega::instance().getTimeStep())));
+	stressUpdateInterval=min(1000,max(1,(int)(1e-5/(abs(strainRate)*Omega::instance().getTimeStep()))));
 	LOG_INFO("Stress will be updated every "<<stressUpdateInterval<<" steps.");
 
 	/* if we have default (<0) crossSectionArea, try to get it from root's AABB;
@@ -133,13 +133,17 @@
 		}
 	}
 	if(asymmetry==0) dAX*=.5; // apply half on both sides if straining symetrically
-	for(size_t i=0; i<negIds.size(); i++){
-		if(asymmetry==0 || asymmetry==-1 /* for +1, don't move*/) negCoords[i]-=dAX;
-		axisCoord(negIds[i])=negCoords[i]; // update current position
+	if(asymmetry!=1){
+		for(size_t i=0; i<negIds.size(); i++){
+			negCoords[i]-=dAX;
+			axisCoord(negIds[i])=negCoords[i]; // update current position
+		}
 	}
-	for(size_t i=0; i<posIds.size(); i++){
-		if(asymmetry==0 || asymmetry==1 /* for -1, don't move */) posCoords[i]+=dAX;
-		axisCoord(posIds[i])=posCoords[i];
+	if(asymmetry!=-1){
+		for(size_t i=0; i<posIds.size(); i++){
+			posCoords[i]+=dAX;
+			axisCoord(posIds[i])=posCoords[i];
+		}
 	}
 
 	Real axialLength=axisCoord(posIds[0])-axisCoord(negIds[0]);




Follow ups