Loading...
Searching...
No Matches
sixDoFRigidBodyMotion.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2016-2023 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
30#include "sixDoFSolver.H"
31#include "septernion.H"
32
33// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34
35void Foam::sixDoFRigidBodyMotion::applyRestraints()
36{
37 if (restraints_.empty())
38 {
39 return;
40 }
41
42 if (Pstream::master())
43 {
44 forAll(restraints_, rI)
45 {
46 if (report_)
47 {
48 Info<< "Restraint " << restraints_[rI].name() << ": ";
49 }
50
51 // Restraint position
52 point rP = Zero;
53
54 // Restraint force
55 vector rF = Zero;
56
57 // Restraint moment
58 vector rM = Zero;
59
60 // Accumulate the restraints
61 restraints_[rI].restrain(*this, rP, rF, rM);
62
63 // Update the acceleration
64 a() += rF/mass_;
65
66 // Moments are returned in global axes, transforming to
67 // body local to add to torque.
68 tau() += Q().T() & (rM + ((rP - centreOfRotation()) ^ rF));
69 }
70 }
71}
72
73
74// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
75
77:
78 time_(time),
79 motionState_(),
80 motionState0_(),
81 restraints_(),
82 constraints_(),
83 tConstraints_(tensor::I),
84 rConstraints_(tensor::I),
85 initialCentreOfMass_(Zero),
86 initialCentreOfRotation_(Zero),
87 initialQ_(I),
88 mass_(VSMALL),
89 momentOfInertia_(diagTensor::one*VSMALL),
90 aRelax_(1.0),
91 aDamp_(1.0),
92 report_(false),
93 updateConstraints_(false),
94 solver_(nullptr)
95{}
96
97
99(
100 const dictionary& dict,
101 const dictionary& stateDict,
102 const Time& time
103)
104:
105 time_(time),
106 motionState_(stateDict),
107 motionState0_(),
108 restraints_(),
109 constraints_(),
110 tConstraints_(tensor::I),
111 rConstraints_(tensor::I),
112 initialCentreOfMass_
113 (
114 dict.getOrDefault
115 (
116 "initialCentreOfMass",
117 dict.get<vector>("centreOfMass")
118 )
119 ),
120 initialCentreOfRotation_(initialCentreOfMass_),
121 initialQ_
122 (
123 dict.getOrDefault
124 (
125 "initialOrientation",
126 dict.getOrDefault("orientation", tensor::I)
127 )
128 ),
129 mass_(dict.get<scalar>("mass")),
130 momentOfInertia_(dict.get<diagTensor>("momentOfInertia")),
131 aRelax_(dict.getOrDefault<scalar>("accelerationRelaxation", 1)),
132 aDamp_(dict.getOrDefault<scalar>("accelerationDamping", 1)),
133 report_(dict.getOrDefault("report", false)),
134 updateConstraints_(dict.getOrDefault("updateConstraints", false)),
135 solver_(sixDoFSolver::New(dict.subDict("solver"), *this))
136{
138
139 // Set constraints and initial centre of rotation
140 // if different to the centre of mass
142
143 // If the centres of mass and rotation are different ...
144 vector R(initialCentreOfMass_ - initialCentreOfRotation_);
145 if (magSqr(R) > VSMALL)
146 {
147 // ... correct the moment of inertia tensor using parallel axes theorem
148 momentOfInertia_ += mass_*diag(I*magSqr(R) - sqr(R));
149
150 // ... and if the centre of rotation is not specified for motion state
151 // update it
152 if (!stateDict.found("centreOfRotation"))
153 {
154 motionState_.centreOfRotation() = initialCentreOfRotation_;
155 }
157
158 // Save the old-time motion state
159 motionState0_ = motionState_;
160}
161
162
164(
165 const sixDoFRigidBodyMotion& sDoFRBM
166)
167:
168 time_(sDoFRBM.time_),
169 motionState_(sDoFRBM.motionState_),
170 motionState0_(sDoFRBM.motionState0_),
171 restraints_(sDoFRBM.restraints_),
172 constraints_(sDoFRBM.constraints_),
173 tConstraints_(sDoFRBM.tConstraints_),
174 rConstraints_(sDoFRBM.rConstraints_),
175 initialCentreOfMass_(sDoFRBM.initialCentreOfMass_),
176 initialCentreOfRotation_(sDoFRBM.initialCentreOfRotation_),
177 initialQ_(sDoFRBM.initialQ_),
178 mass_(sDoFRBM.mass_),
179 momentOfInertia_(sDoFRBM.momentOfInertia_),
180 aRelax_(sDoFRBM.aRelax_),
181 aDamp_(sDoFRBM.aDamp_),
182 report_(sDoFRBM.report_),
183 updateConstraints_(sDoFRBM.updateConstraints_),
184 solver_(sDoFRBM.solver_.clone())
185{}
186
187
188// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
191{} // Define here (incomplete type in header)
192
193
194// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
195
197(
198 const dictionary& dict
199)
200{
201 if (dict.found("restraints"))
202 {
203 const dictionary& restraintDict = dict.subDict("restraints");
204
205 label i = 0;
206
207 restraints_.setSize(restraintDict.size());
208
209 for (const entry& dEntry : restraintDict)
210 {
211 if (dEntry.isDict())
212 {
213 restraints_.set
214 (
215 i++,
217 (
218 dEntry.keyword(),
219 dEntry.dict()
220 )
221 );
222 }
224
225 restraints_.setSize(i);
226 }
227}
228
229
231(
232 const dictionary& dict
233)
234{
235 if (dict.found("constraints"))
236 {
237 const dictionary& constraintDict = dict.subDict("constraints");
238
239 label i = 0;
240
241 constraints_.setSize(constraintDict.size());
242
243 pointConstraint pct;
244 pointConstraint pcr;
245
246 for (const entry& dEntry : constraintDict)
247 {
248 if (dEntry.isDict())
249 {
250 constraints_.set
251 (
252 i,
254 (
255 dEntry.keyword(),
256 dEntry.dict(),
257 *this
258 )
259 );
260
261 constraints_[i].setCentreOfRotation(initialCentreOfRotation_);
262 constraints_[i].constrainTranslation(pct);
263 constraints_[i].constrainRotation(pcr);
264
265 i++;
266 }
267 }
268
269 constraints_.setSize(i);
270
271 tConstraints_ = pct.constraintTransformation();
272 rConstraints_ = pcr.constraintTransformation();
273
274 Info<< "Translational constraint tensor " << tConstraints_ << nl
275 << "Rotational constraint tensor " << rConstraints_ << endl;
276 }
277}
278
279
280void Foam::sixDoFRigidBodyMotion::updateAcceleration
281(
282 const vector& fGlobal,
283 const vector& tauGlobal
284)
285{
286 static bool first = true;
287
288 // Save the previous iteration accelerations for relaxation
289 vector aPrevIter = a();
290 vector tauPrevIter = tau();
291
292 // Calculate new accelerations
293 a() = fGlobal/mass_;
294 tau() = (Q().T() & tauGlobal);
295 applyRestraints();
296
297 // Relax accelerations on all but first iteration
298 if (!first)
299 {
300 a() = aRelax_*a() + (1 - aRelax_)*aPrevIter;
301 tau() = aRelax_*tau() + (1 - aRelax_)*tauPrevIter;
302 }
303 else
304 {
305 first = false;
306 }
307}
308
309
311{
312 if (!updateConstraints_)
313 {
314 return;
315 }
316
317 pointConstraint pct;
318 pointConstraint pcr;
319
320 forAll(constraints_, i)
321 {
322 constraints_[i].setCentreOfRotation(initialCentreOfRotation_);
323 constraints_[i].constrainTranslation(pct);
324 constraints_[i].constrainRotation(pcr);
325 }
326
327 tConstraints_ = pct.constraintTransformation();
328 rConstraints_ = pcr.constraintTransformation();
329
330 Info<< "Translational constraint tensor " << tConstraints_ << nl
331 << "Rotational constraint tensor " << rConstraints_ << endl;
332}
333
334
336(
337 bool firstIter,
338 const vector& fGlobal,
339 const vector& tauGlobal,
340 scalar deltaT,
341 scalar deltaT0
342)
343{
344 if (Pstream::master())
345 {
346 solver_->solve(firstIter, fGlobal, tauGlobal, deltaT, deltaT0);
347
348 if (report_)
349 {
350 status();
352 }
353
354 Pstream::broadcast(motionState_);
355}
356
357
359{
360 Info<< "6-DoF rigid body motion" << nl
361 << " Centre of rotation: " << centreOfRotation() << nl
362 << " Centre of mass: " << centreOfMass() << nl
363 << " Orientation: " << orientation() << nl
364 << " Linear velocity: " << v() << nl
365 << " Angular velocity: " << omega()
366 << endl;
367}
368
369
371(
372 const pointField& initialPoints
373) const
374{
375 return
378 + (Q() & initialQ_.T() & (initialPoints - initialCentreOfRotation_))
379 );
380}
381
382
384(
385 const pointField& initialPoints,
386 const scalarField& scale
387) const
388{
389 // Calculate the transformation septerion from the initial state
391 (
392 centreOfRotation() - initialCentreOfRotation(),
393 quaternion(Q().T() & initialQ())
394 );
395
396 auto tpoints = tmp<pointField>::New(initialPoints);
397 auto& points = tpoints.ref();
398
399 forAll(points, pointi)
400 {
401 // Move non-stationary points
402 if (scale[pointi] > SMALL)
403 {
404 // Use solid-body motion where scale = 1
405 if (scale[pointi] > 1 - SMALL)
406 {
407 points[pointi] = transform(initialPoints[pointi]);
408 }
409 // Slerp septernion interpolation
410 else
411 {
412 septernion ss(slerp(septernion::I, s, scale[pointi]));
413
414 points[pointi] =
415 initialCentreOfRotation()
417 (
418 initialPoints[pointi]
419 - initialCentreOfRotation()
420 );
421 }
422 }
423 }
424
425 return tpoints;
426}
427
428
429// ************************************************************************* //
#define R(A, B, C, D, E, F, K, M)
label size() const noexcept
The number of elements in list.
Definition DLListBase.H:194
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition dictionary.C:441
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition one.H:57
Accumulates point constraints through successive applications of the applyConstraint function.
tensor constraintTransformation() const
Return the accumulated constraint transformation tensor.
Quaternion class used to perform rotations in 3D space.
Definition quaternion.H:54
Septernion class used to perform translations and rotations in 3D space.
Definition septernion.H:63
vector invTransformPoint(const vector &v) const
Inverse Transform the given coordinate point.
Definition septernionI.H:91
static const septernion I
Definition septernion.H:84
static autoPtr< sixDoFRigidBodyMotionConstraint > New(const word &name, const dictionary &sDoFRBMCDict, const sixDoFRigidBodyMotion &motion)
Select constructed from the sDoFRBMCDict dictionary and Time.
static autoPtr< sixDoFRigidBodyMotionRestraint > New(const word &name, const dictionary &sDoFRBMRDict)
Select constructed from the sDoFRBMRDict dictionary and Time.
const point & centreOfRotation() const
Return access to the centre of mass.
point centreOfMass() const
Return the current centre of mass.
void update(bool firstIter, const vector &fGlobal, const vector &tauGlobal, scalar deltaT, scalar deltaT0)
Symplectic integration of velocities, orientation and position.
const vector & v() const
Return the current velocity.
const Time & time() const
Return time.
void status() const
Report the status of the motion.
const tensor & orientation() const
Return the orientation tensor, Q.
void addConstraints(const dictionary &dict)
Add restraints to the motion, public to allow external.
bool updateConstraints() const
Return the update-constraints flag.
sixDoFRigidBodyMotion(const Time &)
Construct null.
point transform(const point &initialPoints) const
Transform the given initial state point by the current motion.
vector omega() const
Return the angular velocity in the global frame.
void addRestraints(const dictionary &dict)
Add restraints to the motion, public to allow external.
const point & centreOfRotation() const
Return the current centre of rotation.
A class for managing temporary objects.
Definition tmp.H:75
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition tmp.H:215
const volScalarField & T
const pointField & points
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.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))
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
DiagTensor< scalar > diagTensor
DiagTensor of scalars, i.e. DiagTensor<scalar>.
Definition diagTensor.H:49
dimensionedSymmTensor sqr(const dimensionedVector &dv)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
messageStream Info
Information stream (stdout output on master, null elsewhere).
static const Identity< scalar > I
Definition Identity.H:100
Tensor< scalar > tensor
Definition symmTensor.H:57
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
vectorField pointField
pointField is a vectorField.
quaternion slerp(const quaternion &qa, const quaternion &qb, const scalar t)
Spherical linear interpolation of quaternions.
Definition quaternion.C:75
Vector< scalar > vector
Definition vector.H:57
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299