Salome HOME
Fix unstable failure of SALOME_TESTS/Grids/smesh/bugs_05/F0
[modules/smesh.git] / src / Tools / ZCracksPlug / main.py
1 import sys, pickle, tempfile, shutil
2 from os import path, getpid, environ, remove, system
3
4 try:
5   from PyQt5.QtCore import *
6   from PyQt5.QtGui import *
7   from PyQt5.QtWidgets import *
8 except:
9   from PyQt4.QtCore import *
10   from PyQt4.QtGui import *
11
12 import utilityFunctions as uF
13 import genereCrack, Zset, output, zcracks_ui
14
15 from output import message, init
16 from zcracks_ui import Ui_Zui
17
18
19 #  ---------------------
20 #    FONCTIONS ANNEXES
21 #  ---------------------
22
23
24 uF.removeFromSessionPath('LD_LIBRARY_PATH', 'Meshgems-2111')
25
26 def stringToFloat(string, typ=float):
27   if str(string).replace(' ','')=='':
28     out=[]
29   else:
30     out=map(typ, str(string).split())
31   return(out)
32
33 def addExtension(string, extension):
34   cond=True
35   strLen=len(string)
36   if strLen<1:
37     out=None
38   else:
39     start=0
40     lastPt=0
41     while cond:
42       res=string.find('.',start)
43       if res==-1:
44         cond=False
45       else:
46         lastPt=res
47         start=res+1
48     if strLen<=(lastPt+1+5) and lastPt!=0:
49       out=string[:(lastPt+1)]+extension.replace('.','')
50     else:
51       out=string+'.'+extension.replace('.','')
52   return(out)
53
54
55 #  ----------------------------
56 #    DEFINITION DE LA CLASSE
57 #  ----------------------------
58 class ShipHolderApplication(QGroupBox):
59
60   def __init__(self, parent=None):
61     super (ShipHolderApplication, self).__init__(parent)
62
63     self.salomeVers=path.normpath(environ['ROOT_SALOME'])
64     self.salomeVers=path.split(self.salomeVers)[-1].split('V')[-1]
65
66     self.createWidgets()
67     self.data=dict()
68     self.GroupToLoad=None
69     self.ui.widget.setVisible(False)
70     self.tmpdir=tempfile.mkdtemp()
71     self.saneGeoName=path.join(self.tmpdir,'salome_sane.geo')
72     self.crackGeoName=path.join(self.tmpdir,'salome_crack.geo')
73     self.crackMedName=path.join(self.tmpdir,'salome_crack.med')
74     self.crackedGeoName=path.join(self.tmpdir,'cracked.geo')
75
76     global log
77     init(self.tmpdir)
78
79     self.verbose=1
80
81     #self.connect(self.ui.CBQuad, SIGNAL("toggled(bool)"),self.pressQuad)
82     #self.connect(self.ui.btReset, SIGNAL("clicked()"),self.pressReset)
83     #self.connect(self.ui.btCancel, SIGNAL("clicked()"),self.pressCancel)
84     #self.connect(self.ui.btApply, SIGNAL("clicked()"),self.pressApply)
85     #self.connect(self.ui.btApplyClose, SIGNAL("clicked()"),self.pressApplyClose)
86     #self.connect(self.ui.btLoad, SIGNAL("clicked()"),self.pressCharger)
87     #self.connect(self.ui.btSave, SIGNAL("clicked()"),self.pressSauver)
88     #self.connect(self.ui.btLoadCracked, SIGNAL("clicked()"),self.pressLoadCracked)
89     #self.connect(self.ui.btLoadSane, SIGNAL("clicked()"),self.pressLoadSane)
90
91     #self.connect(self.ui.btGrVol, SIGNAL("clicked()"),self.pressLoadGroupVOL)
92     #self.connect(self.ui.btGrFace, SIGNAL("clicked()"),self.pressLoadGroupFACE)
93     #self.connect(self.ui.btGrEdge, SIGNAL("clicked()"),self.pressLoadGroupEDGE)
94     #self.connect(self.ui.btGrNode, SIGNAL("clicked()"),self.pressLoadGroupNODE)
95     #self.connect(self.ui.btGrAll, SIGNAL("clicked()"),self.pressLoadGroupALL)
96     #self.connect(self.ui.btVisu, SIGNAL("clicked()"),self.pressVisu)
97
98     #self.connect(self.ui.CBAdvanced, SIGNAL("toggled(bool)"),self.pressAdvanced)
99
100     self.ui.CBQuad.toggled.connect(self.pressQuad)
101     self.ui.btReset.clicked.connect(self.pressReset)
102     self.ui.btCancel.clicked.connect(self.pressCancel)
103     self.ui.btApply.clicked.connect(self.pressApply)
104     self.ui.btApplyClose.clicked.connect(self.pressApplyClose)
105     self.ui.btLoad.clicked.connect(self.pressCharger)
106     self.ui.btSave.clicked.connect(self.pressSauver)
107     self.ui.btLoadCracked.clicked.connect(self.pressLoadCracked)
108     self.ui.btLoadSane.clicked.connect(self.pressLoadSane)
109
110     self.ui.btGrVol.clicked.connect(self.pressLoadGroupVOL)
111     self.ui.btGrFace.clicked.connect(self.pressLoadGroupFACE)
112     self.ui.btGrEdge.clicked.connect(self.pressLoadGroupEDGE)
113     self.ui.btGrNode.clicked.connect(self.pressLoadGroupNODE)
114     self.ui.btGrAll.clicked.connect(self.pressLoadGroupALL)
115     self.ui.btVisu.clicked.connect(self.pressVisu)
116
117     self.ui.CBAdvanced.toggled.connect(self.pressAdvanced)
118     self.lineEditTypes=[str, str, float,
119                         float, float, str,
120                         str, str, str,
121                         float, int, int,
122                         str]
123
124     self.lineEditNames=['crackedName','saneName','minSize',
125                         'maxSize','extractLength','grVol',
126                         'grFace','grEdge','grNodes',
127                         'gradation','iterations','layers',
128                         'surfopt']
129
130     self.lineEditObjects=[self.ui.valCrackedName,self.ui.valSaneName,self.ui.valMinSize,
131                      self.ui.valMaxSize,self.ui.valExtractLength,self.ui.valGrVol,
132                      self.ui.valGrFace,self.ui.valGrEdge,self.ui.valGrNode,
133                      self.ui.valGradation,self.ui.valIterations,self.ui.valLayers,
134                      self.ui.valSurfopt]
135
136   def createWidgets(self):
137     self.ui = Ui_Zui()
138     self.ui.setupUi(self)
139
140 #  -----------------------------------
141 #    FONCTIONS D'ACTIONS DES BOUTONS
142 #  -----------------------------------
143
144   def pressQuad(self):
145     if self.ui.CBQuad.isChecked():
146       self.ui.CBBarsoum.setEnabled(True)
147       self.ui.valGradation.setText(QString('2.3'))
148     else:
149       self.ui.valGradation.setText(QString('1.3'))
150       self.ui.CBBarsoum.setChecked(False)
151       self.ui.CBBarsoum.setEnabled(False)
152
153
154   def pressReset(self):
155     for val in self.lineEditObjects:
156       val.clear()
157     self.ui.CBQuad.setChecked(False)
158     self.ui.CBBarsoum.setChecked(False)
159     nbOnglet=self.ui.tabWidget.count()
160     for iongl in range(nbOnglet):
161       onglet=self.ui.tabWidget.widget(iongl)
162       tab=onglet.findChildren(QTableWidget)[0]
163       for irow in range(tab.rowCount()):
164         if tab.item(irow,0) != None:
165           tab.item(irow,0).setText(QString(''))
166     self.ui.valGradation.setText(QString('1.3'))
167     self.ui.valLayers.setText(QString('5'))
168     self.ui.valIterations.setText(QString('2'))
169     self.ui.CBIs2D.setChecked(False)
170     self.ui.CBRefine.setChecked(False)
171
172
173   def pressApply(self):
174     message('M','\n\n -------------')
175     message('M','  Nouveau cas  ')
176     message('M',' -------------')
177     message('M','Getting parameters and checking ...')
178     self.getParameters()
179     test=uF.check(self.data)
180     self.cleanTmpFiles()
181
182     if test:
183       message('M','Parameters checked and ready to go')
184     else:
185       message('E','Parameters checking failled',goOn=True)
186       return()
187
188     message('M','\nGenerating crack ...')
189     res=genereCrack.main(self.data, self.crackMedName)
190     if res:
191       message('M','Crack generated successfully')
192     else:
193       message('E','Crack generation failed',goOn=True)
194       return()
195
196     if self.ui.CBIs2D.isChecked():
197       res=Zset.medToGeo(self.data['saneName'],self.saneGeoName, self.tmpdir, verbose=self.verbose, opt=['  **to_3d'])
198     else:
199       res=Zset.medToGeo(self.data['saneName'],self.saneGeoName, self.tmpdir, verbose=self.verbose)
200
201     if res!=0:
202       message('E','medToGeo sane failed',goOn=True)
203       return()
204
205     #opt=['**elset crack *function 1.;','**elset elset0 *function 1.;']
206     res=Zset.medToGeo(self.crackMedName,self.crackGeoName, self.tmpdir, verbose=self.verbose)
207     if res!=0:
208       message('E','medToGeo crack failed',goOn=True)
209       return()
210
211     names={'saneGeoName':self.saneGeoName, 'crackGeoName':self.crackGeoName, 'crackedGeoName':self.crackedGeoName}
212     message('M','\nInserting crack ...')
213     res=Zset.insertCrack(self.data, names, self.tmpdir, verbose=self.verbose)
214     if res!=0:
215       message('E','Crack insertion failed',goOn=True)
216       return()
217     else:
218       message('M','Crack inserted successfully')
219
220     if self.ui.CBQuad.isChecked() and self.ui.CBBarsoum.isChecked():
221       message('M','\nSaving cracked mesh in quadratic with Barsoum elements...')
222       opt=['  **lin_to_quad','  **crack_3d_quarter_nodes','   *liset FRONT0']
223       res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, opt=opt, verbose=self.verbose)
224
225     elif self.ui.CBQuad.isChecked() and not self.ui.CBBarsoum.isChecked():
226       message('M','\nSaving cracked mesh in quadratic...')
227       opt=['  **lin_to_quad']
228       res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, opt=opt, verbose=self.verbose)
229
230     else:
231       message('M','\nSaving cracked mesh...')
232       res=Zset.geoToMed(self.data['crackedName'], names['crackedGeoName'], self.tmpdir, verbose=self.verbose)
233
234     uF.extendElsets(self.data['crackedName'])
235
236     if res==0:
237       message('M','Cracked mesh ready at : %s' %(self.data['crackedName']))
238       message('M','Maximal aspect ratio is %f' %(uF.getMaxAspectRatio(self.tmpdir)))
239       #message('M','medit %s/_mesh_out_to_ghs3d.mesh' %(self.tmpdir))
240       message('M','\n ----------------')
241       message('M','    Fin cas OK   ')
242       message('M',' ----------------')
243
244
245
246   def pressApplyClose(self):
247     self.pressApply()
248     self.pressCancel()
249
250
251   def pressLoadCracked(self):
252     fileDiag = QFileDialog(self)
253     fileDiag.setFileMode(QFileDialog.AnyFile)
254     fileDiag.setNameFilters(["Parametres *.med (*.*med)","All files (*)"])
255     fileDiag.setViewMode(QFileDialog.List)
256     if fileDiag.exec_() :
257       fileNames = fileDiag.selectedFiles()
258       filedef = fileNames[0]
259       filedef = addExtension(str(filedef), 'med')
260       self.ui.valCrackedName.setText(QString(filedef))
261
262
263   def pressLoadSane(self):
264     fileDiag = QFileDialog(self)
265     fileDiag.setFileMode(QFileDialog.AnyFile)
266     fileDiag.setNameFilters(["Parametres *.med (*.*med)","All files (*)"])
267     fileDiag.setViewMode(QFileDialog.List)
268     if fileDiag.exec_() :
269       fileNames = fileDiag.selectedFiles()
270       filedef = fileNames[0]
271       self.ui.valSaneName.setText(QString(filedef))
272
273
274   def pressCharger(self):
275     fileDiag = QFileDialog(self)
276     fileDiag.setFileMode(QFileDialog.AnyFile)
277     fileDiag.setNameFilters(["Parametres *.dic (*.dic)","All files (*)"])
278     fileDiag.setViewMode(QFileDialog.List)
279
280     if fileDiag.exec_() :
281       fileNames = fileDiag.selectedFiles()
282       filedef = fileNames[0]
283       if not path.isfile(str(filedef)):
284         message('E','Invalid dic file')
285       self.data=pickle.load(open(str(filedef),'r'))
286       message('M','\nLoading parameters from %s' %str(filedef))
287
288       for cont, obj in enumerate(self.lineEditObjects):
289         if self.lineEditTypes[cont] in [float, int]:
290           obj.setText(QString(self.data['TXT'+self.lineEditNames[cont]]))
291         else:
292           obj.setText(QString(self.data[self.lineEditNames[cont]]))
293
294       self.ui.CBQuad.setChecked(True if 'quad' in self.data.keys() and self.data['quad'] else False)
295       self.ui.CBBarsoum.setChecked(True if 'barsoum' in self.data.keys() and self.data['barsoum'] else False)
296       self.ui.CBIs2D.setChecked(True if 'is2D' in self.data.keys() and self.data['is2D'] else False)
297       self.ui.CBRefine.setChecked(True if 'refine' in self.data.keys() and self.data['refine'] else False)
298
299
300
301
302
303       #if self.data['quad']: self.ui.CBQuad.setChecked(True)
304       #if self.data['barsoum']: self.ui.CBBarsoum.setChecked(True)
305       #if self.data['is2D']: self.ui.CBIs2D.setChecked(True)
306       #if self.data['refine']: self.ui.CBRefine.setChecked(True)
307       self.setTableParameters()
308
309
310   def pressSauver(self):
311     fileDiag = QFileDialog(self)
312     fileDiag.setFileMode(QFileDialog.AnyFile)
313     fileDiag.setNameFilters(["Parametres *.dic (*.dic)","All files (*)"])
314     fileDiag.setViewMode(QFileDialog.List)
315     if fileDiag.exec_() :
316       self.getParameters()
317       fileNames = fileDiag.selectedFiles()
318       filedef = fileNames[0]
319       pickle.dump(self.data, open(addExtension(str(filedef), 'dic'),'w'))
320       message('M','Saving parameters in %s' %addExtension(str(filedef), 'dic'))
321
322   def pressLoadGroupVOL(self):
323     try:
324       self.GroupToLoad='VOL'
325       self.loadGroups()
326     except:
327       message('E','Groups loading impossible',goOn=True)
328
329   def pressLoadGroupFACE(self):
330     try:
331       self.GroupToLoad='FACE'
332       self.loadGroups()
333     except:
334       message('E','Groups loading impossible',goOn=True)
335
336   def pressLoadGroupEDGE(self):
337     try:
338       self.GroupToLoad='EDGE'
339       self.loadGroups()
340     except:
341       message('E','Groups loading impossible',goOn=True)
342
343   def pressLoadGroupNODE(self):
344     try:
345       self.GroupToLoad='NODE'
346       self.loadGroups()
347     except:
348       message('E','Groups loading impossible',goOn=True)
349
350   def pressLoadGroupALL(self):
351     try:
352       self.GroupToLoad='ALL'
353       self.loadGroups()
354     except:
355       message('E','Groups loading impossible',goOn=True)
356
357   def pressAdvanced(self):
358     if self.ui.CBAdvanced.isChecked():
359       self.ui.widget.setVisible(True)
360     else:
361       self.ui.widget.setVisible(False)
362
363   def pressVisu(self):
364     meshFile1=path.join(self.tmpdir,'_mesh_out_to_ghs3d.mesh')
365     meshFile2=path.join(self.tmpdir,'_mesh_out_.mesh')
366     test1=path.isfile(meshFile1)
367     test2=path.isfile(meshFile2)
368     medit=path.join('$Z7PATH/PUBLIC/lib-Linux_64/Zmesh/bin/medit')
369     if not test1:
370       if not test2:
371         message('A','No mesh file to visualize')
372       else:
373         print medit+' %s' %meshFile2
374         system(medit+' %s' %meshFile2)
375     else:
376       print medit+' %s' %meshFile1
377       system(medit+' %s' %meshFile1)
378     return()
379
380   def pressCancel(self):
381     message('M','exiting Zcracks')
382     try:
383       shutil.rmtree(self.tmpdir)
384     except:
385       message('E','Impossible to delete %s' %self.tmpdir,goOn=True)
386       pass
387     exit()
388
389 #  ---------------------------------
390 #    FONCTIONS ANNEXES A LA CLASSE
391 #  ---------------------------------
392
393
394   def getParameters(self):
395     for cont, name in enumerate(self.lineEditNames):
396       value=str(self.lineEditObjects[cont].text())
397       #print name
398       if self.lineEditTypes[cont] == float:
399         self.data['TXT'+name]=value
400         self.data[name]= stringToFloat(value)
401       elif self.lineEditTypes[cont] == int:
402         self.data['TXT'+name]=value
403         self.data[name]= stringToFloat(value, typ=int)
404       else:
405         self.data[name]=value
406     self.data['quad']=self.ui.CBQuad.isChecked()
407     self.data['barsoum']=self.ui.CBBarsoum.isChecked()
408     self.data['TXTcrack']=self.getTableParameters()
409     self.data['crack']=self.getTableParameters(str2float=True)
410     self.data['is2D']=self.ui.CBIs2D.isChecked()
411     self.data['refine']=self.ui.CBRefine.isChecked()
412
413
414   def getTableParameters(self, str2float=False):
415     nbOnglet=self.ui.tabWidget.count()
416     out=dict()
417     iOngletActif=self.ui.tabWidget.currentIndex()
418     ongletActif=False
419     for iongl in range(nbOnglet):
420       crack=dict()
421       onglet=self.ui.tabWidget.widget(iongl)
422       tab=onglet.findChildren(QTableWidget)[0]
423       for irow in range(tab.rowCount()):
424         label=tab.verticalHeaderItem(irow).text()
425         if tab.item(irow,0) is None:
426           crack[str(label)]=''
427         elif 'med file' in str(label):
428           crack[str(label)]=str(tab.item(irow,0).text())
429         else:
430           value=tab.item(irow,0).text()
431           if str2float:
432             crack[str(label)]=stringToFloat(value)
433           else:
434             crack[str(label)]=str(value)
435       out[str(self.ui.tabWidget.tabText(iongl))]=crack
436       if iongl==iOngletActif:
437         ongletActif=str(self.ui.tabWidget.tabText(iongl))
438
439     out['actif']=ongletActif
440     return(out)
441
442
443   def setTableParameters(self):
444     nbOnglet=self.ui.tabWidget.count()
445     #iOngletActif=self.ui.tabWidget.currentIndex()
446     for iongl in range(nbOnglet):
447       onglet=self.ui.tabWidget.widget(iongl)
448       tab=onglet.findChildren(QTableWidget)[0]
449       for irow in range(tab.rowCount()):
450         label=tab.verticalHeaderItem(irow).text()
451         if tab.item(irow,0) == None:
452           item = QTableWidgetItem()
453           tab.setItem(irow, 0, item)
454         tab.item(irow,0).setText(QString(self.data['TXTcrack'][str(self.ui.tabWidget.tabText(iongl))][str(label)]))
455       if str(self.ui.tabWidget.tabText(iongl)) == self.data['TXTcrack']['actif']:
456         self.ui.tabWidget.setCurrentWidget(onglet)
457
458
459   def loadGroups(self):
460     saneFile=str(self.ui.valSaneName.text())
461     message('I','Loading Sane mesh...')
462     if not path.isfile(saneFile):
463       message('E','Sane mesh med file is not valid')
464     else:
465       import SMESH, salome
466       #salome.salome_init()
467       theStudy = salome.myStudy
468       from salome.smesh import smeshBuilder
469       smesh = smeshBuilder.New(theStudy)
470
471       ([objetSain], status) = smesh.CreateMeshesFromMED(saneFile)
472
473       groupsVOL, groupsFAC, groupsEDG, groupsNOD = '', '', '', ''
474       nGr=0
475
476       for group in objetSain.GetGroups():
477         if (self.GroupToLoad in ['VOL','ALL']) and (group.GetType()==SMESH.VOLUME):
478           groupsVOL+=group.GetName().replace(' ','')+" "
479           nGr+=1
480
481         if (self.GroupToLoad in ['FACE','ALL']) and (group.GetType()==SMESH.FACE):
482           groupsFAC+=group.GetName().replace(' ','')+" "
483           nGr+=1
484
485         if (self.GroupToLoad in ['EDGE','ALL']) and (group.GetType()==SMESH.EDGE):
486           groupsEDG+=group.GetName().replace(' ','')+" "
487           nGr+=1
488
489         if (self.GroupToLoad in ['NODE','ALL']) and (group.GetType()==SMESH.NODE):
490           groupsNOD+=group.GetName().replace(' ','')+" "
491           nGr+=1
492
493       if groupsVOL!='':  self.ui.valGrVol.setText(groupsVOL)
494       if groupsFAC!='': self.ui.valGrFace.setText(groupsFAC)
495       if groupsEDG!='': self.ui.valGrEdge.setText(groupsEDG)
496       if groupsNOD!='': self.ui.valGrNode.setText(groupsNOD)
497
498       message('I','%d group(s) found' %nGr)
499
500   def cleanTmpFiles(self):
501     for f in [self.saneGeoName, self.crackGeoName, self.crackMedName, self.crackedGeoName]:
502       try:
503         remove(f)
504       except:
505         pass
506
507
508 #  ---------------------------------
509 #    LANCEMENT DE LA BOITE DE DIAG
510 #  ---------------------------------
511
512
513
514