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
53 changes: 51 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,55 @@ The first release with any implementation in it. Before this the package was a
`PkgTemplates` skeleton: a registered UUID, CI, docs scaffolding and a declared dependency
set, with `src/SimpleSplines.jl` a bare `module … end`.

### The manual

The documentation was one page ending in an `@autodocs` dump, and its opening two paragraphs
still described the package as periodic-only with "one basis" — which had not been true since
the boundary conditions and tensor products landed. It is now a manual of fourteen pages:

| | |
|:--|:--|
| **Tutorial** | one narrative from a bare `using` to a solved boundary-value problem |
| **Theory** | the Cox-de Boor recursion, the derivative recursion, support, smoothness and the three dimension counts; recombination and what it costs; the tensor-product space and its flattening convention |
| **Usage** | one page per object — meshes, bases, boundary conditions, assembly, tensor products, splines — with the exact constructors, the accessor tables, what is rejected, and the traps |
| **Gallery** | eight solved problems, each printing what it measured — a convergence rate where one is meaningful, otherwise the errors themselves |
| **Library** | every export, grouped by topic, with explicit `@docs` blocks rather than `@autodocs` |
| **References** | a bibliography, via `DocumenterCitations` |

Everything computational in it is an `@example` block, so the numbers, the rates and the
sixteen `CairoMakie` figures are produced by the build and a claim that stops being true stops
the build. Three of the gallery problems are new rather than lifted from the suite: Poisson in
one dimension with a `Dirichlet` basis and its variable-coefficient variant, which reports a
measured order of `p+1`; the Dirichlet eigenvalues against `(kπ)²`, which reports the relative
error per mode and per degree; and Poisson on a box through the separable Laplacian, which
reports the error at three refinements.

The library page is written out by hand instead of generated, for two reasons: `@autodocs`
rendered the internal `_bspline` alongside the public API, and an explicit list is what makes
a missing docstring visible. `checkdocs = :exports` is on.

**One documentation bug fixed.** The `@doc raw` block whose signatures read
`findcell(b, x)` / `findcell(m, x)` sat immediately above the internal `_findcell` and so
documented *that*: `?findcell` showed nothing, `@docs findcell` would have failed the build,
and `@autodocs` rendered the text under `SimpleSplines._findcell`. It is now attached to
`findcell` itself. The same class of mistake as a comment between a docstring and its
definition, and equally silent — nothing but a docs build notices.

**One complexity claim corrected.** Writing the cost table for the manual turned up a wrong
figure in the source: `evaluate`'s and `evaluate_all!`'s docstrings gave the single-function
path as `O(p²)`, but `_bspline` runs the recursion unmemoised — it splits into two subproblems
at every level — so one value costs `O(2^p)`. Measured over 20 000 evaluations on a 40-cell
mesh, `evaluate` takes 26 ns at `p = 3` and 15.5 µs at `p = 12`, against 21 ns and 104 ns for
the *whole block* through `evaluate_all`. Nothing about the implementation changed; the
choice to run the formula as written is deliberate, and the reason `evaluate_all!` exists.
What was wrong was the number, in the one place a reader would take it from.

Docstrings were added for the exports that had none: `quadratures`,
`PeriodicBSplineDerivative`, `nnodes`, `grid`, `basis` on a `SplineQuadrature`, and `basis`,
`mass_operator`, `mass_matrix` and `nnodes` on the tensor-product types. `Basis`, `..`,
`leftendpoint` and `rightendpoint` are re-exported unchanged and are documented by the packages
that own them, which the library page says.

### General boundary conditions and tensor products

The package was periodic-only: one basis, on `[0,L)`, on a torus. It now covers bounded
Expand Down Expand Up @@ -491,9 +540,9 @@ Found in review of the branch, not by the suite, and each now has a regression t
reaches, because only that one contributes to `a_{m+1} = c_m D^m φ_{m+1}(a)`. That anchor is
nonzero whenever the leading coefficient `c_m` is — but *how* nonzero is the caller's, not the
construction's. `Robin(1.0, 1e-20)` puts a small coefficient on the highest derivative, the
anchor is then numerically zero, and the recombination coefficients `-a_t/a_{m+1}` overflow:
anchor is then numerically zero, and the recombination coefficients `-a_t/a_{m+1}` become huge:
the mass matrix comes out finite with a condition number already `Inf`, `cholesky(…;
check = false)` reports `issuccess` on a matrix containing `Inf`, and the projection that
check = false)` reports `issuccess` on it anyway, and the projection that
follows looks plausible.

A finiteness guard would catch only the most extreme case and is a symptom patch — the
Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@
[![Coverage](https://codecov.io/gh/JuliaDEC/SimpleSplines.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/JuliaDEC/SimpleSplines.jl)
[![PkgEval](https://JuliaCI.github.io/NanosoldierReports/pkgeval_badges/S/SimpleSplines.svg)](https://JuliaCI.github.io/NanosoldierReports/pkgeval_badges/S/SimpleSplines.html)

Periodic B-spline finite elements on an interval, built from the Cox-de Boor recursion,
with the quadrature and assembly a Galerkin discretisation needs. The package provides the
periodic B-spline basis of arbitrary degree on uniform, graded and random meshes, together
with an assembly table from which the mass, stiffness, derivative and variable-coefficient
matrices follow as single weighted contractions.
B-spline finite elements on an interval, built from the Cox-de Boor recursion, with the
quadrature and assembly a Galerkin discretisation needs.

The package provides the clamped, periodic and recombined B-spline bases of arbitrary degree
on uniform, graded, random or arbitrary meshes; homogeneous Dirichlet, Neumann, Robin, natural
and general local boundary conditions per end; tensor products in any number of dimensions,
with degree, mesh, domain and boundary condition per axis; and an assembly table from which the
mass, stiffness, derivative and variable-coefficient matrices follow as single weighted
contractions. Mass solves go through a representation chosen by the basis — an FFT for a
periodic uniform basis, a banded Cholesky for a bounded one, and a factored Kronecker product
in several dimensions.

The [manual](https://JuliaDEC.github.io/SimpleSplines.jl/dev/) has a tutorial, the spline
theory the package rests on, a gallery of solved problems and the full API.

## Development

Expand Down
8 changes: 7 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
[deps]
CompactBasisFunctions = "a09551c4-f815-4143-809e-dd1986753ba7"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SimpleSplines = "ac480f6c-9a94-4d53-a283-9db69f109154"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[sources]
SimpleSplines = {path = ".."}

[compat]
CairoMakie = "0.12, 0.13, 0.14, 0.15"
Documenter = "1"
DocumenterCitations = "1"
27 changes: 27 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,46 @@
using SimpleSplines
using Documenter
using DocumenterCitations

DocMeta.setdocmeta!(SimpleSplines, :DocTestSetup, :(using SimpleSplines); recursive = true)

bib = CitationBibliography(joinpath(@__DIR__, "src", "references.bib"))

makedocs(;
plugins = [bib],
modules = [SimpleSplines],
authors = "Michael Kraus",
sitename = "SimpleSplines.jl",
checkdocs = :exports,
format = Documenter.HTML(;
prettyurls = get(ENV, "CI", "false") == "true",
canonical = "https://JuliaDEC.github.io/SimpleSplines.jl",
edit_link = "main",
# the library page collects every docstring in the package and is legitimately
# large; the default warning threshold is aimed at pages that are large by accident
size_threshold_warn = 400 * 1024,
size_threshold = 800 * 1024,
assets = String[]
),
pages = [
"Home" => "index.md",
"Tutorial" => "tutorial.md",
"Theory" => [
"B-Splines" => "theory/bsplines.md",
"Boundary Conditions" => "theory/boundary.md",
"Tensor Products" => "theory/tensorproduct.md"
],
"Usage" => [
"Meshes" => "usage/meshes.md",
"Bases" => "usage/bases.md",
"Boundary Conditions" => "usage/boundary.md",
"Assembly" => "usage/quadrature.md",
"Tensor Products" => "usage/tensorproduct.md",
"Splines" => "usage/splines.md"
],
"Gallery" => "gallery.md",
"Library" => "library.md",
"References" => "references.md"
]
)

Expand Down
Loading
Loading