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-------------------------------------------------------------------------------
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
29#include "axesRotation.H"
30#include "dictionary.H"
32
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
35namespace Foam
36{
37namespace coordinateRotations
38{
39
41
42 // Standard short name
44 (
46 axes,
48 axes
49 );
50
51 // Long name - Compat 1806
53 (
55 axes,
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 }
153
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"
198 << exit(FatalIOError);
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
236
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// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addAliasToRunTimeSelectionTable(baseType, thisType, argNames, lookup, other, ver)
Add lookup alias for runTime selection.
#define addNamedToRunTimeSelectionTable(baseType, thisType, argNames, lookupName)
Add to construction table with 'lookupName' as the key.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
virtual bool read()
Re-read model coefficients if they have changed.
Vector< Cmpt > col() const
Extract vector for given column: compile-time check of index.
Vector< Cmpt > & removeCollinear(const Vector< Cmpt > &unitVec)
Definition: VectorI.H:142
User specification of a coordinate rotation.
static vector findOrthogonal(const vector &axis)
Determine best-guess for an orthogonal axis.
A coordinateRotation specified using global axes.
Definition: axesRotation.H:108
axes()
Default construct - an identity transform.
Definition: axesRotation.C:205
virtual tensor R() const
The rotation tensor calculated from the specified axes and order.
Definition: axesRotation.C:261
void read(const dictionary &dict)
Read from dictionary.
Definition: axesRotation.C:160
virtual void writeEntry(const word &keyword, Ostream &os) const
Write dictionary entry.
Definition: axesRotation.C:290
axisOrder
The order/combination of local axes for the axes-rotation definition.
Definition: axesRotation.H:114
@ E2_E3
The axis1 (dominant) is local Y, axis2 is local Z.
Definition: axesRotation.H:116
@ E1_E2
The axis1 (dominant) is local X, axis2 is local Y.
Definition: axesRotation.H:115
@ E3_E1_COMPAT
E3_E1 specified as axis/direction.
Definition: axesRotation.H:118
@ E3_E1
The axis1 (dominant) is local Z, axis2 is local X.
Definition: axesRotation.H:117
virtual void clear()
Reset specification.
Definition: axesRotation.C:253
virtual const coordinateRotation & rotation() const
The rotation specification.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
virtual bool write()
Write the output fields.
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeName(Type)
Define the typeName.
Definition: className.H:96
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
errorManip< error > abort(error &err)
Definition: errorManip.H:144
IOerror FatalIOError
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
Vector< scalar > vector
Definition: vector.H:61
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict