ofsp2024-05 场初步

ofsp2024-05 场初步
Created time
Jul 10, 2025 11:09 AM
type
status
date
slug
summary
tags
category
icon
password
Last edited time
Jul 10, 2025 11:13 AM
😀
前言: Preface:
 
参考:
感谢原作者们的无私引路和宝贵工作。
前置: OpenFOAM开发编程基础04 网格类初步 | 𝓐𝓮𝓻𝓸𝓼𝓪𝓷𝓭 (aerosand.cn)
OpenFOAM 的计算绝大部分都是基于物理场的。基于前几次讨论,本文开始讨论 OpenFOAM 中场的基本操作。
为了操作方便,我们可以在 bashrc 中定义快捷命令(参考 OpenFOAM 环境准备 | 𝓐𝓮𝓻𝓸𝓼𝓪𝓷𝓭 (aerosand.cn)
建立本文的项目文件夹并进入

场的创建

有单位量

dimensionSet

前文用到了 OpenFOAM 的单位预设,其定义在 $FOAM_SRC/OpenFOAM/dimensionSet/dimensionSets.C ,文件中还定义了很多预设单位
回忆 OpenFOAM 的单位设置为 [质量, 长度, 时间, 温度, 摩尔, 电流, 光强] 。
我们可以设置自定义变量的物理单位,如

dimensionedType

在 OpenFOAM 代码中可以看到如下类似语句
查找源代码如下
找到并摘取其中的构造函数如下
OpenFOAM 中还提供了其他的构造函数,我们可以在不同情况下构造自己的有单位物理量。目前阶段来说,我们不需要继续深挖源代码。点到为止,明白确实可以这样用,并且以后按照这种方式去用就可以了。
当然,dimensionedType.H 也定义了配套的成员函数,比如
由此,我们可以便捷的使用 value() 成员函数,例如对上面的 airPressure 取值,再计算最大值
注意,OpenFOAM 会检查数学计算式等号两遍的最终单位是否相同,如果不同则会强制报错并中断程序,后续代码会面临并解决这个问题。

volFields

我们会注意到 OpenFOAM 中有典型的语句如下
那么 volScalarField 是什么呢?又是如何构造场的呢?
我们讨论一下场是怎么被创建的。
也许有同学疑惑“我怎么知道要查看这个文件”。参考 OpenFOAM开发编程基础03 时间类初步 | 𝓐𝓮𝓻𝓸𝓼𝓪𝓷𝓭 (aerosand.cn) 第一节, 安装 OFextension 插件后,直接在 volScalarField 关键字上右键跳转即可。也可以打开 OpenFOAM Doxygen (OpenFOAM: User Guide: OpenFOAM®: Open source CFD : Documentation),查询相关关键字。除特殊情况,以后不再赘述。
volFieldFwd.H 中有类型定义如下
可以看到,volFields 包括常见的 volScalarFieldvolVectorField,是体积场量。无论是 volScalarField 还是 volVectorField 其实都是 GeometricField 的模板的不同情况。所以, volFields 只是一种分类的称呼,而不是真正的类。

surfaceFields

同样的,面场量 surfaceFields 包括常见的 surfaceScalarFieldsurfaceVectorField
surfaceFieldFwd.H 中有类型定义如下
可见,surfaceFields 也是 GeometricField 的模板的不同情况。
surfaceFields 的 surface 都可以写完整,为什么 volFields 的 volume 要简写成 vol 呢?也许是历史代码的原因吧。。。

GeometricField

进一步的,我们查看 GeometricField.H 文件
摘取类的主要结构和几个常用构造函数如下
上述构造函数,对应实际的场的构造,分别举例如下
这三个例子对应了最常见的场的构造函数,暂时明白这三个即可。其他构造函数以及更深入的代码层面的解析在以后会陆续介绍,无需担心。读者也可以尝试多阅读几个。

场的时间推进

我们以压力场为例,结合场的创建,讨论一下场的时间推进计算。

应用准备

脚本和说明

略。

单时间步计算

主源码

编译运行

注意到主源码中的场的覆写是不区分初始时间步和后续时间步的,而且 foamCleanTutorials 命令不能恢复初始时间步文件夹内的场文件的内容。所以,为了避免初始条件被覆盖,强烈推荐备份初始条件。一旦初始场被覆盖,可以随时复原。操作如下
编译运行,结果如下
查看 debug_case/ 文件夹下,多了 0.005/ 文件夹,其中的 0.005/p 文件中写入了计算的场。最后的输出就是最新时间步的场的值。

多时间步计算

如何计算多个时间步呢?

主源码

主源码修改如下
关于写成 ++runTime 而不是 runTime++ 的讨论
  • 在 C++ 中,原则上前置 ++ 的效率更高

编译运行

注意要先清理算例,避免错误,以后不再赘述。
编译运行,结果如下
观察 debug_case/ 文件夹下多了三个时间步的文件夹,如下
查看各个时间步的压力场值,可以知道终端最后输出的值为最新时间步的计算值。

字典控制计算

即使是多时间步计算,我们也是直接修改主源码的计算时间步个数,每次修改都要重新编译整个应用。如果是大型应用,重新编译会相当麻烦。
在实际工作中,我们希望在应用编译完成后,也可以通过外部文件去控制计算,也就是使用 OpenFOAM 的字典文件 controlDict 控制计算。

主源码

主源码修改如下

编译运行

清理调试算例,重新编译运行,结果如下
调试算例 debug_case/ 文件多了几个时间步文件夹,分别是 0.1, 0.2, 0.3, 0.4, 0.5,写入的时间步正好由 system/controlDict 控制。
controlDict 字典的部分参数如下(每 0.005*20 = 0.1 写入一次)
这些参数都可以随时修改调试,无需重新编译应用。

场的基本操作

下面我们伪计算压力场、温度场、速度场。
  1. 求出网格单元和参考点的最大距离
  1. 根据时间、网格单元向量、参考向量、最大距离这 4 个参数计算压力场
  1. 根据压力梯度通过量纲处理,计算速度场

应用准备

脚本和说明

略。

增加物理场

拷贝过来的调试算例并没有温度场,我们给算例添加初始温度场。
温度和压力一样是标量,所以先拷贝压力场文件再修改。
温度场初始条件 debug_case/0/T,内容如下

主源码

编译运行,结果如下
使用 paraview 将计算结果可视化。注意打开需要路径
注意到 debug_case/ 的时间步文件夹下新建了很多场文件,以 debug_case/0.3/ 为例,其文件结构如下
可以查看各个场文件中的数值。
注意:
打开 0.3/phi 可以看到并没有计算更新值,其他非 p,U 文件也没有计算更新值。这是因为场在创建时候给定的计算公式只是初始化,并不会随着时间推进而计算更新。所以,需要在主源码的时间循环中去计算需要的场。

代码整理

在 OpenFOAM 实际应用中,一般的
  • “场的接入”放入单独的文件 createFields.H
  • OpenFOAM 本身提供 createPhi.H
  • 自定义方法也放入单独文件,如 calculatePressure.H
所以该应用的文件结构调整后为
场接入文件 createFields.H
自定义方法 calculatePressure.H
最终主源码整理为
整理后的这种形式更接近 OpenFOAM 求解器等应用的代码组织形式。
  • 主源码功能划分非常清晰
  • 每个功能都更加易于维护
编译运行结果当然还是一样的。

小结

回顾这 5 篇讨论,我们大概可以感受到数值计算的核心要素所在——时间、网格、物理场。有了这些对象之后,我们便可以组建线性代数方程,进行数值求解。不要着急,我们距离求解器编程越来越近了。
 
 
 
💡
欢迎留言讨论,反馈建议和意见,赞助打赏。 Feel free to leave comments, feedback, suggestions, opinions, and donations..
Alipay
Alipay
 
 
上一篇
ofsp2024-06 开发库
下一篇
ofsp2024-04 网格类初步
Loading...