diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h index d78f5aa7f2873affa7882bc5b0bf2088a4debe03..8afa3f41bb895b14d4d5172c482ee15084b78ef6 100644 --- a/Common/GmshDefines.h +++ b/Common/GmshDefines.h @@ -82,6 +82,8 @@ #define MSH_TET_20 29 #define MSH_TET_35 30 #define MSH_TET_56 31 +#define MSH_TET_34 32 +#define MSH_TET_52 33 // Geometric entities #define ENT_NONE 0 diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp index 6cf735bea49dcbc8790d1afb0c6f79dd8436037e..6f79f03ff0b5e437a33e5fe7f7037999791ad732 100644 --- a/Geo/GFace.cpp +++ b/Geo/GFace.cpp @@ -1,4 +1,4 @@ -// $Id: GFace.cpp,v 1.69 2008-07-10 13:29:24 geuzaine Exp $ +// $Id: GFace.cpp,v 1.70 2008-07-11 10:54:24 remacle Exp $ // // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // @@ -732,7 +732,7 @@ bool GFace::buildSTLTriangulation() // by default we assume that straight lines are geodesics SPoint2 GFace::geodesic(const SPoint2 &pt1 , const SPoint2 &pt2 , double t) { - if(CTX.mesh.second_order_experimental){ + if(CTX.mesh.second_order_experimental && geomType() != GEntity::Plane){ // FIXME: this is buggy -- remove the CTX option once we do it in // a robust manner GPoint gp1 = point(pt1.x(), pt1.y()); diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp index e13d701e10514933d18d6de7c906f4b1ec7c1b56..da743dac7a2ffced3acfb0c4f34a0aa20d86c24b 100644 --- a/Geo/GModelIO_Mesh.cpp +++ b/Geo/GModelIO_Mesh.cpp @@ -1,4 +1,4 @@ -// $Id: GModelIO_Mesh.cpp,v 1.58 2008-07-08 12:44:33 remacle Exp $ +// $Id: GModelIO_Mesh.cpp,v 1.59 2008-07-11 10:54:24 remacle Exp $ // // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // @@ -140,8 +140,9 @@ static int getNumVerticesForElementTypeMSH(int type) case MSH_TET_4 : return 4; case MSH_TET_10 : return 4 + 6; case MSH_TET_20 : return 4 + 12 + 4; - case MSH_TET_35 : return 4 + 16 + 12 + 3; - case MSH_TET_56 : return 4 + 20 + 24 + 8; + case MSH_TET_35 : return 4 + 18 + 12 + 1; + case MSH_TET_52 : return 4 + 24 + 24 + 0; + case MSH_TET_56 : return 4 + 24 + 24 + 4; case MSH_HEX_8 : return 8; case MSH_HEX_20 : return 8 + 12; case MSH_HEX_27 : return 8 + 12 + 6 + 1; @@ -171,6 +172,7 @@ static void createElementMSH(GModel *m, int num, int type, int physical, else{ MElementFactory factory; MElement *e = factory.create(type, v, num, part); + if(!e){ Msg::Error("Unknown type of element %d", type); return; @@ -333,7 +335,7 @@ int GModel::readMSH(const std::string &name) } if(!(numVertices = getNumVerticesForElementTypeMSH(type))) return 0; } - int indices[30]; + int indices[60]; for(int j = 0; j < numVertices; j++) fscanf(fp, "%d", &indices[j]); std::vector<MVertex*> vertices; if(vertexVector.size()){ @@ -447,7 +449,7 @@ int GModel::readMSH(const std::string &name) storeVerticesInEntities(vertexMap); // store the physical tags - for(int i = 0; i < 4; i++) + for(int i = 0; i < 4; i++) storePhysicalTagsInEntities(this, i, physicals[i]); fclose(fp); @@ -634,7 +636,7 @@ int GModel::writeMSH(const std::string &name, double version, bool binary, for(fiter it = firstFace(); it != lastFace(); ++it) writeElementsMSH(fp, (*it)->quadrangles, saveAll, version, binary, num, (*it)->tag(), (*it)->physicals); - writeElementHeaderMSH(binary, fp, elements, MSH_TET_4, MSH_TET_10); + writeElementHeaderMSH(binary, fp, elements, MSH_TET_4, MSH_TET_10, MSH_TET_20, MSH_TET_35, MSH_TET_56, MSH_TET_52); for(riter it = firstRegion(); it != lastRegion(); ++it) writeElementsMSH(fp, (*it)->tetrahedra, saveAll, version, binary, num, (*it)->tag(), (*it)->physicals); diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index 6a373763a5986a3378ce0d65b47b3146d7afdf23..a8168ffe6ae2be730bde8826281d849c518606fb 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -1,4 +1,4 @@ -// $Id: MElement.cpp,v 1.79 2008-07-10 13:29:24 geuzaine Exp $ +// $Id: MElement.cpp,v 1.80 2008-07-11 10:54:24 remacle Exp $ // // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // @@ -418,7 +418,7 @@ void MElement::writeMSH(FILE *fp, double version, bool binary, int num, if(physical < 0) revert(); - int verts[30]; + int verts[60]; for(int i = 0; i < n; i++) verts[i] = getVertex(i)->getIndex(); @@ -553,7 +553,7 @@ void MElement::writeVTK(FILE *fp, bool binary) int n = getNumVertices(); if(binary){ - int verts[30]; + int verts[60]; verts[0] = n; for(int i = 0; i < n; i++) verts[i + 1] = getVertexVTK(i)->getIndex() - 1; @@ -731,13 +731,25 @@ void MTetrahedron::pnt(int ord, MVertex *vs[], double uu, double vv, double ww,S { #if !defined(HAVE_GMSH_EMBEDDED) double sf[256]; - switch(ord){ - case 1: gmshFunctionSpaces::find(MSH_TET_4).f(uu, vv, ww,sf); break; - case 2: gmshFunctionSpaces::find(MSH_TET_10).f(uu, vv, ww,sf); break; - case 3: gmshFunctionSpaces::find(MSH_TET_20).f(uu, vv, ww,sf); break; - case 4: gmshFunctionSpaces::find(MSH_TET_35).f(uu, vv, ww,sf); break; - case 5: gmshFunctionSpaces::find(MSH_TET_56).f(uu, vv, ww,sf); break; - default: Msg::Error("Order %d tetrahedron pnt not implemented", ord); break; + + int nv = getNumVolumeVertices(); + + if (!nv){ + switch(ord){ + case 1: gmshFunctionSpaces::find(MSH_TET_4).f(uu, vv, ww,sf); break; + case 2: gmshFunctionSpaces::find(MSH_TET_10).f(uu, vv, ww,sf); break; + case 3: gmshFunctionSpaces::find(MSH_TET_20).f(uu, vv, ww,sf); break; + case 4: gmshFunctionSpaces::find(MSH_TET_34).f(uu, vv, ww,sf); break; + case 5: gmshFunctionSpaces::find(MSH_TET_52).f(uu, vv, ww,sf); break; + default: Msg::Error("Order %d tetrahedron pnt not implemented", ord); break; + } + } + else{ + switch(ord){ + case 4: gmshFunctionSpaces::find(MSH_TET_35).f(uu, vv, ww,sf); break; + case 5: gmshFunctionSpaces::find(MSH_TET_56).f(uu, vv, ww,sf); break; + default: Msg::Error("Order %d tetrahedron pnt not implemented", ord); break; + } } double x = 0 ; for(int i = 0; i < 4; i++) x += sf[i] * _v[i]->x(); @@ -884,7 +896,7 @@ void MTetrahedron::jac( double uu, double vv, double ww, double j[3][3]) { return jac(1,0,uu,vv,ww,j); } -const int numSubEdges = 12; +const int numSubEdges = 6; int MTriangleN::getNumFacesRep(){ return numSubEdges * numSubEdges; } @@ -1020,7 +1032,9 @@ MElement *MElementFactory::create(int type, std::vector<MVertex*> &v, case MSH_PYR_13: return new MPyramid13(v, num, part); case MSH_PYR_14: return new MPyramid14(v, num, part); case MSH_TET_20: return new MTetrahedronN(v, 3, num, part); + case MSH_TET_34: return new MTetrahedronN(v, 3, num, part); case MSH_TET_35: return new MTetrahedronN(v, 4, num, part); + case MSH_TET_52: return new MTetrahedronN(v, 5, num, part); case MSH_TET_56: return new MTetrahedronN(v, 5, num, part); default: return 0; } diff --git a/Geo/MElement.h b/Geo/MElement.h index cf4e67e4724aefc841e4e409ce5c82b18f2e9228..ea226c1b6cb41fb7aef293f5293c4f3583a20e82 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -1479,12 +1479,24 @@ class MTetrahedronN : public MTetrahedron { const int ie = (num+1)*getNumFaceVertices(); for(int i = num*getNumFaceVertices(); i != ie; ++i) v[j++] = _vs[i]; } + virtual int getNumVolumeVertices() + { + switch(getTypeForMSH()){ + case MSH_TET_35 : return 1; + case MSH_TET_56 : return 4; + default : return 0; + } + } + virtual int getNumEdgeVertices(){ return _order - 1; } + virtual int getTypeForMSH() { // (p+1)*(p+2)*(p+3)/6 if(_order == 3 && _vs.size() + 4 == 20) return MSH_TET_20; + if(_order == 4 && _vs.size() + 4 == 34) return MSH_TET_34; if(_order == 4 && _vs.size() + 4 == 35) return MSH_TET_35; if(_order == 5 && _vs.size() + 4 == 56) return MSH_TET_56; + if(_order == 5 && _vs.size() + 4 == 52) return MSH_TET_52; return 0; } virtual void revert() diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp index 5d30f79b006cc2db7b2a467821faa62d62b1c515..c71d68d7a7c4a33999b0e43f91260407f178fc76 100644 --- a/Mesh/HighOrder.cpp +++ b/Mesh/HighOrder.cpp @@ -1,4 +1,4 @@ -// $Id: HighOrder.cpp,v 1.34 2008-07-10 13:29:24 geuzaine Exp $ +// $Id: HighOrder.cpp,v 1.35 2008-07-11 10:54:24 remacle Exp $ // // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // @@ -650,6 +650,51 @@ void getFaceVertices(GRegion *gr, MElement *ele, std::vector<MVertex*> &vf, } } + +void getRegionVertices(GRegion *gr, + MElement *incomplete, + MElement *ele, + std::vector<MVertex*> &vr, + bool linear, int nPts = 1) +{ + + Double_Matrix points; + int start = 0; + + switch (nPts){ + case 3 : + points = gmshFunctionSpaces::find(MSH_TET_35).points; + start = 34; + break; + case 4 : + points = gmshFunctionSpaces::find(MSH_TET_56).points; + start = 52; + break; + default : + return; + break; + } + + for(int k = start ; k < points.size1() ; k++){ + MVertex *v; + const double t1 = points(k, 0); + const double t2 = points(k, 1); + const double t3 = points(k, 2); + double X(0),Y(0),Z(0); + for (int j=0; j<incomplete->getNumVertices(); j++){ + double sf ; incomplete->getShapeFunction(j,t1,t2,t3,sf); + MVertex *vt = incomplete->getVertex(j); + X += sf * vt->x(); + Y += sf * vt->y(); + Z += sf * vt->z(); + } + v = new MVertex(X,Y,Z, gr); + gr->mesh_vertices.push_back(v); + vr.push_back(v); + } +} + + void setHighOrder(GEdge *ge, edgeContainer &edgeVertices, bool linear, int nbPts = 1) { @@ -736,7 +781,7 @@ void setHighOrder(GRegion *gr, edgeContainer &edgeVertices, std::vector<MTetrahedron*> tetrahedra2; for(unsigned int i = 0; i < gr->tetrahedra.size(); i++){ MTetrahedron *t = gr->tetrahedra[i]; - std::vector<MVertex*> ve,vf; + std::vector<MVertex*> ve,vf,vr; getEdgeVertices(gr, t, ve, edgeVertices, linear, nPts); if (nPts == 1){ tetrahedra2.push_back @@ -745,7 +790,11 @@ void setHighOrder(GRegion *gr, edgeContainer &edgeVertices, } else{ getFaceVertices(gr, t, vf, faceVertices, linear, nPts); - ve.insert(ve.end(), vf.begin(), vf.end()); + ve.insert(ve.end(), vf.begin(), vf.end()); + MTetrahedronN incpl (t->getVertex(0), t->getVertex(1), t->getVertex(2), t->getVertex(3), + ve, nPts + 1); + getRegionVertices(gr, &incpl, t, vr, linear, nPts); + ve.insert(ve.end(), vr.begin(), vr.end()); tetrahedra2.push_back (new MTetrahedronN(t->getVertex(0), t->getVertex(1), t->getVertex(2), t->getVertex(3), ve, nPts + 1)); @@ -1432,7 +1481,7 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete) int nPts = order - 1; - Msg::StatusBar(1, true, "Meshing second order..."); + Msg::StatusBar(1, true, "Generating High Order Nodes (q = %d) ...",order); double t1 = Cpu(); // first, make sure to remove any existsing second order vertices/elements diff --git a/Numeric/FunctionSpace.cpp b/Numeric/FunctionSpace.cpp index bebaa356a197e654f3067912875f663d8182f0b8..71646f670420c662a1632b0908715088270b6b7e 100644 --- a/Numeric/FunctionSpace.cpp +++ b/Numeric/FunctionSpace.cpp @@ -1,4 +1,4 @@ -// $Id: FunctionSpace.cpp,v 1.8 2008-07-03 17:06:04 geuzaine Exp $ +// $Id: FunctionSpace.cpp,v 1.9 2008-07-11 10:54:24 remacle Exp $ // // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle // @@ -613,6 +613,14 @@ const gmshFunctionSpace &gmshFunctionSpaces::find(int tag) F.monomials = generatePascalTetrahedron(4); F.points = gmshGeneratePointsTetrahedron(4, false); break; + case MSH_TET_34 : + F.monomials = generatePascalSerendipityTetrahedron(4); + F.points = gmshGeneratePointsTetrahedron(4, true); + break; + case MSH_TET_52 : + F.monomials = generatePascalSerendipityTetrahedron(5); + F.points = gmshGeneratePointsTetrahedron(5, true); + break; case MSH_TET_56 : F.monomials = generatePascalTetrahedron(5); F.points = gmshGeneratePointsTetrahedron(5, false);