From aac03cc03bf70fe0db907291eb68bbda3687b71f Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 28 Nov 2016 01:17:54 +0100 Subject: [PATCH] FEM: gmsh mesh tool, add some more properties to adjust gmsh mesh --- src/Mod/Fem/FemGmshTools.py | 80 +++++++++++++++++++++++++++++++++---- src/Mod/Fem/_FemMeshGmsh.py | 38 ++++++++++++++---- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/src/Mod/Fem/FemGmshTools.py b/src/Mod/Fem/FemGmshTools.py index 1923003c51..8257a08f80 100644 --- a/src/Mod/Fem/FemGmshTools.py +++ b/src/Mod/Fem/FemGmshTools.py @@ -56,18 +56,60 @@ class FemGmshTools(): # clmin, CharacteristicLengthMin: float self.clmin = Units.Quantity(self.mesh_obj.CharacteristicLengthMin).Value - # order, ElementOrder: ['Auto', '1st', '2nd'] + # order + # known_element_orders = ['Automatic', '1st', '2nd'] self.order = self.mesh_obj.ElementOrder if self.order == '1st': self.order = '1' - elif self.order == 'Auto' or self.order == '2nd': + elif self.order == 'Automatic' or self.order == '2nd': self.order = '2' else: print('Error in order') - # dimension, ElementDimension: ['Auto', '1D', '2D', '3D'] + # dimension + # known_element_dimensions = ['Automatic', '1D', '2D', '3D'] self.dimension = self.mesh_obj.ElementDimension + # Algorithm2D + # known_mesh_algorithm_2D = ['Automatic', 'MeshAdapt', 'Delaunay', 'Frontal', 'BAMG', 'DelQuad'] + algo2D = self.mesh_obj.Algorithm2D + if algo2D == 'Automatic': + self.algorithm2D = '2' + elif algo2D == 'MeshAdapt': + self.algorithm2D = '1' + elif algo2D == 'Delaunay': + self.algorithm2D = '5' + elif algo2D == 'Frontal': + self.algorithm2D = '6' + elif algo2D == 'BAMG': + self.algorithm2D = '7' + elif algo2D == 'DelQuad': + self.algorithm2D = '8' + else: + self.algorithm2D = '2' + + # Algorithm3D + # known_mesh_algorithm_3D = ['Automatic', 'Delaunay', 'New Delaunay', 'Frontal', 'Frontal Delaunay', 'Frontal Hex', 'MMG3D', 'R-tree'] + algo3D = self.mesh_obj.Algorithm2D + if algo3D == 'Automatic': + self.algorithm3D = '1' + elif algo3D == 'Delaunay': + self.algorithm3D = '1' + elif algo3D == 'New Delaunay': + self.algorithm3D = '2' + elif algo3D == 'Frontal': + self.algorithm3D = '4' + elif algo3D == 'Frontal Delaunay': + self.algorithm3D = '5' + elif algo3D == 'Frontal Hex': + self.algorithm3D = '6' + elif algo3D == 'MMG3D': + self.algorithm3D = '7' + elif algo3D == 'R-tree': + self.algorithm3D = '9' + else: + self.algorithm3D = '1' + def create_mesh(self): print("\nWe gone start GMSH FEM mesh run!") print(' Part to mesh: Name --> ' + self.part_obj.Name + ', Label --> ' + self.part_obj.Label + ', ShapeType --> ' + self.part_obj.Shape.ShapeType) @@ -88,7 +130,7 @@ class FemGmshTools(): # Dimension # GMSH uses the hightest availabe. # A use case for not auto would be a surface (2D) mesh of a solid or other 3d shape - if self.dimension == 'Auto': + if self.dimension == 'Automatic': shty = self.part_obj.Shape.ShapeType if shty == 'Solid' or shty == 'CompSolid': # print('Found: ' + shty) @@ -217,9 +259,33 @@ class FemGmshTools(): geo.write("Mesh.CharacteristicLengthMax = " + str(self.clmax) + ";\n") geo.write("Mesh.CharacteristicLengthMin = " + str(self.clmin) + ";\n") geo.write("Mesh.ElementOrder = " + self.order + ";\n") - geo.write("//Mesh.HighOrderOptimize = 1;\n") # but does not really work, in GUI it does - geo.write("Mesh.Algorithm3D = 1;\n") - geo.write("Mesh.Algorithm = 2;\n") + geo.write("\n") + geo.write("//optimize the mesh\n") + # GMSH tetra optimizer + if hasattr(self.mesh_obj, 'OptimizeStd') and self.mesh_obj.OptimizeStd is True: + geo.write("Mesh.Optimize = 1;\n") + else: + geo.write("Mesh.Optimize = 0;\n") + # Netgen optimizer in GMSH + if hasattr(self.mesh_obj, 'OptimizeNetgen') and self.mesh_obj.OptimizeNetgen is True: + geo.write("Mesh.OptimizeNetgen = 1;\n") + else: + geo.write("Mesh.OptimizeNetgen = 0;\n") + # hight order mesh optimizing + if hasattr(self.mesh_obj, 'OptimizeNetgen') and self.mesh_obj.OptimizeNetgen is True: + geo.write("Mesh.HighOrderOptimize = 1; //probably needs more lines off adjustment in geo file\n") + else: + geo.write("Mesh.HighOrderOptimize = 0; //probably needs more lines off adjustment in geo file\n") + geo.write("\n") + if hasattr(self.mesh_obj, 'RecombineAll') and self.mesh_obj.RecombineAll is True: + geo.write("//recombine\n") + geo.write("Mesh.RecombineAll = 1;\n") + geo.write("\n") + geo.write("//mesh algorithm\n") + geo.write("Mesh.Algorithm = " + self.algorithm2D + ";\n") + geo.write("Mesh.Algorithm3D = " + self.algorithm3D + ";\n") + geo.write("\n") + geo.write("//more\n") geo.write("Mesh " + self.dimension + ";\n") geo.write("Mesh.Format = 2;\n") # unv if self.analysis and self.group_elements: diff --git a/src/Mod/Fem/_FemMeshGmsh.py b/src/Mod/Fem/_FemMeshGmsh.py index 7e1279e04b..978749c9ef 100644 --- a/src/Mod/Fem/_FemMeshGmsh.py +++ b/src/Mod/Fem/_FemMeshGmsh.py @@ -33,8 +33,10 @@ class _FemMeshGmsh(): """ # they will be used from the task panel too, thus they need to be outside of the __init__ - known_element_dimensions = ['Auto', '1D', '2D', '3D'] - known_element_orders = ['Auto', '1st', '2nd'] + known_element_dimensions = ['Automatic', '1D', '2D', '3D'] + known_element_orders = ['Automatic', '1st', '2nd'] + known_mesh_algorithm_2D = ['Automatic', 'MeshAdapt', 'Delaunay', 'Frontal', 'BAMG', 'DelQuad'] + known_mesh_algorithm_3D = ['Automatic', 'Delaunay', 'New Delaunay', 'Frontal', 'Frontal Delaunay', 'Frontal Hex', 'MMG3D', 'R-tree'] def __init__(self, obj): self.Type = "FemMeshGmsh" @@ -44,19 +46,39 @@ class _FemMeshGmsh(): obj.addProperty("App::PropertyLink", "Part", "FEM Mesh", "Part object to mesh") obj.Part = None - obj.addProperty("App::PropertyLength", "CharacteristicLengthMax", "FEM Mesh Params", "Max mesh element size (0.0 = infinity)") + obj.addProperty("App::PropertyLength", "CharacteristicLengthMax", "FEM GMSH Mesh Params", "Max mesh element size (0.0 = infinity)") obj.CharacteristicLengthMax = 0.0 # will be 1e+22 - obj.addProperty("App::PropertyLength", "CharacteristicLengthMin", "FEM Mesh Params", "Min mesh element size") + obj.addProperty("App::PropertyLength", "CharacteristicLengthMin", "FEM GMSH Mesh Params", "Min mesh element size") obj.CharacteristicLengthMin = 0.0 - obj.addProperty("App::PropertyEnumeration", "ElementDimension", "FEM Mesh Params", "Dimension of mesh elements (Auto = according ShapeType of part to mesh)") + obj.addProperty("App::PropertyEnumeration", "ElementDimension", "FEM GMSH Mesh Params", "Dimension of mesh elements (Auto = according ShapeType of part to mesh)") obj.ElementDimension = _FemMeshGmsh.known_element_dimensions - obj.ElementDimension = 'Auto' # according ShapeType of Part to mesh + obj.ElementDimension = 'Automatic' # according ShapeType of Part to mesh - obj.addProperty("App::PropertyEnumeration", "ElementOrder", "FEM Mesh Params", "Order of mesh elements (Auto will be 2nd)") + obj.addProperty("App::PropertyEnumeration", "ElementOrder", "FEM GMSH Mesh Params", "Order of mesh elements (Auto will be 2nd)") obj.ElementOrder = _FemMeshGmsh.known_element_orders - obj.ElementOrder = 'Auto' # = 2nd + obj.ElementOrder = 'Automatic' # = 2nd + + obj.addProperty("App::PropertyBool", "OptimizeStd", "FEM GMSH Mesh Params", "Optimize tetra elements") + obj.OptimizeStd = False + + obj.addProperty("App::PropertyBool", "OptimizeNetgen", "FEM GMSH Mesh Params", "Optimize tetra elements by use of Netgen") + obj.OptimizeNetgen = False + + obj.addProperty("App::PropertyBool", "HighOrderOptimize", "FEM GMSH Mesh Params", "Optimize hight order meshes") + obj.HighOrderOptimize = False + + obj.addProperty("App::PropertyBool", "RecombineAll", "FEM GMSH Mesh Params", "Apply recombination algorithm to all surfaces") + obj.RecombineAll = False + + obj.addProperty("App::PropertyEnumeration", "Algorithm2D", "FEM GMSH Mesh Params", "mesh algorithm 2D") + obj.Algorithm2D = _FemMeshGmsh.known_mesh_algorithm_2D + obj.Algorithm2D = 'Automatic' # ? + + obj.addProperty("App::PropertyEnumeration", "Algorithm3D", "FEM GMSH Mesh Params", "mesh algorithm 3D") + obj.Algorithm3D = _FemMeshGmsh.known_mesh_algorithm_3D + obj.Algorithm3D = 'Automatic' # ? def execute(self, obj): return