1. ADJUST的适用性
DEFINE_ADJUST是一个通用宏,可用于调整或修改未作为参数传递的Fluent变量。
也就是说DEFINE_ADJUST与之前的DEFINE_PROFILE和DEFIEN_PROPERTY不同,这两个宏有特殊的目的,比如用于边界条件或者用于材料物性。
DEFINE_ADJUST没有这种特殊的目的性,它只是用于调节或者传递某些参数,它可以实现通用的功能。举个例子,DEFINE_PROFILE和DEFIEN_PROPERTY类似于语文和数学课代表,只在语文或者数学课堂上发挥作用,而DEFINE_ADJUST更像是班长,虽然不是课代表,但是却能够协调整个班级。
比如使用DEFINE_ADJUST宏可以计算出口流量的平均值,然后赋值给DEFINE_PROFILE宏,可以只定位某些特殊边界或者网格进行处理,甚至可以强制修改物理量(尽管这样会造成不收敛)。
2. ADJUST宏的用法
DEFINE_ADJUST (name, d)
name 宏的名称,如ergouzi
d 计算域Domain
return void
ADJUST宏适用灵活性很强,因此参数很少,很多必要的东西需要根据自己的情况编写代码。ADJUST宏每个迭代步执行一次,即使是瞬态也是每迭代步执行
name表示宏的名称;d为计算域,为此宏从fluent传递给用户的一个参数,可以直接使用。所谓计算域即fluent中的cell zone conditions。d实际上是一个结构体类似的数据,其中包含了大量的信息,使用时需要一层一层的获取。
贴个ChatGPT给的解释(其实这种解释并不够清楚):
此宏不返回任何内容,如果需要从此宏中获取一些数据,需要配合使用UDM宏。
3. ADJUST宏举例
3.1计算域物理量求和
下面的UDF,命名为my_adjust,计算了整个计算域的湍动能耗散率。
#include "udf.h"
DEFINE_ADJUST(my_adjust,d)
{
Thread *t;
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)
}
}
对代码解释一下:
Thread *t;//使用Thread声明的变量都被称为线程,线程也是一种结构体数据类型,包含大量的数据。实际上就是一系列cell和face的组合体。
cell_t c;//声明网格变量,整型,这个之前的文章提过多次,不细说
thread_loop_c(t,d)//这种宏只要带关键字loop,就说明这是一个循环;怎么循环的呢?后面的括号中两个参数t和d,基本的原则就是在后一个参数中循环前一个参数。比如这里应该是在d中循环t。
begin_c_loop(c,t)//利用上面的规则,这句话也是一个循环,在t中循环c,因此在 begin_c_loop(c,t)循环中的语句达到了c的层面,语句都是对cell进行操作。end_c_loop(c,t)与begin_c_loop(c,t)配套使用,表示循环结束。
sum_diss +=//+=是c语言的一种简写方式,等效于sum_diss =sum_diss +某个值。这就是一种迭加求和语句
C_D(c,t)//这种宏的基本特点以C_开头,表示是网格宏。此宏可获取湍动能耗散率;C_VOLUME(c,t)也是网格宏,可获取cell的体积。
3.2 获取face中心坐标
下面的宏命名为f_centroids,用于获取face的中心坐标
#include "udf.h"
DEFINE_ADJUST(f_centroids, domain)
{
real FC[2];
face_t f;
int ID = 1;
Thread *thread = Lookup_Thread(domain, ID);
begin_f_loop(f, thread)
{
F_CENTROID(FC,f,thread);
}
end_f_loop(f,thread)
}
代码解释
real FC[2];声明了一个数值变量,更为常见的写法是real FC[ND_ND],在二维情况下ND_ND=2,三维情况ND_ND=3
Thread *thread = Lookup_Thread(domain, ID);//声明线程thread,其中Lookup_Thread(domain, ID)是查找线程的宏,表示在domain域中查找ID为1的thread。
注:UDF中只要是ID,都可以在fluent界面直接看到,比如下图outlet的ID编号等于3。
begin_f_loop(f, thread)//按照上个例子的规则,这个宏是一个循环,表示对thread中的所有f进行遍历。实际上就是循环遍历ID编号为1的thread中的所有face。
F_CENTROID(FC,f,thread);//以F_开头的宏,face宏,可以获取face的物理量,比如速度、压力等。F_CENTROID表示获取face的中心坐标,将其赋值给FC数组。
如果要取出坐标值,可令x=FC[0];y=FC[1],这里的x和y需要声明变量;
4. UDF的编译与加载
编译型UDF界面如下图,上面有两个框Source Files和Header Files,Source Files表示源文件,就是编写好的UDF文件;
Header Files表示头文件,只有当UDF很复杂,为了使UDF模块化才需要从这里导入头文件。UDF自带了很多头文件如udf.h,但是这些头文件不需要从这里导入。
首先点击Add,选中编写好的UDF后导入,然后点击Build,如果UDF没有问题,则不会出现任何报错信息(只要控制界面有error,则说明有问题)。
在没有报错的前提下,点击Load,则UDF加载成功。关于UDF报错问题,建议大家看看文章四十九、五十和五十一。如果没有报错,控制台应该会显示下面的信息,其中就有各种DEFINE宏的name
5. UDF的使用
与之前介绍的PROPERTY宏不同,ADJUST宏需要hook使用。如果没有hook,即使ADJUST宏加载成功,也不能调用。
点击Function Hooks,会弹出所有需要hooks界面
下面的图中包含很多宏,即当使用这些DEFINE宏时,都必须hook才能正常使用。比如DEFINE_EXECUTE_AT_END、DEFINE_INIT等,对于ADJUST宏,需要先点击Adjust宏的Edit进行设置界面
选中编写好的UDF宏名称,点击Add,宏名称将从左栏转入到右栏,单击OK,则表示hook成功。当fluent计算时,ADJUST宏也会被执行