sixDoFRigidBody: adding constraints.

Added force to fixedPoint constraint.

Moved application of rotation matrices to function.

Implemented predictedPosition function.

Added maximum iteration check and under-relaxation variable.
This commit is contained in:
graham
2010-01-27 18:31:55 +00:00
parent a0522a2b7b
commit f026a5af0e
7 changed files with 150 additions and 41 deletions

View File

@ -71,13 +71,26 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT)
do do
{ {
converged = true; iter++;
Info<< "Iteration " << iter << endl; if (iter > maxConstraintIters_)
{
FatalErrorIn
(
"Foam::sixDoFRigidBodyMotion::applyConstraints"
"(scalar deltaT)"
)
<< nl << "Maximum number of constraint iterations ("
<< maxConstraintIters_ << ") exceeded." << nl
<< exit(FatalError);
}
converged = true;
forAll(constraints_, cI) forAll(constraints_, cI)
{ {
Info<< "Constraint " << cI << endl; // Info<< "Constraint " << cI << endl;
// constraint position // constraint position
point cP = vector::zero; point cP = vector::zero;
@ -98,11 +111,27 @@ void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT)
cF, cF,
cM cM
); );
// Accumulate constraint force
cFA += cF;
// Accumulate constraint moment
cMA += cM + ((cP - centreOfMass()) ^ cF);
} }
iter++;
} while(!converged); } while(!converged);
Info<< "Constraints converged in " << iter << " iterations" << nl
<< "Constraint force: " << cFA << nl
<< "Constraint moment: " << cMA
<< endl;
// Add the constrain forces and moments to the motion state variables
a() += cFA/mass_;
// The moment of constraint forces has already been added
// during accumulation
tau() += Q().T() & cMA;
} }
} }
@ -114,6 +143,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion()
motionState_(), motionState_(),
restraints_(), restraints_(),
constraints_(), constraints_(),
maxConstraintIters_(0),
refCentreOfMass_(vector::zero), refCentreOfMass_(vector::zero),
momentOfInertia_(diagTensor::one*VSMALL), momentOfInertia_(diagTensor::one*VSMALL),
mass_(VSMALL) mass_(VSMALL)
@ -144,6 +174,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion
), ),
restraints_(), restraints_(),
constraints_(), constraints_(),
maxConstraintIters_(0),
refCentreOfMass_(refCentreOfMass), refCentreOfMass_(refCentreOfMass),
momentOfInertia_(momentOfInertia), momentOfInertia_(momentOfInertia),
mass_(mass) mass_(mass)
@ -155,6 +186,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict)
motionState_(dict), motionState_(dict),
restraints_(), restraints_(),
constraints_(), constraints_(),
maxConstraintIters_(0),
refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())), refCentreOfMass_(dict.lookupOrDefault("refCentreOfMass", centreOfMass())),
momentOfInertia_(dict.lookup("momentOfInertia")), momentOfInertia_(dict.lookup("momentOfInertia")),
mass_(readScalar(dict.lookup("mass"))) mass_(readScalar(dict.lookup("mass")))
@ -173,6 +205,7 @@ Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion
motionState_(sDoFRBM.motionState()), motionState_(sDoFRBM.motionState()),
restraints_(sDoFRBM.restraints()), restraints_(sDoFRBM.restraints()),
constraints_(sDoFRBM.constraints()), constraints_(sDoFRBM.constraints()),
maxConstraintIters_(sDoFRBM.maxConstraintIters()),
refCentreOfMass_(sDoFRBM.refCentreOfMass()), refCentreOfMass_(sDoFRBM.refCentreOfMass()),
momentOfInertia_(sDoFRBM.momentOfInertia()), momentOfInertia_(sDoFRBM.momentOfInertia()),
mass_(sDoFRBM.mass()) mass_(sDoFRBM.mass())
@ -242,15 +275,21 @@ void Foam::sixDoFRigidBodyMotion::addConstraints
constraints_.set constraints_.set
( (
i, i++,
sixDoFRigidBodyMotionConstraint::New(iter().dict()) sixDoFRigidBodyMotionConstraint::New(iter().dict())
); );
} }
i++;
} }
constraints_.setSize(i); constraints_.setSize(i);
if (constraints_.size())
{
maxConstraintIters_ = readLabel
(
constraintDict.lookup("maxIterations")
);
}
} }
} }
@ -274,27 +313,7 @@ void Foam::sixDoFRigidBodyMotion::updatePosition
// Leapfrog orientation adjustment // Leapfrog orientation adjustment
tensor R; rotate(Q(), pi(), deltaT);
R = rotationTensorX(0.5*deltaT*pi().x()/momentOfInertia_.xx());
pi() = pi() & R;
Q() = Q() & R;
R = rotationTensorY(0.5*deltaT*pi().y()/momentOfInertia_.yy());
pi() = pi() & R;
Q() = Q() & R;
R = rotationTensorZ(deltaT*pi().z()/momentOfInertia_.zz());
pi() = pi() & R;
Q() = Q() & R;
R = rotationTensorY(0.5*deltaT*pi().y()/momentOfInertia_.yy());
pi() = pi() & R;
Q() = Q() & R;
R = rotationTensorX(0.5*deltaT*pi().x()/momentOfInertia_.xx());
pi() = pi() & R;
Q() = Q() & R;
} }
Pstream::scatter(motionState_); Pstream::scatter(motionState_);
@ -365,8 +384,17 @@ Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition
scalar deltaT scalar deltaT
) const ) const
{ {
Info<< "predictedPosition NOT IMPLEMENTED" << endl; vector vTemp = v() + deltaT*(a() + deltaForce/mass_);
return pt;
vector piTemp = pi() + deltaT*(tau() + (Q().T() & deltaMoment));
point centreOfMassTemp = centreOfMass() + deltaT*vTemp;
tensor QTemp = Q();
rotate(QTemp, piTemp, deltaT);
return (centreOfMassTemp + (QTemp & (pt - refCentreOfMass_)));
} }

View File

@ -94,6 +94,10 @@ class sixDoFRigidBodyMotion
//- Constaints on the motion //- Constaints on the motion
PtrList<sixDoFRigidBodyMotionConstraint> constraints_; PtrList<sixDoFRigidBodyMotionConstraint> constraints_;
//- Maximum number of iterations allowed to attempt to obey
// constraints
label maxConstraintIters_;
//- Centre of mass of reference state //- Centre of mass of reference state
point refCentreOfMass_; point refCentreOfMass_;
@ -118,6 +122,9 @@ class sixDoFRigidBodyMotion
// frame z-axis by the given angle // frame z-axis by the given angle
inline tensor rotationTensorZ(scalar deltaT) const; inline tensor rotationTensorZ(scalar deltaT) const;
//- Apply rotation tensors to Q for the given torque (pi) and deltaT
inline void rotate(tensor& Q, vector& pi, scalar deltaT) const;
//- Apply the restraints to the object //- Apply the restraints to the object
void applyRestraints(); void applyRestraints();
@ -140,6 +147,10 @@ class sixDoFRigidBodyMotion
inline const PtrList<sixDoFRigidBodyMotionConstraint>& inline const PtrList<sixDoFRigidBodyMotionConstraint>&
constraints() const; constraints() const;
//- Return access to the maximum allowed number of
// constraint iterations
inline label maxConstraintIters() const;
//- Return access to the centre of mass //- Return access to the centre of mass
inline const point& refCentreOfMass() const; inline const point& refCentreOfMass() const;
@ -255,11 +266,11 @@ public:
//- Transform the given reference state pointField by the //- Transform the given reference state pointField by the
// current motion state // current motion state
inline tmp<pointField> currentPosition(const pointField& pts) const; inline tmp<pointField> currentPosition(const pointField& refPts) const;
//- Transform the given reference state point by the current //- Transform the given reference state point by the current
// motion state // motion state
inline point currentPosition(const point& pt) const; inline point currentPosition(const point& refPt) const;
//- Predict the position of the supplied point after deltaT //- Predict the position of the supplied point after deltaT
// given the current motion state and the additional supplied // given the current motion state and the additional supplied

View File

@ -86,11 +86,35 @@ bool Foam::sixDoFRigidBodyMotionConstraints::fixedPoint::constrain
deltaT deltaT
); );
constraintPosition = motion.currentPosition(fixedPoint_);
// Info<< "current position " << constraintPosition << nl
// << "next predictedPosition " << predictedPosition
// << endl;
vector error = predictedPosition - fixedPoint_; vector error = predictedPosition - fixedPoint_;
Info<< error << endl; // Info<< "error " << error << endl;
return true; // Correction force derived from Lagrange multiplier:
// G = -lambda*grad(sigma)
// where
// sigma = mag(error) = 0
// so
// grad(sigma) = error/mag(error)
// Solving for lambda using the SHAKE methodology gives
// lambda = mass*mag(error)/sqr(deltaT)
// This is only strictly applicable (i.e. will converge in one
// iteration) to constraints at the centre of mass. Everything
// else will need to iterate, and may need under-relaxed to be
// stable.
constraintForceIncrement =
-relaxationFactor_*error*motion.mass()/sqr(deltaT);
constraintMomentIncrement = vector::zero;
return (mag(error) < tolerance_);
} }

View File

@ -58,7 +58,9 @@ class fixedPoint
// Private data // Private data
//- Point which is rigidly attached to the body and constrains //- Point which is rigidly attached to the body and constrains
// it so that this point remains fixed. // it so that this point remains fixed. This serves as the
// reference point for displacements as well as the target
// position.
point fixedPoint_; point fixedPoint_;

View File

@ -47,7 +47,11 @@ Foam::sixDoFRigidBodyMotionConstraint::sixDoFRigidBodyMotionConstraint
+ "Coeffs" + "Coeffs"
) )
), ),
tolerance_(readScalar(sDoFRBMCDict.lookup("tolerance"))) tolerance_(readScalar(sDoFRBMCDict.lookup("tolerance"))),
relaxationFactor_
(
sDoFRBMCDict.lookupOrDefault<scalar>("relaxationFactor", 1)
)
{} {}

View File

@ -77,6 +77,9 @@ protected:
// absolute distance or angle. // absolute distance or angle.
scalar tolerance_; scalar tolerance_;
//- Relaxation factor for solution, default to one
scalar relaxationFactor_;
public: public:

View File

@ -62,6 +62,37 @@ Foam::sixDoFRigidBodyMotion::rotationTensorZ(scalar phi) const
} }
inline void Foam::sixDoFRigidBodyMotion::rotate
(
tensor& Q,
vector& pi,
scalar deltaT
) const
{
tensor R;
R = rotationTensorX(0.5*deltaT*pi.x()/momentOfInertia_.xx());
pi = pi & R;
Q = Q & R;
R = rotationTensorY(0.5*deltaT*pi.y()/momentOfInertia_.yy());
pi = pi & R;
Q = Q & R;
R = rotationTensorZ(deltaT*pi.z()/momentOfInertia_.zz());
pi = pi & R;
Q = Q & R;
R = rotationTensorY(0.5*deltaT*pi.y()/momentOfInertia_.yy());
pi = pi & R;
Q = Q & R;
R = rotationTensorX(0.5*deltaT*pi.x()/momentOfInertia_.xx());
pi = pi & R;
Q = Q & R;
}
inline const Foam::sixDoFRigidBodyMotionState& inline const Foam::sixDoFRigidBodyMotionState&
Foam::sixDoFRigidBodyMotion::motionState() const Foam::sixDoFRigidBodyMotion::motionState() const
{ {
@ -83,6 +114,12 @@ Foam::sixDoFRigidBodyMotion::constraints() const
} }
inline Foam::label Foam::sixDoFRigidBodyMotion::maxConstraintIters() const
{
return maxConstraintIters_;
}
inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const inline const Foam::point& Foam::sixDoFRigidBodyMotion::refCentreOfMass() const
{ {
return refCentreOfMass_; return refCentreOfMass_;
@ -171,18 +208,18 @@ inline Foam::vector& Foam::sixDoFRigidBodyMotion::tau()
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
inline Foam::tmp<Foam::pointField> inline Foam::tmp<Foam::pointField>
Foam::sixDoFRigidBodyMotion::currentPosition(const pointField& pts) const Foam::sixDoFRigidBodyMotion::currentPosition(const pointField& refPts) const
{ {
return (centreOfMass() + (Q() & (pts - refCentreOfMass_))); return (centreOfMass() + (Q() & (refPts - refCentreOfMass_)));
} }
inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition inline Foam::point Foam::sixDoFRigidBodyMotion::currentPosition
( (
const point& pt const point& refPt
) const ) const
{ {
return (centreOfMass() + (Q() & (pt - refCentreOfMass_))); return (centreOfMass() + (Q() & (refPt - refCentreOfMass_)));
} }