OpenFOAM是一个开放源代码的计算流体力学CFD软件,很强大。为了使用它,我在openSUSE上面编译了OpenFOAM

OpenFOAM有2个分支。早年仅有社区版

openfoam.org

后来被ESI公司收购后,社区产生了分裂,随后ESI官方提供了一个版本

openfoam.com

而社区的org继续发展。两者非常像,功能基本一致。不过就编译来讲,ESI官方版的比较容易一些。

准备依赖包

我使用的发行版是OpenSuse 15.4

首先是编译器基本包

zypper install patterns-devel-C-C++-devel_C_C++

zypper会把大量的C++开发工具安装到系统中。如果是Debian,还需要安装flex软件包,编译过程中会需要。

然后还有很多其他的依赖包,比如

fftw3-devel

因为python3-mpi4py依赖的是openmpi2,而这个包是python2-vtk所依赖的,所以所有其他依赖mpi的软件我统统选择了openmpi2版本,这也是为了避免在将来运行时出各种莫名其妙的兼容性问题。

要注意,fftw3-mpi-devel依赖openmpi4,但是这个包不是必需的,所以最后我选择不安装这个包

然后还有

cmake

cgal-devel

ptscotch-openmpi2-devel

scotch-devel

metis-devel

paraview-devel

python3-paraview,Tumbleweed版中是python310-paraview

openSUSE的zypper会自动解决依赖关系,把boost相关的包一并安装好

这里面会涉及到一个python3-mpi4py的软件包,在OpenSuse15.3中,它依赖于openmpi2。openmpi这个软件包有1、2、3、4共4个版本共存,很多依赖它的其他软件包也都有对应的版本。因为2版本受到依赖,所以这里就选择openmpi2

在yast当中可以轻易的列出软件包,然后勾选openmpi2版本。

如果是Tumbleweed,则可以选openmpi4,另外python3-paraview也被替换为python38-paraview

如果是Debian 11,还需要增加一个

libpdal-dev

如果是Debian 12, 不需要

公司版编译

下载源代码

首先到官方网站openfoam.com下载最新的源码包,目前最新的是2212版,也就是2022年12月版。其实源码包存放在sourceforge服务器上,所以中国下载比较慢,记得挂上代理。

然后在个人目录下创建一个opt目录,然后把源代码解压缩到这个目录待用。

另外有一个ThirdParty包,是考虑到这个软件需要安装到很多服务器(尤其是超算)上,而服务器的操作系统自带的软件包可能不足以满足OpenFOAM的依赖,所以官方还贴心的准备了一个第三方包.

如果使用OpenFOAM提供的ThirdParty包,那么可以把这个包解压缩到刚才的opt目录,和OpenFOAM的源码目录放在一起,OpenFOAM编译时会自动查找。以我的经验,系统自带的包兼容性、稳定性比额外的包要好,如果系统自带了,尽可能不要用额外的编译包。

如果使用的是openSUSE的最新版,不论是Leap 15.4还是Tumbleweed,这些第三方依赖包在系统内都自带了,通过系统zypper安装即可。

修改编译选项

OpenFOAM的代码编写是遵循C++11标准的,gcc版本只要高于4.8.5就可以,如果系统内有更高版本的编译器,想使用更高版本的C++标准也是可以的,由于源代码没有修改,仅仅修改c++标准版本是不会对最终生成的可执行程序有任何影响的。

不过,OpenFOAM可能会依赖到的其他包,这些包在编写时可能会采用更新的标准,特别是cgal,在5.0以后更新到了c++14,如果采用c++11标准,编译到网格生成的部分,因为依赖cgal,就会出错。

如果是官方版v2212,解压缩之后,编辑wmake/rules/General/Gcc/c++文件,把里面的std=c++11编辑为std=c++14即可,如果是要改成c++17也没什么不行。

配置和编译

然后开启一个terminal不要关闭,接下来所有操作都要在这个terminal中进行,因为这里面涉及到环境变量的设置,如果中途关闭这个terminal,那么环境变量就变了,就会出错。

其中source命令bash自带的,用于导入环境变量配置。但是要注意bash并不是标准的sh,起码source命令肯定是bash比标准sh多的。如果使用的是标准sh(比如FreeBSD),那么就要使用“.”来替代source命令。

# 引入openmpi环境变量
source /usr/lib64/mpi/gcc/openmpi2/bin/mpivars.sh
# 设置OpenFOAM编译时链接系统自带的软件库
cd ~/opt/OpenFOAM-v2112

# 如果系统内安装的某些依赖库有多个版本的话,还需要指定版本,否则会自动识别
# -int32是LABLE选项,一般用32位
# -dp是求解器选项,双精度比较好
./bin/tools/foamConfigurePaths -sys-openmpi -dp -int32 \
    -adios adios-none \ # 目前Opensuse Tumbleweed也仅有adios1,可是OpenFOAM需要adios2,所以先暂时关闭这个功能
    -boost boost-system \
    -cgal  cgal-system \
    -fftw  fftw-system \
    -kahip kahip-none \ # 这个参数很重要,否则后面并行计算可能会缺乏kahip库不能运行,kahip库目前还没有进入各大Linux发行版
    -metis metis-system \
    -scotch scotch-system \
    -paraview system

# 设置OpenFOAM环境变量
source ./etc/bashrc

# 编译
./Allmake

配置选项中的adios、kahip缺失了,这是因为OpenSuse自带的adios仅为1.x,而OpenFOAM需要2.x,而kahip则完全没有进入发行版。

如果追求完美,有2个办法。一个是重新编译OpenSuse发行版自带的包,adios、kahip,替换掉自带的包。这个涉及到rpm打包,这里就不讲了。这两个附加组件提供了对特定数据格式的支持,其实有没有都可以。

另外一个则是使用OpenFOAM提供的Thirdparty包。

首先把OpenFOAM的源代码和Thirdparty的源代码解压缩到同一个目录,我比较喜欢~/opt

修补源码

如果是2112版,里面关于adios2的配置有错误,需要修正。找到OpenFOAM-v2112/config.sh/adios2,把里面的adios2_version设置为Thirdparty-v2112/sources/adios目录下的对应版本,否则会找不到。类似的把OpenFOAM-v2112/config.csh/adios2里的变量也一并改过来

如果CGAL版本高于5.5,也要修正一下,因为早期版本里面有一个Robust_circumcenter_filtered_traits_3.h文件,在新版本里被改为了Robust_weighted_circumcenter_filtered_traits_3.h

而OpenFOAM还在使用旧的Robust_circumcenter_filtered_traits_3.h文件,所以要修改一下。找到

OpenFOAM-v2212/applications/utilities/mesh/generation/foamyMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3DKernel.H

#include "CGAL/Robust_circumcenter_filtered_traits_3.h"
typedef CGAL::Robust_circumcenter_filtered_traits_3<baseK>  K;

修改为

#include "CGAL/Robust_weighted_circumcenter_filtered_traits_3.h"
    typedef CGAL::Robust_weighted_circumcenter_filtered_traits_3<baseK> K;

这样在编译到这个网格划分工具时就不会出错了。虽然笔者自己从来都是用第三方网格划分工具的,不过发现了bug就修正总归是好的。

在2312版本,这个地方已经升级,不需要再修补了。

进行编译

# 引入openmpi环境变量
source /usr/lib64/mpi/gcc/openmpi2/bin/mpivars.sh
# 设置OpenFOAM编译时链接系统自带的软件库
cd ~/opt/OpenFOAM-v2112

# 如果系统内安装的某些依赖库有多个版本的话,还需要指定版本,否则会自动识别
# -int32是LABLE选项,一般用32位
# -dp是求解器选项,双精度比较好
./bin/tools/foamConfigurePaths -sys-openmpi -dp -int32 \
    # -adios adios-none \ # 这个选项不做额外设置,编译脚本会自动寻找Thirdparty目录下的对应组件
    -boost boost-system \
    -cgal  cgal-system \
    -fftw  fftw-system \
    # -kahip kahip-none \ # 这个选项不做额外设置,编译脚本会自动寻找Thirdparty目录下的对应组件
    -metis metis-system \
    -scotch scotch-system \
    # -paraview system # OpenSuse自带的Paraview没有VTK MPI支持,后面编译会出错,不过求解器仍然可用,如果追求完美就要重新编译Paraview。或者在这里不做设置,编译脚本会自动寻找Thirdparty目录下的对应组件,并按照OpenFOAM需要的参数编译paraview组件

# 设置OpenFOAM环境变量
source ./etc/bashrc

另外paraview-5.10的插件规范和过去的版本不同,在编译OpenFOAM自带的paraview插件时找不到VTK MPI模块的,所以后面编译到这里的时候也还会出错。OpenFOAM自带的paraview插件是针对paraview-5.7开发的,编译的兼容性一直延续到5.9,但是最新的5.10就不能保证编译兼容了。不过不必担心,其实praview从5.8开始就自带了OpenFOAM插件,所以OpenFOAM自己提供的这个插件不编译安装也没关系。如果是OpenFOAM自带的preview插件,那么启动时在OpenFOAM的题目目录运行

paraFoam

即可。如果是使用系统自带的paraview,那么需要在OpenFOAM的题目目录下创建一个空的以foam为扩展名的文件——如name.foam——然后用paraview打开这个文件即可。

这样可以仅使用Thirdparty中的adios、kahip这么几个包,其他的可以继续用系统自带的,这样兼容性更好。

耐心等待,几个小时后就编译出来了。遇到paraview插件错误时,编译脚本会自动跳过,然后编译后面的内容。如果不想看到屏幕上的出错信息,可以把modules/visualization目录删掉。

笔者亲自尝试在Debian 11和OpenSUSE 15.4里,这个paraview插件编译要出错的。但是在Debian 12里,如果用户安装paraview,系统包管理器会自动删除libvtk-dev,到这里编译不会出错。

如果是红帽系的,mpi的rpm安装有所不同,所以可以调整一下

# 引入openmpi环境变量
# fedora只会安装一个版本的openmpi
export PATH=$PATH:/usr/lib64/openmpi/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib
# 设置OpenFOAM编译时链接系统自带的软件库
cd ~/opt/OpenFOAM-v2112

# 如果系统内安装的某些依赖库有多个版本的话,还需要指定版本,否则会自动识别
./bin/tools/foamConfigurePaths -sys-openmpi -dp -int32 \
    -adios adios-none \ # 目前Opensuse Tumbleweed也仅有adios1,fedora没有,可是OpenFOAM需要adios2,所以先暂时关闭这个功能
    -boost boost-system \
    -cgal  cgal-system \
    -fftw  fftw-system \
    -kahip kahip-none \ # 这个参数很重要,否则后面并行计算可能会缺乏kahip库不能运行,kahip库目前还没有进入各大Linux发行版
    -metis metis-system \
    -scotch scotch-system \
    -paraview system

# 设置OpenFOAM环境变量
source ./etc/bashrc

配置完成后,进入编译环节,还在这个terminal中

# 编译
./Allmake

如果想要加快编译速度,可以在后面加-j6参数,这个数字代表着编译时并行的进程数,不要超过用户自己的cpu核心数就好。

编译完成后,就可以在这个termina中继续使用OpenFOAM了。如果将来需要新开窗口,则需要

# OpenSuse这样设置openmpi
source /usr/lib64/mpi/gcc/openmpi3/bin/mpivars.sh
# fedora的话,这样设置openmpi
export PATH=$PATH:/usr/lib64/openmpi/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib
# 设置OpenFOAM自己的变量
source ~/opt/OpenFOAM-v2112/etc/bashrc

设定环境变量后即可使用。

公司版在编译到最后,编译后处理组件,供paraview使用的部分的时候,如果配置出错,会自动退出,并提示OpenFOAM自己的组件完成了,其实这个时候如果不需要做后处理,仅仅需要求解器部分的话,已经成功了。如果需要后处理paraview的部分,就需要安装

libxi-devel

vtk-devel

eigen3-devel

python38-devel

libxml2-devel

glew-devel

cgns-devel

jsoncpp-devel

hdf5-devel

libqt5-qtx11extras-devel

libqt5-qtsvg-devel

libqt5-qttools-devel

libqt5-qtdeclarative-devel

libQt5Network-devel

protobuf-devel

libogg-devel

libtheora-devel

libpng16-devel

netcdf-devel

utfcpp-devel

liblz4-devel

double-conversion-devel

pugixml-devel

cli11-devel

这个清单是基于openSUSE,如果是其他发行版,比如红帽系或者debian系,包的名字可能会有所不同。

如果是Debian 11或者12,还需要增加一个

qtxmlpatterns5-dev-tools

社区版编译

下载源代码

社区版目前最新的是10,源码包存放在github上,所以也要挂上代理。

然后在个人目录下创建一个opt目录,然后把源代码解压缩到这个目录待用。

ThridParty包和公司版一样,这里不推荐使用。

修改编译选项

解压缩之后,首先编辑目录名,把OpenFOAM-9-version-10改为OpenFOAM-10,后面的-version-10是github加上去的,要删掉,要不然后面会出错。

然后编辑wmake/rules/linux64Gcc/c++,把里面的std=c++14编辑为std=c++17即可。如果使用的是其他编译器,就要修改对应的文件。因为后面编译paraview依赖文件的时候,CGAL会使用更高版本的语法,所以这里动一下。

打开src/parallel/decompose/ptscotchDecomp/Make/options文件,把

-L$(SCOTCH_ARCH_PATH)/lib

修改为

-L$(SCOTCH_ARCH_PATH)/lib64

否则,在编译到这里时会提示找不到链接库。这处修改是OpenSUSE专属的,因为OpenSUSE特意把64位的库单独列一个目录,如果是其他发行版如Debian,则不需要做这处修改。

类似的,把src/parallel/decompose/metisDecomp/Make/options和src/parallel/decompose/scotchDecomp/Make/options的类似位置都改过来

配置和编译

和公司版一样开启一个terminal不要关闭,设置环境变量后完成操作

# 引入openmpi环境变量
source /usr/lib64/mpi/gcc/openmpi3/bin/mpivars.sh
# 设置OpenFOAM编译时链接系统自带的软件库
cd ~/opt/OpenFOAM-9

# 然后对编译选项进行配置,如果不配置,编译时就会到../ThirdParty目录去找,但我这里希望使用系统自带的
./bin/tools/foamConfigurePaths \
--scotchArchPath /usr/lib64/mpi/gcc/openmpi2 \
--scotchVersion 6.1.0 \
--paraviewInstall /usr \
--paraviewVersion 5.9.0 \
--archOption 64


# 设置OpenFOAM环境变量
source ./etc/bashrc

# 编译
./Allmake

和公司版不同,社区版的选项没有那么多

如果是红帽系的,那么就只有openmpi的设置有所不同,其他的都一样

另外,涉及到后处理的部分,社区版的如果编译paraview插件时失败了,会直接退出,并提示编译失败,这一点和公司版不同。而编译脚本在paraview插件之后还有其他插件没有编译,这样就会出错。为了尽可能完整编译,可以删掉applications/utilities/postProcessing/graphics/PVReaders这个目录,这样编译脚本在到这里的时候就会跳过paraview插件的编译,然后后面的就能顺利编译了。没有这个OpenFOAM自带的插件也没关系,反正使用系统的paraview一样可以打开OpenFOAM的文件,因为它从5.8就自带了OpenFOAM插件。

如果一定要一起编译的话,还需要安装

ffmpeg

libavcode-dev

libavformat-dev

libavutil-dev

libswscale-dev

libgl2ps-dev

再编译就没问题了

使用mpich替代openmpi

我还要用到另一个重要的软件包dealii,而这个软件的mpi仅支持mpich,不支持openmpi,所以我还要探索一下使用mpich替换openmpi来支持OpenFOAM的方法。

方法也很简单

首先要切换系统的mpi。因为openmpi和mpich在系统内是互相冲突的,在redhat和debian系统里提供了mpi-selector的程序可以切换启用一个屏蔽另一个。第一步就是先切换到mpich

公司版openfoam.com

如果是redhat或者debian编译时一样使用mpivars导入mpi环境变量,如果是gentoo完全不需要这步。

在foamConfigurepath的时候,把-sys-openmpi换成-mpi=MPICH

剩下的步骤一样,包括source ./etc/bashrc和./Allmake

社区版openfoam.org

导入mpi环境变量的操作不变

在foamConfigurepath的时候,没有设定mpi的参数。

在foamConfigurepath之后,进入OpenFOAM-11/etc目录,打开bashrc,把

export WM_MPLIB=SYSTEMMPI

修改为

export WM_MPLIB=MPICH

 剩下的步骤一样,包括source ./etc/bashrc和./Allmake