diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp index c17b913e65caf5c6d276fdaf934bb1c5c4a642d1..4bb15f44193a3fbe09ede3e2c9f9289bb7182f11 100644 --- a/Common/Gmsh.cpp +++ b/Common/Gmsh.cpp @@ -246,40 +246,84 @@ int GmshBatch() if (false) { // 11/06/13 : This will be removed later ! + std::vector<int> compare; + std::vector<int> test; for (int i = 1; i < MSH_NUM_TYPE+1; ++i) { if (i == 76 || i == 77 || i == 78) continue; + + const char **name = new const char*[1]; + MElement::getInfoMSH(i, name); + if (i == 67 || i == 68 || i == 70) { - Msg::Warning("ignoring unknown %d", i); - continue; - } - if (MElement::ParentTypeFromTag(i) == TYPE_PRI && MElement::OrderFromTag(i) > 2) { - Msg::Warning("ignoring prism %d (different implementation)", i); + Msg::Info("ignoring unknown %d", i); continue; } - if (MElement::ParentTypeFromTag(i) == TYPE_PYR) { - if (i > 124 && i < 132) { - Msg::Warning("ignoring serendipity pyramid %d (bug in Bergot implementation)", i); - continue; - } - } if (MElement::ParentTypeFromTag(i) == TYPE_POLYG) { - Msg::Warning("ignoring polygone %d", i); + Msg::Info("ignoring polygone %d", i); continue; } if (MElement::ParentTypeFromTag(i) == TYPE_POLYH) { - Msg::Warning("ignoring polyhŹdre %d", i); + Msg::Info("ignoring polyhedre %d", i); continue; } if (MElement::ParentTypeFromTag(i) == TYPE_XFEM) { - Msg::Warning("ignoring xfem %d", i); + Msg::Info("ignoring xfem %d", i); continue; } - const nodalBasis *fs = BasisFactory::getNodalBasis(i); - - if (fs && !fs->compareNewAlgoPointsWithOld() && !fs->serendip) { - fs->compareNewAlgoBaseFunctionsWithOld(); + if (MElement::ParentTypeFromTag(i) == TYPE_PRI && MElement::OrderFromTag(i) > 2) { + Msg::Warning("%d:ignoring %s (different node order)", i, *name); + test.push_back(i); + } + else if (MElement::ParentTypeFromTag(i) == TYPE_PYR && MElement::SerendipityFromTag(i) > 1) { + Msg::Warning("%d:ignoring Serendipity %s (bug in Bergot implementation & new Basis function not implemented)", i, *name); + } + else if (MElement::DimensionFromTag(i) == 3 && MElement::SerendipityFromTag(i) > 1) { + Msg::Warning("%d:ignoring 3D Serendipity : %s (different definition)", i, *name); + test.push_back(i); + } + else { + const nodalBasis *fs = BasisFactory::getNodalBasis(i); + if (fs && !fs->compareNewAlgoPointsWithOld()) { + compare.push_back(i); + } + } + } + Msg::Info(" "); + for (int parent = 1; parent < 12; ++parent) { + for (unsigned int i = 0; i < compare.size(); ++i) { + if (MElement::ParentTypeFromTag(compare[i]) == parent) { + if (parent == TYPE_PYR) { + const char **name = new const char*[1]; + MElement::getInfoMSH(compare[i], name); + Msg::Warning("%d, %s: ignoring, old implementation much better and will be kept", compare[i], *name); + } + else { + const nodalBasis *fs = BasisFactory::getNodalBasis(compare[i]); + fs->compareNewAlgoBaseFunctionsWithOld(); + } + } + } + } + Msg::Info(" "); + Msg::Info("---------------------------"); + for (unsigned int i = 0; i < test.size(); ++i) { + const char **name = new const char*[1]; + MElement::getInfoMSH(test[i], name); + //Msg::Info("%d, %s:", test[i], *name); + const nodalBasis *fs = BasisFactory::getNodalBasis(test[i]); + } + Msg::Info("---------------------------"); + for (int parent = 1; parent < 12; ++parent) { + for (unsigned int i = 0; i < test.size(); ++i) { + if (MElement::ParentTypeFromTag(test[i]) == parent) { + const nodalBasis *fs = BasisFactory::getNodalBasis(test[i]); + /*const char **name = new const char*[1]; + MElement::getInfoMSH(test[i], name); + Msg::Warning("%d, %s: untested !", test[i], *name);*/ + fs->testNewAlgoBaseFunctions(); + } } } } diff --git a/Numeric/nodalBasis.cpp b/Numeric/nodalBasis.cpp index 5856ae2a099b5a7b357546aeac7c8534edd43ed1..2e1a2d0db543907ab0f20d3e95cefa428746cafe 100644 --- a/Numeric/nodalBasis.cpp +++ b/Numeric/nodalBasis.cpp @@ -15,7 +15,7 @@ int nodalBasis::compareNewAlgoPointsWithOld() const const char **name = new const char*[1]; MElement::getInfoMSH(type, name); if (points_newAlgo.size1() == 0) { - Msg::Warning("%d: pas de points (%d, %d, %d) %s", type, parentType, serendip, order, *name); + Msg::Error("%d: pas de points (%d, %d, %d) %s", type, parentType, serendip, order, *name); return 1; } if (points_newAlgo.size1() != points.size1()) { @@ -92,23 +92,70 @@ int nodalBasis::compareNewAlgoBaseFunctionsWithOld() const sumOne[1] += newVal[j]; } sumError = std::sqrt(sumError/ndof); - /*if (sumError > 1e-4) { + /*if (sumError > 1e-5) { Msg::Error("(%.2f, %.2f, %.2f) -> fold=%.2e / fnew=%.2e", P[0] / 1000., P[1] / 1000., P[2] / 1000., sumOne[0], sumOne[1]); //for (int j = 0; j < ndof; ++j) { // Msg::Info("old %.3e vs %.3e new", oldVal[j], newVal[j]); //} }*/ - if (sumError > 1e-13) { - if (type < 10) Msg::Warning(" f(%.2f, %.2f, %.2f) bad precision diff %.2e", P[0] / 1000., P[1] / 1000., P[2] / 1000., sumError); - else if (type < 100) Msg::Warning(" f(%.2f, %.2f, %.2f) bad precision diff %.2e", P[0] / 1000., P[1] / 1000., P[2] / 1000., sumError); - else Msg::Warning(" f(%.2f, %.2f, %.2f) bad precision diff %.2e", P[0] / 1000., P[1] / 1000., P[2] / 1000., sumError); + if (sumError > 1e-5) { + Msg::Error("%d, %s: f(%.2f, %.2f, %.2f) bad precision diff %.2e", type, *name, P[0] / 1000., P[1] / 1000., P[2] / 1000., sumError); + return 1; + } + else if (sumError > 1e-13) { + Msg::Warning("%d, %s: f(%.2f, %.2f, %.2f) bad precision diff %.2e", type, *name, P[0] / 1000., P[1] / 1000., P[2] / 1000., sumError); + return 1; + } + } + return 0; +} + +int nodalBasis::testNewAlgoBaseFunctions() const +{ + const char **name = new const char*[1]; + MElement::getInfoMSH(type, name); + int ndof = points_newAlgo.size1(); + int P[3]; + bool noproblem = true; + for (int i = 0; i < 10; ++i) { + if (i == 0) { + P[0] = 0; + P[1] = 0; + P[2] = 0; + } + else if (i == 1) { + P[0] = 0; + P[1] = 0; + P[2] = 1000; + } + else if (i == 2) { + P[0] = 1000; + P[1] = 0; + P[2] = 0; + } + else { + P[0] = std::rand() % 1001; + P[1] = std::rand() % (1001 - P[0]); + P[2] = std::rand() % (1001 - P[0] - P[1]); + } + + double newVal[ndof]; + fnew(P[0] / 1000., P[1] / 1000., P[2] / 1000., newVal); + + double sumOne = 0; + for (int j = 0; j < ndof; ++j) { + sumOne += newVal[j]; + } + if (sumOne > 1. + 1e-12 || sumOne < 1. - 1e-12) { + noproblem = false; + Msg::Warning("%d, %s: bad precision (%.2f, %.2f, %.2f) -> sum = %.2e (1 + %.2e)", type, *name, P[0] / 1000., P[1] / 1000., P[2] / 1000., sumOne, sumOne-1.); + //for (int j = 0; j < ndof; ++j) { + // Msg::Info(" %d : %.3e", j, newVal[j]); + //} return 1; } - /*else if (type < 10) Msg::Info(" f(%.2f, %.2f, %.2f) ok", P[0] / 1000., P[1] / 1000., P[2] / 1000.); - else if (type < 100) Msg::Info(" f(%.2f, %.2f, %.2f) ok", P[0] / 1000., P[1] / 1000., P[2] / 1000.); - else Msg::Info(" f(%.2f, %.2f, %.2f) ok", P[0] / 1000., P[1] / 1000., P[2] / 1000.); - */ } + if (noproblem) Msg::Info("%d, %s: no problem", type, *name); return 0; } @@ -1477,7 +1524,10 @@ static void generateClosureOrder0(nodalBasis::clCont &closure, int nb) nodalBasis::nodalBasis(int tag) { type = tag; - + parentType = MElement::ParentTypeFromTag(tag); + order = MElement::OrderFromTag(tag); + serendip = MElement::SerendipityFromTag(tag) > 1; + /* switch (tag) { case MSH_PNT : parentType = TYPE_PNT; order = 0; serendip = false; break; case MSH_LIN_1 : parentType = TYPE_LIN; order = 0; serendip = false; break; @@ -1584,6 +1634,7 @@ nodalBasis::nodalBasis(int tag) case MSH_HEX_296 : parentType = TYPE_HEX; order = 7; serendip = true; break; case MSH_HEX_386 : parentType = TYPE_HEX; order = 8; serendip = true; break; case MSH_HEX_488 : parentType = TYPE_HEX; order = 9; serendip = true; break; + case MSH_PYR_1 : parentType = TYPE_PYR; order = 0; serendip = false; break; case MSH_PYR_5 : parentType = TYPE_PYR; order = 1; serendip = false; break; case MSH_PYR_14 : parentType = TYPE_PYR; order = 2; serendip = false; break; case MSH_PYR_30 : parentType = TYPE_PYR; order = 3; serendip = false; break; @@ -1605,7 +1656,7 @@ nodalBasis::nodalBasis(int tag) Msg::Error("Unknown function space %d: reverting to TET_4", tag); parentType = TYPE_TET; order = 1; serendip = false; break; } - + */ switch (parentType) { case TYPE_PNT : diff --git a/Numeric/nodalBasis.h b/Numeric/nodalBasis.h index c7339acca791daeb6f1f5bcdfeadc80bb98d0009..d9d48e911b79a7f8d0a7b5bf45d311cccb543da5 100644 --- a/Numeric/nodalBasis.h +++ b/Numeric/nodalBasis.h @@ -34,6 +34,7 @@ class nodalBasis { int compareNewAlgoPointsWithOld() const; int compareNewAlgoBaseFunctionsWithOld() const; + int testNewAlgoBaseFunctions() const; // closures is the list of the nodes of each face, in the order of // the polynomialBasis of the face; fullClosures is mapping of the diff --git a/Numeric/pointsGenerators.cpp b/Numeric/pointsGenerators.cpp index 20ff853be9a7ab268b727ef4d781de09f336fa0f..b56dea53126e5c53da73cf6943a30dfa8a3c353c 100644 --- a/Numeric/pointsGenerators.cpp +++ b/Numeric/pointsGenerators.cpp @@ -27,782 +27,103 @@ void getDoubleMonomials(fullMatrix<double>& doubleMon, } } -/* --- Lines --- */ +// Points Generators fullMatrix<double> gmshGeneratePointsLine(int order) { - fullMatrix<double> points(order + 1, 1); - points(0,0) = 0; - if (order > 0) { - points(0, 0) = -1.; - points(1, 0) = 1.; - double dd = 2. / order; - for (int i = 2; i < order + 1; i++) points(i, 0) = -1. + dd * (i - 1); - } + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsLine, order, false); + + if (order == 0) return points; + + points.scale(2./order); + points.add(-1.); return points; } -/* --- Triangles --- */ - fullMatrix<double> gmshGeneratePointsTriangle(int order, bool serendip) { - int nbPoints = serendip ? 3 * order : (order + 1) * (order + 2) / 2; - fullMatrix<double> points(nbPoints, 2); - - points(0, 0) = 0; - points(0, 1) = 0; - - if (order > 0) { - double dd = 1. / order; - - points(1, 0) = 1; - points(1, 1) = 0; - points(2, 0) = 0; - points(2, 1) = 1; - - int index = 3; - - if (order > 1) { - - double ksi = 0; - double eta = 0; - - for (int i = 0; i < order - 1; i++, index++) { - ksi += dd; - points(index, 0) = ksi; - points(index, 1) = eta; - } - - ksi = 1.; + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsTriangle, order, serendip); - for (int i = 0; i < order - 1; i++, index++) { - ksi -= dd; - eta += dd; - points(index, 0) = ksi; - points(index, 1) = eta; - } - - eta = 1.; - ksi = 0.; - - for (int i = 0; i < order - 1; i++, index++) { - eta -= dd; - points(index, 0) = ksi; - points(index, 1) = eta; - } + if (order == 0) return points; - if (order > 2 && !serendip) { - fullMatrix<double> inner = gmshGeneratePointsTriangle(order - 3, serendip); - inner.scale(1. - 3. * dd); - inner.add(dd); - points.copy(inner, 0, nbPoints - index, 0, 2, index, 0); - } - } - } + points.scale(1./order); return points; } -/* --- Quadrangles --- */ - fullMatrix<double> gmshGeneratePointsQuadrangle(int order, bool serendip) { - int nbPoints = serendip ? order*4 : (order+1)*(order+1); - fullMatrix<double> points(nbPoints, 2); + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsQuadrangle, order, serendip); - if (order > 0) { - points(0, 0) = -1; - points(0, 1) = -1; - points(1, 0) = 1; - points(1, 1) = -1; - points(2, 0) = 1; - points(2, 1) = 1; - points(3, 0) = -1; - points(3, 1) = 1; + if (order == 0) return points; - if (order > 1) { - int index = 4; - const static int edges[4][2]={{0,1},{1,2},{2,3},{3,0}}; - for (int iedge=0; iedge<4; iedge++) { - int p0 = edges[iedge][0]; - int p1 = edges[iedge][1]; - for (int i = 1; i < order; i++, index++) { - points(index, 0) = points(p0, 0) + i*(points(p1,0)-points(p0,0))/order; - points(index, 1) = points(p0, 1) + i*(points(p1,1)-points(p0,1))/order; - } - } - if (order >= 2 && !serendip) { - fullMatrix<double> inner = gmshGeneratePointsQuadrangle(order-2, false); - inner.scale(1. - 2./order); - points.copy(inner, 0, nbPoints - index, 0, 2, index, 0); - } - } - } - else { - points(0, 0) = 0; - points(0, 1) = 0; - } + points.scale(2./order); + points.add(-1.); return points; - - -} - -/* --- Tetahedra --- */ - -static int nbdoftriangle(int order) { return (order + 1) * (order + 2) / 2; } - -//KH : caveat : node coordinates are not yet coherent with node numbering associated -// to numbering of principal vertices of face !!!! - -// uv surface - orientation v0-v2-v1 -static void nodepositionface0(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = 0.; - u[1]= 0.; v[1]= order; w[1] = 0.; - u[2]= order; v[2]= 0.; w[2] = 0.; - - // edges - for (int k = 0; k < (order - 1); k++){ - u[3 + k] = 0.; - v[3 + k] = k + 1; - w[3 + k] = 0.; - - u[3 + order - 1 + k] = k + 1; - v[3 + order - 1 + k] = order - 1 - k ; - w[3 + order - 1 + k] = 0.; - - u[3 + 2 * (order - 1) + k] = order - 1 - k; - v[3 + 2 * (order - 1) + k] = 0.; - w[3 + 2 * (order - 1) + k] = 0.; - } - - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface0(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3* (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3); - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } } -// uw surface - orientation v0-v1-v3 -static void nodepositionface1(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0] = 0.; v[0]= 0.; w[0] = 0.; - u[1] = order; v[1]= 0.; w[1] = 0.; - u[2] = 0.; v[2]= 0.; w[2] = order; - // edges - for (int k = 0; k < (order - 1); k++){ - u[3 + k] = k + 1; - v[3 + k] = 0.; - w[3 + k] = 0.; - - u[3 + order - 1 + k] = order - 1 - k; - v[3 + order - 1 + k] = 0.; - w[3 + order - 1+ k ] = k + 1; - - u[3 + 2 * (order - 1) + k] = 0. ; - v[3 + 2 * (order - 1) + k] = 0.; - w[3 + 2 * (order - 1) + k] = order - 1 - k; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface1(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order -1 )], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3); - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -// vw surface - orientation v0-v3-v2 -static void nodepositionface2(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = 0.; - u[1]= 0.; v[1]= 0.; w[1] = order; - u[2]= 0.; v[2]= order; w[2] = 0.; - // edges - for (int k = 0; k < (order - 1); k++){ - - u[3 + k] = 0.; - v[3 + k] = 0.; - w[3 + k] = k + 1; - - u[3 + order - 1 + k] = 0.; - v[3 + order - 1 + k] = k + 1; - w[3 + order - 1 + k] = order - 1 - k; - - u[3 + 2 * (order - 1) + k] = 0.; - v[3 + 2 * (order - 1) + k] = order - 1 - k; - w[3 + 2 * (order - 1) + k] = 0.; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface2(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3); - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -// uvw surface - orientation v3-v1-v2 -static void nodepositionface3(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = order; - u[1]= order; v[1]= 0.; w[1] = 0.; - u[2]= 0.; v[2]= order; w[2] = 0.; - // edges - for (int k = 0; k < (order - 1); k++){ - - u[3 + k] = k + 1; - v[3 + k] = 0.; - w[3 + k] = order - 1 - k; - - u[3 + order - 1 + k] = order - 1 - k; - v[3 + order - 1 + k] = k + 1; - w[3 + order - 1 + k] = 0.; - - u[3 + 2 * (order - 1) + k] = 0.; - v[3 + 2 * (order - 1) + k] = order - 1 - k; - w[3 + 2 * (order - 1) + k] = k + 1; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface3(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - - fullMatrix<double> gmshGeneratePointsTetrahedron(int order, bool serendip) { + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsTetrahedron, order, serendip); - int nbPoints = - (serendip ? - 4 + 6 * std::max(0, order - 1) + 4 * std::max(0, (order - 2) * (order - 1) / 2) : - (order + 1) * (order + 2) * (order + 3) / 6); - - fullMatrix<double> points(nbPoints, 3); - - double overOrder = (order == 0 ? 1. : 1. / order); - - points(0, 0) = 0.; - points(0, 1) = 0.; - points(0, 2) = 0.; + if (order == 0) return points; - if (order > 0) { - points(1, 0) = order; - points(1, 1) = 0; - points(1, 2) = 0; - - points(2, 0) = 0.; - points(2, 1) = order; - points(2, 2) = 0.; - - points(3, 0) = 0.; - points(3, 1) = 0.; - points(3, 2) = order; - - // edges e5 and e6 switched in original version, opposite direction - // the template has been defined in table edges_tetra and faces_tetra (MElement.h) - - if (order > 1) { - for (int k = 0; k < (order - 1); k++) { - points(4 + k, 0) = k + 1; - points(4 + order - 1 + k, 0) = order - 1 - k; - points(4 + 2 * (order - 1) + k, 0) = 0.; - points(4 + 3 * (order - 1) + k, 0) = 0.; - // points(4 + 4 * (order - 1) + k, 0) = order - 1 - k; - // points(4 + 5 * (order - 1) + k, 0) = 0.; - points(4 + 4 * (order - 1) + k, 0) = 0.; - points(4 + 5 * (order - 1) + k, 0) = k+1; - - points(4 + k, 1) = 0.; - points(4 + order - 1 + k, 1) = k + 1; - points(4 + 2 * (order - 1) + k, 1) = order - 1 - k; - points(4 + 3 * (order - 1) + k, 1) = 0.; - // points(4 + 4 * (order - 1) + k, 1) = 0.; - // points(4 + 5 * (order - 1) + k, 1) = order - 1 - k; - points(4 + 4 * (order - 1) + k, 1) = k+1; - points(4 + 5 * (order - 1) + k, 1) = 0.; - - points(4 + k, 2) = 0.; - points(4 + order - 1 + k, 2) = 0.; - points(4 + 2 * (order - 1) + k, 2) = 0.; - points(4 + 3 * (order - 1) + k, 2) = order - 1 - k; - points(4 + 4 * (order - 1) + k, 2) = order - 1 - k; - points(4 + 5 * (order - 1) + k, 2) = order - 1 - k; - } - - if (order > 2) { - int ns = 4 + 6 * (order - 1); - int nbdofface = nbdoftriangle(order - 3); - - double *u = new double[nbdofface]; - double *v = new double[nbdofface]; - double *w = new double[nbdofface]; - - nodepositionface0(order - 3, u, v, w); - - // u-v plane - - for (int i = 0; i < nbdofface; i++){ - points(ns + i, 0) = u[i] * (order - 3) + 1.; - points(ns + i, 1) = v[i] * (order - 3) + 1.; - points(ns + i, 2) = w[i] * (order - 3); - } - - ns = ns + nbdofface; - - // u-w plane - - nodepositionface1(order - 3, u, v, w); - - for (int i=0; i < nbdofface; i++){ - points(ns + i, 0) = u[i] * (order - 3) + 1.; - points(ns + i, 1) = v[i] * (order - 3) ; - points(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // v-w plane - - ns = ns + nbdofface; - - nodepositionface2(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - points(ns + i, 0) = u[i] * (order - 3); - points(ns + i, 1) = v[i] * (order - 3) + 1.; - points(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // u-v-w plane - - ns = ns + nbdofface; - - nodepositionface3(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - points(ns + i, 0) = u[i] * (order - 3) + 1.; - points(ns + i, 1) = v[i] * (order - 3) + 1.; - points(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - ns = ns + nbdofface; - - delete [] u; - delete [] v; - delete [] w; - - if (!serendip && order > 3) { - - fullMatrix<double> interior = gmshGeneratePointsTetrahedron(order - 4, false); - for (int k = 0; k < interior.size1(); k++) { - points(ns + k, 0) = 1. + interior(k, 0) * (order - 4); - points(ns + k, 1) = 1. + interior(k, 1) * (order - 4); - points(ns + k, 2) = 1. + interior(k, 2) * (order - 4); - } - } - } - } - } - - points.scale(overOrder); + points.scale(1./order); return points; - } - - -/* --- Hexahedra --- */ - fullMatrix<double> gmshGeneratePointsHexahedron(int order, bool serendip) { - int nbPoints = (order+1)*(order+1)*(order+1); - if (serendip) nbPoints -= (order-1)*(order-1)*(order-1); - fullMatrix<double> points(nbPoints, 3); - - // should be a public member of MHexahedron, just copied - static const int edges[12][2] = { - {0, 1}, - {0, 3}, - {0, 4}, - {1, 2}, - {1, 5}, - {2, 3}, - {2, 6}, - {3, 7}, - {4, 5}, - {4, 7}, - {5, 6}, - {6, 7} - }; - static const int faces[6][4] = { - {0, 3, 2, 1}, - {0, 1, 5, 4}, - {0, 4, 7, 3}, - {1, 2, 6, 5}, - {2, 3, 7, 6}, - {4, 5, 6, 7} - }; + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsHexahedron, order, serendip); - if (order > 0) { - points(0, 0) = -1; - points(0, 1) = -1; - points(0, 2) = -1; - points(1, 0) = 1; - points(1, 1) = -1; - points(1, 2) = -1; - points(2, 0) = 1; - points(2, 1) = 1; - points(2, 2) = -1; - points(3, 0) = -1; - points(3, 1) = 1; - points(3, 2) = -1; - - points(4, 0) = -1; - points(4, 1) = -1; - points(4, 2) = 1; - points(5, 0) = 1; - points(5, 1) = -1; - points(5, 2) = 1; - points(6, 0) = 1; - points(6, 1) = 1; - points(6, 2) = 1; - points(7, 0) = -1; - points(7, 1) = 1; - points(7, 2) = 1; + if (order == 0) return points; - if (order > 1) { - int index = 8; - for (int iedge=0; iedge<12; iedge++) { - int p0 = edges[iedge][0]; - int p1 = edges[iedge][1]; - for (int i = 1; i < order; i++, index++) { - points(index, 0) = points(p0, 0) + i*(points(p1,0)-points(p0,0))/order; - points(index, 1) = points(p0, 1) + i*(points(p1,1)-points(p0,1))/order; - points(index, 2) = points(p0, 2) + i*(points(p1,2)-points(p0,2))/order; - } - } - - fullMatrix<double> fp = gmshGeneratePointsQuadrangle(order - 2, false); - fp.scale(1. - 2./order); - for (int iface=0; iface<6; iface++) { - int p0 = faces[iface][0]; - int p1 = faces[iface][1]; - int p2 = faces[iface][2]; - int p3 = faces[iface][3]; - for (int i=0;i<fp.size1();i++, index++){ - const double u = fp(i,0); - const double v = fp(i,1); - const double newU = - 0.25*(1.-u)*(1.-v)*points(p0,0) + - 0.25*(1.+u)*(1.-v)*points(p1,0) + - 0.25*(1.+u)*(1.+v)*points(p2,0) + - 0.25*(1.-u)*(1.+v)*points(p3,0) ; - const double newV = - 0.25*(1.-u)*(1.-v)*points(p0,1) + - 0.25*(1.+u)*(1.-v)*points(p1,1) + - 0.25*(1.+u)*(1.+v)*points(p2,1) + - 0.25*(1.-u)*(1.+v)*points(p3,1) ; - const double newW = - 0.25*(1.-u)*(1.-v)*points(p0,2) + - 0.25*(1.+u)*(1.-v)*points(p1,2) + - 0.25*(1.+u)*(1.+v)*points(p2,2) + - 0.25*(1.-u)*(1.+v)*points(p3,2) ; - points(index, 0) = newU; - points(index, 1) = newV; - points(index, 2) = newW; - } - } - if (!serendip) { - fullMatrix<double> inner = gmshGeneratePointsHexahedron(order - 2, false); - inner.scale(1. - 2./order); - points.copy(inner, 0, nbPoints - index, 0, 3, index, 0); - } - } - } - else if (order == 0){ - points(0, 0) = 0; - points(0, 1) = 0; - points(0, 2) = 0; - } + points.scale(2./order); + points.add(-1.); return points; } -/* --- Prisms --- */ - fullMatrix<double> gmshGeneratePointsPrism(int order, bool serendip) { - const double prism18Pts[18][3] = { - {0, 0, -1}, // 0 - {1, 0, -1}, // 1 - {0, 1, -1}, // 2 - {0, 0, 1}, // 3 - {1, 0, 1}, // 4 - {0, 1, 1}, // 5 - {0.5, 0, -1}, // 6 - {0, 0.5, -1}, // 7 - {0, 0, 0}, // 8 - {0.5, 0.5, -1}, // 9 - {1, 0, 0}, // 10 - {0, 1, 0}, // 11 - {0.5, 0, 1}, // 12 - {0, 0.5, 1}, // 13 - {0.5, 0.5, 1}, // 14 - {0.5, 0, 0}, // 15 - {0, 0.5, 0}, // 16 - {0.5, 0.5, 0}, // 17 - }; - - int nbPoints = (order + 1)*(order + 1)*(order + 2)/2; - fullMatrix<double> points(nbPoints, 3); - - int index = 0; - fullMatrix<double> triPoints = gmshGeneratePointsTriangle(order,false); - fullMatrix<double> linePoints = gmshGeneratePointsLine(order); - - if (order == 2) - for (int i =0; i<18; i++) - for (int j=0; j<3;j++) - points(i,j) = prism18Pts[i][j]; - else - for (int j = 0; j <linePoints.size1() ; j++) { - for (int i = 0; i < triPoints.size1(); i++) { - points(index,0) = triPoints(i,0); - points(index,1) = triPoints(i,1); - points(index,2) = linePoints(j,0); - index ++; - } - } + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsPrism, order, serendip); - return points; + if (order == 0) return points; -} + fullMatrix<double> tmp; + tmp.setAsProxy(points, 0, 2); + tmp.scale(1./order); -/* --- Pyramids --- */ + tmp.setAsProxy(points, 2, 1); + tmp.scale(2./order); + tmp.add(-1.); + + return points; +} fullMatrix<double> gmshGeneratePointsPyramid(int order, bool serendip) { - int nbPoints = (order+1)*((order+1)+1)*(2*(order+1)+1)/6; - - // Remove volume points if incomplete basis - if (serendip && order > 2) nbPoints -= (order-2)*((order-2)+1)*(2*(order-2)+1)/6; - - fullMatrix<double> points(nbPoints, 3); - - static const int edges[8][2] = { - {0, 1}, - {0, 3}, - {0, 4}, - {1, 2}, - {1, 4}, - {2, 3}, - {2, 4}, - {3, 4}, - }; - static const int faces[5][4] = { - {0, 1, 4, -1}, - {3, 0, 4, -1}, - {1, 2, 4, -1}, - {2, 3, 4, -1}, - {0, 3, 2, 1} - }; - - if (order == 0) { - points(0,0) = 0.0; - points(0,1) = 0.0; - points(0,2) = 0.0; - return points; - } - - // Principal vertices of the pyramid - points(0,0) = -1.0; points(0,1) = -1.0; points(0,2) = 0.0; - points(1,0) = 1.0; points(1,1) = -1.0; points(1,2) = 0.0; - points(2,0) = 1.0; points(2,1) = 1.0; points(2,2) = 0.0; - points(3,0) = -1.0; points(3,1) = 1.0; points(3,2) = 0.0; - points(4,0) = 0.0; points(4,1) = 0.0; points(4,2) = 1.0; - - if (order > 1) { - int p = 5; - - // Edges - for (int e = 0; e < 8; e++) { - double vec[3]; - vec[0] = points(edges[e][1],0) - points(edges[e][0],0); - vec[1] = points(edges[e][1],1) - points(edges[e][0],1); - vec[2] = points(edges[e][1],2) - points(edges[e][0],2); - for (int i = 0; i < order - 1; i++) { - points(p,0) = points(edges[e][0],0) + vec[0]/order * (i+1); - points(p,1) = points(edges[e][0],1) + vec[1]/order * (i+1); - points(p,2) = points(edges[e][0],2) + vec[2]/order * (i+1); - p++; - } - } - - // Faces - for (int f = 0; f < 4; f++) { - fullMatrix<double> fp = gmshGeneratePointsTriangle(order, false); - - fullVector<double> u(4); - fullVector<double> v(4); - fullVector<double> w(4); - fullVector<double> y(4); - - fullVector<double> up(4); - fullVector<double> vp(4); - fullVector<double> wp(4); - fullVector<double> yp(4); - - for (int c = 0; c < 3; c++) { - u(c) = fp(0,c); - v(c) = fp(1,c); - w(c) = fp(2,c); - up(c) = points(faces[f][0],c); - vp(c) = points(faces[f][1],c); - wp(c) = points(faces[f][2],c); - } - - u(2) = 0.0; - v(2) = 0.0; - w(2) = 0.0; - u(3) = 1.0; - v(3) = 1.0; - w(3) = 1.0; - - y(0) = u(0) + ((v(1)-u(1))*(w(2)-u(2)) - (v(2)-u(2))*(w(1)-u(1))); - y(1) = u(1) + ((v(2)-u(2))*(w(0)-u(0)) - (v(0)-u(0))*(w(2)-u(2))); - y(2) = u(2) + ((v(0)-u(0))*(w(1)-u(1)) - (v(1)-u(1))*(w(0)-u(0))); - y(3) = 1.0; - - up(3) = 1.0; - vp(3) = 1.0; - wp(3) = 1.0; - - yp(0) = up(0) + ((vp(1)-up(1))*(wp(2)-up(2)) - (vp(2)-up(2))*(wp(1)-up(1))); - yp(1) = up(1) + ((vp(2)-up(2))*(wp(0)-up(0)) - (vp(0)-up(0))*(wp(2)-up(2))); - yp(2) = up(2) + ((vp(0)-up(0))*(wp(1)-up(1)) - (vp(1)-up(1))*(wp(0)-up(0))); - yp(3) = 1.0; - - fullMatrix<double> M(4,4); - fullMatrix<double> Mp(4,4); + fullMatrix<double> points; + getDoubleMonomials(points, gmshGenerateMonomialsPyramid, order, serendip); - M(0,0) = u(0); M(0,1) = v(0); M(0,2) = w(0); M(0,3) = y(0); - M(1,0) = u(1); M(1,1) = v(1); M(1,2) = w(1); M(1,3) = y(1); - M(2,0) = u(2); M(2,1) = v(2); M(2,2) = w(2); M(2,3) = y(2); - M(3,0) = u(3); M(3,1) = v(3); M(3,2) = w(3); M(3,3) = y(3); + if (order == 0) return points; - Mp(0,0) = up(0); Mp(0,1) = vp(0); Mp(0,2) = wp(0); Mp(0,3) = yp(0); - Mp(1,0) = up(1); Mp(1,1) = vp(1); Mp(1,2) = wp(1); Mp(1,3) = yp(1); - Mp(2,0) = up(2); Mp(2,1) = vp(2); Mp(2,2) = wp(2); Mp(2,3) = yp(2); - Mp(3,0) = up(3); Mp(3,1) = vp(3); Mp(3,2) = wp(3); Mp(3,3) = yp(3); - - - M.invertInPlace(); - fullMatrix<double> T(4,4); - Mp.mult(M, T); - - for(int k = 3*order; k < fp.size1(); k++) { - fullVector<double> pnt(4); - pnt(0) = fp(k,0); - pnt(1) = fp(k,1); - pnt(2) = 0.0; - pnt(3) = 1.0; - - fullVector<double> res(4); - T.mult(pnt, res); - - points(p, 0) = res(0); - points(p, 1) = res(1); - points(p, 2) = res(2); - - p++; - - } - } - - fullMatrix<double> fpq = gmshGeneratePointsQuadrangle(order-2, false); - fullMatrix<double> transform(2,2); - fullMatrix<double> scaled(fpq.size1(), fpq.size2()); - transform(0,0) = (order-2)/(double)order; transform(0,1) = 0.0; - transform(1,0) = 0.0; transform(1,1) = (order-2)/(double)order; - fpq.mult(transform, scaled); - - for (int i = 0; i < scaled.size1(); i++) { - points(p, 0) = scaled(i, 1); - points(p, 1) = scaled(i, 0); - points(p, 2) = 0.0; - p++; - } - - // Volume - if (!serendip && order > 2) { - fullMatrix<double> volume_points = gmshGeneratePointsPyramid(order - 3, false); - // scale to order-3/order - fullMatrix<double> T(3,3); - T(0,0) = (order - 3.0) / order; T(0,1) = 0.0; T(0,2) = 0.0; - T(1,0) = 0.0; T(1,1) = (order - 3.0) / order; T(1,2) = 0.0; - T(2,0) = 0.0; T(2,1) = 0.0; T(2,2) = (order - 3.0) / order; - fullMatrix<double> scaled(volume_points.size1(), volume_points.size2()); - volume_points.mult(T, scaled); - - // translate 1/order - for (int i = 0; i < scaled.size1(); i++) { - points(p, 0) = scaled(i,0); - points(p, 1) = scaled(i,1); - points(p, 2) = scaled(i,2) + 1.0/order; - p++; - } - } - } - return points; + for (int i = 0; i < points.size1(); ++i) { + points(i, 2) = points(i, 2) / order; + const double duv = -1. + points(i, 2); + points(i, 0) = duv + points(i, 0) * 2. / order; + points(i, 1) = duv + points(i, 1) * 2. / order; + } + return points; } -fullMatrix<int> gmshGenerateMonomialsLine(int order) +// Monomials Generators + +fullMatrix<int> gmshGenerateMonomialsLine(int order, bool serendip) { fullMatrix<int> monomials(order + 1, 1); monomials(0,0) = 0; @@ -816,6 +137,7 @@ fullMatrix<int> gmshGenerateMonomialsLine(int order) fullMatrix<int> gmshGenerateMonomialsTriangle(int order, bool serendip) { int nbMonomials = serendip ? 3 * order : (order + 1) * (order + 2) / 2; + if (serendip && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 2); monomials(0, 0) = 0; @@ -855,6 +177,7 @@ fullMatrix<int> gmshGenerateMonomialsTriangle(int order, bool serendip) fullMatrix<int> gmshGenerateMonomialsQuadrangle(int order, bool forSerendipPoints) { int nbMonomials = forSerendipPoints ? order*4 : (order+1)*(order+1); + if (forSerendipPoints && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 2); monomials(0, 0) = 0; @@ -895,6 +218,44 @@ fullMatrix<int> gmshGenerateMonomialsQuadrangle(int order, bool forSerendipPoint return monomials; } +fullMatrix<int> gmshGenerateMonomialsQuadSerendipity(int order) +{ + int nbMonomials = order ? order*4 : 1; + fullMatrix<int> monomials(nbMonomials, 2); + + monomials(0, 0) = 0; + monomials(0, 1) = 0; + + if (order > 0) { + monomials(1, 0) = 1; + monomials(1, 1) = 0; + + monomials(2, 0) = 1; + monomials(2, 1) = 1; + + monomials(3, 0) = 0; + monomials(3, 1) = 1; + + if (order > 1) { + int index = 3; + for (int p = 2; p <= order; ++p) { + monomials(++index, 0) = p; + monomials( index, 1) = 0; + + monomials(++index, 0) = p; + monomials( index, 1) = 1; + + monomials(++index, 0) = 1; + monomials( index, 1) = p; + + monomials(++index, 0) = 0; + monomials( index, 1) = p; + } + } + } + return monomials; +} + //KH : caveat : node coordinates are not yet coherent with node numbering associated // to numbering of principal vertices of face !!!! fullMatrix<int> gmshGenerateMonomialsTetrahedron(int order, bool serendip) @@ -904,6 +265,7 @@ fullMatrix<int> gmshGenerateMonomialsTetrahedron(int order, bool serendip) 4 + 6 * std::max(0, order - 1) + 4 * std::max(0, (order - 2) * (order - 1) / 2) : (order + 1) * (order + 2) * (order + 3) / 6); + if (serendip && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 3); monomials(0, 0) = 0; @@ -983,6 +345,7 @@ fullMatrix<int> gmshGenerateMonomialsPrism(int order, bool forSerendipPoints) { int nbMonomials = forSerendipPoints ? 6 + (order-1)*9 : (order + 1) * (order + 1)*(order + 2)/2; + if (forSerendipPoints && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 3); monomials(0, 0) = 0; @@ -1084,10 +447,84 @@ fullMatrix<int> gmshGenerateMonomialsPrism(int order, bool forSerendipPoints) return monomials; } +fullMatrix<int> gmshGenerateMonomialsPrismSerendipity(int order) +{ + int nbMonomials = order ? 6 + (order-1) * 9 : 1; + fullMatrix<int> monomials(nbMonomials, 3); + + monomials(0, 0) = 0; + monomials(0, 1) = 0; + monomials(0, 2) = 0; + + if (order > 0) { + monomials(1, 0) = 1; + monomials(1, 1) = 0; + monomials(1, 2) = 0; + + monomials(2, 0) = 0; + monomials(2, 1) = 1; + monomials(2, 2) = 0; + + monomials(3, 0) = 0; + monomials(3, 1) = 0; + monomials(3, 2) = 1; + + monomials(4, 0) = 1; + monomials(4, 1) = 0; + monomials(4, 2) = 1; + + monomials(5, 0) = 0; + monomials(5, 1) = 1; + monomials(5, 2) = 1; + + if (order > 1) { + const int ind[7][3] = { + {2, 0, 0}, + {2, 0, 1}, + + {0, 2, 0}, + {0, 2, 1}, + + {0, 0, 2}, + {1, 0, 2}, + {0, 1, 2} + }; + int val[3] = {0, 1, -1}; + int index = 5; + for (int p = 2; p <= order; ++p) { + val[2] = p; + for (int i = 0; i < 7; ++i) { + monomials(++index, 0) = val[ind[i][0]]; + monomials( index, 1) = val[ind[i][1]]; + monomials( index, 2) = val[ind[i][2]]; + } + } + + int val0 = 1; + int val1 = order - 1; + for (int p = 2; p <= order; ++p) { + monomials(++index, 0) = val0; + monomials( index, 1) = val1; + monomials( index, 2) = 0; + + monomials(++index, 0) = val0; + monomials( index, 1) = val1; + monomials( index, 2) = 1; + + ++val0; + --val1; + } + } + } + return monomials; +} + + fullMatrix<int> gmshGenerateMonomialsHexahedron(int order, bool forSerendipPoints) { int nbMonomials = forSerendipPoints ? 8 + (order-1)*12 : (order+1)*(order+1)*(order+1); + if (forSerendipPoints && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 3); monomials(0, 0) = 0; @@ -1174,10 +611,83 @@ fullMatrix<int> gmshGenerateMonomialsHexahedron(int order, bool forSerendipPoint return monomials; } + +fullMatrix<int> gmshGenerateMonomialsHexaSerendipity(int order) +{ + int nbMonomials = order ? 8 + (order-1) * 12 : 1; + fullMatrix<int> monomials(nbMonomials, 3); + + monomials(0, 0) = 0; + monomials(0, 1) = 0; + monomials(0, 2) = 0; + + if (order > 0) { + monomials(1, 0) = 1; + monomials(1, 1) = 0; + monomials(1, 2) = 0; + + monomials(2, 0) = 1; + monomials(2, 1) = 1; + monomials(2, 2) = 0; + + monomials(3, 0) = 0; + monomials(3, 1) = 1; + monomials(3, 2) = 0; + + monomials(4, 0) = 0; + monomials(4, 1) = 0; + monomials(4, 2) = 1; + + monomials(5, 0) = 1; + monomials(5, 1) = 0; + monomials(5, 2) = 1; + + monomials(6, 0) = 1; + monomials(6, 1) = 1; + monomials(6, 2) = 1; + + monomials(7, 0) = 0; + monomials(7, 1) = 1; + monomials(7, 2) = 1; + + if (order > 1) { + const int ind[12][3] = { + {2, 0, 0}, + {2, 0, 1}, + {2, 1, 1}, + {2, 1, 0}, + + {0, 2, 0}, + {0, 2, 1}, + {1, 2, 1}, + {1, 2, 0}, + + {0, 0, 2}, + {0, 1, 2}, + {1, 1, 2}, + {1, 0, 2} + }; + int val[3] = {0, 1, -1}; + int index = 7; + for (int p = 2; p <= order; ++p) { + val[2] = p; + for (int i = 0; i < 12; ++i) { + monomials(++index, 0) = val[ind[i][0]]; + monomials( index, 1) = val[ind[i][1]]; + monomials( index, 2) = val[ind[i][2]]; + } + } + } + } + return monomials; +} + + fullMatrix<int> gmshGenerateMonomialsPyramid(int order, bool forSerendipPoints) { int nbMonomials = forSerendipPoints ? 5 + (order-1)*8 : (order+1)*((order+1)+1)*(2*(order+1)+1)/6; + if (forSerendipPoints && !order) nbMonomials = 1; fullMatrix<int> monomials(nbMonomials, 3); monomials(0, 0) = 0; diff --git a/Numeric/pointsGenerators.h b/Numeric/pointsGenerators.h index 9529cefff67313747e2686d3b7b8b1f53b648e73..dc47ba71897d108fa54e2961a7ef974c48e2e0d4 100644 --- a/Numeric/pointsGenerators.h +++ b/Numeric/pointsGenerators.h @@ -32,17 +32,17 @@ fullMatrix<double> gmshGeneratePointsPyramid(int order, bool serendip); // Monomial exponents -fullMatrix<int> gmshGenerateMonomialsLine(int order); +fullMatrix<int> gmshGenerateMonomialsLine(int order, bool serendip = false); fullMatrix<int> gmshGenerateMonomialsTriangle(int order, bool serendip = false); fullMatrix<int> gmshGenerateMonomialsQuadrangle(int order, bool forSerendipPoints = false); -//fullMatrix<int> gmshGenerateMonomialsQuadSerendipity(int order); //FIXME +fullMatrix<int> gmshGenerateMonomialsQuadSerendipity(int order); fullMatrix<int> gmshGenerateMonomialsTetrahedron(int order, bool serendip = false); fullMatrix<int> gmshGenerateMonomialsHexahedron(int order, bool forSerendipPoints = false); -//fullMatrix<int> gmshGenerateMonomialsHexaSerendipity(int order); //FIXME +fullMatrix<int> gmshGenerateMonomialsHexaSerendipity(int order); fullMatrix<int> gmshGenerateMonomialsPrism(int order, bool forSerendipPoints = false); -//fullMatrix<int> gmshGenerateMonomialsPrismSerendipity(int order); //FIXME +fullMatrix<int> gmshGenerateMonomialsPrismSerendipity(int order); fullMatrix<int> gmshGenerateMonomialsPyramid(int order, bool forSerendipPoints = false); //fullMatrix<int> gmshGenerateMonomialsPyramidSerendipity(int order); //FIXME diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp index 50dfccdf826bbc320942e982a4510b846871a1af..5a7b626b9b19ced3fbdd8f3121678f92b4a081c5 100644 --- a/Numeric/polynomialBasis.cpp +++ b/Numeric/polynomialBasis.cpp @@ -433,7 +433,7 @@ static fullMatrix<double> generateLagrangeMonomialCoefficients max = std::max(max, std::abs(unity(i, j))); } } - if (max > 1e-10) Msg::Info(" max unity = %.3e", max); + //if (max > 1e-10) Msg::Info(" max unity = %.3e", max); return coefficient; } @@ -481,60 +481,47 @@ polynomialBasis::polynomialBasis(int tag) : nodalBasis(tag) coefficients = generateLagrangeMonomialCoefficients(monomials, points); - // TEST NEW ALGO POINTS / MONOMIALS + // NEW ALGO POINTS / MONOMIALS - int rescale = 0; switch (parentType) { case TYPE_PNT : + points_newAlgo = gmshGeneratePointsLine(0); monomials_newAlgo = gmshGenerateMonomialsLine(0); break; case TYPE_LIN : + points_newAlgo = gmshGeneratePointsLine(order); monomials_newAlgo = gmshGenerateMonomialsLine(order); - rescale = 1; break; case TYPE_TRI : + points_newAlgo = gmshGeneratePointsTriangle(order, serendip); monomials_newAlgo = gmshGenerateMonomialsTriangle(order, serendip); break; case TYPE_QUA : - monomials_newAlgo = gmshGenerateMonomialsQuadrangle(order, serendip); - rescale = 1; + points_newAlgo = gmshGeneratePointsQuadrangle(order, serendip); + if (!serendip) + monomials_newAlgo = gmshGenerateMonomialsQuadrangle(order); + else + monomials_newAlgo = gmshGenerateMonomialsQuadSerendipity(order); break; case TYPE_TET : + points_newAlgo = gmshGeneratePointsTetrahedron(order, serendip); monomials_newAlgo = gmshGenerateMonomialsTetrahedron(order, serendip); break; case TYPE_HEX : - monomials_newAlgo = gmshGenerateMonomialsHexahedron(order, serendip); - rescale = 1; + points_newAlgo = gmshGeneratePointsHexahedron(order, serendip); + if (!serendip) + monomials_newAlgo = gmshGenerateMonomialsHexahedron(order); + else + monomials_newAlgo = gmshGenerateMonomialsHexaSerendipity(order); break; case TYPE_PRI : - monomials_newAlgo = gmshGenerateMonomialsPrism(order, serendip); - rescale = 2; + points_newAlgo = gmshGeneratePointsPrism(order, serendip); + if (!serendip) + monomials_newAlgo = gmshGenerateMonomialsPrism(order); + else + monomials_newAlgo = gmshGenerateMonomialsPrismSerendipity(order); break; } - copy(monomials_newAlgo, points_newAlgo); - //if (order == 0) return; - switch (rescale) { - case 0 : - points_newAlgo.scale(1./order); - break; - case 1 : - points_newAlgo.scale(2./order); - points_newAlgo.add(-1.); - break; - case 2 : - { - fullMatrix<double> tmp; - tmp.setAsProxy(points_newAlgo, 0, 2); - tmp.scale(1./order); - - tmp.setAsProxy(points_newAlgo, 2, 1); - tmp.scale(2./order); - tmp.add(-1.); - break; - } - default : - break; - } fullMatrix<double> monDouble; switch (parentType) { @@ -551,6 +538,7 @@ polynomialBasis::polynomialBasis(int tag) : nodalBasis(tag) /*else*/ copy(monomials_newAlgo, monDouble); break; } + coefficients_newAlgo = generateLagrangeMonomialCoefficients(monDouble, points_newAlgo); } diff --git a/Numeric/pyramidalBasis.cpp b/Numeric/pyramidalBasis.cpp index 888752d749e907a55c55fd94f7d54bd4cf7ddc2d..1ee2fd4a0a0b9111e89c4091a0c94e53e17cbeac 100644 --- a/Numeric/pyramidalBasis.cpp +++ b/Numeric/pyramidalBasis.cpp @@ -62,7 +62,7 @@ static fullMatrix<double> generateLagrangeMonomialCoefficientsPyr max = std::max(max, std::abs(unity(i, j))); } } - if (max > 1e-10) Msg::Info("mon max unity = %.3e", max); + //if (max > 1e-14) Msg::Info("mon max unity = %.3e", max); return coefficient; } @@ -98,23 +98,13 @@ pyramidalBasis::pyramidalBasis(int tag) : nodalBasis(tag) max = std::max(max, std::abs(unity(i, j))); } } - if (max > 1e-10) Msg::Info("leg max unity = %.3e", max); + //if (max > 1e-14) Msg::Info("leg max unity = %.3e", max); // TEST NEW ALGO POINTS / MONOMIAL monomials_newAlgo = gmshGenerateMonomialsPyramid(order, serendip); - copy(monomials_newAlgo, points_newAlgo); - if (order == 0) return; - - for (int i = 0; i < points_newAlgo.size1(); ++i) { - points_newAlgo(i, 2) = points_newAlgo(i, 2) / order; - if (i != 4) { - const double duv = -1. + points_newAlgo(i, 2); - points_newAlgo(i, 0) = duv + points_newAlgo(i, 0) * 2. / order; - points_newAlgo(i, 1) = duv + points_newAlgo(i, 1) * 2. / order; - } - } + points_newAlgo = gmshGeneratePointsPyramid(order, serendip); fullMatrix<double> monDouble; copy(monomials_newAlgo, monDouble);