FEM: GMSH mesh tool, the GMSH tool class and a task panel

This commit is contained in:
Bernd Hahnebach 2016-11-22 19:48:02 +01:00
parent 1327589045
commit ae90dd0522
6 changed files with 641 additions and 6 deletions

View File

@ -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

View File

@ -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
View 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
# @}

View 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>

View 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

View File

@ -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.')