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-------------------------------------------------------------------------------
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 "symmTensor.H"
30#include "cubicEqn.H"
32
33using namespace Foam::constant::mathematical;
34
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38template<>
39const char* const Foam::symmTensor::vsType::typeName = "symmTensor";
40
41template<>
43{
44 "xx", "xy", "xz",
45 "yy", "yz",
46 "zz"
47};
48
49template<>
51(
53);
54
55template<>
57(
59);
60
61template<>
63(
65);
66
67template<>
69(
70 symmTensor::uniform(-VGREAT)
71);
72
73template<>
75(
76 symmTensor::uniform(ROOTVGREAT)
77);
78
79template<>
81(
82 symmTensor::uniform(-ROOTVGREAT)
83);
84
85template<>
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// ************************************************************************* //
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
Templated storage for the roots of polynomial equations, plus flags to indicate the nature of the roo...
Definition: Roots.H:73
void type(const direction i, const roots::type t)
Set the type of the i-th root.
Definition: RootsI.H:122
static const SymmTensor I
Definition: SymmTensor.H:74
iterator end() noexcept
Return an iterator to end of VectorSpace.
Definition: VectorSpaceI.H:206
iterator begin() noexcept
Return an iterator to begin of VectorSpace.
Definition: VectorSpaceI.H:199
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
Container to encapsulate various operations for cubic equation of the forms with real coefficients:
Definition: cubicEqn.H:115
Particle-size distribution model wherein random samples are drawn from the doubly-truncated uniform p...
Definition: uniform.H:164
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:62
static const char *const componentNames[]
Definition: bool.H:104
static const complex rootMax
complex (ROOTVGREAT, ROOTVGREAT)
Definition: complex.H:295
static const complex min
complex (-VGREAT,-VGREAT)
Definition: complex.H:292
static const complex max
complex (VGREAT,VGREAT)
Definition: complex.H:293
static const complex rootMin
complex (-ROOTVGREAT, -ROOTVGREAT)
Definition: complex.H:294
const volScalarField & T
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
Mathematical constants.
dimensionedTensor eigenVectors(const dimensionedSymmTensor &dt)
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedVector eigenValues(const dimensionedSymmTensor &dt)
vector eigenVector(const symmTensor &T, const scalar eVal, const vector &standardBasis1, const vector &standardBasis2)
Definition: symmTensor.C:152
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
error FatalError
volScalarField & b
Definition: createFields.H:27
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
static const char *const typeName
The type name used in ensight case files.
A non-counting (dummy) refCount.
Definition: refCount.H:59