乐于分享
好东西不私藏

Ansys Fluent文档-UDF篇:用户自定义函数概述(UDFs)(一)

Ansys Fluent文档-UDF篇:用户自定义函数概述(UDFs)(一)

1.1 什么是用户自定义函数

用户自定义函数(UDF)是一种CC++语言编写的函数,可通过动态加载方式集成到Fluent求解器中以增强其标准功能。例如,可以使用UDF实现以下功能:

①自定义边界条件、材料属性定义、表面和体积反应速率、Fluent输运方程中的源项、用户自定义标量(UDS)输运方程中的源项、扩散函数等。

②以每次迭代为基础调整计算值。

③解决方案的初始化。

④执行UDF的异步(按需)调用。

⑤在迭代结束时、退出Fluent时或加载已编译的UDF库时执行。

⑥增强后处理。

⑦增强现有Fluent模型(例如离散相模型、多相混合模型、离散坐标辐射模型)。

UDF通过.c.cpp扩展名进行标识(例如myudf.c)。一个源文件可以包含单个UDF或多个UDF,并且可以定义多个源文件。

UDF通过Fluent提供的DEFINE宏进行定义。编写UDF时需使用Fluent提供的附加宏和函数来访问求解器数据并执行其他任务。

每个UDF必须在源代码文件的开头包含udf.h文件包含指令(#include “udf.h”),该指令既支持DEFINE宏及其他Fluent提供的宏和函数的定义,也支持将它们纳入编译过程。

包含UDF的源文件在Fluent中可进行解释或编译。

①对于解释型UDF,源文件在run time处通过单步流程直接解释并加载。

②对于编译型UDF,该过程包含两个独立步骤:首先构建共享目标代码库,随后将其加载到Fluent中。

经过解释或编译后,UDF将在Fluent对话框中变为可见且可选,并可通过在相应对话框中选择函数名称挂载至求解器。

总而言之,用户自定义函数(UDF):

①是用C(版本C99或更早)或C++编程语言编写的。

②必须使用由Fluent提供的DEFINE宏进行定义。

③必须包含对udf.h文件的include语句

④使用预定义的宏和函数访问Fluent求解器数据并执行其他任务。

⑤是作为解释执行还是编译执行的函数。

⑥通过图形用户界面对话框连接到Fluent求解器。

重要提示:

Fluent根据文件扩展名自动设置编译器标志。*.c文件必须使用C99早版本编写,*.cpp文件专用于C++代码,而头文件始终使用*.h扩展名(与所有语言无关)。

②确保遵循的C++标准得到编译器的支持。Fluent安装包中包含的Clang编译器(版本10.0.0)支持C++17标准。

1.2 局限性

UDF具有以下限制:

①尽管Fluent中的UDF功能能够满足广泛的应用需求,但并非所有应用都能通过UDF解决。UDF无法访问所有求解变量或Fluent模型。

UDF使用并返回以SI单位指定的值,除非在特殊说明的情况下(如UNIVERSAL_GAS_CONSTANT)会有例外。

③如果Fluent未以UNC模式启动,且主机和节点进程可能在远程机器上启动,则无法加载UDF

Fluent的默认串行版本(也称为-t1)与主机进程和单个计算节点进程交互,因此所有用户自定义函数(UDF)都需要为并行使用而编写。

1.3 使用DEFINE宏定义UDF

UDF(用户定义函数)使用Fluent提供的函数声明进行定义。这些函数声明在代码中通过宏实现,本文档中统称为DEFINE宏。DEFINE宏的定义包含在udf.h头文件中。

DEFINE宏的一般格式为:

DEFINE_MACRONAME (udf_name, passed-in variables)

括号中的第一个参数是提供的UDF名称。参数名称区分大小写,必须使用小写字母指定。当函数被解释或编译后,为UDF命名的名称将在Fluent的下拉列表中可见。

重要提示:

UDF名称必须保持唯一,以避免与Fluent内部同名函数发生冲突。否则,链接器可能会选择错误的函数。确保名称唯一性的简便方法是在每个函数名前添加my_前缀,例如my_adjustmy_is_point_in_cell

DEFINE宏的第二组输入参数是从Fluent求解器传递到函数中的变量。

例如:

DEFINE_PROFILE(inlet_x_velocity, thread, index)

定义了一个名为inlet_x_velocity的边界剖面函数,该函数包含两个变量:threadindex,这些变量从Fluent传入函数。这些传入的变量是边界条件区域ID(作为指向thread的指针)和用于标识待存储变量的索引。在UDF完成解释或编译后,其名称(inlet_x_velocity)将在Fluent相应的边界条件对话框(例如速度入口)的下拉列表中可见并可供选择。

重要提示:使用UDF

DEFINE宏的所有参数都必须放在源代码的同一行。将DEFINE语句拆分成多行会导致编译错误。

②宏(例如DEFINE_PROFILE)与参数的首个括号之间不得留有空格,否则在Windows系统中将引发错误。

③不要在源代码的注释中包含DEFINE宏语句(例如DEFINE_PROFILE)。这会导致编译错误。

1)在源文件中包含udf.h头文件

udf.h头文件包含:

DEFINE宏的定义;

②包含CC++库函数头文件的编译器指令;

③头文件(例如mem.h)用于其他Fluent提供的宏和函数。

因此,必须使用#include编译器指令在每一个UDF源代码文件的开头包含udf.h文件:

#include"udf.h"

例如,当包含前一节中DEFINE语句的源文件中包含了udf.h时:

#include"udf.h"DEFINE_PROFILE(inlet_x_velocity, thread, index)

编译时,该宏将展开为:

voidinlet_x_velocity(Thread *thread, int index)

可以使用/**/来注释掉不想读取的UDF代码片段。注释命令必须放置在适当的位置:

/*DEFINE_ON_DEMAND(unique-name){printf("testing\n");}*/

注意:

由于宏预处理器扩展,无法注释掉函数参数的部分。因此,不允许以下情况:

DEFINE_PROFILE(inlet-x_velocity, /*name must be unique*/thread, /*face thread*/index)/*which variable of the boundary condition*/

1.4 解释与编译UDF

包含UDF的源代码文件在Fluent中可进行解释或编译。两种方式都会对函数进行编译,但源代码的编译方式及编译过程生成的代码在这两种方法中存在差异。

1)编译型UDF

编译型UDF的构建方式与Fluent可执行文件本身的构建方式相同:通过Makefile脚本调用系统CC++编译器来构建目标代码库。只需在“编译型UDF”对话框中点击“构建”即可启动此操作。目标代码库包含用高级CC++源代码编写的本地机器语言翻译版本。随后必须通过称为“动态加载”的进程,在运行时将共享库加载到Fluent中。只需在“编译型UDF”对话框中点击“加载”即可启动此操作。目标代码库不仅与所使用的计算机体系结构相关,还与正在运行的特定版本Fluent可执行文件密切相关。因此,每当升级Fluent、计算机操作系统层级变更或在不同类型的计算机上运行作业时,都必须重新构建这些库。

总而言之,编译型UDF通过图形用户界面采用两步流程从源文件进行编译。该流程通过“编译型UDF”对话框实现:首先从源文件构建共享库对象文件,随后将刚构建的共享库加载到Fluent中。

2)解释型UDF

解释型UDF通过图形用户界面从源文件进行解释,但采用单步处理流程。该流程发生在运行阶段,通过“解释型UDF”对话框实现源文件的解释操作。

Fluent内部,源代码通过C语言预处理器被编译成一种与架构无关的中间机器代码。当用户自定义函数(UDF)被调用时,该机器代码会在内部模拟器或解释器上执行。这层额外的代码会导致性能损失,但使得解释型UDF能够在不同架构、操作系统和Fluent版本间无缝共享。若执行速度成为问题,解释型UDF无需修改即可随时以编译模式运行。

用于解释型UDF的解释器不具备C语言标准编译器(用于编译型UDF)的全部功能,也不支持所有并行UDF宏。

注意:在某些情况下,可能会遇到与Fluent自带的C语言预处理器CPP)相关的解释型UDF错误。作为解决方案,可以在解释型UDF对话框的CPP命令名字段中输入系统预处理器的完整路径,例如:/usr/bin/cppgcc -E(仅限Linux系统)。

3)解释型与编译型UDF之间的差异

解释型和编译型UDF的主要区别在于,解释型UDF无法通过直接结构引用访问Fluent求解器据;它们只能通过Fluent提供的宏间接访问数据。

解释型和编译型UDF之间的差异如下:

1)解释型UDF

①可移植到其他平台;

均可作为编译型UDF运行;

③不需要C编译器;

④比编译型UDF运行速度慢;

受限于支持的C语言使用范围

⑥无法使用C++语言编写

⑦无法链接到已编译的系统库或用户库;

⑧可以只能使用预定义的宏访问存储在Fluent中的数据。

2)编译型UDF

①执行速度比解释型UDF快;

②在使用支持的CC++编程语言方面不受限制;

③可以调用其他语言编写的函数(具体细节取决于系统和编译器);

④如果包含解释器无法处理的某些C语言元素,则不一定能作为解释UDF运行;

3)因此,在Fluent模型中决定使用哪种类型的UDF时:

对于小型、简单的函数,使用解释型UDF;对于复杂的函数,如具有显著的CPU需求时(例如,每次迭代在每个单元格上都会被调用的属性UDF,或需要访问共享库时,使用编译的UDF

参考资料:《Ansys Fluent UDF Manual》 2023R1

特别感谢您的阅读、点赞、转发、推荐!

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » Ansys Fluent文档-UDF篇:用户自定义函数概述(UDFs)(一)

评论 抢沙发

6 + 8 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮