fluent UDFCh1.docx
《fluent UDFCh1.docx》由会员分享,可在线阅读,更多相关《fluent UDFCh1.docx(13页珍藏版)》请在冰豆网上搜索。
fluentUDFCh1
第一章.FluentUDF介绍
本章简要地介绍了用户自定义函数(UDF)及其在Fluent中的用法。
在1.1到1.6节中我们会介绍一下什么是UDF;如何使用UDF,以及为什么要使用UDF,在1.7中将一步步的演示一个UDF例子。
1.1什么是UDF?
1.2为什么要使用UDF?
1.3UDF的局限
1.4Fluent5到Fluent6UDF的变化
1.5UDF基础
1.6解释和编译UDF的比较
1.7一个step-by-stepUDF例子
1.1什么是UDF?
用户自定义函数,或UDF,是用户自编的程序,它可以动态的连接到Fluent求解器上来提高求解器性能。
用户自定义函数用C语言编写。
使用DEFINE宏来定义。
UDF中可使用标准C语言的库函数,也可使用FluentInc.提供的预定义宏,通过这些预定义宏,可以获得Fluent求解器得到的数据。
UDF使用时可以被当作解释函数或编译函数。
解释函数在运行时读入并解释。
而编译UDF则在编译时被嵌入共享库中并与Fluent连接。
解释UDF用起来简单,但是有源代码和速度方面的限制不足。
编译UDF执行起来较快,也没有源代码限制,但设置和使用较为麻烦。
1.2为什么要使用UDF?
一般说来,任何一种软件都不可能满足每一个人的要求,FLUENT也一样,其标准界面及功能并不能满足每个用户的需要。
UDF正是为解决这种问题而来,使用它我们可以编写FLUENT代码来满足不同用户的特殊需要。
当然,FLUENT的UDF并不是什么问题都可以解决的,在下面的章节中我们就会具体介绍一下FLUENTUDF的具体功能。
现在先简要介绍一下UDF的一些功能:
●定制边界条件,定义材料属性,定义表面和体积反应率,定义FLUENT输运方程中的源项,用户自定义标量输运方程(UDS)中的源项扩散率函数等等。
●在每次迭代的基础上调节计算值
●方案的初始化
●(需要时)UDF的异步执行
●后处理功能的改善
●FLUENT模型的改进(例如离散项模型,多项混合物模型,离散发射辐射模型)
由上可以看出FLUENTUDF并不涉及到各种算法的改善,这不能不说是一个遗憾。
当然为了源代码的保密我们还是可以理解这样的做法的。
其实,如果这些代码能够部分开放,哪怕就一点点,我想FLUENT会像LINUX一样发展更为迅速,使用更为广泛。
遗憾的是,从目前来看,这只是一种幻想。
什么时候中国人可以出自己的精品?
1.3UDF的局限
尽管UDF在FLUENT中有着广泛的用途,但是并非所有的情况都可以使用UDF。
UDF并不能访问所有的变量和FLUENT模型。
例如,它不能调节比热值;调节该值需要使用求解器的其它功能。
如果您不知道是否可以用UDF解决某个特定的问题,您可以求助您的技术支持。
1.4Fluent5到Fluent6UDF的变化
如果你有FLUENT5的UDF编程经验,请注意在FLUENT6种的下列变化:
∙FLUENT6中加入了大量的通用多相模型。
Whenoneofthesegeneralmultiphasemodelsisenabled,storagemustbesetasideforthemixtureaswellastheindividualphases.Thisfunctionalityismanifestedinthecodethroughtheuseofadditionalthreadanddomaindatastructures.Consequently,somepredefinedmacroshavebeenaddedthatallowaccesstodatacontainedwithinmixture-levelandphase-leveldomainandthreadstructures.SeeSection 3.11fordetailsonwritingUDFformultiphaseapplications.
IfyouhaveaFLUENT5UDFwithanexternaldomaindeclarationthatyouwanttouseinFLUENT6,thentheexternstatementmustbereplacedbyacalltotheGet_DomainutilityandassignmenttoaDomainpointerasshownbelow.TheFluent-providedutility,Get_Domain
(1),returnsthepointertothemixture-leveldomain.SeeSection 6.5.1formoredetailsonGet_Domain.
Example
externDomain*domain;
DEFINE_ON_DEMAND(my_udf)
{
...
}
istobereplacedby
DEFINE_ON_DEMAND(my_udf)
{
Domain*domain;
domain=Get_Domain
(1);
...
}
ThemacroC_VOFaccessesvolumefractionvaluesfromtheFLUENTsolver.C_VOF(c,pt[i])hastwoarguments,candpt[i].cisthecellidentifier.pt[i]isthepointertothecorrespondingphase-levelthreadfortheithphase,whereiisthephase_domain_index.Forexample,C_VOF(c,pt[i])canbeusedtoreturnthevolumefractionoftheithphasefluidatcellc.Thepointerpt[i]canalsoberetrievedusingTHREAD_SUB_THREAD,discussedinSection 6.5.4,usingiasanargument.
∙ForcompiledUDF,themakefilecalledMakefile.udfthatwasprovidedinpreviousFLUENTreleaseshasbeenrenamedtomakefile.udf2.SeeSection 7.3.2formoredetails.
∙Formultiphaseflowproblems,youwillneedtosupplyyourownuser-definedscalarfluxfunctioninsteadofusingthedefaultfunctionprovidedbyFLUENT.
∙DEFINE_PROPERTYistobeusedtodefineUDFforparticleordropletdiameterforthemixturemodel,previouslytheAlgebraicSlipMixtureModel(ASMM),insteadoftheDEFINE_DRIFT_DIAMmacro.
1.5UDF基础
∙1.5.1输运方程
∙1.5.2单元(Cells),面,区域(Zones)和线(Threads)
∙1.5.3操作
∙1.5.4求解器数据
∙1.5.5运行
1.5.1输运方程
FLUENT求解器建立在有限容积法的基础上,这种方法将计算域离散为有限数目的控制体或是单元。
网格单元是FLUENT中基本的计算单元,这些单元的守恒特性必须保证。
也就是说普通输运方程,例如质量,动量,能量方程的积分形式可以应用到每个单元:
(1.5.1)
此处,
是描述普通输运数量的变量(ageneraltransportablequantity),根据所求解的输运方程它可取不同的值。
下面是在输运方程中可求解的
的子集。
TransportEquation
Variablefor
continuity
1
xmomentum
velocity(u)
ymomentum
velocity(v)
zmomentum
velocity(w)
energy
enthalpy(h)
turbulentkineticenergy
k
turbulentdissipationrate
speciestransport
massfractionofspecies(Yi)
守恒与否需要知道通过单元边界的通量。
因此,需计算出单元和面上的属性值(properties)。
1.5.2单元(Cells),面,区域(Zones)和线(Threads)
单元和单元面被组合为一些区域(zones),这些区域规定了计算域(例如,入口,出口,壁面)的物理组成(physicalcomponents)。
当用户使用FLUENT中的UDF时,用户的UDF可调用流体区域或是边界区域的计算变量(solutionvariables)。
UDF需要获得适当的变量,比如说是区域参考(azonereference)和单元ID,以便标定各个单元。
区域(Azone)是一群单元或单元面的集合,它可以由模型和区域的物理特征(比如入口,出口,壁面,流体区域)来标定。
例如,一些被指定为面域(afacezone)的单元面可以被指定为velocity-inlet类型,由此,速度也就可指定了。
线(Athread)是FLUENT数据结构的内部名称,可被用来指定一个区域。
Thread结构可作为数据储存器来使用,这些数据对于它所表示的单元和面来说是公用的(TheThreadstructureactsasacontainerfordatathatiscommontothegroupofcellsorfacesthatitrepresents)。
1.5.3操作
多数的UDF任务需要在一个线的所有单元和面上重复执行。
比如,定义一个自定义轮廓函数(acustomprofilefunction)则会对一个面线上(inafacethread)的所有单元和面进行循环。
为了用户方便,FluentInc.向用户提供了一些循环宏工具(loopingmacroutilities)来执行对单元,面,节点(nodes)和线(threads)的重复操作。
例如,单元循环宏(Cell-loopingmacros)可以对给定单元线上的所有单元进行循环操作(loopovercellsinagivencellthreadallowingaccesstoallofthecells)。
而面循环宏(Face-loopingmacros)则可调用所有给定面线(agivenfacethread)的面。
Fluent提供的循环工具请见Chapter6。
在某些情况下,UDF需要对某个变量操作,而这个变量恰恰又不能直接被当作变量来传递调用。
比如,如果用户使用DEFINE_ADJUST宏来定义UDF,求解器将不会向它传递thread指针。
这种情况下,用户函数需要用Fluent提供的宏来调用线指针(threadpointer)。
见Chapter6。
1.5.4求解器数据
通过FLUENT用户界面将C函数(它已被编译和连接)连接到求解器上可实现调用求解器变量。
一旦UDF和求解器正确连接,无论何时,函数都可调用求解器数据。
这些数据将会被作为用户变量自动地传递给UDF。
注意,所有的求解器变量,不管是求解器传递给UDF的,还是UDF传递给求解器的,都使用SI单位。
1.5.5运行
UDF将会在预定时刻被FLUENT调用。
但是,也可对它们进行异步执行,使用DEFINE_ON_DEMAND宏,还可在需要时(ondemand)执行。
详情请见4.2.3
1.6解释和编译UDF的比较
编译UDF和FLUENT的构建方式一样。
脚本Makefile被用来调用C编译器来构建一个当地目标代码库(anativeobjectcodelibrary)。
目标代码库包含高级C语言源代码的机器语言翻译。
代码库在FLUENT运行时由“动态加载”(``dynamicloading'')过程连接到FLUENT上。
连接后,与共享库的联系(theassociationwiththesharedlibrary)将会被保存在用户的case文件中,这样,当FLUENT以后再读入case文件时,此编译库将会与FLUENT自动连接。
这些库是针对计算机的体系结构和一定版本的FLUENT使用的。
所以,当FLUENT更新,或计算机操作系统改变,或是在不同类型的机器上运行时,这些库必须重新构建。
而解释UDF则是在运行时,直接从C语言源代码编译和装载(compiledandloadeddirectlyfromtheCsourcecode)。
在FLUENT运行中,源代码被编译为中介的独立于物理结构的使用C预处理程序的机器代码(anintermediate,architecture-independentmachinecode)。
当UDF被调用时,机器代码由内部仿真器(aninternalemulator),或注释器(interpreter)执行。
注释器不具备标准C编译器的所有功能;它不支持C语言的某些原理(elements)。
所以,在使用interpretedUDF时,有语言限制(见3.2)。
例如,interpretedUDF不能够通过废弃结构(dereferencingstructures)来获得FLUENT数据。
要获得数据结构,必须使用由FLUENT提供的预定义宏。
另一个例子是FLUENTinterpreter不能识别指针数组。
这些功能必须由compiledUDF来执行。
编译后,用户的C函数名称和内容将会被储存在case文件中。
函数将会在读入case文件时被自动编译。
独立于物理结构的代码的外层(Thisextralayerofarchitecture-independentcode)可能会导致执行错误(aperformancepenalty),但却可使UDF共享不同的物理结构,操作系统,和Fluent版本。
如果运行速度较慢,UDF不用被调节就可以编译代码的形式(incompiledmode)运行。
FLUENT中的compiled和interpretedUDF请见Chapter7。
选择interpretedUDF或是compiledUDF时,注意以下内容:
∙InterpretedUDF
o对其它平台是便捷的(portable)。
o可作为(compiledUDF)来运行。
o不需C编译器。
o比compiledUDF慢。
o需要较多的代码。
o在使用C语言上有限制。
o不能与编译系统或用户库(compiledsystemoruserlibraries)连接。
o只能使用预定义宏来获得FLUENT结构中的数据。
(见Chapters5和6)。
∙CompiledUDF
o比interpretedUDF运行快。
o在使用C语言上不存在限制。
o可用任何ANSI-compliantC编译器编译。
o能调用以其他语言编写的函数(specificsaresystem-andcompiler-dependent)。
o机器物理结构需要用户建立FLUENT(2Dor3D)的每个版本的共享库(asharedlibraryforeachversionofFLUENT(2Dor3D)neededforyourmachinearchitecture)。
o如果包含有注释器(interpreter)不能处理得C语言元素,则不能作为(interpretedUDF)运行。
总的来说,当决定使用那种类型的UDF时:
∙使用interpretedUDF作为简单的函数
∙使用compiledUDF作为复杂的函数,这些函数
o对CPU有较大要求(例如每次运行时,在每个单元上均须调用的属性UDF(apropertyUDF)。
o需要使用编译库(requireaccesstoacompiledlibrary)。
1.7一个step-by-stepUDF例子
编辑UDF代码,并且在用户的FLUENT模型中有效使用它,须遵循以下七个基本步骤:
1.定义用户模型。
2.编制C语言源代码。
3.运行FLUENT,读入,并设置case文件。
4.编译或注释(Compileorinterpret)C语言源代码。
5.在FLUENT中激活UDF。
6.开始计算。
7.分析计算结果,并与期望值比较。
在开始解决问题前,用户必须使用UDF定义希望解决的问题(Step1)。
例如,加入用户希望使用UDF来定义一个用户化的边界条件(acustomizedboundaryprofile)。
用户首先需要定义一系列数学方程来描述这个条件。
接下来用户需要将这些数学方程(概念设计,conceptualdesign)用C语言写成一个函数(Step2)。
用户可用文本编辑器来完成这一步。
以.c为后缀名来把这个文件保存在工作路径下。
写完C语言函数后,用户即可运行FLUENT并且读入或设置case文件(Step3)。
对C语言源代码进行注释,编译,和调试(interpret,compile,anddebug),并在FLUENT中激活用户函数(Step5)。
最后,运行计算(Step6),分析结果并与期望值比较。
(Step7)。
根据用户对结果的分析,可将上述整个过程重复几次。
具体如下。
Step1:
定义用户模型
生成和使用UDF的第一步是定义用户的模型方程。
如图Figure1.7.1所示的涡轮叶片。
模拟叶片周围的流场使用了非结构化网格。
计算域由底端的周期性边界(aperiodicboundaryonthebottom)延伸到顶端的相同部分(anidenticaloneonthetop),速度入口在左边,压力出口在右边。
Figure1.7.1:
TheGridfortheTurbineVaneExample
文中对入口x速度为常数分布和抛物线分布的流场进行了比较。
分段线性的分布可由边界场选项得到(theapplicationofaprofileusingapiecewise-linearprofileisavailablewiththeboundaryprofilesoption),而多项式分布则只能使用用户自定义函数得到。
进口速度为常数(20m/s)的结果如图1.7.2和1.7.3所示。
当流动沿着涡轮叶片进行时,初始速度场被改变了。
Figure1.7.2:
VelocityMagnitudeContoursforaConstantInletxVelocity
Figure1.7.3:
VelocityVectorsforaConstantInletxVelocity
假定现在要设涡轮叶片入口速度x不是一常数值,其分布如下
变量y在入口中心处为0.0,在入口上部和下部则分别为
0.0745 m而入口中心处的x速度为20m/s,边界上为0。
用户可用UDF描述这一分布,并将它应运到FLUENT模型中来解决这类问题。
Step2:
编制C语言源代码。
选定方程定义UDF后,用户可用任意文本编辑器来书写C语言代码。
以扩展名.c保存源代码文件保存到工作路径下。
关于UDF的书写请参考Chapter 3。
下面是一个怎样在UDF中应用方程的例子。
UDF的功能由主要的DEFINE宏(theleadingDEFINEmacro)来定义。
此处,DEFINE_PROFILE宏用来表示下面的代码旨在给求解器提供边界的轮廓信息。
书中将在以后部分讨论其它的DEFINE宏。
/*************************************************************************/
/*udfexample.c*/
/*UDFforspecifyingasteady-statevelocityprofileboundarycondition*/
/*************************************************************************/
#include"udf.h"
DEFINE_PROFILE(inlet_x_velocity,thread,index)
{
realx[ND_ND];/*thiswillholdthepositionvector*/
realy;
face_tf;
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)
}
DEFINE_PROFILE宏的第一个变量inlet_x_velocity用来定义速度入口面板中的函数。
名称可任意指定。
在给定的边界区域上的所有单元面(identifiedbyfinthefaceloop)上将会使用函数的这个方程。
当用户在FLUENT用户界面选定UDF作为边界条件时,将会自动定义线(thread)。
下标由begin_f_loop应用程序自动定义。
UDF中,begin_f_loop被用来形成对边界区域上所有单元面的循环(loopthroughallcellfacesintheboundaryzone)。
对于每个面,面的质心(thefacecentroid)的坐标可由F_CENTROID宏来获得。
抛物线方程中用到了y坐标y,速度值通过F_PROFILE宏来返回给面。
begin_f_loop宏和F_PROFILE宏都是FLUENT提供的宏。
详情请见Chapter 5。
Step3:
运行FLUENT,读入,并设置case文件
建立UDF后,用户开始设置FLUENT。
1.在工作路径下启动FLUENT。
2.读入(或设置)case文件(如果case文件以前设置过,请确认它是否被保存在了工作