diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index 759f3bb38219c6c10594e8a98a0fa61a23e5cef9..a1dee5e3d36498ec6303b45a0c4e0ccf994b7c41 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -123,8 +123,8 @@ void MElement::scaledJacRange(double &jmin, double &jmax) fullVector<double> SJi(numJacNodes), Bi(numJacNodes); jac->getScaledJacobian(nodesXYZ,SJi); jac->lag2Bez(SJi,Bi); - jmin = *std::min_element(Bi.getDataPtr(),Bi.getDataPtr()+Bi.size()); - jmax = *std::max_element(Bi.getDataPtr(),Bi.getDataPtr()+Bi.size()); + jmin = 0;//*std::min_element(Bi.getDataPtr(),Bi.getDataPtr()+Bi.size()); + jmax = 0;//*std::max_element(Bi.getDataPtr(),Bi.getDataPtr()+Bi.size()); #endif } diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index 6f1584e1bdaedafe494bef6c8994d53c6b296978..a58d3fbc472c971a4d627b4a278fb415def2363d 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -19,118 +19,113 @@ JacobianBasis::JacobianBasis(int tag) const int parentType = ElementType::ParentTypeFromTag(tag); const int order = ElementType::OrderFromTag(tag); - //int jacType = 0, - int primJacType = 0; - - /*if (parentType == TYPE_PYR) { - switch (tag) { - case MSH_PYR_5 : jacType = MSH_PYR_14; primJacType = MSH_PYR_14; break; // TODO: Order 1, Jac. "order" 2, check this - case MSH_PYR_14 : jacType = MSH_PYR_91; primJacType = MSH_PYR_14; break; // TODO: Order 2, Jac. "order" 5, check this - case MSH_PYR_30 : jacType = MSH_PYR_285; primJacType = MSH_PYR_14; break; // TODO: Order 3, Jac. "order" 8, check this + int jacobianOrder, primJacobianOrder; + switch (parentType) { + case TYPE_PNT : + primJacobianOrder = 0; + jacobianOrder = 0; + lagPoints = gmshGeneratePointsLine(0); + break; + case TYPE_LIN : + primJacobianOrder = 0; + jacobianOrder = order - 1; + lagPoints = gmshGeneratePointsLine(jacobianOrder); + break; + case TYPE_TRI : + primJacobianOrder = 0; + jacobianOrder = 2*order - 2; + lagPoints = gmshGeneratePointsTriangle(jacobianOrder); + break; + case TYPE_QUA : + primJacobianOrder = 1; + jacobianOrder = 2*order - 1; + lagPoints = gmshGeneratePointsQuadrangle(jacobianOrder); + break; + case TYPE_TET : + primJacobianOrder = 0; + jacobianOrder = 3*order - 3; + lagPoints = gmshGeneratePointsTetrahedron(jacobianOrder); + break; + case TYPE_PRI : + primJacobianOrder = 2; + jacobianOrder = 3*order - 1; + lagPoints = gmshGeneratePointsPrism(jacobianOrder); + break; + case TYPE_HEX : + primJacobianOrder = 2; + jacobianOrder = 3*order - 1; + lagPoints = gmshGeneratePointsHexahedron(jacobianOrder); + break; + case TYPE_PYR : + primJacobianOrder = 0; + jacobianOrder = 3*order - 3; + lagPoints = generateJacPointsPyramid(jacobianOrder); + break; default : Msg::Error("Unknown Jacobian function space for element type %d", tag); + jacobianOrder = 0; break; - } } - else {*/ - int jacobianOrder, primJacobianOrder; - - switch (parentType) { - case TYPE_PNT : - primJacobianOrder = 0; - jacobianOrder = 0; - lagPoints = gmshGeneratePointsLine(0); - break; - case TYPE_LIN : - primJacobianOrder = 0; - jacobianOrder = order - 1; - lagPoints = gmshGeneratePointsLine(order); - break; - case TYPE_TRI : - primJacobianOrder = 0; - jacobianOrder = 2*order - 2; - lagPoints = gmshGeneratePointsTriangle(order); - break; - case TYPE_QUA : - primJacobianOrder = 1; - jacobianOrder = 2*order - 1; - lagPoints = gmshGeneratePointsQuadrangle(order); - break; - case TYPE_TET : - primJacobianOrder = 0; - jacobianOrder = 3*order - 3; - lagPoints = gmshGeneratePointsTetrahedron(order); - break; - case TYPE_PRI : - primJacobianOrder = 2; - jacobianOrder = 3*order - 1; - lagPoints = gmshGeneratePointsPrism(order); - break; - case TYPE_HEX : - primJacobianOrder = 2; - jacobianOrder = 3*order - 1; - lagPoints = gmshGeneratePointsHexahedron(order); - break; - default : - Msg::Error("Unknown Jacobian function space for element type %d", tag); - jacobianOrder = 0; - break; - } - primJacType = ElementType::getTag(parentType, primJacobianOrder, false); - //} + numJacNodes = lagPoints.size1(); // Store Bezier basis bezier = BasisFactory::getBezierBasis(parentType, jacobianOrder); // Store shape function gradients of mapping at Jacobian nodes - const nodalBasis *mapBasis = BasisFactory::getNodalBasis(tag); fullMatrix<double> allDPsi; + const nodalBasis *mapBasis = BasisFactory::getNodalBasis(tag); + mapBasis->df(lagPoints, allDPsi); - numJacNodes = lagPoints.size1(); numMapNodes = allDPsi.size1(); - gradShapeMatX.resize(numJacNodes,numMapNodes); - gradShapeMatY.resize(numJacNodes,numMapNodes); - gradShapeMatZ.resize(numJacNodes,numMapNodes); - for (int i=0; i<numJacNodes; i++) + + gradShapeMatX.resize(numJacNodes, numMapNodes); + gradShapeMatY.resize(numJacNodes, numMapNodes); + gradShapeMatZ.resize(numJacNodes, numMapNodes); + for (int i=0; i<numJacNodes; i++) { for (int j=0; j<numMapNodes; j++) { - gradShapeMatX(i,j) = allDPsi(j,3*i); - gradShapeMatY(i,j) = allDPsi(j,3*i+1); - gradShapeMatZ(i,j) = allDPsi(j,3*i+2); + gradShapeMatX(i, j) = allDPsi(j, 3*i); + gradShapeMatY(i, j) = allDPsi(j, 3*i+1); + gradShapeMatZ(i, j) = allDPsi(j, 3*i+2); } + } // Compute matrix for lifting from primary Jacobian basis to Jacobian basis + int primJacType = ElementType::getTag(parentType, primJacobianOrder, false); const nodalBasis *primJacBasis = BasisFactory::getNodalBasis(primJacType); numPrimJacNodes = primJacBasis->getNumShapeFunctions(); + matrixPrimJac2Jac.resize(numJacNodes,numPrimJacNodes); - primJacBasis->f(lagPoints, matrixPrimJac2Jac); //FIXME not too much sampling points ?? + primJacBasis->f(lagPoints, matrixPrimJac2Jac); // Compute shape function gradients of primary mapping at barycenter, // in order to compute normal to straight element const int primMapType = ElementType::getTag(parentType, 1, false); const nodalBasis *primMapBasis = BasisFactory::getNodalBasis(primMapType); numPrimMapNodes = primMapBasis->getNumShapeFunctions(); + double xBar = 0., yBar = 0., zBar = 0.; - for (int i=0; i<numPrimMapNodes; i++) { - xBar += primMapBasis->points(i,0); - yBar += primMapBasis->points(i,1); - if (primMapBasis->points.size2() > 2) - zBar += primMapBasis->points(i,2); + double barycenter[3] = {0., 0., 0.}; + for (int i = 0; i < numPrimMapNodes; i++) { + for (int j = 0; i < primMapBasis->points.size2(); ++i) { + barycenter[j] += primMapBasis->points(i, j); + } } - xBar /= numPrimMapNodes; - yBar /= numPrimMapNodes; - zBar /= numPrimMapNodes; + barycenter[0] /= numPrimMapNodes; + barycenter[1] /= numPrimMapNodes; + barycenter[2] /= numPrimMapNodes; + double (*barDPsi)[3] = new double[numPrimMapNodes][3]; primMapBasis->df(xBar, yBar, zBar, barDPsi); - primGradShapeBarX.resize(numPrimMapNodes); - primGradShapeBarY.resize(numPrimMapNodes); - primGradShapeBarZ.resize(numPrimMapNodes); + + primGradShapeBarycenterX.resize(numPrimMapNodes); + primGradShapeBarycenterY.resize(numPrimMapNodes); + primGradShapeBarycenterZ.resize(numPrimMapNodes); for (int j=0; j<numPrimMapNodes; j++) { - primGradShapeBarX(j) = barDPsi[j][0]; - primGradShapeBarY(j) = barDPsi[j][1]; - primGradShapeBarZ(j) = barDPsi[j][2]; + primGradShapeBarycenterX(j) = barDPsi[j][0]; + primGradShapeBarycenterY(j) = barDPsi[j][1]; + primGradShapeBarycenterZ(j) = barDPsi[j][2]; } delete[] barDPsi; - } // Computes (unit) normals to straight line element at barycenter (with norm of gradient as return value) @@ -139,9 +134,9 @@ double JacobianBasis::getPrimNormals1D(const fullMatrix<double> &nodesXYZ, fullM fullVector<double> dxyzdXbar(3); for (int j=0; j<numPrimMapNodes; j++) { - dxyzdXbar(0) += primGradShapeBarX(j)*nodesXYZ(j,0); - dxyzdXbar(1) += primGradShapeBarX(j)*nodesXYZ(j,1); - dxyzdXbar(2) += primGradShapeBarX(j)*nodesXYZ(j,2); + dxyzdXbar(0) += primGradShapeBarycenterX(j)*nodesXYZ(j,0); + dxyzdXbar(1) += primGradShapeBarycenterX(j)*nodesXYZ(j,1); + dxyzdXbar(2) += primGradShapeBarycenterX(j)*nodesXYZ(j,2); } if((fabs(dxyzdXbar(0)) >= fabs(dxyzdXbar(1)) && fabs(dxyzdXbar(0)) >= fabs(dxyzdXbar(2))) || @@ -170,12 +165,12 @@ double JacobianBasis::getPrimNormal2D(const fullMatrix<double> &nodesXYZ, fullMa fullVector<double> dxyzdXbar(3), dxyzdYbar(3); for (int j=0; j<numPrimMapNodes; j++) { - dxyzdXbar(0) += primGradShapeBarX(j)*nodesXYZ(j,0); - dxyzdXbar(1) += primGradShapeBarX(j)*nodesXYZ(j,1); - dxyzdXbar(2) += primGradShapeBarX(j)*nodesXYZ(j,2); - dxyzdYbar(0) += primGradShapeBarY(j)*nodesXYZ(j,0); - dxyzdYbar(1) += primGradShapeBarY(j)*nodesXYZ(j,1); - dxyzdYbar(2) += primGradShapeBarY(j)*nodesXYZ(j,2); + dxyzdXbar(0) += primGradShapeBarycenterX(j)*nodesXYZ(j,0); + dxyzdXbar(1) += primGradShapeBarycenterX(j)*nodesXYZ(j,1); + dxyzdXbar(2) += primGradShapeBarycenterX(j)*nodesXYZ(j,2); + dxyzdYbar(0) += primGradShapeBarycenterY(j)*nodesXYZ(j,0); + dxyzdYbar(1) += primGradShapeBarycenterY(j)*nodesXYZ(j,1); + dxyzdYbar(2) += primGradShapeBarycenterY(j)*nodesXYZ(j,2); } result(0,2) = dxyzdXbar(0) * dxyzdYbar(1) - dxyzdXbar(1) * dxyzdYbar(0); @@ -202,15 +197,15 @@ double JacobianBasis::getPrimJac3D(const fullMatrix<double> &nodesXYZ) const double dxdX = 0, dydX = 0, dzdX = 0, dxdY = 0, dydY = 0, dzdY = 0, dxdZ = 0, dydZ = 0, dzdZ = 0; for (int j=0; j<numPrimMapNodes; j++) { - dxdX += primGradShapeBarX(j)*nodesXYZ(j,0); - dydX += primGradShapeBarX(j)*nodesXYZ(j,1); - dzdX += primGradShapeBarX(j)*nodesXYZ(j,2); - dxdY += primGradShapeBarY(j)*nodesXYZ(j,0); - dydY += primGradShapeBarY(j)*nodesXYZ(j,1); - dzdY += primGradShapeBarY(j)*nodesXYZ(j,2); - dxdZ += primGradShapeBarZ(j)*nodesXYZ(j,0); - dydZ += primGradShapeBarZ(j)*nodesXYZ(j,1); - dzdZ += primGradShapeBarZ(j)*nodesXYZ(j,2); + dxdX += primGradShapeBarycenterX(j)*nodesXYZ(j,0); + dydX += primGradShapeBarycenterX(j)*nodesXYZ(j,1); + dzdX += primGradShapeBarycenterX(j)*nodesXYZ(j,2); + dxdY += primGradShapeBarycenterY(j)*nodesXYZ(j,0); + dydY += primGradShapeBarycenterY(j)*nodesXYZ(j,1); + dzdY += primGradShapeBarycenterY(j)*nodesXYZ(j,2); + dxdZ += primGradShapeBarycenterZ(j)*nodesXYZ(j,0); + dydZ += primGradShapeBarycenterZ(j)*nodesXYZ(j,1); + dzdZ += primGradShapeBarycenterZ(j)*nodesXYZ(j,2); } return fabs(calcDet3D(dxdX,dydX,dzdX,dxdY,dydY,dzdY,dxdZ,dydZ,dzdZ)); @@ -577,3 +572,111 @@ void JacobianBasis::getSignedJacobian(const fullMatrix<double> &nodesX, const fu } } + +fullMatrix<double> JacobianBasis::generateJacMonomialsPyramid(int order) +{ + int nbMonomials = (order+3)*((order+3)+1)*(2*(order+3)+1)/6 - 5; + fullMatrix<double> monomials(nbMonomials, 3); + + if (order == 0) { + fullMatrix<double> prox, quad = gmshGenerateMonomialsQuadrangle(2); + prox.setAsProxy(monomials, 0, 2); + prox.setAll(quad); + return monomials; + } + + monomials(0, 0) = 0; + monomials(0, 1) = 0; + monomials(0, 2) = 0; + + monomials(1, 0) = order+2; + monomials(1, 1) = 0; + monomials(1, 2) = 0; + + monomials(2, 0) = order+2; + monomials(2, 1) = order+2; + monomials(2, 2) = 0; + + monomials(3, 0) = 0; + monomials(3, 1) = order+2; + monomials(3, 2) = 0; + + monomials(4, 0) = 0; + monomials(4, 1) = 0; + monomials(4, 2) = order; + + monomials(5, 0) = 2; + monomials(5, 1) = 0; + monomials(5, 2) = order; + + monomials(6, 0) = 2; + monomials(6, 1) = 2; + monomials(6, 2) = order; + + monomials(7, 0) = 0; + monomials(7, 1) = 2; + monomials(7, 2) = order; + + int index = 8; + + static const int bottom_edges[8][2] = { + {0, 1}, + {1, 2}, + {2, 3}, + {3, 0} + }; + + // bottom "edges" + for (int iedge = 0; iedge < 4; ++iedge) { + int i0 = bottom_edges[iedge][0]; + int i1 = bottom_edges[iedge][1]; + + int u_1 = (monomials(i1,0)-monomials(i0,0)) / (order + 2); + int u_2 = (monomials(i1,1)-monomials(i0,1)) / (order + 2); + + for (int i = 1; i < order + 2; ++i, ++index) { + monomials(index, 0) = monomials(i0, 0) + i * u_1; + monomials(index, 1) = monomials(i0, 1) + i * u_2; + monomials(index, 2) = 0; + } + } + + // top "edges" + for (int iedge = 0; iedge < 4; ++iedge, ++index) { + int i0 = bottom_edges[iedge][0] + 4; + int i1 = bottom_edges[iedge][1] + 4; + + int u_1 = (monomials(i1,0)-monomials(i0,0)) / 2; + int u_2 = (monomials(i1,1)-monomials(i0,1)) / 2; + + monomials(index, 0) = monomials(i0, 0) + u_1; + monomials(index, 1) = monomials(i0, 1) + u_2; + monomials(index, 2) = monomials(i0, 2); + } + + // bottom "face" + fullMatrix<double> uv = gmshGenerateMonomialsQuadrangle(order); + uv.add(1); + for (int i = 0; i < uv.size1(); ++i, ++index) { + monomials(index, 0) = uv(i, 0); + monomials(index, 1) = uv(i, 1); + monomials(index, 2) = 0; + } + + // top "face" + monomials(index, 0) = 1; + monomials(index, 1) = 1; + monomials(index, 2) = order; + ++index; + + // other monomials + for (int k = 1; k < order; ++k) { + fullMatrix<double> uv = gmshGenerateMonomialsQuadrangle(order + 2 - k); + for (int i = 0; i < uv.size1(); ++i, ++index) { + monomials(index, 0) = uv(i, 0); + monomials(index, 1) = uv(i, 1); + monomials(index, 2) = k; + } + } + return monomials; +} diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h index b38e78aa73dba7b8e19f1a5442a4c977172c3eb5..df8ebac767eb7df3b1e782d8d7fa8cd6f8664c30 100644 --- a/Numeric/JacobianBasis.h +++ b/Numeric/JacobianBasis.h @@ -15,11 +15,14 @@ class JacobianBasis { private: const bezierBasis *bezier; + fullMatrix<double> lagPoints; // sampling point fullMatrix<double> gradShapeMatX, gradShapeMatY, gradShapeMatZ; - fullVector<double> primGradShapeBarX, primGradShapeBarY, primGradShapeBarZ; + fullVector<double> primGradShapeBarycenterX, primGradShapeBarycenterY, primGradShapeBarycenterZ; fullMatrix<double> matrixPrimJac2Jac; // Lifts Lagrange basis of primary Jac. to Lagrange basis of Jac. - int numJacNodes, numMapNodes, numPrimJacNodes, numPrimMapNodes; + + int numJacNodes, numPrimJacNodes; + int numMapNodes, numPrimMapNodes; public : JacobianBasis(int tag); @@ -62,6 +65,17 @@ class JacobianBasis { inline void subDivisor(const fullVector<double> &bez, fullVector<double> &result) const { bezier->subDivisor.mult(bez,result); } + + // + static fullMatrix<double> generateJacMonomialsPyramid(int order); + static inline fullMatrix<double> generateJacPointsPyramid(int order) { + fullMatrix<double> points = generateJacMonomialsPyramid(order); + + if (order == 0) return points; + + points.scale(1. / (order+2.)); + return points; + } }; #endif