void PolyhedraSplitter::action() { const shared_ptr<Scene> _rb=shared_ptr<Scene>(); shared_ptr<Scene> rb=(_rb?_rb:Omega::instance().getScene()); vector<PSplitT> splitsV; vector<Matrix3r> bStresses (scene->bodies->size(), Matrix3r::Zero()); getStressForEachBody(bStresses); FOREACH(const shared_ptr<Body>& b, *rb->bodies){ if(!b || !b->material || !b->shape) continue; shared_ptr<Polyhedra> p=YADE_PTR_DYN_CAST<Polyhedra>(b->shape); shared_ptr<PolyhedraMat> m=YADE_PTR_DYN_CAST<PolyhedraMat>(b->material); if(p && m->IsSplitable){ //not real strees, to get real one, it has to be divided by body volume Matrix3r stress = bStresses[b->id]; //get eigenstresses Symmetrize(stress); Matrix3r I_vect(Matrix3r::Zero()), I_valu(Matrix3r::Zero()); matrixEigenDecomposition(stress,I_vect,I_valu); Eigen::Matrix3f::Index min_i, max_i; I_valu.diagonal().minCoeff(&min_i); I_valu.diagonal().maxCoeff(&max_i); //division of stress by volume const Vector3r dirC = I_vect.col(max_i); const Vector3r dirT = I_vect.col(min_i); const Vector3r dir1 = dirC.normalized() + dirT.normalized(); const Vector3r dir2 = dirC.normalized() - dirT.normalized(); //double sigma_t = -comp_stress/2.+ tens_stress; const Real sigma_t = pow(( pow(I_valu(0,0)-I_valu(1,1),2)+ pow(I_valu(0,0)-I_valu(2,2),2)+ pow(I_valu(1,1)-I_valu(2,2),2)) /2.,0.5)/p->GetVolume(); if (sigma_t > getStrength(p->GetVolume(),m->GetStrength())) { splitsV.push_back(std::make_tuple(b, dir1.normalized(), dir2.normalized())); } } } std::for_each(splitsV.begin(), splitsV.end(), &SplitPolyhedraDouble); }
/* Law2_ScGeom_ViscElPhys_Basic */ void Law2_ScGeom_ViscElPhys_Basic::go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I){ const ScGeom& geom=*static_cast<ScGeom*>(_geom.get()); ViscElPhys& phys=*static_cast<ViscElPhys*>(_phys.get()); const int id1 = I->getId1(); const int id2 = I->getId2(); if (geom.penetrationDepth<0) { if (phys.liqBridgeCreated and -geom.penetrationDepth<phys.sCrit and phys.Capillar) { phys.normalForce = -calculateCapillarForce(geom, phys)*geom.normal; if (I->isActive) { addForce (id1,-phys.normalForce,scene); addForce (id2, phys.normalForce,scene); }; return; } else { scene->interactions->requestErase(I); return; }; }; const BodyContainer& bodies = *scene->bodies; const State& de1 = *static_cast<State*>(bodies[id1]->state.get()); const State& de2 = *static_cast<State*>(bodies[id2]->state.get()); /* * This part for implementation of the capillar model. * All main equations are in calculateCapillarForce function. * There is only the determination of critical distance between spheres, * after that the liquid bridge will be broken. */ if (not(phys.liqBridgeCreated) and phys.Capillar) { phys.liqBridgeCreated = true; Sphere* s1=dynamic_cast<Sphere*>(bodies[id1]->shape.get()); Sphere* s2=dynamic_cast<Sphere*>(bodies[id2]->shape.get()); if (s1 and s2) { phys.R = 2 * s1->radius * s2->radius / (s1->radius + s2->radius); } else if (s1 and not(s2)) { phys.R = s1->radius; } else { phys.R = s2->radius; } const Real Vstar = phys.Vb/(phys.R*phys.R*phys.R); const Real Sstar = (1+0.5*phys.theta)*(pow(Vstar,1/3.0) + 0.1*pow(Vstar,2.0/3.0)); // [Willett2000], equation (15), use the full-length e.g 2*Sc phys.sCrit = Sstar*phys.R; } Vector3r& shearForce = phys.shearForce; if (I->isFresh(scene)) shearForce=Vector3r(0,0,0); const Real& dt = scene->dt; shearForce = geom.rotate(shearForce); // Handle periodicity. const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero(); const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero(); const Vector3r c1x = (geom.contactPoint - de1.pos); const Vector3r c2x = (geom.contactPoint - de2.pos - shift2); const Vector3r relativeVelocity = (de1.vel+de1.angVel.cross(c1x)) - (de2.vel+de2.angVel.cross(c2x)) + shiftVel; const Real normalVelocity = geom.normal.dot(relativeVelocity); const Vector3r shearVelocity = relativeVelocity-normalVelocity*geom.normal; // As Chiara Modenese suggest, we store the elastic part // and then add the viscous part if we pass the Mohr-Coulomb criterion. // See http://www.mail-archive.com/[email protected]/msg01391.html shearForce += phys.ks*dt*shearVelocity; // the elastic shear force have a history, but Vector3r shearForceVisc = Vector3r::Zero(); // the viscous shear damping haven't a history because it is a function of the instant velocity // Prevent appearing of attraction forces due to a viscous component // [Radjai2011], page 3, equation [1.7] // [Schwager2007] const Real normForceReal = phys.kn * geom.penetrationDepth + phys.cn * normalVelocity; if (normForceReal < 0) { phys.normalForce = Vector3r::Zero(); } else { phys.normalForce = normForceReal * geom.normal; } Vector3r momentResistance = Vector3r::Zero(); if (phys.mR>0.0) { const Vector3r relAngVel = de1.angVel - de2.angVel; relAngVel.normalized(); if (phys.mRtype == 1) { momentResistance = -phys.mR*phys.normalForce.norm()*relAngVel; // [Zhou1999536], equation (3) } else if (phys.mRtype == 2) { momentResistance = -phys.mR*(c1x.cross(de1.angVel) - c2x.cross(de2.angVel)).norm()*phys.normalForce.norm()*relAngVel; // [Zhou1999536], equation (4) } } const Real maxFs = phys.normalForce.squaredNorm() * std::pow(phys.tangensOfFrictionAngle,2); if( shearForce.squaredNorm() > maxFs ) { // Then Mohr-Coulomb is violated (so, we slip), // we have the max value of the shear force, so // we consider only friction damping. const Real ratio = sqrt(maxFs) / shearForce.norm(); shearForce *= ratio; } else { // Then no slip occurs we consider friction damping + viscous damping. shearForceVisc = phys.cs*shearVelocity; } if (I->isActive) { const Vector3r f = phys.normalForce + shearForce + shearForceVisc; addForce (id1,-f,scene); addForce (id2, f,scene); addTorque(id1,-c1x.cross(f)+momentResistance,scene); addTorque(id2, c2x.cross(f)-momentResistance,scene); } }
bool computeForceTorqueViscEl(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I, Vector3r & force, Vector3r & torque1, Vector3r & torque2) { ViscElPhys& phys=*static_cast<ViscElPhys*>(_phys.get()); const ScGeom& geom=*static_cast<ScGeom*>(_geom.get()); Scene* scene=Omega::instance().getScene().get(); #ifdef YADE_SPH //======================================================================================================= if (phys.SPHmode) { if (computeForceSPH(_geom, _phys, I, force)) { return true; } else { return false; } } //======================================================================================================= #endif const int id1 = I->getId1(); const int id2 = I->getId2(); if (geom.penetrationDepth<0) { return false; } else { const BodyContainer& bodies = *scene->bodies; const State& de1 = *static_cast<State*>(bodies[id1]->state.get()); const State& de2 = *static_cast<State*>(bodies[id2]->state.get()); Vector3r& shearForce = phys.shearForce; if (I->isFresh(scene)) shearForce=Vector3r(0,0,0); const Real& dt = scene->dt; shearForce = geom.rotate(shearForce); // Handle periodicity. const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero(); const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero(); const Vector3r c1x = (geom.contactPoint - de1.pos); const Vector3r c2x = (geom.contactPoint - de2.pos - shift2); const Vector3r relativeVelocity = (de1.vel+de1.angVel.cross(c1x)) - (de2.vel+de2.angVel.cross(c2x)) + shiftVel; const Real normalVelocity = geom.normal.dot(relativeVelocity); const Vector3r shearVelocity = relativeVelocity-normalVelocity*geom.normal; // As Chiara Modenese suggest, we store the elastic part // and then add the viscous part if we pass the Mohr-Coulomb criterion. // See http://www.mail-archive.com/[email protected]/msg01391.html shearForce += phys.ks*dt*shearVelocity; // the elastic shear force have a history, but Vector3r shearForceVisc = Vector3r::Zero(); // the viscous shear damping haven't a history because it is a function of the instant velocity // Prevent appearing of attraction forces due to a viscous component // [Radjai2011], page 3, equation [1.7] // [Schwager2007] phys.Fn = phys.kn * geom.penetrationDepth; phys.Fv = phys.cn * normalVelocity; const Real normForceReal = phys.Fn + phys.Fv; if (normForceReal < 0) { phys.normalForce = Vector3r::Zero(); } else { phys.normalForce = normForceReal * geom.normal; } Vector3r momentResistance = Vector3r::Zero(); if (phys.mR>0.0) { const Vector3r relAngVel = de1.angVel - de2.angVel; relAngVel.normalized(); if (phys.mRtype == 1) { momentResistance = -phys.mR*phys.normalForce.norm()*relAngVel; // [Zhou1999536], equation (3) } else if (phys.mRtype == 2) { momentResistance = -phys.mR*(c1x.cross(de1.angVel) - c2x.cross(de2.angVel)).norm()*phys.normalForce.norm()*relAngVel; // [Zhou1999536], equation (4) } } const Real maxFs = phys.normalForce.squaredNorm() * std::pow(phys.tangensOfFrictionAngle,2); if( shearForce.squaredNorm() > maxFs ) { // Then Mohr-Coulomb is violated (so, we slip), // we have the max value of the shear force, so // we consider only friction damping. const Real ratio = sqrt(maxFs) / shearForce.norm(); shearForce *= ratio; } else { // Then no slip occurs we consider friction damping + viscous damping. shearForceVisc = phys.cs*shearVelocity; } force = phys.normalForce + shearForce + shearForceVisc; torque1 = -c1x.cross(force)+momentResistance; torque2 = c2x.cross(force)-momentResistance; return true; } }