吾生有涯 学海无涯
析模有界 知识无界

Fluent二次开发三板斧:进程调用

除了使用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之道

赞(1) 打赏
版权声明:未经允许,请勿随意用于商业用途。
文章名称:《Fluent二次开发三板斧:进程调用》
文章链接:https://www.topcfd.cn/13991/
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
分享到

说两句 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者吧

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册