Merge pull request #353 from berndhahnebach/bhbdev058

FEM: GMSH tool
This commit is contained in:
wwmayer 2016-11-28 18:04:20 +01:00 committed by GitHub
commit 1f6ed81624
22 changed files with 225 additions and 62 deletions

View File

@ -48,31 +48,73 @@ class FemGmshTools():
# part to mesh
self.part_obj = self.mesh_obj.Part
# clmax, ElementSizeMax: float, 0.0 = 1e+22
self.clmax = Units.Quantity(self.mesh_obj.ElementSizeMax).Value
# clmax, CharacteristicLengthMax: float, 0.0 = 1e+22
self.clmax = Units.Quantity(self.mesh_obj.CharacteristicLengthMax).Value
if self.clmax == 0.0:
self.clmax = 1e+22
# clmin, ElementSizeMin: float
self.clmin = Units.Quantity(self.mesh_obj.ElementSizeMin).Value
# 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)
print(' ElementSizeMax: ' + str(self.clmax))
print(' ElementSizeMin: ' + str(self.clmin))
print(' CharacteristicLengthMax: ' + str(self.clmax))
print(' CharacteristicLengthMin: ' + str(self.clmin))
print(' ElementOrder: ' + self.order)
self.get_dimension()
self.get_tmp_file_paths()
@ -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)
@ -181,6 +223,23 @@ class FemGmshTools():
print(self.group_elements)
else:
print(' NO group meshing.')
self.ele_length_map = self.mesh_obj.CharacteristicLengthMap
self.ele_node_map = {}
if self.ele_length_map:
import FemMeshTools
print(self.ele_length_map)
self.ele_node_map = {}
for e in self.ele_length_map:
if not e.startswith('Solid'):
# Face, Edge, Vertex
ele_shape = self.part_obj.Shape.getElement(e)
else:
# Solid
ele_shape_index = int(e.lstrip('Solid')) - 1
ele_shape = self.part_obj.Shape.Solids[ele_shape_index]
ele_vertexes = FemMeshTools.get_vertexes_by_element(self.part_obj.Shape, ele_shape)
self.ele_node_map[e] = ele_vertexes
print(self.ele_node_map)
def write_part_file(self):
self.part_obj.Shape.exportBrep(self.temp_file_geometry)
@ -190,7 +249,7 @@ class FemGmshTools():
geo.write('Merge "' + self.temp_file_geometry + '";\n')
geo.write("\n")
if self.analysis and self.group_elements:
print(' We gone have found elements to make mesh groups for!')
print(' We gone have found elements to make mesh groups for.')
geo.write("// group data\n")
# we use the element name of FreeCAD which starts with 1 (example: 'Face1'), same as GMSH
for group in self.group_elements:
@ -214,12 +273,44 @@ class FemGmshTools():
# print(ele_nr)
geo.write('Physical ' + physical_type + '("' + group + '") = {' + ele_nr + '};\n')
geo.write("\n")
if self.ele_length_map:
# we use the index FreeCAD which starts with 0, we need to add 1 for the index in GMSH
geo.write("// Characteristic Length according CharacteristicLengthMap\n")
for e in self.ele_length_map:
ele_nodes = (''.join((str(n + 1) + ', ') for n in self.ele_node_map[e])).rstrip(', ')
geo.write("// " + e + "\n")
geo.write("Characteristic Length { " + ele_nodes + " } = " + self.ele_length_map[e] + ";\n")
geo.write("\n")
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:

View File

@ -1162,6 +1162,49 @@ def find_element_in_shape(aShape, anElement):
FreeCAD.Console.PrintError('Compound is not supported.\n')
def get_vertexes_by_element(aShape, anElement):
# we gone extent the method find_element_in_shape and return the vertexes
# import Part
ele_vertexes = []
ele_st = anElement.ShapeType
if ele_st == 'Solid' or ele_st == 'CompSolid':
for index, solid in enumerate(aShape.Solids):
if is_same_geometry(solid, anElement):
for vele in aShape.Solids[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
# print(' ' + str(sorted(ele_vertexes)))
return ele_vertexes
FreeCAD.Console.PrintError('Error, Solid ' + str(anElement) + ' not found in: ' + str(aShape) + '\n')
elif ele_st == 'Face' or ele_st == 'Shell':
for index, face in enumerate(aShape.Faces):
if is_same_geometry(face, anElement):
for vele in aShape.Faces[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
# print(' ' + str(sorted(ele_vertexes)))
return ele_vertexes
elif ele_st == 'Edge' or ele_st == 'Wire':
for index, edge in enumerate(aShape.Edges):
if is_same_geometry(edge, anElement):
for vele in aShape.Edges[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
# print(' ' + str(sorted(ele_vertexes)))
return ele_vertexes
elif ele_st == 'Vertex':
for index, vertex in enumerate(aShape.Vertexes):
if is_same_geometry(vertex, anElement):
ele_vertexes.append(index)
# print(' ' + str(sorted(ele_vertexes)))
return ele_vertexes
elif ele_st == 'Compound':
FreeCAD.Console.PrintError('Compound is not supported.\n')
def is_same_geometry(shape1, shape2):
# the vertexes and the CenterOfMass are compared
# it is a hack, but I do not know any better !

View File

@ -975,7 +975,7 @@ CmdFemDefineNodesSet::CmdFemDefineNodesSet()
sToolTipText = QT_TR_NOOP("Create node set by Poly");
sWhatsThis = "Create node set by Poly";
sStatusTip = QT_TR_NOOP("Create node set by Poly");
sPixmap = "fem-fem-mesh-create-node-by-poly";
sPixmap = "fem-femmesh-create-node-by-poly";
}
void CmdFemDefineNodesSet::activated(int)
@ -1032,7 +1032,7 @@ CmdFemCreateNodesSet::CmdFemCreateNodesSet()
sToolTipText = QT_TR_NOOP("Creates a FEM mesh nodes set");
sWhatsThis = "Fem_CreateNodesSet";
sStatusTip = sToolTipText;
sPixmap = "fem-fem-mesh-create-node-by-poly";
sPixmap = "fem-femmesh-create-node-by-poly";
}
void CmdFemCreateNodesSet::activated(int)

View File

@ -25,10 +25,10 @@
<file>icons/fem-control-solver.svg</file>
<file>icons/fem-cylinder.svg</file>
<file>icons/fem-data.png</file>
<file>icons/fem-fem-mesh-create-node-by-poly.svg</file>
<file>icons/fem-fem-mesh-from-shape.svg</file>
<file>icons/fem-fem-mesh-gmsh-from-shape.svg</file>
<file>icons/fem-fem-mesh-netgen-from-shape.svg</file>
<file>icons/fem-femmesh-create-node-by-poly.svg</file>
<file>icons/fem-femmesh-from-shape.svg</file>
<file>icons/fem-femmesh-gmsh-from-shape.svg</file>
<file>icons/fem-femmesh-netgen-from-shape.svg</file>
<file>icons/fem-femmesh-to-mesh.svg</file>
<file>icons/fem-frequency-analysis.svg</file>
<file>icons/fem-inp-editor.svg</file>

View File

@ -15,7 +15,7 @@
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="fem-fem-mesh-create-node-by-poly.svg"
sodipodi:docname="fem-femmesh-create-node-by-poly.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -14,7 +14,7 @@
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="Fem_FemMesh.svg"
sodipodi:docname="fem-femmesh-from-shape.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs2862">

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -15,7 +15,7 @@
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.5 r10040"
sodipodi:docname="fem-fem-mesh-gmsh-from-shape.svg"
sodipodi:docname="fem-femmesh-gmsh-from-shape.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -15,7 +15,7 @@
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.5 r10040"
sodipodi:docname="fem-fem-mesh-netgen-from-shape.svg"
sodipodi:docname="fem-femmesh-netgen-from-shape.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -41,7 +41,7 @@ using namespace Gui;
TaskAnalysisInfo::TaskAnalysisInfo(Fem::FemAnalysis *pcObject,QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"),
: TaskBox(Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"),
tr("Nodes set"),
true,
parent),

View File

@ -59,7 +59,7 @@ using namespace Gui;
TaskCreateNodeSet::TaskCreateNodeSet(Fem::FemSetNodesObject *pcObject,QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"),
: TaskBox(Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"),
tr("Nodes set"),
true,
parent),

View File

@ -47,7 +47,7 @@ using namespace Gui;
TaskDriver::TaskDriver(Fem::FemAnalysis *pcObject,QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"),
: TaskBox(Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"),
tr("Nodes set"),
true,
parent),

View File

@ -44,7 +44,7 @@ using namespace FemGui;
using namespace Gui;
TaskObjectName::TaskObjectName(App::DocumentObject *pcObject,QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"),
: TaskBox(Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"),
tr("TaskObjectName"),
true,
parent),

View File

@ -171,7 +171,7 @@ void TaskPostBox::updateEnumerationList(App::PropertyEnumeration& prop, QComboBo
//###########################################################################################################
TaskPostDisplay::TaskPostDisplay(Gui::ViewProviderDocumentObject* view, QWidget *parent)
: TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Display options"), parent)
: TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Display options"), parent)
{
//we need a separate container widget to add all controls to
proxy = new QWidget(this);
@ -221,7 +221,7 @@ void TaskPostDisplay::applyPythonCode() {
//############################################################################################
TaskPostFunction::TaskPostFunction(ViewProviderDocumentObject* view, QWidget* parent): TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Implicit function"), parent) {
TaskPostFunction::TaskPostFunction(ViewProviderDocumentObject* view, QWidget* parent): TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Implicit function"), parent) {
assert(view->isDerivedFrom(ViewProviderFemPostFunction::getClassTypeId()));
@ -244,7 +244,7 @@ void TaskPostFunction::applyPythonCode() {
//############################################################################################
TaskPostClip::TaskPostClip(ViewProviderDocumentObject* view, App::PropertyLink* function, QWidget* parent)
: TaskPostBox(view,Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Choose implicit function"), parent) {
: TaskPostBox(view,Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Choose implicit function"), parent) {
assert(view->isDerivedFrom(ViewProviderFemPostClip::getClassTypeId()));
assert(function);
@ -363,7 +363,7 @@ void TaskPostClip::on_InsideOut_toggled(bool val) {
//############################################################################################
TaskPostScalarClip::TaskPostScalarClip(ViewProviderDocumentObject* view, QWidget* parent) :
TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Clip options"), parent) {
TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Clip options"), parent) {
assert(view->isDerivedFrom(ViewProviderFemPostScalarClip::getClassTypeId()));
@ -455,7 +455,7 @@ void TaskPostScalarClip::on_InsideOut_toggled(bool val) {
//############################################################################################
TaskPostWarpVector::TaskPostWarpVector(ViewProviderDocumentObject* view, QWidget* parent) :
TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Clip options"), parent) {
TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Clip options"), parent) {
assert(view->isDerivedFrom(ViewProviderFemPostWarpVector::getClassTypeId()));
@ -540,7 +540,7 @@ void TaskPostWarpVector::on_Min_valueChanged(double v) {
//############################################################################################
TaskPostCut::TaskPostCut(ViewProviderDocumentObject* view, App::PropertyLink* function, QWidget* parent)
: TaskPostBox(view,Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Choose implicit function"), parent) {
: TaskPostBox(view,Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"), tr("Choose implicit function"), parent) {
assert(view->isDerivedFrom(ViewProviderFemPostCut::getClassTypeId()));
assert(function);

View File

@ -48,7 +48,7 @@ using namespace Gui;
TaskTetParameter::TaskTetParameter(Fem::FemMeshShapeNetgenObject *pcObject,QWidget *parent)
: TaskBox(Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"),
: TaskBox(Gui::BitmapFactory().pixmap("fem-femmesh-create-node-by-poly"),
tr("Tet Parameter"),
true,
parent),

View File

@ -183,7 +183,7 @@ App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0
ViewProviderFemMesh::ViewProviderFemMesh()
{
sPixmap = "fem-fem-mesh-from-shape";
sPixmap = "fem-femmesh-from-shape";
ADD_PROPERTY(PointColor,(App::Color(0.7f,0.7f,0.7f)));
ADD_PROPERTY(PointSize,(5.0f));

View File

@ -66,7 +66,7 @@ ViewProviderFemPostObject::ViewProviderFemPostObject() : m_blockPropertyChanges(
ADD_PROPERTY_TYPE(VectorMode,((long)0), "Coloring", App::Prop_None, "Select what to show for a vector field");
ADD_PROPERTY(Transperency, (0));
sPixmap = "fem-fem-mesh-from-shape";
sPixmap = "fem-femmesh-from-shape";
//create the subnodes which do the visualization work
m_shapeHints = new SoShapeHints();

View File

@ -38,7 +38,7 @@ class _CommandMeshGmshFromShape(FemCommands):
# the Fem_MeshGmshFromShape command definition
def __init__(self):
super(_CommandMeshGmshFromShape, self).__init__()
self.resources = {'Pixmap': 'fem-fem-mesh-gmsh-from-shape',
self.resources = {'Pixmap': 'fem-femmesh-gmsh-from-shape',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGmshFromShape", "FEM mesh from shape by GMSH"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGmshFromShape", "Create a FEM mesh from a shape by GMSH mesher")}
self.is_active = 'with_part_feature'

View File

@ -37,7 +37,7 @@ class _CommandMeshNetgenFromShape(FemCommands):
# the Fem_MeshNetgenFromShape command definition
def __init__(self):
super(_CommandMeshNetgenFromShape, self).__init__()
self.resources = {'Pixmap': 'fem-fem-mesh-netgen-from-shape',
self.resources = {'Pixmap': 'fem-femmesh-netgen-from-shape',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "FEM mesh from shape by Netgen"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "Create a FEM volume mesh from a solid or face shape by Netgen internal mesher")}
self.is_active = 'with_part_feature'

View File

@ -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,41 @@ class _FemMeshGmsh():
obj.addProperty("App::PropertyLink", "Part", "FEM Mesh", "Part object to mesh")
obj.Part = None
obj.addProperty("App::PropertyLength", "ElementSizeMax", "FEM Mesh Params", "Max mesh element size (0.0 = infinity)")
obj.ElementSizeMax = 0.0 # will be 1e+22
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", "ElementSizeMin", "FEM Mesh Params", "Min mesh element size")
obj.ElementSizeMin = 0.0
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' # ?
obj.addProperty("App::PropertyMap", "CharacteristicLengthMap", "FEM GMSH Mesh Params", "Map of CharacteristicLength of Shape elements")
def execute(self, obj):
return

View File

@ -27,7 +27,7 @@ __url__ = "http://www.freecadweb.org"
## @package FemSolverZ88
# \ingroup FEM
import FreeCAD
# import FreeCAD
import FemToolsZ88
@ -42,15 +42,15 @@ class _FemSolverZ88():
obj.addProperty("App::PropertyString", "SolverType", "Base", "Type of the solver", 1) # the 1 set the property to ReadOnly
obj.SolverType = str(self.Type)
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
# fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General") # not needed ATM
obj.addProperty("App::PropertyPath", "WorkingDir", "Fem", "Working directory for calculations")
obj.WorkingDir = fem_prefs.GetString("WorkingDir", "")
obj.addProperty("App::PropertyPath", "WorkingDir", "Fem", "Working directory for calculations, will only be used it is left blank in preferences")
# the working directory is not set, the solver working directory is only used if the preferences working directory is left blank
obj.addProperty("App::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis")
obj.AnalysisType = FemToolsZ88.FemToolsZ88.known_analysis_types
analysis_type = fem_prefs.GetInt("AnalysisType", 0)
obj.AnalysisType = FemToolsZ88.FemToolsZ88.known_analysis_types[analysis_type]
known_analysis_types = FemToolsZ88.FemToolsZ88.known_analysis_types
obj.AnalysisType = known_analysis_types
obj.AnalysisType = known_analysis_types[0]
def execute(self, obj):
return

View File

@ -78,14 +78,14 @@ class _TaskPanelFemMeshGmsh:
self.run_gmsh()
def get_mesh_params(self):
self.clmax = self.mesh_obj.ElementSizeMax
self.clmin = self.mesh_obj.ElementSizeMin
self.clmax = self.mesh_obj.CharacteristicLengthMax
self.clmin = self.mesh_obj.CharacteristicLengthMin
self.order = self.mesh_obj.ElementOrder
self.dimension = self.mesh_obj.ElementDimension
def set_mesh_params(self):
self.mesh_obj.ElementSizeMax = self.clmax
self.mesh_obj.ElementSizeMin = self.clmin
self.mesh_obj.CharacteristicLengthMax = self.clmax
self.mesh_obj.CharacteristicLengthMin = self.clmin
self.mesh_obj.ElementOrder = self.order
self.mesh_obj.ElementDimension = self.dimension
@ -141,7 +141,12 @@ class _TaskPanelFemMeshGmsh:
import FemGmshTools
gmsh_mesh = FemGmshTools.FemGmshTools(self.obj, self.analysis)
self.console_log("Start GMSH ...")
error = gmsh_mesh.create_mesh()
error = ''
try:
error = gmsh_mesh.create_mesh()
except:
import sys
print("Unexpected error when creating mesh: ", sys.exc_info()[0])
if error:
print(error)
self.console_log('GMSH had warnings ...')

View File

@ -38,7 +38,7 @@ class _ViewProviderFemMeshGmsh:
vobj.Proxy = self
def getIcon(self):
return ":/icons/fem-fem-mesh-from-shape.svg"
return ":/icons/fem-femmesh-from-shape.svg"
def attach(self, vobj):
self.ViewObject = vobj