GradientBasis::GradientBasis(int tag, int order) { const int type = ElementType::ParentTypeFromTag(tag); fullMatrix<double> samplingPoints; switch (type) { case TYPE_PNT : samplingPoints = gmshGeneratePointsLine(0); break; case TYPE_LIN : samplingPoints = gmshGeneratePointsLine(order); break; case TYPE_TRI : samplingPoints = gmshGeneratePointsTriangle(order,false); break; case TYPE_QUA : samplingPoints = gmshGeneratePointsQuadrangle(order,false); break; case TYPE_TET : samplingPoints = gmshGeneratePointsTetrahedron(order,false); break; case TYPE_PRI : samplingPoints = gmshGeneratePointsPrism(order,false); break; case TYPE_HEX : samplingPoints = gmshGeneratePointsHexahedron(order,false); break; case TYPE_PYR : samplingPoints = gmshGeneratePointsPyramidGeneral(false, order+2, order); break; default : Msg::Error("Unknown Jacobian function space for element tag %d", tag); return; } const int numSampPnts = samplingPoints.size1(); // Store shape function gradients of mapping at Jacobian nodes fullMatrix<double> allDPsi; const nodalBasis *mapBasis = BasisFactory::getNodalBasis(tag); mapBasis->df(samplingPoints, allDPsi); const int numMapNodes = allDPsi.size1(); gradShapeMatX.resize(numSampPnts, numMapNodes); gradShapeMatY.resize(numSampPnts, numMapNodes); gradShapeMatZ.resize(numSampPnts, numMapNodes); for (int i=0; i<numSampPnts; 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); } } }
void bezierBasis::_construct(int parentType, int p) { order = p; fullMatrix<double> exponents; std::vector< fullMatrix<double> > subPoints; if (parentType == TYPE_PYR) { dim = 3; numLagCoeff = 8; exponents = JacobianBasis::generateJacMonomialsPyramid(order); subPoints = generateSubPointsPyr(order); numDivisions = static_cast<int>(subPoints.size()); fullMatrix<double> bezierPoints = exponents; bezierPoints.scale(1. / (order + 2)); matrixBez2Lag = generateBez2LagMatrixPyramid(exponents, bezierPoints, order); matrixBez2Lag.invert(matrixLag2Bez); subDivisor = generateSubDivisorPyramid(exponents, subPoints, matrixLag2Bez, order); return; } int dimSimplex; switch (parentType) { case TYPE_PNT : dim = 0; numLagCoeff = 1; dimSimplex = 0; exponents = gmshGenerateMonomialsLine(0); subPoints.push_back(gmshGeneratePointsLine(0)); break; case TYPE_LIN : { dim = 1; numLagCoeff = 2; dimSimplex = 0; exponents = gmshGenerateMonomialsLine(order); subPoints = generateSubPointsLine(order); break; } case TYPE_TRI : { dim = 2; numLagCoeff = 3; dimSimplex = 2; exponents = gmshGenerateMonomialsTriangle(order); subPoints = generateSubPointsTriangle(order); break; } case TYPE_QUA : { dim = 2; numLagCoeff = 4; dimSimplex = 0; exponents = gmshGenerateMonomialsQuadrangle(order); subPoints = generateSubPointsQuad(order); break; } case TYPE_TET : { dim = 3; numLagCoeff = 4; dimSimplex = 3; exponents = gmshGenerateMonomialsTetrahedron(order); subPoints = generateSubPointsTetrahedron(order); break; } case TYPE_PRI : { dim = 3; numLagCoeff = 6; dimSimplex = 2; exponents = gmshGenerateMonomialsPrism(order); subPoints = generateSubPointsPrism(order); break; } case TYPE_HEX : { dim = 3; numLagCoeff = 8; dimSimplex = 0; exponents = gmshGenerateMonomialsHexahedron(order); subPoints = generateSubPointsHex(order); break; } default : { Msg::Error("Unknown function space of parentType %d : " "reverting to TET_1", parentType); dim = 3; order = 0; numLagCoeff = 4; dimSimplex = 3; exponents = gmshGenerateMonomialsTetrahedron(order); subPoints = generateSubPointsTetrahedron(order); break; } } numDivisions = static_cast<int>(subPoints.size()); fullMatrix<double> bezierPoints = exponents; bezierPoints.scale(1./order); matrixBez2Lag = generateBez2LagMatrix(exponents, bezierPoints, order, dimSimplex); matrixBez2Lag.invert(matrixLag2Bez); subDivisor = generateSubDivisor(exponents, subPoints, matrixLag2Bez, order, dimSimplex); }
JacobianBasis::JacobianBasis(int tag, int jacOrder) : _bezier(NULL), _tag(tag), _dim(ElementType::DimensionFromTag(tag)), _jacOrder(jacOrder >= 0 ? jacOrder : jacobianOrder(tag)) { const int parentType = ElementType::ParentTypeFromTag(tag); const int primJacobianOrder = jacobianOrder(parentType, 1); fullMatrix<double> lagPoints; // Sampling points switch (parentType) { case TYPE_PNT : lagPoints = gmshGeneratePointsLine(0); break; case TYPE_LIN : lagPoints = gmshGeneratePointsLine(_jacOrder); break; case TYPE_TRI : lagPoints = gmshGeneratePointsTriangle(_jacOrder,false); break; case TYPE_QUA : lagPoints = gmshGeneratePointsQuadrangle(_jacOrder,false); break; case TYPE_TET : lagPoints = gmshGeneratePointsTetrahedron(_jacOrder,false); break; case TYPE_PRI : lagPoints = gmshGeneratePointsPrism(_jacOrder,false); break; case TYPE_HEX : lagPoints = gmshGeneratePointsHexahedron(_jacOrder,false); break; case TYPE_PYR : lagPoints = gmshGeneratePointsPyramidGeneral(false, _jacOrder+2, _jacOrder); break; default : Msg::Error("Unknown Jacobian function space for element tag %d", tag); return; } numJacNodes = lagPoints.size1(); // Store shape function gradients of mapping at Jacobian nodes _gradBasis = BasisFactory::getGradientBasis(tag, _jacOrder); // 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); // 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.; double barycenter[3] = {0., 0., 0.}; for (int i = 0; i < numPrimMapNodes; i++) { for (int j = 0; j < primMapBasis->points.size2(); ++j) { barycenter[j] += primMapBasis->points(i, j); } } barycenter[0] /= numPrimMapNodes; barycenter[1] /= numPrimMapNodes; barycenter[2] /= numPrimMapNodes; double (*barDPsi)[3] = new double[numPrimMapNodes][3]; primMapBasis->df(xBar, yBar, zBar, barDPsi); primGradShapeBarycenterX.resize(numPrimMapNodes); primGradShapeBarycenterY.resize(numPrimMapNodes); primGradShapeBarycenterZ.resize(numPrimMapNodes); for (int j=0; j<numPrimMapNodes; j++) { primGradShapeBarycenterX(j) = barDPsi[j][0]; primGradShapeBarycenterY(j) = barDPsi[j][1]; primGradShapeBarycenterZ(j) = barDPsi[j][2]; } delete[] barDPsi; // Compute "fast" Jacobian evaluation matrices (at 1st order nodes + barycenter) numJacNodesFast = numPrimMapNodes+1; fullMatrix<double> lagPointsFast(numJacNodesFast,3); // Sampling points lagPointsFast.copy(primMapBasis->points,0,numPrimMapNodes, 0,primMapBasis->points.size2(),0,0); // 1st order nodes lagPointsFast(numPrimMapNodes,0) = barycenter[0]; // Last point = barycenter lagPointsFast(numPrimMapNodes,1) = barycenter[1]; lagPointsFast(numPrimMapNodes,2) = barycenter[2]; fullMatrix<double> allDPsiFast; const nodalBasis *mapBasis = BasisFactory::getNodalBasis(tag); mapBasis->df(lagPointsFast, allDPsiFast); numMapNodes = mapBasis->getNumShapeFunctions(); gradShapeMatXFast.resize(numJacNodesFast, numMapNodes); gradShapeMatYFast.resize(numJacNodesFast, numMapNodes); gradShapeMatZFast.resize(numJacNodesFast, numMapNodes); for (int i=0; i<numJacNodesFast; i++) { for (int j=0; j<numMapNodes; j++) { gradShapeMatXFast(i, j) = allDPsiFast(j, 3*i); gradShapeMatYFast(i, j) = allDPsiFast(j, 3*i+1); gradShapeMatZFast(i, j) = allDPsiFast(j, 3*i+2); } } }