ActPi向阳技术栈
← 返回文章列表

Windows下编译 Mumps Solver

文章目录
  1. 简介
  2. 编译前提
  3. 相关文档
  4. 编译过程
  5. 集成 Metis 库
  6. 编译 64 位的版本

简介

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

     /*
     *
     *  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()
  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

编译 64 位的版本

所有的依赖库均需要 64位的版本,否则会出现运行时错误

  1. 编辑 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()
  2. 添加 -Dintsize64=on