openfoam文件读取

Posted he_He

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了openfoam文件读取相关的知识,希望对你有一定的参考价值。

对于openfoam或其他c++程序而言,文件的读取是尤为重要的

我们最开始学习C++时,会学到类的初始化,或者是变量定义为某个值,再对某个值进行遍历,,,
类似如下:

点击查看代码
#include <iostream>         // 包含头文件。

using namespace std;        // 指定缺省的命名空间。

int main()

    int a = 10;
    int b = (10);
    int c(10);
    int e = 10;
    int f 10 ;

    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    cout << "c=" << c << endl;
    cout << "e=" << e << endl;
    cout << "f=" << f << endl;


尤其c++,初学时候内心非常感慨,怎么这么多初始化方式,我该用哪个
现在回头看,其实能熟悉一个,其他看懂就行,看不懂都没关系,毕竟我们还有gdb或者typeid()帮忙,可以看看这个变量类型具体是什么
说到底我们要问题导向目标导向,我们学习C++是为了类似openfoam这样的大工程服务的
那学这么多初始化赋值,有必要吗
如果是个大工程或者大程序是完全没必要的,
因为大工程的数据都是从文件或者数据库中获得的
你想想,要计算一个流体问题,如果有一万个网格,手打一万个三维位置就已经非常让人头疼了,更不要说上百个组分和压力等参数了,不现实
所以又回到了问题的起点,读取文件很重要,那么如何从文件中初始化程序,如何读取文件


在看of源码之前,不妨复习下C++是怎么读取文件的,进行下知识巩固

C++多使用fstream类或ifstream类

点击查看代码
#include <iostream>
#include <fstream>  // ifstream类需要包含的头文件。
#include <string>     // getline()函数需要包含的头文件。
using  namespace std;

int main()

    string filename = R"(./test.txt)";

    //ifstream fin(filename, ios::in);
    ifstream fin;
    fin.open(filename , ios::in);

    // 判断打开文件是否成功。
    // 失败的原因主要有:1)目录不存在;2)文件不存在;3)没有权限,Linux平台下很常见。
    if (fin.is_open() == false)
    
        cout << "打开文件" << filename << "失败。\\n";  return 0;
    

    string buffer;
    while (fin >> buffer)
    
        cout << buffer << endl;
    

    fin.close();	   // 关闭文件,fin对象失效前会自动调用close()。

    cout << "操作文件完成。\\n";



OPENFOAM的文件读写,主要是用IOdictionary类

打开IOdictionary类的头文件,并不复杂

点击查看代码
class IOdictionary
:
    public baseIOdictionary


public:

    // Constructors

        //- Construct given an IOobject
        IOdictionary(const IOobject&);

        //- Construct given an IOobject and dictionary
        IOdictionary(const IOobject&, const dictionary&);

        //- Construct given an IOobject and Istream
        IOdictionary(const IOobject&, Istream&);

        //- Copy constructor
        IOdictionary(const IOdictionary&);

        //- Move constructor
        IOdictionary(IOdictionary&&);


    //- Destructor
    virtual ~IOdictionary();


    // Member Functions

        //- Is object global
        virtual bool global() const
        
            return true;
        

        //- Return complete path + object name if the file exists
        //  either in the case/processor or case otherwise null
        virtual fileName filePath() const
        
            return globalFilePath(type());
        


    // Member Operators

        //- Move assignment
        void operator=(IOdictionary&&);
;

继承于baseIOdictionary类,借助于IOobject接口有五个构造函数,这五个中一个移动构造一个拷贝构造,其他类继承可以创建自己成员函数global()和filePath(),头文件还对移动构造创建了等号赋值运算符
我们再看IOdictionary类的关键先生IOobject


IOobject就稍显复杂了,我们先看openfoam对其的描述:

IOobject defines the attributes of an object for which implicit objectRegistry management is supported, and provides the infrastructure for performing stream I/O.
An IOobject is constructed with an object name, a class name, an instance path, a reference to a objectRegistry, and parameters determining its storage status.

下面这张图是openfoam与该接口有关的类谱图

打开regIOobject类,这是个抽象类,openfoam对regIOobject的描述为:

regIOobject is an abstract class derived from IOobject to handle automatic object registration with the objectRegistry.

这里不赘述了,最后查了好半天,大概是哈希表来的,方便查询读取。openfoam中/0,/constant以及/system文件夹中那种奇怪的文件格式肯定有适合自己的读取方法。

那我们看看IOobject类相关源码,
IOobject类有四个枚举控制读取权限以及文件检查

点击查看代码
        //- Enumeration defining the valid states of an IOobject
        enum objectState
        
            GOOD,
            BAD
        ;

        //- Enumeration defining the read options
        enum readOption
        
            MUST_READ,
            MUST_READ_IF_MODIFIED,
            READ_IF_PRESENT,
            NO_READ
        ;

        //- Enumeration defining the write options
        enum writeOption
        
            AUTO_WRITE = 0,
            NO_WRITE = 1
        ;

        //- Enumeration defining the file checking options
        enum fileCheckTypes
        
            timeStamp,
            timeStampMaster,
            inotify,
            inotifyMaster
        ;

内共有六个构造函数,其中一个拷贝构造

点击查看代码
    // Constructors

        //- Construct from name, instance, registry, io options
        IOobject
        (
            const word& name,
            const fileName& instance,
            const objectRegistry& registry,
            readOption r=NO_READ,
            writeOption w=NO_WRITE,
            bool registerObject=true
        );

        //- Construct from name, instance, local, registry, io options
        IOobject
        (
            const word& name,
            const fileName& instance,
            const fileName& local,
            const objectRegistry& registry,
            readOption r=NO_READ,
            writeOption w=NO_WRITE,
            bool registerObject=true
        );

        //- Construct from path, registry, io options
        //  Uses fileNameComponents() to split path into components.
        IOobject
        (
            const fileName& path,
            const objectRegistry& registry,
            readOption r=NO_READ,
            writeOption w=NO_WRITE,
            bool registerObject=true
        );

        //- Construct from copy resetting registry
        IOobject
        (
            const IOobject& io,
            const objectRegistry& registry
        );

        //- Construct from copy resetting name
        IOobject
        (
            const IOobject& io,
            const word& name
        );

        //- Copy constructor
        IOobject(const IOobject& io) = default;

我们举个例子,基于这些构造函数可以这样写类似这样的读取端口:

点击查看代码
IOobject dicName(
    "dicName",
    runTime.timeName(),
    //runTime.constant(),
    mesh,
    IOobject::MUST_READ,
    IOobject::AUTO_WRITE
) ;

再回到IOdictionary类,

通过查看IOdictionary类的构造函数,我们了解到可以在创建好的IOobject端口基础上构建,也可以直接构建IOobject端口

点击查看代码
    IOdictionary dicName(
        IOobject (
            "dicName",
            //runTime.constant(),
            runTime.system(),
            mesh,
            IOobject::MUST_READ,
            IOobject::AUTO_WRITE
        )
    ) ;

那么我们如何通过IOdictionary类读取openfoam内文件呢,
以openfoam内置icoFoam为例
$ ls cavity/
0 constant system
$ tree cavity/
cavity/
├── 0
│ ├── U
│ └── p
├── constant
│ ├── polyMesh
│ │ ├── boundary
│ │ ├── faces
│ │ ├── neighbour
│ │ ├── owner
│ │ └── points
│ └── transportProperties
└── system
├── blockMeshDict
├── controlDict
├── fvSchemes
└── fvSolution
$ head cavity/0/* -n15

  • cavity/0/U *
    /--------------------------------- C++ -----------------------------------
    ========= |
    \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
    \\ / O peration | Website: https://openfoam.org
    \\ / A nd | Version: 8
    \\/ M anipulation |
    *---------------------------------------------------------------------------*/
    FoamFile

    version 2.0;
    format ascii;
    class ** volVectorField;**
    object U;

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

  • cavity/0/p *
    /--------------------------------- C++ -----------------------------------
    ========= |
    \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
    \\ / O peration | Website: https://openfoam.org
    \\ / A nd | Version: 8
    \\/ M anipulation |
    *---------------------------------------------------------------------------*/
    FoamFile

    version 2.0;
    format ascii;
    class ** volScalarField;**
    object p;

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    从以上内容可以看到,U和v分别属于volVectorField类以及volScalarField类,那么就利用IOobject接口分别创建相关类如下所示:

点击查看代码
    volVectorField U(
        IOobject(
            "U" ,
            runTime.timeName() ,
            mesh ,
            IOobject::MUST_READ ,
            IOobject::AUTO_WRITE
        ) ,
        mesh
    );
    volScalarField p(
        IOobject(
            "p" ,
            runTime.timeName() ,
            mesh ,
            IOobject::MUST_READ ,
            IOobject::AUTO_WRITE
        ) ,
        mesh
    );

再看其他两个文件夹
$ grep -rn "dicti" .
./cavity/constant/transportProperties:12: class dictionary;
./cavity/system/controlDict:12: class dictionary;
./cavity/system/fvSolution:12: class dictionary;
./cavity/system/blockMeshDict:12: class dictionary;
./cavity/system/fvSchemes:12: class dictionary;
./constant/transportProperties:12: class dictionary;
./system/controlDict:12: class dictionary;
./system/fvSolution:12: class dictionary;
./system/blockMeshDict:12: class dictionary;
./system/fvSchemes:12: class dictionary;
都是dictionary类,那创建起来更方便了,比如说contorlDict文件

点击查看代码
    IOdictionary controlDict(
        IOobject (
            "controlDict",
            runTime.constant(),
            //runTime.system(),
            mesh,
            IOobject::MUST_READ,
            IOobject::AUTO_WRITE
        )
    ) ;

有了dictionary这个字典类,顾名思义,字典当然是很方便查找啊,而且本身也是在链表以及哈希列表基础上建立的,能用的函数就很丰富了,如lookup()等。


综上,openfoam创建了一个读取方便查找容易的类支持of进行数据处理,寻根溯源很麻烦,但是用起来还是很简单的。

正因为文件读取占用很大的比重,这篇文章写了三个多小时,我们也是借此机会对openfoam内部略窥一二,这样我们就知道我们的程序在写什么,知道其所能为与不能为。


最后奉上自己编写的openfoam codesnip ,节约大家时间

点击查看代码
//***********************************************//
	//openfoam
	"Foam_IOobject": 
		"prefix": "IOobject_Foam_",
		"body": [
			"IOobject $1|U,p,T,dicName|(",
			// "\\t$2|\\"U\\",\\"p\\",\\"T\\"|",
			"\\t\\"$1\\",",
			"\\t//runTime.timeName(),",
			"\\t//runTime.constant(),",
			"\\tmesh,",
			"\\tIOobject::MUST_READ,",
			"\\tIOobject::AUTO_WRITE",
			") ;"
		],
		"description": "FOAM::IOobject"
	,
	"Foam::IOdictionary": 
		"prefix": "IOdictionary_Foam_",
		"body": [
			"IOdictionary $1:dicName(",
			"\\tIOobject (",
			// "\\t$2|\\"U\\",\\"p\\",\\"T\\"|",
			"\\t\\t\\"$1\\",",
			"\\t\\t//runTime.constant(),",
			"\\t\\t//runTime.system(),",
			"\\t\\tmesh,",
			"\\t\\tIOobject::MUST_READ,",
			"\\t\\tIOobject::AUTO_WRITE",
			"\\t)",
			") ;"
		],
		"description": "Foam::IOdictionary"
	,
	"Foam::volVectorField": 
		"prefix": "volVectorField_Foam_",
		"body": [
			"volVectorField $U(",
			"\\tIOobject (",
			"\\t\\t\\"$U\\",",
			"\\t\\trunTime.timeName(),",
			"\\t\\tmesh,",
			"\\t\\tIOobject::MUST_READ,",
			"\\t\\tIOobject::AUTO_WRITE",
			"\\t),",
			"\\tmesh",
			") ;"
		],
		"description": "Foam::volVectorField"
	,
	"Foam::volScalarField": 
		"prefix": "volScalarField_Foam_",
		"body": [
			"volScalarField $p(",
			"\\tIOobject (",
			"\\t\\t\\"$p\\",",
			"\\t\\trunTime.timeName(),",
			"\\t\\tmesh,",
			"\\t\\tIOobject::MUST_READ,",
			"\\t\\tIOobject::AUTO_WRITE",
			"\\t),",
			"\\tmesh",
			") ;"
		],
		"description": "Foam::volScalarField"
	,
	"Foam::scalar": 
		"prefix": "scalar",
		"body": [
			"scalar "
		],
		"description": "Foam::scalar"
	,
	//***********************************************//

创作不易,如若喜欢,不胜感激,欢迎支持,欢迎指正

以上是关于openfoam文件读取的主要内容,如果未能解决你的问题,请参考以下文章

openfoam软件自带的算例描述或讲解有吗?在哪里

在 OpenFOAM 中使用 snappyHexMesh 和 STL 文件的教程

包含来自另一个文件的函数会导致范围错误 (openFoam)

OpenFoam:在 polyMesh 文件夹中找不到 blockMeshDict 文件

用python读取VTK文件

openFOAM- 在 Web 查看器 VTK.js 上可视化 vtk 文件