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

相关文档

编译过程

  1. 克隆仓库到本地: git clone https://github.com/scivision/mumps.git

  2. 使用 oneApi 命令行环境以获取对应环境变量、可通过以下两种方式:
    a. 开始菜单找到 Intel oneAPI command prompt for Intel 64 for Visual Studio 右键以管理员身份打开
    b. 任意管理员权限cmd 窗口输入 C:\Program Files (x86)\Intel\oneAPI\setvars.bat

  3. 进到源码仓库目录
    cd /d D:\mumps\mumps-5.6.0.0

  4. 执行编译命令
    cmake -G Ninja -B build -DBUILD_SINGLE=yes -DBUILD_DOUBLE=yes -DBUILD_COMPLEX=yes -DBUILD_COMPLEX16=yes
    在输出无任何报错的情况下
    cmake --build build

  5. 运行测试
    ctest --test-dir build

  6. 此时需注意生成的lib文件在build目录下还不能直接用于项目、需要执行安装命令
    cmake –install build 会将对应库文件与头文件安装到路径C:\Program Files (x86)\MUMPS

  7. 新建 example 目录、放入以下文件
    a. d_example.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    /*
    *
    * 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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    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()
  8. oneapi 命令行环境进入到example路径、执行
    cmake -B build -DMUMPS_ROOT="C:\Program Files (x86)\MUMPS"

  9. 生成可执行程序
    a. 执行cmake --build build
    b. 到build目录下用 Visual Studio 打开 sln工程文件执行生成

  10. 执行生成的d_example.exe查看输出是否为
    Solution is : ( 1.00 2.00)

集成 Metis 库

  1. 在编译mumps之前需要编译metis
    cmake -Dprefix=d:\mumps\metis -P scripts\build_metis.cmake
  2. 编译mumps
    cmake -G Ninja -B build -DBUILD_SINGLE=yes -DBUILD_DOUBLE=yes -DBUILD_COMPLEX=yes -DBUILD_COMPLEX16=yes -DCMAKE_PREFIX_PATH=d:\mumps\metis -Dmetis=on