Feat: add time integration#385
Conversation
465d2b9 to
16ffc7e
Compare
Adds the remaining part of the heat equation notebook with working video. However, will need to be updated to ensure consistency between the text and code.
The implemented algorithm does not work for fully implicit integrators, so those will need special treatment. This is in progress.
These tests are based on a stability analysis and convergence rates. Currently implemented for Explicit and DiagonallyImplicit schemes that are multi-step but single step. Needs to be extended to fully Implicit and multi-step schemes.
6fbaf0c to
b8eb53c
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a new TimeIntegrators module to Mantis, aiming to support time-dependent (ODE/PDE) problems via a General Linear Methods (GLM) framework, alongside documentation, examples, and a dedicated test suite.
Changes:
- Added
src/TimeIntegrators/*implementing integrator/scheme definitions, initialization, nonlinear solver helpers, and stepping routines. - Added a new
test/TimeIntegratorssuite plus JET inference coverage for the TimeIntegrators API. - Updated docs/examples and plotting utilities (including a new Makie-based basis-function plotting helper).
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
src/TimeIntegrators/TimeIntegrators.jl |
Introduces the TimeIntegrators module entrypoint and includes subcomponents. |
src/TimeIntegrators/Definitions.jl |
Defines core integrator/operator/solution types and related getters. |
src/TimeIntegrators/Schemes.jl |
Adds a library of predefined explicit/implicit/IMEX schemes and a tableau conversion helper. |
src/TimeIntegrators/Initialisations.jl |
Adds initialization logic for single-step and multi-step schemes (with startup schemes). |
src/TimeIntegrators/Integrations.jl |
Implements stepping routines (time_integrate!) across integrator types. |
src/TimeIntegrators/NonlinearSolvers.jl |
Adds Newton/Picard/fixed-point helper constructors for implicit solves. |
test/TimeIntegrators/runtests.jl |
Adds a TimeIntegrators test entrypoint. |
test/TimeIntegrators/AdvectionTests.jl |
Adds an advection-based correctness test for Forward Euler at CFL=1. |
test/TimeIntegrators/ConvergenceTests.jl |
Adds convergence-rate tests across many schemes (explicit/implicit/IMEX, multi-step). |
test/TimeIntegrators/StabilityTests.jl |
Adds von Neumann/amplification-factor stability-function tests. |
test/runtests.jl |
Wires TimeIntegrators tests into the top-level test runner and reformats testsets. |
test/Inference/TimeIntegratorsInferenceTests.jl |
Adds JET inference coverage for TimeIntegrators API calls. |
test/Inference/runtests.jl |
Includes the new TimeIntegrators inference testset. |
src/Mantis.jl |
Includes and exports the new TimeIntegrators module. |
docs/src/Design/Modules/TimeIntegrators.md |
Adds design/module documentation for TimeIntegrators (GLM background + API docs). |
docs/src/refs.bib |
Adds bibliographic entries referenced by TimeIntegrators documentation. |
docs/make.jl |
Wires TimeIntegrators docs module into the documentation build and updates formatting. |
docs/Project.toml |
Adds doc-build dependencies used by the new docs/examples (e.g. Makie/LinearSolve/StaticArrays). |
examples/src/ThreeBodyProblem.jl |
Adds a time-integration example (three-body problem) using TimeIntegrators. |
examples/src/HeatEquation.jl |
Updates the heat equation example (incl. basis plotting via Makie extension). |
ext/MakieExt.jl |
Extends plotting with Makie-based plot_basis for FE spaces. |
src/Plot/Plot.jl |
Adds imports/usings needed by new plotting capabilities. |
src/Plot/PlotHelpers.jl |
Adds plot_basis stub and a point-padding helper for 1D plotting. |
mytest/threebody.jl |
Adds an experimentation script (three-body) outside the docs/examples system. |
mytest/LorenzImplicit.jl |
Adds an experimentation script (implicit Lorenz). |
mytest/benchmark.jl |
Adds an experimentation benchmark script comparing against other ecosystems. |
mytest/Project.toml |
Adds a standalone test environment for experimentation scripts. |
CONTRIBUTORS.md |
Adds a contributors/maintainers list, including TimeIntegrators origin credits. |
.JuliaFormatter.toml |
Tweaks formatter configuration comments/formatting. |
.gitignore |
Ignores common video formats by default (likely for generated example output). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| xi = reduce(vcat, y_nm1 for i in 1:num_stages) | ||
| Y = reduce(vcat, y_n.stage_values for i in 1:num_stages) | ||
|
|
| @inbounds for i in 1:num_steps | ||
| allG = ode.implicitEvaluate(Y; kwargs...) | ||
| for n in 1:N | ||
| @views solution_allocated[n, i] = | ||
| dt * dot(allG[((n - 1) * num_stages + 1):end], scheme.B[i, :]) | ||
| @views solution_allocated[n, i] += sum(y_nm1[n] .* scheme.V[i, :]) | ||
| end | ||
| end |
| These methods are applicable to both ODEs and PDEs, so that both are available in `Mantis`. | ||
|
|
||
| General linear methods can be characterised as follows (see [Butcher2006](@cite), [Vos2011](@cite)). | ||
| Consider the initial value problem as ODE |
There was a problem hiding this comment.
"...problem defined as the ODE..."
| This framework allows for an easy implementation of a variety of explicit, implicit, and implicit-explicit (IMEX) time stepping schemes, and is based on the concept of general linear methods (see, for example, [Butcher2006](@cite)). | ||
| These methods are applicable to both ODEs and PDEs, so that both are available in `Mantis`. | ||
|
|
||
| General linear methods can be characterised as follows (see [Butcher2006](@cite), [Vos2011](@cite)). |
There was a problem hiding this comment.
Introduce (GLM) since it is used below.
| \frac{d\mathbf{y}}{dt} = \mathbf{f}(\mathbf{y}), \quad \mathbf{y}(t_0) = \mathbf{y}_0\;, | ||
| ``` | ||
| where ``\mathbf{f}: \mathbb{R}^N \to \mathbb{R}^N``. | ||
| The ``n``-th (time) step of the GLM comprised of ``r`` (integrator) steps and ``s`` stages is then formulatied as |
| \mathbf{y}^{n-1} | ||
| \end{bmatrix} \;, | ||
| ``` | ||
| which is often simplyfied (with some abuse of notation) to |
|
|
||
| The `AbstractTimeIntegrator{num_stages, num_steps}` type has four concrete subtypes, each | ||
| representing a specific class of time integrators. | ||
| ```@docs |
| ``` | ||
|
|
||
| The ``A``-matrix (see above) in the GLM framework dictates whether a scheme is implicit or not. | ||
| When initialising one of the above structs, this is check using the following function. |
| get_solution | ||
| get_scheme | ||
| get_startup_scheme | ||
| get_remaining_startup_steps |
There was a problem hiding this comment.
will be computed* (in the docstring)
| get_solution_allocated | ||
| get_F_allocated | ||
| get_G_allocated | ||
| get_stage_values |
| To use the `TimeIntegrators`-module, you have to specify which problem you want to solve. | ||
| Information about the problem is collected in `TimeIntegrationOperators`. | ||
| ```@docs | ||
| TimeIntegrationOperators |
There was a problem hiding this comment.
Some of the notation is not introduced.
| define_imex_ode | ||
| define_picard_solver_ode | ||
| define_newton_solver_ode | ||
| define_fixed_point_relaxation_ode |
There was a problem hiding this comment.
Arguments incorrectly formatted.
| if num_G > 0 && remaining_startup_steps - num_G <= 0 | ||
| index_implicit = num_steps + num_G + (remaining_startup_steps - num_G) | ||
| y_n.solution[:, index_implicit] .= | ||
| ode.implicitEvaluate(get_solution(y_n_startup); kwargs...) .* dt | ||
| end |
| xi = reduce(vcat, y_nm1 for i in 1:num_stages) | ||
| Y = reduce(vcat, y_n.stage_values for i in 1:num_stages) | ||
|
|
||
| # newAblocks = ntuple(N) do | ||
| # SparseArrays.sparse(scheme.A * dt) | ||
| # end | ||
| # newA = SparseArrays.blockdiag([SparseArrays.sparse(scheme.A * dt) for i in 1:N]...) | ||
|
|
||
| # sparse_block = SparseArrays.sparse(Matrix(scheme.A * dt)) | ||
| # newA = SparseArrays.blockdiag((sparse_block for i in 1:N)...) | ||
| # Y = ode.implicitSolve(xi, newA, t + scheme.C[1] * dt; kwargs...) | ||
| ode.implicitSolve(Y, xi, scheme.A * dt, t + scheme.C[1] * dt; kwargs...) | ||
|
|
||
| @inbounds for i in 1:num_steps | ||
| allG = ode.implicitEvaluate(Y; kwargs...) | ||
| for n in 1:N | ||
| @views solution_allocated[n, i] = | ||
| dt * dot(allG[((n - 1) * num_stages + 1):end], scheme.B[i, :]) | ||
| @views solution_allocated[n, i] += sum(y_nm1[n] .* scheme.V[i, :]) | ||
| end |
| U = ones(SMatrix{num_stages, 1}) | ||
| V = ones(SMatrix{1, 1}) |
| - `implicitEvaluate::IE`: A function that evaluates the implicit part of the ODE, that is, | ||
| the function that evaluates G = g(y). See the manual section on [TimeIntegrators](@ref) | ||
| for the terminology. **This function must have the following inputs: (yn).** yn will be | ||
| a vector-like object of length N (the number of variables). |
This pull request creates a TimeIntegrators module for Mantis, allowing time-dependent problems to be tackled.
This is not done yet. I think at least the following needs to be done: