triad.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2012-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triad.H"
27 #include "transform.H"
28 #include "quaternion.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 template<>
33 const char* const Foam::triad::vsType::typeName = "triad";
34 
35 template<>
36 const char* const Foam::triad::vsType::componentNames[] = {"x", "y", "z"};
37 
38 template<>
40 (
41  triad::uniform(vector::uniform(0))
42 );
43 
44 template<>
46 (
47  triad::uniform(vector::uniform(1))
48 );
49 
50 template<>
52 (
53  triad::uniform(vector::uniform(vGreat))
54 );
55 
56 template<>
58 (
59  triad::uniform(vector::uniform(-vGreat))
60 );
61 
62 template<>
64 (
65  triad::uniform(vector::uniform(rootVGreat))
66 );
67 
68 template<>
70 (
71  triad::uniform(vector::uniform(-rootVGreat))
72 );
73 
74 template<>
76 (
77  triad::uniform(vector::uniform(NaN))
78 );
79 
81 (
82  vector(1, 0, 0),
83  vector(0, 1, 0),
84  vector(0, 0, 1)
85 );
86 
88 (
89  triad::uniform(vector::uniform(vGreat))
90 );
91 
92 
93 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
94 
96 {
97  tensor Rt(q.R().T());
98  x() = Rt.x();
99  y() = Rt.y();
100  z() = Rt.z();
101 }
102 
103 
105 {
106  x() = t.x();
107  y() = t.y();
108  z() = t.z();
109 }
110 
111 
112 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
113 
115 {
116  // Hack for 2D z-slab cases
117  // if (!set(2))
118  // {
119  // operator[](2) = vector(0, 0, 1);
120  // }
121 
122  // If only two of the axes are set, set the third
123  if (set(0) && set(1) && !set(2))
124  {
125  operator[](2) = orthogonal(operator[](0), operator[](1));
126  }
127  else if (set(0) && set(2) && !set(1))
128  {
129  operator[](1) = orthogonal(operator[](0), operator[](2));
130  }
131  else if (set(1) && set(2) && !set(0))
132  {
133  operator[](0) = orthogonal(operator[](1), operator[](2));
134  }
135 
136  // If all the axes are set
137  if (set())
138  {
139  for (direction i=0; i<2; i++)
140  {
141  const scalar o01
142  (
143  (set(0) && set(1)) ? mag(operator[](0) & operator[](1)) : vGreat
144  );
145  const scalar o02
146  (
147  (set(0) && set(2)) ? mag(operator[](0) & operator[](2)) : vGreat
148  );
149  const scalar o12
150  (
151  (set(1) && set(2)) ? mag(operator[](1) & operator[](2)) : vGreat
152  );
153 
154  if (o01 < o02 && o01 < o12)
155  {
156  operator[](2) = orthogonal(operator[](0), operator[](1));
157 
158  // if (o02 < o12)
159  // {
160  // operator[](1) = orthogonal(operator[](0), operator[](2));
161  // }
162  // else
163  // {
164  // operator[](0) = orthogonal(operator[](1), operator[](2));
165  // }
166  }
167  else if (o02 < o12)
168  {
169  operator[](1) = orthogonal(operator[](0), operator[](2));
170 
171  // if (o01 < o12)
172  // {
173  // operator[](2) = orthogonal(operator[](0), operator[](1));
174  // }
175  // else
176  // {
177  // operator[](0) = orthogonal(operator[](1), operator[](2));
178  // }
179  }
180  else
181  {
182  operator[](0) = orthogonal(operator[](1), operator[](2));
183 
184  // if (o02 < o01)
185  // {
186  // operator[](1) = orthogonal(operator[](0), operator[](2));
187  // }
188  // else
189  // {
190  // operator[](2) = orthogonal(operator[](0), operator[](1));
191  // }
192  }
193  }
194  }
195 }
196 
197 
199 {
200  bool preset[3];
201 
202  for (direction i=0; i<3; i++)
203  {
204  if (t2.set(i) && !set(i))
205  {
206  operator[](i) = t2.operator[](i);
207  preset[i] = true;
208  }
209  else
210  {
211  preset[i] = false;
212  }
213  }
214 
215  if (set() && t2.set())
216  {
217  direction correspondence[3]{0, 0, 0};
218  label signd[3];
219 
220  for (direction i=0; i<3; i++)
221  {
222  if (preset[i])
223  {
224  signd[i] = 0;
225  continue;
226  }
227 
228  scalar mostAligned = -1;
229  for (direction j=0; j<3; j++)
230  {
231  bool set = false;
232  for (direction k=0; k<i; k++)
233  {
234  if (correspondence[k] == j)
235  {
236  set = true;
237  break;
238  }
239  }
240 
241  if (!set)
242  {
243  scalar a = operator[](i) & t2.operator[](j);
244  scalar maga = mag(a);
245 
246  if (maga > mostAligned)
247  {
248  correspondence[i] = j;
249  mostAligned = maga;
250  signd[i] = sign(a);
251  }
252  }
253  }
254 
255  operator[](i) += signd[i]*t2.operator[](correspondence[i]);
256  }
257  }
258 }
259 
260 
262 {
263  if (set())
264  {
265  vector mostAligned
266  (
267  mag(v & operator[](0)),
268  mag(v & operator[](1)),
269  mag(v & operator[](2))
270  );
271 
272  scalar mav;
273 
274  if
275  (
276  mostAligned.x() > mostAligned.y()
277  && mostAligned.x() > mostAligned.z()
278  )
279  {
280  mav = mostAligned.x();
281  mostAligned = operator[](0);
282  }
283  else if (mostAligned.y() > mostAligned.z())
284  {
285  mav = mostAligned.y();
286  mostAligned = operator[](1);
287  }
288  else
289  {
290  mav = mostAligned.z();
291  mostAligned = operator[](2);
292  }
293 
294  if (mav < 0.99)
295  {
296  tensor R(rotationTensor(mostAligned, v));
297 
298  operator[](0) = transform(R, operator[](0));
299  operator[](1) = transform(R, operator[](1));
300  operator[](2) = transform(R, operator[](2));
301  }
302  }
303 }
304 
305 
307 {
308  if (!this->set())
309  {
310  return *this;
311  }
312 
313  triad t;
314 
315  if
316  (
317  mag(operator[](0).x()) > mag(operator[](1).x())
318  && mag(operator[](0).x()) > mag(operator[](2).x())
319  )
320  {
321  t[0] = operator[](0);
322 
323  if (mag(operator[](1).y()) > mag(operator[](2).y()))
324  {
325  t[1] = operator[](1);
326  t[2] = operator[](2);
327  }
328  else
329  {
330  t[1] = operator[](2);
331  t[2] = operator[](1);
332  }
333  }
334  else if
335  (
336  mag(operator[](1).x()) > mag(operator[](2).x())
337  )
338  {
339  t[0] = operator[](1);
340 
341  if (mag(operator[](0).y()) > mag(operator[](2).y()))
342  {
343  t[1] = operator[](0);
344  t[2] = operator[](2);
345  }
346  else
347  {
348  t[1] = operator[](2);
349  t[2] = operator[](0);
350  }
351  }
352  else
353  {
354  t[0] = operator[](2);
355 
356  if (mag(operator[](0).y()) > mag(operator[](1).y()))
357  {
358  t[1] = operator[](0);
359  t[2] = operator[](1);
360  }
361  else
362  {
363  t[1] = operator[](1);
364  t[2] = operator[](0);
365  }
366  }
367 
368  if (t[0].x() < 0) t[0] *= -1;
369  if (t[1].y() < 0) t[1] *= -1;
370  if (t[2].z() < 0) t[2] *= -1;
371 
372  return t;
373 }
374 
375 
376 
378 {
379  tensor R;
380 
381  R.xx() = x().x();
382  R.xy() = y().x();
383  R.xz() = z().x();
384 
385  R.yx() = x().y();
386  R.yy() = y().y();
387  R.yz() = z().y();
388 
389  R.zx() = x().z();
390  R.zy() = y().z();
391  R.zz() = z().z();
392 
393  return quaternion(R);
394 }
395 
396 
397 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
398 
400 {
401  x() = t.x();
402  y() = t.y();
403  z() = t.z();
404 }
405 
406 
407 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
408 
409 Foam::scalar Foam::diff(const triad& A, const triad& B)
410 {
411  triad tmpA = A.sortxyz();
412  triad tmpB = B.sortxyz();
413 
414  scalar sumDifference = 0;
415 
416  for (direction dir = 0; dir < 3; dir++)
417  {
418  if (!tmpA.set(dir) || !tmpB.set(dir))
419  {
420  continue;
421  }
422 
423  scalar cosPhi =
424  (tmpA[dir] & tmpB[dir])
425  /(mag(tmpA[dir])*mag(tmpA[dir]) + small);
426 
427  cosPhi = min(max(cosPhi, -1), 1);
428 
429  sumDifference += mag(cosPhi - 1);
430  }
431 
432  return (sumDifference/3);
433 }
434 
435 
436 // ************************************************************************* //
static const Foam::dimensionedScalar A("A", Foam::dimPressure, 611.21)
static const Foam::dimensionedScalar B("B", Foam::dimless, 18.678)
scalar y
label k
Tensor< Cmpt > T() const
Return transpose.
Definition: TensorI.H:331
Vector< Cmpt > z() const
Definition: TensorI.H:303
Vector< Cmpt > y() const
Definition: TensorI.H:296
Vector< Cmpt > x() const
Definition: TensorI.H:289
static const Form zero
Definition: VectorSpace.H:118
static const char *const componentNames[]
Definition: VectorSpace.H:117
friend Ostream & operator(Ostream &, const VectorSpace< Form, Cmpt, Ncmpts > &)
static const Form one
Definition: VectorSpace.H:119
static const Form nan
Definition: VectorSpace.H:124
static const Form rootMax
Definition: VectorSpace.H:122
static const Form max
Definition: VectorSpace.H:120
static const Form rootMin
Definition: VectorSpace.H:123
static const Form min
Definition: VectorSpace.H:121
static const char *const typeName
Definition: VectorSpace.H:116
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:60
const vector & z() const
Definition: VectorI.H:87
const vector & y() const
Definition: VectorI.H:81
const vector & x() const
Definition: VectorI.H:75
Quaternion class used to perform rotations in 3D space.
Definition: quaternion.H:61
tensor R() const
The rotation tensor corresponding the quaternion.
Definition: quaternionI.H:323
Representation of a 3D Cartesian coordinate system as a Vector of vectors.
Definition: triad.H:68
void align(const vector &v)
Align this triad with the given vector v.
Definition: triad.C:261
static const triad unset
Definition: triad.H:99
triad()
Construct null.
Definition: triadI.H:28
bool set(const direction d) const
Is the vector in the direction d set.
Definition: triadI.H:61
triad sortxyz() const
Sort the axes such that they are closest to the x, y and z axes.
Definition: triad.C:306
static const triad I
Definition: triad.H:98
void operator+=(const triad &t2)
Add the triad t2 to this triad.
Definition: triad.C:198
void operator=(const Vector< vector > &)
Definition: triadI.H:121
void orthogonalise()
Orthogonalise this triad so that it is ortho-normal.
Definition: triad.C:114
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from unit vector n1 to n2.
Definition: transform.H:47
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:409
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:504
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
static scalar R(const scalar a, const scalar x)
Definition: invIncGamma.C:102
uint8_t direction
Definition: direction.H:45
3D tensor transformation operations.