正文共:2055 字 10 图 预计阅读时间: 6 分钟
1 前言
前几天有读者问到如何用UDF调用某个点的温度,以便于其他的使用目的。大家知道,单单读取点的数据是很容易的事情,UDF调用却不太容易。趁着周末挤出一点时间做一个案例,希望对这位读者以及大家有一定的参考价值。
2 问题描述与解决思路
这里沿用我五一节做的那个案例(图片如下),假设我要读取(0.5,0.1)这个点的温度值,UDF怎么操作呢?需要说明的是,我提出的这个处理思路绝对不是最好最准确的,但是在一定精度范围内应该是没问题的,另外其可靠性还需要读者自行去深入验证。
图1 五一快乐
这个问题很早以前我就思考过,最终都没有写出直接读取某个点的温度值的UDF代码。后来我从间接的角度想,如果我们钻牛角尖,实际情况下,测量某个点的温度能测到吗?一个点是没有任何体积的,即使我们使用温度探头去测量,探头严格上将也不算是一个点,实际上我们测得的温度应该是目标位置“点”周围很小区域的平均温度。而且通常情况下,这个点的温度和周围很小区域的温度相差很小了。因此我用一个足够小的球体去近似这个点的温度就可以了,问题就转化为计算某个区域的平均温度,这个UDF代码就很好编写了。为了更好的说明问题,我用了UDM来存储温度值(球体区域内的存储值为实际温度,区域之外为0),并与关心的“点”温度进行对比。如前所述,我们关心的点(0.5,0.1),用一个球体去逼近,关键的语句为:
sqrt(pow(xx-0.5,2)+pow(yy-0.1,2))<=ε,具体的逼近程度由ε来控制,本案例取0.002。关键的问题在于,这个取值既不能过小也不能过大,过小将会无结果,过大的话就好理解了,一个大的区域温度和其中一个点的温度就未必相等了。为什么ε取值过小会没有结果呢?我们先看一下FLUENT的网格数据,如下图,单元(cell)中心为FLUENT场数据存储位置,其他位置的数据通过插值计算。如果ε取值过小,球体区域未把cell中心包围,那么就获取不了数据,如果是计算体积加权平均温度的话可能得到无穷数,因为没有cell体积值。当然了,如果我们关心的点正好在cell中心,那么就一定可以获取数据了,但是这个要求太苛刻了,因此我们要用一个足够大的区域去包含。实际操作时,尝试不同的值,直至区域平均温度和实际的“点”温度几乎相等即可。
图2 FLUENT数据存储结构
根据上面所述,我们取ε=0.0001,测试计算结果如下图,可以看出UDM没有存储到任何温度数据,因此都等于0,同时UDF读取不到体积值,因此体积加权平均温度计算结果出现无穷数。
图3 ε取值过小的结果
我们取ε=0.002,测试计算结果如下图,可以看出,此时UDM已经读取了温度值,并且平均温度和实际“点”温度相对误差为几近等于0。
图4 ε取值合适的结果
我们再取ε=0.05,测试计算结果如下图,可以看出此时的平均温度和实际的点温度一样很接近,这是因为本身区域的温度分布均匀性很好了,如果温度分布均匀性差的话,误差就很大了,这个很好理解。
图5ε取值过大的结果
说明
以上的计算结果还没有收敛,只是迭代了几步,但是对于我们分析的问题没有影响。文末附上相关的UDF代码,我就不一一解释了,相信读者可以很容易理解的。以上的思路希望对读者有所启发,如果您觉得不错,可以点个赞~~~
附录 本案例使用的UDF代码
#include "udf.h"
#include "prop.h"
DEFINE_SOURCE(ptemperature,c,t,dS,eqn)
{
real x[ND_ND];
real xx;
real yy;
0.0; =
0; =
C_CENTROID(x,c,t);
xx=x[0];
yy=x[1];
0.05) =
C_T(c,t)-273.15; =
0; =
return source;
}
DEFINE_ADJUST(ptcal,d)
{
Thread *t;
cell_t c;
real x[ND_ND];
real xx;
real yy;
0; =
0; =
0; =
thread_loop_c (t,d)
{
begin_c_loop (c,t)
{
C_CENTROID(x,c,t);
xx=x[0];
yy=x[1];
0.05) =
{
C_UDMI(c,t,0)*C_VOLUME(c,t); =
C_VOLUME(c,t); =
}
}
end_c_loop (c,t)
}
tpm=sumtp/count;
printf(" the garget sumtemperature is %f ",sumtp);
printf(" the garget volume is %f ",count);
printf(" the garget point temperature is %f ",tpm);
}