欢迎光临散文网 会员登陆 & 注册

udf 中文手册 ANSYS FLUNT (3)

2023-04-04 17:20 作者:0牙膏0  | 我要投稿

UDF 第3写UDF

(翻译不易,辛苦点赞)

本章主要概述了如何在FLUENT写UDF。

3.1 概述

3.2写解释式UDF的限制

3.3 FLUENT中UDF求解过程的顺序

3.4 FLUENT网格拓扑

3.5 FLUENT数据类型

3.6 使用DEFINE Macros定义你的UDF

3.7在你的UDF源文件中包含udf.h文件

3.8 定义你的函数中的变量

3.9函数体

3.10 UDF 任务

3.11 为多相流应用写UDF

3.12在并行中使用你的UDF

3.1概述(Introduction

 

UDF是用来增强FLUENT代码的标准功能的,在写UDF之前,我们要明确以下几个基本的要求。首先,必须用C语言编写UDF。必须使用FLUENT提供的DEFINE宏来定义UDF。UDF必须含有包含于源代码开始指示的udf.h文件;它允许为DEFINE macros和包含在编译过程的其它FLUENT提供的函数定义。UDF只使用预先确定的宏和函数从FLUENT求解器访问数据。通过UDF传递到求解器的任何值或从求解器返回到UDF的值,都指定为国际(SI)单位。

总之,当写UDF时,你必须记住下面的FLUENT要求。UDF:

1.      采用C语言编写。

2.      必须为udf.h文件有一个包含声明。

3.      使用Fluent.Inc提供的DEFINE macros来定义。

4.      使用Fluent.Inc提供的预定义宏和函数来访问FLUENT求解器数据。

5.      必须使返回到FLUENT求解器的所有值指定为国际单位。

 

3.2写解释式UDF的限制(Restriction on Writing Interpreted UDF

无论UDF在FLUENT中以解释还是编译方式执行,用户定义C函数(说明在Section 3.1中)的基本要求是相同的,但还是有一些影响解释式UDF的重大编程限制。FLUENT解释程序不支持所有的C语言编程原理。解释式UDF不能包含以下C语言编程原理的任何一个:

1.      goto 语句。

2.      非ANSI-C原型语法

3.      直接的数据结构查询(direct data structure references)

4.      局部结构的声明

5.      联合(unions)

6.      指向函数的指针(pointers to functions)

7.      函数数组。

在访问FLUENT求解器数据的方式上解释式UDF也有限制。解释式UDF不能直接访问存储在FLUENT结构中的数据。它们只能通过使用Fluent提供的宏间接地访问这些数据。另一方面,编译式UDF没有任何C编程语言或其它注意的求解器数据结构的限制。

 

3.3 FLUENT求解过程中UDF的先后顺序(Sequencing of UDF in the FLUENT Solution Process

 

当你开始写UDF代码的过程时(依赖于你写的UDF的类型),理解FLUENT求解过程中UDF调用的内容或许是重要的。求解器中包含连接你写的用户定义函数的call-outs。知道FLUENT求解过程中迭代之内函数调用的先后顺序能帮助你在给定的任意时间内确定那些数据是当前的和有效的。

 

分离式求解器

 

在分离式求解器求解过程中(Figure 3.3.1),用户定义的初始化函数(使用DEFINE_INIT定义的)在迭代循环开始之前执行。然后迭代循环开始执行用户定义的调整函数(使用DEFINE_ADJUST定义的)。接着,求解守恒方程,顺序是从动量方程和后来的压力修正方程到与特定计算相关的附加标量方程。守恒方程之后,属性被更新(包含用户定义属性)。这样,如果你的模型涉及到气体定律,这时,密度将随更新的温度(和压力 and/or 物质质量分数)而被更新。进行收敛或者附加要求的迭代的检查,循环或者继续或停止。

 

耦合求解器

 

在耦合求解器求解过程中(Figure 3.3.2),用户定义的初始化函数(使用DEFINE_INIT定义的)在迭代循环开始之前执行。然后,迭代循环开始执行用户定义的调整函数(使用DEFINE_ADJUST定义的)。接着,FLUENT求解连续、动量和(适合的地方)能量的控制方程和同时地一套物质输运或矢量方程。其余的求解步骤与分离式求解器相同(Figure 3.3.1)。

Figure 3.3.2: Solution Procedure for the Coupled Solver

 

3.4 FLUENT 网格拓扑

 

在我们开始讨论FLUENT特殊的数据类型之前,你必须理解网格拓扑学的术语因为FLUENT数据类型是为这些实体定义的。下面是显示在Figure 3.4.1中的网格实体的定义。

   单元(cell)                      区域被分割成的控制容积

   单元中心(cell center)             FLUENT中场数据存储的地方

   面(face)                        单元(2D or 3D)的边界

   边(edge)                       面(3D)的边界

   节点(node)                     网格点

   单元线索(cell thread)            在其中分配了材料数据和源项的单元组

   面线索(face thread)             在其中分配了边界数据的面组

   节点线索(node thread)           节点组

   区域(domain)             由网格定义的所有节点、面和单元线索的组合

Figure   3.4.1: Grid Terminology

 

3.5 FLUENT数据类型

 

除了标准的C语言数据类型如real, int 等可用于在你的UDF中定义数据外,还有几个FLUENT指定的与求解器数据相关的数据类型。这些数据类型描述了FLUENT中定义的网格的计算单位(见Figure 3.4.1)。使用这些数据类型定义的变量既有代表性地补充了DEFINE macros的自变量,也补充了其它专门的访问FLUENT求解器数据的函数。

一些更为经常使用的FLUENT数据类型如下:

  cell_t

  face_t

  Thread

  Domain

  Node

cell_t是线索(thread)内单元标识符的数据类型。它是一个识别给定线索内单元的整数下标。face_t是线索内面标识符的数据类型。它是一个识别给定线索内面的整数下标。

Thread数据类型是 FLUENT中的数据结构。它充当了一个与它描述的单元或面的组合相关的数据容器。

Node数据类型也是FLUENT中的数据结构。它充当了一个与单元或面的拐角相关的数据容器。

Domain数据类型代表了FLUENT中最高水平的数据结构。它充当了一个与网格中所有节点、面和单元线索组合相关的数据容器。

!!注意,FLUENT中所有数据类型都是 情形敏感的(case-sensitive)。

3.6 使用DEFINE Macros定义你的UDF

 

Fluent.Inc为你提供了一套你必须使用它来定义你的UDF的预定义函数。这些定义UDF的函数在代码中作为宏执行,可在作为DEFINE(全部大写)宏的文献中查阅。对每个DEFINE 宏的完整描述和它的应用例子,可参考第四章。

DEFINE宏的通用格式为:

DEFINE_MACRONAME(udf_name, passed-in variables)

这里括号内第一个自变量是你的UDF的名称。名称自变量是情形敏感的必须用小写字母指定。一旦函数被编译(和连接),你为你的UDF选择的名字在FLUENT下拉列表中将变成可见的和可选的。第二套输入到DEFINE 宏的自变量是从FLUENT求解器传递到你的函数的变量。

在下面的例子中,宏

 DEFINE_PROFILE(inlet_x_velocity, thread, index)

用两个从FLUENT传递到函数的变量thread和index定义了名字为inlet_x_velocity的分布函数。这些passed-in变量是边界条件区域的ID(作为指向thread的指针)而index确定了被存储的变量。一旦UDF被编译,它的名字(例如,inlet_x_velocity)将在FLUENT适当的边界条件面板(例如,Velocity Inlet面板)的下拉列表中变为可见的和可选的。

!!注意,所有用于DEFINE宏的自变量必须放在你的源代码的同一行上。分割DEFINE的声明为几行可能导致编译错误。

3.7在你的UDF源文件中包含udf.h文件(Including the udf.h File in Your UDF Source File)

 

DEFINE 宏的定义位于称为udf.h(见附录A的列表)的头文件中。为了使DEFINE宏延伸到编译过程,你必须在你写的每个UDF源文件的开始包含udf.h 文件。

#include "udf.h"

 

/* Always include udf.h when writing a UDF. It translates the DEFINE */

/* and other macros into C, which is what the compiler understands.  */

通过在你的UDF源文件中包含udf.h,编译过程中所有的DEFINE宏的定义与源代码一起被包含进来。udf.h文件也为所有的C库函数头文件包含#include指示,与大部分头文件是针对Fluent提供的宏和函数是一样的(例如,mem.h)。除非有另外的指示,没必要在你的UDF中个别地包含这些头文件。

还有,当你编译你的UDF时,你不必放置udf.h的拷贝在你的当地目录下;一旦你的UDF被编译,FLUENT求解器会自动地从Fluent.Inc/fluent6.x/src/目录来读取udf.h文件。

举例

从前面部分的宏

DEFINE_PROFILE(inlet_x_velocity, thread, index)

定义在udf.h文件中为

#define DEFINE_PROFILE(name, t, i) void name(Thread *t, int i)

在编译过程中延伸为

void inlet_x_velocity(Thread *thread, int index)

名字为inlet_x_velocity的函数不返回值由于它被声明为空的数据类型。

3.8在你的函数中定义变量(Defining Variable in Your Function

 

在你的UDF源文件中包含了udf.h头文件后,你必须定义真实的变量。使用把它们定义在所有函数之外的全局变量(如果它们被源文件中大部分或所有函数共享)是非常方便的。关于全局变量的信息见Section 2.5.3。局部于函数的任何变量必须在函数内声明。局部变量的信息见Section 2.5.2。

3.9函数体(Functin Body

 

你的UDF源文件中的C函数体被包含在DEFINE声明之下的一对大括号内,显示在下面的例子中。在这个例子中,mu_lan和temp是局部变量。只有cell_viscosity函数认识它们。

例子

DEFINE_PROPERTY(cell_viscosity, cell, thread)

{

  real mu_lam;

  real temp = C_T(cell, thread);

 

  if (temp > 288.)

    mu_lam = 5.5e-3;

  else if (temp > 286.)

    mu_lam = 143.2135 - 0.49725 * temp;

  else

    mu_lam = 1.;

 

  return mu_lam;

}

3.10  UDF任务(UDF Tasks

UDF可执行的任务有五种不同的类型:

1.      返回值

2.      修改自变量

3.      返回值和修改自变量

4.      修改FLUENT变量(不能作为自变量传递)

5.      写信息到(或读取信息从)case或data文件

函数能返回值,除非它们在udf.h文件中被定义为void。如果它们不返回值,它们能修改自变量,修改存储在内存中的变量,或与case和data文件一起执行输入输出(I/O)任务。

在Section 3.10.1-3.10.5中,提供了描述上面提到的五种不同的函数任务中每一种的UDF源代码例子。

3.10.1 返回值的函数(Function that Return a Value

 

下面的UDF是一个返回值到FLUENT求解器的函数例子。名为cell_viscosity的函数计算了依赖温度的粘度值(mu_lam)并返回这个值到求解器。

/********************************************************************/

/* UDF that returns a value to the solver                                   */

/* Specifies a temperature-dependent viscosity property                      */

/********************************************************************/#include "udf.h"

 

DEFINE_PROPERTY(cell_viscosity, cell, thread)

{

  real mu_lam;

  real temp = C_T(cell, thread);

 

  if (temp > 288.)

    mu_lam = 5.5e-3;

  else if (temp > 286.)

    mu_lam = 143.2135 - 0.49725 * temp;

  else

    mu_lam = 1.;

 

  return mu_lam;

}

cell_viscosity使用了DEFINE_PROPERTY 宏(在Section 4.3.6中描述)来定义。DEFINE_PROPERTY返回一个udf.h中指定的real数据类型。两个real变量传入函数:通过函数计算的层流粘度mu_lam; 和C_T(cell,thread)的值,它是在考虑中的单元的温度值。温度值在它下降范围的基础上被检测,mu_lam的适当值被计算。在函数结尾,mu_lam的计算值被返回。

3.10.2修改自变量的函数(Function that Modify an Argument

 

下面的UDF是一个修改一个自变量的函数的例子。名字为user_rate的函数为一个两种气态物质的的简单系统产生一个自定义的体积反应速率。Real指针rr作为自变量传递给函数,指针指向的变量在函数内被修改。

/**************************************************************/

/* UDF that modifies one of its arguments                            */

/* Specifies a reaction rate in a porous medium                        */

/**************************************************************/

 

#include "udf.h"

 

#define K1 2.0e-2

#define K2 5.

 

DEFINE_VR_RATE(user_rate, c, t, r, mole_weight, species_mf, rr, rr_t)

{

  real s1 = species_mf[0];

  real mw1 = mole_weight[0];

 

  if (FLUID_THREAD_P(t) && THREAD_VAR(t).fluid.porous)

    *rr = K1*s1/pow((1.+K2*s1),2.0)/mw1;

  else

    *rr = 0.;

}

user_rate使用了DEFINE_VR _RATE宏(见Section 4.3.14)来定义。该函数执行一个当前考虑的单元是否在多孔区域的测试,这个反应速率只应用于多孔区域。real指针变量rr是一个传递给函数的自变量。UDF使用废弃操作符 * 分配反应速率值给废弃指针 *rr。指针rr指向的目标是设置反应速率。通过这个操作,存储在内存中这个指针上的字符的地址被改变了,不再是指针地址本身。(关于废弃指针的详细内容见[3])。

3.10.3返回一个值和修改一个自变量的函数(Functions that Return a Value ans Modify an Argument

 

下面的UDF是一个修改它的自变量并返回一个值到FLUENT求解器的函数例子。名字为user_swirl的函数修改ds自变量,指定旋转速度源项并返回它到求解器。

/**************************************************************/

/* UDF that returns a value and modifies an argument                  */

/* Specifies a swirl-velocity source term                             */

/**************************************************************/

 

#include "udf.h"

 

#define OMEGA 50.    /* rotational speed of swirler */

#define WEIGHT 1.e20 /* weighting coefficients in linearized equation */

 

DEFINE_SOURCE(user_swirl, cell, thread, dS, eqn)

{

  real w_vel, x[ND_ND], y, source;

 

  C_CENTROID(x, cell, thread);

  y = x[1];

 

  w_vel = y*OMEGA;          /* linear w-velocity at the cell */

 

  source = WEIGHT*(w_vel - C_WSWIRL(cell,thread));

  dS[eqn] = -WEIGHT;

 

  return source;

}

user_swirl使用DEFINE_SOURCE宏来定义(在Section 4.3.8中描述)。DEFINE_SOURCE返回一个在udf.h中指定的数据类型。函数采用自变量ds(它是数组的名字)并设置由eqn指定的元素为关于速度(w_vel)导数的值。(这是z动量方程源项)。这个函数也计算了旋转速度源项的值source,并返回这个值到求解器。

3.10.4修改FLUENT变量的函数

 

下面的UDF是一个修改存储在内存中FLUENT变量的函数例子。名字为inlet_x_velocity的函数使用F_PROFILE(a Fluent Inc. provided utility(应用程序)“Translate by 金山词霸”)来修改存储在内存中的x速度分布边界条件。

/********************************************************************/

/* UDF that modifies a FLUENT solver variable                            */

/* Specifies a steady-state velocity profile boundary condition                 */

/********************************************************************/

 

#include "udf.h"

 

DEFINE_PROFILE(inlet_x_velocity, thread, index)

{

  real x[ND_ND];          /* this will hold the position vector */

  real y;

  face_t f;

 

  begin_f_loop(f, thread)

    {

      F_CENTROID(x,f,thread);

      y = x[1];

      F_PROFILE(f, thread, index) = 20. - y*y/(.0745*.0745)*20.;

    }

  end_f_loop(f, thread)

}

inlet_x_velocity使用DEFINE_PROFLIE宏来定义(在Section 4.3.5中描述)。它的自变量是thread和index。Thread是一个指向面线索的指针,而index是一个每个循环内为变量设置数值标签的整数。DEFINE_PROPERTY在udf.h文件中一个返回void的数据类型。

函数由声明变量f作为face_t数据类型开始。一维数组x和变量y是real 数据类型。循环宏用来在区域中每个面上循环以创建型线或数据数组。在每个循环内,F_CENTROID为含有index f的面输出面质心的值(数组 x),index f在由thread指向的线索上。存储在x[1]中的y坐标分配给变量y,它用于计算x速度。然后这个值分配给F_PROFILE, 它使用整数index(由求解器传递个它)来设置内存中面上的x速度值。

3.10.5写入Case或Data文件或从中读取的函数(Functions that Write to or Read from a Case or Data File)

下面的C源代码包含了写信息到data文件和读回它的函数例子。这是一个包含多个连接在一起的UDF的单个C文件例子。

/******************************************************************/

/* UDF that increment a variable, write it to a data file                      */

/* and read it back in                                                 */

/******************************************************************/

 

#include "udf.h"

 

int kount = 0;  /* define global variable kount */

 

DEFINE_ADJUST(demo_calc, domain)

{

  kount++;

  printf("kount = %d\n",kount);

}

 

 

DEFINE_RW_FILE(writer, fp)

{

  printf("Writing UDF data to data file...\n");

  fprintf(fp, "%d",kount); /* write out kount to data file */

}

 

 

DEFINE_RW_FILE(reader, fp)

{

  printf("Reading UDF data from data file...\n");

  fscanf(fp, "%d",&kount); /* read kount from data file */

}

在顶部的列表中,整数kount被定义为全局的(由于它被源代码文件中的所有三个函数使用)并初始化为0。名字为demo_calc的第一个函数,使用DEFINE_SDJUST 宏来定义。(关于DEFINE_ADJUST的详细信息见Section 4.2.1)。在demo_calc中,kount的值每次迭代后增加因为每次迭代调用DEFINE_ADJUST一次。名字为writer的第二个函数,使用DEFINE_RW_FILE宏来定义。(关于DEFINE_RW_FILE的详细信息见Section 4.2.4)。当保存数据文件时,它指示FLUENT写当前kount值到数据文件。名字为reader的第三个函数,当读取数据文件时,它指示FLUENT从这个数据文件中读取kount的值。

这三个函数一起工作如下。如果你运行10次迭代计算(kount将增加到值为10)并保存这个数据文件,当前kount(10)的值被写入你的数据文件。如果你读这个数据返回到FLUENT并继续计算,kount将以值10开始随着每次迭代继续增加。注意,你可尽你所想的保存静态变量,但是必须保证以与它们被写的相同顺序来读取它们。

3.11为多相流应用写UDF(Writing UDF for Mulutiphase Applications

 

当一个多相流模型在FLUENT中被激活时,属性和变量的存储和对单相一样应当为所有相的混合设置它们。这可以通过使用附加线索(thread)和区域数据结构在代码中得以表明。

3.11.1多相应用的数据结构(Data Structure for Multiphase Applications

区域和线程(Domains and Threads

 

在多相流应用中,最高级别的区域被用作超级区域。每相占据的区域用作子区域第三种类型区域是相互作用区,为了定义相间的相互作用才引入它的。当混合属性和变量必要时(所有相的和),超级区域用于这些数量而子区域携带了单相的信息。在单一相中混合的概念用于描述所有种类(成分)的和而在多相中它描述了所有相的总和。这个区别是非常重要的因为以后代码将延伸到多相多组分(例如,这里相是种类的混合)。

由于求解器的数据存储在线程(thread)数据结构中,线程必须既和超级区域相联系又和每个子区域相联系。就是说,对定义在超级区域上的每个单元或面线程,有相应的单元或面线程定义在每个子区域上。定义在超级区域每个线程上的某些信息与子区域每个相应线程上的共享。与超级区域相关的线程被用作超级线程,而与子区域相关的线程被用作相级别线程或子线程。区域和线程的层次总结在Figure 3.11.1中。

Figure   3.11.1: Domain and Thread Structure   Hierarchy

Figure 3.11.1也引入了domain_id和phase_domain_indexed的概念。domain_id在UDF中用于辨别超级区域从主要和次要的相级别区域中。超级区域的domain_id值总是被指定为1。相互作用区域也有相同的domain_id。domain_ids不必要如Figure3.11.1显示的顺序排列。dhase_domain_index在UDF中用于从次要相级别线程中辨别主要相级别线程。对主要相级别线程,phase_domain_index总是分配值为0。

访问数据(Accessing Data

 

当你写UDF或为多相应用使用宏时,参考与尝试访问其属性的相(subdomain)或混合(super domain)相关的数据结构(thread or domain)是很重要的。作为例子,宏C_R(c,t)将返回线程t的单元c上的密度。如果t是指向超级线程的指针,那么返回的是混合密度。如果t是指向子线程的指针,那么返回的是相密度。

当传递到你的UDF的线程或区域指针不被你的函数需要时,也有一些例子。这取决于你使用的多相模型,你尝试修改的属性或项(例如,你使用的那个DEFINE宏),还有受到影响的相或混合。为了更好地理解这点,回想一个混合模型和欧拉多相模型之间区别的例子。在混合模型中,为混合相求解单一的动量方程,混合相的属性由它的相的总和来决定。在欧拉模型中,动量方程为每一相求解。当使用混合模型时,FLUENT允许你直接为混合相指定动量源项(使用DEFINE_SOURCE),但是不能为欧拉模型。对后者,你可以为单个相指定动量源项。因此,多相模型及被UDF修改的项,决定了那哪个区域或线程是需要的。

从求解器传递到你的UDF的特定的区域或线程的结构取决于你使用的DEFINE宏。例如,DEFINE_INIT和DEFINE_ADJUST函数总是传递与超级区域相关的区域结构。DEFINE_ON_DEMAND函数不能传递任何区域结构。如果你的UDF不能明确地传递指针到你的函数定义要求的线程或区域,那么你可以使用multiphase-specific utility macro找会它(见第6章)。为了你方便使用,表3.11.1-3.11.6总结了每个多相模型和相,在该相上为每个给定变量指定了UDF。从这些信息,你可推断出那些区域结构是从求解器传递到UDF的。

单相和多相模型应用UDF之间的区别(Differences Between UDF for Single-Phase and Multiphase Applications

注:在许多例子中,为单相流动写的UDF源代码和为多相流动写的是相同的。例如,假设函数只从它被连接(hooked)到的相级别区域访问数据,为单相边界型线(使用DEFINE_PROFIEL定义的)写的C代码为多相边界型线写的代码之间是没有区别的。然而,如果那些函数从除混合级别区域之外的任何区域访问数据,调整和初始化UDF的代码对单相和多相流动是不同的。

3.11.2 对多相模型使用UDFUsing UDF for Multiphase Models

 

在多相模型中,从求解器传递到你的UDF的数据结构(例如区域和线程指针)取决于你使用的DEFINE宏。传递哪一个特定的区域或线程取决于函数连接到求解器的什么地方。例如,被连接到混合模型的函数传递超级区域结构,而连接到特定相的函数传递子区域结构。表3.11.1-3.11.6列举了DEFINE和对每个多相模型UDF被连接到的相。从这些信息你可推断出那些数据结构被传递。回想DEFINE_ADJUST和DEFINE_INIT UDF are hardwired to the mixture-level domain,而DEFINE_ON_DEMAND函数不能连接到任何区域。

Table   3.11.1: DEFINE   Macro Usage for the VOF Model

Variable

Macro

Phase   Specified On

volume fraction

DEFINE_PROFILE

secondary   phase(s)

velocity at a   boundary

DEFINE_PROFILE

mixture

pressure at a   boundary

DEFINE_PROFILE

mixture

boundary   temperature

DEFINE_PROFILE

mixture

turbulent   kinetic energy

DEFINE_PROFILE

mixture

turbulent   dissipation rate

DEFINE_PROFILE

mixture

mass source

DEFINE_SOURCE

primary and

 

 

secondary   phase(s)

momentum source

DEFINE_SOURCE

mixture

energy source

DEFINE_SOURCE

mixture

turbulent   kinetic energy source

DEFINE_SOURCE

mixture

turbulent   dissipation rate source

DEFINE_SOURCE

mixture

density

DEFINE_PROPERTY

primary and

 

 

secondary   phase(s)

viscosity

DEFINE_PROPERTY

primary and

 

 

secondary   phase(s)

     Table   3.11.2: DEFINE   Macro Usage for the Mixture Model

Variable

Macro

Phase   Specified On

volume fraction

DEFINE_PROFILE

secondary   phase(s)

velocity at a   boundary

DEFINE_PROFILE

primary and

 

 

secondary   phase(s)

pressure at a   boundary

DEFINE_PROFILE

mixture

boundary   temperature

DEFINE_PROFILE

mixture

turbulent   kinetic energy

DEFINE_PROFILE

mixture

 


udf 中文手册 ANSYS FLUNT (3)的评论 (共 条)

分享到微博请遵守国家法律