pyansys的目标是让用户可以使用python操控ANSYS的各种产品。除了使用代码进行计算流程控制外,工程中常希望能够搞个GUI界面,这样用起来更方便。既然pyansys使用的是python语言,那么界面开发自然首选PyQt。
下面是一个简单的例子,开发一个计算矩形板的热传导的程序,其中需要输入板的长宽高、温度载荷数据,输出板上的温度分布。
利用Qt Designer可以快速地构建界面。
界面没什么好讲的,主要是一些参数输入。这里添加了一个QtIteractor
用于在软件中显示vtk。但效果并不好,之前想着是可以将pyMAPDL中的几何、网格及结果显示嵌入到QtInteractor中,但折腾了半天也没搞定,后来采用迂回策略,利用pyMAPDL将几何、网格及结果保存为vtk文件,然后读入vtk文件到QtInteractor中,虽然目标是实现了,但总觉得这种方式不优雅。
程序代码很简单,将pyMAPDL代码稍微改造一下就行了。主程序文件launch.py如下:
import sys
from testvistaUI import Ui_Form
from PyQt5.Qt import *
import pyvista as pv
from ansys.mapdl.core import launch_mapdl
import os
class Mywidget(QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
self.length = 1.8
self.width = 0.6
self.height = 0.02
self.meshSize = 5
self.hotTemp = 50
self.coldTemp = 10
self.pushButton_calc.clicked.connect(self.calc)
self.pushButton_geom.clicked.connect(self.geom)
self.pushButton_mesh.clicked.connect(self.mesh)
self.pushButton_Temperature.clicked.connect(self.post)
self.horizontalSlider.valueChanged.connect(self.valueChange)
self.mapdl = launch_mapdl()
def calc(self):
# 读取数据
self.length = float(self.lineEdit_length.text().strip())
self.width = float(self.lineEdit_width.text().strip())
self.height = float(self.lineEdit_height.text().strip())
self.meshSize = self.horizontalSlider.value()
self.hotTemp = float(self.lineEdit_hotTemperature.text())
self.coldTemp = float(self.lineEdit_coldTemperature.text())
# 几何建模与网格
self.mapdl.prep7()
self.mapdl.mp('kxx', 1, 45)
self.mapdl.et(1, 90)
self.mapdl.block(0, self.width, 0, self.length, 0, self.height)
self.mapdl.smrtsize(sizlvl=str(self.horizontalSlider.value()))
self.mapdl.vsweep(1)
self.mapdl.mesh.save('mesh.vtk')
if os.path.isfile('mesh.vtk'):
mesh = pv.get_reader('mesh.vtk')
self.widget_vista.add_mesh(mesh.read(), color='white')
# 施加载荷
self.mapdl.asel("S", vmin=3)
self.mapdl.nsla()
self.mapdl.d("all", "temp", self.coldTemp)
self.mapdl.asel("S", vmin=4)
self.mapdl.nsla()
self.mapdl.d("all", "temp", self.hotTemp)
self.mapdl.allsel()
# 求解计算
self.mapdl.run("/SOLU")
print(self.mapdl.solve())
out = self.mapdl.finish()
self.textEdit_result.append(out)
def geom(self):
self.mapdl.vplot(title='geometry')
def mesh(self):
self.mapdl.eplot(title='element',window_size=[640, 320])
def post(self):
self.mapdl.post1()
self.mapdl.set(1, 1)
self.mapdl.post_processing.plot_nodal_temperature()
def closeEvent(self, event):
self.mapdl.exit()
def valueChange(self):
self.label_meshlevel.setText(str(self.horizontalSlider.value()))
self.label_meshlevel.setFont(QFont('Arial', 12))
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setFont(QFont('微软雅黑', 9))
win = Mywidget()
win.show()
sys.exit(app.exec())
为方便理解,这里将界面代码一并贴出。下面的代码是pyuic自动生成的。界面代码文件testvistaUI.py内容如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(800, 518)
Form.setMinimumSize(QtCore.QSize(800, 0))
Form.setMaximumSize(QtCore.QSize(800, 16777215))
self.gridLayout = QtWidgets.QGridLayout(Form)
self.gridLayout.setObjectName("gridLayout")
self.pushButton_geom = QtWidgets.QPushButton(Form)
self.pushButton_geom.setObjectName("pushButton_geom")
self.gridLayout.addWidget(self.pushButton_geom, 1, 1, 1, 1)
self.widget_vista = QtInteractor(Form)
self.widget_vista.setObjectName("widget_vista")
self.gridLayout.addWidget(self.widget_vista, 0, 2, 1, 2)
self.pushButton_Temperature = QtWidgets.QPushButton(Form)
self.pushButton_Temperature.setObjectName("pushButton_Temperature")
self.gridLayout.addWidget(self.pushButton_Temperature, 1, 3, 1, 1)
self.pushButton_mesh = QtWidgets.QPushButton(Form)
self.pushButton_mesh.setObjectName("pushButton_mesh")
self.gridLayout.addWidget(self.pushButton_mesh, 1, 2, 1, 1)
self.pushButton_calc = QtWidgets.QPushButton(Form)
self.pushButton_calc.setObjectName("pushButton_calc")
self.gridLayout.addWidget(self.pushButton_calc, 1, 0, 1, 1)
self.groupBox_2 = QtWidgets.QGroupBox(Form)
self.groupBox_2.setMaximumSize(QtCore.QSize(16777215, 200))
self.groupBox_2.setObjectName("groupBox_2")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox_2)
self.gridLayout_2.setObjectName("gridLayout_2")
self.textEdit_result = QtWidgets.QTextEdit(self.groupBox_2)
self.textEdit_result.setMaximumSize(QtCore.QSize(16777215, 200))
self.textEdit_result.setReadOnly(True)
self.textEdit_result.setObjectName("textEdit_result")
self.gridLayout_2.addWidget(self.textEdit_result, 0, 0, 1, 1)
self.gridLayout.addWidget(self.groupBox_2, 2, 0, 1, 4)
self.groupBox = QtWidgets.QGroupBox(Form)
self.groupBox.setMinimumSize(QtCore.QSize(380, 0))
self.groupBox.setMaximumSize(QtCore.QSize(380, 16777215))
self.groupBox.setObjectName("groupBox")
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox)
self.gridLayout_3.setObjectName("gridLayout_3")
self.groupBox_3 = QtWidgets.QGroupBox(self.groupBox)
self.groupBox_3.setMinimumSize(QtCore.QSize(0, 120))
self.groupBox_3.setMaximumSize(QtCore.QSize(16777215, 120))
self.groupBox_3.setObjectName("groupBox_3")
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_3)
self.gridLayout_4.setObjectName("gridLayout_4")
self.label = QtWidgets.QLabel(self.groupBox_3)
self.label.setObjectName("label")
self.gridLayout_4.addWidget(self.label, 0, 0, 1, 1)
self.lineEdit_length = QtWidgets.QLineEdit(self.groupBox_3)
self.lineEdit_length.setObjectName("lineEdit_length")
self.gridLayout_4.addWidget(self.lineEdit_length, 0, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(self.groupBox_3)
self.label_4.setObjectName("label_4")
self.gridLayout_4.addWidget(self.label_4, 0, 2, 1, 1)
self.label_2 = QtWidgets.QLabel(self.groupBox_3)
self.label_2.setObjectName("label_2")
self.gridLayout_4.addWidget(self.label_2, 1, 0, 1, 1)
self.lineEdit_width = QtWidgets.QLineEdit(self.groupBox_3)
self.lineEdit_width.setObjectName("lineEdit_width")
self.gridLayout_4.addWidget(self.lineEdit_width, 1, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(self.groupBox_3)
self.label_5.setObjectName("label_5")
self.gridLayout_4.addWidget(self.label_5, 1, 2, 1, 1)
self.label_3 = QtWidgets.QLabel(self.groupBox_3)
self.label_3.setObjectName("label_3")
self.gridLayout_4.addWidget(self.label_3, 2, 0, 1, 1)
self.lineEdit_height = QtWidgets.QLineEdit(self.groupBox_3)
self.lineEdit_height.setObjectName("lineEdit_height")
self.gridLayout_4.addWidget(self.lineEdit_height, 2, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(self.groupBox_3)
self.label_6.setObjectName("label_6")
self.gridLayout_4.addWidget(self.label_6, 2, 2, 1, 1)
self.gridLayout_3.addWidget(self.groupBox_3, 0, 0, 1, 2)
self.groupBox_4 = QtWidgets.QGroupBox(self.groupBox)
self.groupBox_4.setMinimumSize(QtCore.QSize(0, 100))
self.groupBox_4.setMaximumSize(QtCore.QSize(16777215, 100))
self.groupBox_4.setObjectName("groupBox_4")
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_4)
self.gridLayout_6.setObjectName("gridLayout_6")
self.label_9 = QtWidgets.QLabel(self.groupBox_4)
self.label_9.setObjectName("label_9")
self.gridLayout_6.addWidget(self.label_9, 0, 0, 1, 1)
self.lineEdit_hotTemperature = QtWidgets.QLineEdit(self.groupBox_4)
self.lineEdit_hotTemperature.setObjectName("lineEdit_hotTemperature")
self.gridLayout_6.addWidget(self.lineEdit_hotTemperature, 0, 1, 1, 1)
self.label_11 = QtWidgets.QLabel(self.groupBox_4)
self.label_11.setObjectName("label_11")
self.gridLayout_6.addWidget(self.label_11, 0, 2, 1, 1)
self.label_10 = QtWidgets.QLabel(self.groupBox_4)
self.label_10.setObjectName("label_10")
self.gridLayout_6.addWidget(self.label_10, 1, 0, 1, 1)
self.lineEdit_coldTemperature = QtWidgets.QLineEdit(self.groupBox_4)
self.lineEdit_coldTemperature.setObjectName("lineEdit_coldTemperature")
self.gridLayout_6.addWidget(self.lineEdit_coldTemperature, 1, 1, 1, 1)
self.label_12 = QtWidgets.QLabel(self.groupBox_4)
self.label_12.setObjectName("label_12")
self.gridLayout_6.addWidget(self.label_12, 1, 2, 1, 1)
self.gridLayout_3.addWidget(self.groupBox_4, 3, 0, 1, 2)
self.groupBox_5 = QtWidgets.QGroupBox(self.groupBox)
self.groupBox_5.setMinimumSize(QtCore.QSize(0, 60))
self.groupBox_5.setMaximumSize(QtCore.QSize(16777215, 60))
self.groupBox_5.setObjectName("groupBox_5")
self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_5)
self.gridLayout_5.setObjectName("gridLayout_5")
self.label_7 = QtWidgets.QLabel(self.groupBox_5)
self.label_7.setObjectName("label_7")
self.gridLayout_5.addWidget(self.label_7, 0, 0, 1, 1)
self.horizontalSlider = QtWidgets.QSlider(self.groupBox_5)
self.horizontalSlider.setMinimum(1)
self.horizontalSlider.setMaximum(10)
self.horizontalSlider.setProperty("value", 5)
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSlider.setObjectName("horizontalSlider")
self.gridLayout_5.addWidget(self.horizontalSlider, 0, 1, 1, 1)
self.label_meshlevel = QtWidgets.QLabel(self.groupBox_5)
font = QtGui.QFont()
font.setPointSize(12)
self.label_meshlevel.setFont(font)
self.label_meshlevel.setObjectName("label_meshlevel")
self.gridLayout_5.addWidget(self.label_meshlevel, 0, 2, 1, 1)
self.gridLayout_3.addWidget(self.groupBox_5, 1, 0, 1, 2)
self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 2)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "pyMAPDL测试"))
self.pushButton_geom.setText(_translate("Form", "显示几何"))
self.pushButton_Temperature.setText(_translate("Form", "查看温度"))
self.pushButton_mesh.setText(_translate("Form", "显示网格"))
self.pushButton_calc.setText(_translate("Form", "开始计算"))
self.groupBox_2.setTitle(_translate("Form", "过程输出"))
self.groupBox.setTitle(_translate("Form", "计算参数"))
self.groupBox_3.setTitle(_translate("Form", "几何参数"))
self.label.setText(_translate("Form", "长度:"))
self.lineEdit_length.setText(_translate("Form", "1.8"))
self.label_4.setText(_translate("Form", "m"))
self.label_2.setText(_translate("Form", "宽度:"))
self.lineEdit_width.setText(_translate("Form", "0.6"))
self.label_5.setText(_translate("Form", "m"))
self.label_3.setText(_translate("Form", "高度:"))
self.lineEdit_height.setText(_translate("Form", "0.02"))
self.label_6.setText(_translate("Form", "m"))
self.groupBox_4.setTitle(_translate("Form", "载荷参数"))
self.label_9.setText(_translate("Form", "高温面温度:"))
self.lineEdit_hotTemperature.setText(_translate("Form", "50"))
self.label_11.setText(_translate("Form", "K"))
self.label_10.setText(_translate("Form", "低温面温度:"))
self.lineEdit_coldTemperature.setInputMask(_translate("Form", "100"))
self.lineEdit_coldTemperature.setText(_translate("Form", "10"))
self.label_12.setText(_translate("Form", "K"))
self.groupBox_5.setTitle(_translate("Form", "网格参数"))
self.label_7.setText(_translate("Form", "网格级别:"))
self.label_meshlevel.setText(_translate("Form", "5"))
from pyvistaqt import QtInteractor
程序启动后自动连接ANSYS APDL。
点击按钮开始计算
后进行计算,图形窗口中显示几何模型。
点击显示几何
按钮可以打开vtk窗口看到几何模型。
点击显示网格
按钮可以查看网格。
点击查看温度
按钮可以观察温度分布。
关闭软件会自动断开与ansys的连接。
目前采用vtk文件进行中转,才能将计算结果显示在程序中,实现过程极不优雅,而且性能也不好。
先把功能实现了,后面慢慢再改。pyansys真心不太好玩儿~
(完毕)