FEM: GMSH mesh tool, the GMSH tool class and a task panel
This commit is contained in:
parent
1327589045
commit
ae90dd0522
|
@ -87,6 +87,7 @@ SET(FemScripts_SRCS
|
|||
_FemSolverZ88.py
|
||||
_MechanicalMaterial.py
|
||||
_TaskPanelFemBeamSection.py
|
||||
_TaskPanelFemMeshGmsh.py
|
||||
_TaskPanelFemShellThickness.py
|
||||
_TaskPanelFemSolverCalculix.py
|
||||
_TaskPanelMechanicalMaterial.py
|
||||
|
@ -110,6 +111,7 @@ SET(FemScripts_SRCS
|
|||
FemBeamSection.py
|
||||
FemCommands.py
|
||||
FemConstraintSelfWeight.py
|
||||
FemGmshTools.py
|
||||
FemInputWriter.py
|
||||
FemInputWriterCcx.py
|
||||
FemInputWriterZ88.py
|
||||
|
@ -127,6 +129,7 @@ SET(FemScripts_SRCS
|
|||
TestFem.py
|
||||
z88DispReader.py
|
||||
TaskPanelFemBeamSection.ui
|
||||
TaskPanelFemMeshGmsh.ui
|
||||
TaskPanelFemShellThickness.ui
|
||||
TaskPanelFemSolverCalculix.ui
|
||||
TaskPanelMechanicalMaterial.ui
|
||||
|
|
|
@ -40,6 +40,10 @@ INSTALL(
|
|||
_FemMeshGmsh.py
|
||||
_ViewProviderFemMeshGmsh.py
|
||||
_CommandMeshGmshFromShape.py
|
||||
_TaskPanelFemMeshGmsh.py
|
||||
TaskPanelFemMeshGmsh.ui
|
||||
|
||||
FemGmshTools.py
|
||||
|
||||
FemBeamSection.py
|
||||
_FemBeamSection.py
|
||||
|
|
258
src/Mod/Fem/FemGmshTools.py
Normal file
258
src/Mod/Fem/FemGmshTools.py
Normal file
|
@ -0,0 +1,258 @@
|
|||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "Tools for the work with GMSH mesher"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import Fem
|
||||
import subprocess
|
||||
import tempfile
|
||||
from platform import system
|
||||
|
||||
|
||||
# CONFIGURATION - EDIT THE FOLLOWING LINE TO MATCH YOUR GMSH BINARY
|
||||
# gmsh_bin_linux = "/usr/bin/gmsh"
|
||||
gmsh_bin_linux = "/usr/local/bin/gmsh"
|
||||
gmsh_bin_windwos = "C:\\Daten\\gmsh-2.13.2-Windows\\gmsh.exe"
|
||||
gmsh_bin_other = "/usr/bin/gmsh"
|
||||
# END CONFIGURATION
|
||||
|
||||
|
||||
class FemGmshTools():
|
||||
def __init__(self, gmsh_mesh_obj, analysis=None):
|
||||
self.mesh_obj = gmsh_mesh_obj
|
||||
if analysis:
|
||||
self.analysis = analysis
|
||||
# group meshing turned on
|
||||
else:
|
||||
self.analysis = None
|
||||
# group meshing turned off
|
||||
|
||||
# part to mesh
|
||||
self.part_obj = self.mesh_obj.Part
|
||||
|
||||
# clmax, ElementSizeMax: float, 0.0 = 1e+22
|
||||
self.clmax = self.mesh_obj.ElementSizeMax
|
||||
if self.clmax == 0.0:
|
||||
self.clmax = 1e+22
|
||||
|
||||
# clmin, ElementSizeMin: float
|
||||
self.clmin = self.mesh_obj.ElementSizeMin
|
||||
|
||||
# order, ElementOrder: ['Auto', '1st', '2nd']
|
||||
self.order = self.mesh_obj.ElementOrder
|
||||
if self.order == '1st':
|
||||
self.order = '1'
|
||||
elif self.order == 'Auto' or self.order == '2nd':
|
||||
self.order = '2'
|
||||
else:
|
||||
print('Error in order')
|
||||
|
||||
# dimension, ElementDimension: ['Auto', '1D', '2D', '3D']
|
||||
self.dimension = self.mesh_obj.ElementDimension
|
||||
|
||||
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(' ElementOrder: ' + self.order)
|
||||
self.get_dimension()
|
||||
self.get_tmp_file_paths()
|
||||
self.get_gmsh_command()
|
||||
self.get_group_data()
|
||||
self.write_part_file()
|
||||
self.write_geo()
|
||||
error = self.run_gmsh_with_geo()
|
||||
self.read_and_set_new_mesh()
|
||||
return error
|
||||
|
||||
def get_dimension(self):
|
||||
# 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':
|
||||
shty = self.part_obj.Shape.ShapeType
|
||||
if shty == 'Solid' or shty == 'CompSolid':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '3'
|
||||
elif shty == 'Face' or shty == 'Shell':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '2'
|
||||
elif shty == 'Edge' or shty == 'Wire':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '1'
|
||||
elif shty == 'Vertex':
|
||||
# print('Found: ' + shty)
|
||||
FreeCAD.Console.PrintError("You can not mesh a Vertex.\n")
|
||||
self.dimension = '0'
|
||||
elif shty == 'Compound':
|
||||
print('Found: ' + shty)
|
||||
print('I do not know what is inside your Compound. Dimension was set to 3 anyway.')
|
||||
# TODO check contents of Compound
|
||||
# use dimension 3 on any shape works for 2D and 1d meshes as well !
|
||||
# but not in combination with sewfaces or connectfaces
|
||||
self.dimension = '3'
|
||||
else:
|
||||
self.dimension = '0'
|
||||
FreeCAD.Console.PrintError('Could not retrive Dimension from shape type. Please choose dimension.')
|
||||
elif self.dimension == '3D':
|
||||
self.dimension = '3'
|
||||
elif self.dimension == '2D':
|
||||
self.dimension = '2'
|
||||
elif self.dimension == '1D':
|
||||
self.dimension = '1'
|
||||
else:
|
||||
print('Error in dimension')
|
||||
print(' ElementDimension: ' + self.dimension)
|
||||
|
||||
def get_tmp_file_paths(self):
|
||||
if system() == "Linux":
|
||||
path_sep = "/"
|
||||
elif system() == "Windows":
|
||||
path_sep = "\\"
|
||||
else:
|
||||
path_sep = "/"
|
||||
tmpdir = tempfile.gettempdir()
|
||||
# geometry file
|
||||
self.temp_file_geometry = tmpdir + path_sep + self.part_obj.Name + '_Geometry.brep'
|
||||
print(' ' + self.temp_file_geometry)
|
||||
# mesh file
|
||||
self.mesh_name = self.part_obj.Name + '_Mesh_TmpGmsh'
|
||||
self.temp_file_mesh = tmpdir + path_sep + self.mesh_name + '.unv'
|
||||
print(' ' + self.temp_file_mesh)
|
||||
# GMSH input file
|
||||
self.temp_file_geo = tmpdir + path_sep + 'shape2mesh.geo'
|
||||
print(' ' + self.temp_file_geo)
|
||||
|
||||
def get_gmsh_command(self):
|
||||
if system() == "Linux":
|
||||
self.gmsh_bin = gmsh_bin_linux
|
||||
elif system() == "Windows":
|
||||
self.gmsh_bin = gmsh_bin_windwos
|
||||
else:
|
||||
self.gmsh_bin = gmsh_bin_other
|
||||
self.gmsh_command = self.gmsh_bin + ' - ' + self.temp_file_geo # gmsh - /tmp/shape2mesh.geo
|
||||
print(' ' + self.gmsh_command)
|
||||
|
||||
def get_group_data(self):
|
||||
if self.analysis:
|
||||
print(' Group meshing.')
|
||||
import FemMeshTools
|
||||
self.group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj)
|
||||
print(self.group_elements)
|
||||
else:
|
||||
print(' NO group meshing.')
|
||||
|
||||
def write_part_file(self):
|
||||
self.part_obj.Shape.exportBrep(self.temp_file_geometry)
|
||||
|
||||
def write_geo(self):
|
||||
geo = open(self.temp_file_geo, "w")
|
||||
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!')
|
||||
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:
|
||||
gdata = self.group_elements[group]
|
||||
# print(gdata)
|
||||
# geo.write("// " + group + "\n")
|
||||
ele_nr = ''
|
||||
if gdata[0].startswith('Solid'):
|
||||
physical_type = 'Volume'
|
||||
for ele in gdata:
|
||||
ele_nr += (ele.lstrip('Solid') + ', ')
|
||||
elif gdata[0].startswith('Face'):
|
||||
physical_type = 'Surface'
|
||||
for ele in gdata:
|
||||
ele_nr += (ele.lstrip('Face') + ', ')
|
||||
elif gdata[0].startswith('Edge') or gdata[0].startswith('Vertex'):
|
||||
geo.write("// " + group + " group data not written. Edges or Vertexes group data not supported.\n")
|
||||
print(' Groups for Edges or Vertexes reference shapes not handeled yet.')
|
||||
if ele_nr:
|
||||
ele_nr = ele_nr.rstrip(', ')
|
||||
# print(ele_nr)
|
||||
geo.write('Physical ' + physical_type + '("' + group + '") = {' + ele_nr + '};\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("Mesh " + self.dimension + ";\n")
|
||||
geo.write("Mesh.Format = 2;\n") # unv
|
||||
if self.analysis and self.group_elements:
|
||||
geo.write("// For each group save not only the elements but the nodes too.;\n")
|
||||
geo.write("Mesh.SaveGroupsOfNodes = 1;\n")
|
||||
geo.write("// Needed for Group meshing too, because for one material there is no group defined;\n") # belongs to Mesh.SaveAll but anly needed if there are groups
|
||||
geo.write("// Ignore Physical definitions and save all elements;\n")
|
||||
geo.write("Mesh.SaveAll = 1;\n")
|
||||
geo.write("\n")
|
||||
geo.write('Save "' + self.temp_file_mesh + '";\n')
|
||||
geo.write("\n\n")
|
||||
geo.write("//////////////////////////////////////////////////////////////////////\n")
|
||||
geo.write("// GMSH documentation:\n")
|
||||
geo.write("// http://gmsh.info/doc/texinfo/gmsh.html#Mesh\n")
|
||||
geo.write("//\n")
|
||||
geo.write("// We do not check if something went wrong, like negative jacobians etc. You can run GMSH manually yourself: \n")
|
||||
geo.write("//\n")
|
||||
geo.write("// to see full GMSH log, run in bash:\n")
|
||||
geo.write("// " + self.gmsh_bin + " - " + self.temp_file_geo + "\n")
|
||||
geo.write("//\n")
|
||||
geo.write("// to run GMSH and keep file in GMSH GUI (with log), run in bash:\n")
|
||||
geo.write("// " + self.gmsh_bin + " " + self.temp_file_geo + "\n")
|
||||
geo.close
|
||||
|
||||
def run_gmsh_with_geo(self):
|
||||
self.error = False
|
||||
comandlist = [self.gmsh_bin, '-', self.temp_file_geo]
|
||||
# print(comandlist)
|
||||
try:
|
||||
p = subprocess.Popen(comandlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output, error = p.communicate()
|
||||
# print(output) # stdout is still cut at some point but the warnings are in stderr and thus printed :-)
|
||||
# print(error)
|
||||
except:
|
||||
error = 'Error executing: {}\n'.format(self.gmsh_command)
|
||||
FreeCAD.Console.PrintError(error)
|
||||
self.error = True
|
||||
return error
|
||||
|
||||
def read_and_set_new_mesh(self):
|
||||
if not self.error:
|
||||
fem_mesh = Fem.read(self.temp_file_mesh)
|
||||
self.mesh_obj.FemMesh = fem_mesh
|
||||
print(' The Part should have a pretty new FEM mesh!')
|
||||
else:
|
||||
print('No mesh was created.')
|
||||
del self.temp_file_geometry
|
||||
del self.temp_file_mesh
|
||||
|
||||
# @}
|
203
src/Mod/Fem/TaskPanelFemMeshGmsh.ui
Normal file
203
src/Mod/Fem/TaskPanelFemMeshGmsh.ui
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GmshMesh</class>
|
||||
<widget class="QWidget" name="GmshMesh">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>FEM Mesh by GMSH </string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb01_mesh_params">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>1677215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>FEM Mesh Parameter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_1">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="l_dimension">
|
||||
<property name="text">
|
||||
<string>Mesh element dimension:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cb_dimension"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="l_order">
|
||||
<property name="text">
|
||||
<string>Mesh element order:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cb_order"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="l_max">
|
||||
<property name="text">
|
||||
<string>Max element size (0.0 = Auto):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::InputField" name="if_max">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>1000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="decimals" stdset="0">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="l_min">
|
||||
<property name="text">
|
||||
<string>Min element size (0.0 = Auto):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::InputField" name="if_min">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>1000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="decimals" stdset="0">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb03_run_gmsh">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>1677215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>GMSH</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gl_actions">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="l_time">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextEdit" name="te_output">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::InputField</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Gui/InputField.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
170
src/Mod/Fem/_TaskPanelFemMeshGmsh.py
Normal file
170
src/Mod/Fem/_TaskPanelFemMeshGmsh.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshGmsh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import time
|
||||
import _FemMeshGmsh
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGmsh:
|
||||
'''The TaskPanel for editing References property of FemMeshGmsh objects and creation of new FEM mesh'''
|
||||
def __init__(self, obj):
|
||||
self.mesh_obj = obj
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/TaskPanelFemMeshGmsh.ui")
|
||||
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(100) # 100 milli seconds
|
||||
self.gmsh_runs = False
|
||||
self.console_message_gmsh = ''
|
||||
|
||||
QtCore.QObject.connect(self.form.if_max, QtCore.SIGNAL("valueChanged(double)"), self.max_changed)
|
||||
QtCore.QObject.connect(self.form.if_min, QtCore.SIGNAL("valueChanged(double)"), self.min_changed)
|
||||
QtCore.QObject.connect(self.form.cb_dimension, QtCore.SIGNAL("activated(int)"), self.choose_dimension)
|
||||
QtCore.QObject.connect(self.form.cb_order, QtCore.SIGNAL("activated(int)"), self.choose_order)
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.update_timer_text)
|
||||
|
||||
self.form.cb_dimension.addItems(_FemMeshGmsh._FemMeshGmsh.known_element_dimensions)
|
||||
self.form.cb_order.addItems(_FemMeshGmsh._FemMeshGmsh.known_element_orders)
|
||||
|
||||
self.get_mesh_params()
|
||||
self.get_active_analysis()
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Close)
|
||||
# show a apply and a close button
|
||||
# def reject() is called on close button
|
||||
# def clicked(self, button) is needed, to access the apply button
|
||||
# def accept() in no longer needed, since there is no OK button
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def clicked(self, button):
|
||||
if button == QtGui.QDialogButtonBox.Apply:
|
||||
self.run_gmsh()
|
||||
|
||||
def get_mesh_params(self):
|
||||
self.clmax = self.mesh_obj.ElementSizeMax
|
||||
self.clmin = self.mesh_obj.ElementSizeMin
|
||||
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.ElementOrder = self.order
|
||||
self.mesh_obj.ElementDimension = self.dimension
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_max.setText("{} mm".format(self.clmax))
|
||||
self.form.if_min.setText("{} mm".format(self.clmin))
|
||||
index_dimension = self.form.cb_dimension.findText(self.dimension)
|
||||
self.form.cb_dimension.setCurrentIndex(index_dimension)
|
||||
index_order = self.form.cb_order.findText(self.order)
|
||||
self.form.cb_order.setCurrentIndex(index_order)
|
||||
|
||||
def console_log(self, message="", color="#000000"):
|
||||
self.console_message_gmsh = self.console_message_gmsh + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.te_output.setText(self.console_message_gmsh)
|
||||
self.form.te_output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def update_timer_text(self):
|
||||
# print('timer1')
|
||||
if self.gmsh_runs:
|
||||
print('timer2')
|
||||
# print('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def max_changed(self, value):
|
||||
self.clmax = float(value)
|
||||
|
||||
def min_changed(self, value):
|
||||
self.clmin = float(value)
|
||||
|
||||
def choose_dimension(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_dimension.setCurrentIndex(index)
|
||||
self.dimension = str(self.form.cb_dimension.itemText(index)) # form returns unicode
|
||||
|
||||
def choose_order(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_order.setCurrentIndex(index)
|
||||
self.order = str(self.form.cb_order.itemText(index)) # form returns unicode
|
||||
|
||||
def run_gmsh(self):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.console_message_gmsh = ''
|
||||
self.gmsh_runs = True
|
||||
self.console_log("We gone start ...")
|
||||
self.get_active_analysis()
|
||||
self.set_mesh_params()
|
||||
import FemGmshTools
|
||||
gmsh_mesh = FemGmshTools.FemGmshTools(self.obj, self.analysis)
|
||||
self.console_log("Start GMSH ...")
|
||||
error = gmsh_mesh.create_mesh()
|
||||
if error:
|
||||
print(error)
|
||||
self.console_log('GMSH had warnings ...')
|
||||
self.console_log(error, '#FF0000')
|
||||
else:
|
||||
self.console_log('Clean run of GMSH')
|
||||
self.console_log("GMSH done!")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.Timer.stop()
|
||||
self.update()
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def get_active_analysis(self):
|
||||
import FemGui
|
||||
self.analysis = FemGui.getActiveAnalysis()
|
||||
if self.analysis:
|
||||
for m in FemGui.getActiveAnalysis().Member:
|
||||
if m.Name == self.mesh_obj.Name:
|
||||
print(self.analysis.Name)
|
||||
return
|
||||
else:
|
||||
# print('Mesh is not member of active analysis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
else:
|
||||
# print('No active analyis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
|
@ -72,8 +72,7 @@ class _ViewProviderFemMeshGmsh:
|
|||
if FemGui.getActiveAnalysis().Document is FreeCAD.ActiveDocument:
|
||||
if self.Object in FemGui.getActiveAnalysis().Member:
|
||||
if not gui_doc.getInEdit():
|
||||
FreeCAD.Console.PrintError('TaskPanel test not yet implemented\n')
|
||||
# gui_doc.setEdit(vobj.Object.Name)
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Activate the analysis this mesh belongs to!\n')
|
||||
else:
|
||||
|
@ -84,8 +83,7 @@ class _ViewProviderFemMeshGmsh:
|
|||
if m == self.Object:
|
||||
FemGui.setActiveAnalysis(o)
|
||||
print('Analysis the Mesh belongs too was activated.')
|
||||
FreeCAD.Console.PrintError('TaskPanel test not yet implemented\n')
|
||||
# gui_doc.setEdit(vobj.Object.Name)
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
break
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Active Analysis is not in active Document!\n')
|
||||
|
@ -97,8 +95,7 @@ class _ViewProviderFemMeshGmsh:
|
|||
if m == self.Object:
|
||||
FemGui.setActiveAnalysis(o)
|
||||
print('Analysis the Mesh belongs too was activated.')
|
||||
FreeCAD.Console.PrintError('TaskPanel test not yet implemented\n')
|
||||
# gui_doc.setEdit(vobj.Object.Name)
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
break
|
||||
else:
|
||||
print('Mesh GMSH object does not belong to an analysis. Group meshing will is deactivated.')
|
||||
|
|
Loading…
Reference in New Issue
Block a user