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 /// }
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; }