From 9f7e6b694ffe9c30ecf2ed25cbaaeee5e051db64 Mon Sep 17 00:00:00 2001 From: william <william> Date: Thu, 28 Aug 2014 11:25:43 +0100 Subject: [PATCH] BUG: mantis #1373: quick return for diagonal matrices --- .../primitives/Tensor/tensor/tensor.C | 131 ++++++++++-------- 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/src/OpenFOAM/primitives/Tensor/tensor/tensor.C b/src/OpenFOAM/primitives/Tensor/tensor/tensor.C index 30f5ee246fb..fa20ef6bf66 100644 --- a/src/OpenFOAM/primitives/Tensor/tensor/tensor.C +++ b/src/OpenFOAM/primitives/Tensor/tensor/tensor.C @@ -92,76 +92,95 @@ Foam::vector Foam::eigenValues(const tensor& t) // The eigenvalues scalar i, ii, iii; - // Coefficients of the characteristic polynmial - // x^3 + a*x^2 + b*x + c = 0 - scalar a = - - t.xx() - t.yy() - t.zz(); - - scalar b = - t.xx()*t.yy() + t.xx()*t.zz() + t.yy()*t.zz() - - t.xy()*t.yx() - t.yz()*t.zy() - t.zx()*t.xz(); - - scalar c = - - t.xx()*t.yy()*t.zz() - - 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(); + // diagonal matrix + if + ( + ( + mag(t.xy()) + mag(t.xz()) + mag(t.yx()) + + mag(t.yz()) + mag(t.zx()) + mag(t.zy()) + ) + < SMALL + ) + { + i = t.xx(); + ii = t.yy(); + iii = t.zz(); + } - // Auxillary variables - scalar aBy3 = a/3; + // non-diagonal matrix + else + { + // Coefficients of the characteristic polynmial + // x^3 + a*x^2 + b*x + c = 0 + scalar a = + - t.xx() - t.yy() - t.zz(); - scalar P = (a*a - 3*b)/9; // == -p_wikipedia/3 - scalar PPP = P*P*P; + scalar b = + t.xx()*t.yy() + t.xx()*t.zz() + t.yy()*t.zz() + - t.xy()*t.yx() - t.yz()*t.zy() - t.zx()*t.xz(); - scalar Q = (2*a*a*a - 9*a*b + 27*c)/54; // == q_wikipedia/2 - scalar QQ = Q*Q; + scalar c = + - t.xx()*t.yy()*t.zz() + - 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(); - // Three identical roots - if (mag(P) < SMALL && mag(Q) < SMALL) - { - return vector(- aBy3, - aBy3, - aBy3); - } + // Auxillary variables + scalar aBy3 = a/3; - // Two identical roots and one distinct root - else if (mag(PPP/QQ - 1) < SMALL) - { - scalar sqrtP = sqrt(P); - scalar signQ = sign(Q); + scalar P = (a*a - 3*b)/9; // == -p_wikipedia/3 + scalar PPP = P*P*P; - i = ii = signQ*sqrtP - aBy3; - iii = - 2*signQ*sqrtP - aBy3; - } + scalar Q = (2*a*a*a - 9*a*b + 27*c)/54; // == q_wikipedia/2 + scalar QQ = Q*Q; - // Three distinct roots - else if (PPP > QQ) - { - scalar sqrtP = sqrt(P); - scalar value = cos(acos(Q/sqrt(PPP))/3); - scalar delta = sqrt(3 - 3*value*value); + // Three identical roots + if (mag(P) < SMALL && mag(Q) < SMALL) + { + return vector(- aBy3, - aBy3, - aBy3); + } - i = - 2*sqrtP*value - aBy3; - ii = sqrtP*(value + delta) - aBy3; - iii = sqrtP*(value - delta) - aBy3; - } + // Two identical roots and one distinct root + else if (mag(PPP/QQ - 1) < SMALL) + { + scalar sqrtP = sqrt(P); + scalar signQ = sign(Q); - // One real root, two imaginary roots - // based on the above logic, PPP must be less than QQ - else - { - WarningIn("eigenValues(const tensor&)") - << "complex eigenvalues detected for tensor: " << t - << endl; + i = ii = signQ*sqrtP - aBy3; + iii = - 2*signQ*sqrtP - aBy3; + } - if (mag(P) < SMALL) + // Three distinct roots + else if (PPP > QQ) { - i = cbrt(QQ/2); + scalar sqrtP = sqrt(P); + scalar value = cos(acos(Q/sqrt(PPP))/3); + scalar delta = sqrt(3 - 3*value*value); + + i = - 2*sqrtP*value - aBy3; + ii = sqrtP*(value + delta) - aBy3; + iii = sqrtP*(value - delta) - aBy3; } + + // One real root, two imaginary roots + // based on the above logic, PPP must be less than QQ else { - scalar w = cbrt(- Q - sqrt(QQ - PPP)); - i = w + P/w - aBy3; + WarningIn("eigenValues(const tensor&)") + << "complex eigenvalues detected for tensor: " << t + << endl; + + if (mag(P) < SMALL) + { + i = cbrt(QQ/2); + } + else + { + scalar w = cbrt(- Q - sqrt(QQ - PPP)); + i = w + P/w - aBy3; + } + + return vector(-VGREAT, i, VGREAT); } - - return vector(-VGREAT, i, VGREAT); } // Sort the eigenvalues into ascending order @@ -192,7 +211,7 @@ Foam::vector Foam::eigenVector { // Constantly rotating direction ensures different eigenvectors are // generated when called sequentially with a multiple eigenvalue - static vector direction(0,0,1); + static vector direction(1,0,0); vector oldDirection(direction); scalar temp = direction[2]; direction[2] = direction[1]; -- GitLab