Skip to content

Commit 258c798

Browse files
ranochaSKopecz
andauthored
improve performance with sparse matrices (#101)
* implement sparse optimization for out-of-place build_mprk_matrix! * fix broadcasting * format * format * add package versions to tutorial * add warning to docs * fix nonconservative systems * fix comment * mention KLUFactorization * add LinearSolve * skip broken tests * Update docs/src/faq.md Co-authored-by: Stefan Kopecz <[email protected]> --------- Co-authored-by: Stefan Kopecz <[email protected]>
1 parent 5b1c79d commit 258c798

File tree

9 files changed

+468
-59
lines changed

9 files changed

+468
-59
lines changed

docs/Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
[deps]
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
4+
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
5+
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
46
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
7+
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
58
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
69
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
710

811
[compat]
912
BenchmarkTools = "1"
1013
Documenter = "1"
14+
InteractiveUtils = "1"
15+
LinearSolve = "2.21"
1116
OrdinaryDiffEq = "6.59"
17+
Pkg = "1"
1218
Plots = "1"
1319
SparseArrays = "1.7"

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ makedocs(modules = [PositiveIntegrators],
7676
"Tutorials" => [
7777
"Linear Advection" => "linear_advection.md",
7878
],
79+
"Troubleshooting, FAQ" => "faq.md",
7980
"API reference" => "api_reference.md",
8081
"Contributing" => "contributing.md",
8182
"Code of conduct" => "code_of_conduct.md",

docs/src/faq.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Troubleshooting and frequently asked questions
2+
3+
## Sparse matrices
4+
5+
You can use sparse matrices for the linear systems arising in
6+
[PositiveIntegrators.jl](https://github.com/SKopecz/PositiveIntegrators.jl),
7+
as described, e.g., in the [tutorial on linear advection](@ref tutorial-linear-advection).
8+
However, you need to make sure that you do not change the sparsity pattern
9+
of the production term matrix since we assume that the structural nonzeros
10+
are kept fixed. This is a [known issue](https://github.com/JuliaSparse/SparseArrays.jl/issues/190).
11+
For example, you should avoid something like
12+
13+
```@repl
14+
using SparseArrays
15+
p = spdiagm(0 => ones(4), 1 => zeros(3))
16+
p .= 2 * p
17+
```
18+
19+
Instead, you should be able to use a pattern like the following, where the function `nonzeros` is used to modify the values of a sparse matrix.
20+
21+
```@repl
22+
using SparseArrays
23+
p = spdiagm(0 => ones(4), 1 => zeros(3))
24+
for j in axes(p, 2)
25+
for idx in nzrange(p, j)
26+
i = rowvals(p)[idx]
27+
nonzeros(p)[idx] = 10 * i + j # value p[i, j]
28+
end
29+
end; p
30+
```

docs/src/linear_advection.md

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Tutorial: Solution of the linear advection equation
1+
# [Tutorial: Solution of the linear advection equation](@id tutorial-linear-advection)
22

3-
This tutorial is about the efficient solution of production-destruction systems (PDS) with a large number of differential equations.
4-
We will explore several ways to represent such large systems and assess their efficiency.
3+
This tutorial is about the efficient solution of production-destruction systems (PDS) with a large number of differential equations.
4+
We will explore several ways to represent such large systems and assess their efficiency.
55

66
## Definition of the production-destruction system
77

@@ -11,7 +11,7 @@ One example of the occurrence of a PDS with a large number of equations is the s
1111
\partial_t u(t,x)=-a\partial_x u(t,x),\quad u(0,x)=u_0(x)
1212
```
1313

14-
with ``a>0``, ``t≥ 0``, ``x\in[0,1]`` and periodic boundary conditions. To keep things as simple as possible, we
14+
with ``a>0``, ``t≥ 0``, ``x\in[0,1]`` and periodic boundary conditions. To keep things as simple as possible, we
1515
discretize the space domain as ``0=x_0<x_1\dots <x_{N-1}<x_N=1`` with ``x_i = i Δ x`` for ``i=0,\dots,N`` and ``Δx=1/N``. An upwind discretization of the spatial derivative yields the ODE system
1616

1717
```math
@@ -22,13 +22,13 @@ discretize the space domain as ``0=x_0<x_1\dots <x_{N-1}<x_N=1`` with ``x_i = i
2222
```
2323

2424
where ``u_i(t)`` is an approximation of ``u(t,x_i)`` for ``i=1,\dots, N``.
25-
This system can also be written as ``\partial_t \mathbf u(t)=\mathbf A\mathbf u(t)`` with ``\mathbf u(t)=(u_1(t),\dots,u_N(t))`` and
25+
This system can also be written as ``\partial_t \mathbf u(t)=\mathbf A\mathbf u(t)`` with ``\mathbf u(t)=(u_1(t),\dots,u_N(t))`` and
2626

2727
```math
2828
\mathbf A= \frac{a}{Δ x}\begin{bmatrix}-1&0&\dots&0&1\\1&-1&\ddots&&0\\0&\ddots&\ddots&\ddots&\vdots\\ \vdots&\ddots&\ddots&\ddots&0\\0&\dots&0&1&-1\end{bmatrix}.
2929
```
3030

31-
In particular the matrix ``\mathbf A`` shows that there is a single production term and a single destruction term per equation.
31+
In particular the matrix ``\mathbf A`` shows that there is a single production term and a single destruction term per equation.
3232
Furthermore, the system is conservative as ``\mathbf A`` has column sum zero.
3333
To be precise, the production matrix ``\mathbf P = (p_{i,j})`` of this conservative PDS is given by
3434

@@ -67,11 +67,15 @@ As mentioned above, we will try different approaches to solve this PDS and compa
6767

6868
### Standard in-place implementation
6969

70+
By default, we will use dense matrices to store the production terms
71+
and to setup/solve the linear systems arising in MPRK methods. Of course,
72+
this is not efficient for large and sparse systems like in this case.
73+
7074
```@example LinearAdvection
7175
using PositiveIntegrators # load ConservativePDSProblem
7276
7377
function lin_adv_P!(P, u, p, t)
74-
P .= 0.0
78+
fill!(P, 0.0)
7579
N = length(u)
7680
dx = 1 / N
7781
P[1, N] = u[N] / dx
@@ -97,7 +101,9 @@ plot!(x, last(sol.u); label = "u")
97101

98102
### Using sparse matrices
99103

100-
TODO: Some text
104+
To use different matrix types for the production terms and linear systems,
105+
you can use the keyword argument `p_prototype` of
106+
[`ConservativePDSProblem`](@ref) and [`PDSProblem`](@ref).
101107

102108
```@example LinearAdvection
103109
using SparseArrays
@@ -127,4 +133,30 @@ using BenchmarkTools
127133

128134
```@example LinearAdvection
129135
@benchmark solve(prob_sparse, MPRK43I(1.0, 0.5); save_everystep = false)
130-
```
136+
```
137+
138+
By default, we use an LU factorization for the linear systems. At the time of
139+
writing, Julia uses [SparseArrays.jl](https://github.com/JuliaSparse/SparseArrays.jl)
140+
defaulting to UMFPACK from SuiteSparse in this case. However, the linear systems
141+
do not necessarily have the structure for which UMFPACK is optimized for. Thus,
142+
it is often possible to gain performance by switching to KLU instead.
143+
144+
```@example LinearAdvection
145+
using LinearSolve
146+
@benchmark solve(prob_sparse, MPRK43I(1.0, 0.5; linsolve = KLUFactorization()); save_everystep = false)
147+
```
148+
149+
150+
## Package versions
151+
152+
These results were obtained using the following versions.
153+
```@example LinearAdvection
154+
using InteractiveUtils
155+
versioninfo()
156+
println()
157+
158+
using Pkg
159+
Pkg.status(["PositiveIntegrators", "SparseArrays", "KLU", "LinearSolve", "OrdinaryDiffEq"],
160+
mode=PKGMODE_MANIFEST)
161+
nothing # hide
162+
```

src/PositiveIntegrators.jl

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

33
# 1. Load dependencies
44
using LinearAlgebra: LinearAlgebra, Tridiagonal, I, diag, diagind, mul!
5-
using SparseArrays: SparseArrays, AbstractSparseMatrix
5+
using SparseArrays: SparseArrays, AbstractSparseMatrix,
6+
issparse, nonzeros, nzrange, rowvals, spdiagm
67
using StaticArrays: SVector, MVector, SMatrix, StaticArray, @SVector, @SMatrix
78

89
using FastBroadcast: @..

0 commit comments

Comments
 (0)