除了使用ACT及Scheme进行Fluent二次开发外,用户还可以使用进程调用的方式进行开发。本文用简单示例描述此种开发过程。用户可以使用自己熟悉的GUI开发工具创建界面,之后调用Fluent在后台运行并输出计算结果。
这里有两个问题需要解决:
-
进程调用。一般主流的程序设计语言都带有进程调用功能,可以调用外部程序。这里需要将Fluent当做外部程序进行调用。 -
运行脚本。可以作为Fluent的调用参数的脚本包括jou脚本文件、transcript脚本文件以及scm程序代码。
1 进程调用
常见的编程语言通常都能够调用外部程序。如C中ShellExecute函数,c#中的System.Diagnostics.Process.Start函数,python中os.system等均可用于外部程序调用,因此这些语言都可以用来做Fluent二次开发。
下面简单描述Python中进程调用的几种方式。
1.1 os.system()
该方法脱胎于c语言的system函数。调用方式很简单,如下面的代码可以启动Fluent:
import os
os.system(r'C:"Program filesANSYS Inc"v201fluentntbinwin64fluent.exe')
“
注:这里因为本机ANSYS安装到了有空格的路径下,所有需要使用双引号引起来,否则访问不到。若不想受空格困扰,可以将Fluent路径添加到环境变量path中。
os.system函数无法获取调用后的返回结果,因此也无法判断程序什么时候运行结束。利用此方式启动外部程序时,主进程会被阻塞,直至子进程调用完毕。
1.2 os.popen()
popen方式与system方式类似,不过此方法可以返回程序运行结果。
简单的调用形式如下:
import os
out = os.popen(r'C:"Program filesANSYS Inc"v201fluentntbinwin64fluent.exe 2d -t2')
print(out.read())
上面的代码指定以2d,2个CPU并行方式启动Fluent。
popen执行不会造成主进程阻塞。
1.3 subprocess.Popen()
利用subprocess模块中的Popen函数可以调用外部程序。该函数参数较多,不过最简单的方式无异于:
import subprocess
subprocess.Popen(r'C:"Program filesANSYS Inc"v201fluentntbinwin64fluent.exe',shell=True)
以上命令可以启动Fluent。Popen不会造成主进程阻塞。Popen函数的功能众多,这不是本文重点,有兴趣自行查找资料。
1.4 subprocess.call()
call函数与Popen函数并无太大区别。
import subprocess
ps = subprocess.call(r'C:"Program filesANSYS Inc"v201fluentntbinwin64fluent.exe',shell=True)
print(ps)
call会造成主进程阻塞。
1.5 进程调用小结
以上4种方式均可用于外部进程调用。它们的区别在于:
-
os.system()用于简单执行命令,可以显示执行结果。
-
os.popen()用于简单执行命令,不能显示执行结果,可以通过变量返回执行结果。
-
subprocess.Popen() 用于执行复杂命令,可以显示执行结果,可以设置输出内容。
-
subprocess.call() 用于执行复杂命令,可以显示执行结果,可以设置输出内容。
对于Fluent二次开发,上面4种方式皆可使用。下面的案例使用os.popen函数作为进程调用工具。
2 Fluent命令启动
采用命令启动Fluent时可以带有参数,这里挑一些在二次开发时可能用得上的参数。更多参数可参阅Fluent Getting Started 4.1.4。
命令参数 | 说明 |
---|---|
-g | 后台执行,无图形界面 |
-i |
执行脚本,可以为jou或trn脚本 |
-t |
指定CPU数量并行执行 |
-meshing | 启动Fluent Meshing,需要在3d或3ddp模式下 |
-tm |
指定运行Meshing的CPU数量 |
模式 | 2d/2ddp/3d/3ddp |
二次开发时,常将Fluent作为后台应用,因此常用的调用方式为:
fluent 3ddp -t4 -g -i jou1.jou
上面的调用方式为:以3d双精度形式,4个CPU,后台运行,执行脚本jou1.jou文件。
3 测试用TUI
后台运行的Fluent无法执行包含有GUI操作的脚本,因此只能使用TUI。需要注意,如果采用录制脚本的方式产生的log文件,其中的脚本大多是依赖于GUI的,如果Fluent启动命令中包含有-g参数,则运行这些依赖GUI的脚本时会报错。纯粹的TUI命令并不需要GUI支持。
如下为一个简单的TUI流程:
;打开网格文件Ex.msh
/file/read-case "EX.msh"
;修改空间形式为轴对称
/define/models/axisymmetric? yes
;设置湍流模型为realizable k-epsilon模型
/define/models/viscous/ke-realizable? yes
;改变默认材料air为water,并修改其密度与粘度值
/define/materials/change-create air water yes,1000,,yes,0.001,,,yes
;设置入口速度为2m/s
/define/boundary-conditions/set/velocity-inlet ,,vmag,2 q
;采用混合初始化
/solve/initialize/hyb-initialization
;指定迭代次数为300次并执行计算
/solve/iterate/300
;保存cas及dat文件
/file/write-case-data EX2.cas
Fluent调用的脚本可以是Scheme脚本文件,其不仅可以包含TUI指令,还能够具有程序设计结构。
4 开发一个简单的测试程序
基本思路:利用PySimpleGUI开发界面,收集界面上用户输入的信息并生成log文件,利用进程调用该log文件产生计算结果。
界面如图所示。
参数准备完毕后点击Done按钮执行计算流程,计算完毕后在msh文件相同路径下生成cas与dat文件,如下图所示。
这里图简单,将Fluent路径(C:Program filesANSYS Incv201fluentntbinwin64fluent.exe)添加到环境变量Path中,这样调用的时候就无需输入很长的路径了。
程序代码:
import PySimpleGUI as sg
import os
layout = [[sg.Text('读取网格:',size=(8,1)),sg.InputText(size=(32,1)),sg.FileBrowse('浏览...',file_types=(("msh files","*.msh"),("cas files","*.cas"),))],
[sg.Text('密度:',size=(8,1)),sg.Input('1000',size=(32,1)),sg.Text('kg/m3')],
[sg.Text('粘度:',size=(8,1)),sg.Input('0.001',size=(32,1)),sg.Text('Pa.s')],
[sg.Text('入口速度:',size=(8,1)),sg.Input('2',size=(32,1)),sg.Text('m/s')],
[sg.Text('迭代次数:',size=(8,1)),sg.Input('300',size=(32,1)),sg.Text('')],
[sg.Text(size=(8,1)),sg.Button('Done',size=(12,1)),sg.Button('Cancel',size=(12,1))]
]
window = sg.Window('Workflow Demo',text_justification='right').Layout(layout)
def createFile(joufile,mshfile,dens=1000,vis=0.001,vel=2,nit=300):
casfile = mshfile.split('.')[0]+'.cas'
f = open(joufile,'w')
f.write('/file/read-case {0}n'.format(mshfile))
f.write('/define/models/axisymmetric? yesn')
f.write('/define/models/viscous/ke-realizable? yesn')
f.write('/define/materials/change-create air water yes,{0},,yes,{1},,,yesn'.format(dens,vis))
f.write('/define/boundary-conditions/set/velocity-inlet ,,vmag,{0} qn'.format(vel))
f.write('/solve/initialize/hyb-initializationn')
f.write('/solve/iterate/{0}n'.format(nit))
f.write('/file/write-case-data {0}n'.format(casfile))
f.close()
def runCalc(joufile):
if(os.path.exists((joufile))):
os.popen('fluent 2ddp -g -i '+ joufile)
else:
sg.popup('log文件不存在',title='错误')
while True:
event,values = window.Read()
if event is None or event=='Cancel':
break;
elif event =='Done':
try:
mshfile = values[0]
dens = eval(values[1])
vis = eval(values[2])
vel = eval(values[3])
nit = eval(values[4])
# 搞到jou文件的路径
joufile = mshfile.split('.')[0]+'.jou'
createFile(joufile,mshfile,dens,vis,vel,nit)
runCalc(joufile)
except:
# 参数输入有误:包括没有选择msh文件或在数字中输入了字符
sg.popup('参数输入有误!请检查输入参数后再继续!',title='出错了')
window.Close()
包含两个阶段:
-
产生jou文件。这可以简单的使用写文件操作得到。几乎所有主流编程语言都包含此功能。 -
运行带参数的fluent。这通过进程调用实现。
目前存在的未解决的问题:
-
脚本执行期间程序没有反馈。阻塞式调用会造成主程序假死,非阻塞式调用则感觉不出来程序到底运行了没有。这个问题可以尝试返回执行结果,但效果貌似不佳。监测文件则开销巨大,得不偿失。 -
命令行执行时的空格问题。现在采用的是添加环境变量,不过也可以利用字符替换添加转义符,麻烦得要死,这个是dos命令行的缺陷
5 总结
采用进程调用的方式进行二次开发,最大的缺陷是必须安装Fluent,不过相比较ACT或Scheme来说,进程调用可以不启动Fluent图形界面(让其在后台执行),对于流程封装来讲是不错的选择。
此种方式可以采用任何支持进程调用的程序语言进行开发(市面上绝大多数编程语言皆可),GUI可以使用自己觉得最方便的方式进行搭建,灵活度要远超ACT和Scheme。不过此种方式严重依赖于TUI,因此对于一些需要UDF支撑的流程则不如ACT或Scheme(TUI可以编译及加载UDF,但不容易调用UDF中的内容)。
Fluent二次开发的方式,各有利弊,自行取舍。
相关文件下载链接:
本篇文章来源于微信公众号: CFD之道
评论前必须登录!
注册