openFOAM C++代码的一些特性
目录
数值耗散和数值频散
对非线性化项的处理
OpenFOAM程序最基本的架构
OpenFOAM里的代码和C++的区别
关于#include的文件
fvCFD.H
using namespace std
主函数main函数
编译
Make/options文件内容指定
报错咋办
OpenFOAM中的内置类型非常多
OpenFOAM中包含了一些自定义的宏
C++代码例子
OpenFOAM实例
代码封装
数值耗散和数值频散
由于cfd旨在用差分方程代替微分方程,所以差分方程是微分方程的逼近,但二者之间总有误差。误差由阶次不同,可造成解的耗散和频散,其中耗散就如给流场添加了人为的粘性一样,使得本来尖锐的突越变得平滑,分辨率降低。
简单的说截断项中偶数阶微分的存在使得解具有耗散性,奇数阶微分的存在使得解具有频散性。比如一道正弦曲线,耗散使之幅值变低,而频散使之相位和周期发生变化。
https://zhidao.baidu.com/question/399291950.html
对非线性化项的处理
由于非线性求解器非常复杂,因此在OpenFOAM均采用线性化处理。
OpenFOAM程序最基本的架构
每个程序会通过单独一个文件夹来包含(如myFirstFoam文件夹),在这个文件夹下,存在一个Make文件夹,Make中包含files和options文件。同时在myFirstFoam文件夹中,需要包含程序文件(如myFirstFoam.C)。
目录文件夹下的.C文件是OpenFOAM/C++的主程序(注意大写);
Make文件夹是OpenFOAM特有的,里面主要包含两个文件files和options;
files用来指定OpenFOAM顺序进行编译的文件名称以及路径;
options用来指定OpenFOAM需要调用的外挂库的路径以及名称;
OpenFOAM里的代码和C++的区别
输出语句中的cout
被Info
替代,Info
是OpenFOAM中用来输出的语句。不仅仅可以输出字符串,也可以输出其他各种的场(比如体向量场等)。后面的nl
在OpenFOAM中用来表示换行,等同于C++中的endl
。
$(LIB_SRC)
是一个环境变量,在OpenFOAM中等同于$(FOAM_SRC)
,其真实的位置可以通过键入echo $FOAM_SRC来查看。
关于#include的文件
后期编程的时候,则是用户需要自己去OpenFOAM源文件里面找的。需要什么头文件,就写什么头文件。举例,用户可能需要在编程环境中调用volScalarField
类型,这样,就需要在程序最开始,将volScalarField
这个类型进行包含。在OpenFOAM中,可以通过#include "volFields.H"
来处理。其中的volFields.H
,只能用户自己去找,没有规律。
fvCFD.H
OpenFOAM中fvCFD.H文件是一个非常大的框架,它把OpenFOAM中大部分的基本的类型都包含了,在初学不知道应该调用OpenFOAM具体的什么类型的时候,建议直接把fvCFD.H文件进行包含省去寻找具体头文件的过程。
using namespace std
using namespace std之后,就省去了std::,可以直接引用std空间里面的函数和变量。
一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。
例如小李和小韩都参与了一个文件管理系统的开发,它们都定义了一个全局变量 fp,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 fp 重复定义(Redefinition)错误。
为了解决合作开发时的命名冲突问题,C++ 引入了命名空间(Namespace)的概念。请看下面的例子:
namespace Li{ //小李的变量定义FILE fp = NULL;
}
namespace Han{ //小韩的变量定义FILE fp = NULL
}
小李与小韩各自定义了以自己姓氏为名的命名空间,此时再将他们的 fp 变量放在一起编译就不会有任何问题。
namespace 是C++中的关键字,用来定义一个命名空间,语法格式为:
namespace name{//variables, functions, classes
}
::
是一个新符号,称为域解析操作符,在C++中用来指明要使用的命名空间。
http://c.biancheng.net/view/2192.html
主函数main函数
main
函数是一个特殊的函数,在可执行的OpenFOAM/C++程序中,它总是最先运行的代码。int main()
声明了一个叫做main
的函数,它没有参数。如果有参数的话,它们的名称应该出现在小括号()
。但具有一个返回值,类型为int
,因此在程序的最后,会存在一行代码return 0;
。最简单的理解方法是,将所有的主程序函数头都写成int main()
(当然你可以写成void main()
,它并不需要返回值)。但其中的main
是不能变的,大小写也不能变,必须这样写。
编译
OpenFOAM中所有的程序(库)的编译器调用命令为:wmake,用户应该切换到程序目录下,运行wmake
Make/options文件内容指定
options用来指定OpenFOAM需要调用的外挂库的路径以及名称;
报错咋办
同时注意,在提示missing separator
错误之后,即使添加好\
也依然会报错。这时候需要用wclean命令清空一下,再运行wmake。提醒:某些情况下如果Gcc编译器不匹配你的OpenFOAM版本号,也会出现类似问题。这也解释了,为什么比较高版本的OpenFOAM需要比较高版本的Gcc编译器。
OpenFOAM中的内置类型非常多
比如:
volScalarField
体标量场:比如CFD中定义在网格上的温度场;volVectirField
体矢量场:比如CFD中定义在网格上的速度场;fvScalarMatrix
标量矩阵:比如CFD中离散湍流动能生成的稀疏线性系统;autoPtr
OpenFOAM智能指针:OpenFOAM自定义的智能指针;processor
处理器边界类型:并行计算的处理器边界类型;
在这里并不能够全部列举。这需要同学们在以后使用OpenFOAM的过程中持续的摸索。
常用类总结:http://blog.sina.com.cn/s/blog_5333fbde0100dagt.html
对于程序,最常用到的,也是最底层的就是数据,在OpenFOAM中引入了三类基础数据类型:标量scalar, 向量vector, 张量tensor.这三个中数据类型,也是FOAM中最基础的三个类。(还有一个比较重要的就是bool和label,前者就是是非型,及对错型,只不过是更扩展一些,后者是标签型数据,相当于c中的整型。关于更多的其它数据类型可以参看目录..\src\OpenFOAM\primitives里面)
在上述数据类的基础上,增加场(field)的概念,就引入了标量场scalarField, 向量场vectorField, 张量场tensorField.实际上这三个类又是field类的typedef,如typedef field<scalar> 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("p",runTime.timeName(),mesh,IOobject::MUST_READ,IOobject::AUTO_WRITE),mesh);
这是读入标量压力场文件,把压力值存储到网格体中心。为加深对GeometricField类的理解,贴张PG中的图片:
除了体的向量标量张量场外,还有面标量场surfaceScalarField、面向量场surfaceVectorField、面张量场surfaceTensorField。看下面的例子:
surfaceScalarField phi(IOobject("phi",runTime.timeName(),mesh),fvc::interpolate(alpha)*phia+ fvc::interpolate(beta)*phib);
这里的phi既是一个面向量场对象,他用来是纪录单元体面上流过的通量值。
除了常用到的标量向量张量的几何场外,还有一些特殊量的场:surfaceSymmTensor面对称张量几何场、体球面张量场等等。几何场里面还有一个比较重要的类就是GeometricBoundaryField,用来专门对边界进行处理的一个类。
OpenFOAM中包含了一些自定义的宏
其中一些语句可用来执行CFD专属的循环。比如forAll()
语句是非常常用的OpenFOAM语句。看下面的代码:
forAll(U, cellI)
{U[cellI] = vector(1, 0, 0);
}
其中forAll()
为一种遍历,其需要传入两个参数,在上面的例子中,第一个参数为U
(一个volScalarField
),则此forAll()
表示对整个计算域的网格进行循环。括号内的U[cellI] = vector(1, 0, 0);
表示对每个网格的U[cellI]
进行赋值。需要注意的是,上面的例子并不对U的边界进行处理。
如果forAll()
内传入surfaceScalarField
,则对内部的面进行循环,例如:
forAll(phi, index)
{phi[index] = 0.0;
}
上面的代码将phi
内部的面赋值为0。同样的,本例子不对phi
的边界进行处理。
C++代码例子
double shit(double a, int b);//函数返回double类型,名称为shit(),传入一个double类型a,一个int类型bint main()
{double whatName;double a = 2.1;int b = 0;whatName = shit(a, b);//调用shit()函数并将返回值赋给whatNamereturn 0;
}double shit(double a, int b)//函数定义
{
//函数具体计算代码略
}
//函数返回double类型,名称为shit(),传入一个double类型a,一个int类型b
double shit(double a, int b);
{
//函数具体计算代码略
}int main()
{double whatName;double a = 2.1;int b = 0;whatName = shit(a, b);//调用shit()函数并将返回值赋给whatNamereturn 0;
}
OpenFOAM实例
//在main()函数之前的函数定义,返回volScalarField类型,函数名为Function()
volScalarField Function
(//传入一个volVectorField类型volVectorField U,//传入一个dimensionedScalar类型dimensionedScalar nu
)
{
//略
}int main()
{volScalarField p = Function(velocity, nu);//声明一个volScalarField类型叫做p//将Function(velocity, nu)函数返回的volScalarField赋值给p
}
代码封装
我们把类的声明放在了.H文件中,类的实现放在了.C文件中,对这个.C文件进行编译,可以形成一个库(后缀为.so)。同时,在主程序内,将类的.H文件进行包含,同时在options文件中嵌入库文件,即可将程序成功编译。如果同学们想把自己的库函数封装,需要进行下面的步骤:
在自己的电脑上编写类的.H文件和.C文件;
编译出库文件;
拷贝.H文件和库文件给其他用户,其他用户的程序文件中即可调用这个库,并调用其中的库函数(类接口);
需要注意的是,你并不需要把.C文件拷贝给其他人,其他人即可调用你的库(你的函数实现)。这,就是非常典型的类封装过程。因为你的.C文件包含了所有函数实现,且没有被外传。
很多软件都是进行的类似的操作,很有可能同学们下载了一款软件,其中包含了大量的.so文件(在windows下后缀为.dll的文件),然后包含若干的文件头。很明显,这就是封装后的代码。
同时提醒的是,OpenFOAM为一款开源CFD求解器,并不支持闭源行为。
openFOAM C++代码的一些特性相关推荐
- 那些开源程序中让人叹为观止的代码 - 1 浏览器特性判断
浏览器特性判断 解决问题:判断某事件/方法在当前浏览器中是否支持 开源程序:Modernizr 众所周知,各个不同的浏览器对于代码渲染的实现也各自为政百花齐放,虽然有W3C在维护着标准,但是由于市面上 ...
- html中写一个占内存很大死循环代码,HTML5新特性Bug:这12行代码分分钟让你浏览器崩溃iPhone重启...
使用这十二行JavaScript代码能让firefox.chrome.safari等众多浏览器崩溃,甚至让iPhone重启? 起因 今天刷推特的时候发现Cyber Security@cyber__se ...
- C++ 随心记5 C++17 较好用的新特性 (一)令代码简洁的特性
这部分大体包括语法糖(封装优化好的库函数或模块),以及一些令代码更简洁.可读性更强的函数与库. 1. 结构化绑定 C++ 17以前,使用for循环遍历map / unordered_map 时候需要声 ...
- openfoam安装中出现allmake error_深入理解 OpenFOAM 环境与编译过程
深入理解 OpenFOAM 环境变量与编译 操作系统选择 由于 OpenFOAM 在 Linux 平台开发和测试,在非 Linux 平台无法直接对软件进行编译和安装,所以在非 Linux 平台上最简便 ...
- 三,ES6中需要注意的特性(重要)
-----书接上文,前文中我们总结了关于JS的组成部分以及如何快速开展学习JS,相信已经有很多朋友掌握到这些方法.接下来就从更深的ECMAScript开始说起. 1.什么是ES6? ECMAScrip ...
- java 静态代码块 多线程,Java多线程编程笔记10:单例模式
立即加载:"饿汉模式" 立即加载就是指使用类的时候已经将对象创建完毕,常见的实现方法就是直接new实例化.也就是在调用方法前,实例就被创建了.示例代码如下所示: class MyO ...
- 微软发布代码智能新基准数据集CodeXGLUE,多角度衡量模型优劣
来源 | 微软研究院AI头条 编者按:代码智能(code intelligence)目的是让计算机具备理解和生成代码的能力,并利用编程语言知识和上下文进行推理,支持代码检索.补全.翻译.纠错.问答等场 ...
- Lombok!代码简洁神器还是代码“亚健康”元凶?
以下文章来源方志朋的博客,回复"666"获面试宝典 关于Lombok,DD是一个重度用户,从我编写的Spring Boot教程还是Spring Cloud教程中,都可以看到几乎每个 ...
- 微服务测试之静态代码扫描
静态代码扫描为整个发展组织增加价值.无论您在开发组织中发挥的作用如何,静态代码扫描解决方案都具有附加价值,拥有软件开发中所需要的尖端功能,最大限度地提高质量并管理软件产品中的风险. 背景 微服务架构模 ...
最新文章
- java1.8新增超实用Map方法——Map.getOrDefault()和Map.value()方法详解
- java中定义类的关键字为_在Java中,定义类的关键字是__________________.
- gradle不能下载最新依赖包问题
- 读取STM32单片机-ID操作
- c++实现解析文件路径
- 学python要有多少英语词汇量测试_非常适合新手的一个Python爬虫项目: 打造一个英文词汇量测试脚本!...
- Mac搭建PHP+rabbitMQ环境
- kubernetes 升级到1.6
- Mybatis Sql 大于号小于号不兼容
- python制作软件安装包_Python安装包及开发工具
- 基于JMP的神经网络设计案例分析
- Python实现直角坐标系求两点间距离
- 基于esp32的物联网设计
- 百度云网盘一直显示“下载请求中”,一个 解决办法
- 细说Java性能测试第三课 性能测试详解2
- RuntimeError: iter() is only supported inside of tf.function or when eager execution is enabled.
- 魔方机器人大赛——视觉算法
- ERROR 1366(HY000)报错解决方法
- 【线性代数】6-7:SVD分解(Singular Value Decomposition-SVD)
- 如何实现一个精简版的redux-saga
热门文章
- 基于arm-linux-gcc版本,音乐视频播放器mplayer
- ffmpeg笔记(一)音视频基础
- 三维重建方法--激光or视觉
- word里如何在□里打√!框框里打勾!!!!!
- 0xc0000225无法进系统_U盘装win10后无法进系统错误代码0xc0000225怎么修复
- 线下 Meetup 预告|从原理到实战,详解 Database Plus 的互联网最佳实践
- mysql pid无法写入_ERROR /usr/libexec/mysqld:写入文件'/var/run/mysqld/mysqld.pid'时出错(错误代码:28)...
- python学习(五)--打印错误信息
- Springboot启动后频繁打印错误日志 /null/swagger-ui.html解决方案
- 线性规划-pulp-复杂矩阵