EulerCoordinateRotation.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-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 "unitConversion.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  namespace coordinateRotations
38  {
39  defineTypeName(euler);
40 
41  // Standard short name
43  (
44  coordinateRotation,
45  euler,
46  dictionary,
47  euler
48  );
49 
50  // Longer name - Compat 1806
52  (
53  coordinateRotation,
54  euler,
55  dictionary,
56  EulerRotation
57  );
58  }
59 }
60 
61 
62 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
63 
65 (
66  const eulerOrder order,
67  const vector& angles,
68  bool degrees
69 )
70 {
71  scalar angle1(angles.component(vector::X)); // Rotation #1
72  scalar angle2(angles.component(vector::Y)); // Rotation #2
73  scalar angle3(angles.component(vector::Z)); // Rotation #3
74 
75  if (degrees)
76  {
77  angle1 *= degToRad();
78  angle2 *= degToRad();
79  angle3 *= degToRad();
80  }
81 
82  const scalar c1(cos(angle1)); const scalar s1(sin(angle1));
83  const scalar c2(cos(angle2)); const scalar s2(sin(angle2));
84  const scalar c3(cos(angle3)); const scalar s3(sin(angle3));
85 
86  // https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
87 
88  switch (order)
89  {
90  // Proper Euler angles
91 
92  case eulerOrder::XZX: // X1-Z2-X3 rotation
93  {
94  return tensor
95  (
96  ( c2 ), ( -c3*s2 ), ( s2*s3 ),
97  ( c1*s2 ), ( c1*c2*c3 - s1*s3 ), ( -c3*s1 - c1*c2*s3 ),
98  ( s1*s2 ), ( c1*s3 + c2*c3*s1 ), ( c1*c3 - c2*s1*s3 )
99  );
100  break;
101  }
102 
103  case eulerOrder::XYX: // X1-Y2-X3 rotation
104  {
105  return tensor
106  (
107  ( c2 ), ( s2*s3 ), ( c3*s2 ),
108  ( s1*s2 ), ( c1*c3 - c2*s1*s3 ), ( -c1*s3 - c2*c3*s1 ),
109  ( -c1*s2 ), ( c3*s1 + c1*c2*s3 ), ( c1*c2*c3 - s1*s3 )
110  );
111  break;
112  }
113 
114  case eulerOrder::YXY: // Y1-X2-Y3 rotation
115  {
116  return tensor
117  (
118  ( c1*c3 - c2*s1*s3 ), ( s1*s2 ), ( c1*s3 + c2*c3*s1 ),
119  ( s2*s3 ), ( c2 ), ( -c3*s2 ),
120  ( -c3*s1 -c1*c2*s3 ), ( c1*s2 ), ( c1*c2*c3 - s1*s3 )
121  );
122  break;
123  }
124 
125  case eulerOrder::YZY: // Y1-Z2-Y3 rotation
126  {
127  return tensor
128  (
129  ( c1*c2*c3 - s1*s3 ), ( -c1*s2 ), ( c3*s1 + c1*c2*s3 ),
130  ( c3*s2 ), ( c2 ), ( s2*s3 ),
131  (-c1*s3 - c2*c3*s1 ), ( s1*s2 ), ( c1*c3 - c2*s1*s3 )
132  );
133  break;
134  }
135 
136  case eulerOrder::ZYZ: // Z1-Y2-Z3 rotation
137  {
138  return tensor
139  (
140  ( c1*c2*c3 - s1*s3 ), ( -c3*s1 - c1*c2*s3 ), ( c1*s2 ),
141  ( c1*s3 + c2*c3*s1 ), ( c1*c3 - c2*s1*s3 ), ( s1*s2 ),
142  ( -c3*s2 ), ( s2*s3 ), ( c2 )
143  );
144  break;
145  }
146 
147  case eulerOrder::ZXZ: // Z1-X2-Z3 rotation
148  {
149  return tensor
150  (
151  ( c1*c3 - c2*s1*s3 ), ( -c1*s3 - c2*c3*s1 ), ( s1*s2 ),
152  ( c3*s1 + c1*c2*s3 ), ( c1*c2*c3 - s1*s3 ), ( -c1*s2 ),
153  ( s2*s3 ), ( c3*s2 ), ( c2 )
154  );
155  break;
156  }
157 
158 
159  // Tait-Bryan angles
160 
161  case eulerOrder::XZY: // X1-Z2-Y3 rotation
162  {
163  return tensor
164  (
165  ( c2*c3 ), ( -s2 ), ( c2*s3 ),
166  ( s1*s3 + c1*c3*s2 ), ( c1*c2 ), ( c1*s2*s3 - c3*s1 ),
167  ( c3*s1*s2 - c1*s3 ), ( c2*s1 ), ( c1*c3 + s1*s2*s3 )
168  );
169  break;
170  }
171 
172  case eulerOrder::XYZ: // X1-Y2-Z3 rotation
173  {
174  return tensor
175  (
176  ( c2*c3 ), ( -c2*s3 ), ( s2 ),
177  ( c1*s3 + c3*s1*s2 ), ( c1*c3 - s1*s2*s3 ), ( -c2*s1 ),
178  ( s1*s3 - c1*c3*s2 ), ( c3*s1 + c1*s2*s3 ), ( c1*c2 )
179  );
180  break;
181  }
182 
183  case eulerOrder::YXZ: // Y1-X2-Z3 rotation
184  {
185  return tensor
186  (
187  ( c1*c3 + s1*s2*s3 ), ( c3*s1*s2 - c1*s3 ), ( c2*s1 ),
188  ( c2*s3 ), ( c2*c3 ), ( -s2 ),
189  ( c1*s2*s3 - c3*s1 ), ( c1*c3*s2 + s1*s3 ), ( c1*c2 )
190  );
191  break;
192  }
193 
194  case eulerOrder::YZX: // Y1-Z2-X3 rotation
195  {
196  return tensor
197  (
198  ( c1*c2 ), ( s1*s3 - c1*c3*s2 ), ( c3*s1 + c1*s2*s3 ),
199  ( s2 ), ( c2*c3 ), ( -c2*s3 ),
200  ( -c2*s1 ), ( c1*s3 + c3*s1*s2 ), ( c1*c3 - s1*s2*s3 )
201  );
202  break;
203  }
204 
205  case eulerOrder::ZYX: // Z1-Y2-X3 rotation
206  {
207  return tensor
208  (
209  ( c1*c2 ), ( c1*s2*s3 - c3*s1 ), ( s1*s3 + c1*c3*s2 ),
210  ( c2*s1 ), ( c1*c3 + s1*s2*s3 ), ( c3*s1*s2 - c1*s3 ),
211  ( -s2 ), ( c2*s3 ), ( c2*c3 )
212  );
213  break;
214  }
215 
216  case eulerOrder::ZXY: // Z1-X2-Y3 rotation
217  {
218  return tensor
219  (
220  ( c1*c3 - s1*s2*s3 ), ( -c2*s1 ), ( c1*s3 + c3*s1*s2 ),
221  ( c3*s1 + c1*s2*s3 ), ( c1*c2 ), ( s1*s3 - c1*c3*s2 ),
222  ( -c2*s3 ), ( s2 ), ( c2*c3 )
223  );
224  break;
225  }
226 
227  default:
229  << "Unknown euler rotation order "
230  << int(order) << abort(FatalError);
231  break;
232  }
233 
234  return tensor::I;
235 }
236 
237 
239 (
240  const vector& angles,
241  bool degrees
242 )
243 {
244  return rotation(eulerOrder::ZXZ, angles, degrees);
245 }
246 
247 
248 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
249 
251 :
253  angles_(Zero),
254  degrees_(true),
255  order_(eulerOrder::ZXZ)
256 {}
257 
258 
260 :
262  angles_(crot.angles_),
263  degrees_(crot.degrees_),
264  order_(crot.order_)
265 {}
266 
267 
269 (
270  const vector& angles,
271  bool degrees
272 )
273 :
275  angles_(angles),
276  degrees_(degrees),
277  order_(eulerOrder::ZXZ)
278 {}
279 
280 
282 (
283  scalar angle1,
284  scalar angle2,
285  scalar angle3,
286  bool degrees
287 )
288 :
290  angles_(angle1, angle2, angle3),
291  degrees_(degrees),
292  order_(eulerOrder::ZXZ)
293 {}
294 
295 
297 :
299  angles_(dict.get<vector>("angles")),
300  degrees_(dict.getOrDefault("degrees", true)),
301  order_
302  (
303  quaternion::eulerOrderNames.getOrDefault
304  (
305  "order",
306  dict,
307  quaternion::eulerOrder::ZXZ
308  )
309  )
310 {}
311 
312 
313 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
314 
316 {
317  angles_ = Zero;
318  degrees_ = true;
319 }
320 
321 
323 {
324  return euler::rotation(angles_, degrees_);
325 }
326 
327 
329 {
330  os << "euler-angles(" << (degrees_ ? "deg" : "rad") << "): " << angles_;
331 }
332 
333 
335 (
336  const word& keyword,
337  Ostream& os
338 ) const
339 {
340  os.beginBlock(keyword);
341 
342  os.writeEntry("type", type());
343  os.writeEntry("angles", angles_);
344  if (!degrees_)
345  {
346  os.writeEntry("degrees", "false");
347  }
348 
349  // writeEntryIfDifferent, but with enumerated name
350  if (order_ != eulerOrder::ZXZ)
351  {
352  os.writeEntry("order", quaternion::eulerOrderNames[order_]);
353  }
354 
355  os.endBlock();
356 }
357 
358 
359 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::coordinateRotations::euler
A coordinateRotation defined in the z-x-z (intrinsic) Euler convention.
Definition: EulerCoordinateRotation.H:97
Foam::Tensor
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
Definition: complexI.H:275
EulerCoordinateRotation.H
Foam::VectorSpace::component
const Cmpt & component(const direction) const
Definition: VectorSpaceI.H:87
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:264
Foam::coordinateRotations::euler::writeEntry
virtual void writeEntry(const word &keyword, Ostream &os) const
Write dictionary entry.
Definition: EulerCoordinateRotation.C:335
unitConversion.H
Unit conversion functions.
Foam::coordinateRotations::euler::write
virtual void write(Ostream &os) const
Write information.
Definition: EulerCoordinateRotation.C:328
Foam::coordinateRotations::euler::clear
virtual void clear()
Reset specification.
Definition: EulerCoordinateRotation.C:315
Foam::quaternion
Quaternion class used to perform rotations in 3D space.
Definition: quaternion.H:56
Foam::constant::physicoChemical::c1
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Foam::coordinateRotation
User specification of a coordinate rotation.
Definition: coordinateRotation.H:78
Foam::coordinateRotations::defineTypeName
defineTypeName(axes)
Foam::quaternion::eulerOrder
eulerOrder
Euler-angle rotation order.
Definition: quaternion.H:102
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::coordinateRotations::euler::R
virtual tensor R() const
The rotation tensor calculated for the specified Euler angles.
Definition: EulerCoordinateRotation.C:322
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::coordinateRotations::addNamedToRunTimeSelectionTable
addNamedToRunTimeSelectionTable(coordinateRotation, axes, dictionary, axes)
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::constant::physicoChemical::c2
const dimensionedScalar c2
Second radiation constant: default SI units: [m.K].
Y
PtrList< volScalarField > & Y
Definition: createFieldRefs.H:7
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
Foam::quaternion::eulerOrderNames
static const Enum< eulerOrder > eulerOrderNames
The names for Euler-angle rotation order.
Definition: quaternion.H:112
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::Vector< scalar >
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::PtrListOps::get
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
Foam::coordinateRotations::euler::euler
euler()
Default construct - an identity transform.
Definition: EulerCoordinateRotation.C:250
Foam::coordinateRotations::euler::rotation
static tensor rotation(const vector &angles, bool degrees=false)
Definition: EulerCoordinateRotation.C:239
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::tensor
Tensor< scalar > tensor
Tensor of scalars, i.e. Tensor<scalar>.
Definition: symmTensor.H:61
Foam::I
static const Identity< scalar > I
Definition: Identity.H:95
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265