← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2069: NEW TRY to add the updated version of cohesiveFrictionalContactLaw called cohesiveFrictionalPM (s...

 

------------------------------------------------------------
revno: 2069
committer: Luc Scholtes <sch50p@fluent-ph>
branch nick: trunk
timestamp: Wed 2010-03-10 09:43:53 +1000
message:
  NEW TRY to add the updated version of cohesiveFrictionalContactLaw called cohesiveFrictionalPM (see revision 2068)
added:
  pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.cpp
  pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.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.
=== added file 'pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.cpp'
--- pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.cpp	2010-03-09 23:43:53 +0000
@@ -0,0 +1,189 @@
+/* LucScholtes2010  */
+
+#include"CohesiveFrictionalPM.hpp"
+#include<yade/core/Scene.hpp>
+#include<yade/pkg-dem/ScGeom.hpp>
+#include<yade/core/Omega.hpp>
+
+YADE_PLUGIN((Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM)(Ip2_CFpmMat_CFpmMat_CFpmPhys)(CFpmPhys)(CFpmMat));
+
+/********************** Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM ****************************/
+CREATE_LOGGER(Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM);
+
+void Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM::go(shared_ptr<InteractionGeometry>& ig, shared_ptr<InteractionPhysics>& ip, Interaction* contact, Scene* rootBody){
+	
+	ScGeom* geom = static_cast<ScGeom*>(ig.get()); 
+	CFpmPhys* phys = static_cast<CFpmPhys*>(ip.get());
+	int id1 = contact->getId1();
+        int id2 = contact->getId2();
+	shared_ptr<BodyContainer>& bodies = rootBody->bodies;
+	Body* b1 = ( *bodies ) [id1].get();
+	Body* b2 = ( *bodies ) [id2].get();
+	Real dt = Omega::instance().getTimeStep();
+	
+	Real displN = geom->penetrationDepth; // NOTE: the sign for penetrationdepth is different from ScGeom and Dem3DofGeom: geom->penetrationDepth>0 when spheres interpenetrate
+	Real D = 0; // initial interparticular distance
+	Real Dtensile=phys->FnMax/phys->kn;
+	Real Dsoftening = phys->strengthSoftening*Dtensile; 
+	
+	/*to set the equilibrium distance between all cohesive elements when they first meet*/
+	if ( contact->isFresh(rootBody) && phys->isCohesive) { phys->initD = displN; phys->normalForce = Vector3r::ZERO; phys->shearForce = Vector3r::ZERO;}
+	
+	D = displN - phys->initD; // displacement is computed depending on the equilibrium distance
+	
+	/* Determination of interaction */
+	if (D < 0){ //spheres do not touch 
+	  if (!phys->isCohesive){ rootBody->interactions->requestErase(contact->getId1(),contact->getId2()); return; } // destroy the interaction before calculation
+	  if ((phys->isCohesive) && (abs(D) > (Dtensile + Dsoftening))) { // spheres are bonded and the interacting distance is greater than the one allowed ny the defined cohesion
+	    phys->isCohesive=false; 
+	    rootBody->interactions->requestErase(contact->getId1(),contact->getId2()); return;
+	  }
+	}	  
+	
+	/*NormalForce*/
+	Real Fn=0, Dsoft=0;
+		
+	if ((D < 0) && (abs(D) > Dtensile)) { //to take into account strength softening
+	  Dsoft = D+Dtensile; // Dsoft<0 for a negative value of Fn (attractive force)
+	  Fn = phys->FnMax+(phys->kn/phys->strengthSoftening)*Dsoft; // computes FnMax - FnSoftening
+	}
+	else {
+	  Fn = phys->kn*D;
+	}
+		
+	phys->normalForce = Fn*geom->normal;  // NOTE normal is position2-position1 - It is directed from particle1 to particle2
+	        
+	/*ShearForce*/
+	Vector3r& shearForce = phys->shearForce; 
+		
+	// using scGeom function updateShear(Vector3r& shearForce, Real ks, const Vector3r& prevNormal, const State* rbp1, const State* rbp2, Real dt, bool avoidGranularRatcheting)	
+	State* st1 = Body::byId(id1,rootBody)->state.get();
+	State* st2 = Body::byId(id2,rootBody)->state.get();
+	geom->updateShearForce(shearForce, phys->ks, phys->prevNormal, st1, st2, dt, preventGranularRatcheting);
+	
+	// needed for the next timestep
+	phys->prevNormal = geom->normal;
+		
+	/* Morh-Coulomb criterion */
+	Vector3r Fs = shearForce; // NOTE the following could be done directly with shearForce?
+	Real maxFs = abs(Fn)*phys->tanFrictionAngle + phys->FsMax;
+		
+	if (Fs.SquaredLength() > maxFs*maxFs){ 
+	  phys->isCohesive=false; //if not already false to delete cohesive interactions
+	  Fs*=maxFs/Fs.Length(); // to fix the shear force to its yielding value with the right sign
+	}
+	phys->shearForce = Fs; 
+	
+	/* Apply forces */
+	Vector3r f = phys->normalForce + phys->shearForce;
+	
+	// NOTE applyForceAtContactPoint computes torque induced by normal and shear force too
+ 	applyForceAtContactPoint(f, geom->contactPoint, contact->getId2(), b2->state->pos, contact->getId1(), b1->state->pos, rootBody); // NOTE id1 and id2 must suit the orientation of the force
+
+	/* Moment Rotation Law */
+	// NOTE this part could probably be computed in ScGeom to avoid copy/paste multiplication !!!
+	Quaternionr delta( b1->state->ori * phys->initialOrientation1.Conjugate() *phys->initialOrientation2 * b2->state->ori.Conjugate()); //relative orientation
+	Vector3r axisM;	// axis of rotation - this is the Moment direction UNIT vector.
+	Real angleM;	// angle represents the power of resistant ELASTIC moment
+	delta.ToAxisAngle(axisM,angleM);
+	if(angleM > Mathr::PI) angleM -= Mathr::TWO_PI; // angle is between 0 and 2*pi, but should be between -pi and pi 
+	  
+	phys->cumulativeRotation = angleM;
+	  
+	//Find angle*axis. That's all.  But first find angle about contact normal. Result is scalar. Axis is contact normal.
+	Real angle_twist(angleM * axisM.Dot(geom->normal) ); //rotation about normal
+	Vector3r axis_twist(angle_twist * geom->normal);
+	Vector3r moment_twist(axis_twist * phys->kr);
+	  
+	Vector3r axis_bending(angleM*axisM - axis_twist); //total rotation minus rotation about normal
+	Vector3r moment_bending(axis_bending * phys->kr);
+	Vector3r moment = moment_twist + moment_bending;
+
+	Real MomentMax = phys->maxBend*std::fabs(phys->normalForce.Length());
+	Real scalarMoment = moment.Length();
+
+	/*Plastic moment */
+	if(scalarMoment > MomentMax) 
+	{
+	  Real ratio = 0;
+	  ratio *= MomentMax/scalarMoment; // to fix the moment to its yielding value
+	  moment *= ratio;		
+	  moment_twist *=  ratio;
+	  moment_bending *= ratio;
+	}
+
+	phys->moment_twist = moment_twist;
+	phys->moment_bending = moment_bending;
+	  
+	rootBody->forces.addTorque(id1,-moment);
+	rootBody->forces.addTorque(id2, moment);
+		
+}
+
+CREATE_LOGGER(Ip2_CFpmMat_CFpmMat_CFpmPhys);
+
+void Ip2_CFpmMat_CFpmMat_CFpmPhys::go(const shared_ptr<Material>& b1, const shared_ptr<Material>& b2, const shared_ptr<Interaction>& interaction){
+	
+	/* avoid any updates if the interaction already exists */
+	if(interaction->interactionPhysics) return; 
+
+	ScGeom* geom=dynamic_cast<ScGeom*>(interaction->interactionGeometry.get());
+	assert(geom);
+
+	const shared_ptr<CFpmMat>& yade1 = YADE_PTR_CAST<CFpmMat>(b1);
+	const shared_ptr<CFpmMat>& yade2 = YADE_PTR_CAST<CFpmMat>(b2);
+			
+	shared_ptr<CFpmPhys> contactPhysics(new CFpmPhys()); 
+	
+	/* From interaction physics */
+	Real E1 	= yade1->young;
+	Real E2 	= yade2->young;
+	Real V1 	= yade1->poisson;
+	Real V2 	= yade2->poisson;
+	Real f1 	= yade1->frictionAngle;
+	Real f2 	= yade2->frictionAngle;
+
+	/* From interaction geometry */
+	Real R1= geom->radius1;
+	Real R2= geom->radius2;
+	Real rMean = 0.5*(R1+R2); 
+	Real crossSection = Mathr::PI*pow(min(R1,R2),2); 
+	
+	/* calculate stiffness */
+	Real kNormal=0, kShear=0, kRotate=0;
+	
+	if(useAlphaBeta == true){
+	  kNormal	= 2.*E1*R1*E2*R2/(E1*R1+E2*R2); // harmonic average of two stiffnesses
+	  kShear 	= Alpha*kNormal;
+	  kRotate	= Beta*kShear*rMean*rMean; 
+	}
+	else {
+	  kNormal	= 2.*E1*R1*E2*R2/(E1*R1+E2*R2); // harmonic average of two stiffnesses
+	  kShear	= 2.*E1*R1*V1*E2*R2*V2/(E1*R1*V1+E2*R2*V2); // harmonic average of two stiffnesses with ks=V*kn for each sphere
+	  kRotate	= 0.;
+	}
+
+	/* Pass values calculated from above to CFpmPhys */
+	contactPhysics->kn = kNormal;
+	contactPhysics->ks = kShear;
+	contactPhysics->kr = kRotate;
+	contactPhysics->frictionAngle		= std::min(f1,f2); 
+	contactPhysics->tanFrictionAngle	= std::tan(contactPhysics->frictionAngle); 
+	contactPhysics->maxBend 		= eta*rMean;
+	contactPhysics->prevNormal 		= geom->normal;
+	contactPhysics->initialOrientation1	= Body::byId(interaction->getId1())->state->ori;
+	contactPhysics->initialOrientation2	= Body::byId(interaction->getId2())->state->ori;
+	
+	///to set if the contact is cohesive or not
+	if ( (scene->currentIteration < cohesiveTresholdIteration) && ((tensileStrength>0) || (cohesion>0)) && (yade1->type == yade2->type)){ contactPhysics->isCohesive=true; }
+	
+	if ( contactPhysics->isCohesive ) {
+	  contactPhysics->FnMax = tensileStrength*crossSection;
+	  contactPhysics->strengthSoftening = strengthSoftening;
+	  contactPhysics->FsMax = cohesion*crossSection;
+	}
+	
+	interaction->interactionPhysics = contactPhysics;
+}
+
+CFpmPhys::~CFpmPhys(){}
\ No newline at end of file

=== added file 'pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.hpp'
--- pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Engine/GlobalEngine/CohesiveFrictionalPM.hpp	2010-03-09 23:43:53 +0000
@@ -0,0 +1,101 @@
+/* lucScholtes2010 */
+
+#pragma once
+
+#include<yade/pkg-common/ElastMat.hpp>
+#include<yade/pkg-common/InteractionPhysicsFunctor.hpp>
+#include<yade/pkg-common/NormShearPhys.hpp>
+#include<yade/pkg-common/LawFunctor.hpp>
+#include<yade/pkg-dem/ScGeom.hpp>
+
+/*
+=== OVERVIEW OF CohesiveFrictionalPM ===
+
+CohesiveFrictional Particle Model (CohesiveFrictionalPM, CFpm) is a set of classes for modelling mechanical behavior of cohesive frictional material. It is a quite general contact model starting from the basic frictional model with the possible addition of a moment between particles, a tensile strength and a cohesion.
+
+Features of the interaction law:
+
+1.  If useAlphaBeta=False, Kn, Ks are calculated from the harmonic average of the "macro" material parameters young (E) and poisson (V) as defined in SimpleElasticRelationships.cpp and Kr=0.
+
+2.  If useAlphaBeta=True, users have to input Alpha=Ks/Kn, Beta=Kr/(Ks*meanRadius^2), eta=MtPlastic/(meanRadius*Fn) as defined in Plassiard et al. (Granular Matter, 2009) A spherical discrete element model.
+
+3.  Users can input a tensile strength ( FnMax = tensileStrength*) and a cohesion ( FsMax = cohesion*(Ks*meanRadius))
+
+  Remark: - This contact law works well in the case of sphere/sphere and sphere/box interaction as it uses ScGeom to compute the interaction geometry (suitable for the triaxialTest) 
+	  - It has not been tested for sphere/facet or sphere/wall interactions and could be updated to be used by DemXDofGeom
+*/
+
+/** This class holds information associated with each body */
+class CFpmMat: public FrictMat {
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(CFpmMat,FrictMat,"cohesive frictional material, for use with other CFpm classes",
+	  ((int,type,0,"Type of the particle. If particles of two different types interact, it will be with friction only (no cohesion).[-]")),
+	  createIndex();
+	);
+	REGISTER_CLASS_INDEX(CFpmMat,FrictMat);
+};
+REGISTER_SERIALIZABLE(CFpmMat);
+
+/** This class holds information associated with each interaction */
+class CFpmPhys: public NormShearPhys {
+	public:
+		virtual ~CFpmPhys();
+	
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(CFpmPhys,NormShearPhys,"Representation of a single interaction of the CFpm type, storage for relevant parameters",
+		  ((Real,initD,0,"equilibrium distance for particles. Computed as the initial interparticular distance when bonded particle interact. initD=0 for non cohesive interactions."))
+		  ((bool,isCohesive,false,"If false, particles interact in a frictional way. If true, particles are bonded regarding the given cohesion and tensileStrength."))
+		  ((Real, frictionAngle,0,"defines Coulomb friction. [deg]"))
+		  ((Real,tanFrictionAngle,0,"Tangent of frictionAngle. [-]"))
+		  ((Real,FnMax,0,"Defines the maximum admissible normal force in traction FnMax=tensileStrength*crossSection, with crossSection=pi*Rmin^2. [Pa]"))
+		  ((Real,FsMax,0,"Defines the maximum admissible tangential force in shear FsMax=cohesion*FnMax, with crossSection=pi*Rmin^2. [Pa]"))
+		  ((Real,strengthSoftening,0,"Defines the softening when Dtensile is reached to avoid explosion. Typically, when D > Dtensile, Fn=FnMax - (kn/strengthSoftening)*(Dtensile-D). [-]"))
+		  ((Real,cumulativeRotation,0,"Cumulated rotation... [-]"))
+		  ((Real,kr,0,"Defines the stiffness to compute the resistive moment in rotation. [-]"))
+		  ((Real,maxBend,0,"Defines the maximum admissible resistive moment in rotation Mtmax=maxBend*Fn, maxBend=eta*meanRadius. [m]"))
+		  ((Vector3r,prevNormal,Vector3r::ZERO,"Normal to the contact at previous time step."))
+		  ((Vector3r,moment_twist,Vector3r::ZERO," [N.m]"))
+		  ((Vector3r,moment_bending,Vector3r::ZERO," [N.m]"))
+		  ((Quaternionr,initialOrientation1,Quaternionr(1.0,0.0,0.0,0.0),"Use for moment computation."))
+		  ((Quaternionr,initialOrientation2,Quaternionr(1.0,0.0,0.0,0.0),"Use for moment computation."))
+		  ,
+		  createIndex();
+		  ,
+		);
+	DECLARE_LOGGER;
+	REGISTER_CLASS_INDEX(CFpmPhys,NormShearPhys);
+};
+REGISTER_SERIALIZABLE(CFpmPhys);
+
+/** 2d functor creating InteractionPhysics (Ip2) taking CFpmMat and CFpmMat of 2 bodies, returning type CFpmPhys */
+class Ip2_CFpmMat_CFpmMat_CFpmPhys: public InteractionPhysicsFunctor{
+	public:
+		virtual void go(const shared_ptr<Material>& pp1, const shared_ptr<Material>& pp2, const shared_ptr<Interaction>& interaction);
+		
+		FUNCTOR2D(CFpmMat,CFpmMat);
+		DECLARE_LOGGER;
+		
+		YADE_CLASS_BASE_DOC_ATTRS(Ip2_CFpmMat_CFpmMat_CFpmPhys,InteractionPhysicsFunctor,"Converts 2 CFpmmat instances to CFpmPhys with corresponding parameters.",
+		  ((int,cohesiveTresholdIteration,1,"Should new contacts be cohesive? They will before this iter, they won't afterward."))
+		  ((bool,useAlphaBeta,false,"If true, stiffnesses are computed based on Alpha and Beta."))
+		  ((Real,Alpha,0,"Defines the ratio ks/kn."))
+		  ((Real,Beta,0,"Defines the ratio kr/(ks*meanRadius^2) to compute the resistive moment in rotation. [-]"))
+		  ((Real,eta,0,"Defines the maximum admissible resistive moment in rotation MtMax=eta*meanRadius*Fn. [-]"))
+		  ((Real,tensileStrength,0,"Defines the maximum admissible normal force in traction FnMax=tensileStrength*crossSection. [Pa]"))
+		  ((Real,cohesion,0,"Defines the maximum admissible tangential force in shear FsMax=cohesion*crossSection. [Pa]"))
+		  ((Real,strengthSoftening,0,"Defines the softening when Dtensile is reached to avoid explosion of the contact. Typically, when D > Dtensile, Fn=FnMax - (kn/strengthSoftening)*(Dtensile-D). [-]"))
+		);
+};
+REGISTER_SERIALIZABLE(Ip2_CFpmMat_CFpmMat_CFpmPhys);
+
+
+/** 2d functor creating the interaction law (Law2) based on SphereContactGeometry (ScGeom) and CFpmPhys of 2 bodies, returning type CohesiveFrictionalPM */
+class Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM: public LawFunctor{
+	public:
+		virtual void go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, Scene* rootBody);
+		FUNCTOR2D(ScGeom,CFpmPhys);
+
+	YADE_CLASS_BASE_DOC_ATTRS(Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM,LawFunctor,"Constitutive law for the CFpm model.",
+		  ((bool,preventGranularRatcheting,false,"If true rotations are computed such as granular ratcheting is prevented. See F. ALONSO-MARROQUIN, R. GARCIA-ROJO, H.J. HERRMANN, Micro-mechanical investigation of granular ratcheting, in Cyclic Behaviour of Soils and Liquefaction Phenomena, ed. T. Triantafyllidis (Balklema, London, 2004), p. 3-10 - and a lot more papers from the same authors)."))
+	);
+	DECLARE_LOGGER;	
+};
+REGISTER_SERIALIZABLE(Law2_ScGeom_CFpmPhys_CohesiveFrictionalPM);


Follow ups