示例#1
0
void Body::addGlobalForce( Ogre::Vector3& force, Ogre::Vector3& pos )
{
	Ogre::Vector3 bodypos;
	Ogre::Quaternion bodyorient;
	getPositionOrientation( bodyorient, bodypos );

	Ogre::Vector3 topoint = pos - bodypos;
	Ogre::Vector3 torque = topoint.crossProduct( force );

	addForce( force );
	addTorque( torque );
}
示例#2
0
	/*! Convenience function to apply force and torque from one force at contact point. Not sure if this is the right place for it. */
	void applyForceAtContactPoint(const Vector3r& force, const Vector3r& contactPoint, const Body::id_t id1, const Vector3r& pos1, const Body::id_t id2, const Vector3r& pos2){
		addForce(id1, force,scene); addTorque(id1, (contactPoint-pos1).cross(force),scene);
		addForce(id2,-force,scene); addTorque(id2,-(contactPoint-pos2).cross(force),scene);
	}
/* 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);
  }
}
示例#4
0
void TimeStep::operator()()
{
   if( numberOfSubIterations_ == 1 )
   {
      forceEvaluationFunc_();

      collisionResponse_.timestep( timeStepSize_ );
      synchronizeFunc_();
   }
   else
   {
      // during the intermediate time steps of the collision response, the currently acting forces
      // (interaction forces, gravitational force, ...) have to remain constant.
      // Since they are reset after the call to collision response, they have to be stored explicitly before.
      // Then they are set again after each intermediate step.

      // generate map from all known bodies (process local) to total forces/torques
      // this has to be done on a block-local basis, since the same body could reside on several blocks from this process
      using BlockID_T = domain_decomposition::IBlockID::IDType;
      std::map< BlockID_T, std::map< walberla::id_t, std::array< real_t, 6 > > > forceTorqueMap;

      for( auto blockIt = blockStorage_->begin(); blockIt != blockStorage_->end(); ++blockIt )
      {
         BlockID_T blockID = blockIt->getId().getID();
         auto& blockLocalForceTorqueMap = forceTorqueMap[blockID];

         // iterate over local and remote bodies and store force/torque in map
         for( auto bodyIt = pe::BodyIterator::begin(*blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt )
         {
            auto & f = blockLocalForceTorqueMap[ bodyIt->getSystemID() ];

            const auto & force = bodyIt->getForce();
            const auto & torque = bodyIt->getTorque();

            f = {{force[0], force[1], force[2], torque[0], torque[1], torque[2] }};
         }
      }

      // perform pe time steps
      const real_t subTimeStepSize = timeStepSize_ / real_c( numberOfSubIterations_ );
      for( uint_t i = 0; i != numberOfSubIterations_; ++i )
      {

         // in the first iteration, forces are already set
         if( i != 0 )
         {
            for( auto blockIt = blockStorage_->begin(); blockIt != blockStorage_->end(); ++blockIt )
            {
               BlockID_T blockID = blockIt->getId().getID();
               auto& blockLocalForceTorqueMap = forceTorqueMap[blockID];

               // re-set stored force/torque on bodies
               for( auto bodyIt = pe::BodyIterator::begin(*blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt )
               {

                  const auto f = blockLocalForceTorqueMap.find( bodyIt->getSystemID() );

                  if( f != blockLocalForceTorqueMap.end() )
                  {
                     const auto & ftValues = f->second;
                     bodyIt->addForce ( ftValues[0], ftValues[1], ftValues[2] );
                     bodyIt->addTorque( ftValues[3], ftValues[4], ftValues[5] );
                  }
               }
            }
         }

         // evaluate forces (e.g. lubrication forces)
         forceEvaluationFunc_();

         collisionResponse_.timestep( subTimeStepSize );
         synchronizeFunc_();
      }
   }
}
示例#5
0
/* 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) {
 		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());

	Vector3r& shearForce = phys.shearForce;
	if (I->isFresh(scene)) shearForce=Vector3r(0,0,0);
	const Real& dt = scene->dt;
	//Vector3r axis = phys.prevNormal.cross(geom.normal);
	//shearForce -= shearForce.cross(axis);
	//const Real angle = dt*0.5*geom.normal.dot(de1.angVel + de2.angVel);
	//axis = angle*geom.normal;
	//shearForce -= shearForce.cross(axis);
	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 

	phys.normalForce = ( phys.kn * geom.penetrationDepth + phys.cn * normalVelocity ) * geom.normal;
	//phys.prevNormal = geom.normal;

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

	const Vector3r f = phys.normalForce + shearForce + shearForceVisc;
	addForce (id1,-f,scene);
	addForce (id2, f,scene);
	addTorque(id1,-c1x.cross(f),scene);
	addTorque(id2, c2x.cross(f),scene);
}
示例#6
0
void RigidBody::addForceAtWorldPoint(const Mat<float>& force, const Mat<float>& pointW)
{
	addForce(force);
	addTorque( crossproductV( pointW-extract(Pose->exp(), 1,4, 3,4), force) );		
}
示例#7
0
/*! Constitutive law */
void FCPM::go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I){

	
	const ScGeom& geom=*static_cast<ScGeom*>(_geom.get());
	FreshConcretePhys& phys=*static_cast<FreshConcretePhys*>(_phys.get());

	const int id1 = I->getId1();
	const int id2 = I->getId2();
	
	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());

//Calculation of the max penetretion and the radius of the overlap area 
	Sphere* s1=dynamic_cast<Sphere*>(bodies[id1]->shape.get());
	Sphere* s2=dynamic_cast<Sphere*>(bodies[id2]->shape.get());

	Real dist;
	Real contactRadius;
	Real OverlapRadius;

	if (s1 and s2) {
		phys.maxPenetration=s1->radius * phys.Penetration1 + s2->radius * phys.Penetration2;
		dist = s1->radius + s2->radius - geom.penetrationDepth;
		OverlapRadius = pow(((4 * pow(dist,2) * pow(s1->radius,2) - pow((pow(dist,2) - pow(s2->radius,2) + pow(s1->radius,2)),2)) / (4 * pow(dist,2))),(1.0/2.0));
		//contactRadius = (pow(s1->radius,2) + pow(s2->radius,2))/(s1->radius + s2->radius);
		contactRadius = s1->radius;
	} else if (s1 and not(s2)) {
		phys.maxPenetration=s1->radius * phys.Penetration1;
		dist = s1->radius - geom.penetrationDepth;
		OverlapRadius =pow((pow(s1->radius,2) - pow(dist,2)),(1.0/2.0));
		contactRadius = s1->radius;
	} else {
		phys.maxPenetration=s2->radius * phys.Penetration2;
		dist = s2->radius - geom.penetrationDepth;
		OverlapRadius = pow((pow(s2->radius,2) - pow(dist,2)),(1.0/2.0));
		contactRadius = s2->radius;
	}


	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;

//Normal Force
	
	Real OverlapArea;
	Real MaxArea;

	OverlapArea = 3.1415 * pow(OverlapRadius,2);
	MaxArea = 3.1415 * pow(contactRadius,2);

	Real Mult;
	if(OverlapRadius < contactRadius){
		Mult = OverlapArea / MaxArea;
	}
	else{
		Mult = 1;
	}
	
	Real Fn;
	if(geom.penetrationDepth>=0){
//Compression
		if(normalVelocity>=0){
			if (geom.penetrationDepth >= phys.maxPenetration){
				Fn = phys.knI * (geom.penetrationDepth - phys.previousun) + phys.previousElasticN + phys.cnI * normalVelocity;
				phys.previousElasticN += phys.knI * (geom.penetrationDepth - phys.previousun);
				phys.normalForce = Fn * geom.normal;
				phys.t = 0; phys.t2 = 0;
				//phys.previousElasticTensionN = 0;
			} 
			else{
				Fn = Mult * phys.kn * (geom.penetrationDepth - phys.previousun) + Mult * phys.previousElasticN + phys.cn * normalVelocity;
				phys.previousElasticN += Mult * phys.kn * (geom.penetrationDepth - phys.previousun);
				phys.finalElasticN += Mult * phys.kn * (geom.penetrationDepth - phys.previousun);
				phys.normalForce = Fn * geom.normal;
				phys.t = 0; phys.t2 = 0;
				//phys.previousElasticTensionN = 0;
			}
		}
//Tension
		else if(normalVelocity<0){
			if(phys.t == 0){
				phys.maxNormalComp = - phys.finalElasticN;
				//printf("------> %E \n", phys.maxNormalComp);
				phys.RupOverlap = phys.previousun;
				//throw runtime_error("STOP");
				phys.t = 1;
			}
			
			Real MaxTension = phys.maxNormalComp * 0.25;
			Real FnTension = phys.previousElasticTensionN + Mult * phys.kn * dt * normalVelocity;
			//printf("===:: %E \n", MaxTension);
			//printf("===:: %E \n", FnTension);
			if (FnTension > MaxTension && phys.t2 == 0){
				Fn = phys.previousElasticTensionN + Mult * phys.kn * dt * normalVelocity;
				phys.previousElasticTensionN = Fn;
				phys.normalForce = Fn * geom.normal;
				phys.RupOverlap = geom.penetrationDepth;
				//phys.previousElasticN = 0;
				//printf("===-- %E \n", Fn);
			}
			else{
				//phys.DamageTension = geom.penetrationDepth / (phys.maxPenetration - phys.maxPenetration * phys.RupTension);
				//phys.previousElasticTensionN -= phys.DamageTension * Mult * phys.kn * dt * normalVelocity;
				phys.t2 = 1;
				Fn = MaxTension * geom.penetrationDepth / phys.RupOverlap;
				phys.normalForce = Fn * geom.normal;
				//printf("===// %E \n", Fn);
				//throw runtime_error("STOP");
			}
		}
	}
	else{
		Fn = 0;
		phys.normalForce = Fn * geom.normal;
		phys.finalElasticN = 0;
	}

	
	phys.previousun = geom.penetrationDepth;

//Shear Force
	shearForce += phys.ks*dt*shearVelocity;
	Vector3r shearForceVisc = Vector3r::Zero();

	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),scene);
		addTorque(id2, c2x.cross(f),scene);
	}
}