Skip to content

Repository files navigation

SimpleSplines

Stable Dev Build Status Documentation Coverage PkgEval

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.

It is not a curve- and surface-modelling library: there are no NURBS, no knot insertion, no degree elevation and no least-squares fitting of data. It is for discretising a differential equation and then solving with the result.

Installation

No version is registered yet, so install from the repository:

using Pkg
Pkg.add(url = "https://github.com/JuliaDEC/SimpleSplines.jl")

Example

Solving -u'' = f with u(0) = u(1) = 0, on a cubic basis over 16 uniform cells:

using SimpleSplines

# the boundary condition is built into the basis, not applied to the matrix afterwards
b = BSplineBasis(UniformMesh(16, 0 .. 1), 3, Dirichlet())

# assembly tabulates the basis and its derivatives at the global Gauß-Legendre points,
# and every matrix is a weighted contraction of that one table
q = SplineQuadrature(b)
M = mass_matrix(q)
K = stiffness_matrix(q)

f(x) = π^2 * sin* x)
rhs = basis_values(q, 0) * (quadrature_weights(q) .* f.(quadrature_nodes(q)))
û = Matrix(K) \ rhs

maximum(abs(evaluate(b, û, x) - sin* x)) for x in range(0, 1; length = 101))

which is 2.08e-6. Fitting a function to the space instead is an L² projection, and the result is callable:

u = Spline(b, l2_projection(q, x -> sin* x)))
u(0.5), u(0.5, 1), u(0.0)        # value, first derivative, and the imposed u(0) = 0

The manual has a tutorial, the spline theory the package rests on, a usage page per object with the constructors and the traps, a gallery of eight solved problems with their measured errors, and the full API.

Development

Git hooks

Two hooks live in .githooks. They are not active in a fresh clonecore.hooksPath is local configuration and does not travel with a push — so enable them once per clone:

git config core.hooksPath .githooks

pre-commit acts on staged .jl files only, and exits immediately when a commit stages none, so a documentation- or workflow-only commit is not slowed down by it:

  • JuliaFormatter --check, honouring this repository's own .JuliaFormatter.tomlblocks the commit. Formatting is mechanical and always fixable.
  • fatou lint, when fatou is installed — advisory only, and deliberately so: its unused-import rule does not follow include, so it flags the load-bearing imports of every module file.
  • using <Package>, which catches a syntax error or a broken includeblocks.

pre-push runs the full test suite with --check-bounds=auto, but only when pushing to main or master; a topic branch is left to CI. It prints nothing for 10–30 minutes, which looks exactly like a network hang and is not one. If you do interrupt it, check for an orphaned Julia process that the killed hook left behind.

Either hook can be bypassed for a single command with --no-verify, for a change you know it does not apply to:

git commit --no-verify
git push --no-verify

The hooks are generated from one shared copy and are byte-identical across the related repositories, so edit them there rather than here — a local edit is silently undone by the next install.

About

A simple implementation of basic splines.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages