From 3619b8d5e6fc0be01ba90cc0874f9457d19cbcd6 Mon Sep 17 00:00:00 2001 From: Thomas Toulorge <thomas.toulorge@mines-paristech.fr> Date: Wed, 15 Oct 2014 09:18:29 +0000 Subject: [PATCH] Improved computation of inverse condition number and its gradients --- Numeric/CondNumBasis.cpp | 98 +++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/Numeric/CondNumBasis.cpp b/Numeric/CondNumBasis.cpp index ff0b36f828..67cd3253c7 100644 --- a/Numeric/CondNumBasis.cpp +++ b/Numeric/CondNumBasis.cpp @@ -37,7 +37,6 @@ inline double calcInvCondNum2D(double dxdX, double dxdY, double dzdX, double dzdY, double nx, double ny, double nz) { - static const double Eps = 1e-10; const double dxdXSq = dxdX*dxdX, dydXSq = dydX*dydX, dzdXSq = dzdX*dzdX; const double dxdYSq = dxdY*dxdY, dydYSq = dydY*dydY, dzdYSq = dzdY*dzdY; const double Dx = dxdXSq - dxdYSq, Dy = dydXSq - dydYSq; @@ -59,14 +58,12 @@ inline double calcInvCondNum2D(double dxdX, double dxdY, const double N = dxdXSq + dxdYSq + dydXSq + dydYSq + dzdXSq + dzdYSq; const double sqrtS = sqrt(S); const double sigma1Sq = 0.5 * (N + sqrtS), sigma2Sq = 0.5 * (N - sqrtS); - if (sigma2Sq < Eps) return 0.; - const double iCN = 2. / sqrt((sigma1Sq + sigma2Sq) * (1./sigma1Sq + 1./sigma2Sq)); + const double iCN = 2. * sqrt(sigma1Sq*sigma2Sq) / (sigma1Sq+sigma2Sq); if (sign) { const double lnx = dydX*dzdY - dzdX*dydY, lny = dzdX*dxdY - dxdX*dzdY, // Local normal from mapping gradients lnz = dxdX*dydY - dydX*dxdY; const double dp = lnx*nx + lny*ny + lnz*nz; // Dot product to determine element validity - if (dp == 0.) return 0.; - return (dp > 0.) ? iCN : -iCN; + return (dp >= 0.) ? iCN : -iCN; } else return iCN; @@ -110,12 +107,14 @@ inline void calcGradInvCondNum2D(double dxdX, double dxdY, const fullMatrix<double> &gSMatY, fullMatrix<double> &IDI) { + const double EpsDegen = 1.e-6; + bool posJac = true; if (sign) { const double lnx = dydX*dzdY - dzdX*dydY, lny = dzdX*dxdY - dxdX*dzdY, // Local normal from mapping gradients lnz = dxdX*dydY - dydX*dxdY; const double dp = lnx*nx + lny*ny + lnz*nz; // Dot product to determine element validity - posJac = (dp > 0.); + posJac = (dp >= 0.); } const double dxdXSq = dxdX*dxdX, dydXSq = dydX*dydX, dzdXSq = dzdX*dzdX; @@ -144,26 +143,34 @@ inline void calcGradInvCondNum2D(double dxdX, double dxdY, const double N = dxdXSq + dxdYSq + dydXSq + dydYSq + dzdXSq + dzdYSq; const double sqrtS = sqrt(S), invSqrtS = 1./sqrtS; const double sigma1Sq = 0.5 * (N + sqrtS), sigma2Sq = 0.5 * (N - sqrtS); -// if (sigma2Sq < Eps) { // TODO: Degenerate element (sigma2 == 0.) -// const double dnx = dydX*nz - dzdX*ny, dny = dzdX*nx - dxdX*nz, -// dnz = dxdX*ny - dydX*nx; -// -// } - const double invSigma1Sq = 1./sigma1Sq; - const double invSigma2Sq = 1./sigma2Sq; - const double invProd = 1. / ((sigma1Sq + sigma2Sq) * (invSigma1Sq + invSigma2Sq)); - const double invSqrtProd = sqrt(invProd); - IDI(i, 3*numMapNodes) = posJac ? 2. * invSqrtProd : -2. * invSqrtProd; -// std::cout << "DBGTT: Value " << i << "\n"; -// std::cout << "DBGTT: -> I = " << IDI(i, 3*numMapNodes) << "\n"; -// std::cout << "DBGTT: -> S = " << S << ", sqrt(S) = " << sqrtS << "\n"; -// std::cout << "DBGTT: -> N = " << N << "\n"; -// std::cout << "DBGTT: -> sigma1Sq, sigma2Sq = (" << sigma1Sq << ", " << sigma2Sq << ")\n"; + const bool degen = (sigma2Sq < EpsDegen*sigma1Sq); // Check for degenerate element + const double sum = sigma1Sq + sigma2Sq, invSum = 1. / sum; + const double prod = sigma1Sq * sigma2Sq; + const double sqrtProd = sqrt(prod); + const double halfICN = sqrtProd * invSum; + IDI(i, 3*numMapNodes) = posJac ? 2. * halfICN : -2. * halfICN; + + if (degen) { // Degenerate element: special formula for gradients + const double nnXx = dzdX*ny - dydX*nz, nnXy = dxdX*nz - dzdX*nx, + nnXz = dydX*nx - dxdX*ny; + const double nnYx = dzdY*ny - dydY*nz, nnYy = dxdY*nz - dzdY*nx, + nnYz = dydY*nx - dxdY*ny; + const double fact = 2./N; + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dPhidY = gSMatY(i, j); + IDI(i, j) = fact * (dPhidY*nnXx - dPhidX*nnYx); + IDI(i, j+numMapNodes) = fact * (dPhidY*nnXy - dPhidX*nnYy); + IDI(i, j+2*numMapNodes) = fact * (dPhidY*nnXz - dPhidX*nnYz); + } + return; + } + + const double invSqrtProd = 1. / sqrtProd; for (int j = 0; j < numMapNodes; j++) { const double &dPhidX = gSMatX(i, j); const double &dPhidY = gSMatY(i, j); -// std::cout << "DBGTT: -> Node " << j << ":\n"; const double ddxdXSqdxj = 2.*dPhidX*dxdX, ddxdYSqdxj = 2.*dPhidY*dxdY; const double dDxdxj = ddxdXSqdxj - ddxdYSqdxj; @@ -182,19 +189,10 @@ inline void calcGradInvCondNum2D(double dxdX, double dxdY, const double dsqrtSdxj = 0.5*dSdxj*invSqrtS; const double dsigma1Sqdxj = 0.5 * (dNdxj + dsqrtSdxj), dsigma2Sqdxj = 0.5 * (dNdxj - dsqrtSdxj); - const double dinvSigma1Sqdxj = -dsigma1Sqdxj*invSigma1Sq*invSigma1Sq, - dinvSigma2Sqdxj = -dsigma2Sqdxj*invSigma2Sq*invSigma2Sq; - const double dProddxj = (dsigma1Sqdxj + dsigma2Sqdxj) * (invSigma1Sq + invSigma2Sq) - + (sigma1Sq + sigma2Sq) * (dinvSigma1Sqdxj + dinvSigma2Sqdxj); - const double mdiCNdxj = dProddxj*invProd*invSqrtProd; - IDI(i, j) = posJac ? -mdiCNdxj : mdiCNdxj; -// std::cout << "DBGTT: -> d(dxdX)dxj = " << dPhidX << ", d(dxdY)dxj = " << dPhidY << "\n"; -// std::cout << "DBGTT: -> dNdxj = " << dNdxj << ", dSdxj = " << dSdxj << "\n"; -// std::cout << "DBGTT: -> dsigma1Sqdxj = " << dsigma1Sqdxj << ", dsigma2Sqdxj = " << dsigma2Sqdxj << "\n"; -// std::cout << "DBGTT: -> dinvSigma1Sqdxj = " << dinvSigma1Sqdxj << ", dinvSigma2Sqdxj = " << dinvSigma2Sqdxj << "\n"; -// std::cout << "DBGTT: -> mdiCNdxj = " << mdiCNdxj -// << ", -dsigma2Sqdxj/sqrt(sigma1Sq*sigma2Sq) = " << -dsigma2Sqdxj/sqrt(sigma1Sq*sigma2Sq) -// << ", T1 = " << -dNdxj/sqrt(N*N-S) << ", T21 = " << (0.5*dSdxj/sqrtS)/sqrt(N*N-S) << "\n"; + const double dSumdxj = dsigma1Sqdxj + dsigma2Sqdxj; + const double dProddxj = dsigma1Sqdxj*sigma2Sq + sigma1Sq*dsigma2Sqdxj; + const double diCNdxj = (dProddxj*sum - 2.*prod*dSumdxj)*invSum*invSum*invSqrtProd; + IDI(i, j) = posJac ? diCNdxj : -diCNdxj; const double ddydXSqdyj = 2.*dPhidX*dydX, ddydYSqdyj = 2.*dPhidY*dydY; const double dDydyj = ddydXSqdyj - ddydYSqdyj; @@ -213,16 +211,10 @@ inline void calcGradInvCondNum2D(double dxdX, double dxdY, const double dsqrtSdyj = 0.5*dSdyj*invSqrtS; const double dsigma1Sqdyj = 0.5 * (dNdyj + dsqrtSdyj), dsigma2Sqdyj = 0.5 * (dNdyj - dsqrtSdyj); - const double dinvSigma1Sqdyj = -dsigma1Sqdyj*invSigma1Sq*invSigma1Sq, - dinvSigma2Sqdyj = -dsigma2Sqdyj*invSigma2Sq*invSigma2Sq; - const double dProddyj = (dsigma1Sqdyj + dsigma2Sqdyj) * (invSigma1Sq + invSigma2Sq) - + (sigma1Sq + sigma2Sq) * (dinvSigma1Sqdyj + dinvSigma2Sqdyj); - const double mdiCNdyj = dProddyj*invProd*invSqrtProd; - IDI(i, j+numMapNodes) = posJac ? -mdiCNdyj : mdiCNdyj; -// std::cout << "DBGTT: -> d(dydX)dyj = " << dPhidX << ", d(dydY)dyj = " << dPhidY << "\n"; -// std::cout << "DBGTT: -> dNdyj = " << dNdyj << ", dSdyj = " << dSdyj << "\n"; -// std::cout << "DBGTT: -> dsigma1Sqdyj = " << dsigma1Sqdyj << ", dsigma2Sqdyj = " << dsigma2Sqdyj << "\n"; -// std::cout << "DBGTT: -> dinvSigma1Sqdyj = " << dinvSigma1Sqdyj << ", dinvSigma2Sqdyj = " << dinvSigma2Sqdyj << "\n"; + const double dSumdyj = dsigma1Sqdyj + dsigma2Sqdyj; + const double dProddyj = dsigma1Sqdyj*sigma2Sq + sigma1Sq*dsigma2Sqdyj; + const double diCNdyj = (dProddyj*sum - 2.*prod*dSumdyj)*invSum*invSum*invSqrtProd; + IDI(i, j+numMapNodes) = posJac ? diCNdyj : -diCNdyj; const double ddzdXSqdzj = 2.*dPhidX*dzdX, ddzdYSqdzj = 2.*dPhidY*dzdY; const double dS1dzj = 2. * ddzdYSqdzj * dzdYSq; @@ -236,18 +228,10 @@ inline void calcGradInvCondNum2D(double dxdX, double dxdY, const double dsqrtSdzj = 0.5*dSdzj*invSqrtS; const double dsigma1Sqdzj = 0.5 * (dNdzj + dsqrtSdzj), dsigma2Sqdzj = 0.5 * (dNdzj - dsqrtSdzj); - const double dinvSigma1Sqdzj = -dsigma1Sqdzj*invSigma1Sq*invSigma1Sq, - dinvSigma2Sqdzj = -dsigma2Sqdzj*invSigma2Sq*invSigma2Sq; - const double dProddzj = (dsigma1Sqdzj + dsigma2Sqdzj) * (invSigma1Sq + invSigma2Sq) - + (sigma1Sq + sigma2Sq) * (dinvSigma1Sqdzj + dinvSigma2Sqdzj); - const double mdiCNdzj = dProddzj*invProd*invSqrtProd; - IDI(i, j+2*numMapNodes) = posJac ? -mdiCNdzj : mdiCNdzj; -// std::cout << "DBGTT: -> d(dzdX)dzj = " << dPhidX << ", d(dzdY)dzj = " << dPhidY << "\n"; -// std::cout << "DBGTT: -> dNdzj = " << dNdzj << ", dSdzj = " << dSdzj << "\n"; -// std::cout << "DBGTT: -> dsigma1Sqdzj = " << dsigma1Sqdzj << ", dsigma2Sqdzj = " << dsigma2Sqdzj << "\n"; -// std::cout << "DBGTT: -> dinvSigma1Sqdzj = " << dinvSigma1Sqdzj << ", dinvSigma2Sqdzj = " << dinvSigma2Sqdzj << "\n"; -// std::cout << "DBGTT: -> dId{x,y,z} = (" << IDI(i, j) << ", " -// << IDI(i, j+numMapNodes) << ", " << IDI(i, j+2*numMapNodes) << ")\n"; + const double dSumdzj = dsigma1Sqdzj + dsigma2Sqdzj; + const double dProddzj = dsigma1Sqdzj*sigma2Sq + sigma1Sq*dsigma2Sqdzj; + const double diCNdzj = (dProddzj*sum - 2.*prod*dSumdzj)*invSum*invSum*invSqrtProd; + IDI(i, j+2*numMapNodes) = posJac ? diCNdzj : -diCNdzj; } } -- GitLab