我已经开始使用 python 作为编程语言来完成我在 CFD 中的所有作业。我在编程方面的经验很少。我来自机械工程背景,正在攻读航空航天工程的高等教育。
有时,CFD 的计算方面变得比操作方程或做数学更乏味。
使我们的程序运行得更快的一般准则是什么?并行做事的技巧是什么?如何编写运行速度更快的代码?
我在哪里可以获得回答上述问题的资源(对于像我这样的外行来说很容易理解)?
我已经开始使用 python 作为编程语言来完成我在 CFD 中的所有作业。我在编程方面的经验很少。我来自机械工程背景,正在攻读航空航天工程的高等教育。
有时,CFD 的计算方面变得比操作方程或做数学更乏味。
使我们的程序运行得更快的一般准则是什么?并行做事的技巧是什么?如何编写运行速度更快的代码?
我在哪里可以获得回答上述问题的资源(对于像我这样的外行来说很容易理解)?
考虑到您专门要求 Python,我将尝试回答您的问题。我将描述我自己解决模拟问题的方法。本描述中给出了更快模拟的策略。
首先,我用 Python 制作新模拟的原型。当然,我尽量使用NumPy和SciPy。NumPy 为数值模拟提供了合适的数组数据类型,而 SciPy 提供了广泛的使用 NumPy 数组的数值例程。
一旦原型或多或少地工作,我会尝试了解程序或脚本的哪些部分是瓶颈。有典型的候选人:
我使用一个简单的分析策略来了解所有运行时间都花在了哪里。使用IPython shell(我推荐的不够多),我运行我的脚本
%timeit script.py
这个“魔术命令”将为您进行分析(使用timeit),并在您的脚本终止后向您显示一个包含时间的列表。使用此列表找出您的代码太慢的地方。
一旦确定了需要加速的部分,就可以考虑使用编译语言。我将指出两个解决方案。
首先是Cython语言。Cython 是一种与 Python 非常相似的编程语言(事实上,Python 代码通常也是有效的 Python 代码);但是,Cython 编译器将 Cython 文件转换为 C 代码,然后可以将其编译为可从 Python 使用的模块。Cython 理解 NumPy 数组。使用 Cython 可以通过两种方式帮助您:首先,您可以引入数据类型。这将加快函数调用。此外,如果您遍历数组,您的循环将运行得更快(事实上,如果您同时键入虚拟变量和数组,您将得到一个普通的 C 循环!)。其次,在我的实验中,即使是无类型的脚本也运行得更快一些,因为它们是编译的而不是解释的。
对您有用的另一种编译语言是 Fortran。将 Fortran 与 Python 结合使用有多种方法(f2py、fortwrap、Cython)。就我个人而言,f2py 似乎是最简单的方法,我将快速描述它的作用。f2py 可以将 Fortran 代码编译为 Python 模块。它将允许您使用 NumPy 数组作为 Python 空间的输入和输出变量。在 Fortran 空间中,这些将是普通的 Fortran 数组。您可以以全 Fortran 速度对它们进行操作。
就个人而言,我倾向于使用 Cython,其中函数调用的数量是瓶颈。对于循环繁重的东西,我更喜欢 f2py(可能是因为我有很强的 Fortran 背景)。
关于 Fortran 的附加说明:现代 Fortran 的读写与 NumPy 非常相似——语法非常接近。这使得将 NumPy 代码转换为 Fortran 代码变得容易。
请注意,Cython 和 f2py 都以某种方式支持并行性。对于 Cython,您可以在此处找到帮助,而对于 Fortran,有标准技术,例如OpenMP或 MPI。此外,还有MPI 的 Python 包装器。就个人而言,我在 Python 级别使用 mpi4py 以及在 Fortran 中使用 OpenMP。
让我推荐一些文献:H.-P 的Python Scripting For Computational Science一书。Langtangen 是一个很好的 Python 资源,以及让 Python 更快一点的策略。不幸的是,AFAIR,它没有提到 Cython 上的任何内容。作为我的第二个资源,您可以查看这些幻灯片。这些为我在这篇文章中提到的所有内容提供了示例(另请参见此处的代码和源代码)。互联网上还有许多其他不错的幻灯片。
如果您有更具体的问题,我们很乐意为您提供帮助!
对于 CFD+Python,有一个解决方案:http: //pythonflu.wikidot.com/这些是基于 OpenFOAM 的 Python 绑定(在问题的评论中已经提到)。这些绑定允许在“求解器级别”上进行编程(有些示例在 Python 中复制了原始 OpenFOAM 求解器,并且它们并不比原件慢 - 另一个答案中提到的慢循环在这里不是问题,因为“内部循环”会发生在 OpenFOAM 的 C++ 代码中)。
这些绑定的优点还在于 OpenFOAM 中的所有并行化都发生在求解器级别之下,因此您不必费心处理它(以及 OpenFOAM 核心处理的其他内容:输入/输出,线性求解器,算子离散化)
因此,如果您只想编写一个新的求解器而不向 OF 核心添加新功能(边界条件、线性求解器等),那么 PythonFlu 可能对您来说就足够了,您可以避免使用 C++(它比 C++ 具有更高的学习治愈率) Python)
PS:本来想将此作为评论添加到原始问题的讨论中,但我的声誉不允许我这样做