本文以案例形式演示将串行UDF代码改造为并行UDF代码。
前面的案例中,一些代码只能运行在串行模式或单CPU模式中,为了提高计算效率,有必要将串行代码改造为并行代码以使其运行于并行模式下。
1 代码改造
以前面案例中的DEFINE_ADJUST代码为例,描述如何将串行代码改写为并行代码。原始的串行代码如下所示。
DEFINE_ADJUST(post_adjust, d)
{
real T_min = REAL_MAX, T_max = 0.0;
Thread *t;
cell_t c;
if (N_UDM < 1)
{
Message0("n Error: No UDM defined! Abort UDF execution.n");
return;
}
thread_loop_c(t, d){
begin_c_loop(c, t){
C_UDMI(c, t, 0) = C_T(c, t) - 273.15;
if (C_T(c, t) < T_min)
T_min = C_T(c, t);
if (C_T(c, t) > T_max)
T_max = C_T(c, t);
}
end_c_loop(c, t)
}
T_min -= 273.15;
T_max -= 273.15;
Message0(" Minimum temperature = %.1f degCtMaximum temperature = %.1f degCn", T_min, T_max);
}
改造过程包括:
-
将求解数据放到计算节点中。
这可以利用预处理命令#if !RP_HOST
来实现。
DEFINE_ADJUST(post_adjust, d)
{
real T_min = REAL_MAX, T_max = 0.0;
#if !RP_HOST
Thread *t;
cell_t c;
#endif
利用宏RP_HOST
将求解数据放置在计算节点中。
-
N_UDM在所有节点上是等同的,因此无需放置到node节点中。注意代码中的 Message0
宏仅运行在node0节点上,这里不可以使用Message
宏,除非将其放到Node节点中。
DEFINE_ADJUST(post_adjust, d)
{
real T_min = REAL_MAX, T_max = 0.0;
#if !RP_HOST
Thread *t;
cell_t c;
#endif
if (N_UDM < 1)
{
Message0("n Error: No UDM defined! Abort UDF execution.n");
return;
}
-
循环遍历只能在Node节点中进行,不可以在Host节点中运行。
#if !RP_HOST
thread_loop_c(t, d){
begin_c_loop_int(c, t){
C_UDMI(c, t, 0) = C_T(c, t) - 273.15;
if (C_T(c, t) < T_min)
T_min = C_T(c, t);
if (C_T(c, t) > T_max)
T_max = C_T(c, t);
}
end_c_loop(c, t)
}
#endif
注意这里将begin_c_loop
修改为了begin_c_loop_int
,明确指定在内部网格中进行遍历。
-
全局约简
代码需要从全局区域中寻找最大最小温度值,因此需要进行全局约简。利用全局约简宏PRF_GRLOW1
与PRF_GRHIGH1
获取全局区域范围的最小最大值。
T_min = PRF_GRLOW1(T_min);
T_max = PRF_GRHIGH1(T_max);
-
数据传递
计算节点需要将数据传递给Host节点,利用宏node_to_host_real
来完成。
node_to_host_real_2(T_min,T_max);
T_min -= 273.15;
T_max -= 273.15;
-
在Host节点上输出信息
前面已经将计算数据发送至Host节点,因此这里在Host节点上输出信息。注意使用的是
Message
宏。
#if !RP_NODE
Message(" Minimum temperature = %.1f degCtMaximum temperature = %.1f degCn", T_min, T_max);
#endif
修改完毕后的完整代码如下所示。
DEFINE_ADJUST(post_adjust, d)
{
real T_min = REAL_MAX, T_max = 0.0;
#if !RP_HOST
Thread *t;
cell_t c;
#endif
if (N_UDM < 1)
{
Message0("n Error: No UDM defined! Abort UDF execution.n");
return;
}
#if !RP_HOST
thread_loop_c(t, d)
{
begin_c_loop_int(c, t)
{
C_UDMI(c, t, 0) = C_T(c, t) - 273.15;
if (C_T(c, t) < T_min) T_min = C_T(c, t);
if (C_T(c, t) > T_max) T_max = C_T(c, t);
}
end_c_loop(c, t)
}
#endif
T_min = PRF_GRLOW1(T_min);
T_max = PRF_GRHIGH1(T_max);
node_to_host_real_2(T_min, T_max);
T_min -= 273.15;
T_max -= 273.15;
#if !RP_NODE
Message(" Minimum temperature = %.1f degCtMaximum temperature = %.1f degCn", T_min, T_max);
#endif
}
2 代码测试
-
多核CPU并行启动Fluent
-
编译并加载UDF
-
计算信息如下图所示
-
温度云图如下图所示
可以看出,采用多核CPU并行计算,经过改造后的UDF代码能够正确地实现其功能。
案例相关文件下载:
本篇文章来源于微信公众号: CFD之道
评论前必须登录!
注册