Skip to content

Commit 6823231

Browse files
Remove allocations in the spline_interpolation function (#60)
* make the 1d spline_inteprolation functions allocation free * reduce allocations for the 2D spline_interpolation routines * small updates to the docs * apply formatter * fix wrong matrix for bilinear interpolation
1 parent 64fdf88 commit 6823231

File tree

7 files changed

+65
-25
lines changed

7 files changed

+65
-25
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ version = "0.1.2-DEV"
77
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
88
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
99
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
10+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1011

1112
[weakdeps]
1213
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
@@ -19,4 +20,5 @@ Downloads = "1.6"
1920
LinearAlgebra = "1"
2021
Makie = "0.21, 0.22"
2122
SparseArrays = "1"
23+
StaticArrays = "1.9"
2224
julia = "1.10"

docs/src/trixi_jl_examples.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ and [B-spline function](https://trixi-framework.github.io/TrixiBottomTopography.
5252
In this case, a cubic B-spline interpolation function with free end condition is chosen.
5353

5454
```@example trixi1d
55-
# B-spline interpolation of the underlying data
56-
spline_struct = CubicBSpline(Rhine_data)
57-
spline_func(x) = spline_interpolation(spline_struct, x)
55+
# B-spline interpolation of the underlying data.
56+
# The type of this struct is fixed as `CubicBSpline`.
57+
const spline_struct = CubicBSpline(Rhine_data)
58+
spline_func(x::Float64) = spline_interpolation(spline_struct, x)
5859
```
5960

6061
Now that the B-spline interpolation function is determined, the one dimensional shallow water equations implemented in Trixi.jl can be defined by calling:
@@ -242,9 +243,10 @@ nothing #hide
242243
Using the data, a bicubic B-spline interpolation is performed on the data to define a bottom topography function.
243244

244245
```@example trixi2d
245-
# B-spline interpolation of the underlying data
246-
spline_struct = BicubicBSpline(Rhine_data)
247-
spline_func(x,y) = spline_interpolation(spline_struct, x, y)
246+
# B-spline interpolation of the underlying data.
247+
# The type of this struct is fixed as `BicubicBSpline`.
248+
const spline_struct = BicubicBSpline(Rhine_data)
249+
spline_func(x::Float64, y::Float64) = spline_interpolation(spline_struct, x, y)
248250
```
249251

250252
Then the two dimensional shallow water equations are defined, where the gravitational constant has been chosen to be `3.0` and the initial water height `55.0`. Afterwards, the initial condition is defined. Similar to the one dimensional case, in the center of the domain, a circular part with a diameter of `100.0` is chosen where the initial water height is chosen to be `10.0` units higher.

src/1D/spline_cache_1D.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ function LinearBSpline(x::Vector, y::Vector)
7474

7575
Delta = x[2] - x[1]
7676

77-
IP = [-1 1;
78-
1 0]
77+
IP = @SMatrix [-1 1;
78+
1 0]
7979

8080
Q = y
8181

@@ -256,10 +256,10 @@ function CubicBSpline(x::Vector, y::Vector; end_condition = "free", smoothing_fa
256256

257257
n = length(x)
258258
P = vcat(0, y, 0)
259-
IP = [-1 3 -3 1;
260-
3 -6 3 0;
261-
-3 0 3 0;
262-
1 4 1 0]
259+
IP = @SMatrix [-1 3 -3 1;
260+
3 -6 3 0;
261+
-3 0 3 0;
262+
1 4 1 0]
263263

264264
# Free end condition
265265
if end_condition == "free"

src/1D/spline_methods_1D.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,15 @@ function spline_interpolation(b_spline::LinearBSpline, x::Number)
4848

4949
kappa_i = (x - x_vec[i]) / Delta
5050

51-
c_i1 = [kappa_i, 1]' * IP * Q[i:(i + 1)]
51+
# Allocation free version of the naive implementation
52+
# c_i1 = [kappa_i, 1]' * IP * Q[i:(i + 1)]
53+
54+
# Note, IP has already been constructed as an `SMatrix`
55+
# in the `LinearBSpline` constructor
56+
kappa_vec = @SVector [kappa_i, 1]
57+
Q_slice = @SVector [Q[i], Q[i + 1]]
58+
59+
c_i1 = kappa_vec' * IP * Q_slice
5260

5361
return c_i1
5462
end
@@ -101,7 +109,15 @@ function spline_interpolation(b_spline::CubicBSpline, x::Number)
101109

102110
kappa_i = (x - x_vec[i]) / Delta
103111

104-
c_i3 = 1 / 6 * [kappa_i^3, kappa_i^2, kappa_i, 1]' * IP * Q[i:(i + 3)]
112+
# Allocation free version of the naive implementation
113+
# c_i3 = 1 / 6 * [kappa_i^3, kappa_i^2, kappa_i, 1]' * IP * Q[i:(i + 3)]
114+
115+
# Note, IP has already been constructed as an `SMatrix`
116+
# in the `CubicBSpline` constructor
117+
kappa_vec = @SVector [kappa_i^3, kappa_i^2, kappa_i, 1]
118+
Q_slice = @SVector [Q[i], Q[i + 1], Q[i + 2], Q[i + 3]]
119+
120+
c_i3 = (1 / 6) * (kappa_vec' * IP * Q_slice)
105121

106122
return c_i3
107123
end

src/2D/spline_cache_2D.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ function BilinearBSpline(x::Vector, y::Vector, z::Matrix)
9797
Delta = x[2] - x[1]
9898

9999
P = vcat(reshape(z', (m * n, 1)))
100-
IP = [-1 1;
101-
1 0]
100+
IP = @SMatrix [-1 1;
101+
1 0]
102102

103103
Q = reshape(P, (n, m))
104104

@@ -300,10 +300,10 @@ function BicubicBSpline(x::Vector, y::Vector, z::Matrix; end_condition = "free",
300300
inner_elmts = m * n
301301
P = vcat(reshape(z', (inner_elmts, 1)), zeros(boundary_elmts))
302302

303-
IP = [-1 3 -3 1;
304-
3 -6 3 0;
305-
-3 0 3 0;
306-
1 4 1 0]
303+
IP = @SMatrix [-1 3 -3 1;
304+
3 -6 3 0;
305+
-3 0 3 0;
306+
1 4 1 0]
307307

308308
# Mapping matrix Phi
309309
Phi = spzeros((m + 2) * (n + 2), (m + 2) * (n + 2))

src/2D/spline_methods_2D.jl

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,18 @@ function spline_interpolation(b_spline::BilinearBSpline, x::Number, y::Number)
4747
my = (x - x_vec[i]) / Delta
4848
ny = (y - y_vec[j]) / Delta
4949

50-
Q_temp = [Q[i, j:(j + 1)] Q[(i + 1), j:(j + 1)]]
50+
# Allocation free version of the naive implementation
51+
# Q_temp = [Q[i, j:(j + 1)] Q[(i + 1), j:(j + 1)]]
52+
# c = [ny, 1]' * IP * Q_temp * IP' * [my, 1]
5153

52-
c = [ny, 1]' * IP * Q_temp * IP' * [my, 1]
54+
# Note, IP has already been constructed as an `SMatrix`
55+
# in the `BilinearBSpline` constructor
56+
ny_vec = @SVector [ny, 1]
57+
my_vec = @SVector [my, 1]
58+
Q_temp = @SMatrix [Q[i, j] Q[i + 1, j];
59+
Q[i, j + 1] Q[i + 1, j + 1]]
60+
61+
c = ny_vec' * IP * Q_temp * IP' * my_vec
5362

5463
return c
5564
end
@@ -113,10 +122,20 @@ function spline_interpolation(b_spline::BicubicBSpline, x::Number, y::Number)
113122
my = (x - x_vec[i]) / Delta
114123
ny = (y - y_vec[j]) / Delta
115124

116-
Q_temp = [Q[i, j:(j + 3)] Q[(i + 1), j:(j + 3)] Q[(i + 2), j:(j + 3)] Q[(i + 3),
117-
j:(j + 3)]]
125+
# Allocation free version of the naive implementation
126+
# Q_temp = [Q[i, j:(j + 3)] Q[(i + 1), j:(j + 3)] Q[(i + 2), j:(j + 3)] Q[(i + 3), j:(j + 3)]]
127+
# c = 1 / 36 * [ny^3, ny^2, ny, 1]' * IP * Q_temp * IP' * [my^3, my^2, my, 1]
128+
129+
# Note, IP has already been constructed as an `SMatrix`
130+
# in the `BicubicBSpline` constructor
131+
ny_vec = @SVector [ny^3, ny^2, ny, 1]
132+
my_vec = @SVector [my^3, my^2, my, 1]
133+
Q_temp = @SMatrix [Q[i, j] Q[i + 1, j] Q[i + 2, j] Q[i + 3, j];
134+
Q[i, j + 1] Q[i + 1, j + 1] Q[i + 2, j + 1] Q[i + 3, j + 1];
135+
Q[i, j + 2] Q[i + 1, j + 2] Q[i + 2, j + 2] Q[i + 3, j + 2];
136+
Q[i, j + 3] Q[i + 1, j + 3] Q[i + 2, j + 3] Q[i + 3, j + 3]]
118137

119-
c = 1 / 36 * [ny^3, ny^2, ny, 1]' * IP * Q_temp * IP' * [my^3, my^2, my, 1]
138+
c = (1 / 36) * (ny_vec' * IP * Q_temp * IP' * my_vec)
120139

121140
return c
122141
end

src/TrixiBottomTopography.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module TrixiBottomTopography
1010
# Include necessary packages
1111
using LinearAlgebra: norm, diagm, qr, Tridiagonal, SymTridiagonal
1212
using SparseArrays: sparse, spzeros
13+
using StaticArrays: SVector, @SVector, SMatrix, @SMatrix
1314

1415
# Include one dimensional B-spline interpolation
1516
include("1D/spline_cache_1D.jl")

0 commit comments

Comments
 (0)