OpenFOAM 常用类的一些总结OpenFOAM 中有许多类,每个类的功能都很强大,这也使它面向对象设计得以实现对于程序,最常用到的,也是最底层的就是数据,在OpenFOAM中引入了三类基础数据 类型:标量scalar,向量vector,张量tensor.这三个中数据类型,也是FOAM中最基础的三个 类还有一个比较重要的就是bool和label,前者就是是非型,及对错型,只不过是更扩展一 些,后者是标签型数据,相当于 c 中的整型关于更多的其它数据类型可以参看目 录..\src\OpenFOAM\primitives 里面)在上述数据类的基础上,增加场(field)的概念,就引入了标量场scalarField,向量场 vectorField,张量场 tensorField实际上这三个类又是 field 类的 typedef,如 typedef fieldvscalar> saclarField这些场类中都有对应的成员函数进行加减乘除运算,还有复杂的点积叉积等说到 这field class,其实他就像是一个数据存放的区域一样,存放上scalar,那它成了标量场scalarField 这些类中可以有接口实现数据的计算。
从field类中又派生出了 FieldField类,这个就是说场中 场类,其实这个主要用于边界条件类的一个基类因为边界条件算是网格类场中的一个特殊的 场,后面会介绍比field类高一点的就是几何场类GeometricField class,其相比field class多了纪录场位置 的相关信息说到这里请大家注意他和polyMesh class的区别,后者只是纪录网格的结构,如 点的位置、面的组成、体的组成等等polyMesh class中对应有pointMesh,surfaceMesh,volMesh 等类,从字面上很容易理解其处理和记录网格点、网格面、网格体等信息而GeometricField 类,其则是记录了在什么样的网格上有量a的相关信息或数据它包括了内部区域、边界区域(GeometricBoundaryField class)、网格、尺度单位、计算的先前时间阶的值等在该类中有 常用的三种(实际上还有其他的许多,可以参看OpenFOAM网上说明):volScalarField体标 量场,volVectorField体向量场,volTensorField体张量场这里说的场与field有所不同,这里 指的是网格区域上所对应的数据信息。
上述的vol就是指ployMesh中的volMesh,女口 volscalarField 类来说:见下例volScalarField p(IOobject(runTime.timeName(),mesh,IOobject::MUST_READ,IOobject::AUTO_WRITE),mesh);看过老苏博客的朋友肯定都知道这是什么意思,这是读入标量压力场文件,把压力值存储到网 格体中心为加深对GeometricField类的理解,贴张PG中的图片:gwmHr icFi^ld^T/pe.'-geometr icBo undaryFie l(Jpe >■ rvtJoundary^e&li ■“ fvPatc^List■fvPatchFielddimernsLOrt«lpo^tField Ucelist celfLis-tField *Lab«ILi&tir«rH' ■ rwlrr■ ■ ■ r■・!■・・■ ■ ■ i!ianHM!aa i iu Bivrr nra i=b=»fi—rrbftf ・wi!・h・:・■・・・ir・as*polyMnh -■ paly8ou-ndaryMt5ti FvPatch由m帥引QnSei 町Typ asc-alar gets -pcriyPitcfilistpolyPatchCesiSOr syenm^tnsor "in 昭 ThiT syirsmTenwiThudFiguTe l!-5: Biimc structure loadiihj tn geonictrkFi#ldOpenFOAM中有许多类,每个类的功能都很强大,这也使它面向对象设计得以实现。
对于程序,最常用到的,也是最底层的就是数据,在OpenFOAM中引入了三类基础数据类型:标量scalar,向量vector,张量tensor.这三个中数据类型,也是FOAM中最基础的三个类还 有一个比较重要的就是bool和label,前者就是是非型,及对错型,只不过是更扩展一些,后者 是标签型数据,相当于c中的整型关于更多的其它数据类型可以参看目录..\src\OpenFOAM\primitives 里面)在上述数据类的基础上 增加场(field的概念,就引入了标量场scalarField,向量场vectorField, 张量场 tensorField.实际上这三个类又是 field 类的 typedef,如 typedef fieldvscalar> saclarField 这些场类中都有对应的成员函数进行加减乘除运算,还有复杂的点积叉积等说到这 field class, 其实他就像是一个数据存放的区域一样,存放上scalar,那它成了标量场scalarField这些类中 可以有接口实现数据的计算从field类中又派生出了 FieldField类,这个就是说场中场类,其 实这个主要用于边界条件类的一个基类。
因为边界条件算是网格类场中的一个特殊的场,后面 会介绍比field类高一点的就是几何场类GeometricField class,其相比field class多了纪录场位置的相 关信息说到这里请大家注意他和 polyMesh class 的区别,后者只是纪录网格的结构,如点的 位置、面的组成、体的组成等等 polyMesh class中对应有pointMesh,surfaceMesh,volMesh等类, 从字面上很容易理解其处理和记录网格点、网格面、网格体等信息而GeometricField类,其 则是记录了在什么样的网格上有量a的相关信息或数据它包括了内部区域、边界区域(GeometricBoundaryField class)、网格、尺度单位、计算的先前时间阶的值等在该类中有 常用的三种(实际上还有其他的许多,可以参看OpenFOAM网上说明):volScalarField体标量 场,volVectorField体向量场,volTensorField体张量场这里说的场与field有所不同,这里指的 是网格区域上所对应的数据信息上述的vol就是指ployMesh中的volMesh,如volscalarField 类来说:见下例volScalarField p(IOobject(runTime.timeName(),mesh,IOobject::MUST_READ,IOobject::AUTO_WRITE),mesh);看过老苏博客的朋友肯定都知道这是什么意思,这是读入标量压力场文件,把压力值存储到网格体中心。
为加深对GeometricField类的理解,贴张PG中的图片:£ieofTietr icFieldcT^pes-i Ig€Q met ricBou nd-aryF ield■fvB-ounda^yK^-esh -*— fvPaichList■fvPaichField■■- |?ol yMesh ■ polyB oundaryM-esti FvPatctipoly Pitch ListpointField Uce-List «IIL istFiel diprsynnmTsrbsor 匸护詛t Third fiymmTen&or ThirdFi辭r与 2.5: 車山眸 C吨目 Etr^tur^- ieFi^ld除了体的向量标量张量场外,还有面标量场surfaceScalarField、面向量场surfaceVectorField、面张量场surfaceTensorField看下面的例子:surfaceScalarFie phi(IOobject("phi",runTime.timeName(),mesh),fvc::interpolate(alpha)*phia+ fvc::interpolate(beta)*phib);这里的phi既是一个面向量场对象,他用来是纪录单元体面上流过的通量值除了常用到的标量向量张量的几何场外,还有一些特殊量的场:surfaceSymmTensor面对称张量 几何场、体球面张量场等等。
几何场里面还有一个比较重要的类就是GeometricBoundaryField, 用来专门对边界进行处理的一个类如果说数据场类是处理数据的基础,那么时间类则是控制计算步进必不可少的一部分 Time class在进行瞬态计算,用它跟踪时间阶,并使时间按一定步长或者变步长累加,及输出计算参 数,计算时间等见下例:(相关说明见老苏博客 OpenFOAM>>solver>>incompressible>>icoFoam 的说明)Info<< "\nStarting time loop\n" << endl;for (runTime++; !runTime.end(); runTime++){Info<< "Time = " << runTime.timeName() << nl << endl;//……runTime.write();Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"<< " ClockTime = " << runTime.elapsedClockTime() << " s"<< nl << endl;谈到时间大家很容易想到的就是空间,time and space是cfd中非常重要的概念,在离散过程中时间和空间都需要进行离散(非稳态情况),与空间相关的类其实上面已经提到: ployMesh class, 在这不在累述。
需要附加说明的是边界条件类:边界条件在OpenFOAM被定义作为场的一个完 整部分而不是场上额外附加的在fvMatrix类中并入了 patch用来定义区域的外部边界每一 个patch有一个边界条件,再由fvm用合适的方式进行操作处理patch有多种类型:calculated, fixed value, fixed gradient, zero gradient, symmetry, cyclic 等这些类型都继承于基类 patchField在求解之前,需要对偏微分方程组进行离散,转化为线性方程组[A][x]=[b ]的形式其中[x ]就 是我们所要求的量,他也就是咱们前面介绍的GeometricField类,而[A]代数方程的系数,他就 是我们下面所要提到的fvMatrix类对于偏微分方程的每一项,OpenFOAM应用两个类来离散: finiteVolumeMethod 和 finiteVolumeCalculus,分别用 typedef 声明为 fvm 和 fvc. fvm 是计算隐 式导数从而返回fvMatrix,而fvc是计算显式导数或者其它隐式计算返回geometricField,该类 不存储私有数据,仅是执行操作从一个量map到另外一个量上。
对于偏微分方程,其中有很多 种导数形式:拉普拉斯、时间导数、二阶时间导数、对流项、散度、梯度、梯度梯度平方、旋 度、源等,在OpenFOAM中的表示见下图:Irrtit dcsmpticin[mjilicit , ExplicitTc^t expresstoufvm::/fuc:: functionsLapl 賦 bnTmp/E 邓评学VFie Id, volFie IJ-离散化时空之后,就是解方程,其实求解方程的过程主要分成如下几部:1.离散偏微分方程, 2•线性化方程组,3•对应不同的倒数格式选择差分格式,4.求解系数矩阵,5•解方程。
在这就涉 及到了一个重要的部分:矩阵Matrix是OpenFOAM中的一个模板类,他是一个用来存储及运 算标量张量等类型数据的2维矩阵这个矩阵类有点像数学上的矩阵一样对于应用于数值求 解矩阵,OpenFOAM引入了 fvMatrix类,这个就是有限体积(finite volume)矩阵类,他是一 个特殊的矩阵类型,应用于求解有限体积标量方程组,该类成员函数可以实现给定相应场的求 解、通量的计算、残差的计算和控制、方程松弛因子的实现,方程中心系数(central coefficient, 公共成员函数A())和H操作源(H operation source,成员函数H())的计算、设定计算参考等 在此需要提到的是fvMesh类,该类和GoeMesh类差不多,不同之处在于fvMesh类它包含相应 网格信息和拓扑结构的同时,还对网格进行实时更新(动网格的时候)这些更新包括删除单 元体面等,并按要求重新定位并计算新的信息下面举一些关于fvMatrix应用的例子:(选自 icoFoam)fvVectorMatrix UEqn(fvm::ddt(U)+ fvm::div(phi, U) //div ,散度是代表某量通过单元体的面积分,此处 phi 为一个通量场, 该场的值被记录在单元体的面上,而U就是由通量所输运的量,而该速度值则被记录在单元体 中心点上。
fvm::laplacian(nu, U));//源项可以使显式的,在离散时进入方程的右端,当源项为隐式的时候他进入方程的系数 矩阵中solve(UEqn == -fvc::grad(p));〃关于==,一直有所疑问,听老苏分析挺有道理,最近你看到 一篇文章上说==的定义是用来表示数学意义上的方程左右两端的等于,这个运算符为了使其有 最低的的运算优先级所以采用了==,而非=,同时也强调了方程两端得等的概念,而非赋值 在 OpenFOAM 中,对==的操作实际上是形式上的,而非实质上有什么运算,它自动重排方程 各项:所有隐式项写进方程矩阵中,而所有显式项则归于方程的 b 中volScalarField rUA = 1.0/UEqn.A();U = rUA*UEqn.H();pEqn.setReference(pRefCell, pRefValue);pEqn.solve();例子中 fvVectorMatrix 为一向量有限体积矩阵类, OpenFOAM 中定义 typedef fvMatrix fvVectorMatrix,其他的还有标量、张量等其他关于上述程序的说明参看老苏博客。
再看如下例子:fvMatrixScalar rhoEqfvm::ddt(rho)+fvc::div(phi));〃此处是一个关于质量守恒方程的求解,对于phi为密度与速度的积,而此时采用fvc即表示 速度通量在方程中作为已知量,出现在方程的 b 项中,它是计算前一时间阶的值说了一些常用的类,下面介绍一些比较基础底层的类:IOdictionary, argList, IOobject,IOdictionary类是继承于regIOobject类和dictionary类,其主要作于是读入和写入数据如读 取 PISO 控制参数,或读入 transportProperties 参数等等它派生出许多类:1. basicTherm o(用于基本热力学参数读取和计算)2. LESModel (大涡模拟模型控制参数)3. RASModel (RAS 模型控制参数)4. fvSchemes (离散格式参数)5. motionSolver (动网格控制参数)6. radiationModel (辐射模型控制参数)7. solution (求解方程控制参数)8. SRFModel (SRF 模型控制参数)9. tolerances (方程残差控制)10. transportModel (输运模型参数)见下例:IOdictionary transportProperties //在 transportProperties 字典中读入参数(IOobject("transportProperties", runTime.constant(), mesh,IOobject::MUST_READ, IOobject::NO_WRITE));IOobject 类:读入写入数据,他与 IOdictionary 不同之处在于后者是读取一个文件中的一个字 典“{}”之内的数据,而IOobject则是读入整个文件,如读入压力场,速度场等,并且有读入写 出的控制参数,见上例中的“MUST_READ, NO_WRITE”等等。
老苏博客中有详细介绍,在 此不多说了)argList类:读入外部命令参数的一个类,如在命令窗口键入icoFoam -case
,则对目录dir 执行icoFoam计算,其参数有:-case选择一个case目录替代当前工作目录;-parallel指定并行 计算参数;-doc显式该程序文档;-srDoc在浏览器里显示该程序的源文件;-help显示改程 序的使用方法dimensionSet 类是对基本类型的单位设定,并检查其正确性tmp 类是管理临时对象的一个类Ope nF OAM的程序开发初步一.OpenFOAM应用的类型:使用OpenFOAM进行CAE模拟的,大致可分为三种类型:1) 直接利用OpenFOAM的标准的求解器进行模拟,把OpenFOAM替代商业软件来使用,OpenFOAM已基本具有这样的功能和人气,与Fuent, Star-CD等相比较,OpenFOAM显然 具有更高的求解效率和灵活性2) 用户自定义求解器,即利用OpenFOAM的基本类库,如finiteVolume,OpenFOAM库来按 照自己的求解流程来编写针对某类应用的求解器用户需要开发的求解器就是类似于在OpenFOAM的applications中所看到的标准求解器icoFOAM, simpleFOAM等。
显然这一需 求是非常大的,从OpenFOAM问世以来,已有很多用户定义了自己的求解器这类需求的特 点是,并不需要特别关心,离散和求解的最底层的知识,如时间项离散,空间项离散等,关注 的重点是求解的步骤或者流程在编程中,通常是顶层的求解流程的开发,在多数情况下可以 不编译OpenFOAM的finiteVolume和OpenFOAM库这种顶层的求解器的开发,是我们以 前常常忽略的,或者是以前没有能力做到的需要指出的是,商业软件中的所谓udf,user subrout ine和这是不可相比的3)用户自己定义离散方法等对于研究离散格式、代数求解器等人来说,更关注时间项ddt,扩 散项Laplacian,对流项div是如何离散的,能否有更高效更高精度的离散方法,这需要修改 finiteVolume库和OpenFOAM库中对应的代码尤其是对流项,尽管OpenFOAM已经提供了 基于NVD和TVD的模板和40多种有名的高阶高精度格式,但可以预见,这仍然是不够的, 毕竟对流项的离散仍然是目前CFD的重点研究方向可以肯定的是,目前有很多人关注类型2的应用,毕竟将Ope nFOAM当成Flue nt或Star-CCM 来使用,并不见得方便。
但是将OpenFOAM作为类库来构建自己的求解器,这是其它软件无 法实现的二. OpenFOAM程序开发的基本知识2.1OpenFOAM的基本术语重要的环境变量:$WM_PROJECT_USER_DIR ―― OpenFOAM 的用户目录$FOAM_TUTORIALS ——OpenFOAM 的算例目录$ FOAM _SRC ——OpenFOAM库的源程序目录$ FOAM_APP —— OpenFOAM的求解器目录$ FOAM_APPBIN —— OpenFOAM的求解器执行文件目录$ FOAM_RUN ------用户的算例目录重要的shell:run = cd to $FOAM_RUNsrc = cd to $FOAM_SRCapp = cd to $FOAM_APP util = cd to $FOAM_APP/utilitiessolcd to $FOAM_APP/solverstutcd to $FOAM_TUTORIALS求解器的基本文件结构appName包含求解器源代码的目录+appName.C求解器主程序+CreateFields.H场变量的声明和初始化+Make/编译指令+files编译需要的源程序文件和生成的目标文件+opti ons编译选项,如链接库等appName/appName.C是求解器的主程序 appName/createFields.H声明变量,并从文件中读入初值,如p,物性。
appName/Make/files所有源程序的名称,一个文件一行,最后一行是目标代码的名称和存放位置,EXE=$(FOAM_USER_APPBIN)/appNameappName/Make/options设定查找头文件和库的路径,EXE_INCS,和需要链接的库EXE_LIBS算例目录算例的基本文件结构case/+0/包含初始和边界条件+con sta nt/包含初次读入后,不随时间变化的数据+polyMesh/包含多面体网格数据+tra nsportProperties/ 包含物性数据+system/包含计算控制和离散格式设定+con trolDict包含计算控制,如时间步长等+fvSchemes包含离散格式设定+fvSoluti ons包含代数求解器或SIMPLE,PISO算法设定具体而言case/0每个需求解的变量需要一个文件设定其初始边界条件case/c on sta nt/polyMesh网格数据,女口 owner neighbour points faces boundary case/system/transportProperties 物性数据case/system/fvSchemes 设定程序用到的每个微分算子的离散格式case/system/fvSolution 为每个变量选择代数方程求解器/收敛精度及PISO等算法设定三. OpenFOAM程序开发的理论知识作求解开发,必须能写出需要求解的控制方程及其定解条件,并且对于如何求解方程或方程组 的步骤已经明确。
这些流体力学、传热学以及相关的理论是必需的,所谓连续介质力学中的数学模型,控制方程 和定解条件就是表示它的语言在这里是不可能说清楚的,这要看个人的功底了四. OpenFOAM程序开发的最简单的例子下面采用OpenFOAM来开发一个用户自己的求解器主要是利用OpenFOAM的标准求解器 icoFoam,用户不需要写任何代码,只为为了熟悉OpenFOAM程序开发的环境和步骤步骤:1) 将icoFoam目录拷贝到新的目录可采用下面的Linux的命令实现:到 Ope nFOAM 的 in compressible 目录cd applicati on s/i ncompressiblecp - icoFoam myicoFoam以上只是复制目录icoFoam到新的位置,并且新目录名为myicoFoamcd myicoFoam进入新的目录,查看一下,可以看到里面的文件和icoFoam中是否一样2) 原文件改名,并且删除依赖文件将 icoFoam.C 改名 myicoFoam.Cmv icoFoam.C myicoFoam.C删除依赖文件rm icoFoam.dep3) 修改编译文件files和options进入Make目录,打开files文件,将icoFoam.C 源程序文件名EXE = $(FOAM_APPBIN)/icoFoam 可执行文件名修改为myicoFoam.C 源程序文件名EXE = $(FOAM_APPBIN)/myicoFoam 可执行文件名此例中options不需修改,可以打开看看EXE_INC = \ 头文件包含-l$(LIB_SRC)/fi niteVolume/l nln eludeEXE_LIBS = \ 链接库-Ifi niteVolume4) 删除原来的obj文件rm -rf linuxGccDPOptcd ..5) 编译wmake6) 检验一下到tutorial目录,检验一下myicoFoam . cavity六.OpenFOAM程序开发 例子一:在icoFoam中加入温度场求解准备:能量控制方程:dT/dt+div(de n*U*T)=div(a gradT)在壁面上给定值条件。
需要解决的问题:a) 如何创建标量场,Tb) 如何创建物性,ac) 如何定义温度方程,并求解d) 如何在算例中设定T和ae) 如何设定T的离散格式f) 如何设定T的求解器的收敛标准等步骤:1)创建程序需要的新物性和新变量场打开myicoFoam.C可以看到,程序开始运行时调用CreateFields.H,创建变量场打开CreateFields.H,可以看到程序首先从transportProperties文件中读入物性,Infovv "Read ing tra nsportProperties' n" vv en dl;lOdicti on ary tra nsportProperties(lOobject("tra nsportProperties", 从字典文件 tra nsportProperties 读入runTime.constant(), //transportProperties 文件位于目录 runTime.constant()中mesh, 网格对象IOobject::MUST_READ,IOobject::NO_WRITE));仓【J建了 Iodicti on ary 类型对象 tra nsportPropertiesdime nsio nedScalar nu 〃首先读入粘性系数(tra nsportProperties」o okup( "nu"));创建有量纲标量nu, nu通过从字典transportProperties查找”nu”来赋值可以加上新方程需要的物性dime nsio nedScalar DT 〃首先读入热扩散率(tra nsportProperties」o okup("DT"));创建有量纲标量DT,DT通过从字典transportProperties查找”DT”来赋值此外还要从createFields中读入p,U场,我们要加入的新的变量场为温度场T,最快的加入温 度场的方法是拷贝p场的代码,修改为In fovv "Readi ng field T\n" vv endl;volScalarField T(IOobject run Time.timeName(),mesh,IOobject::MUST_READ,IOobject::AUTO_WRITE),mesh);这样,创建了新的vol标量场T,从文件T中读入。
对于T的创建具体解释如下:a) 创建了标量场Tb) T通过读(IOobject::MUST_READ)在runTime.timeName()目录下名称为“T的文件创建,在开 始计算时,runTime.timeName()是 contorlDict 中设定的 startTime 值决定的c) T 将自动写入(IOobject::AUTO_WRITE)计算结果到 runTime.timeName()目录中,runTime.timeName()随迭代是变化的,写入控制由contorlDict中设定d) T是定义在mesh对象上的,这意味着T在内部cell上有值in ter nalField,在边界上还需要边 界条件,这与polyMesh/boundary中要一致2)在求解器中加入新的求解方程下一步回到myicoFoam.C加入新的微分方程,由于温度场依赖于速度场,可放在PISO循 环后面 in clude "con ti nuityErrs.H"U -= rUA*fvc::grad(p);U.correctBo un daryC on diti on s();// Add the temperature equati onfvScalarMatrix Teqn温度是标量方程(fvm::ddt(T)+ fvm::div(phi, T) 要用到界面流量-fvm::laplacian(DT, T)扩散项求解);TEqn. solve();3) 编译wmake 4)在算例中加入新方程的初始和边界条件4.1拷贝一个cavity算例到mycavity4.2 修改 transportProperties 字典文件,设定 DT cd con sta nt修改transportProperties文件,前面已提到DT要从该字典文件读入。
设定DT=0.002m2/s DT DT [0 2 -1 0 0 0 0] 0.002;4.3修改T文件,设定初始值和边界cd 0进入0目录拷贝一个T文件cp p T修改T文件为FoamFile {versi on 2.0;format ascii;class volScalarField;object T;}// * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * //dime nsi ons [0 0 0 1 0 0 0];in ter nalField un iform 300; 初始内部点为 300°Cmovin gWall{type fixedValue;value uniform 350.; 边界为 350CfixedWalls{type fixedValue;value uniform 300.; 边界为 300°C5) 修改离散格式和代数求解器求解控制文件A 进入system 目录由于温度方程有非稳态项,对流项,扩散项,分别要在ddt,div,laplacian中设置打开fvSchemes文件,添加divSchemes{default none;div(phi,U) Gauss upw ind;div(phi,T) Gauss upw ind;}laplacia nSchemes{default none;laplacia n(nu ,U) Gauss lin ear corrected;laplacia n(DT,T) Gauss lin ear corrected;laplacia n((1|A(U)),p) Gauss lin ear corrected;}在fvSolution中设置代数求解器选项T PBiCG{preconditioner DILU;tolera nee 1e-06;relTol 0;};注意T方程形成的矩阵是非对称的,不要用PCG和DIC6) 运行myicoFoam . mycavity七.OpenFOAM程序开发--求解器的详细分析1进入icoFoam目录可以看到createFields.H icoFoam.C icoFoam.dep Make/Make/为wmake编译所需的文件IcoFoam.C为主程序文件,它包含createFields.H编辑 icoFoam.C可以看到icoFoam.C首先引入的头文件为fvCFD.H。
所以你可以看到,在编译选项options中EXE_INC = \-l$(LIB_SRC)/finiteVolume/lnlnclude //fvCFD.H 的存放目录 EXE_LIBS = \-lfi niteVolume 〃需要链接的库找到fvCFD.H,编辑,可以看出这些是主程序必须的类库#if ndef fvCFD_H#defi ne fvCFD_H#i nclude "parRu n.H"#i nclude "Time.H" 时间类#i nclude "fvMesh.H" 网格类#i nclude "fvc.H" fvc 类#i nclude "fvMatrices.H" fvMatrix 类#include "fvm.H" fvm 类#in clude "li near.H"#in clude "calculatedFvPatchFields.H"#in clude "fixedValueFvPatchFields.H"#i nclude "adjustPhi.H"#i nclude "fi ndRefCell.H"#in elude "mathematicalC on sta nts.H"#i nclude "OSspecific.H"#i nclude "argList.H"#if ndef n amespaceFoam#defi ne n amespaceFoamusing n amespace Foam;#en dif #en dif再看看icoFoam的程序体,了解一下求解程序的结构#in clude "fvCFD.H" (头文件)通常位于ma in函数前,是程序所需的类的定义// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main (i nt argc, char *argv[]){ (包含文件)# include "setRootCase.H"# include "createTime.H"# include "createMesh.H" 包含文件通常是程序片断,如创建时间、创建网格等 (求解器代码) # include "createFields.H"需要根据应用,单独写的代码,如"createFields.H"和Ma in,以及Ueq n, pEq n等# include "initContinuityErrs.H"// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //}八.OpenFOAM程序开发一一求解器的详细分析2a. 场变量的定义引用前面的温度场In fovv "Readi ng field T\n" << endl; volScalarField T(IOobject(run Time.timeName(), mesh,IOobject::MUST_READ,IOobject::AUTO_WRITE ), mesh);例如volScalarField CO2 (IOobject(902",run Time.timeName(),mesh,IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),mesh,// Optional declaration, this can be done by accessing a file in "case/0/", 量纲可在文件中读// dime nsio nedScalar("zero", dime nsio nSet(1,-1,-3,0,0,0,0), value));b. 场变量的使用场变量有定义在内部cell上的值,也有边界上的值例如给组分限值Example of a mass fracti on limiter used in this project://I nitialize the variable Y_i for use in a loopscalarField& CO2Internal = CO2.internalField();引用内部点// Loop for all mesh points 遍历内部点forAll(CO2, celli){// Limits the mass fracti on to a positive nu mberif (CO2I nter nal[celli] < 0.0){CO2I nter nal[celli] = 0.0;}// Limits the mass fracti on to max 1.0if (CO2I nter nal[celli] > 1.0){CO2I nter nal[celli] = 1.0;}}c. 定义输运方程OpenFOAM 定义方程时要选择一种类型的 fvMatrix,有 fvScalarMatrix 和 fvVectorMatrix 离散格式在case/system/fvSchemes .中设定// Defi ne a ScalarMatrix as a objectfvScalarMatrix CO2Eqn 定义系数矩阵(fvm::div(phi, CO2) 对流项离散 fvm::div-fvm::laplacian(turbulence->nuEff(),CO2)扩散项离散 fvm::div==S_CO2 源项);// Apply un derrelaxati on to the equati on// Un der relaxati on factors defi ned in file: fvSoluti onCO2Eqn.relax();松弛CO2Eqn.solve();求解运用Ope nF OAM编译器wmake编译自己的程序本文将OpenFoam的编译系统介绍一下,并给出了如何在OpenFOAM下编译“hello wor程序。
OpenFOAM用的编译器是gcc,他并不是直接运用该编译器,而是将该编译器进行了包装,也 就是wmakeOpenFOAM中的头文件通常为H结尾,而代码文件是以C为扩展名,应当注意, 这里的C为大写的,如果写成小写,wmake会出现编译错误,尽管你编写的代码没有错误 运用wmake编译程序,程序所在的文件夹结构必须为如下形式| —neiuApp|-newApp. C| - cit her Header. H|-Make| -files| -optionsMake所在的文件夹中放有主程序和在主程序用到的所有头文件,这里面的代码文件和头文件名 字任意Make文件夹里面有两个文件files和options,这两个文件的名字不能改变files文件主要干两件事(1) 指定哪些文件需要编译,这里的文件是代码文件,也就是.C文件,而不包括.H文件(2) 指定你要编译的类型,是编译成库,还是编译成可执行文件,以及编译成的库文件或者可 执行文件的名字下面是icoFoam的Make文件夹下的files文件的内容icoFoam.CEXE = $(FOAM_APPBIN)/icoFoam要编译的代码文件直接将名字写到里面就行了,如果有多个代码文件,直接一个一个列在上面 就行了。
下面为编译程序类型EXE=,说明要编译成可执行文件,等号右面为编译后的文件放在什么地 方这一行也可以不写,他会将编译的可执行文件放到当前文件夹,名字为OpenFOAM.out.如果你要编译成库的话请采用”“LIB=…”等号后面放编译的库文件所在的目录,一般编译库文件 命名为 lib...,这是一个习惯,而非规定options 文件也是干两件事(1) 指定编译的头文件所在的目录,如果说所用的头文件在当前文件夹或者标准C++的头文件, 无需指定2) 指定编译当前程序所用到的库下面为 icoFoam 下的 options 文件的内容EXE_INC = \-I$(LIB_SRC)/finiteVolume/lnIncludeEXE_LIBS = \-lfiniteVolumeEXE_INC=用于所运用到的头文件所在的目录,EXE_LIB用来指定所有到的库注意这里的库 为OpenFOAM中的库或者你自己写的库,C++的标准库无需在这添加因此如果你不使用OpenFOAM中的库,而是自己独立编写C++程序,并且所有的头文件都在 当前的根目录, options 里无需指定任何东西下面是一个简单的“ Hello world”c++程序,按照我说的方法试一试?第1步:建立一个目录,用于编译当前的Hello world程序?下面为当根目录建立一个hello的文件夹,并进入hello文件夹。
cd //进入根目录mkdir hello //建立文件夹,名为 hellocd hello //进入 hello第 2 步: 建立 Make 文件夹,并进入 Make 建立 files 和 options 文件mkdir Make //建立 Make 文件夹cd Make //进入 Maketouch files //创建 files 文件touch options //创建 options 文件cd.. //退出 Make 文件夹第3步:建立程序文件hello.C,打开hello.C进行编程序touch hello.C //创建 hello.Ckate hello.C //打开 hello.C输入如下代码#include"iostream"using namespace std ;int main (){cout<<"hello world"<
在 CFD 计算过程中有两种残差一种是外残差一种是内残差残差是当前时刻的时刻的收敛数据 带入到下一个时刻的方程中而引起的残差,而内残差是求解代数方程中引起的残差外残差:对于方程f(x,t)=O在t_0时刻有收敛解x_0,则f(x_O,t=t_O)=O;当用tO时刻的结果代 入到tl时刻的方程时,通常并不能满足方程,即f(x_0, t = t_l) = r !=0;这里的残差r称为外残 差内残差:在cfd计算中通常将方程转化为代数方程Ax=b;当得到某个解A*x_0-b = r1;这里的 r1 ->0时,认为Ax=b收敛这里的r1为内残差对于稳态问题:只有当r->0时,才被认为收敛,也就是(x_l - x_0)->0.也就是我们在cfd计算 中通常见到的那个残差,fluent及其pyFoam输出残差图就是这个rR常被作为收敛判据对于非稳态问题,下一时刻的求解结果用于和当前的求解结果不一样(时变的,也就是非稳态), 这时候R并不是很小,对于特定的问题,这个R永远不可能很小(因为是非稳态问题),所。