1UDF第3章写UDF本章主要概述了如何在FLUENT写UDF。3.1概述3.2写解释式UDF的限制3.3FLUENT中UDF求解过程的顺序3.4FLUENT网格拓扑3.5FLUENT数据类型3.6使用DEFINEMacros定义你的UDF3.7在你的UDF源文件中包含udf.h文件3.8定义你的函数中的变量3.9函数体3.10UDF任务3.11为多相流应用写UDF3.12在并行中使用你的UDF3.1概述(Introduction)UDF是用来增强FLUENT代码的标准功能的,在写UDF之前,我们要明确以下几个基本的要求。首先,必须用C语言编写UDF。必须使用FLUENT提供的DEFINE宏来定义UDF。UDF必须含有包含于源代码开始指示的udf.h文件;它允许为DEFINEmacros和包含在编译过程的其它FLUENT提供的函数定义。UDF只使用预先确定的宏和函数从FLUENT求解器访问数据。通过UDF传递到求解器的任何值或从求解器返回到UDF的值,都指定为国际(SI)单位。总之,当写UDF时,你必须记住下面的FLUENT要求。UDF:1.采用C语言编写。2.必须为udf.h文件有一个包含声明。3.使用Fluent.Inc提供的DEFINEmacros来定义。4.使用Fluent.Inc提供的预定义宏和函数来访问FLUENT求解器数据。5.必须使返回到FLUENT求解器的所有值指定为国际单位。3.2写解释式UDF的限制(RestrictiononWritingInterpretedUDF)无论UDF在FLUENT中以解释还是编译方式执行,用户定义C函数(说明在Section3.1中)的基本要求是相同的,但还是有一些影响解释式UDF的重大编程限制。FLUENT解释程序不支持所有的C语言编程原理。解释式UDF不能包含以下C语言编程原理的任何一个:21.goto语句。2.非ANSI-C原型语法3.直接的数据结构查询(directdatastructurereferences)4.局部结构的声明5.联合(unions)6.指向函数的指针(pointerstofunctions)7.函数数组。在访问FLUENT求解器数据的方式上解释式UDF也有限制。解释式UDF不能直接访问存储在FLUENT结构中的数据。它们只能通过使用Fluent提供的宏间接地访问这些数据。另一方面,编译式UDF没有任何C编程语言或其它注意的求解器数据结构的限制。3.3FLUENT求解过程中UDF的先后顺序(SequencingofUDFintheFLUENTSolutionProcess)当你开始写UDF代码的过程时(依赖于你写的UDF的类型),理解FLUENT求解过程中UDF调用的内容或许是重要的。求解器中包含连接你写的用户定义函数的call-outs。知道FLUENT求解过程中迭代之内函数调用的先后顺序能帮助你在给定的任意时间内确定那些数据是当前的和有效的。分离式求解器在分离式求解器求解过程中(Figure3.3.1),用户定义的初始化函数(使用DEFINE_INIT定义的)在迭代循环开始之前执行。然后迭代循环开始执行用户定义的调整函数(使用DEFINE_ADJUST定义的)。接着,求解守恒方程,顺序是从动量方程和后来的压力修正方程到与特定计算相关的附加标量方程。守恒方程之后,属性被更新(包含用户定义属性)。这样,如果你的模型涉及到气体定律,这时,密度将随更新的温度(和压力and/or物质质量分数)而被更新。进行收敛或者附加要求的迭代的检查,循环或者继续或停止。Figure3.3.1:分离解算器的解程序Figure3.3.2:SolutionProcedurefortheCoupledSolverFigure3.4.1:GridTerminology耦合求解器3在耦合求解器求解过程中(Figure3.3.2),用户定义的初始化函数(使用DEFINE_INIT定义的)在迭代循环开始之前执行。然后,迭代循环开始执行用户定义的调整函数(使用DEFINE_ADJUST定义的)。接着,FLUENT求解连续、动量和(适合的地方)能量的控制方程和同时地一套物质输运或矢量方程。其余的求解步骤与分离式求解器相同(Figure3.3.1)。3.4FLUENT网格拓扑在我们开始讨论FLUENT特殊的数据类型之前,你必须理解网格拓扑学的术语因为FLUENT数据类型是为这些实体定义的。下面是显示在Figure3.4.1中的网格实体的定义。单元(cell)区域被分割成的控制容积单元中心(cellcenter)FLUENT中场数据存储的地方面(face)单元(2Dor3D)的边界边(edge)面(3D)的边界节点(node)网格点单元线索(cellthread)在其中分配了材料数据和源项的单元组面线索(facethread)在其中分配了边界数据的面组节点线索(nodethread)节点组区域(domain)由网格定义的所有节点、面和单元线索的组合3.5FLUENT数据类型除了标准的C语言数据类型如real,int等可用于在你的UDF中定义数据外,还有几个FLUENT指定的与求解器数据相关的数据类型。这些数据类型描述了FLUENT中定义的网格的计算单位(见Figure3.4.1)。使用这些数据类型定义的变量既有代表性地补充了DEFINEmacros的自变量,也补充了其它专门的访问FLUENT求解器数据的函数。一些更为经常使用的FLUENT数据类型如下:cell_tface_tThreadDomainNodecell_t是线索(thread)内单元标识符的数据类型。它是一个识别给定线索内单元的整数下标。face_t是线索内面标识符的数据类型。它是一个识别给定线索内面的整数下标。4Thread数据类型是FLUENT中的数据结构。它充当了一个与它描述的单元或面的组合相关的数据容器。Node数据类型也是FLUENT中的数据结构。它充当了一个与单元或面的拐角相关的数据容器。Domain数据类型代表了FLUENT中最高水平的数据结构。它充当了一个与网格中所有节点、面和单元线索组合相关的数据容器。!!注意,FLUENT中所有数据类型都是情形敏感的(case-sensitive)。3.6使用DEFINEMacros定义你的UDFFluent.Inc为你提供了一套你必须使用它来定义你的UDF的预定义函数。这些定义UDF的函数在代码中作为宏执行,可在作为DEFINE(全部大写)宏的文献中查阅。对每个DEFINE宏的完整描述和它的应用例子,可参考第四章。DEFINE宏的通用格式为:DEFINE_MACRONAME(udf_name,passed-invariables)这里括号内第一个自变量是你的UDF的名称。名称自变量是情形敏感的必须用小写字母指定。一旦函数被编译(和连接),你为你的UDF选择的名字在FLUENT下拉列表中将变成可见的和可选的。第二套输入到DEFINE宏的自变量是从FLUENT求解器传递到你的函数的变量。在下面的例子中,宏DEFINE_PROFILE(inlet_x_velocity,thread,index)用两个从FLUENT传递到函数的变量thread和index定义了名字为inlet_x_velocity的分布函数。这些passed-in变量是边界条件区域的ID(作为指向thread的指针)而index确定了被存储的变量。一旦UDF被编译,它的名字(例如,inlet_x_velocity)将在FLUENT适当的边界条件面板(例如,VelocityInlet面板)的下拉列表中变为可见的和可选的。!!注意,所有用于DEFINE宏的自变量必须放在你的源代码的同一行上。分割DEFINE的声明为几行可能导致编译错误。3.7在你的UDF源文件中包含udf.h文件(Includingtheudf.hFileinYourUDFSourceFile)DEFINE宏的定义位于称为udf.h(见附录A的列表)的头文件中。为了使DEFINE宏延伸到编译过程,你必须在你写的每个UDF源文件的开始包含udf.h文件。#includeudf.h/*Alwaysincludeudf.hwhenwritingaUDF.IttranslatestheDEFINE*//*andothermacrosintoC,whichiswhatthecompilerunderstands.*/通过在你的UDF源文件中包含udf.h,编译过程中所有的DEFINE宏的定义与源代码一起被包含进来。udf.h文件也为所有的C库函数头文件包含#include指示,与大部分头文件是针对Fluent提供的宏和函数是一样的(例如,mem.h)。除非有另外的指示,没必要在你的UDF中个别地包含这些头文件。5还有,当你编译你的UDF时,你不必放置udf.h的拷贝在你的当地目录下;一旦你的UDF被编译,FLUENT求解器会自动地从Fluent.Inc/fluent6.x/src/目录来读取udf.h文件。举例从前面部分的宏DEFINE_PROFILE(inlet_x_velocity,thread,index)定义在udf.h文件中为#defineDEFINE_PROFILE(name,t,i)voidname(Thread*t,inti)在编译过程中延伸为voidinlet_x_velocity(Thread*thread,intindex)名字为inlet_x_velocity的函数不返回值由于它被声明为空的数据类型。3.8在你的函数中定义变量(DefiningVariableinYourFunction)在你的UDF源文件中包含了udf.h头文件后,你必须定义真实的变量。使用把它们定义在所有函数之外的全局变量(如果它们被源文件中大部分或所有函数共享)是非常方便的。关于全局变量的信息见Section2.5.3。局部于函数的任何变量必须在函数内声明。局部变量的信息见Section2.5.2。3.9函数体(FunctinBody)你的UDF源文件中的C函数体被包含在DEFINE声明之下的一对大括号内,显示在下面的例子中。在这个例子中,mu_lan和temp是局部变量。只有cell_viscosity函数认识它们。例子DEFINE_PROPERTY(cell_viscosity,cell,thread){realmu_lam;realtemp=C_T(cell,thread);if(temp288.)mu_lam=5.5e-3;elseif(temp286.)mu_lam=143.2135-0.49725*temp;elsemu_lam=1.;returnmu_lam;}3.10UDF任务(UDFTasks)6UDF可执行的任务有五种不同的类型:1.返回值2.修改自变量3.返回值和修改自变量4.修改FLUENT变量(不能作为自变量传递)5.写信息到(或读取信息从)case或data文件函数能返回值,除非它们在udf.h文件中被定义为void。如果它们不返回值,它们能修改自变量,修改存储在内存中的变量,或与case和data文件一起执行输入输出(I/O)任务。在Section3.10.1-3.10.5中,提供了描述上面提到的五种不同的函数任务中每一种的UDF源代码例子。3.10.1返回值的函数(FunctionthatReturnaValue)下面的UDF是一个返回值到FLUENT求解器的函数例子。名为cell_viscosity的函数计算了依赖温度的粘度值(mu_lam)并返回这个值到求解器。/********************************************************************//*UDFthatreturnsavaluetothesolver*//*Specifiesatemperature-dependentviscosityproperty*//******************