一、问题背景
因为对Reserve_User_Memory_Vars这个函数比较陌生,在学习官方文档过程中发现难以理解,于是只好亲手在fluent 2022上测试一番。
直接上结论:
此保留函数运行一次后(设置GUI界面中的UDM数目+第一次加载共享库成功),再如何运行都不会产生保留效果,因此我估计fluent中目前最多加载两个共享库。
二、测试1:
在官方2023的二次开发文档中,如下是保留函数功能的示范性代码。
/* general FLUENT header files */
#include "udf.h"
#include "para.h"
#include "mem.h"
static int udm_offset = UDS_UNRESERVED;
#define N_TESTLIB_UDS 2
#define NUM_UDM 4
DEFINE_EXECUTE_ON_LOADING(on_loading, libname)
{
// if I_AM_NODE_ZERO_P
// {
if (udm_offset == UDM_UNRESERVED)
udm_offset = Reserve_User_Memory_Vars(NUM_UDM);
if (udm_offset == UDM_UNRESERVED)
Message("\nDefine %d extra UDMs in GUI and reload %s\n,and the UDM_UNRESERVED is %d\n", NUM_UDM, libname, UDS_UNRESERVED);
else
{
Message("%d UDMs have been reserved by the current "
"library %s\n", NUM_UDM, libname);
Set_User_Memory_Name(udm_offset,"lib1-UDM-0");
Set_User_Memory_Name(udm_offset+1,"lib1-UDM-1");
Set_User_Memory_Name(udm_offset+2,"lib1-UDM-2");
}
Message("\nUDM Offset for Current Loaded Library = %d",udm_offset);
// }
}
DEFINE_ON_DEMAND(set_udms)
{
Domain *d;
Thread *ct;
cell_t c;
int i;
d=Get_Domain(1);
if(udm_offset != UDM_UNRESERVED)
{
Message("Setting UDMs\n");
for (i=0; i<NUM_UDM; i++)
{
thread_loop_c(ct,d)
{
begin_c_loop(c,ct)
{
C_UDMI(c,ct,udm_offset+i)=2.0+i/10.0;
}
end_c_loop(c,ct)
}
}
}
else
Message("UDMs have not yet been reserved for library 1\n");
}
在on loading宏里面,首先进行第一个if判断,由于初始化时将udm_offset变量赋值为UDS_
UNRESERVED(此预定义宏在sg_udms.h中定义,取值恒为-1),也即-1,所以判定为真,会执行保留函数。
但是保留函数会对UDMs进行判断,如果用户并没有在GUI界面中如下图所示设置UDM的数目,那么保留函数并不会生效。
因此还会进入第2个if判断,从而弹出错误——Define xx extra UDMs in GUI and reload xx1,and the UDM_UNRESERVED is xx。意思是说需要在GUI界面定义至少xx1个UDM.
因此我们在GUI界面中定义UDM后,再返回重新加载libudf共享库。
这次没有报错,console中输出信息如下(本人将NUM_UDM宏改成4了)。之所以会输出这么多条message,是因为本人用的是并行UDF,每条对应1个计算节点/核心。
4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
UDM Offset for Current Loaded Library = 0 4 UDMs have been reserved by the current library libudf
我们可以看出执行保留函数后,UDM Offset变量被复制为NUM_UDM的取值,因此得以进入else语句输出【4 UDMs have been reserved by the current library libudf】
而我们再重新编译一份UDF,代码和上面的差不多,命名为libudf2,加载过程中发现这次保留函数压根就没有生效。
/* general FLUENT header files */
#include "udf.h"
#include "mem.h"
static int udm_offset = UDS_UNRESERVED;
#define N_TESTLIB_UDS 2
#define NUM_UDM 4
DEFINE_EXECUTE_ON_LOADING(on_loading, libname)
{
if (udm_offset == UDM_UNRESERVED)
udm_offset = Reserve_User_Memory_Vars(NUM_UDM);
if (udm_offset == UDM_UNRESERVED)
Message("\nDefine %d extra UDMs in GUI and reload %s\n,and the UDM_UNRESERVED is %d\n", NUM_UDM, libname, UDS_UNRESERVED);
else
{
Message("%d UDMs have been reserved by the current "
"library %s\n", NUM_UDM, libname);
Set_User_Memory_Name(udm_offset,"lib2-UDM-0");
Set_User_Memory_Name(udm_offset+1,"lib2-UDM-1");
Set_User_Memory_Name(udm_offset+2,"lib2-UDM-2");
}
Message("\nUDM Offset for Current Loaded Library = %d",udm_offset);
}
DEFINE_ON_DEMAND(set_udms)
{
Domain *d;
Thread *ct;
cell_t c;
int i;
d=Get_Domain(1);
if(udm_offset != UDM_UNRESERVED)
{
Message("Setting UDMs\n");
for (i=0; i<NUM_UDM; i++)
{
thread_loop_c(ct,d)
{
begin_c_loop(c,ct)
{
C_UDMI(c,ct,udm_offset+i)=2.0+i/10.0;
}
end_c_loop(c,ct)
}
}
}
else
Message("UDMs have not yet been reserved for library 2\n");
}
上面是libudf1的代码
下面是console中的输出信息,可以看出这次保留函数并没有生效。
UDF Autorun:
on_loading
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Done.
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
UDM Offset for Current Loaded Library = -1
Define 4 extra UDMs in GUI and reload libudf1
,and the UDM_UNRESERVED is -1
三、测试2:在加载libudf之后执行demand宏,再加载libudf1
官方文档中如是言:
Note:that the on demand UDF must be executed after the solution is initialized to reset the initial values
for the UDMs.
中文:注意demand udf必须在求解器初始化之后被执行以初始化UDM数值。
于是乎我这次没直接加载libudf1,而是在加载libudf之后执行demand宏,再加载libudf1。
结果仍然没有变化,保留函数仍然没有生效。
四、测试3:修改UDM的数目后再加载
我怀疑是不是每加载一次共享库就需要重新确定GUI界面中的Number of User-Defined Memory Locations。
于是我更改了数目(情况1),或者直接点开这个对话框不修改数目(情况2),再次确定。
这两种情况都已经测试,结果相同,都还是出现上面的问题。
五、无关紧要的并行化测试
其实在中途,我还将# if RP_NODE宏和# if RP_HOST宏包裹住on loading的主干部分,以免输出太多同质化信息让我眼花缭乱。
但是我发现,不管让这个主干代码在host中执行、还是在node中执行、还是在node0中执行,最后都会在加载过程中卡住不动。
于是我无奈只好更改为不使用编译器指令——诸如# if RP_HOST等宏。