diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp index 9c854dd6ac88a8db686a4b85b9c2b86252092171..75a030c7d26673fc90f0b733246fdc211ea00529 100644 --- a/Numeric/polynomialBasis.cpp +++ b/Numeric/polynomialBasis.cpp @@ -13,6 +13,7 @@ #include "GmshMessage.h" #include "polynomialBasis.h" #include "GaussIntegration.h" +#include <limits> static void printClosure(polynomialBasis::clCont &fullClosure, std::vector<int> &closureRef, polynomialBasis::clCont &closures) @@ -1239,6 +1240,138 @@ static void generateFaceClosureTetFull(polynomialBasis::clCont &closureFull, } } +void rotateHex(int iFace, int iRot, int iSign, double uI, double vI, double &uO, double &vO, double &wO) +{ + if (iSign<0){ + double tmp=uI; + uI=vI; + vI=tmp; + } + for (int i=0; i < iRot; i++){ + double tmp=uI; + uI=-vI; + vI=tmp; + } + switch (iFace) { + case 0: uO = vI; vO = uI; wO=-1; break; + case 1: uO = uI; vO = -1; wO=vI; break; + case 2: uO =-1; vO = vI; wO=uI; break; + case 3: uO = 1; vO = uI; wO=vI; break; + case 4: uO =-uI; vO = 1; wO=vI; break; + case 5: uO =uI; vO = vI; wO=1; break; + } +} + +void rotateHexFull(int iFace, int iRot, int iSign, double uI, double vI, double wI, double &uO, double &vO, double &wO) +{ + switch (iFace) { + case 0: uO = uI; vO = vI; wO = wI; break; + case 1: uO = wI; vO = uI; wO = vI; break; + case 2: uO = vI; vO = wI; wO = uI; break; + case 3: uO = wI; vO = vI; wO =-uI; break; + case 4: uO = wI; vO =-uI; wO =-vI; break; + case 5: uO = vI; vO = uI; wO =-wI; break; + } + for (int i = 0; i < iRot; i++){ + double tmp = uO; + uO = -vO; + vO = tmp; + } + if (iSign<0){ + double tmp = uO; + uO = vO; + vO = tmp; + } +} + +inline static double pow2(double x) +{ + return x * x; +} + +/* +static void checkClosure(int tag) { + printf("TYPE = %i\n", tag); + const polynomialBasis &fs = *polynomialBases::find(tag); + for (int i = 0; i < fs.closures.size(); ++i) { + const std::vector<int> &clRef = fs.closures[fs.closureRef[i]]; + const std::vector<int> &cl = fs.closures[i]; + const std::vector<int> &clFull = fs.fullClosures[i]; + printf("i = %i\n", i); + for (int j = 0; j < cl.size(); ++j) { + printf("%3i ", clFull[clRef[j]]); + } + printf("\n"); + for (int j = 0; j < cl.size(); ++j) { + printf("%3i ", cl[j]); + } + printf("\n"); + } +} +*/ + +static void generateFaceClosureHex(polynomialBasis::clCont &closure, int order, bool serendip, const fullMatrix<double> &points) +{ + closure.clear(); + const polynomialBasis &fsFace = *polynomialBases::find(polynomialBasis::getTag(TYPE_QUA, order, serendip)); + for (int iRotate = 0; iRotate < 4; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 6; iFace++) { + polynomialBasis::closure cl; + cl.type = fsFace.type; + cl.resize(fsFace.points.size1()); + for (int iNode = 0; iNode < cl.size(); ++iNode) { + double u,v,w; + rotateHex(iFace, iRotate, iSign, fsFace.points(iNode, 0), fsFace.points(iNode, 1), u, v, w); + cl[iNode] = 0; + double D = std::numeric_limits<double>::max(); + for (int jNode = 0; jNode < points.size1(); ++jNode) { + double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + pow2(points(jNode, 2) - w); + if (d < D) { + cl[iNode] = jNode; + D = d; + } + } + } + closure.push_back(cl); + } + } + } +} + +static void generateFaceClosureHexFull(polynomialBasis::clCont &closure, + std::vector<int> &closureRef, + int order, bool serendip, const fullMatrix<double> &points) +{ + closure.clear(); + int clId = 0; + for (int iRotate = 0; iRotate < 4; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 6; iFace++) { + polynomialBasis::closure cl; + cl.resize(points.size1()); + for (int iNode = 0; iNode < points.size1(); ++iNode) { + double u,v,w; + rotateHexFull(iFace, iRotate, iSign, points(iNode, 0), points(iNode, 1), points(iNode, 2), u, v, w); + int J = 0; + double D = std::numeric_limits<double>::max(); + for (int jNode = 0; jNode < points.size1(); ++jNode) { + double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + pow2(points(jNode, 2) - w); + if (d < D) { + J = jNode; + D = d; + } + } + cl[J] = iNode; + } + closure.push_back(cl); + closureRef.push_back(0); + clId ++; + } + } + } +} + static void getFaceClosurePrism(int iFace, int iSign, int iRotate, polynomialBasis::closure &closure, int order) { @@ -1575,8 +1708,8 @@ const polynomialBasis *polynomialBases::find(int tag) F.dimension = 3; F.monomials = generatePascalHex(F.order, F.serendip); F.points = gmshGeneratePointsHex(F.order, F.serendip); - // generateFaceClosureHex(F.closures, F.order); - // generateFaceClosureHexFull(F.fullClosures, F.closureRef, F.order, F.serendip); + generateFaceClosureHex(F.closures, F.order, F.serendip, F.points); + generateFaceClosureHexFull(F.fullClosures, F.closureRef, F.order, F.serendip, F.points); break; } F.coefficients = generateLagrangeMonomialCoefficients(F.monomials, F.points);