Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ because a changelog assembled after the fact loses exactly the reasoning that ma
keeping. The `[Unreleased]` target below is provisional — confirm it when the first entry is
written.

## [Unreleased] — targeting 0.2.2

### New Features

- **`spectrumplot` draws a reduced basis's spectrum, and `Makie` joins `[weakdeps]`, at `"0.24"`.**
`spectrumplot(σ::AbstractVector{<:Real}; title = "", ylabel = "", size = (620, 380))` draws `σ`
against its index on a log10 axis and returns a `Makie.FigureAxisPlot`. It lives in the extension
`ReducedBasisMethodsMakieExt`, which loads with `Makie`, so without `Makie` the call is a
`MethodError`; `save` needs a backend such as `CairoMakie`.

### Changed

- **The docs environment drops `Weave` and `Plots`, and `get_DEIM_interpolation_matrix` carries a
`jldoctest`.** No page used either package. This is the only `jldoctest` in the package;
`test/quality/doctests.jl` runs it in the `doctests` group.

## [0.2.1] — 2026-10-14

### New Features
Expand Down
7 changes: 7 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ MultiIndexArrays = "2f7e0951-2673-41f4-a6a8-e6772a4b2a08"
ReducedComplexityModeling = "abb4722c-1d8e-48eb-a3bd-45b3116bfaba"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"

[extensions]
ReducedBasisMethodsMakieExt = "Makie"

[compat]
GeometricEquations = "0.21"
HDF5 = "0.16, 0.17"
LinearAlgebra = "1"
Makie = "0.24"
MultiIndexArrays = "0.1.2"
ReducedComplexityModeling = "0.1.1"
Statistics = "1"
Expand Down
4 changes: 0 additions & 4 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
ReducedBasisMethods = "91da5cd7-58ae-4d67-87db-f03d1c8da121"
Weave = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"

[compat]
Documenter = "1.19.0"
Plots = "1.41.7"
Weave = "0.10.12"
5 changes: 0 additions & 5 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using ReducedBasisMethods
using Documenter
using Weave

# weave("src/poisson.jmd",
# out_path = "src",
# doctype = "github")

makedocs(;
modules = [ReducedBasisMethods],
Expand Down
19 changes: 19 additions & 0 deletions ext/ReducedBasisMethodsMakieExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module ReducedBasisMethodsMakieExt

using Makie
using ReducedBasisMethods

function ReducedBasisMethods.spectrumplot(σ::AbstractVector{<:Real};
title = "", ylabel = "", size = (620, 380))
all(isfinite, σ) || throw(ArgumentError("the spectrum holds a NaN or an Inf"))
any(>(0), σ) || throw(ArgumentError("the spectrum holds no positive value"))

# A log-scaled axis cannot draw the exact zeros of a rank-deficient snapshot set or the
# round-off negatives of a Gram spectrum, so every value below the floor is lifted onto it.
y = max.(Float64.(σ), eps(Float64) * Float64(maximum(σ)))

return lines(y; figure = (; size),
axis = (; title, titlealign = :left, xlabel = "i", ylabel, yscale = log10))
end

end
4 changes: 4 additions & 0 deletions src/ReducedBasisMethods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ include("reduced_equations.jl")

export reduced_ode, reduced_pode

include("diagnostics.jl")

export spectrumplot

export h5save, h5load

include("reduced_tensor.jl")
Expand Down
9 changes: 9 additions & 0 deletions src/algorithms/deim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ Returns the `N × k` matrix `Π` whose column `i` is the unit vector of the row
Its element type is `float(eltype(Ψ))`, so a `Float32` basis gives a `Float32` interpolation
matrix. The selection, and with it the `ArgumentError` for `k > N` and for a column whose
largest residual magnitude is not finite and positive, is [`get_DEIM_indices`](@ref)'s.

```jldoctest
julia> using ReducedBasisMethods

julia> get_DEIM_interpolation_matrix([1 1; 2 -1])
2×2 Matrix{Float64}:
0.0 1.0
1.0 0.0
```
"""
function get_DEIM_interpolation_matrix(Ψ::AbstractMatrix)
N, k = size(Ψ)
Expand Down
20 changes: 20 additions & 0 deletions src/diagnostics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
spectrumplot(σ::AbstractVector{<:Real}; title = "", ylabel = "", size = (620, 380))

Draw the spectrum `σ` of a reduced basis against its index on a log-scaled axis, in `Float64`.
The values are drawn as given: singular values, or the squared singular values (Gram eigenvalues)
that a `ReducedBasis` stores in `Λ`. `ylabel` names which, and `size` is the figure size.

Every value below `eps(Float64) * maximum(σ)` is drawn at that floor, so the exact zeros and the
round-off negatives of a Gram spectrum stay on the axis. A spectrum that holds a `NaN` or an `Inf`,
or no positive value, throws an `ArgumentError`.

Returns a `Makie.FigureAxisPlot`. Defined in a package extension that loads with `Makie`; `save`
needs a backend such as `CairoMakie`.

```julia
using ReducedBasisMethods, CairoMakie
save("spectrum.png", spectrumplot(b.Λ; ylabel = "λᵢ"))
```
"""
function spectrumplot end
4 changes: 4 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
GeometricBrackets = "2a9ffa85-4e0d-473f-b05e-278d80d8d306"
GeometricIntegrators = "dcce2d33-59f6-5b8d-9047-0defad88ae06"
Expand All @@ -17,6 +19,8 @@ ReducedBasisMethods = {path = ".."}

[compat]
Aqua = "0.8.18"
CairoMakie = "0.15"
Documenter = "1.19.0"
ForwardDiff = "1.4.6"
GeometricBrackets = "0.1.1, 0.2"
GeometricIntegrators = "0.18.5"
48 changes: 48 additions & 0 deletions test/diagnostics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using CairoMakie
using ReducedBasisMethods
using Test

"The plotted values of a `FigureAxisPlot`."
plotted_y(fap) = [q[2] for q in fap.plot.positions[]]

@testset "Diagnostics" begin
@test Base.get_extension(ReducedBasisMethods, :ReducedBasisMethodsMakieExt) isa Module

@testset "a spectrum is drawn as given and saved headless ($T)" for T in (Float64, Float32)
σ = T.(10.0 .^ (-(1:10)))
fap = spectrumplot(σ)
@test fap isa CairoMakie.Makie.FigureAxisPlot
@test eltype(eltype(fap.plot.positions[])) == Float64
@test plotted_y(fap) == σ

path = joinpath(mktempdir(), "spectrum.png")
save(path, fap)
@test read(path)[1:4] == UInt8[0x89, 0x50, 0x4e, 0x47]
end

@testset "the axis label and the figure size" begin
@test spectrumplot([1.0]).axis.ylabel[] == ""
fap = spectrumplot([1.0, 0.5]; ylabel = "λᵢ", size = (300, 200))
@test fap.axis.ylabel[] == "λᵢ"
@test Base.size(fap.figure.scene) == (300, 200)
end

@testset "a one-element and a BigFloat spectrum" begin
@test plotted_y(spectrumplot([3.0])) == [3.0]
@test plotted_y(spectrumplot(big.([1.0, 0.5, 0.25]))) == [1.0, 0.5, 0.25]
end

@testset "values below the floor are drawn at the floor ($T)" for T in (Float64, Float32)
# the floor is eps(Float64) * maximum(σ) = eps(Float64)
σ = T[1, 1e-3, 1e-20, 0, -1e-18]
@test plotted_y(spectrumplot(σ)) == [1, Float64(T(1e-3)), eps(), eps(), eps()]
end

@testset "a spectrum with a NaN, an Inf or no positive value is refused" begin
@test_throws ArgumentError spectrumplot(Float64[])
@test_throws ArgumentError spectrumplot([1.0, NaN])
@test_throws ArgumentError spectrumplot([1.0, Inf])
@test_throws ArgumentError spectrumplot(zeros(3))
@test_throws ArgumentError spectrumplot([0.0, -1e-17])
end
end
13 changes: 13 additions & 0 deletions test/integration/load_without_makie.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ReducedBasisMethods
using Test

# `Makie` is a weak dependency: loading the package, in an environment that has a Makie backend
# installed, loads no Makie module, and `spectrumplot` has no method.
@testset "Load without Makie" begin
code = """
using ReducedBasisMethods, Test
@test !any(m -> occursin("Makie", m.name), keys(Base.loaded_modules))
@test_throws MethodError spectrumplot([1.0, 0.5])
"""
@test success(`$(Base.julia_cmd()) --startup-file=no --project=$(Base.active_project()) -e $code`)
end
12 changes: 12 additions & 0 deletions test/quality/docs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using ReducedBasisMethods
using Test

@testset "no physical word in the code or the documentation" begin
# The package knows no model. `CHANGELOG.md` and `reference/` may name one.
root = pkgdir(ReducedBasisMethods)
files = [joinpath(path, file) for dir in ("src", "ext", "docs/src")
for (path, _, names) in walkdir(joinpath(root, dir)) for file in names]
for file in [files; joinpath(root, "docs", "make.jl")]
@test !occursin(r"vlasov|particle"i, read(file, String))
end
end
5 changes: 5 additions & 0 deletions test/quality/doctests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using ReducedBasisMethods
using Documenter: doctest

# The docstring doctests. `manual = false` leaves the manual's doctests to `docs/make.jl`.
doctest(ReducedBasisMethods; manual = false)
8 changes: 8 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const GROUPS = isempty(ARGS) ? ["core", "slow"] : ARGS

if "core" in GROUPS
@safetestset "Aqua" include("quality/aqua.jl")
@safetestset "Docs" include("quality/docs.jl")
@safetestset "Generic-only skeleton" include("integration/skeleton.jl")
@safetestset "Reference spectra script" include("integration/reference_spectra.jl")
@safetestset "Reduced basis" include("reducedbasis.jl")
Expand All @@ -16,3 +17,10 @@ if "core" in GROUPS
@safetestset "Symplectic DEIM" include("algorithms/symplectic_deim.jl")
@safetestset "Reduced equations" include("reduced_equations.jl")
end
if "slow" in GROUPS
@safetestset "Load without Makie" include("integration/load_without_makie.jl")
@safetestset "Diagnostics" include("diagnostics.jl")
end
if "doctests" in GROUPS
@safetestset "Doctests" include("quality/doctests.jl")
end
Loading