00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "sixDoFRigidBodyMotion.H"
00027
00028
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
00047 point rP = vector::zero;
00048
00049
00050 vector rF = vector::zero;
00051
00052
00053 vector rM = vector::zero;
00054
00055 restraints_[rI].restrain(*this, rP, rF, rM);
00056
00057 a() += rF/mass_;
00058
00059
00060
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
00081 vector cFA = vector::zero;
00082
00083
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
00098 point cP = vector::zero;
00099
00100
00101 vector cF = vector::zero;
00102
00103
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
00120 cFA += cF;
00121
00122
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
00153 a() += cFA/mass_;
00154
00155
00156
00157
00158 tau() += Q().T() & cMA;
00159 }
00160 }
00161
00162
00163
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
00274
00275 Foam::sixDoFRigidBodyMotion::~sixDoFRigidBodyMotion()
00276 {}
00277
00278
00279
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
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
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
00376
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
00408 centreOfMass() += deltaT*v();
00409
00410
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
00426
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