FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

sixDoFRigidBodyMotion.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 2009-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICLUAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "sixDoFRigidBodyMotion.H"
00027 
00028 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00029 
00030 void Foam::sixDoFRigidBodyMotion::applyRestraints()
00031 {
00032     if (restraints_.empty())
00033     {
00034         return;
00035     }
00036 
00037     if (Pstream::master())
00038     {
00039         forAll(restraints_, rI)
00040         {
00041             if (report_)
00042             {
00043                 Info<< "Restraint " << restraintNames_[rI] << ": ";
00044             }
00045 
00046             // restraint position
00047             point rP = vector::zero;
00048 
00049             // restraint force
00050             vector rF = vector::zero;
00051 
00052             // restraint moment
00053             vector rM = vector::zero;
00054 
00055             restraints_[rI].restrain(*this, rP, rF, rM);
00056 
00057             a() += rF/mass_;
00058 
00059             // Moments are returned in global axes, transforming to
00060             // body local to add to torque.
00061             tau() += Q().T() & (rM + ((rP - centreOfMass()) ^ rF));
00062         }
00063     }
00064 }
00065 
00066 
00067 void Foam::sixDoFRigidBodyMotion::applyConstraints(scalar deltaT)
00068 {
00069     if (constraints_.empty())
00070     {
00071         return;
00072     }
00073 
00074     if (Pstream::master())
00075     {
00076         label iteration = 0;
00077 
00078         bool allConverged = true;
00079 
00080         // constraint force accumulator
00081         vector cFA = vector::zero;
00082 
00083         // constraint moment accumulator
00084         vector cMA = vector::zero;
00085 
00086         do
00087         {
00088             allConverged = true;
00089 
00090             forAll(constraints_, cI)
00091             {
00092                 if (sixDoFRigidBodyMotionConstraint::debug)
00093                 {
00094                     Info<< "Constraint " << constraintNames_[cI] << ": ";
00095                 }
00096 
00097                 // constraint position
00098                 point cP = vector::zero;
00099 
00100                 // constraint force
00101                 vector cF = vector::zero;
00102 
00103                 // constraint moment
00104                 vector cM = vector::zero;
00105 
00106                 bool constraintConverged = constraints_[cI].constrain
00107                 (
00108                     *this,
00109                     cFA,
00110                     cMA,
00111                     deltaT,
00112                     cP,
00113                     cF,
00114                     cM
00115                 );
00116 
00117                 allConverged = allConverged && constraintConverged;
00118 
00119                 // Accumulate constraint force
00120                 cFA += cF;
00121 
00122                 // Accumulate constraint moment
00123                 cMA += cM + ((cP - centreOfMass()) ^ cF);
00124             }
00125 
00126         } while(++iteration < maxConstraintIterations_ && !allConverged);
00127 
00128         if (iteration >= maxConstraintIterations_)
00129         {
00130             FatalErrorIn
00131             (
00132                 "Foam::sixDoFRigidBodyMotion::applyConstraints"
00133                 "(scalar deltaT)"
00134             )
00135                 << nl << "Maximum number of sixDoFRigidBodyMotion constraint "
00136                 << "iterations ("
00137                 << maxConstraintIterations_
00138                 << ") exceeded." << nl
00139                 << exit(FatalError);
00140         }
00141 
00142         Info<< "sixDoFRigidBodyMotion constraints converged in "
00143             << iteration << " iterations" << endl;
00144 
00145         if (report_)
00146         {
00147             Info<< "Constraint force: " << cFA << nl
00148                 << "Constraint moment: " << cMA
00149                 << endl;
00150         }
00151 
00152         // Add the constraint forces and moments to the motion state variables
00153         a() += cFA/mass_;
00154 
00155         // The moment of constraint forces has already been added
00156         // during accumulation.  Moments are returned in global axes,
00157         // transforming to body local
00158         tau() += Q().T() & cMA;
00159     }
00160 }
00161 
00162 
00163 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00164 
00165 Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion()
00166 :
00167     motionState_(),
00168     restraints_(),
00169     restraintNames_(),
00170     constraints_(),
00171     constraintNames_(),
00172     maxConstraintIterations_(0),
00173     initialCentreOfMass_(vector::zero),
00174     initialQ_(I),
00175     momentOfInertia_(diagTensor::one*VSMALL),
00176     mass_(VSMALL),
00177     cDamp_(0.0),
00178     aLim_(VGREAT),
00179     report_(false)
00180 {}
00181 
00182 
00183 Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion
00184 (
00185     const point& centreOfMass,
00186     const tensor& Q,
00187     const vector& v,
00188     const vector& a,
00189     const vector& pi,
00190     const vector& tau,
00191     scalar mass,
00192     const point& initialCentreOfMass,
00193     const tensor& initialQ,
00194     const diagTensor& momentOfInertia,
00195     scalar cDamp,
00196     scalar aLim,
00197     bool report
00198 )
00199 :
00200     motionState_
00201     (
00202         centreOfMass,
00203         Q,
00204         v,
00205         a,
00206         pi,
00207         tau
00208     ),
00209     restraints_(),
00210     restraintNames_(),
00211     constraints_(),
00212     constraintNames_(),
00213     maxConstraintIterations_(0),
00214     initialCentreOfMass_(initialCentreOfMass),
00215     initialQ_(initialQ),
00216     momentOfInertia_(momentOfInertia),
00217     mass_(mass),
00218     cDamp_(cDamp),
00219     aLim_(aLim),
00220     report_(report)
00221 {}
00222 
00223 
00224 Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion(const dictionary& dict)
00225 :
00226     motionState_(dict),
00227     restraints_(),
00228     restraintNames_(),
00229     constraints_(),
00230     constraintNames_(),
00231     maxConstraintIterations_(0),
00232     initialCentreOfMass_
00233     (
00234         dict.lookupOrDefault("initialCentreOfMass", centreOfMass())
00235     ),
00236     initialQ_
00237     (
00238         dict.lookupOrDefault("initialOrientation", Q())
00239     ),
00240     momentOfInertia_(dict.lookup("momentOfInertia")),
00241     mass_(readScalar(dict.lookup("mass"))),
00242     cDamp_(dict.lookupOrDefault<scalar>("accelerationDampingCoeff", 0.0)),
00243     aLim_(dict.lookupOrDefault<scalar>("accelerationLimit", VGREAT)),
00244     report_(dict.lookupOrDefault<Switch>("report", false))
00245 {
00246     addRestraints(dict);
00247 
00248     addConstraints(dict);
00249 }
00250 
00251 
00252 Foam::sixDoFRigidBodyMotion::sixDoFRigidBodyMotion
00253 (
00254     const sixDoFRigidBodyMotion& sDoFRBM
00255 )
00256 :
00257     motionState_(sDoFRBM.motionState_),
00258     restraints_(sDoFRBM.restraints_),
00259     restraintNames_(sDoFRBM.restraintNames_),
00260     constraints_(sDoFRBM.constraints_),
00261     constraintNames_(sDoFRBM.constraintNames_),
00262     maxConstraintIterations_(sDoFRBM.maxConstraintIterations_),
00263     initialCentreOfMass_(sDoFRBM.initialCentreOfMass_),
00264     initialQ_(sDoFRBM.initialQ_),
00265     momentOfInertia_(sDoFRBM.momentOfInertia_),
00266     mass_(sDoFRBM.mass_),
00267     cDamp_(sDoFRBM.cDamp_),
00268     aLim_(sDoFRBM.aLim_),
00269     report_(sDoFRBM.report_)
00270 {}
00271 
00272 
00273 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00274 
00275 Foam::sixDoFRigidBodyMotion::~sixDoFRigidBodyMotion()
00276 {}
00277 
00278 
00279 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
00280 
00281 void Foam::sixDoFRigidBodyMotion::addRestraints
00282 (
00283     const dictionary& dict
00284 )
00285 {
00286     if (dict.found("restraints"))
00287     {
00288         const dictionary& restraintDict = dict.subDict("restraints");
00289 
00290         label i = 0;
00291 
00292         restraints_.setSize(restraintDict.size());
00293 
00294         restraintNames_.setSize(restraintDict.size());
00295 
00296         forAllConstIter(IDLList<entry>, restraintDict, iter)
00297         {
00298             if (iter().isDict())
00299             {
00300                 // Info<< "Adding restraint: " << iter().keyword() << endl;
00301 
00302                 restraints_.set
00303                 (
00304                     i,
00305                     sixDoFRigidBodyMotionRestraint::New(iter().dict())
00306                 );
00307 
00308                 restraintNames_[i] = iter().keyword();
00309 
00310                 i++;
00311             }
00312         }
00313 
00314         restraints_.setSize(i);
00315 
00316         restraintNames_.setSize(i);
00317     }
00318 }
00319 
00320 
00321 void Foam::sixDoFRigidBodyMotion::addConstraints
00322 (
00323     const dictionary& dict
00324 )
00325 {
00326     if (dict.found("constraints"))
00327     {
00328         const dictionary& constraintDict = dict.subDict("constraints");
00329 
00330         label i = 0;
00331 
00332         constraints_.setSize(constraintDict.size());
00333 
00334         constraintNames_.setSize(constraintDict.size());
00335 
00336         forAllConstIter(IDLList<entry>, constraintDict, iter)
00337         {
00338             if (iter().isDict())
00339             {
00340                 // Info<< "Adding constraint: " << iter().keyword() << endl;
00341 
00342                 constraints_.set
00343                 (
00344                     i,
00345                     sixDoFRigidBodyMotionConstraint::New(iter().dict())
00346                 );
00347 
00348                 constraintNames_[i] = iter().keyword();
00349 
00350                 i++;
00351             }
00352         }
00353 
00354         constraints_.setSize(i);
00355 
00356         constraintNames_.setSize(i);
00357 
00358         if (!constraints_.empty())
00359         {
00360             maxConstraintIterations_ = readLabel
00361             (
00362                 constraintDict.lookup("maxIterations")
00363             );
00364         }
00365     }
00366 }
00367 
00368 
00369 void Foam::sixDoFRigidBodyMotion::updatePosition
00370 (
00371     scalar deltaT,
00372     scalar deltaT0
00373 )
00374 {
00375     // First leapfrog velocity adjust and motion part, required before
00376     // force calculation
00377 
00378     if (Pstream::master())
00379     {
00380         vector aClip = a();
00381         scalar aMag = mag(aClip);
00382 
00383         if (aMag > SMALL)
00384         {
00385             aClip /= aMag;
00386         }
00387 
00388         if (aMag > aLim_)
00389         {
00390             WarningIn
00391             (
00392                 "void Foam::sixDoFRigidBodyMotion::updatePosition"
00393                 "("
00394                     "scalar deltaT, "
00395                     "scalar deltaT0"
00396                 ")"
00397             )
00398                 << "Limited acceleration " << a()
00399                 << " to " << aClip*aLim_
00400                 << endl;
00401         }
00402 
00403         v() += 0.5*(1 - cDamp_)*deltaT0*aClip*min(aMag, aLim_);
00404 
00405         pi() += 0.5*(1 - cDamp_)*deltaT0*tau();
00406 
00407         // Leapfrog move part
00408         centreOfMass() += deltaT*v();
00409 
00410         // Leapfrog orientation adjustment
00411         rotate(Q(), pi(), deltaT);
00412     }
00413 
00414     Pstream::scatter(motionState_);
00415 }
00416 
00417 
00418 void Foam::sixDoFRigidBodyMotion::updateForce
00419 (
00420     const vector& fGlobal,
00421     const vector& tauGlobal,
00422     scalar deltaT
00423 )
00424 {
00425     // Second leapfrog velocity adjust part, required after motion and
00426     // force calculation
00427 
00428     if (Pstream::master())
00429     {
00430         a() = fGlobal/mass_;
00431 
00432         tau() = (Q().T() & tauGlobal);
00433 
00434         applyRestraints();
00435 
00436         applyConstraints(deltaT);
00437 
00438         vector aClip = a();
00439         scalar aMag = mag(aClip);
00440 
00441         if (aMag > SMALL)
00442         {
00443             aClip /= aMag;
00444         }
00445 
00446         if (aMag > aLim_)
00447         {
00448             WarningIn
00449             (
00450                 "void Foam::sixDoFRigidBodyMotion::updateForce"
00451                 "("
00452                     "const vector& fGlobal, "
00453                     "const vector& tauGlobal, "
00454                     "scalar deltaT"
00455                 ")"
00456             )
00457                 << "Limited acceleration " << a()
00458                 << " to " << aClip*aLim_
00459                 << endl;
00460         }
00461 
00462         v() += 0.5*(1 - cDamp_)*deltaT*aClip*min(aMag, aLim_);
00463 
00464         pi() += 0.5*(1 - cDamp_)*deltaT*tau();
00465 
00466         if(report_)
00467         {
00468             status();
00469         }
00470     }
00471 
00472     Pstream::scatter(motionState_);
00473 }
00474 
00475 
00476 void Foam::sixDoFRigidBodyMotion::updateForce
00477 (
00478     const pointField& positions,
00479     const vectorField& forces,
00480     scalar deltaT
00481 )
00482 {
00483     vector fGlobal = vector::zero;
00484 
00485     vector tauGlobal = vector::zero;
00486 
00487     if (Pstream::master())
00488     {
00489         fGlobal = sum(forces);
00490 
00491         forAll(positions, i)
00492         {
00493             tauGlobal += (positions[i] - centreOfMass()) ^ forces[i];
00494         }
00495     }
00496 
00497     updateForce(fGlobal, tauGlobal, deltaT);
00498 }
00499 
00500 
00501 Foam::point Foam::sixDoFRigidBodyMotion::predictedPosition
00502 (
00503     const point& pInitial,
00504     const vector& deltaForce,
00505     const vector& deltaMoment,
00506     scalar deltaT
00507 ) const
00508 {
00509     vector vTemp = v() + deltaT*(a() + deltaForce/mass_);
00510 
00511     vector piTemp = pi() + deltaT*(tau() + (Q().T() & deltaMoment));
00512 
00513     point centreOfMassTemp = centreOfMass() + deltaT*vTemp;
00514 
00515     tensor QTemp = Q();
00516 
00517     rotate(QTemp, piTemp, deltaT);
00518 
00519     return
00520     (
00521         centreOfMassTemp
00522       + (QTemp & initialQ_.T() & (pInitial - initialCentreOfMass_))
00523     );
00524 }
00525 
00526 
00527 Foam::vector Foam::sixDoFRigidBodyMotion::predictedOrientation
00528 (
00529     const vector& vInitial,
00530     const vector& deltaMoment,
00531     scalar deltaT
00532 ) const
00533 {
00534     vector piTemp = pi() + deltaT*(tau() + (Q().T() & deltaMoment));
00535 
00536     tensor QTemp = Q();
00537 
00538     rotate(QTemp, piTemp, deltaT);
00539 
00540     return (QTemp & initialQ_.T() & vInitial);
00541 }
00542 
00543 
00544 void Foam::sixDoFRigidBodyMotion::status() const
00545 {
00546     Info<< "Centre of mass: " << centreOfMass() << nl
00547         << "Linear velocity: " << v() << nl
00548         << "Angular velocity: " << omega()
00549         << endl;
00550 }
00551 
00552 
00553 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines