|
@ -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:
|
||||
|
|
|
@ -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 !
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ...')
|
||||
|
|
|
@ -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
|
||||
|
|