diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index d53b76d3d9bcab162908de654fcc37b6502d2995..650a2fbd0f15984b167cc51d3d06ea3e926c0f9c 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -1,4 +1,4 @@ -// $Id: MElement.cpp,v 1.31 2007-02-27 17:15:46 remacle Exp $ +// $Id: MElement.cpp,v 1.32 2007-03-14 15:47:49 remacle Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -375,6 +375,7 @@ void MTriangle::circumcenterXY(double *res) const } int MTriangleN::getNumFacesRep(){ return 1; } + MFace MTriangleN::getFaceRep(int num) { return MFace(_v[0],_v[1],_v[2]); @@ -389,3 +390,222 @@ int MTriangleN::getNumFaceVertices(){ if (_order == 5 && _vs.size() == 18) return 6; throw; } + +int P1[3][2] = { + {0,0}, + {1,0}, + {0,1} +}; + +int P2[6][2] = { + {0,0}, + {1,0}, + {0,1}, + {2,0}, + {0,2}, + {1,1} +}; + +int P3[9][2] = { + {0,0}, + {1,0}, + {0,1}, + {2,0}, + {0,2}, + {3,0}, + {0,3}, + {2,1}, + {1,2} +}; +int P4[12][2] = { + {0,0}, + {1,0}, + {0,1}, + {2,0}, + {0,2}, + {3,0}, + {0,3}, + {4,0}, + {0,4}, + {3,1}, + {1,3}, + {2,2} +}; + +int P5[15][2] = { + {0,0}, + {1,0}, + {0,1}, + {2,0}, + {0,2}, + {3,0}, + {0,3}, + {4,0}, + {0,4}, + {5,0}, + {0,5}, + {4,1}, + {3,2}, + {2,3}, + {1,4} +}; + +double coef1[3][3]={ +{ 1.00000000, -1.00000000, -1.00000000}, +{ 0.00000000, 1.00000000, 0.00000000}, +{ 0.00000000, 0.00000000, 1.00000000} +}; + +double coef2[6][6]={ +{ 1.00000000, -3.00000000, -3.00000000, 2.00000000, 2.00000000, 4.00000000}, +{ 0.00000000, -1.00000000, 0.00000000, 2.00000000, -0.00000000, -0.00000000}, +{ 0.00000000, 0.00000000, -1.00000000, -0.00000000, 2.00000000, -0.00000000}, +{ 0.00000000, 4.00000000, 0.00000000, -4.00000000, -0.00000000, -4.00000000}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, 4.00000000}, +{ 0.00000000, 0.00000000, 4.00000000, -0.00000000, -4.00000000, -4.00000000} +}; + +double coef3[9][9]={ +{ 1.00000000, -5.50000000, -5.50000000, 9.00000000, 9.00000000, -4.50000000, -4.50000000, 4.50000000, 4.50000000}, +{ 0.00000000, 1.00000000, 0.00000000, -4.50000000, -0.00000000, 4.50000000, -0.00000000, -0.00000000, -0.00000000}, +{ 0.00000000, 0.00000000, 1.00000000, -0.00000000, -4.50000000, -0.00000000, 4.50000000, -0.00000000, -0.00000000}, +{ 0.00000000, 9.00000000, 0.00000000, -22.50000000, -0.00000000, 13.50000000, 0.00000000, 4.50000000, -9.00000000}, +{ 0.00000000, -4.50000000, -0.00000000, 18.00000000, 0.00000000, -13.50000000, -0.00000000, -9.00000000, 4.50000000}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, 9.00000000, -4.50000000}, +{ 0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, -4.50000000, 9.00000000}, +{ 0.00000000, 0.00000000, -4.50000000, -0.00000000, 18.00000000, -0.00000000, -13.50000000, 4.50000000, -9.00000000}, +{ 0.00000000, 0.00000000, 9.00000000, -0.00000000, -22.50000000, -0.00000000, 13.50000000, -9.00000000, 4.50000000} +}; +double coef4[12][12]={ +{ 1.00000000, -8.33333333, -8.33333333, 23.33333333, 23.33333333, -26.66666667, -26.66666667, 10.66666667, 10.66666667, 9.33333333, 9.33333333, -2.66666667}, +{ 0.00000000, -1.00000000, 0.00000000, 7.33333333, -0.00000000, -16.00000000, 0.00000000, 10.66666667, -0.00000000, -0.00000000, -0.00000000, -0.00000000}, +{ 0.00000000, 0.00000000, -1.00000000, -0.00000000, 7.33333333, -0.00000000, -16.00000000, -0.00000000, 10.66666667, -0.00000000, -0.00000000, -0.00000000}, +{ 0.00000000, 16.00000000, -0.00000000, -69.33333333, 0.00000000, 96.00000000, -0.00000000, -42.66666667, 0.00000000, -5.33333333, -16.00000000, 21.33333333}, +{ 0.00000000, -12.00000000, 0.00000000, 76.00000000, -0.00000000, -128.00000000, 0.00000000, 64.00000000, -0.00000000, 12.00000000, 12.00000000, -40.00000000}, +{ 0.00000000, 5.33333333, -0.00000000, -37.33333333, 0.00000000, 74.66666667, -0.00000000, -42.66666667, 0.00000000, -16.00000000, -5.33333333, 21.33333333}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, 16.00000000, 5.33333333, -21.33333333}, +{ 0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, -12.00000000, -12.00000000, 40.00000000}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, 5.33333333, 16.00000000, -21.33333333}, +{ 0.00000000, 0.00000000, 5.33333333, -0.00000000, -37.33333333, -0.00000000, 74.66666667, -0.00000000, -42.66666667, -5.33333333, -16.00000000, 21.33333333}, +{ 0.00000000, 0.00000000, -12.00000000, -0.00000000, 76.00000000, -0.00000000, -128.00000000, -0.00000000, 64.00000000, 12.00000000, 12.00000000, -40.00000000}, +{ 0.00000000, 0.00000000, 16.00000000, -0.00000000, -69.33333333, -0.00000000, 96.00000000, -0.00000000, -42.66666667, -16.00000000, -5.33333333, 21.33333333} +}; +double coef5[15][15]={ +{ 1.00000000, -11.41666667, -11.41666667, 46.87500000, 46.87500000, -88.54166667, -88.54166667, 78.12500000, 78.12500000, -26.04166667, -26.04166667, 10.41666667, 5.20833333, 5.20833333, 10.41666667}, +{ 0.00000000, 1.00000000, -0.00000000, -10.41666667, 0.00000000, 36.45833333, -0.00000000, -52.08333333, 0.00000000, 26.04166667, 0.00000000, -0.00000000, 0.00000000, -0.00000000, 0.00000000}, +{ 0.00000000, 0.00000000, 1.00000000, -0.00000000, -10.41666667, -0.00000000, 36.45833333, -0.00000000, -52.08333333, 0.00000000, 26.04166667, -0.00000000, 0.00000000, -0.00000000, 0.00000000}, +{ 0.00000000, 25.00000000, -0.00000000, -160.41666667, 0.00000000, 369.79166667, -0.00000000, -364.58333333, 0.00000000, 130.20833333, -0.00000000, 6.25000000, -38.54166667, 60.41666667, -25.00000000}, +{ 0.00000000, -25.00000000, 0.00000000, 222.91666667, -0.00000000, -614.58333333, 0.00000000, 677.08333333, -0.00000000, -260.41666667, 0.00000000, -16.66666667, 95.83333333, -122.91666667, 25.00000000}, +{ 0.00000000, 16.66666667, -0.00000000, -162.50000000, 0.00000000, 510.41666667, -0.00000000, -625.00000000, 0.00000000, 260.41666667, -0.00000000, 25.00000000, -122.91666667, 95.83333333, -16.66666667}, +{ 0.00000000, -6.25000000, 0.00000000, 63.54166667, -0.00000000, -213.54166667, 0.00000000, 286.45833333, -0.00000000, -130.20833333, 0.00000000, -25.00000000, 60.41666667, -38.54166667, 6.25000000}, +{ 0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, 0.00000000, -0.00000000, 25.00000000, -60.41666667, 38.54166667, -6.25000000}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, 0.00000000, -25.00000000, 122.91666667, -95.83333333, 16.66666667}, +{ 0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, 0.00000000, -0.00000000, 16.66666667, -95.83333333, 122.91666667, -25.00000000}, +{ 0.00000000, 0.00000000, 0.00000000, -0.00000000, -0.00000000, -0.00000000, 0.00000000, -0.00000000, -0.00000000, 0.00000000, 0.00000000, -6.25000000, 38.54166667, -60.41666667, 25.00000000}, +{ 0.00000000, 0.00000000, -6.25000000, -0.00000000, 63.54166667, -0.00000000, -213.54166667, -0.00000000, 286.45833333, 0.00000000, -130.20833333, 6.25000000, -38.54166667, 60.41666667, -25.00000000}, +{ 0.00000000, 0.00000000, 16.66666667, -0.00000000, -162.50000000, -0.00000000, 510.41666667, -0.00000000, -625.00000000, 0.00000000, 260.41666667, -16.66666667, 95.83333333, -122.91666667, 25.00000000}, +{ 0.00000000, 0.00000000, -25.00000000, -0.00000000, 222.91666667, -0.00000000, -614.58333333, -0.00000000, 677.08333333, 0.00000000, -260.41666667, 25.00000000, -122.91666667, 95.83333333, -16.66666667}, +{ 0.00000000, 0.00000000, 25.00000000, -0.00000000, -160.41666667, -0.00000000, 369.79166667, -0.00000000, -364.58333333, 0.00000000, 130.20833333, -25.00000000, 60.41666667, -38.54166667, 6.25000000} +}; + + +void GradGeomShapeFunctionP1 (double u, double v, double grads[6][2]) +{ + for (int i=0;i<3;i++){ + grads[i][0] = 0; + grads[i][1] = 0; + for (int j=0;j<3;j++){ + if (P1[j][0] > 0)grads[i][0] += coef1[i][j] * pow(u,P1[j][0] - 1 ) * pow(v,P1[j][1] ) ; + if (P1[j][1] > 0)grads[i][1] += coef1[i][j] * pow(u,P1[j][0] ) * pow(v,P1[j][1] -1 ) ; + } + } +} +void GradGeomShapeFunctionP2 (double u, double v, double grads[6][2]) +{ + for (int i=0;i<6;i++){ + grads[i][0] = 0; + grads[i][1] = 0; + for (int j=0;j<6;j++){ + if (P2[j][0] > 0)grads[i][0] += coef2[i][j] * pow(u,P2[j][0] - 1 ) * pow(v,P2[j][1] ) ; + if (P2[j][1] > 0)grads[i][1] += coef2[i][j] * pow(u,P2[j][0] ) * pow(v,P2[j][1] -1 ) ; + } + } +} +void GradGeomShapeFunctionP3 (double u, double v, double grads[9][2]) +{ + for (int i=0;i<9;i++){ + grads[i][0] = 0; + grads[i][1] = 0; + for (int j=0;j<9;j++){ + if (P3[j][0] > 0)grads[i][0] += coef3[i][j] * pow(u,P3[j][0] - 1 ) * pow(v,P3[j][1] ) ; + if (P3[j][1] > 0)grads[i][1] += coef3[i][j] * pow(u,P3[j][0] ) * pow(v,P3[j][1] -1 ) ; + } + } +} +void GradGeomShapeFunctionP4 (double u, double v, double grads[12][2]) +{ + for (int i=0;i<12;i++){ + grads[i][0] = 0; + grads[i][1] = 0; + for (int j=0;j<12;j++){ + if (P4[j][0] > 0)grads[i][0] += coef3[i][j] * pow(u,P4[j][0] - 1 ) * pow(v,P4[j][1] ) ; + if (P4[j][1] > 0)grads[i][1] += coef3[i][j] * pow(u,P4[j][0] ) * pow(v,P4[j][1] -1 ) ; + } + } +} + +void GradGeomShapeFunctionP5 (double u, double v, double grads[15][2]) +{ + for (int i=0;i<15;i++){ + grads[i][0] = 0; + grads[i][1] = 0; + for (int j=0;j<15;j++){ + if (P5[j][0] > 0)grads[i][0] += coef3[i][j] * pow(u,P5[j][0] - 1 ) * pow(v,P5[j][1] ) ; + if (P5[j][1] > 0)grads[i][1] += coef3[i][j] * pow(u,P5[j][0] ) * pow(v,P5[j][1] -1 ) ; + } + } +} + + +void MTriangle::jac ( int ord, MVertex *vs[] , double uu, double vv , double j[2][2]) +{ + double grads[256][2]; + switch (ord) + { + case 1: + GradGeomShapeFunctionP1 ( uu , vv , grads );break; + case 2: + GradGeomShapeFunctionP2 ( uu , vv , grads );break; + case 3: + GradGeomShapeFunctionP3 ( uu , vv , grads );break; + case 4: + GradGeomShapeFunctionP4 ( uu , vv , grads );break; + case 5: + GradGeomShapeFunctionP5 ( uu , vv , grads );break; + default: + throw; + } + j[0][0] = 0 ; for (int i=0;i<3;i++)j[0][0] += grads [i][0] * _v[i] -> x() ; + j[1][0] = 0 ; for (int i=0;i<3;i++)j[1][0] += grads [i][1] * _v[i] -> x() ; + j[0][1] = 0 ; for (int i=0;i<3;i++)j[0][1] += grads [i][0] * _v[i] -> y() ; + j[1][1] = 0 ; for (int i=0;i<3;i++)j[1][1] += grads [i][1] * _v[i] -> y() ; + for (int i=3;i<3*ord;i++)j[0][0] += grads [i][0] * vs[i-3] -> x() ; + for (int i=3;i<3*ord;i++)j[1][0] += grads [i][1] * vs[i-3] -> x() ; + for (int i=3;i<3*ord;i++)j[0][1] += grads [i][0] * vs[i-3] -> y() ; + for (int i=3;i<3*ord;i++)j[1][1] += grads [i][1] * vs[i-3] -> y() ; +} + +void MTriangleN::jac ( double uu, double vv , double j[2][2]) +{ + MTriangle::jac (_order,&(*(_vs.begin())),uu,vv,j); +} + +void MTriangle6::jac ( double uu, double vv , double j[2][2]) +{ + MTriangle::jac (2,_vs,uu,vv,j); +} +void MTriangle::jac ( double uu, double vv , double j[2][2]) +{ + jac (1,0,uu,vv,j); +} + diff --git a/Geo/MElement.h b/Geo/MElement.h index a640b6b6eb3bc5ff3f119d237fca5e1d6eda0b34..73971a5302a7bcf7e49554b51600b7edb26ba311 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -288,6 +288,7 @@ class MLineN : public MLine { class MTriangle : public MElement { protected: MVertex *_v[3]; + virtual void jac ( int order, MVertex *v[], double u, double v , double jac[2][2]) ; public : MTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) : MElement(num, part) @@ -342,6 +343,7 @@ class MTriangle : public MElement { { MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp; } + virtual void jac ( double u, double v , double j[2][2]) ; }; class MTriangle6 : public MTriangle { @@ -401,6 +403,7 @@ class MTriangle6 : public MTriangle { tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp; tmp = _vs[0]; _vs[0] = _vs[2]; _vs[2] = tmp; } + virtual void jac ( double u, double v , double j[2][2]) ; }; class MTriangleN : public MTriangle { @@ -464,6 +467,7 @@ class MTriangleN : public MTriangle { inv.insert (inv.begin(),_vs.rbegin(),_vs.rend()); _vs = inv; } + virtual void jac ( double u, double v , double jac[2][2]) ; }; diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp index 67aea10db72f3ab6f4c0ae2cc4eb9cba9594cd32..4d76f08a20a3172b555054b2bceae2c6dbbd43a3 100644 --- a/Mesh/HighOrder.cpp +++ b/Mesh/HighOrder.cpp @@ -1,4 +1,4 @@ -// $Id: HighOrder.cpp,v 1.8 2007-03-13 16:11:43 remacle Exp $ +// $Id: HighOrder.cpp,v 1.9 2007-03-14 15:47:49 remacle Exp $ // // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // @@ -626,6 +626,20 @@ bool straightLine ( std::vector<MVertex *> &l , MVertex *n1, MVertex *n2) } +void getMinMaxJac (MTriangle *t, double &minJ, double &maxJ) +{ + double u[7] = {0,1,0,.5,0,.5,.3333}; + double v[7] = {0,0,1,.5,.5,0,.3333}; + double j[2][2]; + for (int i=0;i<7;i++) + { + t->jac ( u[i], v[i] , j ); + double det = det2x2 ( j ); + minJ = std::min ( det , minJ ); + maxJ = std::max ( det , maxJ ); + } +} + void smoothInternalEdges ( GFace *gf , edgeContainer &edgeVertices) { typedef std::map<std::pair<MVertex*, MVertex*> , std::vector<MElement*> > edge2tris; @@ -638,6 +652,7 @@ void smoothInternalEdges ( GFace *gf , edgeContainer &edgeVertices) e2t[p].push_back(t); } } + for ( edge2tris::iterator it = e2t.begin() ; it != e2t.end() ; ++it) { std::pair<MVertex*, MVertex*> edge = it->first; @@ -650,6 +665,7 @@ void smoothInternalEdges ( GFace *gf , edgeContainer &edgeVertices) MVertex *n4 = edge.second; MTriangle *t1 = (MTriangle*)triangles[0]; MTriangle *t2 = (MTriangle*)triangles[1]; + MVertex *n1 = t1->getOtherVertex (n2,n4); MVertex *n3 = t2->getOtherVertex (n2,n4); if (n1<n2) @@ -768,12 +784,48 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete) setHighOrder(*it, edgeVertices, faceVertices, linear, incomplete, nPts); - if (CTX.mesh.smooth_internal_edges) - for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) - { - for (int i=0;i<10;i++)smoothInternalEdges ( *it , edgeVertices); - } - + for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) + { + if (CTX.mesh.smooth_internal_edges) + for (int i=0;i<10;i++) + smoothInternalEdges ( *it , edgeVertices); + + bool twod = true; + for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ + MTriangle *t = (*it)->triangles[i]; + if(t->getVertex(0)->z() != 0.0 || t->getVertex(1)->z() != 0.0 ||t->getVertex(2)->z() != 0.0)twod = false; + } + + + if (twod && order > 3) + { + Msg(INFO,"Validity check of higher order meshes is still bugged for orders > 3"); + } + else if (twod) + { + double minJ = 1.e22; + double maxJ = -1.e22; + for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ + double minJloc = 1.e22; + double maxJloc = -1.e22; + + MTriangle *t = (*it)->triangles[i]; + getMinMaxJac (t,minJloc,maxJloc); + minJ = std::min(minJ,minJloc); + maxJ = std::max(maxJ,maxJloc); + if (minJloc*maxJloc < 0) + Msg(GERROR,"Triangle %d %d %d has negative jacobians in GFace %d",t->getVertex(0)->getNum(), + t->getVertex(1)->getNum(),t->getVertex(2)->getNum(),(*it)->tag()); + } + + if (minJ*maxJ < 0) + Msg(GERROR,"There exists triangles with negative jacobians in GFace %d",(*it)->tag()); + else + Msg(INFO,"Jacobian range of face %d is %g %g",(*it)->tag(),minJ,maxJ); + + } + } + double t2 = Cpu(); Msg(INFO, "Mesh second order complete (%g s)", t2 - t1); Msg(STATUS1, "Mesh");