diff --git a/src/Mod/Fem/FemGmshTools.py b/src/Mod/Fem/FemGmshTools.py
index 2b14757360..8f3fbf8409 100644
--- a/src/Mod/Fem/FemGmshTools.py
+++ b/src/Mod/Fem/FemGmshTools.py
@@ -355,11 +355,15 @@ class FemGmshTools():
FreeCAD.Console.PrintError("The element " + elems + " of the mesh boundary layer " + mr_obj.Name + " has been added to another mesh boudary layer.\n")
setting = {}
setting['hwall_n'] = Units.Quantity(mr_obj.MinimumThickness).Value
- setting['hwall_t'] = setting['hwall_n'] * 5 # tangetial cell dimension
setting['ratio'] = mr_obj.GrowthRate
- setting['thickness'] = sum([setting['hwall_n'] **i for i in range(mr_obj.NumberOfLayers)])
+ setting['thickness'] = sum([setting['hwall_n'] * setting['ratio']**i for i in range(mr_obj.NumberOfLayers)])
+ setting['hwall_t'] = setting['thickness'] #setting['hwall_n'] * 5 # tangetial cell dimension
+
# hfar: cell dimension outside boundary should be set later if some character length is set
- setting['hfar'] = setting['thickness'] * 2 # set a value for safety, it may works as background mesh cell size
+ if self.clmax > setting['thickness'] * 0.8 and self.clmax < setting['thickness'] * 1.6:
+ setting['hfar'] = self.clmax
+ else:
+ setting['hfar'] = setting['thickness'] # set a value for safety, it may works as background mesh cell size
# from face name -> face id is done in geo file write up
#fan angle setup is not implemented yet
if self.dimension == '2':
@@ -450,11 +454,17 @@ class FemGmshTools():
geo.write("// " + e + "\n")
geo.write("Characteristic Length { " + ele_nodes + " } = " + str(self.ele_length_map[e]) + ";\n")
geo.write("\n")
+
+ # boundary layer generation may need special setup of Gmsh properties, set them in Gmsh TaskPanel
self.write_boundary_layer(geo)
geo.write("// min, max Characteristic Length\n")
geo.write("Mesh.CharacteristicLengthMax = " + str(self.clmax) + ";\n")
- geo.write("Mesh.CharacteristicLengthMin = " + str(self.clmin) + ";\n")
+ if len(self.bl_setting_list):
+ # if minLength must smaller than first layer of boundary_layer, it is safer to set it as zero (defualt value) to avoid error
+ geo.write("Mesh.CharacteristicLengthMin = " + str(0) + ";\n")
+ else:
+ geo.write("Mesh.CharacteristicLengthMin = " + str(self.clmin) + ";\n")
geo.write("\n")
if hasattr(self.mesh_obj, 'RecombineAll') and self.mesh_obj.RecombineAll is True:
geo.write("// other mesh options\n")
@@ -480,12 +490,17 @@ class FemGmshTools():
geo.write("// mesh order\n")
geo.write("Mesh.ElementOrder = " + self.order + ";\n")
geo.write("\n")
- geo.write("// mesh algorithm\n")
+
+ geo.write("// mesh algorithm, only a few algorithms are usable with 3D boundary layer generation\n")
geo.write("// 2D mesh algorithm (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)\n")
- geo.write("Mesh.Algorithm = " + self.algorithm2D + ";\n")
+ if len(self.bl_setting_list) and self.dimension == 3:
+ geo.write("Mesh.Algorithm = " + 'DelQuad' + ";\n") # Frontal/DelQuad are tested
+ else:
+ geo.write("Mesh.Algorithm = " + self.algorithm2D + ";\n")
geo.write("// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree)\n")
geo.write("Mesh.Algorithm3D = " + self.algorithm3D + ";\n")
geo.write("\n")
+
geo.write("// meshing\n")
# remove duplicate vertices, see https://forum.freecadweb.org/viewtopic.php?f=18&t=21571&start=20#p179443
if hasattr(self.mesh_obj, 'CoherenceMesh') and self.mesh_obj.CoherenceMesh is True:
diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc
index 3d2b3165f0..ffe30f3ad8 100755
--- a/src/Mod/Fem/Gui/Resources/Fem.qrc
+++ b/src/Mod/Fem/Gui/Resources/Fem.qrc
@@ -28,6 +28,7 @@
icons/fem-control-solver.svg
icons/fem-cylinder.svg
icons/fem-data.svg
+ icons/fem-femmesh-boundary-layer.svg
icons/fem-femmesh-clear-mesh.svg
icons/fem-femmesh-create-node-by-poly.svg
icons/fem-femmesh-from-shape.svg
diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py
index bef52adbcf..589f1d2658 100644
--- a/src/Mod/Fem/ObjectsFem.py
+++ b/src/Mod/Fem/ObjectsFem.py
@@ -319,7 +319,7 @@ def makeSolverZ88(name="Z88"):
if FreeCAD.GuiUp:
import PyGui._ViewProviderFemSolverZ88
PyGui._ViewProviderFemSolverZ88._ViewProviderFemSolverZ88(obj.ViewObject)
- return obj
+ return obj
'''
diff --git a/src/Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui b/src/Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui
index 66ab0c2f95..c32e8a6174 100644
--- a/src/Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui
+++ b/src/Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui
@@ -46,14 +46,14 @@
0
-
+
80
20
- 0.0
+ 1.0
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -108,7 +108,7 @@
0.100000000000000
- 1.000000000000000
+ 1.300000000000000
diff --git a/src/Mod/Fem/PyGui/_TaskPanelFemMeshBoundaryLayer.py b/src/Mod/Fem/PyGui/_TaskPanelFemMeshBoundaryLayer.py
index 0460983367..3a5540d484 100644
--- a/src/Mod/Fem/PyGui/_TaskPanelFemMeshBoundaryLayer.py
+++ b/src/Mod/Fem/PyGui/_TaskPanelFemMeshBoundaryLayer.py
@@ -47,7 +47,7 @@ class _TaskPanelFemMeshBoundaryLayer:
QtCore.QObject.connect(self.form.bl_number_of_layers, QtCore.SIGNAL("valueChanged(int)"), self.bl_number_of_layers_changed)
QtCore.QObject.connect(self.form.bl_min_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.bl_min_thickness_changed)
- QtCore.QObject.connect(self.form.bl_growth_rate, QtCore.SIGNAL("valueChanged(float)"), self.bl_growth_rate_changed)
+ QtCore.QObject.connect(self.form.bl_growth_rate, QtCore.SIGNAL("valueChanged(double)"), self.bl_growth_rate_changed) # becareful of signal signature for QDoubleSpinbox
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
@@ -72,19 +72,17 @@ class _TaskPanelFemMeshBoundaryLayer:
self.obj.MinimumThickness = self.bl_min_thickness
self.obj.NumberOfLayers = self.bl_number_of_layers
self.obj.GrowthRate = self.bl_growth_rate
-
self.obj.References = self.references
def update(self):
- 'fills the widgets with '
+ 'fills the widgets with data'
self.form.bl_min_thickness.setText(self.bl_min_thickness.UserString)
self.form.bl_number_of_layers.setValue(self.bl_number_of_layers)
self.form.bl_growth_rate.setValue(self.bl_growth_rate)
-
self.rebuild_list_References()
def bl_min_thickness_changed(self, base_quantity_value):
- self.bl_min_thicknes = base_quantity_value
+ self.bl_min_thickness = base_quantity_value
def bl_number_of_layers_changed(self, value):
self.bl_number_of_layers = value
@@ -100,13 +98,14 @@ class _TaskPanelFemMeshBoundaryLayer:
FreeCAD.ActiveDocument.recompute()
return True
- ############### identical to FemMeshRegion ############
def reject(self):
if self.sel_server:
FreeCADGui.Selection.removeObserver(self.sel_server)
FreeCADGui.ActiveDocument.resetEdit()
return True
+ ############### identical to FemMeshRegion ############
+
def choose_selection_mode_standard(self, state):
self.selection_mode_solid = not state
if self.sel_server and not self.selection_mode_solid:
diff --git a/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py b/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py
index f248d10ff3..b9de1adb8c 100644
--- a/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py
+++ b/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py
@@ -31,18 +31,30 @@ __url__ = "http://www.freecadweb.org"
class _FemMeshBoundaryLayer:
"The FemMeshBoundaryLayer object"
def __init__(self, obj):
- obj.addProperty("App::PropertyInteger", "NumberOfLayers", "MeshBoundaryLayerProperties",
+ self.Type = "FemMeshBoundaryLayer"
+ self.Object = obj # keep a ref to the DocObj for nonGui usage
+ obj.Proxy = self # link between App::DocumentObject to this object
+
+ obj.addProperty("App::PropertyInteger", "NumberOfLayers", "MeshBoundaryLayerProperties",
"set number of inflation layers for this boundary")
obj.NumberOfLayers = 3
- obj.addProperty("App::PropertyLength", "MinimumThickness", "MeshBoundaryLayerProperties",
+
+ obj.addProperty("App::PropertyLength", "MinimumThickness", "MeshBoundaryLayerProperties",
"set minimum thickness,usually the first inflation layer")
- obj.addProperty("App::PropertyFloat", "GrowthRate", "MeshBoundaryLayerProperties",
+ # default to zero, user must specify a proper value for this property
+
+ obj.addProperty("App::PropertyFloat", "GrowthRate", "MeshBoundaryLayerProperties",
"set growth rate of inflation layers for smooth transition")
- obj.GrowthRate = 1.0
+ obj.GrowthRate = 1.5
obj.addProperty("App::PropertyLinkSubList", "References", "MeshBoundaryLayerShapes", "List of FEM mesh region shapes")
- obj.Proxy = self
- self.Type = "FemMeshBoundaryLayer"
def execute(self, obj):
return
+
+ def __getstate__(self):
+ return self.Type
+
+ def __setstate__(self, state):
+ if state:
+ self.Type = state