-
Notifications
You must be signed in to change notification settings - Fork 4
/
salome_plugins.py
475 lines (397 loc) · 15.5 KB
/
salome_plugins.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 3 14:35:56 2016
@author: Rainer Jacob
Salome Plugin-manager file for declaration of Elmer functionality to Salome
"""
try:
from PyQt4 import QtGui
from PyQt4 import QtCore
except ImportError:
from PyQt5 import QtWidgets as QtGui
from PyQt5 import QtCore
from distutils import spawn
import salome_pluginsmanager as sp
import SMESH as smesh
import salome
import sys
import os
import subprocess
import pdb
from salome.smesh import smeshstudytools
from salome.gui import helper
# %% setup
plugin_path = ""
# add SALOME_PLUGIN_PATH to Python environment for easier module import
if (os.environ.get("SALOME_PLUGINS_PATH") is not None):
plugin_path = os.environ.get("SALOME_PLUGINS_PATH") +\
os.sep + "ElmerSalome"
if not (os.path.exists(plugin_path + os.sep + "elmer_window_handler.py")):
import inspect
plugin_path = os.path.dirname(inspect.getfile(inspect.currentframe())) +\
os.sep + "ElmerSalome"
sys.path.append(plugin_path)
if not (os.path.exists(plugin_path + os.sep + "elmer_window_handler.py")):
sys.exit("No Elmer module found")
# import window handler
import elmer_window_handler as ewh
# global variable that will contain the Elmer-class and its memory-location
global main
# the environement variable is required to prevent the re-initialization
# of the Elmer-class each time the menu is opened, otherwise everything will
# be lost again,
# see http://www.salome-platform.org/forum/forum_12/575675631/639739196
if os.getenv("already_initialized", "0") != "1":
main = ewh.ElmerWindowHandler()
os.environ["already_initialized"] = "1"
widget = None
tool = smeshstudytools.SMeshStudyTools()
# %% Elmer control window
def control(context):
"""Creates a floating window in the foreground that allows access to the
Elmer functionality the same way the Tools-menu does.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global widget, about, generalSetup, showEquations, showMaterials
global defineElementProperties, showBodyForces, showBoundaryConditions
global showInitialConditions, createMesh, writeSif, startSolver, readSif, parallelSettings
global QtCore
# QWidget
widget = QtGui.QWidget()
widget.setWindowTitle('Elmer control')
widget.setWindowFlags(widget.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
# QPushButtons
button_about = QtGui.QPushButton('About', widget)
button_reader = QtGui.QPushButton('Read sif file', widget)
button_general = QtGui.QPushButton('General settings', widget)
button_eq = QtGui.QPushButton('Equations', widget)
button_mat = QtGui.QPushButton('Materials', widget)
button_bf = QtGui.QPushButton('Body Forces', widget)
button_bc = QtGui.QPushButton('Boundary conditions', widget)
button_ic = QtGui.QPushButton('Initial conditions', widget)
button_ep = QtGui.QPushButton('Object properties', widget)
button_mesh = QtGui.QPushButton('Mesh creation', widget)
button_sif = QtGui.QPushButton('Sif file creation', widget)
button_parallel = QtGui.QPushButton('Parallel settings', widget)
button_solve = QtGui.QPushButton('Start ElmerSolver', widget)
# QPushButton-Events
button_about.clicked.connect(lambda: about(context))
button_reader.clicked.connect(lambda: readSif(context))
button_general.clicked.connect(lambda: generalSetup(context))
button_eq.clicked.connect(lambda: showEquations(context))
button_mat.clicked.connect(lambda: showMaterials(context))
button_bf.clicked.connect(lambda: showBodyForces(context))
button_bc.clicked.connect(lambda: showBoundaryConditions(context))
button_ic.clicked.connect(lambda: showInitialConditions(context))
button_ep.clicked.connect(lambda: defineElementProperties(context))
button_mesh.clicked.connect(lambda: createMesh(context))
button_sif.clicked.connect(lambda: writeSif(context))
button_parallel.clicked.connect(lambda: parallelSettings(context))
button_solve.clicked.connect(lambda: startSolver(context))
layout = QtGui.QVBoxLayout()
layout.addWidget(button_about)
layout.addWidget(button_reader)
layout.addWidget(button_general)
layout.addWidget(button_eq)
layout.addWidget(button_mat)
layout.addWidget(button_bf)
layout.addWidget(button_bc)
layout.addWidget(button_ic)
layout.addWidget(button_ep)
layout.addWidget(button_mesh)
layout.addWidget(button_parallel)
layout.addWidget(button_sif)
layout.addWidget(button_solve)
widget.setLayout(layout)
widget.show()
# %% define about Function
def about(context):
"""Shows an info dialog for the plugin. May contain additional information
in the future.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.about(None, str(active_module),
"Functionality is only provided in mesh module.")
return
title = "ELMER interface for SALOME editor"
msg = "Interface that allows setup of an Elmer simulation with the help of the Salome Mesh editor and generation of necessary sif-file.\n"
msg1 = "The mesh is exported as *.unv and converted with ElmerGrid. ElmerSolver can be started in a single process or using multiprocessing.\n\n"
msg2 = "by raja, mzenker, 2017."
QtGui.QMessageBox.about(None, title, msg + msg1 + msg2)
return
# %% generalSetup
def generalSetup(context):
"""Shows the general setup dialog for Elmer.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.about(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showGeneralSetup()
# %% equation definition
def showEquations(context):
"""Shows the window for the definition of equations.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.about(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showAddEquation()
# %% material defintion
def showMaterials(context):
"""Shows the window for the definition of materials.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showAddMaterial()
# %% element properties
def defineElementProperties(context):
"""Context sensitive window for setting the element properties. Faces and
bodies will create different windows.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
# get selection
selCount = sp.sg.SelectedCount()
if selCount == 0:
QtGui.QMessageBox.information(None, str(active_module),
"Nothing selected. Please select a volume/face or group of.")
return
# check shape, should be volume or face
else:
objID = sp.sg.getSelected(0)
salomeObj = sp.salome.myStudy.FindObjectID(objID)
parentGroupCategory = salomeObj.GetFather().GetName()
if "Volumes" in parentGroupCategory:
main.showBodyPropertyDefinition(salomeObj.GetName())
return
if "Faces" in parentGroupCategory:
main.showBoundaryPropertyDefinition(salomeObj.GetName())
return
else:
mes = "Invalid selection. Check selection."
QtGui.QMessageBox.warning(None, str(active_module), mes)
return
# %% body forces
def showBodyForces(context):
"""Shows the window for the definition of body forces.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showAddBodyForce()
# %% boundary conditions
def showBoundaryConditions(context):
"""Shows the window for the definition of boundary conditions.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showAddBoundaryCondition()
# %% initial conditions
def showInitialConditions(context):
"""Shows the window for the definition of initial conditions.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showAddInitialCondition()
# %% mesh creation
def createMesh(context):
"""Context sensitive window for setting for mesh export. Only a mesh-node
in the object tree of salome will create the correct output - unv-mesh and
ElmerGrid mesh.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, smesh, salome, subprocess, QtGui, pdb, spawn, tool
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
# get selection
selCount = sp.sg.SelectedCount()
if selCount == 0:
QtGui.QMessageBox.warning(None, str(active_module),
"Nothing selected. Please select a mesh.")
return
# check if selection == mesh
else:
try:
myMesh = tool.getMeshObjectSelected()
except AttributeError:
QtGui.QMessageBox.warning(None, str(active_module),
"Selection is not a mesh.")
return
# get a filename for saving the unv-mesh
title = 'Export mesh to file'
fname = QtGui.QFileDialog.getSaveFileName(parent=None, caption=title,
filter='Mesh files (*.unv)')
# Salome 8.2 behavior
if isinstance(fname, tuple):
fname = fname[0]
# pdb.set_trace()
# call to ElmerGrid for converting the unv-file to Elmer-readable file
if fname:
fname = os.path.normpath(str(fname))
path = os.path.dirname(fname)
# Linux does not add file ending automatically
if not fname.endswith('.unv'):
fname = '{}.unv'.format(fname)
if os.path.exists(fname):
os.remove(fname)
myMesh.ExportUNV(fname)
prgm = spawn.find_executable('ElmerGrid')
if prgm != None:
try:
# on Linux shell=True required,
# see http://stackoverflow.com/a/18962815/4141279
subprocess.Popen("ElmerGrid 8 2 {0} -autoclean -out {1}".format(fname, path), shell=True)
main.meshDirectory = path
except OSError:
QtGui.QMessageBox.about(None, "File IO error", "fname: {}, path: {}".format(fname, path))
print (fname)
print (path)
return
else:
QtGui.QMessageBox.warning(None, str(active_module),
"ElmerGrid executable not found. Check system variables.")
return
# %% call to ElmerSolver
def startSolver(context):
"""Calls the ElmerSolver. Checks if a sif-file is present and whether
multiprocessing is available.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, sp, smesh, salome, subprocess, QtGui, pdb, spawn
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.start_Solver()
# %% parallel settings
def parallelSettings(context):
"""Shows the parallel settings window
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.showParallelSettings()
# %% sif generator
def writeSif(context):
"""Calls the sif generator.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.sif_write()
# %% sif reader
def readSif(context):
"""Calls the sif reader.
Args:
-----
context: salome context
Context variable provided by the Salome environment
"""
global main, QtGui, ewh
main = ewh.ElmerWindowHandler()
# get active module and check if SMESH
active_module = context.sg.getActiveComponent()
if active_module != "SMESH":
QtGui.QMessageBox.information(None, str(active_module),
"Functionality is only provided in mesh module.")
return
main.sif_read()
# %% declare Elmer-Functions to plugin manager
sp.AddFunction('Elmer FEM', 'Elmer plugin control window', control)