Windows下编译 Mumps Solver
简介
MUMPS Solver 是一种用于求解大规模线性方程组的开源软件,Mumps官网:https://mumps-solver.org,获取 MUMPS Solver 源代码可在https://mumps-solver.org/index.php?page=dwnld 提交信息后获取。
编译前提
- cmake
- ninja 编译器
- OneApi_base_toolkit —提供C、C++编译器与 MKL
- OneApi_hpc_toolkit —提供Fortran编译器与 MPI
相关文档
- Mumps官方用户手册: https://mumps-solver.org/doc/userguide_5.6.0.pdf
- Cmake编译说明文档:https://github.com/scivision/mumps/blob/main/Readme_Windows.md
- 编译成功后项目集成使用文档: https://github.com/scivision/mumps/issues/3
编译过程
-
克隆仓库到本地:
git clone https://github.com/scivision/mumps.git -
使用 oneApi 命令行环境以获取对应环境变量、可通过以下两种方式: a. 开始菜单找到
Intel oneAPI command prompt for Intel 64 for Visual Studio右键以管理员身份打开 b. 任意管理员权限cmd 窗口输入C:\Program Files (x86)\Intel\oneAPI\setvars.bat -
进到源码仓库目录
cd /d D:\mumps\mumps-5.6.0.0 -
执行编译命令
cmake -G Ninja -B build -DBUILD_SINGLE=yes -DBUILD_DOUBLE=yes -DBUILD_COMPLEX=yes -DBUILD_COMPLEX16=yes在输出无任何报错的情况下cmake --build build -
运行测试
ctest --test-dir build -
此时需注意生成的lib文件在build目录下还不能直接用于项目、需要执行安装命令
cmake –install build会将对应库文件与头文件安装到路径C:\Program Files (x86)\MUMPS下 -
新建 example 目录、放入以下文件 a. d_example.c
/* * * This file is part of MUMPS 5.5.1, released * on Tue Jul 12 13:17:24 UTC 2022 * */ /* Example program using the C interface to the * double real arithmetic version of MUMPS, dmumps_c. * We solve the system A x = RHS with * A = diag(1 2) and RHS = [1 4]^T * Solution is [1 2]^T */ #include <stdio.h> #include <string.h> #include "mpi.h" #include "dmumps_c.h" #define JOB_INIT -1 #define JOB_END -2 #define USE_COMM_WORLD -987654 int main(int argc, char ** argv) { DMUMPS_STRUC_C id; MUMPS_INT n = 2; MUMPS_INT8 nnz = 2; MUMPS_INT irn[] = {1,2}; MUMPS_INT jcn[] = {1,2}; double a[2]; double rhs[2]; /* When compiling with -DINTSIZE64, MUMPS_INT is 64-bit but MPI ilp64 versions may still require standard int for C interface. */ /* MUMPS_INT myid, ierr; */ int myid, ierr; int error = 0; ierr = MPI_Init(&argc, &argv); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); /* Define A and rhs */ rhs[0]=1.0;rhs[1]=4.0; a[0]=1.0;a[1]=2.0; /* Initialize a MUMPS instance. Use MPI_COMM_WORLD */ id.comm_fortran=USE_COMM_WORLD; id.par=1; id.sym=0; id.job=JOB_INIT; dmumps_c(&id); /* Define the problem on the host */ if (myid == 0) { id.n = n; id.nnz =nnz; id.irn=irn; id.jcn=jcn; id.a = a; id.rhs = rhs; } #define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */ /* No outputs */ id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0; /* Call the MUMPS package (analyse, factorization and solve). */ id.job=6; dmumps_c(&id); if (id.infog[0]<0) { printf(" (PROC %d) ERROR RETURN: \tINFOG(1)= %d\n\t\t\t\tINFOG(2)= %d\n", myid, id.infog[0], id.infog[1]); error = 1; } /* Terminate instance. */ id.job=JOB_END; dmumps_c(&id); if (myid == 0) { if (!error) { printf("Solution is : (%8.2f %8.2f)\n", rhs[0],rhs[1]); } else { printf("An error has occured, please check error code returned by MUMPS.\n"); } } ierr = MPI_Finalize(); return 0; }b. CMakeLists.txt
cmake_minimum_required(VERSION 3.13...3.25) project(MUMPSExamples LANGUAGES C Fortran ) enable_testing() if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU|Intel") add_compile_options($<$<COMPILE_LANGUAGE:C>:-Werror-implicit-function-declaration>) endif() if(NOT PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) file(GENERATE OUTPUT .gitignore CONTENT "*") endif() find_package(MUMPS CONFIG REQUIRED) message(STATUS "MUMPS_DIR: ${MUMPS_DIR}") function(precision_ex a) add_executable(${a}_example ${a}_example.c) target_link_libraries(${a}_example PRIVATE MUMPS::MUMPS) if(MUMPS_parallel) add_test(NAME ${a}_example_C COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 2 $<TARGET_FILE:${a}_example>) else() add_test(NAME ${a}_example_C COMMAND ${a}_example) endif() endfunction() if(MUMPS_d_FOUND) precision_ex("d") endif() # test properties get_property(test_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TESTS) if(MUMPS_parallel) set_property(TEST ${test_names} PROPERTY RESOURCE_LOCK cpu_mpi) endif() if(WIN32 AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.22) get_property(imp_mumps TARGET MUMPS::COMMON PROPERTY IMPORTED_LOCATION_RELEASE) if(imp_mumps) get_filename_component(imp_mumps_dir ${imp_mumps} DIRECTORY) endif() set_property(TEST ${test_names} PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_append:${imp_mumps_dir};PATH=path_list_append:${CMAKE_PREFIX_PATH}/bin") endif() -
在
oneapi命令行环境进入到example路径、执行cmake -B build -DMUMPS_ROOT="C:\Program Files (x86)\MUMPS" -
生成可执行程序 a. 执行
cmake --build buildb. 到build目录下用 Visual Studio 打开sln工程文件执行生成 -
执行生成的
d_example.exe查看输出是否为Solution is : ( 1.00 2.00)
集成 Metis 库
- 在编译
mumps之前需要编译metiscmake -Dprefix=d:\mumps\metis -P scripts\build_metis.cmake - 编译
mumpscmake -G Ninja -B build -DBUILD_SINGLE=yes -DBUILD_DOUBLE=yes -DBUILD_COMPLEX=yes -DBUILD_COMPLEX16=yes -DCMAKE_PREFIX_PATH=d:\mumps\metis -Dmetis=on
编译 64 位的版本
所有的依赖库均需要 64位的版本,否则会出现运行时错误
- 编辑 CMakeLists.txt 文件,在链接 MPI_C 之前添加如下内容
if(intsize64) set(MPI_ILP64_LIBRARY "${MPI_LIB_DIR}/libmpi_ilp64.lib") # Linux 添加libmpi_ilp64.so message(STATUS "+++++ MPI_ILP64_LIBRARY ${MPI_ILP64_LIBRARY}") list(APPEND NUMERIC_LIBS ${MPI_ILP64_LIBRARY}) endif() - 添加
-Dintsize64=on