1 # Copyright (C) 2016-2019 CEA/DEN, EDF R&D
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 import sys, pickle, tempfile, shutil
21 from os import path, getpid, environ, remove, system
23 from PyQt5.QtCore import *
24 from PyQt5.QtGui import *
25 from PyQt5.QtWidgets import *
27 from . import utilityFunctions as uF
28 from . import genereCrack, Zset, output, zcracks_ui
30 from .output import message, init
31 from .zcracks_ui import Ui_Zui
34 # ---------------------
36 # ---------------------
39 def stringToFloat(string, typ=float):
40 if str(string).replace(' ','')=='':
43 out=list(map(typ, str(string).split()))
46 def addExtension(string, extension):
55 res=string.find('.',start)
61 if strLen<=(lastPt+1+5) and lastPt!=0:
62 out=string[:(lastPt+1)]+extension.replace('.','')
64 out=string+'.'+extension.replace('.','')
68 # ----------------------------
69 # DEFINITION DE LA CLASSE
70 # ----------------------------
71 class ShipHolderApplication(QGroupBox):
73 def __init__(self, parent=None):
74 super (ShipHolderApplication, self).__init__(parent)
76 self.salomeVers=path.normpath(environ['ROOT_SALOME'])
77 self.salomeVers=path.split(self.salomeVers)[-1].split('V')[-1]
82 self.ui.widget.setVisible(False)
83 self.tmpdir=tempfile.mkdtemp()
84 self.saneGeoName=path.join(self.tmpdir,'salome_sane.geo')
85 self.crackGeoName=path.join(self.tmpdir,'salome_crack.geo')
86 self.crackMedName=path.join(self.tmpdir,'salome_crack.med')
87 self.crackedGeoName=path.join(self.tmpdir,'cracked.geo')
94 self.ui.CBQuad.toggled.connect(self.pressQuad)
95 self.ui.btReset.clicked.connect(self.pressReset)
96 self.ui.btCancel.clicked.connect(self.pressCancel)
97 self.ui.btApply.clicked.connect(self.pressApply)
98 self.ui.btApplyClose.clicked.connect(self.pressApplyClose)
99 self.ui.btLoad.clicked.connect(self.pressCharger)
100 self.ui.btSave.clicked.connect(self.pressSauver)
101 self.ui.btLoadCracked.clicked.connect(self.pressLoadCracked)
102 self.ui.btLoadSane.clicked.connect(self.pressLoadSane)
104 self.ui.btGrVol.clicked.connect(self.pressLoadGroupVOL)
105 self.ui.btGrFace.clicked.connect(self.pressLoadGroupFACE)
106 self.ui.btGrEdge.clicked.connect(self.pressLoadGroupEDGE)
107 self.ui.btGrNode.clicked.connect(self.pressLoadGroupNODE)
108 self.ui.btGrAll.clicked.connect(self.pressLoadGroupALL)
109 self.ui.btVisu.clicked.connect(self.pressVisu)
111 self.ui.CBAdvanced.toggled.connect(self.pressAdvanced)
112 self.lineEditTypes=[str, str, float,
118 self.lineEditNames=['crackedName','saneName','minSize',
119 'maxSize','extractLength','grVol',
120 'grFace','grEdge','grNodes',
121 'gradation','iterations','layers',
124 self.lineEditObjects=[self.ui.valCrackedName,self.ui.valSaneName,self.ui.valMinSize,
125 self.ui.valMaxSize,self.ui.valExtractLength,self.ui.valGrVol,
126 self.ui.valGrFace,self.ui.valGrEdge,self.ui.valGrNode,
127 self.ui.valGradation,self.ui.valIterations,self.ui.valLayers,
130 def createWidgets(self):
132 self.ui.setupUi(self)
134 # -----------------------------------
135 # FONCTIONS D'ACTIONS DES BOUTONS
136 # -----------------------------------
139 if self.ui.CBQuad.isChecked():
140 self.ui.CBBarsoum.setEnabled(True)
141 self.ui.valGradation.setText('2.3')
143 self.ui.valGradation.setText('1.3')
144 self.ui.CBBarsoum.setChecked(False)
145 self.ui.CBBarsoum.setEnabled(False)
148 def pressReset(self):
149 for val in self.lineEditObjects:
151 self.ui.CBQuad.setChecked(False)
152 self.ui.CBBarsoum.setChecked(False)
153 nbOnglet=self.ui.tabWidget.count()
154 for iongl in range(nbOnglet):
155 onglet=self.ui.tabWidget.widget(iongl)
156 tab=onglet.findChildren(QTableWidget)[0]
157 for irow in range(tab.rowCount()):
158 if tab.item(irow,0) != None:
159 tab.item(irow,0).setText('')
160 self.ui.valGradation.setText('1.3')
161 self.ui.valLayers.setText('6')
162 self.ui.valIterations.setText('2')
163 self.ui.CBIs2D.setChecked(False)
164 self.ui.CBRefine.setChecked(False)
167 def pressApply(self):
168 message('M','\n\n -------------')
169 message('M',' Nouveau cas ')
170 message('M',' -------------')
171 message('M','Getting parameters and checking ...')
173 test=uF.check(self.data)
177 message('M','Parameters checked and ready to go')
179 message('E','Parameters checking failled',goOn=True)
182 message('M','\nGenerating crack ...')
183 res=genereCrack.main(self.data, self.crackMedName)
185 message('M','Crack generated successfully')
187 message('E','Crack generation failed',goOn=True)
190 if self.ui.CBIs2D.isChecked():
191 res=Zset.medToGeo(self.data['saneName'],self.saneGeoName, self.tmpdir, verbose=self.verbose, opt=[' **to_3d'])
193 res=Zset.medToGeo(self.data['saneName'],self.saneGeoName, self.tmpdir, verbose=self.verbose)
196 message('E','medToGeo sane failed',goOn=True)
199 #opt=['**elset crack *function 1.;','**elset elset0 *function 1.;']
200 res=Zset.medToGeo(self.crackMedName,self.crackGeoName, self.tmpdir, verbose=self.verbose)
202 message('E','medToGeo crack failed',goOn=True)
205 names={'saneGeoName':self.saneGeoName, 'crackGeoName':self.crackGeoName, 'crackedGeoName':self.crackedGeoName}
206 message('M','\nInserting crack ...')
207 res=Zset.insertCrack(self.data, names, self.tmpdir, verbose=self.verbose)
209 message('E','Crack insertion failed',goOn=True)
212 message('M','Crack inserted successfully')
214 if self.ui.CBQuad.isChecked() and self.ui.CBBarsoum.isChecked():
215 message('M','\nSaving cracked mesh in quadratic with Barsoum elements...')
216 opt=[' **lin_to_quad',' **crack_3d_quarter_nodes',' *liset FRONT0']
217 res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, opt=opt, verbose=self.verbose)
219 elif self.ui.CBQuad.isChecked() and not self.ui.CBBarsoum.isChecked():
220 message('M','\nSaving cracked mesh in quadratic...')
221 opt=[' **lin_to_quad']
222 res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, opt=opt, verbose=self.verbose)
225 message('M','\nSaving cracked mesh...')
226 res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, verbose=self.verbose)
228 uF.extendElsets(self.data['crackedName'])
231 message('M','Cracked mesh ready at : %s' %(self.data['crackedName']))
232 message('M','Maximal aspect ratio is %f' %(uF.getMaxAspectRatio(self.tmpdir)))
233 #message('M','medit %s/_mesh_out_to_ghs3d.mesh' %(self.tmpdir))
234 message('M','\n ----------------')
235 message('M',' Fin cas OK ')
236 message('M',' ----------------')
240 def pressApplyClose(self):
245 def pressLoadCracked(self):
246 fileDiag = QFileDialog(self)
247 fileDiag.setFileMode(QFileDialog.AnyFile)
248 fileDiag.setNameFilters(["Parametres *.med (*.*med)","All files (*)"])
249 fileDiag.setViewMode(QFileDialog.List)
250 if fileDiag.exec_() :
251 fileNames = fileDiag.selectedFiles()
252 filedef = fileNames[0]
253 filedef = addExtension(str(filedef), 'med')
254 self.ui.valCrackedName.setText(filedef)
257 def pressLoadSane(self):
258 fileDiag = QFileDialog(self)
259 fileDiag.setFileMode(QFileDialog.AnyFile)
260 fileDiag.setNameFilters(["Parametres *.med (*.*med)","All files (*)"])
261 fileDiag.setViewMode(QFileDialog.List)
262 if fileDiag.exec_() :
263 fileNames = fileDiag.selectedFiles()
264 filedef = fileNames[0]
265 self.ui.valSaneName.setText(filedef)
268 def pressCharger(self):
269 fileDiag = QFileDialog(self)
270 fileDiag.setFileMode(QFileDialog.AnyFile)
271 fileDiag.setNameFilters(["Parametres *.dic (*.dic)","All files (*)"])
272 fileDiag.setViewMode(QFileDialog.List)
274 if fileDiag.exec_() :
275 fileNames = fileDiag.selectedFiles()
276 filedef = fileNames[0]
277 if not path.isfile(str(filedef)):
278 message('E','Invalid dic file')
279 self.data=pickle.load(open(str(filedef),'r'))
280 message('M','\nLoading parameters from %s' %str(filedef))
282 for cont, obj in enumerate(self.lineEditObjects):
283 if self.lineEditTypes[cont] in [float, int]:
284 obj.setText(self.data['TXT'+self.lineEditNames[cont]])
286 obj.setText(self.data[self.lineEditNames[cont]])
288 self.ui.CBQuad.setChecked(True if 'quad' in list(self.data.keys()) and self.data['quad'] else False)
289 self.ui.CBBarsoum.setChecked(True if 'barsoum' in list(self.data.keys()) and self.data['barsoum'] else False)
290 self.ui.CBIs2D.setChecked(True if 'is2D' in list(self.data.keys()) and self.data['is2D'] else False)
291 self.ui.CBRefine.setChecked(True if 'refine' in list(self.data.keys()) and self.data['refine'] else False)
293 self.setTableParameters()
296 def pressSauver(self):
297 fileDiag = QFileDialog(self)
298 fileDiag.setFileMode(QFileDialog.AnyFile)
299 fileDiag.setNameFilters(["Parametres *.dic (*.dic)","All files (*)"])
300 fileDiag.setViewMode(QFileDialog.List)
301 if fileDiag.exec_() :
303 fileNames = fileDiag.selectedFiles()
304 filedef = fileNames[0]
305 pickle.dump(self.data, open(addExtension(str(filedef), 'dic'),'w'))
306 message('M','Saving parameters in %s' %addExtension(str(filedef), 'dic'))
308 def pressLoadGroupVOL(self):
310 self.GroupToLoad='VOL'
313 message('E','Groups loading impossible',goOn=True)
315 def pressLoadGroupFACE(self):
317 self.GroupToLoad='FACE'
320 message('E','Groups loading impossible',goOn=True)
322 def pressLoadGroupEDGE(self):
324 self.GroupToLoad='EDGE'
327 message('E','Groups loading impossible',goOn=True)
329 def pressLoadGroupNODE(self):
331 self.GroupToLoad='NODE'
334 message('E','Groups loading impossible',goOn=True)
336 def pressLoadGroupALL(self):
338 self.GroupToLoad='ALL'
341 message('E','Groups loading impossible',goOn=True)
343 def pressAdvanced(self):
344 if self.ui.CBAdvanced.isChecked():
345 self.ui.widget.setVisible(True)
347 self.ui.widget.setVisible(False)
350 meshFile1=path.join(self.tmpdir,'_mesh_out_to_ghs3d.mesh')
351 meshFile2=path.join(self.tmpdir,'_mesh_out_.mesh')
352 test1=path.isfile(meshFile1)
353 test2=path.isfile(meshFile2)
354 medit=path.join('$Z7PATH/PUBLIC/lib-Linux_64/Zmesh/bin/medit')
357 message('A','No mesh file to visualize')
359 print(medit+' %s' %meshFile2)
360 system(medit+' %s' %meshFile2)
362 print(medit+' %s' %meshFile1)
363 system(medit+' %s' %meshFile1)
366 def pressCancel(self):
367 message('M','exiting Zcracks')
369 shutil.rmtree(self.tmpdir)
371 message('E','Impossible to delete %s' %self.tmpdir,goOn=True)
375 # ---------------------------------
376 # FONCTIONS ANNEXES A LA CLASSE
377 # ---------------------------------
380 def getParameters(self):
381 for cont, name in enumerate(self.lineEditNames):
382 value=str(self.lineEditObjects[cont].text())
384 if self.lineEditTypes[cont] == float:
385 self.data['TXT'+name]=value
386 self.data[name]= stringToFloat(value)
387 elif self.lineEditTypes[cont] == int:
388 self.data['TXT'+name]=value
389 self.data[name]= stringToFloat(value, typ=int)
391 self.data[name]=value
392 self.data['quad']=self.ui.CBQuad.isChecked()
393 self.data['barsoum']=self.ui.CBBarsoum.isChecked()
394 self.data['TXTcrack']=self.getTableParameters()
395 self.data['crack']=self.getTableParameters(str2float=True)
396 self.data['is2D']=self.ui.CBIs2D.isChecked()
397 self.data['refine']=self.ui.CBRefine.isChecked()
400 def getTableParameters(self, str2float=False):
401 nbOnglet=self.ui.tabWidget.count()
403 iOngletActif=self.ui.tabWidget.currentIndex()
405 for iongl in range(nbOnglet):
407 onglet=self.ui.tabWidget.widget(iongl)
408 tab=onglet.findChildren(QTableWidget)[0]
409 for irow in range(tab.rowCount()):
410 label=tab.verticalHeaderItem(irow).text()
411 if tab.item(irow,0) is None:
413 elif 'med file' in str(label):
414 crack[str(label)]=str(tab.item(irow,0).text())
416 value=tab.item(irow,0).text()
418 crack[str(label)]=stringToFloat(value)
420 crack[str(label)]=str(value)
421 out[str(self.ui.tabWidget.tabText(iongl))]=crack
422 if iongl==iOngletActif:
423 ongletActif=str(self.ui.tabWidget.tabText(iongl))
425 out['actif']=ongletActif
429 def setTableParameters(self):
430 nbOnglet=self.ui.tabWidget.count()
431 #iOngletActif=self.ui.tabWidget.currentIndex()
432 for iongl in range(nbOnglet):
433 onglet=self.ui.tabWidget.widget(iongl)
434 tab=onglet.findChildren(QTableWidget)[0]
435 for irow in range(tab.rowCount()):
436 label=tab.verticalHeaderItem(irow).text()
437 if tab.item(irow,0) == None:
438 item = QTableWidgetItem()
439 tab.setItem(irow, 0, item)
440 tab.item(irow,0).setText(self.data['TXTcrack'][str(self.ui.tabWidget.tabText(iongl))][str(label)])
441 if str(self.ui.tabWidget.tabText(iongl)) == self.data['TXTcrack']['actif']:
442 self.ui.tabWidget.setCurrentWidget(onglet)
445 def loadGroups(self):
446 saneFile=str(self.ui.valSaneName.text())
447 message('I','Loading Sane mesh...')
448 if not path.isfile(saneFile):
449 message('E','Sane mesh med file is not valid')
452 #salome.salome_init()
453 from salome.smesh import smeshBuilder
454 smesh = smeshBuilder.New()
456 ([objetSain], status) = smesh.CreateMeshesFromMED(saneFile)
458 groupsVOL, groupsFAC, groupsEDG, groupsNOD = '', '', '', ''
461 for group in objetSain.GetGroups():
462 if (self.GroupToLoad in ['VOL','ALL']) and (group.GetType()==SMESH.VOLUME):
463 groupsVOL+=self.cleanGroupName(group)
466 if (self.GroupToLoad in ['FACE','ALL']) and (group.GetType()==SMESH.FACE):
467 groupsFAC+=self.cleanGroupName(group)
470 if (self.GroupToLoad in ['EDGE','ALL']) and (group.GetType()==SMESH.EDGE):
471 groupsEDG+=self.cleanGroupName(group)
474 if (self.GroupToLoad in ['NODE','ALL']) and (group.GetType()==SMESH.NODE):
475 groupsNOD+=self.cleanGroupName(group)
478 if groupsVOL!='': self.ui.valGrVol.setText(groupsVOL)
479 if groupsFAC!='': self.ui.valGrFace.setText(groupsFAC)
480 if groupsEDG!='': self.ui.valGrEdge.setText(groupsEDG)
481 if groupsNOD!='': self.ui.valGrNode.setText(groupsNOD)
483 message('I','%d group(s) found' %nGr)
485 def cleanTmpFiles(self):
486 for f in [self.saneGeoName, self.crackGeoName, self.crackMedName, self.crackedGeoName]:
492 def cleanGroupName(self, group):
494 while name.endswith(' '): name=name[:-1]
496 message('A','%s group has a space in its name --> ignored' %name)
501 def checkNamesSpaces(self, names):
502 if type(names) is str: names=[names]
506 message('E','%s has a space in its name, please remove it' %n, goOn=True)
511 # ---------------------------------
512 # LANCEMENT DE LA BOITE DE DIAG
513 # ---------------------------------