openfoam学习心得——openfoam编程进阶
openfoam学习心得——openfoam编程重新学
1、OpenFOAM编程入门:setRootCase都干了些啥?
setRootCase都干了些啥
2、blockMesh > log.blockMesh
运行blockMesh这个命令,并将其output写进log文件里面
可以看blockMesh源代码学习数据的写入
3、mesh.boundaryMesh() 返回polyBoundaryMesh类
polyBoundaryMesh类输出结果
(movingWall{type wall;inGroups List<word> 1(wall);nFaces 20;startFace 760;}fixedWalls{type wall;inGroups List<word> 1(wall);nFaces 60;startFace 780;}frontAndBack{type patch;nFaces 800;startFace 840;}
)
**polyPatch类:**
type wall;
inGroups List<word> 1(wall);
nFaces 20;
startFace 760;**fvboundarymesh类****fvPatch类:**polyPatch可以理解为fvPatch的一个总和,fvpatch用来计算面中心等
4、openfoam Workshop
5、The openfoam technology primer–边界条件与几何场如何结合的
6、 TypeName (“base”)与defineTypeNameAndDebug(AlgorithmBase,0)-必须写类全名
展开为:
ClassName("base");
virtual const word& type() const {return typeName}
再展开:
ClassNameNoDebug("base");
static int debug
virtual const word& type() const {return typeName}
再展开:char*可以指向一个字符串TypeName ("base")最终展开
static const char* typeName_(){return "base"} //返回classname
virtual const word& type() const {return typeName} //返回typename-虚函数,可被覆盖
static const ::Foam::word typeName
static int debug
这里初始化了两个变量但是没有赋值,下面来看赋值:
defineTypeNameAndDebug(AlgorithmBase,0)
展开为:
defineTypeName(AlgorithmBase)
defineDebugSwitch(AlgorithmBase,0)--debug有关,不深究
展开为:
defineTypeNameWithName(AlgorithmBase,AlgorithmBase::typeName_());
defineDebugSwitch(AlgorithmBase,0)
最后展开为:
const Foam::word AlgorithmBase::TypeName(AlgorithmBase::typeName_())
defineDebugSwitch(AlgorithmBase,0)
咋一看,对于此类类对象,其typeName_()与type()返回值是一样的,但是注意type() 方法是虚函数,固当用指针时,将产生奇效,如下:
autoPtr< incompressible::turbulenceModel > turbulence
turbulence->typeName_() --返回turbulenceModel
turbulence->type() --返回kOmega
7、 RTS机制相关宏函数展开
完整代码请移步:openfoam RTS机制分析
第一个要学习的宏函数如下,顺带学习下如何展开宏函数:
#define declareRunTimeSelectionTable(autoPtr,baseType,argNames,argList,parList)\\/* Construct from argList function pointer type */ \typedef autoPtr<baseType> (*argNames##ConstructorPtr)argList; \\/* Construct from argList function table type */ \typedef HashTable<argNames##ConstructorPtr, word, string::hash> \argNames##ConstructorTable; \\/* Construct from argList function pointer table pointer */ \static argNames##ConstructorTable* argNames##ConstructorTablePtr_; \\/* Table constructor called from the table add function */ \static void construct##argNames##ConstructorTables(); \\/* Table destructor called from the table add function destructor */ \static void destroy##argNames##ConstructorTables(); \\/* Class to add constructor from argList to table */ \template<class baseType##Type> \class add##argNames##ConstructorToTable \{ \public: \\static autoPtr<baseType> New argList \{ \return autoPtr<baseType>(new baseType##Type parList); \} \\add##argNames##ConstructorToTable \( \const word& lookup = baseType##Type::typeName \) \{ \construct##argNames##ConstructorTables(); \if (!argNames##ConstructorTablePtr_->insert(lookup, New)) \{ \std::cerr<< "Duplicate entry " << lookup \<< " in runtime selection table " << #baseType \<< std::endl; \error::safePrintStack(std::cerr); \} \} \\~add##argNames##ConstructorToTable() \{ \destroy##argNames##ConstructorTables(); \} \}; \\/* Class to add constructor from argList to table */ \/* Remove only the entry (not the table) upon destruction */ \template<class baseType##Type> \class addRemovable##argNames##ConstructorToTable \{ \/* retain lookup name for later removal */ \const word& lookup_; \\public: \\static autoPtr<baseType> New argList \{ \return autoPtr<baseType>(new baseType##Type parList); \} \\addRemovable##argNames##ConstructorToTable \( \const word& lookup = baseType##Type::typeName \) \: \lookup_(lookup) \{ \construct##argNames##ConstructorTables(); \argNames##ConstructorTablePtr_->set(lookup, New); \} \\~addRemovable##argNames##ConstructorToTable() \{ \if (argNames##ConstructorTablePtr_) \{ \argNames##ConstructorTablePtr_->erase(lookup_); \} \} \};
declareRunTimeSelectionTable--一次声明对应一个构造函数(autoPtr, AlgorithmBase, Word, argNames--word构造、copy构造等(const word& algorithmName argList-此构造函数形参数),(algorithmName))
展开后如下:
上面宏中###是为了区分开参数与非参数
typedef autoPtr< AlgorithmBase > (*WordConstructorPtr)( const word& algorithmName );
函数指针--WordConstructorPtr理解成一个类,其对象就是函数指针
string::hash默认参数,word是key,value是WordConstructorPtr类(或叫函数指针)
typedef HashTable< WordConstructorPtr, word, string::hash > WordConstructorTable;
初始化哈希表指针-静态的,父类、子类对象均可访问此表-所有对象访问的都是同一张表
static WordConstructorTable* WordConstructorTablePtr_;
函数声明
static void constructWordConstructorTables();
static void destroyWordConstructorTables();
template< class AlgorithmBaseType >--类中类
class addWordConstructorToTable --将构造函数添加到Hash表中
{public:static autoPtr< AlgorithmBase > New ( const word& algorithmName ){给指向基类的指针动态分配内存-指向由word构造生成的基类对象return autoPtr< AlgorithmBase >(new AlgorithmBaseType (algorithmName));}找类中的typename静态名称addWordConstructorToTable ( const word& lookup = AlgorithmBaseType::typeName ){调用前面声明的函数constructWordConstructorTables();New函数是一个前面指定好的函数指针类型if (!WordConstructorTablePtr_->insert(lookup, New)){std::cerr<< "Duplicate entry "<< lookup << " in runtime selection table "<< "AlgorithmBase" << std::endl;error::safePrintStack(std::cerr);}}析构函数,因为前面的函数中一旦调用将产生有动态分配的内存~addWordConstructorToTable(){destroyWordConstructorTables();}
};
类中类
template< class AlgorithmBaseType >
class addRemovableWordConstructorToTable
{const word& lookup_; 私有成员public:静态函数:返回一个基类指针,其指向的可能是别的对象======植入进哈希表的是一个函数static autoPtr< AlgorithmBase > New ( const word& algorithmName ){return autoPtr< AlgorithmBase >(new AlgorithmBaseType (algorithmName));}======植入进哈希表的是一个函数addRemovableWordConstructorToTable ( const word& lookup = AlgorithmBaseType::typeName ): lookup_(lookup){constructWordConstructorTables();WordConstructorTablePtr_->set(lookup, New);}=======删除某个哈希表元素~addRemovableWordConstructorToTable(){if (WordConstructorTablePtr_){WordConstructorTablePtr_->erase(lookup_);}}
};
上面声明了一个静态数据成员-一张哈希表,key-typename;value是一个函数:此函数的功能是为基类指针复制基类或子类对象。下面的宏将上述静态变量与函数展开。
defineRunTimeSelectionTable(AlgorithmBase, Word)展开后如下:
初始化
AlgorithmBase::WordConstructorTable* AlgorithmBase::WordConstructorTablePtr_ = __null;不至于变成野指针void AlgorithmBase::constructWordConstructorTables() {static bool constructed = false;if (!constructed) {constructed = true;初始化哈希表指针-分配了内存AlgorithmBase::WordConstructorTablePtr_ = new AlgorithmBase::WordConstructorTable; }};如果这个指针不为空指针,就删除堆内存的对象,并设置为空指针void AlgorithmBase::destroyWordConstructorTables() {if (AlgorithmBase::WordConstructorTablePtr_) {delete AlgorithmBase::WordConstructorTablePtr_;AlgorithmBase::WordConstructorTablePtr_ = __null;}};
至此,上述的类变定义完成了,我们也搞清楚了类中每个函数的意思,下面还有一个宏来使用上面定义好的类。
addToRunTimeSelectionTable(AlgorithmBase, AlgorithmBase, Word)展开为:
这里告诉我们如何调用类中类
AlgorithmBase::addWordConstructorToTable< AlgorithmBase > addAlgorithmBaseWordConstructorToAlgorithmBaseTable_;
上面初始化一个类中类对象,在初始化过程中,为基类的哈希表中插入了key-value对,这说明这个表会一直存在。即时再用别的基类对象访问这个表,此表仍然存在相同的数据。第一个AlgorithmBase表示addWordConstructorToTable方法位于基类中,第二个参数AlgorithmBase,代表了插入的key-value的typename函数以及New函数的功能,其返回的是一个基类还是子类对象有此参数指定。可能有点难理解,我们来看其子类。
class AlgorithmNew
:public AlgorithmBase
{public: // Declare the static variable typeName of the class AlgorithmNew.TypeName ("new");// Empty constructor. AlgorithmNew () {};// Word constructor.AlgorithmNew (const word& algorithmName) {};// Make the class callable (function object) virtual void operator()(){Info << "AlgorithmNew::operator()()" << endl;}
};
defineTypeNameAndDebug(AlgorithmNew, 0);
addToRunTimeSelectionTable(AlgorithmBase, AlgorithmNew , Word);
此时基类的static成员,哈希表中应该是这样的:
AlgorithmBase – New函数–返回基类指针,指针指向的是以word构造生成的AlgorithmBase类对象
AlgorithmNew – New函数–返回基类指针,指针指向的是以word构造生成的AlgorithmNew类对象
再来一个继承:
class AlgorithmAdditional
:public AlgorithmNew
{public: // Declare the static variable typeName of the class AlgorithmAdditional.TypeName ("additional");// Empty constructor. AlgorithmAdditional () {};// Word constructor.AlgorithmAdditional (const word& algorithmName) {};// Make the class callable (function object) virtual void operator()(){// Call base operator explicitly.AlgorithmNew::operator()();// Perform additional operations.Info << "AlgorithmAdditional::operator()()" << endl;}
};defineTypeNameAndDebug(AlgorithmAdditional, 0);
addToRunTimeSelectionTable(AlgorithmBase, AlgorithmAdditional , Word)
此时基类的static成员,哈希表中应该是这样的:
AlgorithmBase – New函数–返回基类指针,指针指向的是以word构造生成的AlgorithmBase类对象
AlgorithmNew – New函数–返回基类指针,指针指向的是以word构造生成的AlgorithmNew类对象
AlgorithmAdditional – New函数–返回基类指针,指针指向的是以word构造生成的AlgorithmAdditional 类对象
这个表在编译的时候就已经永恒存在了,可以发现都是以word构造生成的对象,要是我有别的构造呢?如copy构造,原理相同。
注意,表中的New函数是定义在addWordConstructorToTable类中-此类为基类中的类的,在基类中同样有一个New函数,充当selector
static autoPtr< AlgorithmBase > New (const word& algorithmName){输入一个typename--也就是keyWordConstructorTable::iterator cstrIter =WordConstructorTablePtr_->find(algorithmName);找不到就报错// If the Factory Method was not found. if (cstrIter == WordConstructorTablePtr_->end()){FatalErrorIn("AlgorithmBase::New(const word&)") << "Unknown AlgorithmBase type "<< algorithmName << nl << nl<< "Valid AlgorithmBase types are :" << endl<< WordConstructorTablePtr_->sortedToc()<< exit(FatalError);}cstrIter()--返回key对应的value,也就是new函数,并传参定义基类指针。return cstrIter()(algorithmName);}
从上面代码我们可以学习到,哈希表类中有个迭代器的类中类,()运算符被重载,用来返回key对应的value。
综上学习完毕,RTS机制说直接点就是在基类中生成一个静态的哈希表,基类和子类每编译一次,就往哈希表中加入一个值,其加入值的方法也很精妙,竟然是初始化类中类对象,这个值是永恒的,与求解器运行与否无关,同时基类中还会有一个静态的New函数,用来做选择,看看到底调用哈希表中的哪个函数指针,生成什么类型的对象赋予基类指针。可以猜想定义湍流模型肯定是需要往哈希表中加值的。
8、湍流模型中的RTS分析
1. turbulenceModel 类中
declareRunTimeNewSelectionTable宏-–生成一个哈希表,同时生成往哈希表中插值的类,此时的类中类New函数–也就是此类中哈希表的value返回的是key值所对应类的New函数–选择器:
defineRunTimeSelectionTable宏–这个宏是定义declareRunTimeNewSelectionTable宏中所声明的函数用的
2.RASModel类中
declareRunTimeSelectionTable宏–生成一个哈希表,同时生成往哈希表中插值的类,这个返回的是基类或子类对象。
defineRunTimeSelectionTable(RASModel, dictionary)宏–说明是哈希表中New函数返回的对象是由字典构造生成的。
addToRunTimeSelectionTable(turbulenceModel, RASModel, turbulenceModel)宏–说明将RASModel类添加到turbulenceModel类的哈希表中:
也就是RASModel(类的typename) New—这个函数返回RASModel::New
3、kEpsilon类中
addToRunTimeSelectionTable(RASModel, kEpsilon, dictionary)宏–说明将kEpsilon类添加到RASModel的哈希表中,采用字典构造生成kEpsilon类对象,返回给基类指针。
把类添加到哈希表等同于key=类的typename,value=New函数(属于类中类的New函数),其返回此类对象。某一个类中存在哈希表,则存在select(属于基类的New函数),可以在哈希表中用迭代器来选择函数执行。
故而我们在文件中指定的都是typename–可能与类名相同,也可能不同,一般是一样的。
综上,autoPtr< incompressible::turbulenceModel > turbulence
(
incompressible::turbulenceModel::New(U, phi, laminarTransport)
);运行过程为,turbulenceModel::New根据字典选择RASModel,则调用RASModel中的RASModel::New函数,然后根据字典选择kEpsilon,则在生成kEpsilon对象。
openfoam学习心得——openfoam编程进阶相关推荐
- openfoam学习心得—壁面函数在CFD中如何实施
openfoam学习心得-壁面函数在CFD中如何实施 最近研究壁面函数,发现邱教授博客,讲的很是不错!记录一下 http://xiaopingqiu.github.io/2016/04/25/wall ...
- openfoam学习心得--N-S方程无数种写法汇总与转换
openfoam学习心得–N-S方程无数种写法汇总与转换以及守恒与非守恒型 在学习openfoam的途中,楼主被流体中存在的无数个方程.同一个方程无数种写法弄的晕头转向,决定对此做一些总结,方便以后查 ...
- C++学习心得和进阶路线总结
C++学习心得和进阶路线总结 借用王国维老先生的话,C++学习也可以分为四个阶段 C++缺点之一,是相对许多语言复杂,而且难学难精.许多人说学习C语言只需一本K&R<C程序设计语言> ...
- OpenFOAM学习网站汇总(更新中)
推荐几个好用的OpenFOAM学习网站: 官网,里面包含了相应的安装包及配套安装教程以及CFD的一些基本知识: 苏军伟的博客,里面讲述了苏教授对于OpenFOAM求解器的一些理解,对于初学者有很大帮助 ...
- 【一起学OpenFOAM】04 OpenFOAM的学习资源
OpenFOAM的学习资料并不多,个人猜测也许是与软件的类型有关系. 对于商用软件来讲,由于要占领市场,软件开发商自然是巴不得会用软件的人越多越好,因为他们卖的是软件,会用的人越多,软件卖得越好.他们 ...
- 计算机编程老鸟的心得,java入门123——一个老鸟java学习心得.docx
java入门123--一个老鸟的java学习心得 学习Java心得体会 学习了一学期的Java课程,觉得是该总结自己的心得体会了.开始学习任何一门课(包括java),兴趣最重要.一直觉得自己在学计算机 ...
- c语言编程基础心得,C语言编程学习心得体会
C语言是在国内外广泛使用的一种计算机语言.其语言功能丰富.表达能力强.使用灵活方便.既具有高级语言的优点,又具有低级语言的许多特点,适合编写系统软件.本文是C语言编程学习心得,希望对大家有帮助. C语 ...
- c语言程序培训,C语言编程培训学习心得
说到C语言学习真的是千言万语,可以说C语言在世界语言排行榜中位居前列,像一些操作系统.驱动软件.多媒体软件.大型游戏. 杀毒软件等等软件操作系统,都是C\C++的特区,对于其他语言来讲真的是望尘莫及. ...
- c语言编程培训心得体会,编程培训个人心得体会 编程学习心得
<编程培训个人心得体会 编程学习心得>由会员分享,可在线阅读,更多相关<编程培训个人心得体会 编程学习心得(4页珍藏版)>请在人人文库网上搜索. 1.编程培训个人心得体会 编程 ...
最新文章
- mqttnet 详解_MQTTnet 3.0.5学习笔记
- 利用windows的rar工具创建自解压安装文件的方法
- linux 系统迁移到固态硬盘,windows 和 Linux 系统 从硬盘迁移到SSD
- 云服务器可以安装操作系统么,云服务器安装操作系统吗
- ant的下载与安装——mybatis学习笔记之预备篇(一)
- WindowsAPI中PostMessage与SendMessage的区别
- python大于小于_在Python中大于/小于Pandas DataFrames / Series之间的比较
- mui 时间样式错乱_微信公众号素材样式中心在哪?公众号动态分割线怎么添加?...
- 【转载】向量空间模型VSM及余弦计算
- ECCV 2020 论文大盘点-实例分割篇
- LaTeX TikZ绘图——组合数学中棋盘多项式的画法
- php jquery mysql,使用PHP / MySQL搜索并使用jQuery动态更新
- django1.11 mysql配置_Mysql没有使用python3.6与Django 1.11.7连接
- Kubernetes master无法加入etcd 集群解决方法
- Python【每日一问】27
- Python-查看python版本-常用代码-VS编译器版本号
- android 汉字笔顺,汉字笔画顺序之启动界面一
- SI4463实验笔记
- 深度篇——目标检测史(五) 细说 SSD 目标检测
- 数据脱敏:k-anonymity,l-diversity,t-closeness