新浪博客

ANSYS FLUENT 13.0 UDF 手册 --并行设置

2017-10-07 03:08阅读:
7章介绍ANSYS FLUENT并行UDF设置及应用
l FLUENT并行概要
ANSYS FLUENT 并行求解器对大规模问题采用多核同步求解,或者单机或者分布式机群。并行求解首先将计算域划分,然后给每个子块的数据分配一个计算进程。每个计算节点同步对其分配到的数据执行相同的运算程序。主进程不负责网格单元、面、节点(除使用DPM共享内存模型),其主要负责Cortex命令解释(用户交互、图形相关函数的解析),然后再把这些命令传给其他计算节点。内部节点编号为: Host (compute Node-0), compute Node_1, compute Node-2, etc
相邻计算节点的计算域有一层单元的重叠来保证节点间通信。虽然单元、面都是按计算域划分的,但是全域信息,如单元编号,都是映射到每个计算节点上的,它按链表存储就和串行求解一样。最后,该并行计算(配置)支持大型并行机、多CPU核工作站、网络分布式集群。
l 分区网格中的单元和面
l 串行UDF的并行化
ANSYS FLUENT 串行求解器包含一个Cortex和唯一的一个
FLUENT 进程。然而,并行求解器包括三个可执行部分:Cortex, 主节点,从计算节点。并行运行ANSYS FLUENT,从Cortex开始,然后是一个主节点和若干个(n)从计算节点,即共有n+2个进程。因此,并行计算时,就需要保证函数可以分别在主、从节点上执行。当然,这不是说你必须写三个版本的UDF,然后分别在串行、主、从节点上跑。好的编程模式只写一个UDF,而编译生成任何想要的一个版本。这样的编程需要使用并行相关的宏文件以及编译指令(例如,#if RP_NODE, RP_HOST,PARALLEL),指引编译器对特定进程有用的UDF部分函数编译,而忽略其余。
基本要求是UDF必须是可并行的。所以,如果UDF执行的一个操作依赖于接受、发送其他计算节点的数据,那么这个UDF里有关全局规约的运算,比如全局求和、最值、某个操作需要使用相邻节点数据的等,就需要修改以支持并行。其他需要针对并行修正的串行程序还有:
读写文件
全域缩并
全域求和
全域最值
全域逻辑判断
单元、面的某些循环操作
信息显示
主从节点打印
l 离散相模型(DPM)UDF并行化
DPM可采用如下并行选项:
共享内存
消息传递
当使用DPM相关UDF时,这些UDF会在控制研究(对象)粒子的机器上执行,基于上述两种并行选择。因为在DPM模型中所有流体变量都存入追踪粒子的数据结构中,使用DPM UDF的并行不需要其他考虑了,除了并行写输出文件。这时,不允许使用C语言的fprintf函数,而要使用一个专为并行写文件操作定义的新函数。每个计算节点将各自信息写到各自独立文件里,最后再排序整合到一个文件。该新函数使用同fprintf的变量。这些文件的排序需要额外的一个参数列表。不使用排序函数 par_fprintf_head,就需要将排序信息填在输出文件的文件头。
par_fprintf_head('x-coordinate y-coordinate z-coordinate')
上述函数会自动将字符“ x-coordinate, y-coordinate, z-coordinate” 放到输出文件的文件头。
计算节点信息如下:
par_fprintf('%d %d %e %e %e', P_INJ_ID(P_INJECTION(p)), p->part_id,
P_POS(p)[0], P_POS(p)[1], P_POS(p)[2]);
额外参数P_INJ_ID(P_INJECTION(p))p- >part_id在并行方案中使用,但是不管串并行都必须有这两个参数。写入各自节点信息文件时这两个参数将被去掉。
注意,如果你需要得到其他数据,比如单元变量值。那么对消息传递方法,你将得到所有流体变量以及求解器相关变量。但是共享内存法,你只能得到在SV_DPM_LISTSV_DPMS_LIST中定义的变量。这些宏定义参考dmp.h
l UDF并行宏
编译指令宏
主从进程传递宏
谓词宏(逻辑判断宏)
全域归并宏
循环宏
分区单元ID、面ID
消息显示宏
消息传递宏
从节点消息传递宏
l 并行UDF缺点
PRINCIPAL_FACE_P只能用于并行UDFetc
l 进程标识
并行ANSYS FLUENT的每个进程都有一个唯一的整数标识号,它存在全局变量myid里。当在UDF里使用myid,它将返回当前计算节点的标识号。主进程ID node_host(=999999),存在全局变量node_hostNode_0节点标识号是0,对应全局变量node_zero. 并行ANSYS FLUENT的全局变量
int node_zero = 0;
int node_host = 999999;
int node_one = 1;
int node_serial = 1000000;
int node_last;
int compute_node_count;
int myid;

myid常用于IF条件语句。下面给出一个使用全局变量myid的例子。其中,总面数在一个面线程中通过累加求的。那么,如果myid不是0号计算节点(node_0,那么所有计算节点的面数豆浆通过PRF_CSEND_INT宏传给0号计算节点。
int noface=0;
begin_f_loop(f, tf)
{
noface++;
}
end_f_loop(f, tf)

#if RP_NODE if(myid!=node_zero)
{
PRF_CSEND_INT(node_zero, &noface, 1, myid);
}
#endif
l 并行UDF实例
#include 'udf.h'

DEFINE_ADJUST(face_av,domain)
{

int surface_thread_id=0;
real total_area=0.0;
real total_force=0.0;


#if !RP_HOST
Thread* thread;
face_t face;
real area[ND_ND];
#endif



#if !RP_NODE
surface_thread_id = RP_Get_Integer('pres_av/thread-id');
Message('Calculating on Thread # %d',surface_thread_id);
#endif






host_to_node_int_1(surface_thread_id);

#if RP_NODE Message('Node %d is calculating on thread # %d',myid,
surface_thread_id);
#endif

#if !RP_HOST

thread = Lookup_Thread(domain,surface_thread_id);
begin_f_loop(face,thread)




if (PRINCIPAL_FACE_P(face,thread))
{
F_AREA(area,face,thread);
total_area += NV_MAG(area);
total_force += NV_MAG(area)*F_P(face,thread);
}

end_f_loop(face,thread)
Message('Total Area Before Summing %f',total_area);
Message('Total Normal Force Before Summing %f',total_force);

# if RP_NODE
total_area = PRF_GRSUM1(total_area);
total_force = PRF_GRSUM1(total_force);
# endif

#endif


node_to_host_real_2(total_area,total_force);

#if !RP_NODE
Message('Total Area After Summing: %f (m2)',total_area);
Message('Total Normal Force After

我的更多文章

下载客户端阅读体验更佳

APP专享