科学计算文献

计算科学 Python C++ 正则
2021-11-27 10:41:42

也许,这是一个转储问题。但无论如何。

我为发电机理论中的一类问题开发了一个有限差分代码。我使用了非常适合测试的 GNU Octave (MATLAB)。问题规模成二次方。因此,未知数变得相对较大。

我正在考虑用不同的编程语言重写我的程序。在我的印象中,科学计算中最常用的语言是 FORTRAN、C++ 或 Python。我想说的是,我不想重新发明轮子。

得到这个想法的一些方面:

  • 我想将现有的库/包(例如 LAPACK、ARPACK、UMFPACK、PETSc 等)用于线性代数应用程序。我不想再写高斯消元法了。
  • 我不想在 for 循环中对每个矩阵乘法进行编程。
  • 我想将非结构化数据导出为vtk文件格式。我想使用 GNU Octave 中的二维绘图工具。
  • 我想使用 MATLAB 之类的方法,例如sparseor blkdiag
  • 在多个处理器上运行的可能性将受到赞赏,即 openMPI。

我既不是在寻找像Numerical Recipes这样的书,一本关于 PDE 数值的书,也不是一本关于编程的介绍性教科书。我正在寻找一本描述一般方法的书。如何构建程序?如何使我们现有的包?一个例子,例如标准的二维泊松方程会很好。

2个回答

老实说,最好的想法已经说过了。无论如何,我会尝试综合我的想法。

首先,编写程序的最佳方式是在最短的开发时间内为您提供所需的结果。对于某些应用程序,您需要裸机性能,但很多时候您不需要。由于您到目前为止一直在 Octave 中工作,因此您可能不会属于裸机类别,除非您突然大幅增加问题规模。即使你是,C 与 Fortran 速度的争论在这种规模下也大多无关紧要。如果它是 0.1 秒与 1 秒,即使是 10 倍也没有多大关系。

其次,我的经验是,代码的大部分功能最好由高级语言(如 Matlab、Python 等)处理。通常只有一小部分代码真正受益于额外的编程工作优化它们。通常,这些是内循环求解器、复杂的编译函数等。用高级语言编写程序的大部分内容,然后根据需要调用低级库函数以实现真正的性能密集型内容,这是非常有益的。.mex 文件是 Matlab 处理这个的方式(看起来 Octave 也有这个的克隆)。Python 也特别擅长它,例如 f2py、Cython、numba 等。

第三,也是最后一点,到目前为止,最重要的方面是可供您使用的软件生态系统。Matlab 没有被广泛使用,因为它的速度非常快。它被广泛使用,因为它可以绘制数据、执行 LU 分解、数字积分等等,所有这些都使用简单的命令,并且减少几个月(或几年!)的开发时间几乎总是值得性能损失。

总而言之,您需要量化您的需求(您的问题大小,以及解决方案可接受的时间长度),检查您已经拥有的(用于重用和/或移植),并列出您的生态系统要求(vtk、线性代数等)。根据您为此提出的具体答案,有许多可能的“最佳”选项。其中一些可能包括:

  • 保留您的 Octave 代码,但将其重构为使用使用 .mex 文件的外部库,其中性能要求证明了它的合理性。

  • 用 Python 重写您的代码,以访问各种库和出色的混合语言编程工具。这就是我在工作中所做的,相当成功。

  • 使用 PETSc、MPI 等编写一个新的、完全并行化的 HPC 代码。除非问题规模要求您在超级计算机上运行此代码,否则我认为您应该远离这个代码。我的一个朋友曾经将一个串行 CFD 代码迁移到 PETSc,他花了好几年的时间。YMMV

我认为您将不得不选择您的主要标准:性能、模块化或可移植性。

我拿了一个高度优化的 Fortran 90 代码,并尝试将它模块化,使其更加面向对象,而在面向对象的版本中,性能变得差了 3 倍。我发现为了两全其美,我能做的最好的事情就是制作 OO 数据结构,这些结构都是指向原始非 OO 数据结构的指针。Fortran 使用高效的数组步幅,这使得进行线性代数计算非常快。问题是面向对象 (OO) 方法破坏了您从非 OO 方法中的循环中获得的最佳缓存一致性。这里有一个很好的讨论

如果您主要关心性能,我会使用 Python / Fortran 90 组合方法并通过 f2py 模块连接它们。Fortran 90 通常比 C 或 C++ 更快,尤其是对于线性代数(尽管取决于平台),并且对 OpenMPI、Lapack 等许多数值库有很好的支持。我会做所有的计算密集型(例如线性代数)在 Fortran 90 中的东西,并在 Python 中完成所有编码密集的东西(例如 vtk)。这里有一个通过 f2py 使用 Fortran 90 / Python 组合方法求解拉普拉斯方程2u=0. Python 拥有最大的现代高级语言科学计算社区之一,并且对许多模块有很好的支持,尤其是 numpy、scipy 和 vtk 模块。这里有一个通过 Python 的 vtk 模块读取非结构化网格的示例

另一方面,如果您想要更加模块化和/或可移植,您可能想要考虑使用 Java,但您将不得不牺牲性能。基于 Java 的模拟并没有给我留下太深刻的印象,尤其是在性能方面。

关于参考资料,我认为没有任何书籍涵盖此类问题的软件架构。但是,您可能想查看这篇题为“在面向对象的有限元编程中使用设计模式”的论文。

我对此没有任何经验,但人们对在 Julia 中编写这类问题的兴趣正在迅速增长。所以,你也可以看看这个: http: //www.codeproject.com/Articles/579983/Finite-Element-programming-in-Julia