2
目录
1. 前言 ...........................................................................................................3
2. 简介 ...........................................................................................................3
3. Fluent-Scheme接口..................................................................................3
3.1 在 Fluent中调用 scheme命令 ......................................................3
3.2 在 Scheme中调用 Fluent命令 ......................................................3
3.3 RP-变量 ............................................................................................4
3.4 CX-变量 ............................................................................................4
4. Fluent-Scheme-UDFs 接口 .......................................................................4
4.1 数据交换 .........................................................................................4
4.2 函数的调用 .....................................................................................5
5. 数学函数 ...................................................................................................5
6. 全局 Scheme变量 ....................................................................................6
7. 局部 Scheme变量 ....................................................................................7
8. 串列(list) ....................................................................................................7
9. If 命令 ......................................................................................................8
10. Do循环 .....................................................................................................9
11. Format 命令 ...........................................................................................11
12. for-each 循环 .........................................................................................11
13. 在 TUI中的 Alias方法 ............................................................................12
14. 实例:建立动画 .....................................................................................13
15. 实例:从数据文件生成报告 .................................................................14
16. 实例:从 Data或者 Case文件你读取数据 ..........................................17
17. 实例:输出 Fluent Zone的名称到 UDF ................................................18
18. 迭代控制 .................................................................................................20
19. Fluent Scheme的特色 ............................................................................21
19.1 Eval 命令和环境 .........................................................................21
19.2 Listen 命令 ..................................................................................21
19.3 Format 命令 ................................................................................22
19.4 System 命令 ................................................................................22
19.5 Fluent 变量和函数......................................................................22
20. Scheme 文献 ..........................................................................................22
21. Fluent Scheme的标准函数 ....................................................................22
22. Fluent-Scheme 环境...............................................................................26
3
1. 前言
在 Fluent 中使用 Scheme 可以非常轻松的自动执行仿真流程。非常遗憾的是,到目前
为止都没有正式的支持文档。在 Fluent中使用 Scheme必须对标准的 Scheme语言有足够的
了解。这个文档非常简单,但是仍然不失为一个好的参考资料,Fluent 德国都是直接向用
户推荐这个手册,因为他们自己本身也没有官方的手册。实际上,Fluent 的后续版本将不
会再使用 Scheme作为开发语言,转而使用 Python这个灵活度更高的语言。
2. 简介
Scheme 是 Lisp的一个分支,有着非常统一而又简单的命令格式:
(commandname argument1 argument2 ...)
每一个命令调用都是一个函数调用,因此也就会输出一个结果。命令名和变量名不区分大
小写,但是只能以字母开头,可以包含除了 a-z 和 0-9 之外的特殊符号,包括+-
*/<>=?.:%$!~^_等字符。
注释使用;;开头,行结束就表示注释结束。
3. Fluent-Scheme接口
3.1 在 Fluent中调用 scheme命令
l 使用 Fluent的命令行界面输入(也可以使用鼠标拷贝命令)或者
l 在文本编辑器中编好 Scheme 程序,然后用.scm 结尾的文件储存,再通过 Fluent 的菜
单“File/Read/Scheme”调用
l 如果在用户文件夹中存在一个.fluent文件,这个文件会随着 Fluent的启动而运行
l 在菜单”Solve/Monitor/Commands/Command“输入 Scheme 命令,可以在每次迭代或
者时长运行。
3.2 在 Scheme中调用 Fluent命令
l 文字界面输入命令:
(ti-menu-load-string "display/contour temperature 30 100")
返回值: #t 代表执行成功,#f 代表失败或者是使用 Ctrl-C 取消的;Ctrl-C 终止 Fluent 命令,
但不终止 Scheme程序的执行。
l GUI命令:Journal文件中可以直接使用 Scheme命令,执行图形化操作。比如:
(cx-gui-do cx-activate-item "Velocity Vectors*PanelButtons*PushButton1(OK)")
文字命令执行速度更快,更紧凑,而且在很多方面可以使用。GUI 命令比较慢,不方便查
看和编写(查找 Fluent 命令比较麻烦)。因此应该优先使用文字界面命令,只有当没有文字
4
命令可以使用的时候才使用 GUI命令。
文字界面命令还不能注释,操作步骤:搜索想要运行的命令,尝试运行,然后组织命令行。
在 Fluent文字界面的输出样式:
(display object)
(newline)
3.3 RP-变量
获得变量值:比如获得模拟时间:
> (rpgetvar 'flow-time)
0.1
设置变量值:
> (rpsetvar 'flow-time 0)
所有 RP变量都是在 Case中定义(参考"变量"一章).
3.4 CX-变量
读取变量,比如说颜色历程表,
> (cxgetvar ‘cmap-list)
0.1
设置变量:
> (cxsetvar 'def-cmap "rgb")
所有的 CX变量都是在 Case文件中定义的(参考”Cortex变量”)
4. Fluent-Scheme-UDFs 接口
4.1 数据交换
可以定义自己的 RP 变量,通过 Fluent 的文字界面或者在 UDF 中通过特殊的函数进行调用。
定义一个自己的 RP变量::
(rp-var-define name default-and-init-value type #f)
类型: 'int 'real 'boolean 'string ...?
比如:
> (rp-var-define 'udf/var1 0 'real #f)
5
变量信息:
> (rp-var-object 'udf/var1)
(udf/var1 0 real #f 0)
> (rp-var-object 'udf/var2)
#f
变量的改变和查询可以像上面一样通过 rpsetvar和 rpgetvar来完成。
如果一个变量已经被定义一次,则在 Fluent 程序结束之前它都是有效的,储存在每个 Case
文件里面。重新载入这样的一个 Case文件的时候,如果此变量没有被定义,则它会被自动
创建,并且储存在 Case文件里面的变量值会被指定给这个变量。
在 UDF 里面,RP 变量可以通过如下的 C 函数(在 Fluent.Inc/fluentX.Y/src/var.h 中被声明)
赋值和查询
real RP_Get_Real(char *s);
long RP_Get_Integer(char *s);
char *RP_Get_String(char *s);
boolean RP_Get_Boolean(char *s);
void RP_Set_Real(char *s, real v);
void RP_Set_Integer(char *s, long v);
void RP_Set_Boolean(char *s, boolean v);
void RP_Set_String(char *s, char *v);
void RP_Set_Symbol(char *s, char *v);
例如:
var1 = RP_Get_Real("udf/var1");
RP_Set_Real("udf/var1", 3.2);
如果 UDF 是在并行模式中被使用,RP 变量的操作需要特别注意,详情请查阅 Fluent 的
UDF手册。
4.2 函数的调用
EOD类型的 UDF可以使用 Scheme的如下命令调用:
(%udf-on-demand "udf-eod-name")
目前还没有可能在在 UDF 中调用 Scheme 函数;虽然 Fluent.Inc/fluentX.Y/cortex/src/cx.h 中
声明的 C 函数 CX_Interpret_String("scheme-command-string")可以解释"scheme-command-
string",但是没有途径可以进入此环境。
5. 数学函数
基本运算 + - * /, 可以有 2个以上的参数:
6
> (+ 2 4 5)
11
> (/ 6 3)
2
> (/ 2) ;; 等同于 (/ 1 2)
0.5
其它函数: (abs x), (sqrt x), (expt x y) [= xy], (exp x)[= ex], (log x) [= ln x], (sin x), (cos x),
(atan x), (atan x y) [= arctan(x/y)], ⋯
取整函数:
> (remainder 45 6)
3
> (modulo 5 2)
1
(truncate x), (round x), (ceiling x), (floor x), ...
其它
(max x y ...), (min x y ...)
比如,寻找串列中的最大值:
> (apply max '(1 5 8 3 4))
8
6. 全局 Scheme变量
用如下方法定义:
> (define x 3)
> (+ x 1)
4
没有变量类型区别 (Integer, Real, String, ...) – 每个变量都可以接受任何一种类型的值.
使用再定义方法改变变量值(不能在函数内部操作,函数内部是局部变量区域,所以定义的
将会是一个新的局部变量),更好的方式是使用如下的句子:
(set! x 1)
输出显示变量值
(display x)
或者
7
(write x)
Write 仅当 Fluent 变量值都储存在文件里面而又想读出来的时候才使用;Write 使用前置符
号显示符号变量值。
常量: 整数 (2), 浮点数 (2.5), 布尔值 (#t 真, #f 假) 字符串 ("this is a text string") 和符号
( 'symbol),比如:
(define x 'this-is-a-symbol)
字符串中的特殊符号使用:
\" "
\n 新行
全局变量和自定义 Scheme函数的有效性保持到 Fluent结束运行。
7. 局部 Scheme变量
(let ((var1 value1) (var2 value2) ...)
... 命令...
)
8. 串列(list)
定义方法,例如::
> (define my-surfaces '(wall-top wall-bottom symmetry))
任意长度,支持动态管理和嵌套
使用如下格式进行定义: ‘(elements ...) :
> (define l '(a b c))
串列的第一个元素
> (car l)
a
串列剩下的部分 (没有第一个元素的串列)
> (cdr l)
(b c)
串列长度(元素个数)
> (length l)
3
8
串列的第 i个元素
(listref liste i)
在串列中搜索元素:
> (member 'd '(a b c d e f g))
(d e f g)
对串列应用函数:
> (map (lambda (x) (* x x)) '(1 2 3))
(1 4 9)
> (apply + '(2 4 5))
11
> (apply max '(1 5 8 3 4))
8
9. If 命令
If 命令是一个函数:
(if cond true-value false-value)
Cond 是一个逻辑表达式,#t (true) 或者 #f (false).
比较操作:
等式:
(= a b) ;; 数字
(eq? a b) ;; 对象
(eqv? a b) ;; 对象比较值
关系:
(positive? x)
(negative? x)
(< a b)
(> a b)
(<= a b)
(>= a b)
逻辑函数:
(not a)
(and a b c ...)
(or a b c ...)
if和 else分支可以实用块命令 begin进行很多扩展
(if cond
(begin ;; if
9
...
true-value
)
(begin ;; else
...
false-value
)
)
如果 if命令的返回值不需要保存,else分支和它的返回值都可以省略。
用于条件流程控制的复合命令(例如分段函数)
(cond (test1 value1) (test2 value2) ... (else value))
一个变量的离散值
(case x ((x11 x12 x13 ...) value1) ((x21 x22 x23 ...) value2) ... (else value))
如果 X可以在串列中找到(例如在 (x11 x12 x13 ...)),则对应的值赋给(value1)。
10. Do循环
最简单的形式(变量,开始值,指定步长,结束条件)
(do ((x x-start (+ x delta-x))) ((> x x-end)) ...loop-body... )
例子:创建 ISO面,等间距创建多个 ISO面并自动命名。首先必须在 TUI(Text User Interface)
中形成一个用于创建 ISO面的脚本集。
>
adapt/ grid/ surface/
display/ plot/ view/
define/ report/ exit
file/ solve/
> surface
/surface>
delete-surface mouse-line point-array
surface-cells mouse-plane rake-surface
iso-surface mouse-rake rename-surface
iso-clip partition-surface sphere-slice
list-surfaces plane-slice zone-surface
/surface> iso-surface
iso-surface of>
pressure entropy x-surface-area
pressure-coefficient total-energy y-surface-area
dynamic-pressure internal-energy z-surface-area
10
...
rel-total-temperature x-coordinate dp-dx
wall-temp-out-surf y-coordinate dp-dy
wall-temp-in-surf z-coordinate dp-dz
iso-surface of> x-coordinate
new surface id/name [x-coordinate-31] testname
range [-10.0131, 4.8575001]
from surface [()] ()
()
iso-value(1) (m) [()] 1.234
iso-value(2) (m) [()] ()
所有命令写成一行(用逗号取代回车)如下:
surface/iso-surface x-coordinate testname () 1.234 ()
进行参数循环:
(do ((x 0 (+ x 0.2)) ) ((> x 3.1))
(ti-menu-load-string
(format #f "surface/iso-surface x-coordinate x-~3.1f () ~a ()" x x))
)
生成如下的命令行
surface/iso-surface x-coordinate x-0.0 () 0 ()
surface/iso-surface x-coordinate x-0.2 () 0.2 ()
surface/iso-surface x-coordinate x-0.4 () 0.4 ()
...
surface/iso-surface x-coordinate x-3.0 () 3 ()
细化:对正负坐标进行更好的命名
(do ((z -1 (+ z 0.25))) ((> z 1))
(ti-menu-load-string
(format #f "surface/iso-surface z-coordinate z~a~05.3f () ~a ()"
(if (>= z 0) "+" "") z z))
)
surface/iso-surface z-coordinate z-1.000 () -1 ()
surface/iso-surface z-coordinate z-0.750 () -0.75 ()
surface/iso-surface z-coordinate z-0.500 () -0.5 ()
surface/iso-surface z-coordinate z-0.250 () -0.25 ()
surface/iso-surface z-coordinate z+0.000 () 0 ()
surface/iso-surface z-coordinate z+0.250 () 0.25 ()
surface/iso-surface z-coordinate z+0.500 () 0.5 ()
surface/iso-surface z-coordinate z+0.750 () 0.75 ()
surface/iso-surface z-coordinate z+1.000 () 1 ()
变化:两个循环变量
11
(do ((x 0 (+ x 0.2)) (i 1 (+ i 1))) ((> x 3.1))
(ti-menu-load-string
(format #f "surface/iso-surface x-coordinate x-~02d () ~a ()" i x))
)
surface/iso-surface x-coordinate x-01 () 0 ()
surface/iso-surface x-coordinate x-02 () 0.2 ()
surface/iso-surface x-coordinate x-03 () 0.4 ()
...
surface/iso-surface x-coordinate x-16 () 3 ()
11. Format 命令
(format #f "像 C语言一样的格式化字符串" var1 var2 ... )
和 C不一样的是,不使用%符号开头,而是使用~符号开头;比如说:
~a
~d
通用形式的任意变量(字符串没有““)
整数
~04d 整数,占 4个位置,不足的以 0在前面填充。如输出为 0005, 对于文件名命名很
重要。
~f 浮点小数
~4.2f 浮点数,总共占 4个位置,2位小数。如 1.2 wird zu 1.20
~s
带双引号的字符串。如(format #f "string: ~s !" "text") 输出字符串 "text" !
...
特殊符号:
\n 回车符
\" "
format 命令和它的模式不是标准的 Scheme语法,是依赖于 Fluent的 Scheme解释器。
12. for-each 循环
针对一个 List的一个或者多个元素都运行一个自定义的函数:
(for-each function list1 list2 ...)
函数的参数个数必须和 List的个数对应。设置多个墙区的边界条件时,需要设置 Zonename
或者 ZoneID、文件名字(不含大写字母)、温度以及墙的速度等等。
12
(define velocity 0.1)
(for-each
(lambda (zone)
(ti-menu-load-string
(format #f "def/bc/wall ~a 0 0 yes giesspulver yes temperature no 1800 yes no no ~a
0 -1
0 no 0 0.5" zone velocity)
)
(newline) (display " ")
)
'(
kok_li kok_re
kok_innen kok_aussen
bieg_li bieg_re
bieg_aussen bieg_innen
kreis_li kreis_re
kreis_aussen kreis_innen
)
)
Lambda命令用来定义局部函数
(lambda (arg1 arg2 ...) ... Funktionswert)
13. 在 TUI中的 Alias方法
在 TUI中创建缩写命令:
(alias 'name scheme-function)
例如:
(alias 'time (lambda () (display (rpgetvar 'flow-time))))
在命令行界面中调用:
> time
0.1
参数不能在 Scheme 函数中直接给出(总是空参数,Lambda()),而是必须通过在命令行中使
用如下函数进行读取:
(read-real prompt default)
(read-integer prompt default)
(ti-read-unquoted-string prompt default)
(yes-or-no? prompt default)
prompt 是一个字符串,default代表缺省值, 代表如果用户只是按回车的时候的返回值。
13
如果你在.fluent-file中定义了各种缩写替代命令,那么就可以直接使用。
14. 实例:建立动画
从一个静态计算的数据文件中提取的图片组成一个动画。数据文件名称采用数字进行编号,
开头、结尾是固定的,中间部分逐步增长。 运行 Fluent 命令的时候碰到的错误,或者按
下 Ctrl-C可以终止此 Scheme程序。
(define datfilename "test-") ;; -> test-0010.dat, test-020.dat, ...
(define first-index 10)
(define last-index 110)
(define delta 10)
(define imagefilename "image-") ;; -> image-01.bmp, ...
(define (time) (rpgetvar 'flow-time))
(define t0 0)
;;------------------------------------------------------------------------
;; funktion, die die einzelbilder fuer den film erstellt
;;------------------------------------------------------------------------
(define (pp)
(let
(
(break #f)
)
(ti-menu-load-string "display/set/hardcopy/driver/tiff") ;; TIFF-Format einstellen
(ti-menu-load-string "display/set/hardcopy/color-mode/color") ;; Default ist "grey"
(do ((j first-index (+ j delta)) ;; datfile startwert und delta
(i 1 (+ i 1))) ;; imagefile startwert und delta
((or (> j last-index) break)) ;; datfile endwert
(set! break (not (and
(ti-menu-load-string
(format #f "file/read-data ~a~04d.dat" datfilename j))
(begin (if (= i 1) (set! t0 (time))) #t)
(disp)
(system "rm temp.tif") ;; hardcopy funktioniert nicht wenn file schon existiert
(ti-menu-load-string "display/hardcopy temp.tif")
(system
(format #f "convert temp.tif ~a~02d.bmp &" imagefilename i))
;; convert-Befehl von www.imagemagick.com
)))
)
(if break (begin (newline)(newline)(display "scheme interrupted!")(newline)))
)
)
示例函数(disp):简单的云图显示
(define (disp)
(ti-menu-load-string "display/contour/temperature 290 1673")
14
)
示例函数(disp):叠加云图/速度矢量图, 插入时间:
(define (disp)
(and
(ti-menu-load-string
(format #f "display set title \"Time = ~5.1f s\"" (- (time) t0))
(ti-menu-load-string "display/set/overlays no")
(ti-menu-load-string "display/contour temperature 290 1673")
(ti-menu-load-string "display/set/overlays yes")
(ti-menu-load-string "display/velocity-vectors velocity-magnitude 0.0 1.0 5 0")
;; colored by min max scale
skip
)
)
示例函数(disp):生成等值面, VOF计算产生的相边界使用 y坐标(高度)进行颜色标注:
(define (disp)
(and
(ti-menu-load-string "display/surface/iso-surface vof-steel interface-1 , 0.5 ,")
(ti-menu-load-string "display/set/contours/surfaces interface-1 ()")
(ti-menu-load-string "display/contour y-coordinate 2.755 2.780")
(ti-menu-load-string "display/surface/delete interface-1")
)
)
调用 disp函数测试:
> (disp)
调用函数创建图片
> (pp)
15. 实例:从数据文件生成报告
必须通过一个 transcript文件来产生数据报告:
(ti-menu-load-string "file/start-transcript temp.trn")
(ti-menu-load-string "report/cell-average fluid , temperature")
(ti-menu-load-string "file/stop-transcript")
对此 Scheme有一个函数可以起到同样的作用:
(with-output-to-file "temp.trn"
(lambda ()
(ti-menu-load-string "report/cell-average fluid , temperature")))
这里运行成功不会在屏幕输出任何东西。
Transcript文件 "temp.trn":
report/cell-average fluid , temperature
volume-average of temperature on cell zones (fluid)
Volume-weighted average = 300
file/stop-transcript
在 Scheme 中 Transcript 文件作为一个 List 的对象读入,搜索“=“后面的
内容
财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容
,输出跟在
等号后面的元素的对应值:
(let
15
(
(data
(let ((p (open-input-file "temp.trn")))
(let f ((x (read p)))
(if (eof-object? x)
(begin
(close-input-port p)
'())
(cons x (f (read p)))
)
)
)
)
(value 0)
)
(ti-menu-load-string "! rm temp.trn") (newline)
(do ((i 0 (+ i 1)) ) ((>= i (length data)))
(if (eq? (list-ref data i) '=)
(set! value (list-ref data (+ i 1)))
)
)
value
)
缩写 do循环(没有变量需要取值)的方法:
(cadr (member '= data))
嵌套 car-cdr:
(cadr x) = (car (cdr x))
输出基于热流平衡(在 TUI中为所有面建立)的特定表面的热流值:
输出的格式:
...
zone 15 (stahl-bodenplatte): 11.2
zone 5 (stahl-kokille): 53.5
zone 6 (schlacke-aussen): 32.4
zone 14 (haube-schlacke): 26.9
...
Scheme程序:
(let
(
(p (open-output-file "fluxes.txt")) ;; Ausgabe-Textdatei öffnen
(n 0)
(surfaces '(
stahl-bodenplatte
stahl-kokille
stahl-schlacke
haube-schlacke
elektrode-schlacke
16
schlacke-innen
schlacke-aussen
aufsatz-schlacke
haube-kuehlung
))
)
(for-each
(lambda (filename)
(if (zero? (modulo n 2)) ;; nur jedes zweite Datenfile nehmen
(begin
(ti-menu-load-string
(format #f "file read-data ~a" filename))
(ti-menu-load-string "file/start-transcript temp.trn")
(ti-menu-load-string "report/heat-transfer")
(ti-menu-load-string "file/stop-transcript")
(define data ;; transcriptfile in "data" laden
(let ((p (open-input-file "temp.trn")))
(let f ((x (read p)))
(if (eof-object? x)
(begin
(close-input-port p)
'())
(cons x (f (read p)))
)
)
)
)
(ti-menu-load-string "! rm temp.trn")
(display (time) p)
(display " " p)
(for-each
(lambda (zone)
(begin
(display (list-ref (member (list zone) data) 2) p)
;; fluxwert von zone ermitteln
(display " " p)
)
)
surfaces
)
(newline p)
)
)
(set! n (+ n 1))
)
'(
best-0060.dat best-0120.dat best-0132.dat best-0144.dat best-0156.dat
best-0168.dat best-0180.dat best-0192.dat best-0204.dat best-0216.dat
best-0228.dat best-0240.dat best-0252.dat best-0264.dat best-0276.dat
best-0288.dat best-0300.dat best-0312.dat best-0324.dat best-0336.dat
17
)
)
(close-output-port p)
)
数据文件 list可以在 Unix使用 ls –x *.dat 命令建立
16. 实例:从 Data或者 Case文件你读取数据
Fluent文件的格式就是嵌套的 Scheme List,比如说:
(0 "fluent5.3.18")
(0 "Machine Config:")
(4 (23 1 0 1 2 4 4 4 8 4 4))
(0 "Grid size:")
(33 (10540 21489 10947))
(0 "Variables:")
(37 (
(flow-time 3.7)
(time-step 0.1)
(periodic/pressure-derivative 0)
(number-of-samples 0)
(dpm/summary ())))
(0 "Data:")
(2300 (1 1 1 0 0 1 430)
...
因此可以非常简单的作为 Scheme 对象读入。 比如说,从数据文件里面读取时间,然后使
用 hh:mm:ss 的时间格式重命名数据文件。
(let ((p (open-input-file filename)) (found #f) (t -1))
(do ((x (read p) (read p))) ((or found (eof-object? x)) (close-input-port p) )
(if (eqv