1、第一章. 介绍 本章简要地介绍了用户自定义函数(UDF)及其在 Fluent 中的用法。在 1.1 到 1.6 节中我 们会介绍一下什么是 UDF;如何使用 UDF,以及为什么要使用 UDF,在 1.7 中将一步步的 演示一个 UDF 例子。 1.1 什么是 UDF? 1.2 为什么要使用 UDF? 1.3 UDF 的局限 1.4 Fluent5到 Fluent6 UDF的变化 1.5 UDF 基础 1.6 解释和编译 UDF的比较 1.7 一个 step-by-stepUDF 例子 1.1 什么是 UDF? 用户自定义函数,或 UDF,是用户自编的程序,它可以动态的连接到 Fluent 求解
2、器上 来提高求解器性能。用户自定义函数用 C 语言编写。使用 DEFINE 宏来定义。UDF 中可使 用标准 C 语言的库函数,也可使用 Fluent Inc.提供的预定义宏,通过这些预定义宏,可以获 得 Fluent求解器得到的数据。 UDF 使用时可以被当作解释函数或编译函数。解释函数在运行时读入并解释。而编译 UDF 则在编译时被嵌入共享库中并与 Fluent 连接。解释 UDF 用起来简单,但是有源代码和 速度方面的限制不足。编译 UDF 执行起来较快,也没有源代码限制,但设置和使用较为麻 烦。 1.2为什么要使用 UDF? 一般说来,任何一种软件都不可能满足每一个人的要求,FLUEN
3、T 也一样,其标准界 面及功能并不能满足每个用户的需要。UDF 正是为解决这种问题而来,使用它我们可以编 写 FLUENT 代码来满足不同用户的特殊需要。当然, FLUENT 的 UDF 并不是什么问题都可 以解决的,在下面的章节中我们就会具体介绍一下 FLUENT UDF的具体功能。现在先简要 介绍一下 UDF 的一些功能: 定制边界条件,定义材料属性,定义表面和体积反应率,定义 FLUENT 输运方程 中的源项,用户自定义标量输运方程(UDS)中的源项扩散率函数等等。 在每次迭代的基础上调节计算值 方案的初始化 (需要时)UDF 的异步执行 后处理功能的改善 FLUENT 模型的改进(例如
4、离散项模型,多项混合物模型,离散发射辐射模型) 由上可以看出 FLUENT UDF 并不涉及到各种算法的改善,这不能不说是一个遗憾。当 然为了源代码的保密我们还是可以理解这样的做法的。其实,如果这些代码能够部分开放, 哪怕就一点点,我想 FLUENT 会像 LINUX 一样发展更为迅速,使用更为广泛。遗憾的是, 从目前来看,这只是一种幻想。什么时候中国人可以出自己的精品? 1.3 UDF的局限 尽管 UDF 在 FLUENT 中有着广泛的用途, 但是并非所有的情况都可以使用 UDF。 UDF 并不能访问所有的变量和 FLUENT 模型。例如,它不能调节比热值;调节该值需要使用求 解器的其它功能
5、。如果您不知道是否可以用 UDF 解决某个特定的问题,您可以求助您的技 术支持。 1.4 Fluent5到 Fluent6UDF的变化 如果你有 FLUENT5 的 UDF 编程经验,请注意在 FLUENT6 种的下列变化: FLUENT6 中加入了大量的通用多相模型。When one of these general multiphase models is enabled, storage must be set aside for the mixture as well as the individual phases. This functionality is manifested
6、in the code through the use of additional thread and domain data structures. Consequently, some predefined macros have been added that allow access to data contained within mixture-level and phase-level domain and thread structures. See Section 3.11 for details on writing UDF for multiphase applicat
7、ions. If you have a FLUENT 5 UDF with an external domain declaration that you want to use in FLUENT 6, then the extern statement must be replaced by a call to the Get_Domain utility and assignment to a Domain pointer as shown below. The Fluent-provided utility, Get_Domain(1), returns the pointer to
8、the mixture-level domain. See Section 6.5.1 for more details on Get_Domain. Example extern Domain *domain; DEFINE_ON_DEMAND(my_udf) . is to be replaced by DEFINE_ON_DEMAND(my_udf) Domain *domain; domain = Get_Domain(1); . The macro C_VOF accesses volume fraction values from the FLUENT solver. C_VOF(
9、c, pti) has two arguments, c and pti. c is the cell identifier. pti is the pointer to the corresponding phase-level thread for the ith phase, where i is the phase_domain_index. For example, C_VOF(c,pti) can be used to return the volume fraction of the ith phase fluid at cell c. The pointer pti can a
10、lso be retrieved using THREAD_SUB_THREAD, discussed in Section 6.5.4, using i as an argument. For compiled UDF, the makefile called Makefile.udf that was provided in previous FLUENT releases has been renamed to makefile.udf2. See Section 7.3.2 for more details. For multiphase flow problems, you will
11、 need to supply your own user-defined scalar flux function instead of using the default function provided by FLUENT. DEFINE_PROPERTY is to be used to define UDF for particle or droplet diameter for the mixture model, previously the Algebraic Slip Mixture Model (ASMM), instead of the DEFINE_DRIFT_DIA
12、M macro. 1.5 UDF 基础 1.5.1 输运方程 1.5.2 单元(Cells),面,区域(Zones)和线(Threads) 1.5.3 操作 1.5.4 求解器数据 1.5.5 运行 1.5.1 输运方程 FLUENT 求解器建立在有限容积法的基础上,这种方法将计算域离散为有限数目的控 制体或是单元。网格单元是 FLUENT 中基本的计算单元,这些单元的守恒特性必须保证。 也就是说普通输运方程,例如质量,动量,能量方程的积分形式可以应用到每个单元: (1.5.1) 此处, 是描述普通输运数量的变量(a general transportable quantity),根据所求解的
13、输运 方程它可取不同的值。下面是在输运方程中可求解的 的子集。 Transport Equation Variable for continuity 1 x momentum velocity ( u) y momentum velocity ( v) z momentum velocity ( w) energy enthalpy ( h) turbulent kinetic energy k turbulent dissipation ratespecies transport mass fraction of species ( Y i ) 守恒与否需要知道通过单元边界的通量。因此,需计
14、算出单元和面上的属性值(properties)。 1.5.2 单元(Cells),面,区域(Zones)和线(Threads) 单元和单元面被组合为一些区域(zones),这些区域规定了计算域(例如,入口,出 口,壁面)的物理组成(physical components)。当用户使用 FLUENT 中的 UDF 时,用户 的 UDF 可调用流体区域或是边界区域的计算变量(solution variables)。UDF 需要获得适 当的变量,比如说是区域参考(a zone reference)和单元 ID,以便标定各个单元。 区域(A zone)是一群单元或单元面的集合,它可以由模型和区域的物理
15、特征(比如入 口,出口,壁面,流体区域)来标定。例如,一些被指定为面域(a face zone)的单元面可 以被指定为 velocity-inlet 类型,由此,速度也就可指定了。线(A thread)是 FLUENT 数 据结构的内部名称,可被用来指定一个区域。Thread 结构可作为数据储存器来使用,这些 数据对于它所表示的单元和面来说是公用的(The Thread structure acts as a container for data that is common to the group of cells or faces that it represents)。 1.5.3 操
16、作 多数的 UDF 任务需要在一个线的所有单元和面上重复执行。比如,定义一个自定义轮 廓函数(a custom profile function)则会对一个面线上(in a face thread)的所有单元和面进 行循环。 为了用户方便, Fluent Inc.向用户提供了一些循环宏工具(looping macro utilities) 来执行对单元, 面, 节点 (nodes) 和线 (threads) 的重复操作。 例如, 单元循环宏 (Cell-looping macros )可以对给定单元线上的所有单元进行循环操作(loop over cells in a given cell th
17、read allowing access to all of the cells)。 而面循环宏(Face-looping macros)则可调用所有给定 面线(a given face thread)的面。Fluent提供的循环工具请见 Chapter 6。 在某些情况下,UDF 需要对某个变量操作,而这个变量恰恰又不能直接被当作变量来 传递调用。比如,如果用户使用 DEFINE_ADJUST 宏来定义 UDF,求解器将不会向它传递 thread 指针。这种情况下,用户函数需要用 Fluent 提供的宏来调用线指针(thread pointer)。 见 Chapter 6。 1.5.4 求解
18、器数据 通过 FLUENT 用户界面将 C 函数(它已被编译和连接)连接到求解器上可实现调用求 解器变量。一旦 UDF 和求解器正确连接,无论何时,函数都可调用求解器数据。这些数据 将会被作为用户变量自动地传递给 UDF。注意,所有的求解器变量,不管是求解器传递给 UDF 的,还是 UDF 传递给求解器的,都使用 SI 单位。 1.5.5 运行 UDF 将会在预定时刻被 FLUENT 调用 。但是,也可对它们进行异步执行,使用 DEFINE_ON_DEMAND 宏,还可在需要时(on demand)执行。详情请见 4.2.3 1.6 解释和编译 UDF 的比较 编译 UDF 和 FLUENT
19、的构建方式一样。脚本 Makefile 被用来调用 C 编译器来构建一 个当地目标代码库(a native object code library)。目标代码库包含高级 C语言源代码的机器 语言翻译。代码库在 FLUENT 运行时由“动态加载”(dynamic loading)过程连接到 FLUENT 上。连接后,与共享库的联系(the association with the shared library)将会被保存 在用户的 case 文件中,这样, 当 FLUENT 以后再读入 case 文件时, 此编译库将会与 FLUENT 自动连接。这些库是针对计算机的体系结构和一定版本的 FLUE
20、NT 使用的。所以,当 FLUENT 更新,或计算机操作系统改变,或是在不同类型的机器上运行时,这些库必须重 新构建。 而解释 UDF 则是在运行时,直接从 C 语言源代码编译和装载(compiled and loaded directly from the C source code)。在 FLUENT 运行中,源代码被编译为中介的独立于物理 结构的使用 C 预处理程序的机器代码(an intermediate, architecture-independent machine code)。当 UDF 被调用时,机器代码由内部仿真器(an internal emulator),或注释器 (i
21、nterpreter)执行。注释器不具备标准 C 编译器的所有功能;它不支持 C 语言的某些原理 (elements)。所以,在使用 interpreted UDF 时,有语言限制(见 3.2)。例如,interpreted UDF 不能够通过废弃结构(dereferencing structures)来获得 FLUENT 数据。要获得数据结 构,必须使用由 FLUENT 提供的预定义宏。另一个例子是 FLUENT interpreter 不能识别指 针数组。这些功能必须由 compiled UDF 来执行。 编译后,用户的 C 函数名称和内容将会被储存在 case 文件中。函数将会在读入 c
22、ase 文 件时被自动编译。独立于物理结构的代码的外层(This extra layer of architecture-independent code)可能会导致执行错误(a performance penalty),但却可使 UDF 共享不同的物理结构, 操作系统,和 Fluent版本。如果运行速度较慢, UDF 不用被调节就可以编译代码的形式(in compiled mode)运行。FLUENT 中的 compiled 和 interpreted UDF 请见 Chapter 7。 选择 interpreted UDF或是 compiled UDF时,注意以下内容: Interpret
23、ed UDF o 对其它平台是便捷的(portable)。 o 可作为(compiled UDF)来运行。 o 不需 C 编译器。 o 比 compiled UDF慢 。 o 需要较多的代码。 o 在使用 C 语言上有限制。 o 不能与编译系统或用户库(compiled system or user libraries)连接。 o 只能使用预定义宏来获得 FLUENT 结构中的数据。 (见 Chapters 5 和 6) 。 Compiled UDF o 比 interpreted UDF 运行快。 o 在使用 C 语言上不存在限制。 o 可用任何 ANSI-compliant C 编译器编译
24、。 o 能调用以其他语言编写的函数 (specifics are system- and compiler-dependent)。 o 机器物理结构需要用户建立 FLUENT (2D or 3D) 的每个版本的共享库(a shared library for each version of FLUENT (2D or 3D) needed for your machine architecture) 。 o 如果包含有注释器(interpreter)不能处理得 C 语言元素,则不能作为 (interpreted UDF )运行。 总的来说,当决定使用那种类型的 UDF 时: 使用 interp
25、reted UDF作为简单的函数 使用 compiled UDF作为复杂的函数,这些函数 o 对 CPU有较大要求(例如每次运行时,在每个单元上均须调用的属性 UDF (a property UDF)。 o 需要使用编译库(require access to a compiled library) 。 1.7一个 step-by-stepUDF例子 编辑 UDF 代码,并且在用户的 FLUENT 模型中有效使用它,须遵循以下七个基本步骤: 1. 定义用户模型。 2. 编制 C 语言源代码。 3. 运行 FLUENT ,读入,并设置 case 文件。 4. 编译或注释(Compile or in
26、terpret)C 语言源代码。 5. 在 FLUENT 中激活 UDF。 6. 开始计算。 7. 分析计算结果,并与期望值比较。 在开始解决问题前,用户必须使用 UDF 定义希望解决的问题(Step 1)。例如,加入 用户希望使用 UDF 来定义一个用户化的边界条件(a customized boundary profile )。用户 首先需要定义一系列数学方程来描述这个条件。 接下来用户需要将这些数学方程(概念设计,conceptual design)用 C 语言写成一个函 数(Step 2)。用户可用文本编辑器来完成这一步。以.c 为后缀名来把这个文件保存在工作 路径下。 写完 C 语言
27、函数后,用户即可运行 FLUENT 并且读入或设置 case 文件(Step 3)。对 语言源代码进行注释,编译,和调试(interpret, compile, and debug),并在 FLUENT 中 激活用户函数 (Step 5)。最后, 运行计算(Step 6),分析结果并与期望值比较。(Step 7)。根据用户对结果的分析,可将上述整个过程重复几次。具体如下。 Step 1: 定义用户模型 生成和使用 UDF 的第一步是定义用户的模型方程。 如图 Figure1.7.1 所示的涡轮叶片。模拟叶片周围的流场使用了非结构化网格。计算域由底 端的周期性边界( a periodic bou
28、ndary on the bottom )延伸到顶端的相同部分(an identical one on the top),速度入口在左边,压力出口在右边。 Figure 1.7.1: The Grid for the Turbine Vane Example 文中对入口 x 速度为常数分布和抛物线分布的流场进行了比较。 分段线性的分布可由边 界场选项得到(the application of a profile using a piecewise-linear profile is available with the boundary profiles option),而多项式分布则只能使用
29、用户自定义函数得到。 进口速度为常数(20 m/s)的结果如图和所示。当流动沿着涡轮叶片 进行时,初始速度场被改变了。 Figure 1.7.2: Velocity Magnitude Contours for a Constant Inlet x Velocity Figure 1.7.3: Velocity Vectors for a Constant Inlet x Velocity 假定现在要设涡轮叶片入口速度 x不是一常数值,其分布如下 变量 y 在入口中心处为,在入口上部和下部则分别为 0.0745 m 而入口中心处的 x 速度为 20 m/s ,边界上为。 用户可用 UDF 描述
30、这一分布,并将它应运到 FLUENT 模型中来解决这类问题。 Step 2: 编制 C 语言源代码。 选定方程定义 UDF 后,用户可用任意文本编辑器来书写语言代码。以扩展名.c 保存 源代码文件保存到工作路径下。关于 UDF 的书写请参考 Chapter 。 下面是一个怎样在 UDF 中应用方程的例子。UDF 的功能由主要的 DEFINE 宏(the leading DEFINE macro)来定义。此处,DEFINE_PROFILE 宏用来表示下面的代码旨在给 求解器提供边界的轮廓信息。书中将在以后部分讨论其它的 DEFINE 宏。 /*/ /* udf e xam ple.c */ /*
31、 UDF for specifying a steady-state velocity profile boundary condition */ /*/ #include “udf.h“ DEFINE_PROFILE(inlet_x_velocity, thread, index) real xND_ND; /* this will hold the position vector */ real y; face_t f; begin_f_loop(f, thread) F_CENTROID(x,f,thread); y = x1; F_PROFILE(f, thread, index) =
32、 20. - y*y/(.0745*.0745)*20.; end_f_loop(f, thread) DEFINE_PROFILE 宏的第一个变量 inlet_x_velocity 用来定义速度入口面板中的函数。 名称 可任意指定。在给定的边界区域上的所有单元面(identified by f in the face loop)上将会使 用函数的这个方程。当用户在 FLUENT 用户界面选定 UDF 作为边界条件时,将会自动定 义线(thread)。下标由 begin_f_loop 应用程序自动定义。UDF 中,begin_f_loop 被用来形 成对边界区域上所有单元面的循环(loop t
33、hrough all cell faces in the boundary zone)。对于每 个面,面的质心(the face centroid)的坐标可由 F_CENTROID 宏来获得。抛物线方程中用到了 y 坐标 y ,速度值通过 F_PROFILE 宏来返回给面。 begin_f_loop 宏和 F_PROFILE 宏都是 FLUENT 提供的宏。详情请见 Chapter 。 Step 3: 运行 FLUENT ,读入,并设置 case 文件 建立 UDF 后,用户开始设置 FLUENT。 1. 在工作路径下启动 FLUENT。 2. 读入(或设置)case 文件(如果 case 文
34、件以前设置过,请确认它是否被保存在了工作路 径下) 。 Step 4: 编译或注释(Compile or interpret)C 语言源代码 这部分将例中的源代码作为 interpreted UDF 来编译。注意,这个例子不可应用于 Windows 的并行网络(Windows parallel networks)。完整的编译和连接 UDF 请见 Chapter 。 1. 确认 UDF 的 case 文件(如果以前设置过)和 C 语言源代码在工作路径下。 2. 用 Interpreted UDF 面板编译 UDF (例如, udfexample.c) 。 Define User-Defined
35、Functions Interpreted. Figure 1.7.4: The Interpreted UDF Panel (a) 在 Source File Name下键入 C 语言源代码文件 ( 例如, udfexample.c) 。 ! 如果用户源代码不在目前工作路径下,则在编译 UDF 时,需在 Interpreted UDF 面板中间如文件完整的路径。 (b) 在 CPP Command Name 一栏里,选择 C 预处理器。 (c) Stack Size 缺省设置为 10000。如果用户函数的局部变量数目大于 10000,将会 导致堆栈溢出。这种情况下,应将 Stack Size
36、 设置为比局部变量大的数。 (d) 点击 Compile 编译 UDF。 存储 case 文件时, C 语言代码的名称和内容将会储存在 case文件中。 如果 Interpreted UDF 面板中的 Display Assembly Listing 选项被选中,当编译进行时,控制台窗口中 将会显示汇编语言代码。另外,此选项将会被存储在 case文件中,当以后用户在执 行 FLUENT 任务时,控制台窗口中将会编译时一样显示汇编语言代码。 inlet_x_velocity: .local.pointer thread (r0) .local.int nv (r1) 0 .local.end 0
37、 sav e .local.int f (r3) 1 push.int 0 .local.pointer x (r4) 3 begin.data 8 bytes, 0 bytes initialized: 7 sav e . . . . 156 pre.inc.int f (r3) 158 pop.int 159 b .L3 (22) .L2: 161 restore 162 restore 163 ret.v ! 注意,如果编译失败,FLUENT 将会给出错误信息,请调试程序。详见 7.2.3。 (e) 编译结束后,点击 Close。 ! 此例中的 UDF 源代码也可作为 compiled
38、UDF运行。 Step 5: 在 FLUENT 中激活 UDF 编译连接完 UDF 后,FLUENT 用户界面面板中将会看到 UDF。此例中,可在 Velocity Inlet面板中选择 UDF。 Define Boundary Conditions. 在 X-Velocity下拉列表中,选择 udf inlet_x_velocity,此名称是由例中的函数给定的。一旦 选中,UDF 将会替代 X-Velocity 中的 0 值进行运算。点击 OK 接受新的边界条件,关闭面 板。 Step 6: 开始计算 运算方式和以前一样。 Solve Iterate. Step 7: 分析计算结果,并与期望
39、值比较 计算收敛后,获得一个修正的速度场。 Figure1.7.5 为入口 x速度为抛物线分布的速度等 值线,可与(Figure 1.7.2)所示的入口速度为常数 20 m/sec 的流场比较。常数条件下,流 动在涡轮叶片周围变形(distorted)。入口抛物线分布,在入口中心处为最大值,边缘上为 0。 Figure 1.7.5: Velocity Magnitude Contours for a Parabolic Inlet x Velocity 第二章.UDF 的 C 语言基 础 本章介绍 了 UDF 的 C 语言基础 2.1 引言 2.2 注释你的 C 代码 2.3FLUENT 中的
40、 C 数据 类型 2.4 常数 2.5 变量 2.6 自定义数 据类型 2.7 强制转换 2.8 函数 2.9 数组 2.10 指针 2.11 声明 2.12 常用 C 操作符 2.13C 库函数 2.14 用#define 实现宏置换 2.15 用#include 实现文件 包含 2.16 与 FORTRAN 比较 2.1 引言 本章介绍了 C 语言的一 些基本信息, 这些信息对处理 FLUENT 的 UDF 很有帮助。 本章 首先假定你有一些编程经验而不是 C 语言的初级介绍。本章不会介绍诸如 while-do 循环, 联合,递归,结构以及读写文件的基础知识。如果你对 C 语言不熟悉可以参
41、阅 C 语言的相 关书籍。 2.2 注释你 的 C 代码 熟悉 C 语言 的人都知道,注释在编写程序和调试程序等处理中是很重要的。注释的每 一行以“/*” 开 始,后面的是注释的文本行,然后是“*/” 结尾 如:/* This is how I put a comment in my C program */ 2.3FLUENT 的 C 数据类 型 FLUENT 的 UDF 解释程 序支持下面的 C 数据类 型: Int :整型 Long :长整 型 Real :实数 Float :浮点 型 Double :双 精度 Char :字符 型 注意:UDF 解释函数在单精度算法中定义 real 类
42、型为 float 型, 在双精度算法宏定义 real 为 double 型。 因为解释函数自动作如此分配,所以使用在 UDF 中声明所 有的 float 和 double 数据变量时使用 real 数 据类型是很好的编程习惯。 2.4 常数 常数是表达式中所使用的绝对值,在 C 程序中 用语句#define 来定义。最 简单的常数是 十进制整数(如:0 ,1 ,2 )包含小 数点或者包含字母 e 的 十进制数被看成浮点常数。按惯 例, 常数的声明一般都使用大写字母。 例如, 你可以设定区域的 ID 或者定义 YMIN 和 YMAX 如下:#define WALL_ID 5 #define YM
43、IN 0.0 #define YMAX 0.4064 2.5 变量 变量或者对象保存在可以存储数值的内存中。 每一个变量都有类型、 名字和值。 变量在 使用之前必须在 C 程序 中声明。这样,计算机才会提前知道应该如何分配给相应变量的存 储类型。 2.5.1 声明 变量 变量声明的结构如下: 首先是数据类型, 然后是具有相应类型的一个或多个变量的名字。 变量声明时可以给定初值,最后面用分号结尾。变量名的头字母必须是 C 所允许 的合法字 符,变量名字中可以有字母,数字和下划线。需要注意的是,在 C 程 序中,字母是区分大 小写的。下面是变量声明的例子: int n; /* 声明变 量 n 为整
44、型*/ int i1 , i 2; /* 声明变 量 i1 和 i2 为整 型*/ float tmax = 0.; /* tmax 为浮点型实数,初值为 0 */ real average_temp = 0.0; /* average_temp 为实数, 赋初值为 0.1*/ 2.5.2 局部 变量 局部变量只用于单一的函数中。 当函数调用时, 就被创建了, 函数返回之后, 这个变 量 就不存在了,局部变量在函数内部(大括号内)声明。在下面的例子中,mu_lam 和 temp 是 局部变量。 DEFINE_PROPERTY(cell_viscosity, cell, thread) real
45、 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; e ls e mu_lam = 1.; return mu_lam; 2.5.3 全局 变量 全局变量在你的 UDF 源 文件中是对所有的函数都起作用的。 (调用一个 UDF 源文件 可 能会包括一 系列的连接 函数。 )它们 是在单一函 数的外部定 义的。全局 变量一般是 在预处理 程序之后的文件开始处声明。 2.5.4 外部 变量 如果全
46、局变量在某一源代码文件中声明, 但是另一个源代码的某一文件需要用到它, 那 么你必须在另一个文件中声明它是外部变量。 外部变量的声明很简单, 你只需要在变量声明 的最前面加上 extern 即 可。 如果有几个文件涉及到该变量, 最方便的处理方法就是在头文件 (.h)中 加 上 extern 的 定义, 然后在所有的.c 文件中引用该头文件即可。 只有一个.c 文件应 该包括没有 extern 关键字 的变量声明,如下所示。注意:extern 只用于编 译过的 UDF 。 例子: /* filea.h */ /* 包含外部定 义的头文件*/ extern real volume; /* fil
47、ea.c */ /* 调用头文 件 filea.h 中 声明的 volumn 的 C 函数*/ #include “udf.h“ #include “filea.h“ real volume; DEFINE_ADJUST(compute_volume, domain) /* 计算某 些区域 volumn 的代码*/ volume = /* fileb.c */ /* 调用头文 件 filea.h 中 声明的 volumn 的另一个 C 函数*/ #include “udf.h“ #include “filea.h“ DEFINE_SOURCE(heat_source,c,t,ds,eqn) /
48、* 用总数 来计算每个单位体积的源项的代码*/ /*fliea.c 的 compute_volum 计算出的 volume*/ real total_source = .; real source; source = total_source/volume; return source; 2.5.5 静态 变量 static 声明对 于全局变量和局部变量的影响是不一样的。静态局部变量在函数调用返回 之后, 该变量不会被破坏。 静态全局变量则在定义该变量的.c 源文件之外对任何函数保持不 可见。 静态声明也可以用于函数, 使该函数只对定义它的.c 源文件保持 可见。 下面是静态全 局变量声明的例子。注意:extern 只 用于编译过的 UDF 。 例子: #include “udf.h“ static real abs_coeff = 1.0; /* 吸收系 数*/ real source; DEFINE_SOURCE(energy_source, c, t, dS, eqn) int P1 = ; dSeqn = -16.* abs_coeff * SIGMA_SBC * pow(C_T(c,t),3.); source =-abs_coeff *(4.* SIGMA_SBC * pow(C_T(c,t),4.) - C_UDSI(c,t,P1); r