How to use ezARPACK in your project

Depending on what build system your C++ project is based on, there are two ways to use ezARPACK. Either way, you would need

Warning

The Parallel ARPACK eigensolvers for general complex matrices are known to be unstable and can yield wrong results in ARPACK-NG versions prior to 3.8.0. Be sure to link your code to ARPACK-NG 3.8.0 or newer if you use the complex variant of ezarpack::mpi::arpack_solver.

Makefiles/no build system

Assume that <EZARPACK_ROOT> is either a directory with unpacked ezARPACK sources or its installation directory. A compiler command line for your program can be as simple as

g++ -O3 -o myprog myprog.cpp \
    -I<EZARPACK_ROOT>/include -L<ARPACK_NG_ROOT>/lib -larpack

# For executables using the Parallel ARPACK (MPI) solvers
mpic++ -O3 -o myprog_mpi myprog_mpi.cpp -I<EZARPACK_ROOT>/include \
       -L<ARPACK_NG_ROOT>/lib -larpack -lparpack

(similar for clang++ and other compilers). More -I flags may be needed if the linear algebra framework you choose is not visible to the compiler by default. Similarly, adding -I<MPI_ROOT>/include -L<MPI_ROOT>/lib may be necessary if you are using an MPI implementation installed in a non-system location.

Note

When linking to the static version of ARPACK-NG library (libarpack.a), you might also need to explicitly link your executable to a BLAS/LAPACK implementation. A common symptom of this problem is undefined references to dgemv_ and other LAPACK subroutines.

CMake

Here is a minimal example of a root CMakeLists.txt script for your project.

cmake_minimum_required(VERSION 3.13.0 FATAL_ERROR)

project(myproject LANGUAGES CXX)

# ezARPACK_ROOT is the installation prefix of ezARPACK.
set(ezARPACK_DIR ${ezARPACK_ROOT}/lib/cmake)

# Import ezARPACK target.
find_package(ezARPACK 1.0 CONFIG REQUIRED)

# Import Eigen (Blaze, Armadillo, etc) targets.
find_package(Eigen3 CONFIG REQUIRED)

# Build an executable called `myprog`.
add_executable(myprog myprog.cpp)
target_link_libraries(myprog ezarpack Eigen3::Eigen)

# Find a usable version of ARPACK-NG.
find_arpackng(3.6.0 REQUIRED)

# Link the executable to the ARPACK library.
target_link_libraries(myprog ${ARPACK_LIBRARIES})

Linking your targets to ARPACK-NG libraries can be a bit of a hassle, as CMake interface of ARPACK-NG changed a few times since version 3.6.0. In particular, CMake scripts of the versions prior to 3.8.0 do not export any targets. Instead, they expose library information via a variable arpack_ng_LIBRARIES. In order to make linking more user-friendly, ezARPACK exports a macro called find_arpackng(). It finds an ARPACK-NG installation while taking care of said CMake interface differences. Upon successful detection of ARPACK-NG, find_arpackng() sets two variables that can be later passed to target_link_libraries(),

  • ARPACK_LIBRARIES - list of ARPACK libraries and linker flags

  • PARPACK_LIBRARIES - list of Parallel ARPACK libraries and linker flags

Setting CMake variable ARPACK_NG_ROOT will instruct find_arpackng() to look for ARPACK-NG at a specific installation prefix before proceeding to system locations.

Making the Parallel ARPACK solvers work requires additional linking to MPI and PARPACK.

# Parallel ARPACK (MPI)

# Build another executable `myprog_mpi`.
add_executable(myprog_mpi myprog_mpi.cpp)
target_link_libraries(myprog_mpi ezarpack Eigen3::Eigen)

# Detect an MPI-3.0 implementation.
find_package(MPI 3.0 REQUIRED)

# Link the executable to the Parallel ARPACK library and to the MPI.
target_include_directories(myprog_mpi PRIVATE ${MPI_CXX_INCLUDE_PATH})
target_link_libraries(myprog_mpi ${PARPACK_LIBRARIES} ${MPI_CXX_LIBRARIES})