Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
e0f73ed
Elixir for implicit solver using sparse jacobian
Jul 10, 2025
9dbe05c
Docstring for new semidiscretize
Jul 22, 2025
6adff66
PR comments
Jul 23, 2025
097e994
Making the hacks into an extension
Jul 23, 2025
2e7cebf
Apply suggestions from code review
DanielDoehring Jul 24, 2025
2be59f8
work
DanielDoehring Jul 24, 2025
254a79f
packages
DanielDoehring Jul 24, 2025
9089e6a
reduce time
DanielDoehring Jul 24, 2025
89a7b92
work
DanielDoehring Jul 24, 2025
524ae9a
use sparse ode
DanielDoehring Jul 24, 2025
c984c02
comment
DanielDoehring Jul 24, 2025
0dd324d
be more explicit
DanielDoehring Jul 24, 2025
1f5a40b
try nonlinear
DanielDoehring Jul 24, 2025
46b2d92
comment
DanielDoehring Jul 24, 2025
ca5f951
comment
DanielDoehring Jul 24, 2025
7bdfc8d
exchange solver
DanielDoehring Jul 25, 2025
2f9d246
work
DanielDoehring Jul 25, 2025
c1ebd50
comment
DanielDoehring Jul 25, 2025
7d141cf
comments
DanielDoehring Jul 25, 2025
bb6b7d5
Merge branch 'main' into SteveSparseDiff
DanielDoehring Jul 25, 2025
4e163fe
comment
DanielDoehring Jul 25, 2025
dad7fe7
rename
DanielDoehring Jul 28, 2025
b5db145
comments
DanielDoehring Jul 28, 2025
3ce1a4c
Moving the ext back into the elixirs
Jul 28, 2025
a65537c
Adding CI test
Jul 28, 2025
27bc102
Adding CI test for implicit_sparse_jacobian elixir
Jul 28, 2025
d956961
Update examples/tree_1d_dgsem/elixir_euler_convergence_implicit_spars…
DanielDoehring Jul 29, 2025
4b1dbdd
Update examples/tree_1d_dgsem/elixir_euler_convergence_implicit_spars…
DanielDoehring Jul 29, 2025
cc3fa6a
Apply suggestions from code review
DanielDoehring Jul 29, 2025
6e9a0d0
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Jul 29, 2025
6344c66
comments on constant jacs
DanielDoehring Jul 29, 2025
63c9214
move dir
DanielDoehring Jul 29, 2025
691cedf
comment
DanielDoehring Jul 29, 2025
c5f5fcf
order
DanielDoehring Jul 29, 2025
5586491
restart file
DanielDoehring Jul 29, 2025
eb6aa90
Apply suggestions from code review
DanielDoehring Jul 29, 2025
e851808
compat
DanielDoehring Jul 29, 2025
82caac1
Merge branch 'elixir_implicit_sparse' of github.com:sbairos/Trixi.jl …
DanielDoehring Jul 29, 2025
9d97bcc
remove redundant comments
DanielDoehring Jul 29, 2025
2ed4e38
Elixir for implicit solver using sparse jacobian
Jul 10, 2025
7bd5f32
Docstring for new semidiscretize
Jul 22, 2025
238cadb
PR comments
Jul 23, 2025
8a4ce20
Making the hacks into an extension
Jul 23, 2025
d12dca7
Apply suggestions from code review
DanielDoehring Jul 24, 2025
6b3a900
work
DanielDoehring Jul 24, 2025
ef31890
packages
DanielDoehring Jul 24, 2025
d65fadb
reduce time
DanielDoehring Jul 24, 2025
8289379
work
DanielDoehring Jul 24, 2025
61e8f13
use sparse ode
DanielDoehring Jul 24, 2025
6e3d6ea
comment
DanielDoehring Jul 24, 2025
d02e4d1
be more explicit
DanielDoehring Jul 24, 2025
d024182
try nonlinear
DanielDoehring Jul 24, 2025
4041aab
comment
DanielDoehring Jul 24, 2025
b5f7e10
comment
DanielDoehring Jul 24, 2025
80b3d53
exchange solver
DanielDoehring Jul 25, 2025
979a66b
work
DanielDoehring Jul 25, 2025
914e1dd
comment
DanielDoehring Jul 25, 2025
9cfdbd0
comments
DanielDoehring Jul 25, 2025
0fa5381
comment
DanielDoehring Jul 25, 2025
987c1ea
rename
DanielDoehring Jul 28, 2025
8c7a425
comments
DanielDoehring Jul 28, 2025
b526312
Moving the ext back into the elixirs
Jul 28, 2025
51a5b77
Adding CI test
Jul 28, 2025
9f713b9
Adding CI test for implicit_sparse_jacobian elixir
Jul 28, 2025
4ca244b
CI tests for both
Jul 29, 2025
6909159
Merge branch 'workwork' into elixir_implicit_sparse
Jul 29, 2025
4467be4
Other 2 CI tests
Jul 29, 2025
5bb92d6
Uncomment commented tests and delete 1D convergence_implicit elixir
Jul 29, 2025
0cc77c0
Replace the test that I accidentally overwrote
Jul 29, 2025
a829d5c
Unit test
Jul 29, 2025
c303210
Update test/test_unit.jl
DanielDoehring Jul 29, 2025
84a5be8
Update Project.toml
DanielDoehring Jul 29, 2025
747768e
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Jul 29, 2025
9a164a8
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Jul 29, 2025
03ac768
revisit
DanielDoehring Jul 30, 2025
b0e9083
unit test
DanielDoehring Jul 30, 2025
5c33791
repeat comment
DanielDoehring Jul 30, 2025
5e7e7b1
linear structure
DanielDoehring Jul 30, 2025
9137af2
fmzt
DanielDoehring Jul 30, 2025
5ae5c72
fix unit test
DanielDoehring Jul 30, 2025
026bc8a
Apply suggestions from code review
DanielDoehring Jul 31, 2025
6e8115c
Spellcheck
Jul 31, 2025
2a894fe
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Jul 31, 2025
a147c1c
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Jul 31, 2025
5719d0e
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 1, 2025
61e4d47
comment
DanielDoehring Aug 1, 2025
122a46e
add sparse arrays
DanielDoehring Aug 1, 2025
47a7a5b
try module
DanielDoehring Aug 1, 2025
ea8cf44
rm
DanielDoehring Aug 1, 2025
b9a54d2
try more specific overload
DanielDoehring Aug 2, 2025
476b174
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 2, 2025
309c730
simplify
DanielDoehring Aug 2, 2025
6d6a497
v
DanielDoehring Aug 4, 2025
36ed9b9
v
DanielDoehring Aug 4, 2025
07589c2
Update examples/structured_2d_dgsem/elixir_euler_convergence_implicit…
DanielDoehring Aug 11, 2025
70b3861
Update examples/structured_2d_dgsem/elixir_euler_convergence_implicit…
DanielDoehring Aug 11, 2025
f479c92
Update examples/structured_2d_dgsem/elixir_euler_convergence_implicit…
DanielDoehring Aug 11, 2025
8478589
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 11, 2025
aba1e36
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 12, 2025
25518ef
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Aug 14, 2025
6ea38f2
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 15, 2025
5153dab
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 19, 2025
f2f3780
correct comment
DanielDoehring Aug 19, 2025
613f01a
Merge branch 'elixir_implicit_sparse' of github.com:sbairos/Trixi.jl …
DanielDoehring Aug 19, 2025
1b241ae
simplify
DanielDoehring Aug 19, 2025
25b54b5
kwargs
DanielDoehring Aug 19, 2025
c026cf9
adapt
DanielDoehring Aug 19, 2025
0f3f00c
shorten
DanielDoehring Aug 19, 2025
9bc0f6c
Update examples/tree_2d_dgsem/elixir_advection_implicit_sparse_jacobi…
DanielDoehring Aug 19, 2025
cde1bff
fmt
DanielDoehring Aug 19, 2025
eb29838
simplify
DanielDoehring Aug 19, 2025
a72dce2
try different warning
DanielDoehring Aug 19, 2025
2c9eb34
warning
DanielDoehring Aug 19, 2025
d9e4b51
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 19, 2025
f99ac51
test
DanielDoehring Aug 19, 2025
5c5722f
Merge branch 'elixir_implicit_sparse' of github.com:sbairos/Trixi.jl …
DanielDoehring Aug 19, 2025
8542b3e
up
DanielDoehring Aug 19, 2025
43900a4
revert
DanielDoehring Aug 20, 2025
9d04c00
move comment
DanielDoehring Aug 20, 2025
03c6b7b
compat
DanielDoehring Aug 20, 2025
7824a97
v
DanielDoehring Aug 20, 2025
5357ec3
v
DanielDoehring Aug 20, 2025
a16419a
v
DanielDoehring Aug 20, 2025
a4f3af4
try plots
DanielDoehring Aug 20, 2025
6991c6e
v
DanielDoehring Aug 20, 2025
63a415e
Update test/Project.toml
DanielDoehring Aug 20, 2025
d21a0e2
module replace
DanielDoehring Aug 20, 2025
151bc57
Merge branch 'elixir_implicit_sparse' of github.com:sbairos/Trixi.jl …
DanielDoehring Aug 20, 2025
72ac79f
typo
DanielDoehring Aug 20, 2025
b04e814
Merge branch 'main' into elixir_implicit_sparse
DanielDoehring Aug 21, 2025
76754b5
error tol
DanielDoehring Aug 21, 2025
c815383
Merge branch 'elixir_implicit_sparse' of github.com:sbairos/Trixi.jl …
DanielDoehring Aug 21, 2025
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
4 changes: 4 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221"
Octavian = "6fd5a793-0b7e-452c-907f-f8bfe9c57db4"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
P4est = "7d669430-f675-4ae7-b43e-fab78ec5a902"
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Expand Down Expand Up @@ -59,12 +60,15 @@ Convex = "f65535da-76fb-5f13-bab9-19810c17039a"
ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

[extensions]
TrixiCUDAExt = "CUDA"
TrixiConvexECOSExt = ["Convex", "ECOS"]
TrixiMakieExt = "Makie"
TrixiNLsolveExt = "NLsolve"
TrixiSparseDiffToolsExt = ["SparseDiffTools", "Symbolics"]

[compat]
Accessors = "0.1.36"
Expand Down
78 changes: 78 additions & 0 deletions examples/tree_2d_dgsem/elixir_advection_sparse_jacobian.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Trixi
using OrdinaryDiffEq
using SparseDiffTools, Symbolics

using .TrixiSparseDiffToolsExt

###############################################################################
### semidiscretization of the linear advection equation ###

advection_velocities = (1.0, 1.1)
equations = LinearScalarAdvectionEquation2D(advection_velocities)

# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux
d = 3
# `RealT = Real` requires fewer overloads than the more explicit `RealT = Num`
# solver_real used for computing the Jacobian
solver_real = DGSEM(polydeg = d, surface_flux = flux_lax_friedrichs, RealT = Real)
# solver_float used for solving using the Jacobian
solver_float = DGSEM(polydeg = d, surface_flux = flux_lax_friedrichs)

coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y))
coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y))

# Create a uniformly refined mesh with periodic boundaries
RefinementLevel = 5
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level = RefinementLevel,
n_cells_max = 30_000) # set maximum capacity of tree data structure

# A semidiscretization collects data structures and functions for the spatial discretization
# semi_real used for computing the Jacobian
semi_real = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test,
solver_real)
# semi_float used for solving using the Jacobian
semi_float = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test,
solver_float)

# 2^RefinementLevel = 16 elements, (d+1) local polynomial coefficients per element
N = Int(2^RefinementLevel * (d+1)) #64
u0_ode = zeros(N*N)
du_ode = 80 * ones(N*N) # initialize with something
t0 = 0.0
tSpan = (t0, t0 + 10.0)

###############################################################################
### Compute the Jacobian with SparseDiffTools ###

# Create a function with two parameters:du_ode and u0_ode
# to fulfill the requirments of an in_place function in SparseDiffTools
rhs = (du_ode,u0_ode)->Trixi.rhs!(du_ode, u0_ode, semi_real, t0)

#From the example to detect the pattern and choose how to do the AutoDiff automatically
sd = SymbolicsSparsityDetection()
adtype = AutoSparseFiniteDiff()

#From the example provided in SparseDiffTools. cache will reduce calculation time when Jacobian will be calculated multiple times
sparse_cache = sparse_jacobian_cache(adtype, sd, rhs, du_ode, u0_ode)

###############################################################################
# callback functions during the time integration

ode = semidiscretize(semi_float, tSpan, sparse_cache.jac_prototype, sparse_cache.coloring.colorvec)

# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results
analysis_callback = AnalysisCallback(semi_float, interval = 100)

# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup
# and resets the timers
summary_callback = SummaryCallback()

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback)

###############################################################################
# Run the simulation using ImplicitEuler method

sol = solve(ode, ImplicitEuler(; autodiff = AutoFiniteDiff());
dt = 1.0, save_everystep = false, callback = callbacks);
43 changes: 43 additions & 0 deletions ext/TrixiSparseDiffToolsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Package extension for using SparseDiffTools with Trixi for implicit solvers
module TrixiSparseDiffToolsExt

using Trixi

import Base: *, zero, one # For overloading

###############################################################################
### Hacks ###

# Required for setting up the Lobatto Legendre basis for abstract `Real` type
function Trixi.eps(::Type{Real}, RealT = Float64)
return eps(RealT)
end

# There are several places in trixi where they do one(RealT) or zero(uEltype) where RealT or uEltype is Real
# this just returns an Int64 1 or 0 respectively. We don't want to use ints so we override this behavior
# Real(x::Real) = Float64(x)
Base.one(::Type{Real}) = 1.0
Base.zero(::Type{Real}) = 0.0

# Multiplying two Matrix{Real}s gives a Matrix{Any}.
# This causes problems when instantiating the Legendre basis.
# Called in `calc_{forward,reverse}_{upper, lower}`
function *(A::Matrix{Real}, B::Matrix{Real})::Matrix{Real}
m, n = size(A, 1), size(B, 2)
kA = size(A, 2)
kB = size(B, 1)
@assert kA == kB "Matrix dimensions must match for multiplication"

C = Matrix{Real}(undef, m, n)
for i in 1:m, j in 1:n
#acc::Real = zero(promote_type(typeof(A[i,1]), typeof(B[1,j])))
acc = zero(Real)
for k in 1:kA
acc += A[i,k] * B[k,j]
end
C[i,j] = acc
end
return C
end

end # module TrixiNLsolveExt
30 changes: 30 additions & 0 deletions src/semidiscretization/semidiscretization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,36 @@ function semidiscretize(semi::AbstractSemidiscretization, tspan;
return ODEProblem{iip, specialize}(rhs!, u0_ode, tspan, semi)
end

"""
semidiscretize(semi::AbstractSemidiscretization, tspan)

Wrap the semidiscretization `semi` as an ODE problem in the time interval `tspan`
that can be passed to `solve` from the [SciML ecosystem](https://diffeq.sciml.ai/latest/).

The arguments `jac_prototype` and `coloring` are SparseDiffTools.jl objects which will be used
to reduce repeating calculations as part of the ODE solve.
"""
function semidiscretize(semi::AbstractSemidiscretization, tspan, jac_prototype, coloring;
reset_threads = true)
# Optionally reset Polyester.jl threads. See
# https://github.com/trixi-framework/Trixi.jl/issues/1583
# https://github.com/JuliaSIMD/Polyester.jl/issues/30
if reset_threads
Polyester.reset_threads!()
end

u0_ode = compute_coefficients(first(tspan), semi)
# TODO: MPI, do we want to synchronize loading and print debug statements, e.g. using
# mpi_isparallel() && MPI.Barrier(mpi_comm())
# See https://github.com/trixi-framework/Trixi.jl/issues/328
iip = true # is-inplace, i.e., we modify a vector when calling rhs!
specialize = SciMLBase.FullSpecialize # specialize on rhs! and parameters (semi)
# See SparseDiffTools.jl docs for the typing of jac_prototype and colorvec
# https://github.com/JuliaDiff/SparseDiffTools.jl
ode = SciMLBase.ODEFunction(rhs!, jac_prototype=jac_prototype, colorvec=coloring)
return ODEProblem{iip, specialize}(ode, u0_ode, tspan, semi)
end

"""
semidiscretize(semi::AbstractSemidiscretization, tspan,
restart_file::AbstractString)
Expand Down