Saturday, December 27, 2025

编译开源电磁仿真求解器Palace

Palace 是AWS Labs推出的一款用于全波 3D 电磁仿真的并行有限元求解器,开源许可证为Apache 2.0,求解器支持频域/时域全波、特征模、静电/静磁集总参数提取,适配笔记本到超算的多平台与 GPU 加速,可以用于量子计算硬件、射频 / 微波器件、天线等建模。 Image 笔者曾经简要介绍了如何在Windows下编译Palace的文章,参见《Windows环境下编译电磁仿真求解器Palace》一文。本文是在前文的基础上,更为详细的介绍编译过程,尤其着重介绍依赖库的编译。本文讨论的依赖库有: Hypre:大型线性代数矩阵计算包。本例使用2.33.0版本。 MUMPS:来自法国的求解大规模稀疏线性方程组的开源软件库。本例使用5.8.1版本。 ARPACK-NG:支持复数线性矩阵计算,用于特征值计算。以Fortran程序为主,无需依赖PETSc,可以独立编译。需要通过Palace提供的diff文件手动修改部分源代码。 GSLIB:用于高阶谱单元的插值计算。 libCEED:是一款线性代数计算管理终端,支持对各种CPU,GPU和集群的并行计算。本例使用0.12版本。需要手动修改源代码以通过Windows Visual Studio的编译。 MFEM:提供灵活、高效、可扩展的有限元离散化框架。本例使用4.8.1版本。是Palace的核心求解依赖库。需要通过Palace提供的diff文件手动修改部分源代码。 系统环境与依赖库 操作系统:Windows 11, 64-bit 编译器:Visual Studio 2022 Community, C++17。Inter Fortran Compiler 2022,Intel MKL 2024。 Palace版本:0.15 编译Hypre Hypre是劳伦斯利弗莫尔国家实验室 LLNL 开发的开源高性能并行线性求解器库,专为大规模科学计算和工程模拟设计。核心目标是高效求解大规模稀疏线性方程组(形如 Ax=b),尤其擅长处理超大规模、分布式内存并行环境下的问题。hypre 原生支持 MPI并行,能充分利用超级计算机、集群等分布式内存架构的算力,轻松处理数百万甚至数十亿自由度的线性系统,这是它区别于小型求解器(如 Eigen)的核心优势。 Image Windows下编译hypre并不复杂,可以直接使用自带的CMakeFile文件,生成Visual Studio的项目文件,生成静态库文件。在配置CMake时,参数如下设置: HYPRE_WITH_MPI = ON HYPRE_USING_OPENMP = ON HYPRE_WITH_CUDA = OFF HYPRE_ENABLE_SYCL = OFF HYPRE_INSTALL_PREFIX=D:/WelSimLLC/CodeDV/3rdParty/hypre/myInstall CMAKE_INSTALL_PREFIX=D:/WelSimLLC/CodeDV/3rdParty/hypre/myInstall 如果编译顺利,会生成hyper.lib静态库文件。 编译 MUMPS Palace求解器需要SuperLU, StrumPack,或者MUMPS三个直接线代求解器中的一个,才能求解Wave Port问题。由于笔者比较熟悉MUMPS,因此就选择的MUMPS求解器作为依赖库。 MUMPS是由法国 INRIA、CNRS 等机构联合开发的开源并行稀疏直接求解器库。它的核心目标是用 “直接法” 求解大规模稀疏线性方程组(Ax=b),区别于 hypre 以 “迭代法” 为主,MUMPS 用直接法通过矩阵分解(LU/Cholesky)计算出解,无需迭代,精度更高、鲁棒性更强,尤其适合求解非对称、对称正定 / 不定的稀疏矩阵问题。 MUMPS 依赖 BLAS/LAPACK(基础线性代数库)、SCALAPACK(并行线性代数库)。这里我们使用Intel的MKL库作为依赖库。 原始版本的MUMPS不提供Windows的编译方式,可以选择GitHub上的scivision/mumps版本,提供了基于CMake的编译方式,可以轻易实现编译。本例下载的是最新的5.8.1版本。 确保环境变量中含有MKLTOOL= C:\Program Files (x86)\Intel\oneAPI\mkl\latest 在CMake编译下,设置 MUMPS_openmp = ON MUMP_parallel = OFF 生成Visual Studio的项目文件后,直接编译即可生成MUMPS的所有静态库。生成的静态库如下图所示。 Image 编译ARPACK Palace在计算特征值相关的功能时,如计算Eigenmode,需要有SLEPc或者ARPACK复数求解器。由于SLEPc依赖PETSc,而PETSc在Windows下的编译较为复杂,因此就不选用SLEPc,这里选择ARPACK作为Palace的复数求解器。 ARPACK是由莱斯大学、桑迪亚国家实验室等机构,联合开发的开源大规模特征值/特征向量求解库。它的核心目标是高效计算大型稀疏矩阵的少数特征值与对应特征向量,和 hypre、MUMPS 这类求解线性方程组(Ax=b)的库不同,ARPACK 专注于处理特征值问题(Ax=λx 或 Ax=λBx)。 Image 从GitHub上下载ARPACK-ng,使用自带的CMake编译方式。确保环境变量中含有MKLTOOL= C:\Program Files (x86)\Intel\oneAPI\mkl\latest,这样CMake会自动找到MKL里的BLAS和Lapack。在CMake中设置如下 ICE = ON Eigen = ON Build_SHARED_LIBS = OFF 同时,确保环境变量中含有MKLTOOL= C:\Program Files (x86)\Intel\oneAPI\mkl\latest,这样CMake会自动找到MKL里的BLAS和Lapack。 同时,需要根据palace目录中extern/patch/arpack-ng文件夹下的diff文件,对源文件做相应修改。生成Visual Studio项目文件后,既可以直接编译得到Arpack的静态库。 编译GSLib GSLIB是一个开源的并行稀疏通信库,它专为有限元、谱元、有限差分等并行数值模拟场景,提供高效的稀疏数据聚合 – 分发(Gather/Scatter)通信与算子支持。大幅简化并行稀疏通信开发,降低分布式内存编程门槛;自适应算法保证大规模并行下的通信效率,适配超大规模仿真需求。 Image 由于GSLib并没有CMake文件,无法在Windows下自动生成Visual Studio的项目文件,需要用户自己建立Visual Studio的项目文件。新建一个静态库项目,取名为gslib-palace,并将所有的源文件和头文件添加到此项目中。 在Visual Studio的项目预处理定义中,添加GSLIB_USE_CBLAS, GSLIB_USE_MKL。 编译时,当遇到以下错误提示时: unary minus operator applied to unsigned type, result still unsigned 需要修改代码,如将 p[map->n].el = -(uint)1; 改为 p[map->n].el = 0-(uint)1; 以通过编译。 当遇到以下错误提示时: potentially uninitialized local pointer variable 'h' used 需要修改代码,给指针添加NULL初始值。 如果提示fgs_free函数已经有重复的定义。将fgs_setup, fgs_free与fgs_unique函数注释掉即可。 编译libCEEM libCEED 是一个高效可扩展的离散化库,专注于基于有限元和谱元方法的高效计算离散化。它提供轻量级代数接口,用于线性和非线性算子及预条件子,支持基于 CPU、GPU 等多种计算设备的运行时选择优化实现。 Image 编译libCEEM是整个工作的难点,由于libCEED不提供CMakeFile文件,同时含有较多的选项,同时Visual Studio不支持C99的语法,需要大量手动修改源文件,尤其是对于动态数组的修改。如将以下动态数组 CeedInt num_points[num_elem]; 修改成为 CeedInt *num_points = (CeedInt *)malloc(num_elem * sizeof(CeedInt)); 使用完成后,还需在结尾处,使用free函数,从内存中删除此数组,free(num_points)。 一些含有路径的字符串,也需要做修改。如 *(relative_file_path) = strstr(absolute_file_path, "ceed/jit-source"); 改为 #ifdef _WIN32 *(relative_file_path) = strstr(absolute_file_path, "ceed\\jit-source"); #else *(relative_file_path) = strstr(absolute_file_path, "ceed/jit-source"); #endif 由于Visual Studio对weak的函数支持方式与Linux不一样,需要对源码中的weak函数做如下修改: #define CEED_BACKEND(name, num_prefixes, ...) \ CEED_INTERN int name(void) __attribute__((weak)); \ int name(void) { return CeedRegister_Weak(__func__, num_prefixes, __VA_ARGS__); } #include "ceed-backend-list.h" 改为 #ifdef _WIN32 #define CEED_BACKEND(name, num_prefixes, ...) \ CEED_INTERN int name(void) __declspec(selectany); \ int name(void) { return CeedRegister_Weak(__func__, num_prefixes, __VA_ARGS__); } #else #define CEED_BACKEND(name, num_prefixes, ...) \ CEED_INTERN int name(void) __attribute__((weak)); \ int name(void) { return CeedRegister_Weak(__func__, num_prefixes, __VA_ARGS__); } #include "ceed-backend-list.h" #endif Visual Studio不支持__restrict__关键字,需要改成__restrict。 还有一些小范围的修改,如将popen改成_popen,将pclose改成 _pclose。有一处环境变量设定setenv("RUST_TOOLCHAIN", "nightly", 0),需要做如下修改: char env_str[1024]; snprintf(env_str, sizeof(env_str), "%s=%s", "nightly", 0); _putenv(env_str); 为了减少不必要的复杂度,本次编译只支持CPU并行计算的内容,GPU并行无需支持,因此在ceed-backend-list.h文件中,只需要支持以下功能: CEED_BACKEND(CeedRegister_Opt_Blocked, 1, "/cpu/self/opt/blocked") CEED_BACKEND(CeedRegister_Opt_Serial, 1, "/cpu/self/opt/serial") CEED_BACKEND(CeedRegister_Ref, 1, "/cpu/self/ref/serial") CEED_BACKEND(CeedRegister_Ref_Blocked, 1, "/cpu/self/ref/blocked") CEED_BACKEND(CeedRegister_Xsmm_Blocked, 1, "/cpu/self/xsmm/blocked") CEED_BACKEND(CeedRegister_Xsmm_Serial, 1, "/cpu/self/xsmm/serial") 其余的计算功能可以注释掉。编译成功后会生成libCEEM的静态库。 编译MFEM MFEM是Palace的核心求解器,由劳伦斯利弗莫尔国家实验室(LLNL)主导开发的开源高阶有限元库,专为大规模科学计算和工程仿真设计,核心目标是提供灵活、高效、可扩展的有限元离散化框架。MFEM 也是计算流体力学、电磁仿真、结构力学、核物理模拟等领域的主流开源有限元工具。 Image 编译MFEM相对简单,可以通过CMake的方式生成Visual Studio项目文件来编译。在CMake的选项中,选择激活的选项如下: MFEM_USE_MPI = ON MFEM_USE_ZLIB = ON MFEM_USE_METIS = ON MFEM_USE_LAPACK = ON MFEM_USE_LEGACY_OPENMP = ON MFEM_THREAD_SAFE = ON MFEM_USE_MUMPS = ON 同时,需要根据palace目录中extern/patch/mfem文件夹下的diff文件,对源文件做相应修改。由于需要修改的源文件较多,需要耐心仔细,或者在Linux下先编译一遍,将自动修改好的mfem拷贝覆盖至Windows下需要编译的mfem文件夹。整个生成Visual Studio的项目文件后,直接编译,即可得到mfem的静态库。 编译Palace 至此,复杂的依赖库都已经编译完成。开始整个项目的最后一步,使用自带的CMakeFile文件,生成Visual Studio的项目文件,编译Palace。这里要注意的是,应该选择在palace子目录中的CMakeFile.txt文件,而不是根目录下的CMakeFile.txt,因为后者是用于生成Superbuild的。 CMake下设置: PALACE_WITH_ARPACK = ON PALACE_WITH_OPENMP = ON PALACE_WITH_SLEPC = OFF MPI_Fortran_WORKS = C:/Program Files (x86)/Microsoft SDKs/MPI/Include/x64 设置路径 nlohmann_json_DIR = D:/WelSimLLC/CodeDV/3rdParty/nlohmann_json/json-3.12.0/myInstall/share/cmake/nlohmann_json fmt_DIR = D:\WelSimLLC\CodeDV\3rdParty\fmt\fmt-11.0.2\myInstall\lib\cmake\fmt scn_DIR = D:\WelSimLLC\CodeDV\libPack\lib\scn\cmake\scn MFEM_DIR = D:/WelSimLLC/CodeDV/libPack/lib/palace/mfem-cmake arpackng_DIR = D:\WelSimLLC\CodeDV\libPack\lib\palace\arpack-cmake\arpackng 打开生成的Visual Studio项目,可以看到名为libpalace的静态库项目,和名为palace的可执行文件项目。如果在编译时提示找不到头文件,或者连接时缺少相关函数,可以直接在项目中添加相关路径和静态库。 Image 完成编译后,可以试运行一下palace.exe。注意使用时,需要将动态依赖库放置与palace.exe同一个文件夹下,如MKL系列的相关动态库文件。 计算一个简单算例,得到如下显示。表明编译基本成功。 Image 总结 目前可用的开源电磁场仿真求解器不多,Palace是目前功能最多的开源电磁求解器。Palace的依赖库较多,版本还在不断更新迭代,一些依赖库只支持Linux版本,增加了Windows下编译的难度。本文记录编译整个Palace的过程,同时给开源社区提供一些Windows下编译Palace的参考。 还有一些其他依赖库编译相对容易,如Eigen, fmt, Metis,nlhmann/json等。有经验的开发者可以自行在Windows下成功编译,就不在本文中赘述了。 笔者已将编译好的palace.exe可执行文件收录在WELSIM安装包中,用户也可以直接从WELSIM安装包中获得Windows版本的palace.exe,无需自己编译。 本文介绍的是CPU多核并行计算下的Palace,GPU版本的编译方法,如CUDA, HIP,或SYCL版本,会在以后的文章中讨论。 WelSim与作者不隶属于Palace, Hypre, MUMPS, Arpack, GSLib, libCEEM, 和MFEM。和Palace, Hypre, MUMPS, Arpack, GSLib, libCEEM, 和MFEM开发团队与机构没有直接关系。这里引用这些开源软件的名称和图片仅用作技术博客文章与软件使用的参考。

No comments:

Post a Comment