axesRotation.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-2022 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 
29 #include "axesRotation.H"
30 #include "dictionary.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 namespace coordinateRotations
38 {
39 
41 
42  // Standard short name
44  (
46  axes,
47  dictionary,
48  axes
49  );
50 
51  // Long name - Compat 1806
53  (
55  axes,
56  dictionary,
57  axes,
59  1806
60  );
61 
62 } // End namespace coordinateRotations
63 } // End namespace Foam
64 
65 
66 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
67 
69 (
70  const vector& axis1,
71  const vector& axis2,
72  axisOrder order
73 )
74 {
75  const scalar magAxis1(mag(axis1));
76  scalar magAxis2(mag(axis2));
77 
78  if (magAxis1 < ROOTVSMALL)
79  {
81  << "Dominant coordinate axis cannot have zero length"
82  << nl << endl
83  << abort(FatalError);
84  }
85 
86  const vector ax1(axis1 / magAxis1); // normalise
87  vector ax2(axis2);
88 
89  if (magAxis2 < ROOTVSMALL)
90  {
91  // axis2 == Zero : Use best-guess for the second axis.
92  ax2 = findOrthogonal(axis1);
93  }
94 
95  ax2.removeCollinear(ax1);
96 
97  magAxis2 = mag(ax2);
98 
99  if (magAxis2 < SMALL)
100  {
102  << "axis1, axis2 appear to be co-linear: "
103  << axis1 << ", " << axis2 << " Revert to guessing axis2"
104  << nl << endl;
105 
106  ax2 = findOrthogonal(axis1);
107 
108  ax2.removeCollinear(ax1);
109 
110  magAxis2 = mag(ax2);
111 
112  if (magAxis2 < SMALL)
113  {
115  << "Could not find an appropriate second axis"
116  << nl << endl
117  << abort(FatalError);
118  }
119  }
120 
121  ax2 /= magAxis2; // normalise
122 
123 
124  // The local axes are columns of the rotation matrix
125 
126  tensor rotTensor;
127 
128  switch (order)
129  {
130  case E1_E2:
131  {
132  rotTensor.col<0>(ax1);
133  rotTensor.col<1>(ax2);
134  rotTensor.col<2>(ax1^ax2);
135  break;
136  }
137  case E2_E3:
138  {
139  rotTensor.col<0>(ax1^ax2);
140  rotTensor.col<1>(ax1);
141  rotTensor.col<2>(ax2);
142  break;
143  }
144  case E3_E1:
145  case E3_E1_COMPAT:
146  {
147  rotTensor.col<0>(ax2);
148  rotTensor.col<1>(ax1^ax2);
149  rotTensor.col<2>(ax1);
150  break;
151  }
152  }
154  return rotTensor;
155 }
156 
157 
158 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
159 
161 {
162  if
163  (
164  dict.readIfPresent("e1", axis1_)
165  && dict.readIfPresent("e2", axis2_)
166  )
167  {
168  order_ = E1_E2;
169  }
170  else if
171  (
172  dict.readIfPresent("e2", axis1_)
173  && dict.readIfPresent("e3", axis2_)
174  )
175  {
176  order_ = E2_E3;
177  }
178  else if
179  (
180  dict.readIfPresent("e3", axis1_)
181  && dict.readIfPresent("e1", axis2_)
182  )
183  {
184  order_ = E3_E1;
185  }
186  else if
187  (
188  dict.readIfPresent("axis", axis1_)
189  && dict.readIfPresent("direction", axis2_)
190  )
191  {
192  order_ = E3_E1_COMPAT;
193  }
194  else
195  {
197  << "No entries of the type (e1, e2) or (e2, e3) or (e3, e1) found"
199  }
200 }
201 
202 
203 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
204 
206 :
208  axis1_(0,0,1), // e3 = global Z
209  axis2_(1,0,0), // e1 = global X
210  order_(E3_E1)
211 {}
212 
213 
215 :
217  axis1_(crot.axis1_),
218  axis2_(crot.axis2_),
219  order_(crot.order_)
220 {}
221 
222 
224 (
225  const vector& axis1,
226  const vector& axis2,
227  axisOrder order
228 )
229 :
231  axis1_(axis1),
232  axis2_(axis2),
233  order_(order)
234 {}
235 
238 :
239  coordinateRotations::axes(axis, Zero, E3_E1_COMPAT) // Guess second axis
240 {}
241 
242 
244 :
245  coordinateRotations::axes()
246 {
247  read(dict);
248 }
249 
250 
251 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
252 
254 {
255  axis1_ = vector(0,0,1); // primary axis (e3, global Z)
256  axis2_ = vector(1,0,0); // secondary axis (e1, global X)
257  order_ = E3_E1;
258 }
259 
260 
262 {
263  return axes::rotation(axis1_, axis2_, order_);
264 }
265 
266 
267 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
268 
270 {
271  switch (order_)
272  {
273  case E1_E2:
274  os << "e1: " << axis1_ << " e2: " << axis2_;
275  break;
276  case E2_E3:
277  os << "e2: " << axis1_ << " e3: " << axis2_;
278  break;
279  case E3_E1:
280  os << "e1: " << axis2_ << " e3: " << axis1_;
281  break;
282  case E3_E1_COMPAT:
283  os << "axis: " << axis1_ << " direction: " << axis2_;
284  break;
285  }
286 }
287 
288 
290 (
291  const word& keyword,
292  Ostream& os
293 ) const
294 {
295  // We permit direct embedding of the axes specification without
296  // requiring a sub-dictionary.
297 
298  const bool subDict = !keyword.empty();
299 
300  if (subDict)
301  {
302  os.beginBlock(keyword);
303  os.writeEntry("type", type());
304  }
305 
306  switch (order_)
307  {
308  case E1_E2:
309  {
310  os.writeEntry("e1", axis1_);
311  os.writeEntry("e2", axis2_);
312  break;
313  }
314  case E2_E3:
315  {
316  os.writeEntry("e2", axis1_);
317  os.writeEntry("e3", axis2_);
318  break;
319  }
320  case E3_E1:
321  {
322  os.writeEntry("e1", axis2_);
323  os.writeEntry("e3", axis1_);
324  break;
325  }
326  case E3_E1_COMPAT:
327  {
328  os.writeEntry("axis", axis1_);
329  os.writeEntry("direction", axis2_);
330  break;
331  }
332  }
333 
334  if (subDict)
335  {
336  os.endBlock();
337  }
338 }
339 
340 
341 // ************************************************************************* //
E3_E1 specified as axis/direction.
Definition: axesRotation.H:117
User specification of a coordinate rotation.
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Tensor< scalar > tensor
Definition: symmTensor.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Macros for easy insertion into run-time selection tables.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
The axis1 (dominant) is local Y, axis2 is local Z.
Definition: axesRotation.H:115
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
The axis1 (dominant) is local Z, axis2 is local X.
Definition: axesRotation.H:116
static tensor rotation(const vector &axis1, const vector &axis2, axisOrder order=E3_E1)
The rotation tensor calculated from two axes and their order.
Definition: axesRotation.C:62
A class for handling words, derived from Foam::string.
Definition: word.H:63
Vector< scalar > vector
Definition: vector.H:57
addAliasToRunTimeSelectionTable(coordinateRotation, axes, dictionary, axes, axesRotation, 1806)
errorManip< error > abort(error &err)
Definition: errorManip.H:139
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
OBJstream os(runTime.globalPath()/outputName)
static vector findOrthogonal(const vector &axis)
Determine best-guess for an orthogonal axis.
void read(const dictionary &dict)
Read from dictionary.
Definition: axesRotation.C:153
virtual void writeEntry(const word &keyword, Ostream &os) const
Write dictionary entry.
Definition: axesRotation.C:283
#define WarningInFunction
Report a warning using Foam::Warning.
A coordinateRotation specified using global axes.
Definition: axesRotation.H:101
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
addNamedToRunTimeSelectionTable(coordinateRotation, axes, dictionary, axes)
The axis1 (dominant) is local X, axis2 is local Y.
Definition: axesRotation.H:114
Tensor of scalars, i.e. Tensor<scalar>.
virtual void write(Ostream &os) const
Write information.
Definition: axesRotation.C:262
virtual void clear()
Reset specification.
Definition: axesRotation.C:246
axes()
Default construct - an identity transform.
Definition: axesRotation.C:198
Namespace for OpenFOAM.
virtual tensor R() const
The rotation tensor calculated from the specified axes and order.
Definition: axesRotation.C:254
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127