mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Migrated eigen vector/value updates from old development line and updated dependencies
This commit is contained in:
@ -70,24 +70,30 @@ const Foam::tensor Foam::tensor::I
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::vector Foam::eigenValues(const tensor& t)
|
Foam::vector Foam::eigenValues(const tensor& T)
|
||||||
{
|
{
|
||||||
// The eigenvalues
|
// The eigenvalues
|
||||||
scalar i, ii, iii;
|
scalar i, ii, iii;
|
||||||
|
|
||||||
// diagonal matrix
|
// diagonal matrix
|
||||||
if
|
const scalar onDiagMagSum =
|
||||||
(
|
|
||||||
(
|
(
|
||||||
mag(t.xy()) + mag(t.xz()) + mag(t.yx())
|
mag(T.xx()) + mag(T.yy()) + mag(T.zz())
|
||||||
+ mag(t.yz()) + mag(t.zx()) + mag(t.zy())
|
);
|
||||||
)
|
|
||||||
< SMALL
|
const scalar offDiagMagSum =
|
||||||
)
|
(
|
||||||
|
mag(T.xy()) + mag(T.xz()) + mag(T.yx())
|
||||||
|
+ mag(T.yz()) + mag(T.zx()) + mag(T.zy())
|
||||||
|
);
|
||||||
|
|
||||||
|
const scalar magSum = onDiagMagSum + offDiagMagSum;
|
||||||
|
|
||||||
|
if (offDiagMagSum < max(VSMALL, SMALL*magSum))
|
||||||
{
|
{
|
||||||
i = t.xx();
|
i = T.xx();
|
||||||
ii = t.yy();
|
ii = T.yy();
|
||||||
iii = t.zz();
|
iii = T.zz();
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-diagonal matrix
|
// non-diagonal matrix
|
||||||
@ -96,16 +102,16 @@ Foam::vector Foam::eigenValues(const tensor& t)
|
|||||||
// Coefficients of the characteristic polynmial
|
// Coefficients of the characteristic polynmial
|
||||||
// x^3 + a*x^2 + b*x + c = 0
|
// x^3 + a*x^2 + b*x + c = 0
|
||||||
scalar a =
|
scalar a =
|
||||||
- t.xx() - t.yy() - t.zz();
|
- T.xx() - T.yy() - T.zz();
|
||||||
|
|
||||||
scalar b =
|
scalar b =
|
||||||
t.xx()*t.yy() + t.xx()*t.zz() + t.yy()*t.zz()
|
T.xx()*T.yy() + T.xx()*T.zz() + T.yy()*T.zz()
|
||||||
- t.xy()*t.yx() - t.yz()*t.zy() - t.zx()*t.xz();
|
- T.xy()*T.yx() - T.yz()*T.zy() - T.zx()*T.xz();
|
||||||
|
|
||||||
scalar c =
|
scalar c =
|
||||||
- t.xx()*t.yy()*t.zz()
|
- T.xx()*T.yy()*T.zz()
|
||||||
- t.xy()*t.yz()*t.zx() - t.xz()*t.zy()*t.yx()
|
- T.xy()*T.yz()*T.zx() - T.xz()*T.zy()*T.yx()
|
||||||
+ t.xx()*t.yz()*t.zy() + t.yy()*t.zx()*t.xz() + t.zz()*t.xy()*t.yx();
|
+ T.xx()*T.yz()*T.zy() + T.yy()*T.zx()*T.xz() + T.zz()*T.xy()*T.yx();
|
||||||
|
|
||||||
// Auxillary variables
|
// Auxillary variables
|
||||||
scalar aBy3 = a/3;
|
scalar aBy3 = a/3;
|
||||||
@ -117,13 +123,13 @@ Foam::vector Foam::eigenValues(const tensor& t)
|
|||||||
scalar QQ = Q*Q;
|
scalar QQ = Q*Q;
|
||||||
|
|
||||||
// Three identical roots
|
// Three identical roots
|
||||||
if (mag(P) < SMALL && mag(Q) < SMALL)
|
if (mag(P) < SMALL*sqr(magSum) && mag(Q) < SMALL*pow3(magSum))
|
||||||
{
|
{
|
||||||
return vector(- aBy3, - aBy3, - aBy3);
|
return vector(- aBy3, - aBy3, - aBy3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two identical roots and one distinct root
|
// Two identical roots and one distinct root
|
||||||
else if (mag(PPP/QQ - 1) < SMALL)
|
else if (mag(PPP - QQ) < SMALL*pow6(magSum))
|
||||||
{
|
{
|
||||||
scalar sqrtP = sqrt(P);
|
scalar sqrtP = sqrt(P);
|
||||||
scalar signQ = sign(Q);
|
scalar signQ = sign(Q);
|
||||||
@ -148,11 +154,11 @@ Foam::vector Foam::eigenValues(const tensor& t)
|
|||||||
// based on the above logic, PPP must be less than QQ
|
// based on the above logic, PPP must be less than QQ
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningIn("eigenValues(const tensor&)")
|
||||||
<< "complex eigenvalues detected for tensor: " << t
|
<< "complex eigenvalues detected for tensor: " << T
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
if (mag(P) < SMALL)
|
if (mag(P) < SMALL*sqr(magSum))
|
||||||
{
|
{
|
||||||
i = cbrt(QQ/2);
|
i = cbrt(QQ/2);
|
||||||
}
|
}
|
||||||
@ -188,21 +194,14 @@ Foam::vector Foam::eigenValues(const tensor& t)
|
|||||||
|
|
||||||
Foam::vector Foam::eigenVector
|
Foam::vector Foam::eigenVector
|
||||||
(
|
(
|
||||||
const tensor& t,
|
const tensor& T,
|
||||||
const scalar lambda
|
const scalar lambda,
|
||||||
|
const vector& direction1,
|
||||||
|
const vector& direction2
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Constantly rotating direction ensures different eigenvectors are
|
|
||||||
// generated when called sequentially with a multiple eigenvalue
|
|
||||||
static vector direction(1,0,0);
|
|
||||||
vector oldDirection(direction);
|
|
||||||
scalar temp = direction[2];
|
|
||||||
direction[2] = direction[1];
|
|
||||||
direction[1] = direction[0];
|
|
||||||
direction[0] = temp;
|
|
||||||
|
|
||||||
// Construct the linear system for this eigenvalue
|
// Construct the linear system for this eigenvalue
|
||||||
tensor A(t - lambda*I);
|
tensor A(T - lambda*I);
|
||||||
|
|
||||||
// Determinants of the 2x2 sub-matrices used to find the eigenvectors
|
// Determinants of the 2x2 sub-matrices used to find the eigenvectors
|
||||||
scalar sd0, sd1, sd2;
|
scalar sd0, sd1, sd2;
|
||||||
@ -252,9 +251,9 @@ Foam::vector Foam::eigenVector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sub-determinants for a repeated eigenvalue
|
// Sub-determinants for a repeated eigenvalue
|
||||||
sd0 = A.yy()*direction.z() - A.yz()*direction.y();
|
sd0 = A.yy()*direction1.z() - A.yz()*direction1.y();
|
||||||
sd1 = A.zz()*direction.x() - A.zx()*direction.z();
|
sd1 = A.zz()*direction1.x() - A.zx()*direction1.z();
|
||||||
sd2 = A.xx()*direction.y() - A.xy()*direction.x();
|
sd2 = A.xx()*direction1.y() - A.xy()*direction1.x();
|
||||||
magSd0 = mag(sd0);
|
magSd0 = mag(sd0);
|
||||||
magSd1 = mag(sd1);
|
magSd1 = mag(sd1);
|
||||||
magSd2 = mag(sd2);
|
magSd2 = mag(sd2);
|
||||||
@ -265,8 +264,8 @@ Foam::vector Foam::eigenVector
|
|||||||
vector ev
|
vector ev
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
(A.yz()*direction.x() - direction.z()*A.yx())/sd0,
|
(A.yz()*direction1.x() - direction1.z()*A.yx())/sd0,
|
||||||
(direction.y()*A.yx() - A.yy()*direction.x())/sd0
|
(direction1.y()*A.yx() - A.yy()*direction1.x())/sd0
|
||||||
);
|
);
|
||||||
|
|
||||||
return ev/mag(ev);
|
return ev/mag(ev);
|
||||||
@ -275,9 +274,9 @@ Foam::vector Foam::eigenVector
|
|||||||
{
|
{
|
||||||
vector ev
|
vector ev
|
||||||
(
|
(
|
||||||
(direction.z()*A.zy() - A.zz()*direction.y())/sd1,
|
(direction1.z()*A.zy() - A.zz()*direction1.y())/sd1,
|
||||||
1,
|
1,
|
||||||
(A.zx()*direction.y() - direction.x()*A.zy())/sd1
|
(A.zx()*direction1.y() - direction1.x()*A.zy())/sd1
|
||||||
);
|
);
|
||||||
|
|
||||||
return ev/mag(ev);
|
return ev/mag(ev);
|
||||||
@ -286,8 +285,8 @@ Foam::vector Foam::eigenVector
|
|||||||
{
|
{
|
||||||
vector ev
|
vector ev
|
||||||
(
|
(
|
||||||
(A.xy()*direction.z() - direction.y()*A.xz())/sd2,
|
(A.xy()*direction1.z() - direction1.y()*A.xz())/sd2,
|
||||||
(direction.x()*A.xz() - A.xx()*direction.z())/sd2,
|
(direction1.x()*A.xz() - A.xx()*direction1.z())/sd2,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -295,40 +294,57 @@ Foam::vector Foam::eigenVector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Triple eigenvalue
|
// Triple eigenvalue
|
||||||
return oldDirection;
|
return direction1^direction2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::tensor Foam::eigenVectors(const tensor& t)
|
Foam::tensor Foam::eigenVectors(const tensor& T, const vector& lambdas)
|
||||||
{
|
{
|
||||||
vector evals(eigenValues(t));
|
vector Ux(1, 0, 0), Uy(0, 1, 0), Uz(0, 0, 1);
|
||||||
|
|
||||||
tensor evs
|
Ux = eigenVector(T, lambdas.x(), Uy, Uz);
|
||||||
(
|
Uy = eigenVector(T, lambdas.y(), Uz, Ux);
|
||||||
eigenVector(t, evals.x()),
|
Uz = eigenVector(T, lambdas.z(), Ux, Uy);
|
||||||
eigenVector(t, evals.y()),
|
|
||||||
eigenVector(t, evals.z())
|
|
||||||
);
|
|
||||||
|
|
||||||
return evs;
|
return tensor(Ux, Uy, Uz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::vector Foam::eigenValues(const symmTensor& t)
|
Foam::tensor Foam::eigenVectors(const tensor& T)
|
||||||
{
|
{
|
||||||
return eigenValues(tensor(t));
|
const vector lambdas(eigenValues(T));
|
||||||
|
|
||||||
|
return eigenVectors(T, lambdas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::vector Foam::eigenVector(const symmTensor& t, const scalar lambda)
|
Foam::vector Foam::eigenValues(const symmTensor& T)
|
||||||
{
|
{
|
||||||
return eigenVector(tensor(t), lambda);
|
return eigenValues(tensor(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::tensor Foam::eigenVectors(const symmTensor& t)
|
Foam::vector Foam::eigenVector
|
||||||
|
(
|
||||||
|
const symmTensor& T,
|
||||||
|
const scalar lambda,
|
||||||
|
const vector& direction1,
|
||||||
|
const vector& direction2
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return eigenVectors(tensor(t));
|
return eigenVector(tensor(T), lambda, direction1, direction2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tensor Foam::eigenVectors(const symmTensor& T, const vector& lambdas)
|
||||||
|
{
|
||||||
|
return eigenVectors(tensor(T), lambdas);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tensor Foam::eigenVectors(const symmTensor& T)
|
||||||
|
{
|
||||||
|
return eigenVectors(tensor(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -50,13 +50,27 @@ namespace Foam
|
|||||||
|
|
||||||
typedef Tensor<scalar> tensor;
|
typedef Tensor<scalar> tensor;
|
||||||
|
|
||||||
vector eigenValues(const tensor&);
|
vector eigenValues(const tensor& T);
|
||||||
vector eigenVector(const tensor&, const scalar lambda);
|
vector eigenVector
|
||||||
tensor eigenVectors(const tensor&);
|
(
|
||||||
|
const tensor& T,
|
||||||
|
const scalar lambda,
|
||||||
|
const vector& direction1,
|
||||||
|
const vector& direction2
|
||||||
|
);
|
||||||
|
tensor eigenVectors(const tensor& T, const vector& lambdas);
|
||||||
|
tensor eigenVectors(const tensor& T);
|
||||||
|
|
||||||
vector eigenValues(const symmTensor&);
|
vector eigenValues(const symmTensor& T);
|
||||||
vector eigenVector(const symmTensor&, const scalar lambda);
|
vector eigenVector
|
||||||
tensor eigenVectors(const symmTensor&);
|
(
|
||||||
|
const symmTensor& T,
|
||||||
|
const scalar lambda,
|
||||||
|
const vector& direction1,
|
||||||
|
const vector& direction2
|
||||||
|
);
|
||||||
|
tensor eigenVectors(const symmTensor& T, const vector& lambdas);
|
||||||
|
tensor eigenVectors(const symmTensor& T);
|
||||||
|
|
||||||
//- Data associated with tensor type are contiguous
|
//- Data associated with tensor type are contiguous
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@ -458,7 +458,7 @@ void Foam::edgeCollapser::faceCollapseAxisAndAspectRatio
|
|||||||
// normal, as it has the greatest value. The minimum eigenvalue
|
// normal, as it has the greatest value. The minimum eigenvalue
|
||||||
// is the dominant collapse axis for high aspect ratio faces.
|
// is the dominant collapse axis for high aspect ratio faces.
|
||||||
|
|
||||||
collapseAxis = eigenVector(J, eVals.x());
|
collapseAxis = eigenVectors(J, eVals).x();
|
||||||
|
|
||||||
// The inertia calculation describes the mass distribution as a
|
// The inertia calculation describes the mass distribution as a
|
||||||
// function of distance squared to the axis, so the square root of
|
// function of distance squared to the axis, so the square root of
|
||||||
|
|||||||
Reference in New Issue
Block a user