sixDoFRigidBodyMotion.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "sixDoFRigidBodyMotion.H"
27 #include "sixDoFSolver.H"
28 #include "septernion.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 void Foam::sixDoFRigidBodyMotion::applyRestraints()
33 {
34  if (restraints_.empty())
35  {
36  return;
37  }
38 
39  if (Pstream::master())
40  {
41  forAll(restraints_, rI)
42  {
43  if (report_)
44  {
45  Info<< "Restraint " << restraints_[rI].name() << ": ";
46  }
47 
48  // Restraint position
49  point rP = Zero;
50 
51  // Restraint force
52  vector rF = Zero;
53 
54  // Restraint moment
55  vector rM = Zero;
56 
57  // Accumulate the restraints
58  restraints_[rI].restrain(*this, rP, rF, rM);
59 
60  // Update the acceleration
61  a() += rF/mass_;
62 
63  // Moments are returned in global axes, transforming to
64  // body local to add to torque.
65  tau() += Q().T() & (rM + ((rP - centreOfRotation()) ^ rF));
66  }
67  }
68 }
69 
70 
71 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
72 
74 :
75  motionState_(),
76  motionState0_(),
77  restraints_(),
78  constraints_(),
79  tConstraints_(tensor::I),
80  rConstraints_(tensor::I),
81  initialCentreOfMass_(Zero),
82  initialCentreOfRotation_(Zero),
83  initialQ_(I),
84  mass_(vSmall),
85  momentOfInertia_(diagTensor::one*vSmall),
86  aRelax_(1.0),
87  aDamp_(1.0),
88  report_(false),
89  solver_(nullptr)
90 {}
91 
92 
94 (
95  const dictionary& dict,
96  const dictionary& stateDict
97 )
98 :
99  motionState_(stateDict),
100  motionState0_(),
101  restraints_(),
102  constraints_(),
103  tConstraints_(tensor::I),
104  rConstraints_(tensor::I),
105  initialCentreOfMass_
106  (
107  dict.lookupOrDefault
108  (
109  "initialCentreOfMass",
110  vector(dict.lookup("centreOfMass"))
111  )
112  ),
113  initialCentreOfRotation_(initialCentreOfMass_),
114  initialQ_
115  (
116  dict.lookupOrDefault
117  (
118  "initialOrientation",
119  dict.lookupOrDefault("orientation", tensor::I)
120  )
121  ),
122  mass_(readScalar(dict.lookup("mass"))),
123  momentOfInertia_(dict.lookup("momentOfInertia")),
124  aRelax_(dict.lookupOrDefault<scalar>("accelerationRelaxation", 1.0)),
125  aDamp_(dict.lookupOrDefault<scalar>("accelerationDamping", 1.0)),
126  report_(dict.lookupOrDefault<Switch>("report", false)),
127  solver_(sixDoFSolver::New(dict.subDict("solver"), *this))
128 {
129  addRestraints(dict);
130 
131  // Set constraints and initial centre of rotation
132  // if different to the centre of mass
133  addConstraints(dict);
134 
135  // If the centres of mass and rotation are different ...
136  vector R(initialCentreOfMass_ - initialCentreOfRotation_);
137  if (magSqr(R) > vSmall)
138  {
139  // ... correct the moment of inertia tensor using parallel axes theorem
140  momentOfInertia_ += mass_*diag(I*magSqr(R) - sqr(R));
141 
142  // ... and if the centre of rotation is not specified for motion state
143  // update it
144  if (!stateDict.found("centreOfRotation"))
145  {
146  motionState_.centreOfRotation() = initialCentreOfRotation_;
147  }
148  }
149 
150  // Save the old-time motion state
151  motionState0_ = motionState_;
152 }
153 
154 
156 (
157  const sixDoFRigidBodyMotion& sDoFRBM
158 )
159 :
160  motionState_(sDoFRBM.motionState_),
161  motionState0_(sDoFRBM.motionState0_),
162  restraints_(sDoFRBM.restraints_),
163  constraints_(sDoFRBM.constraints_),
164  tConstraints_(sDoFRBM.tConstraints_),
165  rConstraints_(sDoFRBM.rConstraints_),
166  initialCentreOfMass_(sDoFRBM.initialCentreOfMass_),
167  initialCentreOfRotation_(sDoFRBM.initialCentreOfRotation_),
168  initialQ_(sDoFRBM.initialQ_),
169  mass_(sDoFRBM.mass_),
170  momentOfInertia_(sDoFRBM.momentOfInertia_),
171  aRelax_(sDoFRBM.aRelax_),
172  aDamp_(sDoFRBM.aDamp_),
173  report_(sDoFRBM.report_)
174 {}
175 
176 
177 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
178 
180 {}
181 
182 
183 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
184 
186 (
187  const dictionary& dict
188 )
189 {
190  if (dict.found("restraints"))
191  {
192  const dictionary& restraintDict = dict.subDict("restraints");
193 
194  label i = 0;
195 
196  restraints_.setSize(restraintDict.size());
197 
198  forAllConstIter(IDLList<entry>, restraintDict, iter)
199  {
200  if (iter().isDict())
201  {
202  restraints_.set
203  (
204  i++,
206  (
207  iter().keyword(),
208  iter().dict()
209  )
210  );
211  }
212  }
213 
214  restraints_.setSize(i);
215  }
216 }
217 
218 
220 (
221  const dictionary& dict
222 )
223 {
224  if (dict.found("constraints"))
225  {
226  const dictionary& constraintDict = dict.subDict("constraints");
227 
228  label i = 0;
229 
230  constraints_.setSize(constraintDict.size());
231 
232  pointConstraint pct;
233  pointConstraint pcr;
234 
235  forAllConstIter(IDLList<entry>, constraintDict, iter)
236  {
237  if (iter().isDict())
238  {
239  constraints_.set
240  (
241  i,
243  (
244  iter().keyword(),
245  iter().dict(),
246  *this
247  )
248  );
249 
250  constraints_[i].setCentreOfRotation(initialCentreOfRotation_);
251  constraints_[i].constrainTranslation(pct);
252  constraints_[i].constrainRotation(pcr);
253 
254  i++;
255  }
256  }
257 
258  constraints_.setSize(i);
259 
260  tConstraints_ = pct.constraintTransformation();
261  rConstraints_ = pcr.constraintTransformation();
262 
263  Info<< "Translational constraint tensor " << tConstraints_ << nl
264  << "Rotational constraint tensor " << rConstraints_ << endl;
265  }
266 }
267 
268 
269 void Foam::sixDoFRigidBodyMotion::updateAcceleration
270 (
271  const vector& fGlobal,
272  const vector& tauGlobal
273 )
274 {
275  static bool first = true;
276 
277  // Save the previous iteration accelerations for relaxation
278  vector aPrevIter = a();
279  vector tauPrevIter = tau();
280 
281  // Calculate new accelerations
282  a() = fGlobal/mass_;
283  tau() = (Q().T() & tauGlobal);
284  applyRestraints();
285 
286  // Relax accelerations on all but first iteration
287  if (!first)
288  {
289  a() = aRelax_*a() + (1 - aRelax_)*aPrevIter;
290  tau() = aRelax_*tau() + (1 - aRelax_)*tauPrevIter;
291  }
292  else
293  {
294  first = false;
295  }
296 }
297 
298 
300 (
301  bool firstIter,
302  const vector& fGlobal,
303  const vector& tauGlobal,
304  scalar deltaT,
305  scalar deltaT0
306 )
307 {
308  if (Pstream::master())
309  {
310  solver_->solve(firstIter, fGlobal, tauGlobal, deltaT, deltaT0);
311 
312  if (report_)
313  {
314  status();
315  }
316  }
317 
318  Pstream::scatter(motionState_);
319 }
320 
321 
323 {
324  Info<< "6-DoF rigid body motion" << nl
325  << " Centre of rotation: " << centreOfRotation() << nl
326  << " Centre of mass: " << centreOfMass() << nl
327  << " Orientation: " << orientation() << nl
328  << " Linear velocity: " << v() << nl
329  << " Angular velocity: " << omega()
330  << endl;
331 }
332 
333 
335 (
336  const pointField& initialPoints
337 ) const
338 {
339  return
340  (
342  + (Q() & initialQ_.T() & (initialPoints - initialCentreOfRotation_))
343  );
344 }
345 
346 
348 (
349  const pointField& initialPoints,
350  const scalarField& scale
351 ) const
352 {
353  // Calculate the transformation septerion from the initial state
354  septernion s
355  (
356  centreOfRotation() - initialCentreOfRotation(),
357  quaternion(Q().T() & initialQ())
358  );
359 
360  tmp<pointField> tpoints(new pointField(initialPoints));
361  pointField& points = tpoints.ref();
362 
363  forAll(points, pointi)
364  {
365  // Move non-stationary points
366  if (scale[pointi] > small)
367  {
368  // Use solid-body motion where scale = 1
369  if (scale[pointi] > 1 - small)
370  {
371  points[pointi] = transform(initialPoints[pointi]);
372  }
373  // Slerp septernion interpolation
374  else
375  {
376  septernion ss(slerp(septernion::I, s, scale[pointi]));
377 
378  points[pointi] =
379  initialCentreOfRotation()
380  + ss.invTransformPoint
381  (
382  initialPoints[pointi]
383  - initialCentreOfRotation()
384  );
385  }
386  }
387  }
388 
389  return tpoints;
390 }
391 
392 
393 // ************************************************************************* //
Six degree of freedom motion for a rigid body.
Template class for intrusive linked lists.
Definition: ILList.H:50
void addConstraints(const dictionary &dict)
Add restraints to the motion, public to allow external.
dictionary dict
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:438
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
point centreOfMass() const
Return the current centre of mass.
const point & centreOfRotation() const
Return the current centre of rotation.
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:174
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Tensor< Cmpt > T() const
Return transpose.
Definition: TensorI.H:321
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none/any.
Definition: Switch.H:60
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
point transform(const point &initialPoints) const
Transform the given initial state point by the current motion.
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Septernion class used to perform translations and rotations in 3D space.
Definition: septernion.H:65
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:699
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
const point & centreOfRotation() const
Return access to the centre of mass.
const pointField & points
static const Identity< scalar > I
Definition: Identity.H:93
vector omega() const
Return the angular velocity in the global frame.
sixDoFRigidBodyMotion()
Construct null.
const tensor & orientation() const
Return the orientation tensor, Q.
Quaternion class used to perform rotations in 3D space.
Definition: quaternion.H:60
static const zero Zero
Definition: zero.H:97
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:68
static const septernion I
Definition: septernion.H:83
void status() const
Report the status of the motion.
Accumulates point constraints through successive applications of the applyConstraint function...
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
static const Tensor I
Definition: Tensor.H:80
static const char nl
Definition: Ostream.H:265
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
tensor constraintTransformation() const
Return the accumulated constraint transformation tensor.
vector invTransformPoint(const vector &v) const
Inverse Transform the given coordinate point.
Definition: septernionI.H:88
static autoPtr< sixDoFRigidBodyMotionRestraint > New(const word &name, const dictionary &sDoFRBMRDict)
Select constructed from the sDoFRBMRDict dictionary and Time.
vector point
Point is a vector.
Definition: point.H:41
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
#define R(A, B, C, D, E, F, K, M)
quaternion slerp(const quaternion &qa, const quaternion &qb, const scalar t)
Spherical linear interpolation of quaternions.
Definition: quaternion.C:55
messageStream Info
static autoPtr< sixDoFRigidBodyMotionConstraint > New(const word &name, const dictionary &sDoFRBMCDict, const sixDoFRigidBodyMotion &motion)
Select constructed from the sDoFRBMCDict dictionary and Time.
A class for managing temporary objects.
Definition: PtrList.H:53
static autoPtr< sixDoFSolver > New(const dictionary &dict, sixDoFRigidBodyMotion &body)
void update(bool firstIter, const vector &fGlobal, const vector &tauGlobal, scalar deltaT, scalar deltaT0)
Symplectic integration of velocities, orientation and position.
void addRestraints(const dictionary &dict)
Add restraints to the motion, public to allow external.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:583
A class representing the concept of 1 (scalar(1)) used to avoid unnecessary manipulations for objects...
Definition: one.H:50