diff --git a/README.md b/README.md index c2ee384..3b0a27d 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,13 @@ [![CI Testing](https://github.com/JuliaSparse/Pardiso.jl/workflows/CI/badge.svg)](https://github.com/JuliaSparse/Pardiso.jl/actions?query=workflow%3ACI+branch%3Amaster) -The Pardiso.jl package provides an interface for using [PARDISO -6.0](http://www.pardiso-project.org/) and [Intel MKL -PARDISO](https://software.intel.com/en-us/node/470282) from the [Julia -language](http://julialang.org). You cannot use `Pardiso.jl` without either -having a valid license for PARDISO or having the MKL library installed. This +The Pardiso.jl package provides an interface for using [Panua Pardiso](https://panua.ch/pardiso), it's predecessors from +[pardiso-project.org](http://www.pardiso-project.org/), and [Intel MKL +PARDISO](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-0/onemkl-pardiso-parallel-direct-sparse-solver-iface.html) from the [Julia +language](http://julialang.org). + +You cannot use `Pardiso.jl` without either having a valid license for Panua Pardiso or +having the MKL library installed. This package is available free of charge and in no way replaces or alters any functionality of the linked libraries. @@ -18,7 +20,7 @@ library. ### MKL PARDISO -By default Julia, will automatically install a suitable MKL for your platform by loading `MKL_jll.jl`. +By default, when adding "Pardiso.jl" to the active environmnent, Julia will automatically install a suitable MKL for your platform by loading `MKL_jll.jl`. Note that if you use a mac you will need to pin `MKL_jll` to version 2023. If you instead use a self installed MKL, follow these instructions: @@ -29,25 +31,21 @@ If you instead use a self installed MKL, follow these instructions: executing something like `source /opt/intel/oneapi/setvars.sh intel64` or running `"C:\Program Files (x86)\IntelSWTools\compilers_and_libraries\windows\mkl\bin\mklvars.bat" intel64` * Run `Pkg.build("Pardiso", verbose=true)` -* Run `Pardiso.show_build_log()` to see the build log for additional - information. -* Note that the `MKLROOT` environment variable must be set, and `LD_LIBRARY_PATH` must contain `$MKLROOT/lib` - whenever using the library. - -### PARDISO 6.0 - -* Put the PARDISO library `libpardiso600-WIN-X86-64.dll`, `libpardiso600-GNUXXX-X86-64.so` or - `libpardiso600-MACOS-X86-64.dylib` in a folder somewhere and set the environment variable `JULIA_PARDISO` to that folder. - For example, create an entry `ENV["JULIA_PARDISO"] = "/Users/Someone/Pardiso"` in the - `.julia/config/startup.jl` file and download the Pardiso library to that folder. -* Perform the platform specific steps below -* Run `Pkg.build("Pardiso")` -* Run `Pardiso.show_build_log()` to see the build log for additional information. - -Note: Weird errors and problems with MKL Pardiso has been observed when Pardiso 6.0 is enabled -(likely because some library that is needed by Pardiso 6.0 is problematic with MKL). -If you want to use MKL Pardiso it is better ot just disable Paridso 6.0 by not setting -the environment variable `JULIA_PARDISO` (and rerunning `build Pardiso`). +* Eventually, run `Pardiso.show_build_log()` to see the build log for additional information. +* Note that the `MKLROOT` environment variable must be set, and `LD_LIBRARY_PATH` must contain `$MKLROOT/lib` whenever using the library this way. + +### PARDISO from [panua.ch](https://panua.ch) ("PanuaPardiso", formerly "ProjectPardiso") + +* Unzip the download file `panua-pardiso-yyyymmdd-os.zip` to some folder and set the environment variable `JULIA_PARDISO` to the `lib` subdirectory of this folder. For example, create an entry `ENV["JULIA_PARDISO"] = "/Users/Someone/panua-pardiso-yyyymmdd-os/lib"` in `.julia/config/startup.jl`. If you have a valid license for the predecessor from pardiso-project.org, put the PARDISO library to a subdirectory denoted by `ENV["JULIA_PARDISO"]` and + evenutally rename it to `libpardiso.so`. +* Perform the platform specific steps described below +* Run `Pkg.build("Pardiso", verbose=true)` +* Eventually, run `Pardiso.show_build_log()` to see the build log for additional information. + +Note: In the past, weird errors and problems with MKL Pardiso had been observed when PanuaPardiso is enabled +(likely because some library that is needed by PanauaPardiso was problematic with MKL). +In that case, if you want to use MKL Pardiso it is better to just disable PanuaPardiso by not setting +the environment variable `JULIA_PARDISO` (and rerunning `Pkg.build("Pardiso")`). ##### Linux / macOS specific @@ -55,13 +53,24 @@ the environment variable `JULIA_PARDISO` (and rerunning `build Pardiso`). * Make sure OpenMP is installed. * Install a (fast) installation of a BLAS and LAPACK (this should preferably be single threaded since PARDISO handles threading itself), using for example [OpenBLAS](https://github.com/xianyi/OpenBLAS/wiki/Precompiled-installation-packages) +`gfortran` and OpenMP usually come with recent version of gcc/gfortran. On Linux, Panua Pardiso +looks for libraries `libgfortran.so` and `libgomp.so` . They may be named differently on your system. +In this situation you may try to create links to them with names known to +`Pardiso.jl` (bash; pathnames serve as examples here): +```` +$ mkdir $HOME/extralibs +$ ln -s /usr/lib64/libgomp.so.1 $HOME/extralibs/libgomp.so +$ ln -s /usr/lib64/libgfortran.so.5 $HOME/extralibs/libgfortran.so +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/extralibs/ +```` + ## Basic Usage This section will explain how to solve equations using `Pardiso.jl` with the default settings of the library. For more advanced users there is a section further down. ## Creating the PardisoSolver -A `PardisoSolver` is created with `PardisoSolver()` for solving with PARDISO 6.0 or `MKLPardisoSolver()` for solving with MKL PARDISO. This object will hold the settings of the solver and will be passed into the solve functions. In the following sections an instance of a `PardisoSolver` or an `MKLPardisoSolver()` will be referred to as `ps`. +A `PardisoSolver` is created with `PardisoSolver()` for solving with PanuaPardiso or `MKLPardisoSolver()` for solving with MKL PARDISO. This object will hold the settings of the solver and will be passed into the solve functions. In the following sections an instance of a `PardisoSolver` or an `MKLPardisoSolver()` will be referred to as `ps`. ### Solving @@ -100,7 +109,7 @@ julia> X -1.17295 8.47922 ``` -### Schur Complement (6.0 only) +### Schur Complement (PanuaPardiso only) Given a partitioned matrix `M = [A B; C D]`, the Schur complement of `A` in `M` is `S = D-CA⁻¹B`. This can be found with the function `schur_complement` with the following signatures: @@ -147,7 +156,7 @@ At present there seems to be an instability in the Schur complement computation ### Setting the number of threads -The number of threads to use is set in different ways for MKL PARDISO and PARDISO 6.0. +The number of threads to use is set in different ways for MKL PARDISO and PanuaPardiso. #### MKL PARDISO @@ -156,7 +165,7 @@ set_nprocs!(ps, i) # Sets the number of threads to use get_nprocs(ps) # Gets the number of threads being used ``` -#### PARDISO 6.0 +#### PanuaPardiso The number of threads are set at the creation of the `PardisoSolver` by looking for the environment variable `OMP_NUM_THREADS`. This can be done in Julia with for example `ENV["OMP_NUM_THREADS"] = 2`. **Note:** `OMP_NUM_THREADS` must be set *before* `Pardiso` is loaded and can not be changed during runtime. @@ -166,7 +175,7 @@ The number of threads used by a `PardisoSolver` can be retrieved with `get_nproc This section discusses some more advanced usage of `Pardiso.jl`. -For terminology in this section please refer to the [PARDISO 6.0 manual](http://www.pardiso-project.org/manual/manual.pdf) and the [MKL PARDISO section](https://software.intel.com/en-us/node/470282). +For terminology in this section please refer to the [PanuaPardiso manual](http://panua.ch/manual/manual.pdf) and the [oneMKL PARDISO manual](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-0/onemkl-pardiso-parallel-direct-sparse-solver-iface.html). After using functionality in this section, calls should no longer be made to the `solve` functions but instead directly to the function @@ -198,8 +207,8 @@ The matrix type can be explicitly set with `set_matrixtype!(ps, key)` where the The matrix type for a solver can be retrieved with `get_matrixtype(ps)`. -### Setting the solver (6.0 only) -PARDISO 6.0 supports direct and iterative solvers. The solver is set with `set_solver!(ps, key)` where the key has the following meaning: +### Setting the solver (PanuaPardiso only) +PanuatPardiso supports direct and iterative solvers. The solver is set with `set_solver!(ps, key)` where the key has the following meaning: | enum | integer | Solver | |--------------------|---------|----------------------------------| @@ -227,7 +236,7 @@ Depending on the phase calls to `solve` (and `pardiso` which is mentioned later) | RELEASE_ALL | -1 | Release all internal memory for all matrices | ### Setting `IPARM` and `DPARM` explicitly -Advanced users likely want to explicitly set and retrieve the `IPARM` and `DPARM` (6.0 only) parameters. +Advanced users likely want to explicitly set and retrieve the `IPARM` and `DPARM` (PanuaPardiso only) parameters. This can be done with the getters and setters: ```jl @@ -235,7 +244,7 @@ get_iparm(ps, i) # Gets IPARM[i] get_iparms(ps) # Gets IPARM set_iparm!(ps, i, v) # Sets IPARM[i] = v -# 6.0 only +# PanuaPardiso only get_dparm(ps, i) # Gets DPARM[i] get_dparms(ps) # Gets DPARM set_dparm!(ps, i, v) # Sets DPARM[i] = v @@ -254,7 +263,7 @@ It is possible for Pardiso to print out timings and statistics when solving. Thi ### Matrix and vector checkers -PARDISO 6.0 comes with a few matrix and vector checkers to check the consistency and integrity of the input data. These can be called with the functions: +PanuaPardiso comes with a few matrix and vector checkers to check the consistency and integrity of the input data. These can be called with the functions: ```jl printstats(ps, A, B) @@ -279,7 +288,7 @@ get_perm(ps) set_perm!(ps, perm) # Perm is a Vector{Int} ``` -### Schur Complement (6.0 only) +### Schur Complement (PanuaPardiso only) The `pardiso(ps,...)` syntax can be used to compute the Schur compelement (as described below). The answer can be retrieved with `pardisogetschur(ps)`. diff --git a/deps/build.jl b/deps/build.jl index 0be64a0..019715f 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -10,16 +10,18 @@ println("===============") const LIBPARDISONAMES = if Sys.iswindows() [ + "libpardiso.dll", "libpardiso600-WIN-X86-64.dll", ] elseif Sys.isapple() [ + "libpardiso.dylib", "libpardiso600-MACOS-X86-64.dylib", ] elseif Sys.islinux() [ + "libpardiso.so", "libpardiso600-GNU800-X86-64.so", - "libpardiso600-GNU720-X86-64.so", ] else error("unhandled OS") diff --git a/src/Pardiso.jl b/src/Pardiso.jl index d784d45..e1e5987 100644 --- a/src/Pardiso.jl +++ b/src/Pardiso.jl @@ -51,6 +51,7 @@ export solve, solve! export get_matrix export schur_complement, pardisogetschur export fix_iparm! +export mkl_is_available, panua_is_available struct PardisoException <: Exception info::String @@ -112,6 +113,8 @@ const pardiso_chkvec_z = Ref{Ptr}() const pardiso_get_schur_f = Ref{Ptr}() const PARDISO_LOADED = Ref(false) +panua_is_available() = PARDISO_LOADED[] + function __init__() global MKL_LOAD_FAILED if LOCAL_MKL_FOUND diff --git a/src/project_pardiso.jl b/src/project_pardiso.jl index ca57110..215e036 100644 --- a/src/project_pardiso.jl +++ b/src/project_pardiso.jl @@ -12,8 +12,8 @@ mutable struct PardisoSolver <: AbstractPardisoSolver end function PardisoSolver() - if !PARDISO_LOADED[] - error("pardiso library was not loaded") + if !panua_is_available() + error("Panua pardiso library was not loaded") end pt = zeros(Int, 64)