symmTensor.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) 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 \*---------------------------------------------------------------------------*/
28 
29 #include "symmTensor.H"
30 #include "cubicEqn.H"
31 #include "mathematicalConstants.H"
32 
33 using namespace Foam::constant::mathematical;
34 
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 template<>
39 const char* const Foam::symmTensor::vsType::typeName = "symmTensor";
40 
41 template<>
42 const char* const Foam::symmTensor::vsType::componentNames[] =
43 {
44  "xx", "xy", "xz",
45  "yy", "yz",
46  "zz"
47 };
48 
49 template<>
51 (
53 );
54 
55 template<>
57 (
59 );
60 
61 template<>
63 (
64  symmTensor::uniform(VGREAT)
65 );
66 
67 template<>
69 (
70  symmTensor::uniform(-VGREAT)
71 );
72 
73 template<>
75 (
76  symmTensor::uniform(ROOTVGREAT)
77 );
78 
79 template<>
81 (
82  symmTensor::uniform(-ROOTVGREAT)
83 );
84 
85 template<>
87 (
88  1, 0, 0,
89  1, 0,
90  1
91 );
92 
93 
94 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
95 
97 {
98  // Return ascending diagonal if T is effectively diagonal tensor
99  if ((sqr(T.xy()) + sqr(T.xz()) + sqr(T.yz())) < ROOTSMALL)
100  {
101  vector eVals(T.diag());
102 
103  std::sort(eVals.begin(), eVals.end());
104 
105  return eVals;
106  }
107 
108  // Coefficients of the characteristic cubic polynomial (a = 1)
109  const scalar b = - T.xx() - T.yy() - T.zz();
110  const scalar c =
111  T.xx()*T.yy() + T.xx()*T.zz() + T.yy()*T.zz()
112  - T.xy()*T.yx() - T.yz()*T.zy() - T.zx()*T.xz();
113  const scalar d =
114  - T.xx()*T.yy()*T.zz()
115  - T.xy()*T.yz()*T.zx() - T.xz()*T.zy()*T.yx()
116  + T.xx()*T.yz()*T.zy() + T.yy()*T.zx()*T.xz() + T.zz()*T.xy()*T.yx();
117 
118  // Determine the roots of the characteristic cubic polynomial
119  Roots<3> roots(cubicEqn(1, b, c, d).roots());
120 
121  vector eVals(Zero);
122 
123  // Check the root types
124  forAll(roots, i)
125  {
126  switch (roots.type(i))
127  {
128  case roots::real:
129  eVals[i] = roots[i];
130  break;
131  case roots::complex:
132  case roots::posInf:
133  case roots::negInf:
134  case roots::nan:
136  << "Eigenvalue computation fails for symmTensor: " << T
137  << "due to the non-real root = " << roots[i]
138  << endl;
139  eVals[i] = roots[i];
140  break;
141  }
142  }
143 
144  // Sort the eigenvalues into ascending order
145  std::sort(eVals.begin(), eVals.end());
146 
147  return eVals;
148 }
149 
150 
152 (
153  const symmTensor& T,
154  const scalar eVal,
155  const vector& standardBasis1,
156  const vector& standardBasis2
157 )
158 {
159  // Construct the characteristic equation system for this eigenvalue
160  const tensor A(T - eVal*I);
161 
162  {
163  // Determinants of the 2x2 sub-matrices used to find the eigenvectors
164  // Sub-determinants for a unique eigenvenvalue
165  const scalar sd0 = A.yy()*A.zz() - A.yz()*A.zy();
166  const scalar sd1 = A.zz()*A.xx() - A.zx()*A.xz();
167  const scalar sd2 = A.xx()*A.yy() - A.xy()*A.yx();
168  const scalar magSd0 = mag(sd0);
169  const scalar magSd1 = mag(sd1);
170  const scalar magSd2 = mag(sd2);
171 
172  // Evaluate the eigenvector using the largest sub-determinant
173  if (magSd0 >= magSd1 && magSd0 >= magSd2 && magSd0 > SMALL)
174  {
175  const vector eVec
176  (
177  1,
178  (A.yz()*A.zx() - A.zz()*A.yx())/sd0,
179  (A.zy()*A.yx() - A.yy()*A.zx())/sd0
180  );
181 
182  #ifdef FULLDEBUG
183  if (mag(eVec) < SMALL)
184  {
186  << "Eigenvector magnitude should be non-zero:"
187  << "mag(eigenvector) = " << mag(eVec)
188  << abort(FatalError);
189  }
190  #endif
191 
192  return eVec/mag(eVec);
193  }
194  else if (magSd1 >= magSd2 && magSd1 > SMALL)
195  {
196  const vector eVec
197  (
198  (A.xz()*A.zy() - A.zz()*A.xy())/sd1,
199  1,
200  (A.zx()*A.xy() - A.xx()*A.zy())/sd1
201  );
202 
203  #ifdef FULLDEBUG
204  if (mag(eVec) < SMALL)
205  {
207  << "Eigenvector magnitude should be non-zero:"
208  << "mag(eigenvector) = " << mag(eVec)
209  << abort(FatalError);
210  }
211  #endif
212 
213  return eVec/mag(eVec);
214  }
215  else if (magSd2 > SMALL)
216  {
217  const vector eVec
218  (
219  (A.xy()*A.yz() - A.yy()*A.xz())/sd2,
220  (A.yx()*A.xz() - A.xx()*A.yz())/sd2,
221  1
222  );
223 
224  #ifdef FULLDEBUG
225  if (mag(eVec) < SMALL)
226  {
228  << "Eigenvector magnitude should be non-zero:"
229  << "mag(eigenvector) = " << mag(eVec)
230  << abort(FatalError);
231  }
232  #endif
233 
234  return eVec/mag(eVec);
235  }
236  }
237 
238  // Sub-determinants for a repeated eigenvalue
239  const scalar sd0 = A.yy()*standardBasis1.z() - A.yz()*standardBasis1.y();
240  const scalar sd1 = A.zz()*standardBasis1.x() - A.zx()*standardBasis1.z();
241  const scalar sd2 = A.xx()*standardBasis1.y() - A.xy()*standardBasis1.x();
242  const scalar magSd0 = mag(sd0);
243  const scalar magSd1 = mag(sd1);
244  const scalar magSd2 = mag(sd2);
245 
246  // Evaluate the eigenvector using the largest sub-determinant
247  if (magSd0 >= magSd1 && magSd0 >= magSd2 && magSd0 > SMALL)
248  {
249  const vector eVec
250  (
251  1,
252  (A.yz()*standardBasis1.x() - standardBasis1.z()*A.yx())/sd0,
253  (standardBasis1.y()*A.yx() - A.yy()*standardBasis1.x())/sd0
254  );
255 
256  #ifdef FULLDEBUG
257  if (mag(eVec) < SMALL)
258  {
260  << "Eigenvector magnitude should be non-zero:"
261  << "mag(eigenvector) = " << mag(eVec)
262  << abort(FatalError);
263  }
264  #endif
265 
266  return eVec/mag(eVec);
267  }
268  else if (magSd1 >= magSd2 && magSd1 > SMALL)
269  {
270  const vector eVec
271  (
272  (standardBasis1.z()*A.zy() - A.zz()*standardBasis1.y())/sd1,
273  1,
274  (A.zx()*standardBasis1.y() - standardBasis1.x()*A.zy())/sd1
275  );
276 
277  #ifdef FULLDEBUG
278  if (mag(eVec) < SMALL)
279  {
281  << "Eigenvector magnitude should be non-zero:"
282  << "mag(eigenvector) = " << mag(eVec)
283  << abort(FatalError);
284  }
285  #endif
286 
287  return eVec/mag(eVec);
288  }
289  else if (magSd2 > SMALL)
290  {
291  const vector eVec
292  (
293  (A.xy()*standardBasis1.z() - standardBasis1.y()*A.xz())/sd2,
294  (standardBasis1.x()*A.xz() - A.xx()*standardBasis1.z())/sd2,
295  1
296  );
297 
298  #ifdef FULLDEBUG
299  if (mag(eVec) < SMALL)
300  {
302  << "Eigenvector magnitude should be non-zero:"
303  << "mag(eigenvector) = " << mag(eVec)
304  << abort(FatalError);
305  }
306  #endif
307 
308  return eVec/mag(eVec);
309  }
310 
311  // Triple eigenvalue
312  return standardBasis1^standardBasis2;
313 }
314 
315 
317 (
318  const symmTensor& T,
319  const vector& eVals
320 )
321 {
322  vector Ux(1, 0, 0), Uy(0, 1, 0), Uz(0, 0, 1);
323 
324  Ux = eigenVector(T, eVals.x(), Uy, Uz);
325  Uy = eigenVector(T, eVals.y(), Uz, Ux);
326  Uz = eigenVector(T, eVals.z(), Ux, Uy);
327 
328  return tensor(Ux, Uy, Uz);
329 }
330 
331 
333 {
334  const vector eVals(eigenValues(T));
335 
336  return eigenVectors(T, eVals);
337 }
338 
339 
340 // ************************************************************************* //
Foam::VectorSpace::rootMax
static const Form rootMax
Definition: VectorSpace.H:119
Foam::Roots::type
void type(const direction i, const roots::type t)
Set the type of the i-th root.
Definition: RootsI.H:122
Foam::Tensor< scalar >
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
mathematicalConstants.H
Foam::SymmTensor
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements,...
Definition: SymmTensor.H:58
Foam::roots::complex
Definition: Roots.H:57
cubicEqn.H
Foam::roots::posInf
Definition: Roots.H:58
Foam::VectorSpace::one
static const Form one
Definition: VectorSpace.H:116
Foam::roots::nan
Definition: Roots.H:60
Foam::VectorSpace< SymmTensor< scalar >, scalar, 6 >::uniform
static SymmTensor< scalar > uniform(const scalar &s)
Return a VectorSpace with all elements = s.
Definition: VectorSpaceI.H:164
Foam::VectorSpace::componentNames
static const char *const componentNames[]
Definition: VectorSpace.H:114
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::eigenVector
vector eigenVector(const symmTensor &T, const scalar eVal, const vector &standardBasis1, const vector &standardBasis2)
Definition: symmTensor.C:152
Foam::eigenValues
dimensionedVector eigenValues(const dimensionedSymmTensor &dt)
Definition: dimensionedTensor.C:149
Foam::VectorSpace::end
iterator end() noexcept
Return an iterator to end of VectorSpace.
Definition: VectorSpaceI.H:206
Foam::eigenVectors
dimensionedTensor eigenVectors(const dimensionedSymmTensor &dt)
Definition: dimensionedTensor.C:160
A
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
Foam::VectorSpace::begin
iterator begin() noexcept
Return an iterator to begin of VectorSpace.
Definition: VectorSpaceI.H:199
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::VectorSpace::min
static const Form min
Definition: VectorSpace.H:118
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
symmTensor.H
Foam::SymmTensor< scalar >::I
static const SymmTensor I
Definition: SymmTensor.H:78
Foam::roots::negInf
Definition: Roots.H:59
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:58
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:261
Foam::roots::real
Definition: Roots.H:56
Foam::FatalError
error FatalError
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::VectorSpace::rootMin
static const Form rootMin
Definition: VectorSpace.H:120
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::constant::mathematical
Mathematical constants.
Foam::VectorSpace::max
static const Form max
Definition: VectorSpace.H:117
Foam::Vector< scalar >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::VectorSpace::zero
static const Form zero
Definition: VectorSpace.H:115
Foam::cubicEqn
Container to encapsulate various operations for cubic equation of the forms with real coefficients:
Definition: cubicEqn.H:112
Foam::Roots
Templated storage for the roots of polynomial equations, plus flags to indicate the nature of the roo...
Definition: Roots.H:70
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::tensor
Tensor< scalar > tensor
Tensor of scalars, i.e. Tensor<scalar>.
Definition: symmTensor.H:61
Foam::I
static const Identity< scalar > I
Definition: Identity.H:95
Foam::VectorSpace::typeName
static const char *const typeName
Definition: VectorSpace.H:113