ANSYS Fluent 能够求解自定义标量输运方程。本文描述在 Fluent 中求解自定义标量方程需要使用的一些 UDF 宏。
对于用户在 ANSYS Fluent 模型中指定的每个标量方程,可以为标量输运方程中的扩散系数、通量以及瞬态项提供单独的 UDF 进行指定。对于多相流问题,用户还可以为每一相指定 UDF。另外,用户还可以利用 UDF 为标量方程指定源项以及边界条件。
1. 扩散系数
用户可以利用 UDF 为流体或固体材料指定各向同性或各向异性的扩散系数。
各相同性扩散系数通过 UDF 宏 DEFINE_DIFFUSIVITY 指定,而各向异性则使用 UDF 宏 DEFINE_ANISOTROPIC_DIFFUSIVITY 进行定义。
2. 通量
利用 UDF 宏 DEFINE_UDS_FLUX 来指定通量。
3. 源项
UDS 中的源项采用 UDF 宏 DEFINE_SOURCE 进行指定,定义方式与普通的源项定义方式相同。
4. 边界条件
与一般的边界定义相同,UDS 中采用 DEFINE_PROFILE 宏来指定边界条件。
宏 DEFINE_ANISOTROPIC_DIFFUSIVITY 用于定义各相异性扩散系数。
DEFINE_ANISOTROPIC_DIFFUSIVITY(name,c,t,i,dmatrix)
宏参数包括:
name:宏名称,可以随便定义,symbol
类型
c:网格单元索引,由 Fluent 传入。cell_t
类型
t:网格索引指针,由 Fluent 传入。Thread *
类型
i:标量索引。int
类型
dmatrix:一个 real 类型的数组,其定义为real dmatrix[ND_ND][ND_ND]
返回值:void
该宏利用 dmatrix 返回扩散系数数据,因此在程序中要为 dmatrix 赋值,对于二维问题,dmatix 是一个 2x2 的数组,对于三维问题,则是一个 3x3 的数组。
The following UDF, named cyl_ortho_diff computes the anisotropic diffusivity matrix for a cylindrical shell which has different diffusivities in radial, tangential, and axial directions
/***************************************************************
Example UDF that demonstrates DEFINE_ANISOTROPIC_DIFFUSIVITY
***************************************************************/
#include "udf.h"
/* Computation of anisotropic diffusivity matrix for
* cylindrical orthotropic diffusivity */
/* axis definition for cylindrical diffusivity */
static const real origin[3] = {0.0, 0.0, 0.0};
static const real axis[3] = {0.0, 0.0, 1.0};
/* diffusivities in radial, tangential and axial directions */
static const real diff[3] = {1.0, 0.01, 0.01};
DEFINE_ANISOTROPIC_DIFFUSIVITY(cyl_ortho_diff,c,t,i,dmatrix)
{
real x[3][3]; /* principal direction matrix for cell in cartesian coords. */
real xcent[ND_ND];
real R;
C_CENTROID(xcent,c,t);
NV_VV(x[0],=,xcent,-,origin);
#if RP_3D
NV_V(x[2],=,axis);
#endif
#if RP_3D
R = NV_DOT(x[0],x[2]);
NV_VS(x[0],-=,x[2],*,R);
#endif
R = NV_MAG(x[0]);
if (R > 0.0)
NV_S(x[0],/=,R);
#if RP_3D
N3V_CROSS(x[1],x[2],x[0]);
#else
x[1][0] = -x[0][1];
x[1][1] = x[0][0];
#endif
/* dmatrix is computed as xT*diff*x */
dmatrix[0][0] = diff[0]*x[0][0]*x[0][0]
+ diff[1]*x[1][0]*x[1][0]
#if RP_3D
+ diff[2]*x[2][0]*x[2][0]
#endif
;
dmatrix[1][1] = diff[0]*x[0][1]*x[0][1]
+ diff[1]*x[1][1]*x[1][1]
#if RP_3D
+ diff[2]*x[2][1]*x[2][1]
#endif
;
dmatrix[1][0] = diff[0]*x[0][1]*x[0][0]
+ diff[1]*x[1][1]*x[1][0]
#if RP_3D
+ diff[2]*x[2][1]*x[2][0]
#endif
;
dmatrix[0][1] = dmatrix[1][0];
#if RP_3D
dmatrix[2][2] = diff[0]*x[0][2]*x[0][2]
+ diff[1]*x[1][2]*x[1][2]
+ diff[2]*x[2][2]*x[2][2]
;
dmatrix[0][2] = diff[0]*x[0][0]*x[0][2]
+ diff[1]*x[1][0]*x[1][2]
+ diff[2]*x[2][0]*x[2][2]
;
dmatrix[2][0] = dmatrix[0][2];
dmatrix[1][2] = diff[0]*x[0][1]*x[0][2]
+ diff[1]*x[1][1]*x[1][2]
+ diff[2]*x[2][1]*x[2][2]
;
dmatrix[2][1] = dmatrix[1][2];
#endif
}
DEFINE_UDS_FLUX 宏用于指定 UDS 中对流项的计算方式。
DEFINE_UDS_FLUX(name, f, t, i)
宏参数:
name
:宏名称
f
:面索引,由 Fluent 传入,类型为face_t
t
:面线索指针,由 Fluent 传入,数据类型为Thread *
i
:标量索引,int
类型,由 Fluent 传入
函数返回 :real
DEFIEN_UDS_FLUX 宏包括四个参数,其中 name 由用户指定,f,t,i 由 Fluent 传入。该宏需要利用 return 显式返回值。
微分形式的传输方程对流项通常具有以下的通用形式:
$\nabla \cdot \vec{\psi} \phi$
式中,$\phi$为用于自定义的守恒标量,$\vec{\psi}$为向量场。默认情况下的对流项中,$\vec{\psi}$为密度与速度向量的乘积:
$\vec{\psi}_{\text {default}}=\rho \vec{v}$
使用宏 DFFINE_UDS_FLUX 定义对流项时,UDF 必须返回标量值$\vec{\psi} \cdot \vec{A}$,其中 $\vec{A}$ 为面法向方向的投影面积。
UDF 提供的通量场应当满足连续方程。意味着离散条件下每一个单元的通量之和应当为零。
在 UDF 中需要计算 $\vec{\psi}$,利用 Fluent 提供的预制宏计算速度及密度等参数,如下面的代码片段:
sample C source code that computes dot product of psi and A
Note that this is not a complete C function
**********************************************************************/
real NV_VEC(psi), NV_VEC(A); /* declaring vectors psi and A */
/* defining psi in terms of velocity field */
NV_D(psi, =, F_U(f,t), F_V(f,t), F_W(f,t));
NV_S(psi, *=, F_R(f,t)) /* multiplying density to get psi vector */
F_AREA(A,f,t) /* face normal vector returned from F_AREA */
return NV_DOT(psi,A); /* dot product of the two returned */
如果要求解多个标量,则可以在UDF中使用条件IF语句为每个i定义不同的通量函数。i=0与uds-0(要求解的第一个标量方程)相关联。DEFINE_UDS_UNSTEADY
可以利用 DEFINE_UDS_UNSTEADY 宏自定义标量方程的瞬态项:
DEFINE_UDS_UNSTEADY(name, c, t ,i ,apu ,su)
参数定义:
symbol name
:自定义的 UDF 名称
cell_t c
:网格索引
Thread *t
:网格索引指针
int i
:标量方程索引
real *apu
:中间系数指针
real *su
:源项指针
返回值:void
宏 DEFINE_UDS_UNSTEADY 包含 6 个参数,其中 name 为用户提供,c,t,i 由 Fluent 传入,在 UDF 中需要设定参数 apu 及 su 的值。
在 ANSYS Fluent 中,瞬态项被分解为源项 su 和中间系数项 apu:
$\begin{aligned} \text { unsteadyterm } &=-\int \frac{\partial}{\partial t}(\rho \phi) d V \\ & \approx-\left[\frac{(\rho \phi)^{n}-(\rho \phi)^{p-1}}{\Delta t}\right] \cdot \Delta V \\ &=-\frac{\rho \Delta V}{\Delta t} \phi^{n}+\frac{\rho \Delta V}{\Delta t} \phi^{n-1} \end{aligned}$
式中第一项为 apu,第二项为 su。
如下面的代码片段:
DEFINE_UDS_UNSTEADY(my_uds_unsteady,c,t,i,apu,su)
{
real physical_dt, vol, rho, phi_old;
physical_dt = RP_Get_Real("physical-time-step");
vol = C_VOLUME(c,t);
rho = C_R_M1(c,t);
*apu = -rho*vol / physical_dt;/*implicit part*/
phi_old = C_STORAGE_R(c,t,SV_UDSI_M1(i));
*su = rho*vol*phi_old/physical_dt;/*explicit part*/
}
FLUENT calculates the gradient of flow in a cell (based on the divergence theory) and stores this value in the variable identified by the suffix _G. For example cell temperature is stored in the variable C_T, and the temperature gradient of the cell is stored in C_T_G. The gradients stored in variables with the _G suffix are non-limited values and if used to reconstruct values within the cell (at faces, for example), may potentially result in values that are higher (or lower) than values in the surrounding cells. Therefore, if your UDF needs to compute face values from cell gradients, you should use the reconstruction gradient (RG) values instead of non-limited gradient (G) values. Reconstruction gradient variables are identified by the suffix _RG, and use the limiting method that you have activated in your FLUENT model to limit the cell gradient values.
Note that gradient variables are available only when the equation for that variable is being solved.
For example, if you are defining a source term for energy, your UDF can access the cell temperature gradient (using C_T_G), but it can not get access to the x-velocity gradient (using C_U_G). The reason for this is that the solver continually removes data from memory that it doesn't need. In order to retain the gradient data (when you want to set up user-defined scalar transport equations, for example), you can prevent the solver from freeing up memory by issuing the text command solve/set/expert
and then answering yes to the question Keep temporary solver memory from being freed?
. Note that when you do this, all of the gradient data is retained, but the calculation requires more memory to run.
最近我也测试了使用DEFINE_ADJUST宏来获得某一变量的二阶导数。心得如下:
- 梯度变量在FLUENT计算过程中是暂存变量,计算完成后将自动释放。如果要获取,需使用如下方法强制求解器保存梯度变量已供后用:
在FLUENT主窗中输入:solve/set/expert
,出现的是否保存梯度变量询问语句回答为yes - 梯度变量在首次计算中是不存在的。即使在计算之前,UDS已经使用一定方法进行过初始化,UDS_G仍将是空值,在第一步计算时内存中不存在这一变量,因此无论如何设置,第一步计算都不能调用C_UDSI_G宏。计算进行了一步或更多步之后才可以。
- C_UDSI_G调出的变量并不一定是内部计算使用的梯度值。在某些复杂边界处,Fluent内部有其他未公开的处理函数,C_UDSI_G只在计算区域中的绝大部分里非常接近内部计算使用的梯度值。