對於openfoam或其他c++程式而言,文件的讀取是尤為重要的 我們最開始學習C++時,會學到類的初始化,或者是變數定義為某個值,再對某個值進行遍歷,,, 類似如下: 點擊查看代碼 #include <iostream> // 包含頭文件。 using namespace std; // 指定預設 ...
對於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"
},
//***********************************************//
創作不易,如若喜歡,不勝感激,歡迎支持,歡迎指正