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