← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2626: 1. Clean up NewtonIntegrator following the discussion on the list; adds 1st order damping for asp...

 

------------------------------------------------------------
revno: 2626
committer: Václav Šmilauer <eu@xxxxxxxx>
branch nick: yade
timestamp: Wed 2010-12-22 11:55:23 +0100
message:
  1. Clean up NewtonIntegrator following the discussion on the list; adds 1st order damping for aspherical particles; comments welcome.
  2. Add Body.intrs() in python
modified:
  core/Body.cpp
  core/Body.hpp
  pkg/dem/NewtonIntegrator.cpp
  pkg/dem/NewtonIntegrator.hpp


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'core/Body.cpp'
--- core/Body.cpp	2010-08-15 16:30:00 +0000
+++ core/Body.cpp	2010-12-22 10:55:23 +0000
@@ -1,18 +1,9 @@
-/*************************************************************************
-*  Copyright (C) 2004 by Olivier Galizzi                                 *
-*  olivier.galizzi@xxxxxxx                                               *
-*  Copyright (C) 2004 by Janek Kozicki                                   *
-*  cosurgi@xxxxxxxxxx                                                    *
-*                                                                        *
-*  This program is free software; it is licensed under the terms of the  *
-*  GNU General Public License v2 or later. See file LICENSE for details. *
-*************************************************************************/
-
-#include "Body.hpp"
-
-#include <limits>
-#include "Scene.hpp"
-#include "Omega.hpp"
+
+#include<yade/core/Body.hpp>
+#include<limits>
+#include<yade/core/Scene.hpp>
+#include<yade/core/Omega.hpp>
+#include<yade/core/InteractionContainer.hpp>
 
 //! This could be -1 if id_t is re-typedef'ed as `int'
 const Body::id_t Body::ID_NONE=Body::id_t(-1);
@@ -20,4 +11,14 @@
 const shared_ptr<Body>& Body::byId(Body::id_t _id, Scene* rb){return (*((rb?rb:Omega::instance().getScene().get())->bodies))[_id];}
 const shared_ptr<Body>& Body::byId(Body::id_t _id, shared_ptr<Scene> rb){return (*(rb->bodies))[_id];}
 
+// return list of interactions of this particle
+python::list Body::py_intrs(){
+	Scene* scene=Omega::instance().getScene().get(); // potentially unsafe with multiple simulations
+	python::list ret;
+	FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
+		if(!I->isReal()) continue;
+		if(I->getId1()==id || I->getId2()==id) ret.append(I);
+	}
+	return ret;
+}
 

=== modified file 'core/Body.hpp'
--- core/Body.hpp	2010-12-10 15:07:56 +0000
+++ core/Body.hpp	2010-12-22 10:55:23 +0000
@@ -62,6 +62,8 @@
 		 * (otherwise, GLViewer would depend on Clump and therefore Clump would have to go to core...) */
 		virtual void userForcedDisplacementRedrawHook(){return;}
 
+		python::list py_intrs();
+
 		Body::id_t getId() const {return id;};
 
 		int getGroupMask() {return groupMask; };
@@ -95,7 +97,8 @@
 		.def_readwrite("mask",&Body::groupMask,"Shorthand for :yref:`Body::groupMask`")
 		.add_property("isStandalone",&Body::isStandalone,"True if this body is neither clump, nor clump member; false otherwise.")
 		.add_property("isClumpMember",&Body::isClumpMember,"True if this body is clump member, false otherwise.")
-		.add_property("isClump",&Body::isClump,"True if this body is clump itself, false otherwise.");
+		.add_property("isClump",&Body::isClump,"True if this body is clump itself, false otherwise.")
+		.def("intrs",&Body::py_intrs,"Return all interactions in which this body participates.")
 	);
 };
 REGISTER_SERIALIZABLE(Body);

=== modified file 'pkg/dem/NewtonIntegrator.cpp'
--- pkg/dem/NewtonIntegrator.cpp	2010-12-21 22:50:34 +0000
+++ pkg/dem/NewtonIntegrator.cpp	2010-12-22 10:55:23 +0000
@@ -14,8 +14,9 @@
 
 YADE_PLUGIN((NewtonIntegrator));
 CREATE_LOGGER(NewtonIntegrator);
+
 void NewtonIntegrator::cundallDamp(const Real& dt, const Vector3r& N, const Vector3r& V, Vector3r& A){
-	for(int i=0; i<3; i++) A[i]*= 1 - damping*Mathr::Sign ( N[i]*(V[i] + (Real) 0.5 *dt*A[i]) );
+	for(int i=0; i<3; i++) A[i]*= 1 - damping*Mathr::Sign ( N[i]*(V[i] + 0.5*dt*A[i]) );
 }
 
 Vector3r NewtonIntegrator::computeAccel(const Vector3r& force, const Real& mass, int blockedDOFs){
@@ -31,26 +32,28 @@
 	return ret;
 }
 
-void NewtonIntegrator::handleClumpMemberAccel(Scene* scene, const Body::id_t& memberId, State* memberState, State* clumpState){
+Vector3r NewtonIntegrator::clumpMemberAccel(const Body::id_t& memberId, const State* memberState, const State* clumpState){
 	const Vector3r& f=scene->forces.getForce(memberId);
-	Vector3r diffClumpAccel=computeAccel(f,clumpState->mass,clumpState->blockedDOFs); // use blockedDOFs of the clump
-	// damp increment of accels on the clump, using velocities of the clump MEMBER
-	cundallDamp(scene->dt,f,memberState->vel,diffClumpAccel);
-	clumpState->accel+=diffClumpAccel;
+	Vector3r dA=computeAccel(f,clumpState->mass,clumpState->blockedDOFs);
+	cundallDamp(scene->dt,f,memberState->vel,dA); // damp using velocities of the member
+	return dA;
 }
-void NewtonIntegrator::handleClumpMemberAngAccel(Scene* scene, const Body::id_t& memberId, State* memberState, State* clumpState){
+Vector3r NewtonIntegrator::clumpMemberAngAccel(const Body::id_t& memberId, const State* memberState, const State* clumpState){
 	// angular acceleration from: normal torque + torque generated by the force WRT particle centroid on the clump centroid
 	const Vector3r& m=scene->forces.getTorque(memberId); const Vector3r& f=scene->forces.getForce(memberId);
-	Vector3r diffClumpAngAccel=computeAngAccel(m+(memberState->pos-clumpState->pos).cross(f),clumpState->inertia,clumpState->blockedDOFs);
-	// damp increment of accels on the clump, using velocities of the clump MEMBER
-	cundallDamp(scene->dt,m,memberState->angVel,diffClumpAngAccel);
-	clumpState->angAccel+=diffClumpAngAccel;
+	Vector3r dAA=computeAngAccel(m+(memberState->pos-clumpState->pos).cross(f),clumpState->inertia,clumpState->blockedDOFs);
+	cundallDamp(scene->dt,m,memberState->angVel,dAA);
+	return dAA;
 }
-void NewtonIntegrator::handleClumpMemberTorque(Scene* scene, const Body::id_t& memberId, State* memberState, State* clumpState, Vector3r& M){
+Vector3r NewtonIntegrator::clumpMemberTorque(const Body::id_t& memberId, const State* memberState, const State* clumpState){
 	const Vector3r& m=scene->forces.getTorque(memberId); const Vector3r& f=scene->forces.getForce(memberId);
-	M+=(memberState->pos-clumpState->pos).cross(f)+m;
+	Vector3r dM=(memberState->pos-clumpState->pos).cross(f)+m;
+	for(int i=0; i<3; i++) if(clumpState->blockedDOFs & State::axisDOF(i,true)) dM[i]=0.;
+	cundallDamp(0,m,memberState->angVel,dM); // damp dM; dt=0 makes the acceleration term vanish, since here it is torque rather than acceleration
+	return dM;
 }
-void NewtonIntegrator::saveMaximaVelocity(Scene* scene, const Body::id_t& id, State* state){
+
+void NewtonIntegrator::saveMaximaVelocity(const Body::id_t& id, State* state){
 	if(haveBins) velocityBins->binVelSqUse(id,VelocityBins::getBodyVelSq(state));
 	#ifdef YADE_OPENMP
 		Real& thrMaxVSq=threadMaxVelocitySq[omp_get_thread_num()]; thrMaxVSq=max(thrMaxVSq,state->vel.squaredNorm());
@@ -133,64 +136,48 @@
 			}
 
 			if (likely(b->isStandalone())){
-				// translate equation
 				state->accel=computeAccel(f,state->mass,state->blockedDOFs);
 				cundallDamp(dt,f,fluctVel,state->accel);
-				leapfrogTranslate(scene,state,id,dt);
-				// rotate equation
+				leapfrogTranslate(state,id,dt);
 				// exactAsphericalRot is disabled or the body is spherical
 				if (likely(!exactAsphericalRot || !b->isAspherical() || b->state->inertia.minCoeff()<=0.)){
 					state->angAccel=computeAngAccel(m,state->inertia,state->blockedDOFs);
 					cundallDamp(dt,m,state->angVel,state->angAccel);
-					leapfrogSphericalRotate(scene,state,id,dt);
+					leapfrogSphericalRotate(state,id,dt);
 				} else { // exactAsphericalRot enabled & aspherical body
-					// no damping in this case
-					leapfrogAsphericalRotate(scene,state,id,dt,m);
+					// damp the torque
+					Vector3r mm(m); cundallDamp(0,m,state->angVel,mm); 
+					leapfrogAsphericalRotate(state,id,dt,mm);
 				}
 			} else if (b->isClump()){
-				// reset acceleration of the clump itself; computed from accels on constituents
-				state->accel=state->angAccel=Vector3r::Zero();
-				// clump mass forces
-				Vector3r dLinAccel=computeAccel(f,state->mass,state->blockedDOFs);
-				cundallDamp(dt,f,fluctVel,dLinAccel);
-				state->accel+=dLinAccel;
-				Vector3r M(m); // torque on the clump itself, will accumulate from members
-				// sum force on clump memebrs
-				// exactAsphericalRot enabled and clump is aspherical
-				if (exactAsphericalRot && b->isAspherical() && b->state->inertia.maxCoeff()>0){
-					FOREACH(Clump::MemberMap::value_type mm, static_cast<Clump*>(b->shape.get())->members){
-						const Body::id_t& memberId=mm.first;
-						const shared_ptr<Body>& member=Body::byId(memberId,scene); assert(member->isClumpMember());
-						State* memberState=member->state.get();
-						handleClumpMemberAccel(scene,memberId,memberState,state);
-						handleClumpMemberTorque(scene,memberId,memberState,state,M);
-					}
-					// motion
-					leapfrogTranslate(scene,state,id,dt);
-					leapfrogAsphericalRotate(scene,state,id,dt,M);
-				} else { // exactAsphericalRot disabled or clump is spherical
-					Vector3r dAngAccel=computeAngAccel(M,state->inertia,state->blockedDOFs);
-					cundallDamp(dt,M,state->angVel,dAngAccel);
-					state->angAccel+=dAngAccel;
-					FOREACH(Clump::MemberMap::value_type mm, static_cast<Clump*>(b->shape.get())->members){
-						const Body::id_t& memberId=mm.first;
-						const shared_ptr<Body>& member=Body::byId(memberId,scene); assert(member->isClumpMember());
-						State* memberState=member->state.get();
-						handleClumpMemberAccel(scene,memberId,memberState,state);
-						handleClumpMemberAngAccel(scene,memberId,memberState,state);
-					}
-					// motion
-					leapfrogTranslate(scene,state,id,dt);
-					leapfrogSphericalRotate(scene,state,id,dt);
+				// aspherical if allowed, if the body is aspherical, has no zero inertia term (->NaN) and has at least one rotational DOF unblocked
+				const bool aspherical=(exactAsphericalRot && b->isAspherical() && b->state->inertia.maxCoeff()>0 && ((state->blockedDOFs&State::DOF_RXRYRZ)!=State::DOF_RXRYRZ));
+				Vector3r M(m); // torque on the clump itself, aspherical only
+				state->accel=computeAccel(f,state->mass,state->blockedDOFs); cundallDamp(dt,f,fluctVel,state->accel);
+				if(!aspherical){ state->angAccel=computeAngAccel(M,state->inertia,state->blockedDOFs); cundallDamp(dt,m,state->angVel,state->angAccel); }
+				if(state->blockedDOFs!=State::DOF_ALL){ // if the clump has all DoFs blocked, forces on members would be computed uselessly
+					FOREACH(Clump::MemberMap::value_type mm, static_cast<Clump*>(b->shape.get())->members){
+						const Body::id_t& memberId=mm.first;
+						const shared_ptr<Body>& member=Body::byId(memberId,scene); assert(member->isClumpMember());
+						State* memberState=member->state.get();
+						state->accel+=clumpMemberAccel(memberId,memberState,state);
+						if(aspherical) M+=clumpMemberTorque(memberId,memberState,state);
+						else state->angAccel+=clumpMemberAngAccel(memberId,memberState,state);
+					}
 				}
+				// translation
+				leapfrogTranslate(state,id,dt);
+				// rotation
+				if(aspherical) leapfrogAsphericalRotate(state,id,dt,M);
+				else leapfrogSphericalRotate(state,id,dt);
 				Clump::moveMembers(b,scene);
 				// save max velocity for all members of the clump
 				FOREACH(Clump::MemberMap::value_type mm, static_cast<Clump*>(b->shape.get())->members){
 					const shared_ptr<Body>& member=Body::byId(mm.first,scene); assert(member->isClumpMember());
-					saveMaximaVelocity(scene,mm.first,member->state.get());
+					saveMaximaVelocity(mm.first,member->state.get());
 				}
 			}
-			saveMaximaVelocity(scene,id,state);
+			saveMaximaVelocity(id,state);
 			// process callbacks
 			for(size_t i=0; i<callbacksSize; i++){
 				cerr<<"<"<<b->id<<",cb="<<callbacks[i]<<",scene="<<callbacks[i]->scene<<">"; // <<",force="<<callbacks[i]->scene->forces.getForce(b->id)<<">";
@@ -204,7 +191,7 @@
 	if(scene->isPeriodic) { prevCellSize=scene->cell->getSize(); prevVelGrad=scene->cell->velGrad; }
 }
 
-inline void NewtonIntegrator::leapfrogTranslate(Scene* scene, State* state, const Body::id_t& id, const Real& dt){
+void NewtonIntegrator::leapfrogTranslate(State* state, const Body::id_t& id, const Real& dt){
 	if (scene->forces.getMoveRotUsed()) state->pos+=scene->forces.getMove(id);
 	if (homoDeform==Cell::HOMO_VEL || homoDeform==Cell::HOMO_VEL_2ND) {
 		// update velocity reflecting changes in the macroscopic velocity field, making the problem homothetic.
@@ -223,7 +210,7 @@
 	state->pos+=state->vel*dt;
 }
 
-inline void NewtonIntegrator::leapfrogSphericalRotate(Scene* scene, State* state, const Body::id_t& id, const Real& dt )
+void NewtonIntegrator::leapfrogSphericalRotate(State* state, const Body::id_t& id, const Real& dt )
 {
 	state->angVel+=dt*state->angAccel;
 	Vector3r axis = state->angVel;
@@ -242,15 +229,7 @@
 	state->ori.normalize();
 }
 
-void NewtonIntegrator::leapfrogAsphericalRotate(Scene* scene, State* state, const Body::id_t& id, const Real& dt, const Vector3r& M){
-	// if all DoFs are blocked then return; warn if there is angular acceleration, since it will be ignored
-	if((state->blockedDOFs & State::DOF_RXRYRZ)==State::DOF_RXRYRZ){
-		/* necessarily angular acceleration is zero, we can call the spherical integrator safely */
-		if(state->angVel!=Vector3r::Zero()) leapfrogSphericalRotate(scene,state,id,dt); /* in most cases, angVel will be zero; no need to integrate anything, just return */
-		return;
-	}
-	// if only some rotations are allowed, warn, since it is not handled (yet?)
-	if((state->blockedDOFs & State::DOF_RXRYRZ)!=0) LOG_WARN("Aspherical body #"<<id<<" with some rotational DoFs blocked is not supported (blocked DoFs ignored).");
+void NewtonIntegrator::leapfrogAsphericalRotate(State* state, const Body::id_t& id, const Real& dt, const Vector3r& M){
 	Matrix3r A=state->ori.conjugate().toRotationMatrix(); // rotation matrix from global to local r.f.
 	const Vector3r l_n = state->angMom + dt/2 * M; // global angular momentum at time n
 	const Vector3r l_b_n = A*l_n; // local angular momentum at time n

=== modified file 'pkg/dem/NewtonIntegrator.hpp'
--- pkg/dem/NewtonIntegrator.hpp	2010-12-21 15:31:40 +0000
+++ pkg/dem/NewtonIntegrator.hpp	2010-12-22 10:55:23 +0000
@@ -23,19 +23,20 @@
 
 class NewtonIntegrator : public GlobalEngine{
 	inline void cundallDamp(const Real& dt, const Vector3r& N, const Vector3r& V, Vector3r& A);
-	inline void handleClumpMemberAccel(Scene* ncb, const Body::id_t& memberId, State* memberState, State* clumpState);
-	inline void handleClumpMemberAngAccel(Scene* ncb, const Body::id_t& memberId, State* memberState, State* clumpState);
-	inline void handleClumpMemberTorque(Scene* ncb, const Body::id_t& memberId, State* memberState, State* clumpState, Vector3r& M);
-	inline void saveMaximaVelocity(Scene* ncb, const Body::id_t& id, State* state);
+	inline void saveMaximaVelocity(const Body::id_t& id, State* state);
 	bool haveBins;
-	inline void leapfrogTranslate(Scene* ncb, State* state, const Body::id_t& id, const Real& dt); // leap-frog translate
-	inline void leapfrogSphericalRotate(Scene* ncb, State* state, const Body::id_t& id, const Real& dt); // leap-frog rotate of spherical body
-	inline void leapfrogAsphericalRotate(Scene* ncb, State* state, const Body::id_t& id, const Real& dt, const Vector3r& M); // leap-frog rotate of aspherical body
+	inline void leapfrogTranslate(State*, const Body::id_t& id, const Real& dt); // leap-frog translate
+	inline void leapfrogSphericalRotate(State*, const Body::id_t& id, const Real& dt); // leap-frog rotate of spherical body
+	inline void leapfrogAsphericalRotate(State*, const Body::id_t& id, const Real& dt, const Vector3r& M); // leap-frog rotate of aspherical body
 	Quaternionr DotQ(const Vector3r& angVel, const Quaternionr& Q);
 
 	// compute linear and angular acceleration, respecting State::blockedDOFs
 	Vector3r computeAccel(const Vector3r& force, const Real& mass, int blockedDOFs);
 	Vector3r computeAngAccel(const Vector3r& torque, const Vector3r& inertia, int blockedDOFs);
+	// compute contribution of clump member
+	Vector3r clumpMemberAccel(const Body::id_t&, const State* clumpState, const State* memberState);
+	Vector3r clumpMemberAngAccel(const Body::id_t&, const State* clumpState, const State* memberState);
+	Vector3r clumpMemberTorque(const Body::id_t&, const State* clumpState, const State* memberState);
 
 	// whether the cell has changed from the previous step
 	bool cellChanged;


Follow ups