Skip to content

Commit 740cf9f

Browse files
authored
Use local dynamic libraries rather than jll binaries (#235)
* update initialisation to allow specfying a lobrary on HPC systems: We now have 2 options: # Option 1: point directly to your library (sets libs AND skips JLL) export JULIA_PETSC_LIBRARY=/path/to/libpetsc.so # Option 2: skip JLL, then use set_petsclib() in your script export JULIA_PETSC_SKIP_JLL=1 With option 2, getlib() won't work (no libs registered), but set_petsclib("/path/to/libpetsc.so") gives you full control over scalar/int types. * configure type of library through ENV variables: export JULIA_PETSC_LIBRARY=/path/to/libpetsc.so export JULIA_PETSC_SCALAR=Float64 # Float32 | ComplexFloat64 | ComplexFloat32 export JULIA_PETSC_INT=Int64 # Int32 * update docs * update getting started page * replace environmental variables by preferences * oops * load preferences
1 parent 153f223 commit 740cf9f

8 files changed

Lines changed: 189 additions & 54 deletions

File tree

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
99
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
1111
MPIPreferences = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267"
12+
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
1213
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
1314
PETSc_jll = "8fa3689e-f0b9-5420-9873-adf6ccf46f2d"
1415
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
@@ -22,6 +23,7 @@ Libdl = "^1.10"
2223
LinearAlgebra = "^1.10"
2324
MPI = "0.20"
2425
MPIPreferences = "0.1"
26+
Preferences = "1"
2527
OffsetArrays = "1.0"
2628
PETSc_jll = "3.22"
2729
Pkg = "^1.10"

README.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,16 @@ julia>]test PETSc
2929

3030
By default, the package uses a pre-built binary of PETSc (see [PETSc_jll](https://github.com/JuliaBinaryWrappers/PETSc_jll.jl)) along with a default installation of `MPI.jl`, so you don't have to install it on your machine.
3131

32-
If you want to use the package with custom builds of the PETSc library, this can be done by using the function `set_petsclib` which requires you to point to the correct dynamic library (which should be compatible with the MPI version used by `MPI.jl`)
32+
If you want to use the package with a custom PETSc build, use `set_library!` to configure it once — the path is stored persistently in `LocalPreferences.toml` and no environment variables are needed:
3333

3434
```julia
3535
using PETSc
36-
37-
# Create custom library instance
38-
petsclib = set_petsclib("/path/to/custom/libpetsc.so";
39-
PetscScalar=Float64, PetscInt=Int64)
40-
# Use it like any precompiled library
41-
PETSc.initialize(petsclib, log_view=true)
42-
# ... your code ...
43-
PETSc.finalize(petsclib)
36+
PETSc.set_library!("/path/to/custom/libpetsc.so"; PetscScalar=Float64, PetscInt=Int64)
37+
# Restart Julia — PETSc_jll is not loaded and your library is used automatically.
4438
```
39+
40+
To revert to the bundled binaries: `PETSc.unset_library!()`. To check the current configuration: `PETSc.library_info()`.
41+
4542
To get an overview of available precompiled libraries:
4643
```julia
4744
julia>using PETSc

docs/src/man/FAQ.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,27 @@
22

33

44
## 1. Can I use my own PETSc library?
5-
Yes, see the function `set_petsclib`. You do need to compile this library as a dynamic library, and `MPI.jl` must be configured to be compatible with the MPI library used to compile PETSc. If you run this on a HPC system, and you don't know exactly which options were used, you can compile one of the PETSc examples and run it with the `-log_view` command line option. At the end of the simulation, it will give you the configuration options used on that machine.
5+
Yes. You do need to compile PETSc as a dynamic (shared) library, and `MPI.jl` must be configured to be compatible with the MPI used to compile PETSc. If you run this on an HPC system and don't know the configuration options, compile one of the PETSc examples and run it with `-log_view`; the output lists all configuration options used on that machine.
66

7-
Please note that the version of PETSc should be compatible with the version used for the wrapper.
7+
Please note that the version of PETSc should be compatible with the version used for the wrappers.
8+
9+
The recommended approach is `set_library!`, which stores the path persistently in `LocalPreferences.toml` — no environment variables needed:
10+
11+
```julia
12+
using PETSc
13+
PETSc.set_library!("/path/to/libpetsc.so"; PetscScalar=Float64, PetscInt=Int64)
14+
# Restart Julia — the custom library is used automatically from here on.
15+
```
16+
17+
To revert to the bundled `PETSc_jll` binaries:
18+
```julia
19+
PETSc.unset_library!()
20+
```
21+
22+
For a one-off session without changing the persistent preference, use `set_petsclib` directly:
23+
```julia
24+
petsclib = PETSc.set_petsclib("/path/to/libpetsc.so"; PetscScalar=Float64, PetscInt=Int64)
25+
```
826

927
## 2. Help, my code crashes?
1028
That is very possible. If you provide a *short* minimum working example (MWE), feel free to open an issue on the github repo, so we can check it out.

docs/src/man/getting_started.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
- [Getting started](#getting-started)
55
- [1a. Installation using pre-built libraries](#1a-installation-using-pre-built-libraries)
6-
- [1b. Installation using pre-built libraries](#1b-installation-using-pre-built-libraries)
6+
- [1b. Installation using a custom PETSc build](#1b-installation-using-a-custom-petsc-build)
77
- [2. Solving a linear system of equations](#2-solving-a-linear-system-of-equations)
88
- [3. Nonlinear example](#3-nonlinear-example)
99
- [4. Next steps](#4-next-steps)
@@ -21,14 +21,28 @@ which will install a pre-built PETSc library (`PETSc_jll`) as well as `MPI.jl` o
2121

2222
**Windows users are therefore advised to install the [Windows Subsystem for Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux) (WSL) and run PETSc.jl from within WSL.** This will provide full functionality with both serial and parallel (MPI) support.
2323

24-
### 1b. Installation using pre-built libraries
25-
On many high-performance clusters, you will have to use the provided `MPI` installation for that cluster and the default download above will not be sufficient. Alternatively, you may be interested in a PETSc installation that comes with additional external packages. Ensure that this PETSc installation is compiled as a dynamic (and not a static) library, after which you need to specify the correct library with:
24+
### 1b. Installation using a custom PETSc build
25+
Sometimes, you may be interested in a PETSc installation that comes with additional external packages, or that you compiled yourself. Ensure the library is compiled as a **dynamic** (not static) library.
26+
27+
Use `set_library!` to configure the path once — it is stored in `LocalPreferences.toml` and no environment variables are needed afterwards:
28+
29+
```julia
30+
using PETSc
31+
PETSc.set_library!(
32+
"/path/to/custom/libpetsc.so";
33+
PetscScalar = Float64,
34+
PetscInt = Int64,
35+
)
36+
# Restart Julia — PETSc_jll is not loaded and your library is used automatically.
37+
```
38+
39+
To revert to the bundled binaries: `PETSc.unset_library!()`.
40+
41+
For a one-off session without changing persistent settings, use `set_petsclib` directly:
2642

2743
```julia
28-
# Create custom library instance
29-
petsclib = set_petsclib("/path/to/custom/libpetsc.so";
30-
PetscScalar=Float64, PetscInt=Int64)
31-
# Use it like any precompiled library
44+
petsclib = PETSc.set_petsclib("/path/to/custom/libpetsc.so";
45+
PetscScalar=Float64, PetscInt=Int64)
3246
PETSc.initialize(petsclib, log_view=true)
3347
# ... your code ...
3448
PETSc.finalize(petsclib)

docs/src/man/lowlevel_intro.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,28 +71,30 @@ You can link to your own custom build of PETSc instead of using the prebuilt bin
7171
- Debug builds for troubleshooting
7272
- Integration with specific external packages
7373

74-
To use a custom PETSc installation:
74+
To persistently configure a custom PETSc installation (recommended):
7575

7676
```julia
7777
using PETSc
78+
PETSc.set_library!("/path/to/your/libpetsc.so"; PetscScalar=Float64, PetscInt=Int64)
79+
# Restart Julia — PETSc_jll is not loaded and your library is used automatically.
80+
```
7881

79-
# Create a custom library instance pointing to your PETSc installation
80-
petsclib = PETSc.set_petsclib("/path/to/your/libpetsc.so";
81-
PetscScalar=Float64,
82-
PetscInt=Int64)
82+
To revert: `PETSc.unset_library!()`. To inspect the current config: `PETSc.library_info()`.
8383

84-
# Initialize and use as normal
85-
PETSc.initialize(petsclib)
84+
For a one-off session without changing persistent settings:
8685

86+
```julia
87+
petsclib = PETSc.set_petsclib("/path/to/your/libpetsc.so";
88+
PetscScalar=Float64, PetscInt=Int64)
89+
PETSc.initialize(petsclib)
8790
# ... your code using petsclib ...
88-
8991
PETSc.finalize(petsclib)
9092
```
9193

9294
**Important notes for custom builds:**
93-
- The dynamic library path should point to `libpetsc.so` (Linux), `libpetsc.dylib` (macOS), or `libpetsc.dll` (Windows)
94-
- The `PetscScalar` and `PetscInt` types must match how your PETSc was configured
95-
- Your custom PETSc must be compatible with the MPI version used by `MPI.jl`
95+
- The library must be compiled as a dynamic/shared library (`libpetsc.so` / `.dylib`)
96+
- `PetscScalar` and `PetscInt` must match how your PETSc was configured
97+
- Your PETSc must be linked against the same MPI that `MPI.jl` uses
9698
- You can check available precompiled libraries with `[PETSc.petsclibs...]`
9799

98100
### 2. Zero-Based Indexing

src/LibPETSc_startup.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ function getlibs()
1212
return libs
1313
end
1414
=#
15-
const libs = @static if !haskey(ENV, "JULIA_PETSC_LIBRARY")
15+
using Preferences
16+
17+
# @load_preference is evaluated at compile time; changing a preference via
18+
# set_library!() triggers automatic recompilation (standard Preferences.jl behaviour).
19+
const libs = @static if @load_preference("library_path", nothing) === nothing
1620
using PETSc_jll
1721
(
1822
((PETSc_jll.libpetsc_Float64_Real_Int64,), Float64, Int64),
@@ -25,7 +29,15 @@ const libs = @static if !haskey(ENV, "JULIA_PETSC_LIBRARY")
2529
((PETSc_jll.libpetsc_Float32_Complex_Int32,), Complex{Float32}, Int32),
2630
)
2731
else
28-
error("JULIA_PETSC_LIBRARY not currently working")
32+
let _path = @load_preference("library_path"),
33+
_scalar = @load_preference("PetscScalar", "Float64"),
34+
_int = @load_preference("PetscInt", "Int64")
35+
_st = _scalar == "Float32" ? Float32 :
36+
_scalar == "ComplexFloat64" ? Complex{Float64} :
37+
_scalar == "ComplexFloat32" ? Complex{Float32} : Float64
38+
_it = _int == "Int32" ? Int32 : Int64
39+
(((_path,), _st, _it),)
40+
end
2941
end
3042

3143
const petsc_library_file =

src/PETSc.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module PETSc
44

5-
using MPI, LinearAlgebra, SparseArrays, OffsetArrays
5+
using MPI, LinearAlgebra, SparseArrays, OffsetArrays, Preferences
66

77
MPI.Initialized() || MPI.Init()
88

@@ -23,6 +23,7 @@ using .LibPETSc
2323
export LibPETSc
2424
export audit_petsc_file
2525
export set_petsclib
26+
export set_library!, unset_library!, library_info
2627

2728
using Libdl
2829

src/init.jl

Lines changed: 111 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -199,39 +199,47 @@ inttype(
199199
200200
Create a custom PETSc library instance from a user-specified shared library path.
201201
202-
This function allows you to use a custom-compiled PETSc library instead of the
203-
pre-built libraries provided by PETSc_jll. The custom library must be:
204-
- Compiled as a shared/dynamic library (not static)
205-
- Built with the correct scalar type (real vs complex) and integer size
206-
- Compatible with the same MPI installation that MPI.jl is using
202+
This function allows you to use a custom-compiled PETSc library instead of the
203+
pre-built libraries provided by `PETSc_jll`. The custom library must be compiled as a
204+
shared/dynamic library (not static), built with the matching scalar type and integer
205+
size, and linked against the same MPI installation that `MPI.jl` uses.
206+
207+
On HPC systems, set `JULIA_PETSC_SKIP_JLL=1` before starting Julia to prevent
208+
`PETSc_jll` from being precompiled (its MPI stack is typically incompatible with
209+
cluster MPI). Then call this function in your script to load the cluster library.
207210
208211
# Arguments
209-
- `library_path::String`: Path to the custom PETSc shared library (e.g., "/path/to/libpetsc.so")
210-
- `PetscScalar::Type`: Scalar type used by the library. Options: `Float64`, `Float32`,
211-
`Complex{Float64}`, or `Complex{Float32}`. Default: `Float64`
212-
- `PetscInt::Type`: Integer type used by the library. Options: `Int32` or `Int64`.
212+
- `library_path::String`: Path to the PETSc shared library (e.g. `"/path/to/libpetsc.so"`)
213+
- `PetscScalar::Type`: Scalar type the library was built with. One of `Float64`,
214+
`Float32`, `Complex{Float64}`, `Complex{Float32}`. Default: `Float64`
215+
- `PetscInt::Type`: Integer type the library was built with. `Int32` or `Int64`.
213216
Default: `Int64`
214217
215218
# Returns
216-
- A `PetscLibType` instance that can be used with `initialize()`, `finalize()`, and
217-
all other PETSc.jl functions
219+
A `PetscLibType` instance for use with `initialize`, `finalize`, and all PETSc.jl functions.
220+
221+
# Environment-variable alternative
222+
Instead of calling `set_petsclib`, you can configure everything before Julia starts:
223+
```
224+
JULIA_PETSC_LIBRARY=/path/to/libpetsc.so # also suppresses PETSc_jll
225+
JULIA_PETSC_SCALAR=Float64 # Float32 | ComplexFloat64 | ComplexFloat32
226+
JULIA_PETSC_INT=Int64 # Int32
227+
```
228+
With these set, `PETSc.getlib(; PetscScalar=Float64, PetscInt=Int64)` returns the
229+
custom library directly.
218230
219231
# Examples
220232
```julia
221-
using PETSc
222-
223-
# For a custom double-precision real PETSc library with 64-bit indices
224-
petsclib = PETSc.set_petsclib("/path/to/custom/libpetsc.so";
225-
PetscScalar=Float64, PetscInt=Int64)
226-
227-
# For a single-precision complex library with 32-bit indices
228-
petsclib = PETSc.set_petsclib("/opt/petsc/lib/libpetsc.so";
229-
PetscScalar=Complex{Float32}, PetscInt=Int32)
230-
231-
# Initialize and use the custom library
233+
# Double-precision real, 64-bit indices (typical HPC build)
234+
petsclib = PETSc.set_petsclib("/path/to/libpetsc.so";
235+
PetscScalar=Float64, PetscInt=Int64)
232236
PETSc.initialize(petsclib)
233237
# ... your code ...
234238
PETSc.finalize(petsclib)
239+
240+
# Single-precision complex, 32-bit indices
241+
petsclib = PETSc.set_petsclib("/opt/petsc/lib/libpetsc.so";
242+
PetscScalar=Complex{Float32}, PetscInt=Int32)
235243
```
236244
237245
# See Also
@@ -248,6 +256,87 @@ function set_petsclib(library_path::String; PetscScalar::Type=Float64, PetscInt:
248256
return petsclib
249257
end
250258

259+
"""
260+
library_info()
261+
262+
Print the current PETSc library configuration: which library is in use, how it
263+
was configured (preference or default JLL), and the scalar/integer types.
264+
"""
265+
function library_info()
266+
pref_path = @load_preference("library_path", nothing)
267+
pref_scalar = @load_preference("PetscScalar", nothing)
268+
pref_int = @load_preference("PetscInt", nothing)
269+
270+
if pref_path !== nothing
271+
println("Source : LocalPreferences.toml")
272+
println("Path : ", pref_path)
273+
println("Scalar : ", something(pref_scalar, "Float64"))
274+
println("Int : ", something(pref_int, "Int64"))
275+
else
276+
println("Source : PETSc_jll (default precompiled binaries)")
277+
end
278+
279+
println("\nLoaded libraries (this session):")
280+
for lib in petsclibs
281+
path = lib.petsc_library isa AbstractString ? lib.petsc_library :
282+
try Libdl.dlpath(Libdl.dlopen(lib.petsc_library)) catch; string(lib.petsc_library) end
283+
println(" [$(lib.PetscScalar), $(lib.PetscInt)]: ", path)
284+
end
285+
end
286+
287+
"""
288+
set_library!(path; PetscScalar=Float64, PetscInt=Int64)
289+
290+
Persistently configure PETSc.jl to use a custom PETSc shared library.
291+
292+
The path and type configuration are stored in `LocalPreferences.toml` (per-project,
293+
git-ignorable) and take effect on the next Julia session. Recompilation is triggered
294+
automatically — no environment variables are needed.
295+
296+
To revert to the default `PETSc_jll` libraries, call [`unset_library!`](@ref).
297+
298+
# Arguments
299+
- `path`: path to the PETSc shared library (e.g. `"/path/to/libpetsc.so"`)
300+
- `PetscScalar`: scalar type the library was built with (`Float64`, `Float32`,
301+
`Complex{Float64}`, `Complex{Float32}`). Default: `Float64`
302+
- `PetscInt`: integer type the library was built with (`Int64` or `Int32`).
303+
Default: `Int64`
304+
305+
# Examples
306+
```julia
307+
PETSc.set_library!(
308+
"/project/petsc/lib/libpetsc.so";
309+
PetscScalar = Float64,
310+
PetscInt = Int64,
311+
)
312+
# Restart Julia — the new library is used automatically from here on.
313+
```
314+
315+
# See Also
316+
- [`unset_library!`](@ref): remove the preference and revert to `PETSc_jll`
317+
- [`set_petsclib`](@ref): load a custom library for the current session only
318+
"""
319+
function set_library!(path; PetscScalar::Type=Float64, PetscInt::Type=Int64)
320+
ispath(path) || error("PETSc library not found: $path")
321+
@set_preferences!(
322+
"library_path" => realpath(path),
323+
"PetscScalar" => string(PetscScalar),
324+
"PetscInt" => string(PetscInt),
325+
)
326+
@info "PETSc library configured — restart Julia to use the new library." path PetscScalar PetscInt
327+
end
328+
329+
"""
330+
unset_library!()
331+
332+
Remove the persistent custom-library preference set by [`set_library!`](@ref),
333+
reverting to the default `PETSc_jll` binaries on the next Julia session.
334+
"""
335+
function unset_library!()
336+
@delete_preferences!("library_path", "PetscScalar", "PetscInt")
337+
@info "PETSc library preference removed — restart Julia to revert to PETSc_jll."
338+
end
339+
251340

252341
"""
253342
check_petsc_wrappers_version(petsclib=nothing)

0 commit comments

Comments
 (0)