diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index 416e6bff5966845b035a52e0b09e3263b9d6b4ee..2863b339c3ce0449c3041f0abb057f9abafbfe00 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -85,6 +85,7 @@ void PrintUsage(const char *name) Msg::Direct(" -rand float Set random perturbation factor"); Msg::Direct(" -bgm file Load background mesh from file"); Msg::Direct(" -check Perform various consistency checks on mesh"); + Msg::Direct(" -mpass int Do several passes on the mesh for complex backround fields"); #if defined(HAVE_FLTK) Msg::Direct("Post-processing options:"); Msg::Direct(" -link int Select link mode between views (0, 1, 2, 3, 4)"); @@ -438,6 +439,16 @@ void GetOptions(int argc, char *argv[]) else Msg::Fatal("Missing number"); } + else if(!strcmp(argv[i] + 1, "mpass")) { + i++; + if(argv[i]) { + CTX::instance()->mesh.multiplePasses = atoi(argv[i++]); + if(CTX::instance()->mesh.multiplePasses <= 0) + Msg::Fatal("Number of Mesh Passes must be > 0"); + } + else + Msg::Fatal("Missing number"); + } else if(!strcmp(argv[i] + 1, "edgelmin")) { i++; if(argv[i]) { diff --git a/Common/Context.h b/Common/Context.h index 466f44274c56d86067c16e466a5d3e22e56546f1..5dbe2af47c8414ce18e4ab3b6777b6822543e771 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -37,6 +37,7 @@ struct contextMeshOptions { int saveElementTagType; int switchElementTags; int highOrderNoMetric; + int multiplePasses; }; struct contextGeometryOptions { diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 25a2c2ac6435fb9b419ede1351c2384812d123d0..d1d4947561dd37a0578f31b279953d0da705c65c 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1152,6 +1152,8 @@ StringXNumber MeshOptions_Number[] = { "Version of the MSH file format to use" }, { F|O, "MshFilePartitioned" , opt_mesh_msh_file_partitioned , 0. , "Split MSH file by mesh partition" }, + { F|O, "MultiplePassesMeshes" , opt_mesh_multiple_passes , 0. , + "Do a first simple mesh and use it for complex background meshes (curvatures...)" }, { F|O, "PartitionHexWeight" , opt_mesh_partition_hex_weight , 1 , "Weight of hexahedral element for METIS load balancing" }, diff --git a/Common/Options.cpp b/Common/Options.cpp index 931c14bf60cf88242b54ac795567063e59c931a5..9cd4ce697ce5b7d5b29acf5b09f705f663374a07 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -5839,6 +5839,13 @@ double opt_mesh_second_order_experimental(OPT_ARGS_NUM) return CTX::instance()->mesh.secondOrderExperimental; } +double opt_mesh_multiple_passes(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->mesh.multiplePasses = (int)val; + return CTX::instance()->mesh.multiplePasses; +} + double opt_mesh_second_order_linear(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 1f13d6f411fe6365be60eb35cd7af16bb2fef2c1..a43ed93917bf50bb9c7db78b85a0ff3454655849 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -539,6 +539,7 @@ double opt_mesh_mesh_only_visible(OPT_ARGS_NUM); double opt_mesh_min_circ_points(OPT_ARGS_NUM); double opt_mesh_allow_swap_edge_angle(OPT_ARGS_NUM); double opt_mesh_min_curv_points(OPT_ARGS_NUM); +double opt_mesh_multiple_passes(OPT_ARGS_NUM); double opt_mesh_order(OPT_ARGS_NUM); double opt_mesh_smooth_internal_edges(OPT_ARGS_NUM); double opt_mesh_second_order_experimental(OPT_ARGS_NUM); diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp index eb2544dfdb600ea971c808b73b7b24f89cd2f9cf..b16f0f125f32c129240aa9bda499167fbbc21018 100644 --- a/Mesh/BackgroundMesh.cpp +++ b/Mesh/BackgroundMesh.cpp @@ -16,6 +16,7 @@ #include "MElementOctree.h" #include "MLine.h" #include "MTriangle.h" +#include "MQuadrangle.h" #include "MVertex.h" #if defined(HAVE_SOLVER) @@ -410,6 +411,10 @@ void backgroundMesh::unset() backgroundMesh::backgroundMesh(GFace *_gf) { + // create a bunch of triangles on the parametric space + // those triangles are local to the backgroundMesh so that + // they do not depend on the actual mesh that can be deleted + for (unsigned int i = 0; i < _gf->triangles.size(); i++){ MTriangle *e = _gf->triangles[i]; MVertex *news[3]; @@ -429,7 +434,11 @@ backgroundMesh::backgroundMesh(GFace *_gf) } _triangles.push_back(new MTriangle(news[0],news[1],news[2])); } + + // build a search structure _octree = new MElementOctree(_triangles); + + // compute the mesh sizes at nodes if (CTX::instance()->mesh.lcFromPoints) propagate1dMesh(_gf); else { @@ -438,7 +447,12 @@ backgroundMesh::backgroundMesh(GFace *_gf) _sizes[itv2->first] = MAX_LC; } } + // ensure that other criteria are fullfilled updateSizes(_gf); + + // compute optimal mesh orientations + propagatecrossField(_gf); + _3Dto2D.clear(); _2Dto3D.clear(); } @@ -450,13 +464,9 @@ backgroundMesh::~backgroundMesh() delete _octree; } -void backgroundMesh::propagate1dMesh(GFace *_gf) +static void propagateValuesOnFace (GFace *_gf, + std::map<MVertex*,double> &dirichlet) { -#if defined(HAVE_SOLVER) - std::list<GEdge*> e = _gf->edges(); - std::list<GEdge*>::const_iterator it = e.begin(); - std::map<MVertex*,double> sizes; - linearSystem<double> *_lsys = 0; #if defined(HAVE_PETSC) && !defined(HAVE_TAUCS) _lsys = new linearSystemPETSc<double>; @@ -469,8 +479,50 @@ void backgroundMesh::propagate1dMesh(GFace *_gf) #else _lsys = new linearSystemFull<double>; #endif - + dofManager<double> myAssembler(_lsys); + + // fix boundary conditions + std::map<MVertex*, double>::iterator itv = dirichlet.begin(); + for ( ; itv != dirichlet.end(); ++itv){ + myAssembler.fixVertex(itv->first, 0, 1, itv->second); + } + + + // Number vertices + std::set<MVertex*> vs; + for (unsigned int k = 0; k < _gf->triangles.size(); k++) + for (int j=0;j<3;j++)vs.insert(_gf->triangles[k]->getVertex(j)); + for (unsigned int k = 0; k < _gf->quadrangles.size(); k++) + for (int j=0;j<4;j++)vs.insert(_gf->quadrangles[k]->getVertex(j)); + for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) + myAssembler.numberVertex(*it, 0, 1); + + // Assemble + simpleFunction<double> ONE(1.0); + laplaceTerm l(0, 1, &ONE); + for (unsigned int k = 0; k < _gf->triangles.size(); k++){ + MTriangle *t = _gf->triangles[k]; + SElement se(t); + l.addToMatrix(myAssembler, &se); + } + + // Solve + _lsys->systemSolve(); + + // save solution + for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it){ + myAssembler.getDofValue(*it, 0, 1, dirichlet[*it]); + } + + delete _lsys; +} + +void backgroundMesh::propagate1dMesh(GFace *_gf) +{ + std::list<GEdge*> e = _gf->edges(); + std::list<GEdge*>::const_iterator it = e.begin(); + std::map<MVertex*,double> sizes; for( ; it != e.end(); ++it ){ if (!(*it)->isSeam(_gf)){ @@ -484,48 +536,93 @@ void backgroundMesh::propagate1dMesh(GFace *_gf) MVertex *v = (*it)->lines[i]->getVertex(k); std::map<MVertex*, double>::iterator itv = sizes.find(v); if (itv == sizes.end()) - sizes[v] = d; + sizes[v] = log(d); else - itv->second = 0.5 * (itv->second + d); + itv->second = 0.5 * (itv->second + log(d)); } } } } - std::map<MVertex*, double>::iterator itv = sizes.begin(); - for ( ; itv != sizes.end(); ++itv){ - myAssembler.fixVertex(itv->first, 0, 1, itv->second); + + propagateValuesOnFace(_gf,sizes); + + std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin(); + for ( ; itv2 != _2Dto3D.end(); ++itv2){ + MVertex *v_2D = itv2->first; + MVertex *v_3D = itv2->second; + _sizes[v_2D] = exp(sizes[v_3D]); } +} - simpleFunction<double> ONE(1.0); - laplaceTerm l(0, 1, &ONE); +// C R O S S F I E L D S - for (unsigned int k = 0; k < _gf->triangles.size(); k++){ - MTriangle *t = _gf->triangles[k]; - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); +crossField2d :: crossField2d (MVertex* v, GEdge* ge){ + double p; + bool success = reparamMeshVertexOnEdge(v, ge, p); + if (!success){ + Msg::Warning("cannot reparametrize a point in crossField"); + _angle = 0; + return; } + SVector3 t = ge->firstDer (p); + t.normalize(); + _angle = atan2 (t.y(),t.x()); + crossField2d::normalizeAngle (_angle); +} + + + + +void backgroundMesh::propagatecrossField(GFace *_gf) +{ + std::map<MVertex*,double> _cosines4,_sines4; + std::list<GEdge*> e = _gf->edges(); + std::list<GEdge*>::const_iterator it = e.begin(); - for (unsigned int k = 0; k < _gf->triangles.size(); k++){ - MTriangle *t = _gf->triangles[k]; - SElement se(t); - l.addToMatrix(myAssembler, &se); + for( ; it != e.end(); ++it ){ + if (!(*it)->isSeam(_gf)){ + for(unsigned int i = 0; i < (*it)->lines.size(); i++ ){ + MVertex *v[2]; + v[0] = (*it)->lines[i]->getVertex(0); + v[1] = (*it)->lines[i]->getVertex(1); + SPoint2 p1,p2; + bool success = reparamMeshEdgeOnFace(v[0],v[1],_gf,p1,p2); + // double angle = atan2 ( p1.y()-p2.y() , p1.x()-p2.x() ); + double angle = atan2 ( v[0]->y()-v[1]->y() , v[0]->x()- v[1]->x() ); + crossField2d::normalizeAngle (angle); + for (int i=0;i<2;i++){ + std::map<MVertex*,double>::iterator itc = _cosines4.find(v[i]); + std::map<MVertex*,double>::iterator its = _sines4.find(v[i]); + if (itc != _cosines4.end()){ + itc->second = 0.5*(itc->second + cos(4*angle)); + its->second = 0.5*(its->second + sin(4*angle)); + } + else { + _cosines4[v[i]] = cos(4*angle); + _sines4[v[i]] = sin(4*angle); + } + } + } + } } - _lsys->systemSolve(); + + propagateValuesOnFace(_gf,_cosines4); + propagateValuesOnFace(_gf,_sines4); std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin(); for ( ; itv2 != _2Dto3D.end(); ++itv2){ MVertex *v_2D = itv2->first; MVertex *v_3D = itv2->second; - myAssembler.getDofValue(v_3D, 0, 1, _sizes[v_2D]); + double angle = atan2(_sines4[v_3D],_cosines4[v_3D]) / 4.0; + crossField2d::normalizeAngle (angle); + _angles[v_2D] = angle; } - delete _lsys; -#endif + } + void backgroundMesh::updateSizes(GFace *_gf) { -#if defined(HAVE_SOLVER) std::map<MVertex*,double>::iterator itv = _sizes.begin(); for ( ; itv != _sizes.end(); ++itv){ SPoint2 p; @@ -548,80 +645,6 @@ void backgroundMesh::updateSizes(GFace *_gf) itv->second = std::max(itv->second, CTX::instance()->mesh.lcMin); itv->second = std::min(itv->second, CTX::instance()->mesh.lcMax); } - // return; - // now do some diffusion - - std::list<GEdge*> e = _gf->edges(); - std::list<GEdge*>::const_iterator it = e.begin(); - - linearSystem<double> *_lsys = 0; -#if defined(HAVE_PETSC) && !defined(HAVE_TAUCS) - _lsys = new linearSystemPETSc<double>; -#elif defined(HAVE_GMM) && !defined(HAVE_TAUCS) - linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>; - _lsysb->setGmres(1); - _lsys = _lsysb; -#elif defined(HAVE_TAUCS) - _lsys = new linearSystemCSRTaucs<double>; -#else - _lsys = new linearSystemFull<double>; -#endif - - dofManager<double> myAssembler(_lsys); - - // M (U^{t+1} - U^{t})/DT + K U^{t+1} = 0 - - for( ; it != e.end(); ++it ){ - if (!(*it)->isSeam(_gf)){ - for(unsigned int i = 0; i < (*it)->lines.size(); i++ ){ - MVertex *v1 = (*it)->lines[i]->getVertex(0); - MVertex *v2 = (*it)->lines[i]->getVertex(1); - MVertex *v1_2D = _3Dto2D[ v1 ]; - MVertex *v2_2D = _3Dto2D[ v2 ]; - - myAssembler.fixVertex(v1, 0, 1, _sizes[v1_2D]); - myAssembler.fixVertex(v2, 0, 1, _sizes[v2_2D]); - } - } - } - - double DT = 0.01; - simpleFunction<double> ONEOVERDT(1.0/DT); - simpleFunction<double> ONE(1.0); - helmholtzTerm<double> diffusionTerm(0,1, 1, &ONE,&ONEOVERDT); - helmholtzTerm<double> massTerm(0,1, 1, 0,&ONEOVERDT); - - for (unsigned int k= 0; k< _gf->triangles.size(); k++){ - MTriangle *t = _gf->triangles[k]; - myAssembler.numberVertex(t->getVertex(0), 0, 1); - myAssembler.numberVertex(t->getVertex(1), 0, 1); - myAssembler.numberVertex(t->getVertex(2), 0, 1); - } - fullMatrix<double> mass_matrix(3,3); - for (unsigned int k= 0; k< _gf->getNumMeshElements(); k++){ - MElement *e = _gf->getMeshElement(k); - SElement se(e); - diffusionTerm.addToMatrix(myAssembler, &se); - massTerm.elementMatrix(&se,mass_matrix); - for (int i = 0; i < e->getNumVertices();i++){ - double TERM = 0.0; - for (int j = 0; j < e->getNumVertices();j++){ - MVertex *v_2D = _3Dto2D[ e->getVertex(j) ]; - TERM+=_sizes[v_2D] * mass_matrix(i,j); - } - myAssembler.assemble(e->getVertex(i),0,1,TERM); - } - } - _lsys->systemSolve(); - - std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin(); - for ( ; itv2 != _2Dto3D.end(); ++itv2){ - MVertex *v_2D = itv2->first; - MVertex *v_3D = itv2->second; - myAssembler.getDofValue(v_3D, 0, 1, _sizes[v_2D]); - } - delete _lsys; -#endif } double backgroundMesh::operator() (double u, double v, double w) const @@ -641,7 +664,35 @@ double backgroundMesh::operator() (double u, double v, double w) const return itv1->second * (1-uv2[0]-uv2[1]) + itv2->second * uv2[0] + itv3->second * uv2[1]; } -void backgroundMesh::print (const std::string &filename, GFace *gf) const +double backgroundMesh::getAngle (double u, double v, double w) const +{ + double uv[3] = {u, v, w}; + double uv2[3]; + // return 1.0; + MElement *e = _octree->find(u, v, w); + if (!e) { + Msg::Error("cannot find %g %g", u, v); + return 0.0; + } + e->xyz2uvw(uv, uv2); + std::map<MVertex*,double>::const_iterator itv1 = _angles.find(e->getVertex(0)); + std::map<MVertex*,double>::const_iterator itv2 = _angles.find(e->getVertex(1)); + std::map<MVertex*,double>::const_iterator itv3 = _angles.find(e->getVertex(2)); + + double cos4 = cos (4*itv1->second) * (1-uv2[0]-uv2[1]) + + cos (4*itv2->second) * uv2[0] + + cos (4*itv3->second) * uv2[1] ; + double sin4 = sin (4*itv1->second) * (1-uv2[0]-uv2[1]) + + cos (4*itv2->second) * uv2[0] + + cos (4*itv3->second) * uv2[1] ; + double angle = atan2(sin4,cos4)/4.0; + crossField2d::normalizeAngle (angle); + + return angle; +} + + +void backgroundMesh::print (const std::string &filename, GFace *gf, const std::map<MVertex*,double> &_whatToPrint) const { FILE *f = fopen (filename.c_str(),"w"); fprintf(f,"View \"Background Mesh\"{\n"); @@ -649,9 +700,9 @@ void backgroundMesh::print (const std::string &filename, GFace *gf) const MVertex *v1 = _triangles[i]->getVertex(0); MVertex *v2 = _triangles[i]->getVertex(1); MVertex *v3 = _triangles[i]->getVertex(2); - std::map<MVertex*,double>::const_iterator itv1 = _sizes.find(v1); - std::map<MVertex*,double>::const_iterator itv2 = _sizes.find(v2); - std::map<MVertex*,double>::const_iterator itv3 = _sizes.find(v3); + std::map<MVertex*,double>::const_iterator itv1 = _whatToPrint.find(v1); + std::map<MVertex*,double>::const_iterator itv2 = _whatToPrint.find(v2); + std::map<MVertex*,double>::const_iterator itv3 = _whatToPrint.find(v3); if (!gf){ fprintf(f,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n", v1->x(),v1->y(),v1->z(), diff --git a/Mesh/BackgroundMesh.h b/Mesh/BackgroundMesh.h index 8477fbaf31ae9a264a8af2cadb408cd7cbbbd1df..f98db7599d65ba80e70f18539a2f9123206b155b 100644 --- a/Mesh/BackgroundMesh.h +++ b/Mesh/BackgroundMesh.h @@ -18,6 +18,21 @@ class MElement; class MVertex; class GEntity; +struct crossField2d +{ + double _angle; + static void normalizeAngle (double &angle) { + if (angle < 0) + while ( angle < 0 ) angle += (M_PI * .5); + else if (angle >= M_PI * .5) + while ( angle >= M_PI * .5 ) angle -= (M_PI * .5); + } + crossField2d (MVertex*, GEdge*); + crossField2d (double a) : _angle(a){} + crossField2d & operator += ( const crossField2d & ); +}; + + class backgroundMesh : public simpleFunction<double> { MElementOctree *_octree; @@ -27,6 +42,7 @@ class backgroundMesh : public simpleFunction<double> std::map<MVertex*,MVertex*> _3Dto2D; std::map<MVertex*,MVertex*> _2Dto3D; std::map<MVertex*,double> _distance; + std::map<MVertex*,double> _angles; static backgroundMesh * _current; backgroundMesh(GFace *); ~backgroundMesh(); @@ -35,9 +51,17 @@ class backgroundMesh : public simpleFunction<double> static void unset(); static backgroundMesh *current () { return _current; } void propagate1dMesh(GFace *); + void propagatecrossField(GFace *); void updateSizes(GFace *); double operator () (double u, double v, double w) const; - void print (const std::string &filename, GFace *gf) const; + double getAngle(double u, double v, double w) const ; + void print (const std::string &filename, GFace *gf, const std::map<MVertex*,double>&) const; + void print (const std::string &filename, GFace *gf, int choice = 0) const { + switch(choice) { + case 0 : print(filename,gf,_sizes); return; + default : print(filename,gf,_angles); return; + } + } }; double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y, double Z); diff --git a/Mesh/Field.cpp b/Mesh/Field.cpp index ad5d796fcf0e74e171a29b21bf07b5951ae62695..cc79e9695cc2899683e1709b50c21f034fb0813c 100644 --- a/Mesh/Field.cpp +++ b/Mesh/Field.cpp @@ -22,6 +22,7 @@ #include "GmshMessage.h" #include "Numeric.h" #include "mathEvaluator.h" +#include "BackgroundMesh.h" #if defined(HAVE_POST) #include "OctreePost.h" @@ -1710,10 +1711,16 @@ public: // (dist/hwall)*(ratio-1) + 1 = ratio^{m} // lc = dist*(ratio-1) + hwall const double ll1 = dist*(ratio-1) + hwall_n; - const double lc_n = std::min(ll1,hfar); + double lc_n = std::min(ll1,hfar); const double ll2 = dist*(ratio-1) + hwall_t; double lc_t = std::min(lc_n*CTX::instance()->mesh.anisoMax, std::min(ll2,hfar)); + if (backgroundMesh::current()){ + const double lcBG = backgroundMesh::current()->operator() (x,y,z); + lc_n = std::min(lc_n, lcBG); + lc_t = std::min(lc_t, lcBG); + } + SVector3 t1,t2,t3; double L1,L2,L3; diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp index 293861cb3ff911adffbcaff9fd5328d87c7e6e82..abbc9828ee7a606b3a3eb3475f5b30e954c0708d 100644 --- a/Mesh/Generator.cpp +++ b/Mesh/Generator.cpp @@ -448,16 +448,17 @@ static void Mesh2D(GModel *m) int nIter = 0; while(1){ - meshGFace mesher; int nbPending = 0; for(std::set<GFace*>::iterator it = f.begin(); it != f.end(); ++it){ if ((*it)->meshStatistics.status == GFace::PENDING){ + meshGFace mesher (true, CTX::instance()->mesh.multiplePasses); mesher(*it); nbPending++; } } for(std::set<GFace*>::iterator it = cf.begin(); it != cf.end(); ++it){ if ((*it)->meshStatistics.status == GFace::PENDING){ + meshGFace mesher (true, CTX::instance()->mesh.multiplePasses); mesher(*it); nbPending++; } diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp index 59920098e7a39d33f764555230808e4170b74eb6..240f1173dfe8dd782d4e8ebd9fddd84f0941a5a3 100644 --- a/Mesh/HighOrder.cpp +++ b/Mesh/HighOrder.cpp @@ -29,32 +29,7 @@ static bool mappingIsInvertible(MTetrahedron *e) { if (e->getPolynomialOrder() == 1) return true; - - double mat[3][3]; - e->getPrimaryJacobian(0., 0., 0., mat); - double det0 = det3x3(mat); - - fullMatrix<double> df; - { - const fullMatrix<double> &alldf = - e->getGradShapeFunctionsAtIntegrationPoints(e->getPolynomialOrder()); - for (int i = 0; i < alldf.size2()/3; i++){ - df.setAsProxy(alldf, 3*i, 3); - e->getJacobian(df, mat); - if (det0 * det3x3(mat) <= 0.) return false; - } - } - { - const fullMatrix<double> &points = e->getFunctionSpace()->points; - const fullMatrix<double> &alldf = - e->getGradShapeFunctionsAtNodes(e->getPolynomialOrder()); - for (int i = 0; i < alldf.size2() / 3; i++){ - df.setAsProxy(alldf, 3*i, 3); - e->getJacobian(df, mat); - if (det0 * det3x3(mat) <= 0.) return false; - } - } - return true; + if (e->getPolynomialOrder() == 1) return e->distoShapeMeasure() > 0; } // The aim here is to build a polynomial representation that consist @@ -267,8 +242,8 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve, if(relax < 1.e-2) Msg::Warning ("Failed to compute equidistant parameters (relax = %g, value = %g) " - "for edge %d-%d parametrized with %g %g on GEdge %d", - relax, US[1], v0->getNum(), v1->getNum(),u0,u1,ge->tag()); + "for edge %d-%d parametrized with %g %g on GEdge %d linear %d", + relax, US[1], v0->getNum(), v1->getNum(),u0,u1,ge->tag(), linear); } } for(int j = 0; j < nPts; j++){ @@ -277,8 +252,9 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve, double uc = (1. - t) * u0 + t * u1; // can be wrong, that's ok MVertex *v; if(linear || !reparamOK || uc < std::min(u0,u1) || uc > std::max(u0,u1)){ - Msg::Warning("We don't have a valid parameter on curve %d-%d", - v0->getNum(), v1->getNum()); + if (!linear) + Msg::Warning("We don't have a valid parameter on curve %d-%d", + v0->getNum(), v1->getNum()); // we don't have a (valid) parameter on the curve SPoint3 pc = edge.interpolate(t); v = new MVertex(pc.x(), pc.y(), pc.z(), ge); @@ -1256,10 +1232,10 @@ static void checkHighOrderTetrahedron(const char* cc, GModel *m, } } if (minJGlob < 0) - Msg::Info("%s : Worst Tetrahedron Smoothness %g Gamma %g NbFair = %d", - cc, minJGlob, minGGlob, nbfair); - else - Msg::Warning("%s : Worst Tetrahedron Smoothness %g (%d negative jacobians) " + Msg::Warning("%s : Worst Tetrahedron Smoothness %g Gamma %g NbFair = %d NbBad = %d", + cc, minJGlob, minGGlob, nbfair, bad.size()); + else + Msg::Info("%s : Worst Tetrahedron Smoothness %g (%d negative jacobians) " "Worst Gamma %g Avg Smoothness %g", cc, minJGlob, bad.size(), minGGlob, avg / (count ? count : 1)); } @@ -1407,7 +1383,8 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete) if (!linear){ hot.ensureMinimumDistorsion(0.1); - checkHighOrderTriangles("final mesh", m, bad, worst); + checkHighOrderTriangles("Final mesh", m, bad, worst); + checkHighOrderTetrahedron("Final mesh", m, bad, worst); } // m->writeMSH("CORRECTED.msh"); diff --git a/Mesh/highOrderSmoother.cpp b/Mesh/highOrderSmoother.cpp index 42f21fcbf2f8a44838d86468f41061089b8356d4..65a335a661fc889c85be69eaf69b8f152a46987b 100644 --- a/Mesh/highOrderSmoother.cpp +++ b/Mesh/highOrderSmoother.cpp @@ -402,7 +402,7 @@ void highOrderSmoother::optimize(GFace * gf, // } // then try to swap for better configurations - smooth(gf, !CTX::instance()->mesh.highOrderNoMetric); + //smooth(gf, !CTX::instance()->mesh.highOrderNoMetric); // for (int i=0;i<100;i++){ @@ -411,7 +411,7 @@ void highOrderSmoother::optimize(GFace * gf, // printf("%d swaps\n",nbSwap); // } - // smooth(gf,true); + smooth(gf,true); // smooth(gf,true); // smooth(gf,true); // smooth(gf,true); @@ -838,10 +838,8 @@ void highOrderSmoother::smooth(std::vector<MElement*> &all) { #if defined(HAVE_TAUCS) linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; - printf("coucou\n"); #elif defined(HAVE_PETSC) linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; - printf("coucou PETSC\n"); #else linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>; lsys->setNoisy(1); @@ -854,9 +852,9 @@ void highOrderSmoother::smooth(std::vector<MElement*> &all) std::vector<MElement*> layer, v; double minD; - getDistordedElements(all, 0.85, v, minD); + getDistordedElements(all, 0.15, v, minD); - Msg::Info("%d elements / %d distorted min Disto = %g\n", + Msg::Info("%d elements / %d distorted min Disto = %g", all.size(), v.size(), minD); if (!v.size()); diff --git a/Mesh/highOrderTools.cpp b/Mesh/highOrderTools.cpp index c20e7ba8fdcc2aab7f201153527143562955a45e..ea884c357ece57e0a21819ff511f9ed732b1230c 100644 --- a/Mesh/highOrderTools.cpp +++ b/Mesh/highOrderTools.cpp @@ -481,6 +481,55 @@ void highOrderTools::computeStraightSidedPositions () } } + for(GModel::riter it = _gm->firstRegion(); it != _gm->lastRegion(); ++it){ + for (int i=0;i<(*it)->mesh_vertices.size();i++){ + MVertex *v = (*it)->mesh_vertices[i]; + _targetLocation[v] = SVector3(v->x(),v->y(),v->z()); + } + for (int i=0;i<(*it)->tetrahedra.size();i++){ + _dim = 3; + MTetrahedron *t = (*it)->tetrahedra[i]; + MTetrahedron t_1 ((*it)->tetrahedra[i]->getVertex(0), + (*it)->tetrahedra[i]->getVertex(1), + (*it)->tetrahedra[i]->getVertex(2), + (*it)->tetrahedra[i]->getVertex(3)); + const polynomialBasis* fs = t->getFunctionSpace(); + for (int j=0;j<t->getNumVertices();j++){ + if (t->getVertex(j)->onWhat() == *it){ + double t1 = fs->points(j, 0); + double t2 = fs->points(j, 1); + double t3 = fs->points(j, 2); + SPoint3 pc; t_1.pnt(t1, t2, t3,pc); + _straightSidedLocation [t->getVertex(j)] = + SVector3(pc.x(),pc.y(),pc.z()); + } + } + } + for (int i=0;i<(*it)->hexahedra.size();i++){ + _dim = 3; + MHexahedron *h = (*it)->hexahedra[i]; + MHexahedron h_1 ((*it)->hexahedra[i]->getVertex(0), + (*it)->hexahedra[i]->getVertex(1), + (*it)->hexahedra[i]->getVertex(2), + (*it)->hexahedra[i]->getVertex(3), + (*it)->hexahedra[i]->getVertex(4), + (*it)->hexahedra[i]->getVertex(5), + (*it)->hexahedra[i]->getVertex(6), + (*it)->hexahedra[i]->getVertex(7)); + const polynomialBasis* fs = h->getFunctionSpace(); + for (int j=0;j<h->getNumVertices();j++){ + if (h->getVertex(j)->onWhat() == *it){ + double t1 = fs->points(j, 0); + double t2 = fs->points(j, 1); + double t3 = fs->points(j, 2); + SPoint3 pc; h_1.pnt(t1, t2, t3,pc); + _straightSidedLocation [h->getVertex(j)] = + SVector3(pc.x(),pc.y(),pc.z()); + } + } + } + } + Msg::Info("highOrderTools has been set up : %d nodes are considered",_straightSidedLocation.size()); } @@ -621,10 +670,10 @@ void highOrderTools::ensureMinimumDistorsion (std::vector<MElement*> &all, double minD; std::vector<MElement*> disto; getDistordedElements(all, threshold, disto, minD); - if (num == disto.size())break; + // if (num == disto.size())break; if (!disto.size())break; num = disto.size(); - Msg::Info("fixing %d bad curved elements (worst disto %g)",disto.size(),minD); + Msg::Info("Fixing %d bad curved elements (worst disto %g)",disto.size(),minD); for (int i=0;i<disto.size();i++){ ensureMinimumDistorsion(disto[i],threshold); } diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 2fff56356f959c9d82d2d6b1dc4dd1f619eab0fe..828d00a090ba3fe71191203eb04344daf5662393 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -1576,19 +1576,22 @@ void meshGFace::operator() (GFace *gf) Msg::Debug("Type %d %d triangles generated, %d internal vertices", gf->geomType(), gf->triangles.size(), gf->mesh_vertices.size()); - // test : recompute the background mesh using a PDE - /* - if (backgroundMesh::current()){ + // do the 2D mesh in several passes. For second and other passes, + // a background mesh is constructed with the previous mesh and + // nodal values of the metric are computed that take into account + // complex size fields that are tedious to evaluate on the fly + if (!twoPassesMesh)return; + twoPassesMesh--; + if (backgroundMesh::current()){ backgroundMesh::unset(); - } - else{ - backgroundMesh::set(gf); - char name[256]; - sprintf(name,"bgm-%d.pos",gf->tag()); - backgroundMesh::current()->print(name,gf); - (*this)(gf); - } - */ + } + backgroundMesh::set(gf); + char name[256]; + sprintf(name,"bgm-%d.pos",gf->tag()); + backgroundMesh::current()->print(name,gf); + sprintf(name,"cross-%d.pos",gf->tag()); + backgroundMesh::current()->print(name,gf,1); + (*this)(gf); } bool checkMeshCompound(GFaceCompound *gf, std::list<GEdge*> &edges) diff --git a/Mesh/meshGFace.h b/Mesh/meshGFace.h index e2c870cb331ebaef53010147a0477648cce98f27..3f79ce359b3926e0b8321207d80b719eacb97906 100644 --- a/Mesh/meshGFace.h +++ b/Mesh/meshGFace.h @@ -17,15 +17,16 @@ class GFaceCompound; // Create the mesh of the face class meshGFace { const bool repairSelfIntersecting1dMesh; + int twoPassesMesh; public : - meshGFace (bool r = true, bool s = false) : repairSelfIntersecting1dMesh(r){} + meshGFace (bool r = true, int t = 0) : repairSelfIntersecting1dMesh(r), twoPassesMesh(t){} void operator () (GFace *); }; // Destroy the mesh of the face class deMeshGFace { public : - deMeshGFace (bool s = false){} + deMeshGFace (){} void operator () (GFace *); }; diff --git a/Mesh/meshGFaceBDS.cpp b/Mesh/meshGFaceBDS.cpp index 7478cde5149ca89521b5ea2fd94588b487fc8674..ef3e7c514c2efa1e292e2832551e3d0cf6fead38 100644 --- a/Mesh/meshGFaceBDS.cpp +++ b/Mesh/meshGFaceBDS.cpp @@ -558,7 +558,8 @@ void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split) (coord * e->p1->u + (1 - coord) * e->p2->u)*m.scalingU, (coord * e->p1->v + (1 - coord) * e->p2->v)*m.scalingV, mid->X,mid->Y,mid->Z); - mid->lc() = 0.5 * (e->p1->lc() + e->p2->lc()); + // mid->lc() = exp(0.5 * (log(e->p1->lc()) + log(e->p2->lc()))); + mid->lc() = 0.5 * (e->p1->lc() + e->p2->lc()); } if(!m.split_edge(e, mid)) m.del_point(mid); else nb_split++; diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp index eb635f6c31373825cffeb21743042eb6ee35217f..d166913081869e9ab61ecbd61c9dd856f387e1bc 100644 --- a/Mesh/meshGFaceDelaunayInsertion.cpp +++ b/Mesh/meshGFaceDelaunayInsertion.cpp @@ -616,10 +616,17 @@ static void insertAPoint(GFace *gf, std::set<MTri3*,compareTri3Ptr>::iterator it // printf("the new point is %g %g\n",p.x(),p.y()); MVertex *v = new MFaceVertex(p.x(), p.y(), p.z(), gf, center[0], center[1]); v->setIndex(Us.size()); - double lc1 = ((1. - uv[0] - uv[1]) * vSizes[ptin->tri()->getVertex(0)->getIndex()] + - uv[0] * vSizes[ptin->tri()->getVertex(1)->getIndex()] + - uv[1] * vSizes[ptin->tri()->getVertex(2)->getIndex()]); - double lc = BGM_MeshSize(gf, center[0], center[1], p.x(), p.y(), p.z()); + double lc1,lc; + if (backgroundMesh::current()){ + lc1 = lc = + backgroundMesh::current()->operator()(center[0], center[1], 0.0); + } + else { + lc1 = ((1. - uv[0] - uv[1]) * vSizes[ptin->tri()->getVertex(0)->getIndex()] + + uv[0] * vSizes[ptin->tri()->getVertex(1)->getIndex()] + + uv[1] * vSizes[ptin->tri()->getVertex(2)->getIndex()]); + lc = BGM_MeshSize(gf, center[0], center[1], p.x(), p.y(), p.z()); + } //SMetric3 metr = BGM_MeshMetric(gf, center[0], center[1], p.x(), p.y(), p.z()); // vMetricsBGM.push_back(metr); vSizesBGM.push_back(lc); diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp index 3705a67305a9332c41ee51b94fa208eac07b4c90..911f522b669c0bfea356af8fe8ed2a35d891df68 100644 --- a/Mesh/meshGFaceOptimize.cpp +++ b/Mesh/meshGFaceOptimize.cpp @@ -1764,7 +1764,7 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1) for (int k=0;k<elist[0];k++){ int i1 = elist[1+3*k],i2 = elist[1+3*k+1],an=elist[1+3*k+2]; // FIXME !! - if (an == 100000){// || an == 1000){ + if (an == 100000 || an == 1000){ toProcess.push_back(std::make_pair(n2t[i1],n2t[i2])); Msg::Debug("Extra edge found in blossom algorithm, optimization will be required"); } diff --git a/Mesh/meshRefine.cpp b/Mesh/meshRefine.cpp index 2ee8cca87607a0ebde0c3cb2099a7baef77bb009..1b4fa1e6f65bf0685710a5d0b0cd65eeb8f12219 100644 --- a/Mesh/meshRefine.cpp +++ b/Mesh/meshRefine.cpp @@ -377,11 +377,17 @@ void RefineMesh(GModel *m, bool linear, bool splitIntoQuads, bool splitIntoHexas // mesh for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); ++it) Subdivide(*it); - for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) + for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it){ Subdivide(*it, splitIntoQuads, splitIntoHexas, faceVertices); + if (splitIntoQuads){ + recombineIntoQuads(*it,true,true); + } + } for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it) Subdivide(*it, splitIntoHexas, faceVertices); + + double t2 = Cpu(); Msg::StatusBar(2, true, "Done refining mesh (%g s)", t2 - t1); } diff --git a/Mesh/qualityMeasures.cpp b/Mesh/qualityMeasures.cpp index c311c180b0fa43e82cf5d24a1141a016f88ddc16..18fe5f57aa5f5e87c7359fbe14ff4a97c12ae9b5 100644 --- a/Mesh/qualityMeasures.cpp +++ b/Mesh/qualityMeasures.cpp @@ -203,10 +203,10 @@ double mesh_functional_distorsion(MElement *t, double u, double v) double sign = 1.0; prosca(normal1, normal, &sign); double det = norm3(normal) * (sign > 0 ? 1. : -1.) / nn; - //double det = norm3(normal); - // compute distorsion - // double dist = std::min(1. / det, det); + // printf("%g %g : %g : %g n1 (%g,%g,%g)\n",u,v,sign,det, normal1[0], normal1[1], normal1[2]); + // printf("n (%g,%g,%g)\n", normal[0], normal[1], normal[2]); + return det; } @@ -305,17 +305,27 @@ double mesh_functional_distorsion_p2_exact(MTriangle *t) double mesh_functional_distorsion_pN(MElement *t) { const bezierBasis *jac = t->getJacobianFuncSpace()->bezier; - // jac->monomials.print("coucou"); fullVector<double>Ji(jac->points.size1()); + // printf("%d points for bez \n",jac->points.size1()); for (int i=0;i<jac->points.size1();i++){ - const double u = jac->points(i,0); - const double v = jac->points(i,1); - Ji(i) = mesh_functional_distorsion(t,u,v); + double u = jac->points(i,0); + double v = jac->points(i,1); + + // JF : bezier points are defined in the [0,1] x [0,1] quad + if (t->getType() == TYPE_QUA){ + u = -1 + 2*u; + v = -1 + 2*v; + } + + Ji(i) = mesh_functional_distorsion(t,u,v); + // printf("J(%g,%g) = %12.5E\n",u,v,Ji(i)); } fullVector<double> Bi( jac->matrixLag2Bez.size1() ); jac->matrixLag2Bez.mult(Ji,Bi); + // jac->matrixLag2Bez.print("Lag2Bez"); + return *std::min_element(Bi.getDataPtr(),Bi.getDataPtr()+Bi.size()); } diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index 5776a7109f5fae8e541ba7ca07b275ca8d2768d4..0ef87ad82679a4c6dbf1b8c368766eb14fdcd64d 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -108,6 +108,8 @@ static fullMatrix<double> generateExposantsQuad(int order) } } + // exposants.print("expq"); + return exposants; } static int nbdoftriangle(int order) { return (order + 1) * (order + 2) / 2; } @@ -760,19 +762,19 @@ static fullMatrix<double> generatePointsPrism(int order, bool serendip) return point; } -static fullMatrix<double> generatePointsQuad(int order, bool serendip) +static fullMatrix<double> generatePointsQuadRecur(int order, bool serendip) { int nbPoints = serendip ? order*4 : (order+1)*(order+1); fullMatrix<double> point(nbPoints, 2); if (order > 0) { - point(0, 0) = 0; - point(0, 1) = 0; + point(0, 0) = -1; + point(0, 1) = -1; point(1, 0) = 1; - point(1, 1) = 0; + point(1, 1) = -1; point(2, 0) = 1; point(2, 1) = 1; - point(3, 0) = 0; + point(3, 0) = -1; point(3, 1) = 1; if (order > 1) { @@ -786,8 +788,8 @@ static fullMatrix<double> generatePointsQuad(int order, bool serendip) point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order; } } - if (order > 2 && !serendip) { - fullMatrix<double> inner = generatePointsQuad(order - 2, false); + if (order >= 2 && !serendip) { + fullMatrix<double> inner = generatePointsQuadRecur(order - 2, false); inner.scale(1. - 2./order); point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); } @@ -797,9 +799,22 @@ static fullMatrix<double> generatePointsQuad(int order, bool serendip) point(0, 0) = 0; point(0, 1) = 0; } + + + return point; +} + +static fullMatrix<double> generatePointsQuad(int order, bool serendip){ + fullMatrix<double> point = generatePointsQuadRecur(order, serendip); + // rescale to [0,1] x [0,1] + for (int i=0;i<point.size1();i++){ + point(i,0) = (1.+point(i,0))*.5; + point(i,1) = (1.+point(i,1))*.5; + } return point; } + // Sub Control Points static std::vector< fullMatrix<double> > generateSubPointsLine(int order) { @@ -1231,6 +1246,7 @@ const bezierBasis *bezierBasis::find(int tag) B.points = generatePointsQuad(F->order,false); dimSimplex = 0; subPoints = generateSubPointsQuad(F->order); + // B.points.print("points"); break; } case TYPE_PRI : { diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp index b90a654082cd5370004bf22f6baa16cfb761ba60..64aefa92e5df859cff75ff074a05df35b9283723 100644 --- a/Numeric/Numeric.cpp +++ b/Numeric/Numeric.cpp @@ -522,7 +522,7 @@ void FindCubicRoots(const double coef[4], double real[3], double imag[3]) double d = coef[0]; if(!a || !d){ - Msg::Error("Degenerate cubic: use a second degree solver!"); + // Msg::Error("Degenerate cubic: use a second degree solver!"); return; } diff --git a/benchmarks/2d/naca12_2d.geo b/benchmarks/2d/naca12_2d.geo index 70ba9b91ff4a8d860daabdb9c452731a6d502651..6d1b45d0d4653271f039e6b3dda161886ff8126d 100644 --- a/benchmarks/2d/naca12_2d.geo +++ b/benchmarks/2d/naca12_2d.geo @@ -1,6 +1,6 @@ -lc = 0.2 ; -lc2 = 10 ; -lc3 = 0.1 ; +lc = .033 ; +lc2 = 2.2 ; +lc3 = .03 ; Point(1) = {1.000000e+00,0.000000e+00,0.000000e+00,lc3}; Point(2) = {9.997533e-01,0.000000e+00,-3.498543e-05,lc}; Point(3) = {9.990134e-01,0.000000e+00,-1.398841e-04,lc}; diff --git a/benchmarks/2d/wing-splines.geo b/benchmarks/2d/wing-splines.geo index 0aea8841a1e4b89961e10d51b4c16029446fc027..49d30ddc7b75270e0cac582bb4c32fcaee9c1a20 100644 --- a/benchmarks/2d/wing-splines.geo +++ b/benchmarks/2d/wing-splines.geo @@ -1,7 +1,7 @@ scale = .01 ; -lc_wing = 0.001 * scale ; +lc_wing = 0.05 * scale ; lc_box = 10 * scale ; Point(3895) = {1.177410e-02*scale,-2.768003e-03*scale,0,lc_wing}; @@ -520,32 +520,32 @@ Point(4) = {-4.447736e+01*scale,-4.504225e+01*scale,0,lc_box}; Point(1) = {4.552264e+01*scale,-4.504225e+01*scale,0,lc_box}; //one -Spline(1) = {3846,3981,4001,3942,3940,3889,3892,3891,3943,3895, +Spline(1) = {3846,3981,4001,3942,3940,3892,3943,3895, 3897,3896,3968,3995,4003,3857,3856,3860,3861,3863, - 3864,3865,3866,3867,3868,3869,3870,3871,3872,3977, + 3864,3865,3866,3867,3869,3870,3871,3872,3977, 3877,3876,3878,3934,3873,3874,3875,3935,3880,3879, 3881,3936,3882,3883,3885,3884,1218,3933,3996,3989, - 3990,3978,3979,3974,3973,3963,3947,3948,3904,3903, + 3990,3978,3979,3974,3973,3963,3948,3904,3903, 3946,3902,3901,3900,3908,3907,3951,3950,3847}; Spline(2) = {3847,3949,3952,3905,3906,3909,3969,3970,3997,3998, 4004,3959,3960,3972,3984,3988,3961,3962,3937,3938, 3886,3887,3888,3993,3994,3971,3918,3919,3920,3956, - 3955,3965,3966,3910,3913,3912,3911,3914,3915,3916, + 3965,3910,3913,3912,3914,3915,3916, 3917,3953,3954,3964,3975,3992,3991,3999,3939,3967, - 3987,3985,3986,4002,3922,4005,3851,3850,3853,3852, - 3849,3848,3921,3983,3982,3976,3929,3958,3928,3957, - 3927,3926,3925,3924,3932,3931,3930,3923,3862,3859, + 3987,3986,4002,3922,4005,3851,3850,3853,3852, + 3849,3848,3921,3983,3982,3976,3929,3958,3957, + 3927,3926,3925,3924,3931,3930,3923,3862,3859, 3858,3855,3854,3945,3944,3899,3898,3894,3890,3893, 3941,4000,3980,3846}; // two Spline(3) = {4063,4062,4061,4114,4153,4178,4179,4191,4203,4109, - 4202,4199,4201,4200,4100,4099,4045,4044,4043,4147, + 4202,4201,4200,4100,4099,4045,4044,4043,4147, 4146,4180,4167,4166,4134,4133,4098,4097,4042,4041, 4040,4095,4096,4132,4131,4165,4164,4163,4130,4129, 4094,4093,4039,4038,4037,4092,4091,4128,4127,4162, 4161,4183,4160,4159,4126,4125,4088,4087,4033,4032, - 4032,4031,4086,4085,4124,4123,4158,4157,4156,4122, + 4031,4086,4085,4124,4123,4158,4157,4156,4122, 4121,4081,4080,4020,4019,4018,4143,4118,4022,4016, 4015,4011,4010,4009,4219,4177,4176,4149,4059,4058, 4055,4113,4110,4213,4210,4217,4006}; @@ -560,24 +560,24 @@ Spline(6) = {4008,4030,4084,4194,4195,4154,4155,4119,4120,4089, 4106,4052,4053,4054,4107,4108,4141,4142,4174,4175, 4187,4188,4145,4046,4047,4048,4196,4197,4198,4189, 4190,4214,4181,4182,4151,4152,4064,4065,4066,4205, - 4206,4207,4072,4074,4073,4076,4075,4079,4078,4077, + 4206,4207,4072,4074,4076,4079,4078,4077, 4068,4067,4069,4070,4071,4115,4116,4204,4063}; //three Spline(10) = {4298,4297,4222}; Spline(11) = {4222,4250,4252,4221}; -Spline(12) = {4221,4251,4299,4335,4337,4267,4294,4269,4233,4234, - 4273,4293,4314,4317,4317,4318,4318,4274,4235,4236, - 4237,4301,4319,4321,4320,4322,4347,4323,4324,4325, - 4276,4238,4240,4239,4241,4277,4326,4327,4328,4350, +Spline(12) = {4221,4251,4299,4335,4337,4267,4269,4233,4234, + 4273,4293,4314,4317,4318,4274,4235,4236, + 4237,4301,4319,4321,4322,4347,4323,4324,4325, + 4276,4238,4240,4241,4277,4326,4327,4328,4350, 4348,4349,4332,4333,4334,4278,4247,4248,4249,4282, 4283,4341,4342,4343,4289,4290,4286,4255,4257,4256, - 4346,4288,4287,4260,4259,4258,4262,4261,4264,4264, - 4263,4265,4266,4302,4304,4305,4306,4307,4308, + 4346,4288,4287,4260,4259,4258,4262,4261,4264, + 4263,4265,4266,4304,4307, 4309,4345,4344,4254,4253,4285,4284,4340,4339,4338, 4246,4245,4281,4280,4279,4244,4243,4242,4296,4295, - 4300,4330,4331,4329,4232,4231,4230,4229,4228,4227, - 4225,4226,4312,4223,4224,4311,4310,4275,4316,4315, + 4300,4331,4329,4232,4231,4230,4229,4228,4227, + 4225,4226,4312,4224,4311,4310,4275,4316,4315, 4313,4292,4272,4271,4270,4268,4291,4336,4298}; //box diff --git a/benchmarks/2d/wing.geo b/benchmarks/2d/wing.geo index febf083bd3a23fbcf2f8389d6d62681ccb3d8841..8cc01c722036375e4251d55e9ba345b0cb43c3fe 100644 --- a/benchmarks/2d/wing.geo +++ b/benchmarks/2d/wing.geo @@ -1,6 +1,6 @@ scale = 2 ; -lc1 = 5.e-3 *scale ; +lc1 = 15.e-3 *scale ; lc2 = 1.e-2 *scale ; lc3 = 10 *scale ;