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