The TrixiEnzyme Module
TrixiEnzyme — ModuleTrixiEnzymeTrixiEnzyme.jl is a component package of the Trixi.jl ecosystem and integrates Trixi.jl with Compiler-Based (LLVM level) automatic differentiation via Enzyme.jl for hyperbolic partial differential equations (PDEs). The integration of Trixi.jl with Compiler-Based (LLVM level) automatic differentiation via Enzyme.jl offers the following benefits: facilitates rapid forward mode AD, enables reverse mode AD, supports cross-language AD, and critically, supports mutating operations and caching, on which Trixi.jl relies, to enhance the performance of both simulation runs and AD. The final deliverable will include as many of Trixi's advanced features as possible, such as adaptive mesh refinement, shock capturing, etc., showcasing the benefits of differentiable programming in Julia's ecosystem.
Module Index
TrixiEnzyme.enzyme_rhs!TrixiEnzyme.jacobian_enzyme_forwardTrixiEnzyme.jacobian_enzyme_forward_closureTrixiEnzyme.jacobian_enzyme_reverseTrixiEnzyme.jacobian_enzyme_reverse_closureTrixiEnzyme.pick_batchsizeTrixiEnzyme.upwind!
Detailed API
TrixiEnzyme.enzyme_rhs! — Methodenzyme_rhs!(du_ode::AbstractVector, u_ode::AbstractVector, mesh, equations, initial_condition, boundary_conditions, source_terms, solver, boundaries, _node_coordinates, cell_ids, node_coordinates, inverse_jacobian, _neighbor_ids, neighbor_ids, orientation, surface_flux_values, u)The best thing to do for a user would be to separate out the things that you need to track through, make them arguments to the function, and then simply Duplicate on those.
TrixiEnzyme.jacobian_enzyme_forward — Functionjacobian_enzyme_forward(semi::SemidiscretizationHyperbolic; N = pick_batchsize(semi))Uses the right-hand side operator of the semidiscretization semi and forward mode automatic differentiation to compute the Jacobian J of the semidiscretization semi at state u0_ode.
Notes
Both jacobian_enzyme_forward(semi) and jacobian_enzyme_reverse(semi) depend on enzyme_rhs!.
jacobian_enzyme_forward(f!::F, x::AbstractArray; N = pick_batchsize(x)) where F <: FunctionUses the function f! and forward mode automatic differentiation to compute the Jacobian J
Examples
julia> x = -1:0.5:1;
julia> batch_size = 2;
julia> jacobian_enzyme_forward(TrixiEnzyme.upwind!, x, N=batch_size)
5×5 Matrix{Float64}:
-0.2 -0.0 -0.0 -0.0 0.2
0.2 -0.2 -0.0 -0.0 -0.0
-0.0 0.2 -0.2 -0.0 -0.0
-0.0 -0.0 0.2 -0.2 -0.0
-0.0 -0.0 -0.0 0.2 -0.2TrixiEnzyme.jacobian_enzyme_forward_closure — Methodjacobian_enzyme_forward_closure(semi::SemidiscretizationHyperbolic; N = pick_batchsize(semi))Same as jacobian_enzyme_forward but with closure
Notes
I resolved issues related to type instability caused by closures, which is a known limitation of Enzyme.
I utilized closures here because they simplify the reuse of memory buffers and temporary variables without the need for explicit storage. let blocks create a new hard scope and optionally introduce new local bindings.
TrixiEnzyme.jacobian_enzyme_reverse — Methodjacobian_enzyme_reverse(semi::SemidiscretizationHyperbolic)The jacobianenzymereverse reuses containers for shadow variables. This might provide beginners with a clear view of how Enzyme works in detail.
Enzyme.jl does not play well with Polyester.jl and there are no plans to fix this soon.
TrixiEnzyme.jacobian_enzyme_reverse_closure — Methodjacobian_enzyme_reverse_closure(semi::SemidiscretizationHyperbolic)Same as jacobian_enzyme_reverse but with closure
Enzyme.jl does not play well with Polyester.jl and there are no plans to fix this soon.
TrixiEnzyme.pick_batchsize — Functionpick_batchsize(x)
pick_batchsize(semi)Return a reasonable batch size for batched differentiation.
Arguments
x: AbstractArraysemi: SemidiscretizationHyperbolic in Trixi.jl
Notes
Inspired by https://github.com/EnzymeAD/Enzyme.jl/pull/1545/files
This function is experimental, and not part of the public API.
Examples
julia> pick_batchsize(rand(3))
3
julia> pick_batchsize(rand(20))
11TrixiEnzyme.upwind! — Methodupwind!(du, u, cache)Vanilla upwind scheme