void Law2_ScGeom6D_CohFrictPhys_CohesionMoment::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
{
	const Real& dt = scene->dt;
	const int &id1 = contact->getId1();
	const int &id2 = contact->getId2();
	ScGeom6D* currentContactGeometry  = YADE_CAST<ScGeom6D*> (ig.get());
	CohFrictPhys* currentContactPhysics = YADE_CAST<CohFrictPhys*> (ip.get());
	Vector3r& shearForce    = currentContactPhysics->shearForce;

	if (contact->isFresh(scene)) shearForce   = Vector3r::Zero();
	Real un     = currentContactGeometry->penetrationDepth;
	Real Fn    = currentContactPhysics->kn*(un-currentContactPhysics->unp);

	if (currentContactPhysics->fragile && (-Fn)> currentContactPhysics->normalAdhesion) {
		// BREAK due to tension
		scene->interactions->requestErase(contact); return;
	} else {
		if ((-Fn)> currentContactPhysics->normalAdhesion) {//normal plasticity
			Fn=-currentContactPhysics->normalAdhesion;
			currentContactPhysics->unp = un+currentContactPhysics->normalAdhesion/currentContactPhysics->kn;
			if (currentContactPhysics->unpMax && currentContactPhysics->unp<currentContactPhysics->unpMax)
				scene->interactions->requestErase(contact); return;
		}
		currentContactPhysics->normalForce = Fn*currentContactGeometry->normal;
		State* de1 = Body::byId(id1,scene)->state.get();
		State* de2 = Body::byId(id2,scene)->state.get();
		///////////////////////// CREEP START ///////////
		if (shear_creep) shearForce -= currentContactPhysics->ks*(shearForce*dt/creep_viscosity);
		///////////////////////// CREEP END ////////////

		Vector3r& shearForce = currentContactGeometry->rotate(currentContactPhysics->shearForce);
		const Vector3r& dus = currentContactGeometry->shearIncrement();

		//Linear elasticity giving "trial" shear force
		shearForce -= currentContactPhysics->ks*dus;

		Real Fs = currentContactPhysics->shearForce.norm();
		Real maxFs = currentContactPhysics->shearAdhesion;
		if (!currentContactPhysics->cohesionDisablesFriction || maxFs==0)
			maxFs += Fn*currentContactPhysics->tangensOfFrictionAngle;
		maxFs = std::max((Real) 0, maxFs);
		if (Fs  > maxFs) {//Plasticity condition on shear force
			if (currentContactPhysics->fragile && !currentContactPhysics->cohesionBroken) {
				currentContactPhysics->SetBreakingState();
				maxFs = max((Real) 0, Fn*currentContactPhysics->tangensOfFrictionAngle);
			}
			maxFs = maxFs / Fs;
			Vector3r trialForce=shearForce;
			shearForce *= maxFs;
			Real dissip=((1/currentContactPhysics->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
			if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);
			if (Fn<0)  currentContactPhysics->normalForce = Vector3r::Zero();//Vector3r::Zero()
		}
		applyForceAtContactPoint(-currentContactPhysics->normalForce-shearForce, currentContactGeometry->contactPoint, id1, de1->se3.position, id2, de2->se3.position);

		/// Moment law  ///
		if (currentContactPhysics->momentRotationLaw && (!currentContactPhysics->cohesionBroken || always_use_moment_law)) {
			if (!useIncrementalForm){
				if (twist_creep) {
					Real viscosity_twist = creep_viscosity * std::pow((2 * std::min(currentContactGeometry->radius1,currentContactGeometry->radius2)),2) / 16.0;
					Real angle_twist_creeped = currentContactGeometry->getTwist() * (1 - dt/viscosity_twist);
					Quaternionr q_twist(AngleAxisr(currentContactGeometry->getTwist(),currentContactGeometry->normal));
					Quaternionr q_twist_creeped(AngleAxisr(angle_twist_creeped,currentContactGeometry->normal));
					Quaternionr q_twist_delta(q_twist_creeped * q_twist.conjugate());
					currentContactGeometry->twistCreep = currentContactGeometry->twistCreep * q_twist_delta;
				}
				currentContactPhysics->moment_twist = (currentContactGeometry->getTwist()*currentContactPhysics->ktw)*currentContactGeometry->normal;
				currentContactPhysics->moment_bending = currentContactGeometry->getBending() * currentContactPhysics->kr;
			}	
			else{ // Use incremental formulation to compute moment_twis and moment_bending (no twist_creep is applied)
				if (twist_creep) throw std::invalid_argument("Law2_ScGeom6D_CohFrictPhys_CohesionMoment: no twis creep is included if the incremental form for the rotations is used.");
				Vector3r relAngVel = currentContactGeometry->getRelAngVel(de1,de2,dt);
				// *** Bending ***//
				Vector3r relAngVelBend = relAngVel - currentContactGeometry->normal.dot(relAngVel)*currentContactGeometry->normal; // keep only the bending part 
				Vector3r relRotBend = relAngVelBend*dt; // relative rotation due to rolling behaviour	
				// incremental formulation for the bending moment (as for the shear part)
				Vector3r& momentBend = currentContactPhysics->moment_bending;
				momentBend = currentContactGeometry->rotate(momentBend); // rotate moment vector (updated)
				momentBend = momentBend-currentContactPhysics->kr*relRotBend;
				// ----------------------------------------------------------------------------------------
				// *** Torsion ***//
				Vector3r relAngVelTwist = currentContactGeometry->normal.dot(relAngVel)*currentContactGeometry->normal;
				Vector3r relRotTwist = relAngVelTwist*dt; // component of relative rotation along n  FIXME: sign?
				// incremental formulation for the torsional moment
				Vector3r& momentTwist = currentContactPhysics->moment_twist;
				momentTwist = currentContactGeometry->rotate(momentTwist); // rotate moment vector (updated)
				momentTwist = momentTwist-currentContactPhysics->ktw*relRotTwist; // FIXME: sign?
			}
			/// Plasticity ///
			// limit rolling moment to the plastic value, if required
			Real RollMax = currentContactPhysics->maxRollPl*currentContactPhysics->normalForce.norm();
			if (RollMax>0.){ // do we want to apply plasticity?
				LOG_WARN("If :yref:`CohesiveFrictionalContactLaw::useIncrementalForm` is false, then plasticity would not be applied correctly (the total formulation would not reproduce irreversibility).");
				Real scalarRoll = currentContactPhysics->moment_bending.norm();		
				if (scalarRoll>RollMax){ // fix maximum rolling moment
					Real ratio = RollMax/scalarRoll;
					currentContactPhysics->moment_bending *= ratio;	
				}	
			}
			// limit twisting moment to the plastic value, if required
			Real TwistMax = currentContactPhysics->maxTwistMoment.norm();
			if (TwistMax>0.){ // do we want to apply plasticity?
				LOG_WARN("If :yref:`CohesiveFrictionalContactLaw::useIncrementalForm` is false, then plasticity would not be applied correctly (the total formulation would not reproduce irreversibility).");
				Real scalarTwist= currentContactPhysics->moment_twist.norm();		
				if (scalarTwist>TwistMax){ // fix maximum rolling moment
					Real ratio = TwistMax/scalarTwist;
					currentContactPhysics->moment_twist *= ratio;	
				}	
			}
			// Apply moments now
			Vector3r moment = currentContactPhysics->moment_twist + currentContactPhysics->moment_bending;
			scene->forces.addTorque(id1,-moment);
			scene->forces.addTorque(id2, moment);			
		}
		/// Moment law END       ///
	}
}
void Ip2_CohFrictMat_CohFrictMat_CohFrictPhys::go(const shared_ptr<Material>& b1    // CohFrictMat
                                        , const shared_ptr<Material>& b2 // CohFrictMat
                                        , const shared_ptr<Interaction>& interaction)
{
	CohFrictMat* sdec1 = static_cast<CohFrictMat*>(b1.get());
	CohFrictMat* sdec2 = static_cast<CohFrictMat*>(b2.get());
	ScGeom6D* geom = YADE_CAST<ScGeom6D*>(interaction->geom.get());

	//Create cohesive interractions only once
	if (setCohesionNow && cohesionDefinitionIteration==-1) cohesionDefinitionIteration=scene->iter;
	if (setCohesionNow && cohesionDefinitionIteration!=-1 && cohesionDefinitionIteration!=scene->iter) {
		cohesionDefinitionIteration = -1;
		setCohesionNow = 0;}

	if (geom) {
		if (!interaction->phys) {
			interaction->phys = shared_ptr<CohFrictPhys>(new CohFrictPhys());
			CohFrictPhys* contactPhysics = YADE_CAST<CohFrictPhys*>(interaction->phys.get());
			Real Ea 	= sdec1->young;
			Real Eb 	= sdec2->young;
			Real Va 	= sdec1->poisson;
			Real Vb 	= sdec2->poisson;
			Real Da 	= geom->radius1;
			Real Db 	= geom->radius2;
			Real fa 	= sdec1->frictionAngle;
			Real fb 	= sdec2->frictionAngle;
			Real Kn = 2.0*Ea*Da*Eb*Db/(Ea*Da+Eb*Db);//harmonic average of two stiffnesses

			// harmonic average of alphas parameters
			Real AlphaKr = 2.0*sdec1->alphaKr*sdec2->alphaKr/(sdec1->alphaKr+sdec2->alphaKr);
			Real AlphaKtw;
			if (sdec1->alphaKtw && sdec2->alphaKtw) AlphaKtw = 2.0*sdec1->alphaKtw*sdec2->alphaKtw/(sdec1->alphaKtw+sdec2->alphaKtw);
			else AlphaKtw=0;

			Real Ks;
			if (Va && Vb) Ks = 2.0*Ea*Da*Va*Eb*Db*Vb/(Ea*Da*Va+Eb*Db*Vb);//harmonic average of two stiffnesses with ks=V*kn for each sphere
			else Ks=0;

			contactPhysics->kr = Da*Db*Ks*AlphaKr;
			contactPhysics->ktw = Da*Db*Ks*AlphaKtw;
			contactPhysics->tangensOfFrictionAngle		= std::tan(std::min(fa,fb));

			if ((setCohesionOnNewContacts || setCohesionNow) && sdec1->isCohesive && sdec2->isCohesive)
			{
				contactPhysics->cohesionBroken = false;
				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(Db, Da),2);
				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(Db, Da),2);
				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
			}
			contactPhysics->kn = Kn;
			contactPhysics->ks = Ks;

			contactPhysics->maxRollPl = min(sdec1->etaRoll*Da,sdec2->etaRoll*Db);
			contactPhysics->maxTwistPl = min(sdec1->etaTwist*Da,sdec2->etaTwist*Db);
			contactPhysics->momentRotationLaw=(sdec1->momentRotationLaw && sdec2->momentRotationLaw);
		}
		else {// !isNew, but if setCohesionNow, all contacts are initialized like if they were newly created
			CohFrictPhys* contactPhysics = YADE_CAST<CohFrictPhys*>(interaction->phys.get());
			if ((setCohesionNow && sdec1->isCohesive && sdec2->isCohesive) || contactPhysics->initCohesion)
			{
				contactPhysics->cohesionBroken = false;
				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(geom->radius2, geom->radius1),2);

				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
				contactPhysics->initCohesion=false;
			}
		}
	}
};
void Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
{
// 	cout<<"Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment"<<endl;
	const Real& dt = scene->dt;
	const int &id1 = contact->getId1();
	const int &id2 = contact->getId2();
	ScGeom6D* geom  = YADE_CAST<ScGeom6D*> (ig.get());
	InelastCohFrictPhys* phys = YADE_CAST<InelastCohFrictPhys*> (ip.get());
	Vector3r& shearForce    = phys->shearForce;
			
	cout<<"id1= "<<id1<<" id2= "<<id2<<endl;
	
	if (contact->isFresh(scene)) shearForce   = Vector3r::Zero();
		
	///Tension-Compresion///
	
	Real un     = geom->penetrationDepth;
	Real Fn = phys->knT*(un);
	//FIXME: Check signs on TESTS
	State* de1 = Body::byId(id1,scene)->state.get();
	State* de2 = Body::byId(id2,scene)->state.get();
	
	
	if(!(phys->isBrokenT)){
		
		/// Tension ///
		if(un<=0){
			if((un>= -(phys->dElT)) && !onplastT){
				Fn = phys->knT*(un);
// 				cout<<"TENSION ELASTIC Fn= "<<Fn<<" un= "<<un<<endl;
			}
			if(un< -(phys->dElT) || onplastT){
				onplastT = true;
				Fn = phys->knT*(-phys->dElT) + phys->crpT*(un+phys->dElT);
// 				cout<<"TENSION PLASTIC Fn= "<<Fn<<" un= "<<un<<" normalF= "<<phys->normalForce.norm()<<endl;
				
				if(phys->unloadedT ||(-phys->normalForce.norm()<=Fn)){
					Fn = phys->knT*(-phys->dElT)+ phys->crpT*(lastPlastUn+phys->dElT) + phys->unldT*(un-lastPlastUn);
					phys->unloadedT = true; 
// 					cout<<"TENSION PLASTIC unloading Fn= "<<Fn<<" un= "<<un<<endl;
					
					if(un<=lastPlastUn){ // Recovers creep after unload and reload
						phys->unloadedT=false;
						Fn = phys->knT*(-phys->dElT) + phys->crpT*(un+phys->dElT);
// 						cout<<"TENSION PLASTIC load aftr unld Fn= "<<Fn<<" un= "<<un<<" LPun= "<<lastPlastUn<<endl;
					}
					
				} // Unloading::  //FIXME: ?? Check Fn Sign
				else{// loading, applying Creeping
					lastPlastUn = un;
// 					cout<<"TENSION PLASTIC Creep Fn= "<<Fn<<" un= "<<un<<endl;
					
					if (un<-phys->epsMaxT){ // Plastic rupture //
						Fn = 0.0;
						phys->isBrokenT = true;  
// 						cout<<"TENSION PLASTIC creep BROKEN Fn= "<<Fn<<" un= "<<un<<endl;
					}
				}  
			}
		}
		/// Compresion ///
		if(un>0){
			if((un<=phys->dElC) && !onplastT){
				Fn = phys->knC*(un);
// 				cout<<"COMPRESION ELASTIC Fn= "<<Fn<<" un= "<<un<<endl;

			}
			if(un>phys->dElC || onplastT){
				onplastT = true;
				Fn = phys->knC*(phys->dElC) + phys->crpT*(un-phys->dElC);
				if(phys->unloadedC || (phys->normalForce.norm()>=Fn)){
					Fn = phys->knC*(phys->dElC)+ phys->crpT*(lastPlastUn-phys->dElC) + phys->unldT*(un-lastPlastUn);
					phys->unloadedC = true; 
// 					cout<<"COMPRESION PLASTIC unloading Fn= "<<Fn<<" un= "<<un<<endl;
					
					if(un>=lastPlastUn){ // Recovers creep after unload and reload
						phys->unloadedC=false;
						Fn = phys->knC*(phys->dElC) + phys->crpT*(un-phys->dElC);
// 						cout<<"COMPRESION PLASTIC load aftr unld Fn= "<<Fn<<" un= "<<un<<" LPun= "<<lastPlastUn<<endl;
					}
				
				} // Unloading::  //FIXME: Verify Fn Sign
				else{// loading, applying Creeping
					lastPlastUn = un;
// 					cout<<"COMPRESION PLASTIC Creep Fn= "<<Fn<<" un= "<<un<<endl;
					// Fn stills Fn = phys->crpT*(un-phys->unp) ;}
					if (un>phys->epsMaxC){ // Plastic rupture //
						Fn = 0.0;
						phys->isBrokenT = true;  
// 						cout<<"COMPRESION PLASTIC creep BROKEN Fn= "<<Fn<<" un= "<<un<<endl;
					}
				}  
			}
		}
	phys->normalForce = Fn*geom->normal;
	}
// 	if ((-Fn)> phys->normalAdhesion) {//normal plasticity
// 		Fn=-phys->normalAdhesion;
// 		phys->unp = un+phys->normalAdhesion/phys->kn;
// 		if (phys->unpMax && phys->unp<phys->unpMax)
// 			scene->interactions->requestErase(contact); return;
// 	}
	
	// 	cout<<"Tension-Comp normalF= "<<phys->normalForce<<endl;
	///end tension-compresion///
	
	///Shear/// ELASTOPLASTIC perfect law TO BE DONE
	//FIXME:: TO DO::Shear ElastoPlastic perfect LAW  
	///////////////////////// CREEP START ///////////
	if (shear_creep) shearForce -= phys->ks*(shearForce*dt/creep_viscosity);
	///////////////////////// CREEP END ////////////

	shearForce = geom->rotate(phys->shearForce);
	const Vector3r& dus = geom->shearIncrement();

	//Linear elasticity giving "trial" shear force
	shearForce -= phys->ks*dus;
	
	
	Real Fs = phys->shearForce.norm();
	Real maxFs = phys->shearAdhesion;
	
	
	if (!phys->cohesionDisablesFriction || maxFs==0)
		maxFs += Fn*phys->tangensOfFrictionAngle;
		maxFs = std::max((Real) 0, maxFs);
	if (Fs  > maxFs) {//Plasticity condition on shear force
// 		cout<<"Plastshear ShearAdh= "<<phys->shearAdhesion<<endl;
		if (phys->fragile && !phys->cohesionBroken) {
			phys->SetBreakingState();
			maxFs = max((Real) 0, Fn*phys->tangensOfFrictionAngle);
		}
		maxFs = maxFs / Fs;
		Vector3r trialForce=shearForce;
		shearForce *= maxFs;
		if (unlikely(scene->trackEnergy)){
			Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
			if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);}
		if (Fn<0)  phys->normalForce = Vector3r::Zero();//Vector3r::Zero()
	}
// 	cout<<"Fs= "<<Fs<<" maxFs= "<<maxFs<<endl;

	//Apply the force
	applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position + (scene->isPeriodic ? scene->cell->intrShiftPos(contact->cellDist): Vector3r::Zero()));
// 		Vector3r force = -phys->normalForce-shearForce;
// 		scene->forces.addForce(id1,force);
// 		scene->forces.addForce(id2,-force);
// 		scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
// 		scene->forces.addTorque(id2,(geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force));
	/// end Shear ///
	
	/// Moment law  ///
	/// Bending///
	if(!(phys->isBrokenB)){
		Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
		Vector3r relAngVelBend = relAngVel - geom->normal.dot(relAngVel)*geom->normal; // keep only the bending part
		Vector3r relRotBend = relAngVelBend*dt; // relative rotation due to rolling behaviour	
		Vector3r& momentBend = phys->moment_bending;
		momentBend = geom->rotate(momentBend); // rotate moment vector (updated)

		//To check if in elastic zone in current iteration
		Real BendValue = (phys->moment_bending-phys->kr*relRotBend).norm();
		Real MaxElastB = phys->maxElastB;
		bool elasticBState = (BendValue<=MaxElastB);
		
		if(!onplastB && elasticBState){
			momentBend = momentBend-phys->kr*relRotBend;
// 			cout<<"BENDING Elastic"<<" momentB= "<<momentBend<<endl;
		
		}else{  ///Bending Plasticity///
			onplastB = true;
			BendValue = (phys->moment_bending-phys->crpB*relRotBend).norm();
// 			cout<<"BENDING Plastic"<<" momentB= "<<momentBend<<endl;
			// Unloading:: RelRotBend > 0 ::::
			if(phys->unloadedB || phys->moment_bending.norm()>=BendValue){
				momentBend = momentBend-phys->unldB*relRotBend;
				phys->unloadedB = true; 
// 				cout<<"BENDING Plastic UNLD"<<" momentB= "<<momentBend<<endl;
				if(BendValue>=lastPlastBend){phys->unloadedB = false;} 
				
			} 
			else{
				momentBend = momentBend-phys->crpB*relRotBend;// loading, applying Creeping
				Vector3r AbsRot = de1->rot()-de2->rot();
				Real AbsBending = (AbsRot - geom->normal.dot(AbsRot)*geom->normal).norm();
				lastPlastBend= BendValue;
				if (AbsBending>phys->phBMax){ // Plastic rupture //FIXME: This line is not ok, need to find the compare the total(or just plastic) angular displacement to PhBmax, true meaning of relRotBend??
					momentBend = Vector3r(0,0,0);
					phys->isBrokenB = true;
// 					cout<<"BENDING Plastic BREAK"<<" momentB= "<<momentBend<<endl;
				}
			}	
		}
		phys->moment_bending = momentBend;
	}	
	
	///Twist///
	
	if(!(phys->isBrokenTw)){
		Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
		Vector3r relAngVelTwist = geom->normal.dot(relAngVel)*geom->normal;
		Vector3r relRotTwist = relAngVelTwist*dt; // component of relative rotation along n  FIXME: sign?
		Vector3r& momentTwist = phys->moment_twist;
		momentTwist = geom->rotate(momentTwist); // rotate moment vector (updated)
		
		//To check if in elastic zone in current iteration
		Real TwistValue = (phys->moment_twist-phys->kt*relRotTwist).norm();
		Real MaxElastTw = phys->maxElastTw;
		bool elasticTwState = (TwistValue<=MaxElastTw);
		
		if (!onplastTw && elasticTwState){
			momentTwist = momentTwist-phys->kt*relRotTwist; // FIXME: sign?
// 			cout<<"TWIST Elast"<<" momentTwist="<<momentTwist<<endl;
		}else {  ///Twist Plasticity///
			onplastTw = true;
			TwistValue = (phys->moment_twist-phys->crpTw*relRotTwist).norm();
// 			cout<<"TWIST Plast"<<endl;
			if (phys->unloadedTw || phys->moment_twist.norm()>=TwistValue){// Unloading:: RelRotTwist > 0 
				momentTwist = momentTwist-phys->unldTw*relRotTwist;
				phys->unloadedTw = true; 
// 				cout<<"TWIST Plast UNLD"<<endl;
				if(TwistValue>=lastPlastTw){phys->unloadedTw = false;} 
			} 
			    
			else{momentTwist = momentTwist-phys->crpTw*relRotTwist;// loading, applying Creeping
				Vector3r AbsRot = de1->rot()-de2->rot();
				Real AbsTwist = (geom->normal.dot(AbsRot)*geom->normal).norm();
				lastPlastTw= TwistValue;
// 				cout<<"TWIST Creep momentTwist="<<momentTwist<<" AbsTwist="<<AbsTwist<<endl;
				if (AbsTwist>phys->phTwMax){ // Plastic rupture //FIXME: This line is not ok, need to find the compare the total(or just plastic) angular displacement to PhBmax, true meaning of relRotBend??
					momentTwist = Vector3r(0,0,0);
					phys->isBrokenTw = true;
				}
			} 
		}
		phys->moment_twist = momentTwist;
	}
	
// 	cout<<"moment Twist= "<<phys->moment_twist<<endl;

	
	// Apply moments now
	Vector3r moment = phys->moment_twist + phys->moment_bending;
	scene->forces.addTorque(id1,-moment);
	scene->forces.addTorque(id2, moment);			
	/// Moment law END ///

}
Esempio n. 4
0
bool Law2_ScGeom6D_NormalInelasticityPhys_NormalInelasticity::go(shared_ptr<IGeom>& iG, shared_ptr<IPhys>& iP, Interaction* contact)
{
	int id1 = contact->getId1();
	int id2 = contact->getId2();
// 	cout << "contact entre " << id1 << " et " << id2;

	NormalInelasticMat* Mat1 = static_cast<NormalInelasticMat*>(Body::byId(id1,scene)->material.get());
	ScGeom6D* geom		= YADE_CAST<ScGeom6D*>(iG.get());
	NormalInelasticityPhys* currentContactPhysics = YADE_CAST<NormalInelasticityPhys*> (iP.get());

	Vector3r& shearForce 			= currentContactPhysics->shearForce;

	if (contact->isFresh(scene))
		{
		shearForce			= Vector3r::Zero();
		currentContactPhysics->previousun=0.0;
		currentContactPhysics->previousFn=0.0;
		currentContactPhysics->unMax=0.0;
		}

	un = geom->penetrationDepth; // >0 for real penetration

// Check if there is a real overlap or not. The Ig2... seems to let exist interactions with negative un (= no overlap). Such interactions seem then to have to be deleted here.
        if (   un < 0      )
        {
		 return false;// this, among other things, resets the interaction : geometry and physics variables (as forces, ...) are reset to defaut values
        }



//	********	Computation of normal Force : depends of the history			*******	 //

// 	cout << " Dans Law2 valeur de kn : " << currentContactPhysics->kn << endl;
// 	cout << "un = " << un << " alors que unMax = "<< currentContactPhysics->unMax << " et previousun = " << currentContactPhysics->previousun << " et previousFn =" << currentContactPhysics->previousFn << endl;

	if(un >= currentContactPhysics->unMax)	// case of virgin load : on the "principal line" (limit state of the (un,Fn) space)
	{
		Fn = currentContactPhysics->knLower*un;
		currentContactPhysics->unMax = std::abs(un);
// 		cout << "je suis dans le calcul normal " << endl;
	}
	else// a priori then we need a greater stifness. False in the case when we are already on the limit state, but a correction below will then do the job
	{
		currentContactPhysics->kn = currentContactPhysics->knLower* Mat1->coeff_dech;
		// Incremental computation of the new normal force :
		Fn = currentContactPhysics->previousFn + currentContactPhysics->kn * (un-currentContactPhysics->previousun);
// 		cout << "je suis dans l'autre calcul" << endl;
		if(std::abs(Fn) > std::abs(currentContactPhysics->knLower * un))	// check if the limit state is not violated
		{
		    Fn = currentContactPhysics->knLower*un;
// 		    cout <<  "j'etais dans l'autre calcul mais j'ai corrige pour ne pas depasser la limite" << endl;
		}
		if(Fn < 0.0 )	// check to stay >=0
		{
			Fn = 0;
// 			cout << "j'ai corrige pour ne pas etre negatif" << endl;
		}
	}
	currentContactPhysics->normalForce	= Fn*geom->normal;
// 	cout << "Fn appliquee " << Fn << endl << endl;

	// actualisation :
	currentContactPhysics->previousFn = Fn;
	currentContactPhysics->previousun = un;

// 	*** End of computation of normal force *** //



//	********	Tangential force				*******	 //
        if (   un < 0      )
        { // BREAK due to tension
		return false;
        }
        else
        {
		// Correction of previous shear force to take into account the change in normal:
		shearForce = 	geom->rotate(currentContactPhysics->shearForce);
		// Update of shear force corresponding to shear displacement increment:
		shearForce -= currentContactPhysics->ks * geom->shearIncrement();

                Fs = currentContactPhysics->shearForce.norm();
                maxFs = std::max((Real) 0,Fn*currentContactPhysics->tangensOfFrictionAngle);

                if ( Fs  > maxFs )
                {
			maxFs = max((Real) 0, Fn * currentContactPhysics->tangensOfFrictionAngle);

			maxFs = maxFs / Fs;
			if (maxFs>1)
                        	cerr << "maxFs>1!!!!!!!!!!!!!!!!!!!" << endl;
                    	shearForce *= maxFs;
			if (Fn<0)  currentContactPhysics->normalForce = Vector3r::Zero();
                }


                f	= currentContactPhysics->normalForce + shearForce;
		scene->forces.addForce (id1,-f);
		scene->forces.addForce (id2, f);
		scene->forces.addTorque(id1,-(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(f));
		scene->forces.addTorque(id2, -(geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(f));
// 	*** End of computation of tangential force *** //


//	********	Moment law				*******	 //

		if(momentRotationLaw)
		{
			currentContactPhysics->moment_twist = (geom->getTwist()*currentContactPhysics->kr)*geom->normal ;
			currentContactPhysics->moment_bending = geom->getBending() * currentContactPhysics->kr;

			moment = currentContactPhysics->moment_twist + currentContactPhysics->moment_bending;

// 	Limitation by plastic threshold of this part of the moment caused by relative twist and bending
			if (!momentAlwaysElastic)
			{
				Real normeMomentMax = currentContactPhysics->forMaxMoment * std::abs(Fn);
				if(moment.norm()>normeMomentMax)
					{
					moment *= normeMomentMax/moment.norm();
					}
			}
			scene->forces.addTorque(id1,-moment);
			scene->forces.addTorque(id2, moment);
		}
//	********	Moment law END				*******	 //
    }
    return true;
}
bool Law2_ScGeom6D_CohFrictPhys_CohesionMoment::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
{
	const Real& dt = scene->dt;
	const int &id1 = contact->getId1();
	const int &id2 = contact->getId2();
	ScGeom6D* geom  = YADE_CAST<ScGeom6D*> (ig.get());
	CohFrictPhys* phys = YADE_CAST<CohFrictPhys*> (ip.get());
	Vector3r& shearForce    = phys->shearForce;

	if (contact->isFresh(scene)) shearForce   = Vector3r::Zero();
	Real un     = geom->penetrationDepth;
	Real Fn    = phys->kn*(un-phys->unp);

	if (phys->fragile && (-Fn)> phys->normalAdhesion) {
		// BREAK due to tension
		return false;
	} else {
		if ((-Fn)> phys->normalAdhesion) {//normal plasticity
			Fn=-phys->normalAdhesion;
			phys->unp = un+phys->normalAdhesion/phys->kn;
			if (phys->unpMax>=0 && -phys->unp>phys->unpMax)  // Actually unpMax should be defined as a function of the average particule sizes for instance
				return false;
		}
		phys->normalForce = Fn*geom->normal;
		State* de1 = Body::byId(id1,scene)->state.get();
		State* de2 = Body::byId(id2,scene)->state.get();
		///////////////////////// CREEP START ///////////
		if (shear_creep) shearForce -= phys->ks*(shearForce*dt/creep_viscosity);
		///////////////////////// CREEP END ////////////

		Vector3r& shearForce = geom->rotate(phys->shearForce);
		const Vector3r& dus = geom->shearIncrement();

		//Linear elasticity giving "trial" shear force
		shearForce -= phys->ks*dus;

		Real Fs = phys->shearForce.norm();
		Real maxFs = phys->shearAdhesion;
		if (!phys->cohesionDisablesFriction || maxFs==0)
			maxFs += Fn*phys->tangensOfFrictionAngle;
		maxFs = std::max((Real) 0, maxFs);
		if (Fs  > maxFs) {//Plasticity condition on shear force
			if (phys->fragile && !phys->cohesionBroken) {
				phys->SetBreakingState();
				maxFs = max((Real) 0, Fn*phys->tangensOfFrictionAngle);
			}
			maxFs = maxFs / Fs;
			Vector3r trialForce=shearForce;
			shearForce *= maxFs;
			if (scene->trackEnergy || traceEnergy){
				Real sheardissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
				if(sheardissip>0) {
					plasticDissipation+=sheardissip;
					if (scene->trackEnergy) scene->energy->add(sheardissip,"shearDissip",shearDissipIx,/*reset*/false);}
			}
			if (Fn<0)  phys->normalForce = Vector3r::Zero();//Vector3r::Zero()
		}
		//Apply the force
		applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position + (scene->isPeriodic ? scene->cell->intrShiftPos(contact->cellDist): Vector3r::Zero()));

		/// Moment law  ///
		if (phys->momentRotationLaw && (!phys->cohesionBroken || always_use_moment_law)) {
			if (!useIncrementalForm){
				if (twist_creep) {
					Real viscosity_twist = creep_viscosity * std::pow((2 * std::min(geom->radius1,geom->radius2)),2) / 16.0;
					Real angle_twist_creeped = geom->getTwist() * (1 - dt/viscosity_twist);
					Quaternionr q_twist(AngleAxisr(geom->getTwist(),geom->normal));
					Quaternionr q_twist_creeped(AngleAxisr(angle_twist_creeped,geom->normal));
					Quaternionr q_twist_delta(q_twist_creeped * q_twist.conjugate());
					geom->twistCreep = geom->twistCreep * q_twist_delta;
				}
				phys->moment_twist = (geom->getTwist()*phys->ktw)*geom->normal;
				phys->moment_bending = geom->getBending() * phys->kr;
			}	
			else{ // Use incremental formulation to compute moment_twis and moment_bending (no twist_creep is applied)
				if (twist_creep) throw std::invalid_argument("Law2_ScGeom6D_CohFrictPhys_CohesionMoment: no twis creep is included if the incremental form for the rotations is used.");
				Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
				// *** Bending ***//
				Vector3r relAngVelBend = relAngVel - geom->normal.dot(relAngVel)*geom->normal; // keep only the bending part
				Vector3r relRotBend = relAngVelBend*dt; // relative rotation due to rolling behaviour	
				// incremental formulation for the bending moment (as for the shear part)
				Vector3r& momentBend = phys->moment_bending;
				momentBend = geom->rotate(momentBend); // rotate moment vector (updated)
				momentBend = momentBend-phys->kr*relRotBend;
				// ----------------------------------------------------------------------------------------
				// *** Torsion ***//
				Vector3r relAngVelTwist = geom->normal.dot(relAngVel)*geom->normal;
				Vector3r relRotTwist = relAngVelTwist*dt; // component of relative rotation along n  FIXME: sign?
				// incremental formulation for the torsional moment
				Vector3r& momentTwist = phys->moment_twist;
				momentTwist = geom->rotate(momentTwist); // rotate moment vector (updated)
				momentTwist = momentTwist-phys->ktw*relRotTwist; // FIXME: sign?
			}
			/// Plasticity ///
			// limit rolling moment to the plastic value, if required
			if (phys->maxRollPl>=0.){ // do we want to apply plasticity?
				Real RollMax = phys->maxRollPl*phys->normalForce.norm();
				if (!useIncrementalForm) LOG_WARN("If :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::useIncrementalForm` is false, then plasticity will not be applied correctly (the total formulation would not reproduce irreversibility).");
				Real scalarRoll = phys->moment_bending.norm();
				if (scalarRoll>RollMax){ // fix maximum rolling moment
					Real ratio = RollMax/scalarRoll;
					phys->moment_bending *= ratio;
					if (scene->trackEnergy){
						Real bendingdissip=((1/phys->kr)*(scalarRoll-RollMax)*RollMax)/*active force*/;
						if(bendingdissip>0) scene->energy->add(bendingdissip,"bendingDissip",bendingDissipIx,/*reset*/false);}
				}
			}
			// limit twisting moment to the plastic value, if required
			if (phys->maxTwistPl>=0.){ // do we want to apply plasticity?
				Real TwistMax = phys->maxTwistPl*phys->normalForce.norm();
				if (!useIncrementalForm) LOG_WARN("If :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::useIncrementalForm` is false, then plasticity will not be applied correctly (the total formulation would not reproduce irreversibility).");
				Real scalarTwist= phys->moment_twist.norm();
				if (scalarTwist>TwistMax){ // fix maximum rolling moment
					Real ratio = TwistMax/scalarTwist;
					phys->moment_twist *= ratio;
					if (scene->trackEnergy){
						Real twistdissip=((1/phys->ktw)*(scalarTwist-TwistMax)*TwistMax)/*active force*/;
						if(twistdissip>0) scene->energy->add(twistdissip,"twistDissip",twistDissipIx,/*reset*/false);}
				}	
			}
			// Apply moments now
			Vector3r moment = phys->moment_twist + phys->moment_bending;
			scene->forces.addTorque(id1,-moment);
			scene->forces.addTorque(id2, moment);			
		}
		/// Moment law END       ///
	}
	return true;
}