OpenFOAM開發編程基礎02 主函數參數列表類初步
參考:
https://github.com/UnnamedMoose/BasicOpenFOAMProgrammingTutorials https://www.topcfd.cn/simulation/solve/openfoam/openfoam-program/ https://www.tfd.chalmers.se/~hani/kurser/OS_CFD/ https://github.com/ParticulateFlow/OSCCAR-doc/blob/master/openFoamUserManual_PFM.pdf https://www.youtube.com/watch?v=KB9HhggUi_E&ab_channel=UCLOpenFOAMWorkshop http://dyfluid.com/# https://ss1.xrea.com/penguinitis.g1.xrea.com/study/OpenFOAM/index.html 感謝原作者們的無私引路和寶貴工作。
OpenFOAM 初學者很難不注意到求解器總是有幾個固定的頭文件,包括 setRootCase.H ,createTime.H 和 createMesh.H 。網絡上找到的代碼解析常常只有一句注釋介紹功能,也許無法消除困惑感。
更新和勘誤詳見 aerosand.cn。
本文同樣從 C++ 開始,簡單介紹主函數參數,在此基礎上討論 setRootCase.H 頭文件。
建立本文的項目文件夾并進入
// terminal
cd /home/aerosand/aerosand/ofsp
mkdir 02_args
cd 02_args
C++ 實現
主函數參數
我們在初學 C++ 的時候,主函數的參數列表一般留空,即有如下形式
...
int main() // 省略參數列表
{
...
}
當進一步深入 C++ 開發時,了解到主函數的更一般寫法為
...
int main(int argc, char *argv[]) {}
// 或者
int main(int argc, char **argv) {}
-
argc即argument count的縮寫,保存程序運行時傳遞給主函數的參數個數 -
argv即argument vector的縮寫,保存程序運行時傳遞給主函數的具體參數的字符型指針,每個指針都指向一個具體的參數。 -
argv[0]指向程序運行時的全路徑名稱 -
argv[1]指向程序運行時命令行中執行程序名后第一個字符串 -
argv[2]指向程序運行時命令行中執行程序名后第二個字符串 -
其他以此類推
項目實現
新建項目 02_arg/02_01_args/
主源碼 src/main.cpp 如下所示
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "Number of arguments = " << argc << std::endl;
for (int i=0; i<argc; ++i)
{
std::cout << "Argument " << i << ": "
<< argv[i] << std::endl;
}
return 0;
}
終端直接編譯運行
// terminal
make run
運行結果如下
Number of arguments = 1
Argument 0: ./output/main
如果運行時增加參數,例如
// terminal
./output/main hi hey hello
運行結果如下
Number of arguments = 4
Argument 0: ./output/main
Argument 1: hi
Argument 2: hey
Argument 3: hello
基于主函數參數列表的了解,下面討論 OpenFOAM 中的主函數參數等內容。
OpenFOAM 實現
應用準備
// terminal
cd /home/aerosand/aerosand/ofsp/02_args/
foamNewApp 02_02_args
cd 02_02_args
cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity debug_case
code .
文件結構如下
|- 02_02_args/
|- debug_case/
|- 0/
|- constant/
|- system/
|- Make/
|- files
|- options
|- 02_02_args.C
以后非特別情況不再贅述文件結構。
腳本和說明
新建腳本
// terminal
code _appmake.sh _appclean.sh _caserun.sh _caseclean.sh README.md
腳本內容和說明文檔略。
setRootCase.H
先看一下主源碼中的頭文件 setRootCase.H
// termianl
find $FOAM_SRC -iname setRootCase.H
// $FOAM_SRC/OpenFOAM/include/setRootCase.H
代碼具體為
// Construct from (int argc, char* argv[]),
// - use argList::argsMandatory() to decide on checking command arguments.
// - check validity of the options
Foam::argList args(argc, argv); // 構造argList類型的args變量
if (!args.checkRootCase()) // 如果檢查應用參數(算例路徑)錯誤
{
Foam::FatalError.exit(); // 報錯退出
}
// User can also perform checks on otherwise optional arguments.
// Eg,
//
// if (!args.check(true, false))
// {
// Foam::FatalError.exit();
// }
// Force dlOpen of FOAM_DLOPEN_LIBS (principally for Windows applications)
#include "foamDlOpenLibs.H" // 兼容性處理,無需深究
代碼討論
-
該 H 文件檢查了該應用的參數是否正確 -
構造參數列表的對象 args(所以此 H 文件需要放在所有的參數代碼等后面) -
如果參數列表檢查不通過,則報錯退出
argList 類是一個非常基礎的類,具有很多的成員數據和成員方法。我們大概挑幾處代碼作為切入點簡單了解一下 argList 類。
// terminal
find $FOAM_SRC -iname argList.H
// /usr/lib/openfoam/openfoam2306/src/OpenFOAM/global/argList/argList.H
打開 argList.H ,內容如下
...
class argList
{
...
public:
...
// 基于參數的構造函數
argList
(
int& argc, // 主函數參數個數
char**& argv, // 主函數參數的指針
bool checkArgs = argList::argsMandatory(),
bool checkOpts = true,
bool initialise = true
);
...
...
方法的實現較為復雜,對于現階段來說,基礎類沒有必要去深入討論代碼的實現部分,目前只需要做到心里有數、看到不那么陌生即可。
在上一篇文章的討論中,也可以深入看一下 OpenFOAM 的
IOdictionary類,終端使用命find $FOAM_SRC -iname IOdictionary.H,可以找到對應的構造函數原型。也可以查找到IOobject.H中的構造函數原型。
主源碼
幫助信息
#include "fvCFD.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"Demonstrates how to handle command line options.\n\n"
"Application arguments:\n"
"----------------------\n"
" mathLib - Eigen/GSL/Armodillo/BLAS\n"
" level - computation speedup\n"
);
#include "setRootCase.H"
#include "createTime.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< nl;
runTime.printExecutionTime(Info);
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //
編譯后查看幫助信息
// terminal
02_02_args -help
終端輸出
Usage: 02_02_args [OPTIONS]
Options:
-case <dir> Case directory (instead of current directory)
-decomposeParDict <file>
Alternative decomposePar dictionary file
-parallel Run in parallel
-doc Display documentation in browser
-help Display short help and exit
-help-full Display full help and exit
Demonstrates how to handle command line options.
Application arguments:
----------------------
mathLib - Eigen/GSL/Armodillo/BLAS
level - computation speedup
Using: OpenFOAM-2306 (2306) - visit www.openfoam.com
Build: _fbf00d6b-20230626
Arch: LSB;label=32;scalar=64
可以看到我們自定義的幫助信息。
應用參數
應用參數(arguments)在執行應用命令時是強制需要的,下一節的應用選項(option)是可選的。
給主源碼增加應用參數如下
#include "fvCFD.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"Demonstrates how to handle command line options.\n\n"
"Application arguments:\n"
"----------------------\n"
" mathLib - Eigen/GSL/Armodillo/BLAS\n"
" level - computation speedup\n"
);
argList::validArgs.append("mathLib");
argList::validArgs.append("level");
// 將應用參數增補到主函數參數列表里
// 這兩個參數是強制必須的
#include "setRootCase.H" // 構造OpenFOAM的argList類型的args對象
#include "createTime.H"
#include "createMesh.H"
// args第0參數是程序名本身
const word args1 = args[1]; // args第1參數就是增補的第1個參數
const scalar args2 = args.get<scalar>(2); // 增補的第2個參數
// 顯示參數
Info<< "Solver setup: " << nl
<< " use : " << args1 << nl
<< " speedup : " << args2 << nl
<< nl << endl;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< nl;
runTime.printExecutionTime(Info);
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //
終端運行是必須要提供相應類型的參數
編譯后運行
// terminal
blockMesh -case debug_case
02_02_args -case debug_case GSL 2
結果為
Create time
Create mesh for time = 0
Solver setup:
use : GSL
speedup : 2
ExecutionTime = 0 s ClockTime = 0 s
End
應用選項
應用選項在運行時可寫可不寫。
主源碼如下
#include "fvCFD.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"Demonstrates how to handle command line options.\n\n"
"Application arguments:\n"
"----------------------\n"
" mathLib - Eigen/GSL/Armodillo/BLAS\n"
" level - computation speedup\n"
);
// 應用參數要在 setRootCase.H 構造 args 之前
argList::validArgs.append("mathLib");
argList::validArgs.append("level");
// 應用選項也要在 setRootCase.H 構造 args 之前
argList::addOption
(
"dict",
"word",
"Use addtional dictionary (just for example)"
);
argList::addOption
(
"nPrecision",
"label",
"Set the precision level (just for example)"
);
argList::addBoolOption
(
"log",
"output the log"
);
// setRootCase.H 將構造argList類型的args對象
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
const word args1 = args[1];
const scalar args2 = args.get<scalar>(2);
Info<< "Solver setup: " << nl
<< " use : " << args1 << nl
<< " speedup : " << args2 << nl
<< nl << endl;
// 創建_dict并給默認初始值
fileName _dict("./system/myDict");
if (args.found("dict"))
{
args.readIfPresent("dict",_dict);
// 如果使用了 -dict 選項,則使用 -dict 后的值
// 也許會有同學疑問上面這句代碼為什么能讀取 -dict 后的值并傳給 _dict
// 建議先不要深究,以后熟悉C++了可以翻閱OpenFOAM更底層的源代碼
Info<< "Reading myDict " << endl;
}
Info<< "Dictionary from " << _dict << nl << endl;
// 創建 label 類型的對象并給默認初始值
label _nPrecision(6);
args.readIfPresent("nPrecision",_nPrecision);
Info<< "Precision is " << _nPrecision << endl;
const bool _log = args.found("log");
if (_log)
{
Info<< "Output the logs" << endl;
}
// 只要使用 -log 選項,就會執行一些方法,比如這里的輸出
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< nl;
runTime.printExecutionTime(Info);
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //
編譯運行應用
// terminal
blockMesh -case debug_case
02_02_args -case debug_case GSL 2 -dict ../constant/myDict -nPrecision 12
運行結果為
Create time
Create mesh for time = 0
Solver setup:
use : GSL
speedup : 2
Reading myDict
Dictionary from "../constant/myDict"
Precision is 12
ExecutionTime = 0 s ClockTime = 0 s
End
如果運行應用如下
02_02_args -case debug_case GSL 2 -dict ../constant/myDict -log
運行結果為
Create time
Create mesh for time = 0
Solver setup:
use : GSL
speedup : 2
Reading myDict
Dictionary from "../constant/myDict"
Precision is 0
Output the logs
ExecutionTime = 0.01 s ClockTime = 0 s
End
應用選項 -dict 也有默認值,可以嘗試省略并運行應用。
通過使用不同的應用選項,看到各行源代碼的效果。
小結
從 C++ 基礎出發, 簡單討論了主函數運行時的幫助、參數和選項。雖然上面的開發都是僅停留在表面做做樣子,但目的也是使讀者對 OpenFOAM 中運行應用的命令行方法有了一些了解,以后也可以在此基礎上深入。更深入的開發見后續討論。
本文基本搞明白了 OpenFOAM 求解器中必備的 setRootCase.H 到底是什么,那么 createTime.H 頭文件到底是什么呢?
文章來源: Aerosand
工程師必備
- 項目客服
- 培訓客服
- 平臺客服
TOP




















