transform.H
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) 2020 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
27InNamespace
28 Foam
29
30Description
31 3D tensor transformation operations.
32
33\*---------------------------------------------------------------------------*/
34
35#ifndef Foam_transform_H
36#define Foam_transform_H
37
38#include "tensor.H"
40#include <type_traits>
41
42// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43
44namespace Foam
45{
46
47// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48
49//- Rotational transformation tensor from vector n1 to n2
51(
52 const vector& n1,
53 const vector& n2
54)
55{
56 const scalar s = n1 & n2;
57 const vector n3 = n1 ^ n2;
58 const scalar magSqrN3 = magSqr(n3);
59
60 // n1 and n2 define a plane n3
61 if (magSqrN3 > SMALL)
62 {
63 // Return rotational transformation tensor in the n3-plane
64 return
65 s*I
66 + (1 - s)*sqr(n3)/magSqrN3
67 + (n2*n1 - n1*n2);
68 }
69 // n1 and n2 are contradirectional
70 else if (s < 0)
71 {
72 // Return mirror transformation tensor
73 return I + 2*n1*n2;
74 }
75 // n1 and n2 are codirectional
76 else
77 {
78 // Return null transformation tensor
79 return I;
80 }
81}
82
83
84//- Rotational transformation tensor about the x-axis by omega radians
85inline tensor Rx(const scalar omega)
86{
87 const scalar s = sin(omega);
88 const scalar c = cos(omega);
89 return tensor
90 (
91 1, 0, 0,
92 0, c, s,
93 0, -s, c
94 );
95}
96
97
98//- Rotational transformation tensor about the y-axis by omega radians
99inline tensor Ry(const scalar omega)
100{
101 const scalar s = sin(omega);
102 const scalar c = cos(omega);
103 return tensor
104 (
105 c, 0, -s,
106 0, 1, 0,
107 s, 0, c
108 );
109}
110
111
112//- Rotational transformation tensor about the z-axis by omega radians
113inline tensor Rz(const scalar omega)
114{
115 const scalar s = sin(omega);
116 const scalar c = cos(omega);
117 return tensor
118 (
119 c, s, 0,
120 -s, c, 0,
121 0, 0, 1
122 );
123}
124
125
126//- Rotational transformation tensor about axis a by omega radians
127inline tensor Ra(const vector& a, const scalar omega)
128{
129 const scalar s = sin(omega);
130 const scalar c = cos(omega);
131
132 return tensor
133 (
134 sqr(a.x())*(1 - c) + c,
135 a.y()*a.x()*(1 - c) + a.z()*s,
136 a.x()*a.z()*(1 - c) - a.y()*s,
137
138 a.x()*a.y()*(1 - c) - a.z()*s,
139 sqr(a.y())*(1 - c) + c,
140 a.y()*a.z()*(1 - c) + a.x()*s,
141
142 a.x()*a.z()*(1 - c) + a.y()*s,
143 a.y()*a.z()*(1 - c) - a.x()*s,
144 sqr(a.z())*(1 - c) + c
145 );
146}
147
148
149//- No-op rotational transform for base types
150template<class T>
151constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
152transform(const tensor&, const T val)
153{
154 return val;
155}
156
157//- No-op inverse rotational transform for base types
158template<class T>
159constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
160invTransform(const tensor&, const T val)
161{
162 return val;
163}
164
165
166//- Use rotational tensor to transform a vector.
167// Same as (rot & v)
168template<class Cmpt>
169inline Vector<Cmpt> transform(const tensor& tt, const Vector<Cmpt>& v)
170{
171 return (tt & v);
172}
173
174
175//- Use rotational tensor to inverse transform a vector.
176// Same as (v & rot)
177template<class Cmpt>
178inline Vector<Cmpt> invTransform(const tensor& tt, const Vector<Cmpt>& v)
179{
180 return (v & tt);
181}
182
183
184//- Use rotational tensor to transform a tensor.
185// Same as (rot & input & rot.T())
186template<class Cmpt>
187inline Tensor<Cmpt> transform(const tensor& tt, const Tensor<Cmpt>& t)
188{
189 return Tensor<Cmpt>
190 (
191 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.xx()
192 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.xy()
193 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.xz(),
194
195 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.yx()
196 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.yy()
197 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.yz(),
198
199 (tt.xx()*t.xx() + tt.xy()*t.yx() + tt.xz()*t.zx())*tt.zx()
200 + (tt.xx()*t.xy() + tt.xy()*t.yy() + tt.xz()*t.zy())*tt.zy()
201 + (tt.xx()*t.xz() + tt.xy()*t.yz() + tt.xz()*t.zz())*tt.zz(),
202
203 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.xx()
204 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.xy()
205 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.xz(),
206
207 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.yx()
208 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.yy()
209 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.yz(),
210
211 (tt.yx()*t.xx() + tt.yy()*t.yx() + tt.yz()*t.zx())*tt.zx()
212 + (tt.yx()*t.xy() + tt.yy()*t.yy() + tt.yz()*t.zy())*tt.zy()
213 + (tt.yx()*t.xz() + tt.yy()*t.yz() + tt.yz()*t.zz())*tt.zz(),
214
215 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.xx()
216 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.xy()
217 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.xz(),
218
219 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.yx()
220 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.yy()
221 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.yz(),
222
223 (tt.zx()*t.xx() + tt.zy()*t.yx() + tt.zz()*t.zx())*tt.zx()
224 + (tt.zx()*t.xy() + tt.zy()*t.yy() + tt.zz()*t.zy())*tt.zy()
225 + (tt.zx()*t.xz() + tt.zy()*t.yz() + tt.zz()*t.zz())*tt.zz()
226 );
227}
228
229
230//- Use rotational tensor to inverse transform a tensor.
231// Same as (rot.T() & input & rot)
232template<class Cmpt>
233inline Tensor<Cmpt> invTransform(const tensor& tt, const Tensor<Cmpt>& t)
234{
235 return Tensor<Cmpt>
236 (
237 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xx()
238 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yx()
239 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zx(),
240
241 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xy()
242 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yy()
243 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zy(),
244
245 (tt.xx()*t.xx() + tt.yx()*t.yx() + tt.zx()*t.zx())*tt.xz()
246 + (tt.xx()*t.xy() + tt.yx()*t.yy() + tt.zx()*t.zy())*tt.yz()
247 + (tt.xx()*t.xz() + tt.yx()*t.yz() + tt.zx()*t.zz())*tt.zz(),
248
249 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xx()
250 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yx()
251 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zx(),
252
253 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xy()
254 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yy()
255 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zy(),
256
257 (tt.xy()*t.xx() + tt.yy()*t.yx() + tt.zy()*t.zx())*tt.xz()
258 + (tt.xy()*t.xy() + tt.yy()*t.yy() + tt.zy()*t.zy())*tt.yz()
259 + (tt.xy()*t.xz() + tt.yy()*t.yz() + tt.zy()*t.zz())*tt.zz(),
260
261 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xx()
262 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yx()
263 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zx(),
264
265 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xy()
266 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yy()
267 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zy(),
268
269 (tt.xz()*t.xx() + tt.yz()*t.yx() + tt.zz()*t.zx())*tt.xz()
270 + (tt.xz()*t.xy() + tt.yz()*t.yy() + tt.zz()*t.zy())*tt.yz()
271 + (tt.xz()*t.xz() + tt.yz()*t.yz() + tt.zz()*t.zz())*tt.zz()
272 );
273}
274
275
276//- Use rotational tensor to transform a spherical tensor (no-op).
277template<class Cmpt>
279(
280 const tensor& tt,
281 const SphericalTensor<Cmpt>& st
282)
283{
284 return st;
285}
286
287
288//- Use rotational tensor to inverse transform a spherical tensor (no-op).
289template<class Cmpt>
291(
292 const tensor& tt,
293 const SphericalTensor<Cmpt>& st
294)
295{
296 return st;
297}
298
299
300//- Use rotational tensor to transform a symmetrical tensor.
301// Same as (rot & input & rot.T())
302template<class Cmpt>
304{
305 return SymmTensor<Cmpt>
306 (
307 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.xx()
308 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.xy()
309 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.xz(),
310
311 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.yx()
312 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.yy()
313 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.yz(),
314
315 (tt.xx()*st.xx() + tt.xy()*st.xy() + tt.xz()*st.xz())*tt.zx()
316 + (tt.xx()*st.xy() + tt.xy()*st.yy() + tt.xz()*st.yz())*tt.zy()
317 + (tt.xx()*st.xz() + tt.xy()*st.yz() + tt.xz()*st.zz())*tt.zz(),
318
319 (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.yx()
320 + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.yy()
321 + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.yz(),
322
323 (tt.yx()*st.xx() + tt.yy()*st.xy() + tt.yz()*st.xz())*tt.zx()
324 + (tt.yx()*st.xy() + tt.yy()*st.yy() + tt.yz()*st.yz())*tt.zy()
325 + (tt.yx()*st.xz() + tt.yy()*st.yz() + tt.yz()*st.zz())*tt.zz(),
326
327 (tt.zx()*st.xx() + tt.zy()*st.xy() + tt.zz()*st.xz())*tt.zx()
328 + (tt.zx()*st.xy() + tt.zy()*st.yy() + tt.zz()*st.yz())*tt.zy()
329 + (tt.zx()*st.xz() + tt.zy()*st.yz() + tt.zz()*st.zz())*tt.zz()
330 );
331}
332
333
334//- Use rotational tensor to inverse transform a symmetrical tensor.
335// Same as (rot.T() & input & rot)
336template<class Cmpt>
337inline SymmTensor<Cmpt>
339{
340 return SymmTensor<Cmpt>
341 (
342 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xx()
343 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yx()
344 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zx(),
345
346 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xy()
347 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yy()
348 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zy(),
349
350 (tt.xx()*st.xx() + tt.yx()*st.xy() + tt.zx()*st.xz())*tt.xz()
351 + (tt.xx()*st.xy() + tt.yx()*st.yy() + tt.zx()*st.yz())*tt.yz()
352 + (tt.xx()*st.xz() + tt.yx()*st.yz() + tt.zx()*st.zz())*tt.zz(),
353
354 (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xy()
355 + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yy()
356 + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zy(),
357
358 (tt.xy()*st.xx() + tt.yy()*st.xy() + tt.zy()*st.xz())*tt.xz()
359 + (tt.xy()*st.xy() + tt.yy()*st.yy() + tt.zy()*st.yz())*tt.yz()
360 + (tt.xy()*st.xz() + tt.yy()*st.yz() + tt.zy()*st.zz())*tt.zz(),
361
362 (tt.xz()*st.xx() + tt.yz()*st.xy() + tt.zz()*st.xz())*tt.xz()
363 + (tt.xz()*st.xy() + tt.yz()*st.yy() + tt.zz()*st.yz())*tt.yz()
364 + (tt.xz()*st.xz() + tt.yz()*st.yz() + tt.zz()*st.zz())*tt.zz()
365 );
366}
367
368
369template<class Type1, class Type2>
370inline Type1 transformMask(const Type2& t)
371{
372 return t;
373}
374
375
376template<>
378{
379 return sph(t);
380}
381
382
383template<>
385{
386 return symm(t);
387}
388
389
390//- Estimate angle of vec in coordinate system (e0, e1, e0^e1).
391// Is guaranteed to return increasing number but is not correct
392// angle. Used for sorting angles. All input vectors need to be normalized.
393//
394// Calculates scalar which increases with angle going from e0 to vec in
395// the coordinate system e0, e1, e0^e1
396//
397// Jumps from 2*pi -> 0 at -SMALL so hopefully parallel vectors with small
398// rounding errors should still get the same quadrant.
399//
400inline scalar pseudoAngle
401(
402 const vector& e0,
403 const vector& e1,
404 const vector& vec
405)
406{
407 const scalar cos_angle = vec & e0;
408 const scalar sin_angle = vec & e1;
409
410 if (sin_angle < -SMALL)
411 {
412 return (3.0 + cos_angle)*constant::mathematical::piByTwo;
413 }
414 else
415 {
416 return (1.0 - cos_angle)*constant::mathematical::piByTwo;
417 }
418}
419
420
421// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
422
423} // End namespace Foam
424
425// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
426
427#endif
428
429// ************************************************************************* //
A templated (3 x 3) diagonal tensor of objects of <T>, effectively containing 1 element,...
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements,...
Definition: SymmTensor.H:57
const Cmpt & xx() const
Definition: SymmTensorI.H:97
const Cmpt & yz() const
Definition: SymmTensorI.H:127
const Cmpt & xz() const
Definition: SymmTensorI.H:109
const Cmpt & zz() const
Definition: SymmTensorI.H:145
const Cmpt & xy() const
Definition: SymmTensorI.H:103
const Cmpt & yy() const
Definition: SymmTensorI.H:121
const Cmpt & xx() const
Definition: TensorI.H:153
const Cmpt & yx() const
Definition: TensorI.H:174
const Cmpt & yz() const
Definition: TensorI.H:188
const Cmpt & xz() const
Definition: TensorI.H:167
const Cmpt & zz() const
Definition: TensorI.H:209
const Cmpt & xy() const
Definition: TensorI.H:160
const Cmpt & zx() const
Definition: TensorI.H:195
const Cmpt & zy() const
Definition: TensorI.H:202
const Cmpt & yy() const
Definition: TensorI.H:181
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const volScalarField & T
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))
constexpr scalar piByTwo(0.5 *M_PI)
Namespace for OpenFOAM.
dimensionSet invTransform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:542
scalar pseudoAngle(const vector &e0, const vector &e1, const vector &vec)
Estimate angle of vec in coordinate system (e0, e1, e0^e1).
Definition: transform.H:401
tensor Rx(const scalar omega)
Rotational transformation tensor about the x-axis by omega radians.
Definition: transform.H:85
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
tensor Ra(const vector &a, const scalar omega)
Rotational transformation tensor about axis a by omega radians.
Definition: transform.H:127
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:536
dimensionedSymmTensor sqr(const dimensionedVector &dv)
sphericalTensor transformMask< sphericalTensor >(const symmTensor &st)
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from vector n1 to n2.
Definition: transform.H:51
tensor Ry(const scalar omega)
Rotational transformation tensor about the y-axis by omega radians.
Definition: transform.H:99
dimensionedScalar sin(const dimensionedScalar &ds)
static const Identity< scalar > I
Definition: Identity.H:94
Tensor< scalar > tensor
Definition: symmTensor.H:61
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
Type1 transformMask(const Type2 &t)
Definition: transform.H:370
tensor Rz(const scalar omega)
Rotational transformation tensor about the z-axis by omega radians.
Definition: transform.H:113
SphericalTensor< Cmpt > sph(const DiagTensor< Cmpt > &dt)
Return the spherical part of a DiagTensor as a SphericalTensor.
Definition: DiagTensorI.H:130
symmTensor transformMask< symmTensor >(const symmTensor &st)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dimensionedScalar cos(const dimensionedScalar &ds)