diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index 485910cae16548e35f93fdc1ec7bb3da085a1dd6..df254ed28182c6452f76535cc1a2748fd3609867 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -16,15 +16,273 @@ #include "Numeric.h" namespace { - inline double calcDet3D(double dxdX, double dydX, double dzdX, - double dxdY, double dydY, double dzdY, - double dxdZ, double dydZ, double dzdZ) - { - return dxdX*dydY*dzdZ + dxdY*dydZ*dzdX + dydX*dzdY*dxdZ - - dxdZ*dydY*dzdX - dxdY*dydX*dzdZ - dydZ*dzdY*dxdX; + +// Compute the determinant of a 3x3 matrix +inline double calcDet3D(double M11, double M12, double M13, + double M21, double M22, double M23, + double M31, double M32, double M33) +{ + return M11 * (M22*M33 - M23*M32) + - M12 * (M21*M33 - M23*M31) + + M13 * (M21*M32 - M22*M31); +} + +// Compute the squared Frobenius norm a matrix +inline double calcFrobNormSq3D(double M11, double M12, double M13, + double M21, double M22, double M23, + double M31, double M32, double M33) +{ + return M11*M11 + M12*M12 + M13*M13 + + M21*M21 + M22*M22 + M23*M23 + + M31*M21 + M32*M22 + M33*M33; +} + +// Compute the squared Frobenius norm of the inverse of a matrix +inline double calcFrobNormSqInv3D(double M11, double M12, double M13, + double M21, double M22, double M23, + double M31, double M32, double M33) +{ + const double invD = 1./calcDet3D(M11, M12, M13, M21, M22, M23, M31, M32, M33); + const double I11 = M22*M33-M23*M32, I12 = M13*M32-M12*M33, I13 = M12*M23-M13*M22, + I21 = M23*M31-M21*M33, I22 = M11*M33-M13*M31, I23 = M13*M21-M11*M23, + I31 = M21*M32-M22*M31, I32 = M12*M31-M11*M32, I33 = M11*M22-M12*M21; + return (I11*I11 + I12*I12 + I13*I13 + + I21*I21 + I22*I22 + I23*I23 + + I31*I21 + I32*I22 + I33*I33)*invD*invD; +} + +// Compute signed Jacobian and its gradients w.r.t. +// node positions, at one location in a 1D element +inline void calcJDJ1D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + fullMatrix<double> &JDJ) +{ + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + JDJ(i, j) = dPhidX * dydY * dzdZ + dPhidX * dzdY * dydZ; + JDJ(i, j+numMapNodes) = dPhidX * dzdY * dxdZ - dPhidX * dxdY * dzdZ; + JDJ(i, j+2*numMapNodes) = dPhidX * dxdY * dydZ - dPhidX * dydY * dxdZ; + } + JDJ(i, 3*numMapNodes) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); +} + +// Compute signed Jacobian and its gradients w.r.t. +// node positions, at one location in a 2D element +inline void calcJDJ2D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, + fullMatrix<double> &JDJ) +{ + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dPhidY = gSMatY(i, j); + JDJ(i, j) = + dPhidX * dydY * dzdZ + dzdX * dPhidY * dydZ + + dPhidX * dzdY * dydZ - dydX * dPhidY * dzdZ; + JDJ(i, j+numMapNodes) = + dxdX * dPhidY * dzdZ + + dPhidX * dzdY * dxdZ - dzdX * dPhidY * dxdZ + - dPhidX * dxdY * dzdZ; + JDJ(i, j+2*numMapNodes) = + dPhidX * dxdY * dydZ + + dydX * dPhidY * dxdZ - dPhidX * dydY * dxdZ - + dxdX * dPhidY * dydZ; + } + JDJ(i, 3*numMapNodes) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); +} + +// Compute signed Jacobian and its gradients w.r.t. +// node positions, at one location in a 3D element +inline void calcJDJ3D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, + const fullMatrix<double> &gSMatZ, + fullMatrix<double> &JDJ) +{ + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dPhidY = gSMatY(i, j); + const double &dPhidZ = gSMatZ(i, j); + JDJ(i, j) = + dPhidX * dydY * dzdZ + dzdX * dPhidY * dydZ + + dydX * dzdY * dPhidZ - dzdX * dydY * dPhidZ - + dPhidX * dzdY * dydZ - dydX * dPhidY * dzdZ; + JDJ(i, j+numMapNodes) = + dxdX * dPhidY * dzdZ + dzdX * dxdY * dPhidZ + + dPhidX * dzdY * dxdZ - dzdX * dPhidY * dxdZ - + dxdX * dzdY * dPhidZ - dPhidX * dxdY * dzdZ; + JDJ(i, j+2*numMapNodes) = + dxdX * dydY * dPhidZ + dPhidX * dxdY * dydZ + + dydX * dPhidY * dxdZ - dPhidX * dydY * dxdZ - + dxdX * dPhidY * dydZ - dydX * dxdY * dPhidZ; + } + JDJ(i, 3*numMapNodes) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); +} + +// Compute inverse condition number and its gradients +// w.r.t. node positions, at one location in a 1D element +inline void calcIDI1D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &JDJ, + fullMatrix<double> &IDI) +{ + const double &J = JDJ(i, 3*numMapNodes), JSq = J*J, JQuadInv = 1./(JSq*JSq); + const double A1 = dydY*dzdZ - dydZ*dzdY, A2 = dydX*dzdZ - dydZ*dzdX, + A3 = dxdY*dzdZ - dxdZ*dzdY, A4 = dxdX*dzdZ - dxdZ*dzdX, + A5 = dydX*dzdY - dydY*dzdX, A6 = dxdX*dzdY - dxdY*dzdX, + A7 = dxdY*dydZ - dxdZ*dydY, A8 = dxdX*dydZ - dxdZ*dydX, + A9 = dxdX*dydY - dxdY*dydX; + const double A = A1*A1 + A2*A2 + A3*A3 + A4*A4 + A5*A5 + A6*A6 + A7*A7 + A8*A8 + A9*A9; + const double nInvJSq = A/JSq; + const double nJSq = dxdX*dxdX + dxdY*dxdY + dxdZ*dxdZ + + dydX*dydX + dydY*dydY + dydZ*dydZ + + dzdX*dzdX + dzdY*dzdY + dzdZ*dzdZ; + const double invProd = 1./(nJSq*nInvJSq), sqrtInvProd = sqrt(invProd); + IDI(i, 3*numMapNodes) = sqrtInvProd; + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dJdxj = JDJ(i, j), &dJdyj = JDJ(i, j+numMapNodes), + &dJdzj = JDJ(i, j+2*numMapNodes); + const double dAdxj = 2.*(dPhidX*dzdZ * A4 + dPhidX*dzdY * A6 + + dPhidX*dydZ * A8 + dPhidX*dydY * A9); + const double dnInvJSqdxj = (dAdxj*JSq-2.*dJdxj*J*A)*JQuadInv; + const double dnJSqdxj = 2.*dPhidX*dxdX; + IDI(i, j) = -0.5*(dnJSqdxj*nInvJSq+nJSq*dnInvJSqdxj)*invProd*sqrtInvProd; + const double dAdyj = 2.*(dPhidX*dzdZ * A2 + dPhidX*dzdY * A5 + - dxdZ*dPhidX * A8 - dxdY*dPhidX * A9); + const double dnInvJSqdyj = (dAdyj*JSq-2.*dJdyj*J*A)*JQuadInv; + const double dnJSqdyj = 2.*dPhidX*dydX; + IDI(i, j+numMapNodes) = -0.5*(dnJSqdyj*nInvJSq+nJSq*dnInvJSqdyj)*invProd*sqrtInvProd; + const double dAdzj = 2.*(-dydZ*dPhidX * A2 - dxdZ*dPhidX * A4 + - dydY*dPhidX * A5 - dxdY*dPhidX * A6); + const double dnInvJSqdzj = (dAdzj*JSq-2.*dJdzj*J*A)*JQuadInv; + const double dnJSqdzj = 2.*dPhidX*dzdX; + IDI(i, j+2*numMapNodes) = -0.5 * (dnJSqdzj*nInvJSq + nJSq*dnInvJSqdzj) * invProd*sqrtInvProd; + } +} + +// Compute inverse condition number and its gradients +// w.r.t. node positions, at one location in a 2D element +inline void calcIDI2D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, + const fullMatrix<double> &JDJ, + fullMatrix<double> &IDI) +{ + const double &J = JDJ(i, 3*numMapNodes), JSq = J*J, JQuadInv = 1./(JSq*JSq); + const double A1 = dydY*dzdZ - dydZ*dzdY, A2 = dydX*dzdZ - dydZ*dzdX, + A3 = dxdY*dzdZ - dxdZ*dzdY, A4 = dxdX*dzdZ - dxdZ*dzdX, + A5 = dydX*dzdY - dydY*dzdX, A6 = dxdX*dzdY - dxdY*dzdX, + A7 = dxdY*dydZ - dxdZ*dydY, A8 = dxdX*dydZ - dxdZ*dydX, + A9 = dxdX*dydY - dxdY*dydX; + const double A = A1*A1 + A2*A2 + A3*A3 + A4*A4 + A5*A5 + A6*A6 + A7*A7 + A8*A8 + A9*A9; + const double nInvJSq = A/JSq; + const double nJSq = dxdX*dxdX + dxdY*dxdY + dxdZ*dxdZ + + dydX*dydX + dydY*dydY + dydZ*dydZ + + dzdX*dzdX + dzdY*dzdY + dzdZ*dzdZ; + const double invProd = 1./(nJSq*nInvJSq), sqrtInvProd = sqrt(invProd); + IDI(i, 3*numMapNodes) = 2.*sqrtInvProd; + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dPhidY = gSMatY(i, j); + const double &dJdxj = JDJ(i, j), &dJdyj = JDJ(i, j+numMapNodes), + &dJdzj = JDJ(i, j+2*numMapNodes); + const double dAdxj = 2.*(dPhidY*dzdZ * A3 + dPhidX*dzdZ * A4 + + (dPhidX*dzdY - dPhidY*dzdX) * A6 + dPhidY*dydZ * A7 + + dPhidX*dydZ * A8 + (dPhidX*dydY - dPhidY*dydX) * A9); + const double dnInvJSqdxj = (dAdxj*JSq-2.*dJdxj*J*A)*JQuadInv; + const double dnJSqdxj = 2.*(dPhidX*dxdX + dPhidY*dxdY); + IDI(i, j) = -(dnJSqdxj*nInvJSq+nJSq*dnInvJSqdxj)*invProd*sqrtInvProd; + const double dAdyj = 2.*(dPhidY*dzdZ * A1 + dPhidX*dzdZ * A2 + + (dPhidX*dzdY - dPhidY*dzdX) * A5 - dxdZ*dPhidY * A7 + - dxdZ*dPhidX * A8 + (dxdX*dPhidY - dxdY*dPhidX) * A9); + const double dnInvJSqdyj = (dAdyj*JSq-2.*dJdyj*J*A)*JQuadInv; + const double dnJSqdyj = 2.*(dPhidX*dydX + dPhidY*dydY); + IDI(i, j+numMapNodes) = -(dnJSqdyj*nInvJSq+nJSq*dnInvJSqdyj)*invProd*sqrtInvProd; + const double dAdzj = 2.*(-dydZ*dPhidY * A1 - dydZ*dPhidX * A2 + - dxdZ*dPhidY * A3 - dxdZ*dPhidX * A4 + + (dydX*dPhidY - dydY*dPhidX) * A5 + (dxdX*dPhidY - dxdY*dPhidX) * A6); + const double dnInvJSqdzj = (dAdzj*JSq-2.*dJdzj*J*A)*JQuadInv; + const double dnJSqdzj = 2.*(dPhidX*dzdX + dPhidY*dzdY); + IDI(i, j+2*numMapNodes) = -(dnJSqdzj*nInvJSq + nJSq*dnInvJSqdzj) * invProd*sqrtInvProd; } } +// Compute inverse condition number and its gradients +// w.r.t. node positions, at one location in a 3D element +inline void calcIDI3D(double dxdX, double dxdY, double dxdZ, + double dydX, double dydY, double dydZ, + double dzdX, double dzdY, double dzdZ, + int i, int numMapNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, + const fullMatrix<double> &gSMatZ, + const fullMatrix<double> &JDJ, + fullMatrix<double> &IDI) +{ + const double &J = JDJ(i, 3*numMapNodes), JSq = J*J, JQuadInv = 1./(JSq*JSq); + const double A1 = dydY*dzdZ - dydZ*dzdY, A2 = dydX*dzdZ - dydZ*dzdX, + A3 = dxdY*dzdZ - dxdZ*dzdY, A4 = dxdX*dzdZ - dxdZ*dzdX, + A5 = dydX*dzdY - dydY*dzdX, A6 = dxdX*dzdY - dxdY*dzdX, + A7 = dxdY*dydZ - dxdZ*dydY, A8 = dxdX*dydZ - dxdZ*dydX, + A9 = dxdX*dydY - dxdY*dydX; + const double A = A1*A1 + A2*A2 + A3*A3 + A4*A4 + A5*A5 + A6*A6 + A7*A7 + A8*A8 + A9*A9; + const double nInvJSq = A/JSq; + const double nJSq = dxdX*dxdX + dxdY*dxdY + dxdZ*dxdZ + + dydX*dydX + dydY*dydY + dydZ*dydZ + + dzdX*dzdX + dzdY*dzdY + dzdZ*dzdZ; + const double invProd = 1./(nJSq*nInvJSq), sqrtInvProd = sqrt(invProd); + IDI(i, 3*numMapNodes) = 3.*sqrtInvProd; + for (int j = 0; j < numMapNodes; j++) { + const double &dPhidX = gSMatX(i, j); + const double &dPhidY = gSMatY(i, j); + const double &dPhidZ = gSMatZ(i, j); + const double &dJdxj = JDJ(i, j), &dJdyj = JDJ(i, j+numMapNodes), + &dJdzj = JDJ(i, j+2*numMapNodes); + const double dAdxj = 2.*((dPhidY*dzdZ - dPhidZ*dzdY) * A3 + (dPhidX*dzdZ - dPhidZ*dzdX) * A4 + + (dPhidX*dzdY - dPhidY*dzdX) * A6 + (dPhidY*dydZ - dPhidZ*dydY) * A7 + + (dPhidX*dydZ - dPhidZ*dydX) * A8 + (dPhidX*dydY - dPhidY*dydX) * A9); + const double dnInvJSqdxj = (dAdxj*JSq-2.*dJdxj*J*A)*JQuadInv; + const double dnJSqdxj = 2.*(dPhidX*dxdX + dPhidY*dxdY + dPhidZ*dxdZ); + IDI(i, j) = -1.5*(dnJSqdxj*nInvJSq+nJSq*dnInvJSqdxj)*invProd*sqrtInvProd; + const double dAdyj = 2.*((dPhidY*dzdZ - dPhidZ*dzdY) * A1 + (dPhidX*dzdZ - dPhidZ*dzdX) * A2 + + (dPhidX*dzdY - dPhidY*dzdX) * A5 + (dxdY*dPhidZ - dxdZ*dPhidY) * A7 + + (dxdX*dPhidZ - dxdZ*dPhidX) * A8 + (dxdX*dPhidY - dxdY*dPhidX) * A9); + const double dnInvJSqdyj = (dAdyj*JSq-2.*dJdyj*J*A)*JQuadInv; + const double dnJSqdyj = 2.*(dPhidX*dydX + dPhidY*dydY + dPhidZ*dydZ); + IDI(i, j+numMapNodes) = -1.5*(dnJSqdyj*nInvJSq+nJSq*dnInvJSqdyj)*invProd*sqrtInvProd; + const double dAdzj = 2.*((dydY*dPhidZ - dydZ*dPhidY) * A1 + (dydX*dPhidZ - dydZ*dPhidX) * A2 + + (dxdY*dPhidZ - dxdZ*dPhidY) * A3 + (dxdX*dPhidZ - dxdZ*dPhidX) * A4 + + (dydX*dPhidY - dydY*dPhidX) * A5 + (dxdX*dPhidY - dxdY*dPhidX) * A6); + const double dnInvJSqdzj = (dAdzj*JSq-2.*dJdzj*J*A)*JQuadInv; + const double dnJSqdzj = 2.*(dPhidX*dzdX + dPhidY*dzdY + dPhidZ*dzdZ); + IDI(i, j+2*numMapNodes) = -1.5 * (dnJSqdzj*nInvJSq + nJSq*dnInvJSqdzj) * invProd*sqrtInvProd; + } +} + +} + GradientBasis::GradientBasis(int tag, int order) : _type(ElementType::ParentTypeFromTag(tag)), _idealDifferent(_type == TYPE_TRI || _type == TYPE_PRI || @@ -316,7 +574,9 @@ double JacobianBasis::getPrimJac3D(const fullMatrix<double> &nodesXYZ) const dzdZ += primGradShapeBarycenterZ(j)*nodesXYZ(j,2); } - return fabs(calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ)); + return fabs(calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ)); } @@ -347,7 +607,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = normals(0,0), &dydY = normals(0,1), &dzdY = normals(0,2); const double &dxdZ = normals(1,0), &dydZ = normals(1,1), &dzdZ = normals(1,2); - jacobian(i) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + jacobian(i) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); } break; } @@ -367,7 +629,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); const double &dxdZ = normal(0,0), &dydZ = normal(0,1), &dzdZ = normal(0,2); - jacobian(i) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + jacobian(i) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); } break; } @@ -383,7 +647,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2); - jacobian(i) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + jacobian(i) = calcDet3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); } if (scaling) { const double scale = 1./getPrimJac3D(nodesXYZ); @@ -452,9 +718,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do const double &dxdY = normals(0,0), &dydY = normals(0,1), &dzdY = normals(0,2); const double &dxdZ = normals(1,0), &dydZ = normals(1,1), &dzdZ = normals(1,2); for (int i = 0; i < nJacNodes; i++) - jacobian(i,iEl) = calcDet3D(dxdX(i,iEl),dydX(i,iEl),dzdX(i,iEl), - dxdY,dydY,dzdY, - dxdZ,dydZ,dzdZ); + jacobian(i,iEl) = calcDet3D(dxdX(i,iEl), dxdY, dxdZ, + dydX(i,iEl), dydY, dydZ, + dzdX(i,iEl), dzdY, dzdZ); } break; } @@ -485,9 +751,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do } const double &dxdZ = normal(0,0), &dydZ = normal(0,1), &dzdZ = normal(0,2); for (int i = 0; i < nJacNodes; i++) - jacobian(i,iEl) = calcDet3D(dxdX(i,iEl),dydX(i,iEl),dzdX(i,iEl), - dxdY(i,iEl),dydY(i,iEl),dzdY(i,iEl), - dxdZ,dydZ,dzdZ); + jacobian(i,iEl) = calcDet3D(dxdX(i,iEl), dxdY(i,iEl), dxdZ, + dydX(i,iEl), dydY(i,iEl), dydZ, + dzdX(i,iEl), dzdY(i,iEl), dzdZ); } break; } @@ -507,9 +773,9 @@ inline void JacobianBasis::getJacobianGeneral(int nJacNodes, const fullMatrix<do } for (int iEl = 0; iEl < numEl; iEl++) { for (int i = 0; i < nJacNodes; i++) - jacobian(i,iEl) = calcDet3D(dxdX(i,iEl),dydX(i,iEl),dzdX(i,iEl), - dxdY(i,iEl),dydY(i,iEl),dzdY(i,iEl), - dxdZ(i,iEl),dydZ(i,iEl),dzdZ(i,iEl)); + jacobian(i,iEl) = calcDet3D(dxdX(i,iEl), dxdY(i,iEl), dxdZ(i,iEl), + dydX(i,iEl), dydY(i,iEl), dydZ(i,iEl), + dzdX(i,iEl), dzdY(i,iEl), dzdZ(i,iEl)); if (scaling) { fullMatrix<double> nodesXYZ(numPrimMapNodes,3); for (int i = 0; i < numPrimMapNodes; i++) { @@ -580,13 +846,11 @@ inline void JacobianBasis::getSignedJacAndGradientsGeneral(int nJacNodes, const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = normals(0,0), &dydY = normals(0,1), &dzdY = normals(0,2); const double &dxdZ = normals(1,0), &dydZ = normals(1,1), &dzdZ = normals(1,2); - for (int j = 0; j < numMapNodes; j++) { - const double &dPhidX = gSMatX(i,j); - JDJ (i,j) = dPhidX * dydY * dzdZ + dPhidX * dzdY * dydZ; - JDJ (i,j+1*numMapNodes) = dPhidX * dzdY * dxdZ - dPhidX * dxdY * dzdZ; - JDJ (i,j+2*numMapNodes) = dPhidX * dxdY * dydZ - dPhidX * dydY * dxdZ; - } - JDJ(i,3*numMapNodes) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + calcJDJ1D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, JDJ); } break; } @@ -600,27 +864,96 @@ inline void JacobianBasis::getSignedJacAndGradientsGeneral(int nJacNodes, const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); const double &dxdZ = normals(0,0), &dydZ = normals(0,1), &dzdZ = normals(0,2); - for (int j = 0; j < numMapNodes; j++) { - const double &dPhidX = gSMatX(i,j); - const double &dPhidY = gSMatY(i,j); - JDJ (i,j) = - dPhidX * dydY * dzdZ + dzdX * dPhidY * dydZ + - dPhidX * dzdY * dydZ - dydX * dPhidY * dzdZ; - JDJ (i,j+1*numMapNodes) = - dxdX * dPhidY * dzdZ + - dPhidX * dzdY * dxdZ - dzdX * dPhidY * dxdZ - - dPhidX * dxdY * dzdZ; - JDJ (i,j+2*numMapNodes) = - dPhidX * dxdY * dydZ + - dydX * dPhidY * dxdZ - dPhidX * dydY * dxdZ - - dxdX * dPhidY * dydZ; - } - JDJ(i,3*numMapNodes) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + calcJDJ2D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, JDJ); + } + break; + } + + case 3 : { + fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3), dxyzdZ(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + gSMatY.mult(nodesXYZ, dxyzdY); + gSMatZ.mult(nodesXYZ, dxyzdZ); + if (ideal) _gradBasis->mapFromIdealElement(&dxyzdX, &dxyzdY, &dxyzdZ); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); + const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2); + calcJDJ3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, gSMatZ, JDJ); + } + break; + } + + } + +} + +// Calculate the inverse condition number in Frobenius norm for one element, with normal vectors to straight +// element for regularization. Evaluation points depend on the given matrices for shape function gradients. +template<bool ideal> +inline void JacobianBasis::getInvCondGeneral(int nJacNodes, const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, const fullMatrix<double> &gSMatZ, + const fullMatrix<double> &nodesXYZ, fullVector<double> &invCond) const +{ + switch (_dim) { + + case 0 : { + for (int i = 0; i < nJacNodes; i++) invCond(i) = 1.; + break; + } + + case 1 : { + fullMatrix<double> normals(2,3); + const double invScale = getPrimNormals1D(nodesXYZ,normals); + fullMatrix<double> dxyzdX(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = normals(0,0), &dydY = normals(0,1), &dzdY = normals(0,2); + const double &dxdZ = normals(1,0), &dydZ = normals(1,1), &dzdZ = normals(1,2); + const double nJSq = calcFrobNormSq3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + const double nInvJSq = calcFrobNormSqInv3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + invCond(i) = 1./sqrt(nJSq*nInvJSq); + } + break; + } + + case 2 : { + fullMatrix<double> normal(1,3); + const double invScale = getPrimNormal2D(nodesXYZ,normal); + fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + gSMatY.mult(nodesXYZ, dxyzdY); + if (ideal) _gradBasis->mapFromIdealElement(&dxyzdX, &dxyzdY, NULL); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); + const double &dxdZ = normal(0,0), &dydZ = normal(0,1), &dzdZ = normal(0,2); + const double nJSq = calcFrobNormSq3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + const double nInvJSq = calcFrobNormSqInv3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + invCond(i) = 2./sqrt(nJSq*nInvJSq); } break; } case 3 : { + fullMatrix<double> dum; fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3), dxyzdZ(nJacNodes,3); gSMatX.mult(nodesXYZ, dxyzdX); gSMatY.mult(nodesXYZ, dxyzdY); @@ -630,24 +963,111 @@ inline void JacobianBasis::getSignedJacAndGradientsGeneral(int nJacNodes, const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2); + const double nJSq = calcFrobNormSq3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + const double nInvJSq = calcFrobNormSqInv3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ); + invCond(i) = 3./sqrt(nJSq*nInvJSq); + } + break; + } + } +} + +// Calculate the inverse condition number in Frobenius norm and its gradients w.r.t. node position, +// with normal vectors to straight element for regularization. Evaluation points depend on the +// given matrices for shape function gradients. +template<bool ideal> +inline void JacobianBasis::getInvCondAndGradientsGeneral(int nJacNodes, + const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, + const fullMatrix<double> &gSMatZ, + const fullMatrix<double> &nodesXYZ, + const fullMatrix<double> &normals, + fullMatrix<double> &IDI) const +{ + fullMatrix<double> JDJ(nJacNodes, 3*numMapNodes+1); + + switch (_dim) { + + case 0 : { + for (int i = 0; i < nJacNodes; i++) { for (int j = 0; j < numMapNodes; j++) { - const double &dPhidX = gSMatX(i,j); - const double &dPhidY = gSMatY(i,j); - const double &dPhidZ = gSMatZ(i,j); - JDJ (i,j) = - dPhidX * dydY * dzdZ + dzdX * dPhidY * dydZ + - dydX * dzdY * dPhidZ - dzdX * dydY * dPhidZ - - dPhidX * dzdY * dydZ - dydX * dPhidY * dzdZ; - JDJ (i,j+1*numMapNodes) = - dxdX * dPhidY * dzdZ + dzdX * dxdY * dPhidZ + - dPhidX * dzdY * dxdZ - dzdX * dPhidY * dxdZ - - dxdX * dzdY * dPhidZ - dPhidX * dxdY * dzdZ; - JDJ (i,j+2*numMapNodes) = - dxdX * dydY * dPhidZ + dPhidX * dxdY * dydZ + - dydX * dPhidY * dxdZ - dPhidX * dydY * dxdZ - - dxdX * dPhidY * dydZ - dydX * dxdY * dPhidZ; + IDI(i,j) = 0.; + IDI(i,j+1*numMapNodes) = 0.; + IDI(i,j+2*numMapNodes) = 0.; } - JDJ(i,3*numMapNodes) = calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ); + IDI(i,3*numMapNodes) = 1.; + } + break; + } + + case 1 : { + fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = normals(0,0), &dydY = normals(0,1), &dzdY = normals(0,2); + const double &dxdZ = normals(1,0), &dydZ = normals(1,1), &dzdZ = normals(1,2); + calcJDJ1D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, JDJ); + calcIDI1D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, JDJ, IDI); + } + break; + } + + case 2 : { + fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + gSMatY.mult(nodesXYZ, dxyzdY); + if (ideal) _gradBasis->mapFromIdealElement(&dxyzdX, &dxyzdY, NULL); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); + const double &dxdZ = normals(0,0), &dydZ = normals(0,1), &dzdZ = normals(0,2); + calcJDJ2D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, JDJ); + calcIDI2D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, JDJ, IDI); + } + break; + } + + case 3 : { + fullMatrix<double> dxyzdX(nJacNodes,3), dxyzdY(nJacNodes,3), dxyzdZ(nJacNodes,3); + gSMatX.mult(nodesXYZ, dxyzdX); + gSMatY.mult(nodesXYZ, dxyzdY); + gSMatZ.mult(nodesXYZ, dxyzdZ); + if (ideal) _gradBasis->mapFromIdealElement(&dxyzdX, &dxyzdY, &dxyzdZ); + for (int i = 0; i < nJacNodes; i++) { + const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2); + const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2); + const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2); + calcJDJ3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, gSMatZ, JDJ); + calcIDI3D(dxdX, dxdY, dxdZ, + dydX, dydY, dydZ, + dzdX, dzdY, dzdZ, + i, numMapNodes, + gSMatX, gSMatY, gSMatZ, JDJ, IDI); } break; } diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h index 4dd280ecc88693bd36f46d4c91c53d14bc856c9c..fb5cae75e9eb4dbeb170ce69fa8ce9e6411ee011 100644 --- a/Numeric/JacobianBasis.h +++ b/Numeric/JacobianBasis.h @@ -158,6 +158,19 @@ class JacobianBasis { const fullMatrix<double> &gSMatY, const fullMatrix<double> &gSMatZ, const fullMatrix<double> &nodesXYZ, const fullMatrix<double> &normals, fullMatrix<double> &JDJ) const; + + template<bool ideal> + inline void getInvCondGeneral(int nJacNodes, const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, const fullMatrix<double> &gSMatZ, + const fullMatrix<double> &nodesXYZ, fullVector<double> &invCond) const; + + template<bool ideal> + inline void getInvCondAndGradientsGeneral(int nJacNodes, const fullMatrix<double> &gSMatX, + const fullMatrix<double> &gSMatY, const fullMatrix<double> &gSMatZ, + const fullMatrix<double> &nodesXYZ, const fullMatrix<double> &normals, + fullMatrix<double> &IDI) const; + + }; #endif