From 4cbdd579cdd0f601dc2d491163368c14bfd3dd7d Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 18 Sep 2010 11:18:27 +0000 Subject: [PATCH] * new option to select recombination algo (using subdivisionAlgo==3 is a bad idea) * new option to recombine all tri meshes, whatever the specific setting for a given surface * libmatch -> libblossom (there's a libMatch.dylib in the default MacOS install) --- CMakeLists.txt | 10 ++++------ Common/Context.h | 1 + Common/DefaultOptions.h | 4 ++++ Common/Options.cpp | 32 +++++++++++++++++++++++++++++++- Common/Options.h | 2 ++ Fltk/optionWindow.cpp | 33 +++++++++++++++++++++++++-------- Geo/Geo.cpp | 1 + Mesh/Generator.cpp | 6 +++--- Mesh/meshGEdge.cpp | 2 +- Mesh/meshGFace.cpp | 6 ++++-- Mesh/meshGFaceOptimize.cpp | 5 ++--- Mesh/meshGFaceTransfinite.cpp | 4 ++-- Mesh/meshGRegionTransfinite.cpp | 5 ++++- benchmarks/2d/recombine.geo | 1 - 14 files changed, 84 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58386f088c..6c6c4703b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -702,17 +702,15 @@ if(ENABLE_ACIS) endif(ENABLE_ACIS) if(ENABLE_MATCH) - find_library(MATCH_LIB match PATH_SUFFIXES) + find_library(MATCH_LIB blossom PATH_SUFFIXES) find_library(CONCORDE_LIB concorde PATH_SUFFIXES) if(MATCH_LIB AND CONCORDE_LIB) find_path(CONCORDE_INC "concorde.h" PATH_SUFFIXES) find_path(MATCH_INC "match.h" PATH_SUFFIXES) if(MATCH_INC AND CONCORDE_INC) - set_config_option(HAVE_MATCH "Match") - list(APPEND EXTERNAL_LIBRARIES ${MATCH_LIB}) - list(APPEND EXTERNAL_LIBRARIES ${CONCORDE_LIB}) - list(APPEND EXTERNAL_INCLUDES ${MATCH_INC}) - list(APPEND EXTERNAL_INCLUDES ${CONCORDE_INC}) + set_config_option(HAVE_MATCH "Match") + list(APPEND EXTERNAL_LIBRARIES ${MATCH_LIB} ${CONCORDE_LIB}) + list(APPEND EXTERNAL_INCLUDES ${MATCH_INC} ${CONCORDE_INC}) endif(MATCH_INC AND CONCORDE_INC) endif(MATCH_LIB AND CONCORDE_LIB) endif(ENABLE_MATCH) diff --git a/Common/Context.h b/Common/Context.h index 6999f63533..662170ef44 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -29,6 +29,7 @@ struct contextMeshOptions { int lcFromPoints, lcFromCurvature, lcExtendFromBoundary; int dual, voronoi, drawSkinOnly, colorCarousel, labelSampling; int fileFormat, nbSmoothing, algo2d, algo3d, algoSubdivide; + int algoRecombine, recombineAll; int order, secondOrderLinear, secondOrderIncomplete; int secondOrderExperimental, meshOnlyVisible; int smoothInternalEdges, minCircPoints, minCurvPoints; diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index dde2fc4b5b..1c7470f07e 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1215,6 +1215,10 @@ StringXNumber MeshOptions_Number[] = { { F|O, "RandomFactor" , opt_mesh_rand_factor , 1.e-9 , "Random factor used in the 2D meshing algorithm (should be increased if " "RandomFactor * size(triangle)/size(model) approaches machine accuracy)" }, + { F|O, "RecombinationAlgorithm" , opt_mesh_algo_recombine , 0 , + "Mesh recombination algorithm (0=standard, 1=blossom)" }, + { F|O, "RecombineAll" , opt_mesh_recombine_all , 0 , + "Apply recombination algorithm to all surfaces, ignoring per-surface spec" }, { F|O, "RefineSteps" , opt_mesh_refine_steps , 10 , "Number of refinement steps in the MeshAdapt-based 2D algorithms" }, { F|O, "Remove4Triangles" , opt_mesh_remove_4_triangles , 0 , diff --git a/Common/Options.cpp b/Common/Options.cpp index a70eec2f55..0778cdac46 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -5604,12 +5604,42 @@ double opt_mesh_algo2d(OPT_ARGS_NUM) return CTX::instance()->mesh.algo2d; } +double opt_mesh_algo_recombine(OPT_ARGS_NUM) +{ + if(action & GMSH_SET){ + CTX::instance()->mesh.algoRecombine = (int)val; + if(CTX::instance()->mesh.algoRecombine < 0 && + CTX::instance()->mesh.algoRecombine > 1) + CTX::instance()->mesh.algoRecombine = 0; + } +#if defined(HAVE_FLTK) + if(FlGui::available() && (action & GMSH_GUI)) { + FlGui::instance()->options->mesh.choice[1]->value + (CTX::instance()->mesh.algoRecombine); + } +#endif + return CTX::instance()->mesh.algoRecombine; +} + +double opt_mesh_recombine_all(OPT_ARGS_NUM) +{ + if(action & GMSH_SET){ + CTX::instance()->mesh.recombineAll = (int)val; + } +#if defined(HAVE_FLTK) + if(FlGui::available() && (action & GMSH_GUI)) + FlGui::instance()->options->mesh.butt[21]->value + (CTX::instance()->mesh.recombineAll); +#endif + return CTX::instance()->mesh.recombineAll; +} + double opt_mesh_algo_subdivide(OPT_ARGS_NUM) { if(action & GMSH_SET){ CTX::instance()->mesh.algoSubdivide = (int)val; if(CTX::instance()->mesh.algoSubdivide < 0 && - CTX::instance()->mesh.algoSubdivide > 3) + CTX::instance()->mesh.algoSubdivide > 2) CTX::instance()->mesh.algoSubdivide = 0; } #if defined(HAVE_FLTK) diff --git a/Common/Options.h b/Common/Options.h index 1ac5159857..b0afa9e771 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -524,6 +524,8 @@ double opt_mesh_bdf_field_format(OPT_ARGS_NUM); double opt_mesh_nb_smoothing(OPT_ARGS_NUM); double opt_mesh_algo2d(OPT_ARGS_NUM); double opt_mesh_algo3d(OPT_ARGS_NUM); +double opt_mesh_algo_recombine(OPT_ARGS_NUM); +double opt_mesh_recombine_all(OPT_ARGS_NUM); double opt_mesh_algo_subdivide(OPT_ARGS_NUM); double opt_mesh_mesh_only_visible(OPT_ARGS_NUM); double opt_mesh_min_circ_points(OPT_ARGS_NUM); diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp index 54d8c022d2..c8fb6db7fc 100644 --- a/Fltk/optionWindow.cpp +++ b/Fltk/optionWindow.cpp @@ -451,6 +451,8 @@ static void mesh_options_ok_cb(Fl_Widget *w, void *data) opt_mesh_algo3d(0, GMSH_SET, (o->mesh.choice[3]->value() == 0) ? ALGO_3D_DELAUNAY : ALGO_3D_FRONTAL); + opt_mesh_algo_recombine(0, GMSH_SET, o->mesh.choice[1]->value()); + opt_mesh_recombine_all(0, GMSH_SET, o->mesh.butt[21]->value()); opt_mesh_algo_subdivide(0, GMSH_SET, o->mesh.choice[5]->value()); opt_mesh_color_carousel(0, GMSH_SET, o->mesh.choice[4]->value()); opt_mesh_quality_type(0, GMSH_SET, o->mesh.choice[6]->value()); @@ -1972,11 +1974,15 @@ optionWindow::optionWindow(int deltaFontSize) {"Frontal", 0, 0, 0}, {0} }; + static Fl_Menu_Item menu_recombination_algo[] = { + {"Standard", 0, 0, 0}, + {"Blossom", 0, 0, 0}, + {0} + }; static Fl_Menu_Item menu_subdivision_algo[] = { {"None", 0, 0, 0}, {"All Quads", 0, 0, 0}, {"All Hexas", 0, 0, 0}, - {"All Quads (Blossom)", 0, 0, 0}, {0} }; @@ -1992,14 +1998,25 @@ optionWindow::optionWindow(int deltaFontSize) mesh.choice[3]->align(FL_ALIGN_RIGHT); mesh.choice[3]->callback(mesh_options_ok_cb); + mesh.choice[1] = new Fl_Choice + (L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Recombination algorithm"); + mesh.choice[1]->menu(menu_recombination_algo); + mesh.choice[1]->align(FL_ALIGN_RIGHT); + mesh.choice[1]->callback(mesh_options_ok_cb); + + mesh.butt[21] = new Fl_Check_Button + (L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Recombine all triangular meshes"); + mesh.butt[21]->type(FL_TOGGLE_BUTTON); + mesh.butt[21]->callback(mesh_options_ok_cb); + mesh.choice[5] = new Fl_Choice - (L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Subdivision algorithm"); + (L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Subdivision algorithm"); mesh.choice[5]->menu(menu_subdivision_algo); mesh.choice[5]->align(FL_ALIGN_RIGHT); mesh.choice[5]->callback(mesh_options_ok_cb); mesh.value[0] = new Fl_Value_Input - (L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Smoothing steps"); + (L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Smoothing steps"); mesh.value[0]->minimum(0); mesh.value[0]->maximum(100); mesh.value[0]->step(1); @@ -2007,7 +2024,7 @@ optionWindow::optionWindow(int deltaFontSize) mesh.value[0]->callback(mesh_options_ok_cb); mesh.value[2] = new Fl_Value_Input - (L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Element size factor"); + (L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Element size factor"); mesh.value[2]->minimum(0.001); mesh.value[2]->maximum(1000); mesh.value[2]->step(0.01); @@ -2015,17 +2032,17 @@ optionWindow::optionWindow(int deltaFontSize) mesh.value[2]->callback(mesh_options_ok_cb); mesh.value[25] = new Fl_Value_Input - (L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Minimum element size"); + (L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Minimum element size"); mesh.value[25]->align(FL_ALIGN_RIGHT); mesh.value[25]->callback(mesh_options_ok_cb); mesh.value[26] = new Fl_Value_Input - (L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Maximum element size"); + (L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Maximum element size"); mesh.value[26]->align(FL_ALIGN_RIGHT); mesh.value[26]->callback(mesh_options_ok_cb); mesh.value[3] = new Fl_Value_Input - (L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Element order"); + (L + 2 * WB, 2 * WB + 10 * BH, IW, BH, "Element order"); mesh.value[3]->minimum(1); mesh.value[3]->maximum(2); mesh.value[3]->step(1); @@ -2033,7 +2050,7 @@ optionWindow::optionWindow(int deltaFontSize) mesh.value[3]->callback(mesh_options_ok_cb); mesh.butt[4] = new Fl_Check_Button - (L + 2 * WB, 2 * WB + 9 * BH, BW, BH, "Use incomplete high order elements"); + (L + 2 * WB, 2 * WB + 11 * BH, BW, BH, "Use incomplete high order elements"); mesh.butt[4]->type(FL_TOGGLE_BUTTON); mesh.butt[4]->callback(mesh_options_ok_cb); diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp index 53d33fd68c..d383b533d6 100644 --- a/Geo/Geo.cpp +++ b/Geo/Geo.cpp @@ -591,6 +591,7 @@ Surface *Create_Surface(int Num, int Typ) pS->Typ = Typ; pS->Method = MESH_UNSTRUCTURED; pS->Recombine = 0; + pS->RecombineAngle = 45; pS->Recombine_Dir = -1; pS->TypeOfMapping = 1; pS->TransfiniteSmoothing = -1; diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp index f8fba46418..3bebd69de2 100644 --- a/Mesh/Generator.cpp +++ b/Mesh/Generator.cpp @@ -474,10 +474,10 @@ static void Mesh2D(GModel *m) GFaceCompound *gfc = (GFaceCompound*) gf; if(gfc->getNbSplit() != 0) continue; } - int recombine = gf->meshAttributes.recombine; + int rec = (CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine); Msg::Info("Lloyd optimization for face %d", gf->tag()); - gf->lloyd(25, recombine); - if(recombine) recombineIntoQuads(gf); + gf->lloyd(25, rec); + if(rec) recombineIntoQuads(gf); } } diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp index 655e1e6f40..d8144024d3 100644 --- a/Mesh/meshGEdge.cpp +++ b/Mesh/meshGEdge.cpp @@ -384,7 +384,7 @@ void meshGEdge::operator() (GEdge *ge) N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.)); } - if(CTX::instance()->mesh.algoSubdivide == 3 && N%2 == 0)N++; + if(CTX::instance()->mesh.algoRecombine == 1 && N%2 == 0) N++; // printFandPrimitive(ge->tag(),Points); diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 44c8a4ffed..edbec3bfd0 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -898,7 +898,8 @@ static bool meshGenerator(GFace *gf, int RECUR_ITER, // delete the mesh delete m; - if(gf->meshAttributes.recombine && !CTX::instance()->mesh.optimizeLloyd) + if((CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine) && + !CTX::instance()->mesh.optimizeLloyd) recombineIntoQuads(gf); computeElementShapes(gf, gf->meshStatistics.worst_element_shape, @@ -1468,7 +1469,8 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true) // delete the mesh delete m; - if(gf->meshAttributes.recombine && !CTX::instance()->mesh.optimizeLloyd) + if((CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine) && + !CTX::instance()->mesh.optimizeLloyd) recombineIntoQuads(gf); computeElementShapes(gf, gf->meshStatistics.worst_element_shape, diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp index e4b602c2ac..e2a7d50156 100644 --- a/Mesh/meshGFaceOptimize.cpp +++ b/Mesh/meshGFaceOptimize.cpp @@ -1337,10 +1337,9 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1) std::set<MElement*> touched; - if(CTX::instance()->mesh.algoSubdivide == 3){ + if(CTX::instance()->mesh.algoRecombine == 1){ #ifdef HAVE_MATCH int ncount = gf->triangles.size(); - // printf("%d %d ----------------\n",CTX::instance()->mesh.algoSubdivide, ncount); if (ncount % 2 == 0) { int ecount = cubicGraph ? pairs.size() + makeGraphPeriodic.size() : pairs.size(); printf("%d internal %d closed\n",pairs.size(), makeGraphPeriodic.size()); @@ -1552,7 +1551,7 @@ void recombineIntoQuads(GFace *gf) gf->model()->writeMSH("raw.msh"); for(int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) laplaceSmoothing(gf); - if(success && CTX::instance()->mesh.algoSubdivide == 3){ + if(success && CTX::instance()->mesh.algoRecombine == 1){ gf->model()->writeMSH("smoothed.msh"); int COUNT = 0; char NAME[256]; diff --git a/Mesh/meshGFaceTransfinite.cpp b/Mesh/meshGFaceTransfinite.cpp index e94cfb20bb..ce00a080ec 100644 --- a/Mesh/meshGFaceTransfinite.cpp +++ b/Mesh/meshGFaceTransfinite.cpp @@ -420,7 +420,7 @@ int MeshTransfiniteSurface(GFace *gf) MVertex *v2 = tab[i + 1][j]; MVertex *v3 = tab[i + 1][j + 1]; MVertex *v4 = tab[i][j + 1]; - if(gf->meshAttributes.recombine) + if(CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine) gf->quadrangles.push_back(new MQuadrangle(v1, v2, v3, v4)); else if(gf->meshAttributes.transfiniteArrangement == 1 || (gf->meshAttributes.transfiniteArrangement == 0 && @@ -449,7 +449,7 @@ int MeshTransfiniteSurface(GFace *gf) MVertex *v2 = tab[i + 1][j]; MVertex *v3 = tab[i + 1][j + 1]; MVertex *v4 = tab[i][j + 1]; - if(gf->meshAttributes.recombine) + if(CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine) gf->quadrangles.push_back(new MQuadrangle(v1, v2, v3, v4)); else if(gf->meshAttributes.transfiniteArrangement == 1 || (gf->meshAttributes.transfiniteArrangement == 0 && diff --git a/Mesh/meshGRegionTransfinite.cpp b/Mesh/meshGRegionTransfinite.cpp index 54c06268e0..7bcf689c31 100644 --- a/Mesh/meshGRegionTransfinite.cpp +++ b/Mesh/meshGRegionTransfinite.cpp @@ -220,7 +220,10 @@ class GOrientedTransfiniteFace { // returns the index of the face in the reference hexahedron int index() const { return _index; } // returns true if the face is recombined - int recombined() const { return _gf->meshAttributes.recombine; } + int recombined() const + { + return CTX::instance()->mesh.recombineAll || _gf->meshAttributes.recombine; + } // returns the number or points in the transfinite mesh in both // parameter directions int getNumU(){ return (_permutation % 2) ? _HH + 1: _LL + 1; } diff --git a/benchmarks/2d/recombine.geo b/benchmarks/2d/recombine.geo index b0cddc8b8e..083f744b62 100644 --- a/benchmarks/2d/recombine.geo +++ b/benchmarks/2d/recombine.geo @@ -10,4 +10,3 @@ Line(4) = {4,1} ; Line Loop(5) = {4,1,-2,3} ; Plane Surface(6) = {5} ; Recombine Surface{6}; -Mesh.SubdivisionAlgorithm = 3; -- GitLab