参考:
感谢原作者们的无私引路和宝贵工作。
前置:
OpenFOAM开发编程基础02 主函数参数列表类初步 | 𝓐𝓮𝓻𝓸𝓼𝓪𝓷𝓭 (aerosand.cn)
本文简单介绍 OpenFOAM 中的 Time 类,在此基础上讨论了 createTime.H
头文件。
建立本文的项目文件夹并进入
1 2 3 4
| // terminal cd /home/aerosand/aerosand/ofsp mkdir 03_time cd 03_time
|
OFextension 插件使用
十分推荐在 vscode 中安装社区插件 OFextension
参考 OpenFOAM在VS Code下的debug模式调试 - 知乎 (zhihu.com)
配置插件
Ofextension: OFpath
设置正确的 OpenFOAM 安装路径
- 使用 vscode 打开用户的开发应用,使用
F1
输入 ofInit
初始化配置
代码编写
在应用开发中,例如本文应用,在主源码中输入 runTime.
,vscode 会自动弹出可选的 runTime
方法(成员函数)。
而且可以在主源码中选中头文件、类等,右键使用 Go to Definition
,Go to Declaration
等,直接跳转查看源代码。
非常推荐此插件,十分方便。注意不要在 OpenFOAM 源文件夹下初始化。
程序调试
- 调试算例的文件夹名称保持为
debug_case
userApp/Make/options
中的 EXE_INC =
下的第一行需要添加 -g \
调试参数
- 执行
ofInit
初始化配置
- 给代码行打点,进入 vscode 调试界面进行调试
时间类方法
应用准备
1 2 3 4 5
| // terminal foamNewApp 03_01_time cd 03_01_time cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity debug_case code .
|
脚本和说明
读者可能感受到前几篇文章使用的脚本对每个不同的应用都要重新写,十分繁琐。
我们逐渐介绍一些更方便的脚本写法。
新建脚本
1 2
| // terminal code caserun caseclean
|
caserun
脚本负责应用编译成功后,调试算例的运行,内容如下
1 2 3 4 5 6 7 8 9 10 11 12
| #!/bin/sh cd "${0%/*}" || exit 1
appPath=$(cd `dirname $0`; pwd) appName="${appPath##*/}"
blockMesh -case debug_case | tee debug_case/log.mesh echo "Meshing done."
$appName -case debug_case | tee debug_case/log.run
|
$0
返回当前脚本的绝对路径
%xxx
去除 xxx 字符
/*
表示 /
及之后的所有字符
不用担心脚本语言,暂时只需要知道使用上述脚本即可,更深入的脚本语言会随着讨论深入而逐渐介绍。
caseclean
脚本负责清理调试算例,还原到初始状态,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/sh cd "${0%/*}" || exit 1
appPath=$(cd `dirname $0`; pwd) appName="${casePath##*/}"
cd debug_case
rm -rf log.* foamCleanTutorials echo "Cleaning Done."
|
这两个脚本自动获取应用路径和应用名称,所以也适合后续讨论的其他应用使用,只需要复制使用即可。注意,上述写法不适合 .sh
文件格式,因为脚本语言的语法会导致上述脚本中的 cd
语句报错。
使脚本生效
1 2
| // termianl chmod +x caserun caseclean
|
使用方法
1 2 3
| // terminal ./caserun ./caseclean
|
除非特殊强调,以后均使用这两个脚本。
createTime.H
看一下和时间类相关的头文件 createTime.H
1 2 3
| // termianl find $FOAM_SRC -iname createTime.H // /usr/lib/openfoam/openfoam2306/src/OpenFOAM/include/createTime.H
|
如果使用 OFextension
可以直接跳转。
内容如下
1 2 3
| Foam::Info<< "Create time\n" << Foam::endl;
Foam::Time runTime(Foam::Time::controlDictName, args);
|
第一行是正常的输出语句。
第二行构造了一个 Foam::Time
类型的 runTime
对象,构造基于 controlDictName
和 args
。
args
需要先创建,所以 createTime.H
要在 setRootCase.H
之后
Time
是一个非常基础的类,具有很多的成员数据和成员方法。我们大概挑几处代码作为切入点简单了解一下 Time
类。
1 2 3
| // termianl find $FOAM_SRC -iname Time.H // /usr/lib/openfoam/openfoam2306/src/OpenFOAM/db/Time/Time.H
|
推荐使用 OFextension
插件,直接跳转查看,以后不再赘述。
打开 Time.H
,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ... class Time : public clock, public cpuTime, public TimePaths, public objectRegistry, public TimeState { public: ... private: ... protected: ... private: ... public: ... inline Time ( const word& ctrlDictName, const argList& args, const bool enableFunctionObjects = true, const bool enableLibs = true ); ... virtual dimensionedScalar startTime() const;
virtual dimensionedScalar endTime() const; ... ...
|
方法的实现较为复杂,对于现阶段来说,基础类没有必要去深入讨论代码的实现部分,目前只需要做到心里有数、看到不那么陌生即可。
主源码
在主源码中使用时间类方法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include "fvCFD.H"
int main(int argc, char *argv[]) { #include "setRootCase.H" Foam::Info<< "Create time\n" << Foam::endl; Foam::Time runTime(Foam::Time::controlDictName, args);
Info<< "Case name : " << runTime.caseName() << endl; Info<< "Root path : " << runTime.rootPath() << endl; Info<< "Path : " << runTime.path() << endl; Info<< "Time path : " << runTime.timePath() << endl; Info<< "Controdict : " << runTime.controlDict() << endl; Info<< "Format : " << runTime.writeFormat() << endl; Info<< "Version : " << runTime.writeVersion() << endl; Info<< "Start time : " << runTime.startTime() << endl; Info<< "End time : " << runTime.endTime() << endl; Info<< "Time step : " << runTime.deltaT() << endl;
Info<< "# set end time = 10" << endl; runTime.setEndTime(10);
Info<< "# set deltaT = 1" << endl; runTime.setDeltaT(1);
Info<< "Start time : " << runTime.startTime() << endl; Info<< "End time : " << runTime.endTime() << endl; Info<< "Time step : " << runTime.deltaT() << endl;
while (runTime.loop()) { Info<< "Time: " << runTime.timeName() << endl; runTime.write(); }
Info<< nl; Info<< "Execution time: " << runTime.elapsedCpuTime() << " s" << endl; Info<< "Clock time: " << runTime.elapsedClockTime() << " s" << endl;
Info<< "End\n" << endl;
return 0; }
|
编译运行
通过终端编译运行此应用
1 2 3 4
| // terminal wmake ./caseclean ./caserun
|
运行结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| Create time
Case name : "debug_case" Root path : "/home/aerosand/aerosand/ofsp/03_timeMesh/03_01_time" Path : "/home/aerosand/aerosand/ofsp/03_timeMesh/03_01_time/debug_case" Time path : "/home/aerosand/aerosand/ofsp/03_timeMesh/03_01_time/debug_case/0" Controdict : { application icoFoam; startFrom startTime; startTime 0; stopAt endTime; endTime 0.5; deltaT 0.005; writeControl timeStep; writeInterval 20; purgeWrite 0; writeFormat ascii; writePrecision 6; writeCompression off; timeFormat general; timePrecision 6; runTimeModifiable true; }
Format : ascii Version : 2.0 Start time : startTime [0 0 1 0 0 0 0] 0 End time : endTime [0 0 1 0 0 0 0] 0.5 Time step : deltaT [0 0 1 0 0 0 0] 0.005 # set end time = 10 # set deltaT = 1 Start time : startTime [0 0 1 0 0 0 0] 0 End time : endTime [0 0 1 0 0 0 0] 10 Time step : deltaT [0 0 1 0 0 0 0] 1 Time: 1 Time: 2 Time: 3 Time: 4 Time: 5 Time: 6 Time: 7 Time: 8 Time: 9 Time: 10
Execution time: 0 s Clock time: 0 s End
|
小结
加上之前的讨论,我们已经大体理解 OpenFOAM 应用中常见的 setRootCase.H
和 createTime.H
头文件,下一篇将讨论最后一个必备头文件 createMesh.H
。
Copyright Notice: 此文章版权归aerosand.cn所有,如有转载,请注明来自原作者