基于有限差分法的面向对象程序设计

计算科学 有限差分
2021-12-15 08:53:21

通常,使用过程规划方法(PP)通过有限差分法(FDM)求解偏微分方程是很自然的。也就是说,一 (1) 定义矩阵来存储节点处的属性和节点之间的通量,(2) 基于对控制方程的离散化组装线性系统,(3) 求解线性方程,并且 (4) 进入下一次步。由于每个控制方程在整个域中求解一个属性,因此定义一个属性的矩阵非常方便。

但到目前为止,我意识到使用这种方法的一些(可能)缺点,即用于过程(2)的模块(或子例程)不容易移植到解决另一个基本方程的另一个程序。基本上,如果要解决另一个问题,则需要从头开始(当然矩阵求解器除外)。

有人建议我使用面向对象的编程方法(OOP)来处理这个问题,这种方法对代码进行模块化非常方便,并且模块的可重用性很高。

据我了解,通过 OOP 方法,可能不会定义存储整个域的属性的矩阵,而是定义具有许多属性的每个节点(使用对象)。这种方法在光滑粒子流体动力学和格子玻尔兹曼方法等一些拉格朗日方法中是相当稳健的。但是由于矩阵已经被分解,这种方法可能不太方便求解线性系统。

相比之下,现在很多编程开始支持OOP,甚至fortran也开始支持对象。另外,目前有很多使用OOP概念的FDM、有限元法(FEM)、有限体积法(FVM)包(例如openfoam),只需要定义基本方程,然后脱敏似乎使用相同的代码完成. 我认为使用 PP 处理可能并不容易。我必须对 OOP 的想法有所遗漏。

当然这个问题可能不限于使用有限差分方法,还可以使用 FVM 和 FEM,在我看来,用 OOP 概念来构建似乎更难。

有任何想法吗?提前致谢!

Ps:我一般使用fortran,matlab,R,python来处理CFD和使用PP的多孔介质中的多相流问题。

2个回答

OOP 在科学编程中具有很大的实用性,但是在接受非科学软件工程教育后编写“OOP”科学程序的自然方式可能是解决问题的不好方法。轶事:

  • 我作为本科生的第一个半严肃的 CFD 代码,我编写了一个有限体积的 2D Euler 方程求解器,过度使用了 OOP。直观地说,我认为“单元”将是一个很好的类,每个类都有指向在单元之间共享的“面”类的指针。然后我遍历单元格和面部对象。即,我有几百万个“细胞”和“脸”类型的小物体。它非常慢——这些元素的每次访问都会导致大量的取消引用指针。

作为一般经验法则,我建议听取 CUDA 人员的建议(出于同样的原因——这对了解高性能代码的人来说不是新闻):

  • 大数组的小结构比小结构的大数组好。

查看 Damian Rouson 的“Scientific Software Design: The Object Oriented Way”,了解如何将 OOP 用于高性能代码。我在那里的细节有一些严重的问题,但它仍然相当不错。

对于有限差分或有限元使用过程编程,绝对没有什么是“自然的”。事实上,过去 15 年来出现的所有广泛使用的有限元方法软件包都是面向对象的(例如 libmesh、openfoam、我自己的 library deal.II、fenics...),同样如此用于线性代数包(例如,petsc、trilinos)。这并不意味着每一件事情(比如一个单元)都应该是一个对象,但可以肯定的是,像网格、矩阵、有限元这样的东西都可以作为类来实现。在我们的社区中,毫无疑问这是处理大型软件的唯一可能方式。

SciComp StackEchange 网站上还有其他几个处理类似问题的问题。