UDF可执行的任务有五种不同的类型: 1. 返回值 2. 修改自变量
3. 返回值和修改自变量
4. 修改FLUENT变量(不能作为自变量传递) 5. 写信息到(或读取信息从)case或data文件
函数能返回值,除非它们在udf.h文件中被定义为void。如果它们不返回值,它们能修改自变量,修改存储在内存中的变量,或与case和data文件一起执行输入输出(I/O)任务。
在Section 3.10.1-3.10.5中,提供了描述上面提到的五种不同的函数任务中每一种的UDF源代码例子。 3.10.1 返回值的函数(Function that Return a Value)
下面的UDF是一个返回值到FLUENT求解器的函数例子。名为cell_viscosity的函数计算了依赖温度的粘度值(mu_lam)并返回这个值到求解器。
/********************************************************************/ /* UDF that returns a value to the solver */ /* Specifies a temperature-dependent viscosity property */
/********************************************************************/#include \DEFINE_PROPERTY(cell_viscosity, cell, thread) {
real mu_lam;
real temp = C_T(cell, thread); if (temp > 288.) mu_lam = 5.5e-3; else if (temp > 286.)
mu_lam = 143.2135 - 0.49725 * temp; else
mu_lam = 1.; return mu_lam; }
cell_viscosity使用了DEFINE_PROPERTY 宏(在Section 4.3.6中描述)来定义。DEFINE_PROPERTY返回一个udf.h中指定的real数据类型。两个real变量传入函数:通过函数计算的层流粘度mu_lam; 和C_T(cell,thread)的值,它是在考虑中的单元的温度值。温度值在它下降范围的基础上被检测,mu_lam的适当值被计算。在函数结尾,mu_lam
6
的计算值被返回。
3.10.2修改自变量的函数(Function that Modify an Argument)
下面的UDF是一个修改一个自变量的函数的例子。名字为user_rate的函数为一个两种气态物质的的简单系统产生一个自定义的体积反应速率。Real指针rr作为自变量传递给函数,指针指向的变量在函数内被修改。 /**************************************************************/ /* UDF that modifies one of its arguments */ /* Specifies a reaction rate in a porous medium */ /**************************************************************/ #include \
#define K1 2.0e-2 #define K2 5.
DEFINE_VR_RATE(user_rate, c, t, r, mole_weight, species_mf, rr, rr_t) {
real s1 = species_mf[0]; real mw1 = mole_weight[0];
if (FLUID_THREAD_P(t) && THREAD_VAR(t).fluid.porous) *rr = K1*s1/pow((1.+K2*s1),2.0)/mw1; else *rr = 0.; }
user_rate使用了DEFINE_VR _RATE宏(见Section 4.3.14)来定义。该函数执行一个当前考虑的单元是否在多孔区域的测试,这个反应速率只应用于多孔区域。real指针变量rr是一个传递给函数的自变量。UDF使用废弃操作符 * 分配反应速率值给废弃指针 *rr。指针rr指向的目标是设置反应速率。通过这个操作,存储在内存中这个指针上的字符的地址被改变了,不再是指针地址本身。(关于废弃指针的详细内容见[3])。
3.10.3返回一个值和修改一个自变量的函数(Functions that Return a Value ans Modify an Argument)
下面的UDF是一个修改它的自变量并返回一个值到FLUENT求解器的函数例子。名字为user_swirl的函数修改ds自变量,指定旋转速度源项并返回它到求解器。
/**************************************************************/ /* UDF that returns a value and modifies an argument */ /* Specifies a swirl-velocity source term */
7
/**************************************************************/ #include \
#define OMEGA 50. /* rotational speed of swirler */
#define WEIGHT 1.e20 /* weighting coefficients in linearized equation */ DEFINE_SOURCE(user_swirl, cell, thread, dS, eqn) {
real w_vel, x[ND_ND], y, source; C_CENTROID(x, cell, thread); y = x[1];
w_vel = y*OMEGA;
/* linear w-velocity at the cell */
source = WEIGHT*(w_vel - C_WSWIRL(cell,thread)); dS[eqn] = -WEIGHT; return source; }
user_swirl使用DEFINE_SOURCE宏来定义(在Section 4.3.8中描述)。DEFINE_SOURCE返回一个在udf.h中指定的数据类型。函数采用自变量ds(它是数组的名字)并设置由eqn指定的元素为关于w速度(w_vel)导数的值。(这是z动量方程源项)。这个函数也计算了旋转速度源项的值source,并返回这个值到求解器。 3.10.4修改FLUENT变量的函数
下面的UDF是一个修改存储在内存中FLUENT变量的函数例子。名字为inlet_x_velocity的函数使用F_PROFILE(a Fluent Inc. provided utility(应用程序)“Translate by 金山词霸”)来修改存储在内存中的x速度分布边界条件。
/********************************************************************/ /* UDF that modifies a FLUENT solver variable */ /* Specifies a steady-state velocity profile boundary condition */ /********************************************************************/ #include \
DEFINE_PROFILE(inlet_x_velocity, thread, index) {
real x[ND_ND]; real y; face_t f;
8
/* this will hold the position vector */
begin_f_loop(f, thread) {
F_CENTROID(x,f,thread); y = x[1];
F_PROFILE(f, thread, index) = 20. - y*y/(.0745*.0745)*20.; }
end_f_loop(f, thread) }
inlet_x_velocity使用DEFINE_PROFLIE宏来定义(在Section 4.3.5中描述)。它的自变量是thread和index。Thread是一个指向面线索的指针,而index是一个每个循环内为变量设置数值标签的整数。DEFINE_PROPERTY在udf.h文件中一个返回void的数据类型。
函数由声明变量f作为face_t数据类型开始。一维数组x和变量y是real 数据类型。循环宏用来在区域中每个面上循环以创建型线或数据数组。在每个循环内,F_CENTROID为含有index f的面输出面质心的值(数组 x),index f在由thread指向的线索上。存储在x[1]中的y坐标分配给变量y,它用于计算x速度。然后这个值分配给F_PROFILE, 它使用整数index(由求解器传递个它)来设置内存中面上的x速度值。
3.10.5写入Case或Data文件或从中读取的函数(Functions that Write to or Read from a Case or Data File) 下面的C源代码包含了写信息到data文件和读回它的函数例子。这是一个包含多个连接在一起的UDF的单个C文件例子。
/******************************************************************/ /* UDF that increment a variable, write it to a data file */ /* and read it back in */ /******************************************************************/ #include \
int kount = 0; /* define global variable kount */ DEFINE_ADJUST(demo_calc, domain) { kount++;
printf(\}
DEFINE_RW_FILE(writer, fp)
{ printf(\
fprintf(fp, \
9
}
DEFINE_RW_FILE(reader, fp)
{ printf(\ fscanf(fp, \}
在顶部的列表中,整数kount被定义为全局的(由于它被源代码文件中的所有三个函数使用)并初始化为0。名字为demo_calc的第一个函数,使用DEFINE_SDJUST 宏来定义。(关于DEFINE_ADJUST的详细信息见Section 4.2.1)。在demo_calc中,kount的值每次迭代后增加因为每次迭代调用DEFINE_ADJUST一次。名字为writer的第二个函数,使用DEFINE_RW_FILE宏来定义。(关于DEFINE_RW_FILE的详细信息见Section 4.2.4)。当保存数据文件时,它指示FLUENT写当前kount值到数据文件。名字为reader的第三个函数,当读取数据文件时,它指示FLUENT从这个数据文件中读取kount的值。
这三个函数一起工作如下。如果你运行10次迭代计算(kount将增加到值为10)并保存这个数据文件,当前kount(10)的值被写入你的数据文件。如果你读这个数据返回到FLUENT并继续计算,kount将以值10开始随着每次迭代继续增加。注意,你可尽你所想的保存静态变量,但是必须保证以与它们被写的相同顺序来读取它们。 3.11为多相流应用写UDF(Writing UDF for Mulutiphase Applications)
当一个多相流模型在FLUENT中被激活时,属性和变量的存储和对单相一样应当为所有相的混合设置它们。这可以通过使用附加线索(thread)和区域数据结构在代码中得以表明。
3.11.1多相应用的数据结构(Data Structure for Multiphase Applications)区域和线程(Domains and Threads)
在多相流应用中,最高级别的区域被用作超级区域。每相占据的区域用作子区域第三种类型区域是相互作用区,为了定义相间的相互作用才引入它的。当混合属性和变量必要时(所有相的和),超级区域用于这些数量而子区域携带了单相的信息。在单一相中混合的概念用于描述所有种类(成分)的和而在多相中它描述了所有相的总和。这个区别是非常重要的因为以后代码将延伸到多相多组分(例如,这里相是种类的混合)。
由于求解器的数据存储在线程(thread)数据结构中,线程必须既和超级区域相联系又和每个子区域相联系。就是说,对定义在超级区域上的每个单元或面线程,有相应的单元或面线程定义在每个子区域上。定义在超级区域每个线程上的某些信息与子区域每个相应线程上的共享。与超级区域相关的线程被用作超级线程,而与子区域相关的线程被用作相级别线程或子线程。区域和线程的层次总结在Figure 3.11.1中。
10