有人留言说UDF专题好多内容是翻译自帮助文档,事实的确是这样的。UDF本没有太多需要介绍的内容,各位学习UDF的朋友们要养成查UDF文档的好习惯,没事儿多看看C语言,多动手练习。编程技能还是要靠不断地练习和总结,程序代码也要靠不断地修改和优化。
从本期开始,UDF专题进入攻坚阶段。本期介绍UDF中的通用宏。
Fluent UDF提供了一些通用宏,用于控制Fluent在使用过程中的一些行为,一些比较常用的通用宏包括:
-
DEFINE_ADJUST:用于操纵变量
-
DEFINE_DELTAT:用于调整时间步长
-
DEFINE_EXECUTE_AT_END:在迭代完成后执行操作
-
DEFINE_EXECUTE_AT_EXIT:在Fluent关闭时执行操作
-
DEFINE_EXECUTE_FROM_GUI:实现在用户自定义界面中执行操作
-
DEFINE_EXECUTE_ON_LOADING:加载UDF时执行一些操作
-
DEFINE_EXECUTE_AFTER_CASE/DATA:读取Case文件后执行操作
-
DEFINE_INIT:初始化
-
DEFINE_ON_DEMAND:异步执行一些操作
-
DEFINE_REPORT_DEFINITION_FN:为用户定义的报告返回值
-
DEFINE_RW_FILE:读写文件
-
DEFINE_RW_HDF_FILE:读写HDF文件
可以利用DEFINE_ADJUST宏调整或控制一些不作为调用参数的变量。例如用户可以使用DEFINE_ADJUST修改流动参数(如速度、压力等),也可以计算某些标量在全域的积分量,甚至可以基于计算结果调整边界条件。DEFINE_ADJUST宏在每一个迭代步被执行,并且在每一个迭代中传输方程求解之前被调用。
-
宏形式:DEFINE_ADJUST(name , d)
-
宏参数:symbol name, Domain *d
-
返回值:无返回值
-
调用形式:解释或编译
下面是一个简单的案例,其利用DEFINE_ADJUST宏在每一步迭代过程中计算区域内的湍流耗散率,计算结果显示在console中。
#include "udf.h"
DEFINE_ADJUST(my_adjust,d) { Thread *t; /* Integrate dissipation. */ real sum_diss=0.; cell_t c; thread_loop_c(t,d) { begin_c_loop(c,t) { sum_diss += C_D(c,t)* C_VOLUME(c,t); } end_c_loop(c,t) }
printf("总耗散率: %gn", sum_diss); }
DEFINE_ADJUST宏编译或解释后,可以通过User Defined标签页下的Function Hooks…工具按钮来加载。如下图所示。
选择此工具按钮后弹出UDF加载对话框,如下图所示。
选择Adjust后的Edit…按钮,弹出Adjust Functions对话框,如下图所示,选择列表框中的宏,选择Add按钮将其从左侧列表框中加载至右侧列表框,点击OK按钮确认操作并关闭对话框。
这样,DEFINE_ADJUST宏就被被挂载到Fluent中,在每一次迭代时都会调用。
DEFINE_DELTAT宏主要用于在瞬态求解过程中控制时间步长。需要注意的是:此宏只能用于Time Stepping Method为Adaptive时。若为默认的Fixed,则会出错。如下图所示。
-
宏形式:DEFINE_DELTAT(name , d)
-
宏参数:symbol name, Domain *d
-
返回值:real
-
调用形式:解释或编译
如下例程为调整时间步长,当计算时间小于0.5s时,采用时间步长0.1s,其他时刻时间步长采用0.2。
#include "udf.h"
DEFINE_DELTAT(mydeltat,d) { real time_step; real flow_time = CURRENT_TIME;
if (flow_time < 0.5) time_step = 0.1;
else time_step = 0.2;
return time_step; }
解释或编译UDF后,此宏的加载方式为:
-
选择Run Calculation树形节点后,选择Time Stepping Method为Adaptive。
-
点选按钮Settings…,如下图所示。
-
在弹出的设置对话框中,设置User-Defined Time Step为所编译的UDF,如下图所示。点击OK按钮挂载宏。
此宏由用户手动调用执行,而非Fluent自动调用。
-
宏形式:DEFINE_ON_DEMAND(name )
-
宏参数:symbol name
-
返回值:没有任何返回值
-
调用形式:解释或编译
此宏的参数中并无任何Fluent传入的数据,因此如果是获取计算域中的数据,则需要利用Get_Domain先获取对应区域的Domain结构。
例如下面的实例计算了一个温度函数:
并将值赋给UDM。
#include "udf.h"
DEFINE_ON_DEMAND(on_demand_calc) { Domain *d; real tavg = 0.; real tmax = 0.; real tmin = 0.; real temp,volume,vol_tot; Thread *t; cell_t c; d = Get_Domain(1); thread_loop_c(t,d) { begin_c_loop(c,t) { volume = C_VOLUME(c,t); temp = C_T(c,t);
if (temp < tmin || tmin == 0.)
tmin = temp;
if (temp > tmax || tmax == 0.)
tmax = temp; vol_tot += volume; tavg += temp*volume; } end_c_loop(c,t) tavg /= vol_tot; begin_c_loop(c,t) { temp = C_T(c,t); C_UDMI(c,t,0) = (temp-tmin)/(tmax-tmin); } end_c_loop(c,t) } }
此宏编译或解释后,可通过User Defined标签页下按钮Execute on Demand…加载,如下图所示。
加载UDF后如下图所示。
利用DEFINE_RW_FILE宏可以向case或data文件写入信息,或者从case和data文件中读取信息。
-
宏形式:DEFINE_RW_FILE(name,fp )
-
宏参数:symbol name, FILE fp
-
返回值:没有任何返回值
-
调用形式:解释或编译
在宏中可以利用fscanf函数读取文件中的信息,也可以利用fprintf函数向文件写入信息。如下例程可以向data文件中写入DEFINE_ADJUST宏调用的次数,同时从data文件中读取调用的次数。
#include "udf.h"
int kount = 0;
/* define global variable kount */
DEFINE_ADJUST(demo_calc,d) { kount++;
printf("kount = %dn",kount); } DEFINE_RW_FILE(writer,fp) {
printf("Writing UDF data to data file...n");
fprintf(fp,"%d",kount);
/* write out kount to data file */
} DEFINE_RW_FILE(reader,fp) {
printf("Reading UDF data from data file...n");
fscanf(fp,"%d",&kount);
/* read kount from data file */
}
此宏的加载与DEFINE_ADJUST宏相同,也在User-Defined Function Hooks对话框中。
下期结合案例具体讲这四个宏的用法。
本篇文章来源于微信公众号: CFD之道
评论前必须登录!
注册