ENH: Migrated eigen vector/value updates from old development line and updated dependencies

This commit is contained in:
andy
2016-02-22 12:14:53 +00:00
committed by Andrew Heather
parent 1bb86b47a6
commit de6313e4ce
3 changed files with 97 additions and 67 deletions

View File

@ -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.xx()) + mag(T.yy()) + mag(T.zz())
);
const scalar offDiagMagSum =
( (
mag(t.xy()) + mag(t.xz()) + mag(t.yx()) mag(T.xy()) + mag(T.xz()) + mag(T.yx())
+ mag(t.yz()) + mag(t.zx()) + mag(t.zy()) + mag(T.yz()) + mag(T.zx()) + mag(T.zy())
) );
< SMALL
) 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);
Uz = eigenVector(T, lambdas.z(), Ux, Uy);
return tensor(Ux, Uy, Uz);
}
Foam::tensor Foam::eigenVectors(const tensor& T)
{
const vector lambdas(eigenValues(T));
return eigenVectors(T, lambdas);
}
Foam::vector Foam::eigenValues(const symmTensor& T)
{
return eigenValues(tensor(T));
}
Foam::vector Foam::eigenVector
( (
eigenVector(t, evals.x()), const symmTensor& T,
eigenVector(t, evals.y()), const scalar lambda,
eigenVector(t, evals.z()) const vector& direction1,
); const vector& direction2
)
return evs; {
return eigenVector(tensor(T), lambda, direction1, direction2);
} }
Foam::vector Foam::eigenValues(const symmTensor& t) Foam::tensor Foam::eigenVectors(const symmTensor& T, const vector& lambdas)
{ {
return eigenValues(tensor(t)); return eigenVectors(tensor(T), lambdas);
} }
Foam::vector Foam::eigenVector(const symmTensor& t, const scalar lambda) Foam::tensor Foam::eigenVectors(const symmTensor& T)
{ {
return eigenVector(tensor(t), lambda); return eigenVectors(tensor(T));
}
Foam::tensor Foam::eigenVectors(const symmTensor& t)
{
return eigenVectors(tensor(t));
} }

View File

@ -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<>

View File

@ -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