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 -------------------------------------------------------------------------------
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 InNamespace
28  Foam
29 
30 Description
31  3D tensor transformation operations.
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #ifndef Foam_transform_H
36 #define Foam_transform_H
37 
38 #include "tensor.H"
39 #include "mathematicalConstants.H"
40 #include <type_traits>
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 
44 namespace 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
85 inline 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
99 inline 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
113 inline 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
127 inline tensor Ra(const vector& a, const scalar omega)
128 {
129  const scalar s = sin(omega);
130  const scalar c = cos(omega);
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
150 template<class T>
151 constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
152 transform(const tensor&, const T val)
153 {
154  return val;
155 }
156 
157 //- No-op inverse rotational transform for base types
158 template<class T>
159 constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type
160 invTransform(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)
168 template<class Cmpt>
169 inline 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)
177 template<class Cmpt>
178 inline 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())
186 template<class Cmpt>
187 inline 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)
232 template<class Cmpt>
233 inline 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).
277 template<class Cmpt>
278 inline SphericalTensor<Cmpt> transform
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).
289 template<class Cmpt>
290 inline SphericalTensor<Cmpt> invTransform
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())
302 template<class Cmpt>
303 inline SymmTensor<Cmpt> transform(const tensor& tt, const SymmTensor<Cmpt>& st)
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)
336 template<class Cmpt>
337 inline SymmTensor<Cmpt>
338 invTransform(const tensor& tt, const SymmTensor<Cmpt>& st)
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 
369 template<class Type1, class Type2>
370 inline Type1 transformMask(const Type2& t)
371 {
372  return t;
373 }
374 
375 
376 template<>
378 {
379  return sph(t);
380 }
381 
382 
383 template<>
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 //
400 inline 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 // ************************************************************************* //
const Cmpt & xz() const noexcept
Definition: SymmTensor.H:152
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements, derived from VectorSpace.
Definition: SymmTensor.H:50
dimensionSet invTransform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:535
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:434
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Tensor< scalar > tensor
Definition: symmTensor.H:57
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:47
SphericalTensor< Cmpt > sph(const DiagTensor< Cmpt > &dt)
Return the spherical part of a DiagTensor as a SphericalTensor.
Definition: DiagTensorI.H:87
const Cmpt & zz() const noexcept
Definition: SymmTensor.H:158
tensor Rz(const scalar omega)
Rotational transformation tensor about the z-axis by omega radians.
Definition: transform.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:752
dimensionedScalar cos(const dimensionedScalar &ds)
symmTensor transformMask< symmTensor >(const symmTensor &st)
static const Identity< scalar > I
Definition: Identity.H:100
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition: symmTensor.H:55
const Cmpt & xx() const noexcept
Definition: SymmTensor.H:150
Vector< scalar > vector
Definition: vector.H:57
constexpr scalar piByTwo(0.5 *M_PI)
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross-product operators.
Definition: Vector.H:58
dimensionedScalar sin(const dimensionedScalar &ds)
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
tensor Ry(const scalar omega)
Rotational transformation tensor about the y-axis by omega radians.
Definition: transform.H:99
Type1 transformMask(const Type2 &t)
Definition: transform.H:400
const Cmpt & yy() const noexcept
Definition: SymmTensor.H:154
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
const dimensionedScalar c
Speed of light in a vacuum.
tensor Ra(const vector &a, const scalar omega)
Rotational transformation tensor about axis a by omega radians.
Definition: transform.H:131
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
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))
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:529
Tensor of scalars, i.e. Tensor<scalar>.
tensor Rx(const scalar omega)
Rotational transformation tensor about the x-axis by omega radians.
Definition: transform.H:83
const Cmpt & xy() const noexcept
Definition: SymmTensor.H:151
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Namespace for OpenFOAM.
const Cmpt & yz() const noexcept
Definition: SymmTensor.H:155