MethodOfLines: How can I compute the Jacobian of the system of ODEs?

How can I compute the Jacobian of the system of ODEs obtained by spatially discretising a linear advection equation? A MWE follows:

using OrdinaryDiffEq, ModelingToolkit, MethodOfLines, DomainSets

@independent_variables t x
@variables T(..)
Dₜ = Differential(t)
Dₓ = Differential(x)

eq  = Dₜ(T(t, x)) ~ -Dₓ(T(t, x))

T₀ = 10.0
bcs = [T(0, x) ~ T₀,
       T(t, 0) ~ T₀+exp(-((t-1.0)^2)/0.1)]

domains = [t ∈ Interval(0.0, 1.0),
           x ∈ Interval(0.0, 2.0)]

@named pdesys = PDESystem(eq, bcs, domains, [t, x], [T(t, x)])

Δx = 0.1
discretization = MOLFiniteDifference([x => Δx], t, advection_scheme = UpwindScheme())

prob = discretize(pdesys,discretization)

How do I get the Jacobian matrix from the prob variable, which is of type ODEProblem?

An identical question has been asked and answered some two years ago: MethodOfLines.jl: Obtain Jacobian of MOL semi-discretization. The advise given by @ChrisRackauckas there was “During discretize if you pass jac=true then it will generate it, and sys.jac or prob.f.jac are these pieces.” But when I try

prob = discretize(pdesys,discretization,jac=true)

Julia seems to never stop computing. I confess that after some fifteen minutes I had to kill it. The more so that I cannot find such option anywhere in the docs. In fact, I cannot find any docs for the discretize function at all.

Combined with the fact that the advice is now some two years old (maybe it is now deprecated?), that is also why I decided not to “necropost” but rather write a new post.

Haven’t tried this in a while, but if I recall correctly, slow computation of the symbolic expressions involved in MethodOfLines.jl is a known problem. It should mostly matter for large expressions – it looks like you only have ~20 grid points though :thinking: but Jacobians probably take a lot longer than the right-hand-side functions themselves.

The Performance Tips mention JuliaSimCompiler.jl as an alternative which is supposedly faster. Haven’t tried it yet though.

As you point out, 20 grid points is not too many. I have even reduced it to 5. No change. After the discretize() command, Julia seems to keep evaluating forever.

Are you bound to MethodOfLines.jl ? If not, check out Trixi.jl which supports quick computation via ForwardDiff.jl (of an albeit dense) Jacobian

1 Like

Note that this is changing a lot in the next month. I wasn’t going to answer until the changes are done, but it seems like they will take too long to just wait :sweat_smile: . SymbolicUtils v4 is making Symbolics fully type-stable under the hood, and then we are changing to allow for a good array-based code gen (that’s the end of October goal). Once that is done we will need to update MethodOfLines to hit the array codegen correctly, and then it should have O(1) codegen. Then we really need implement array calculus… otherwise for this exact thing we will need to scalarize. That doesn’t really have a timeline… but anyways that’s how all of this is evolving. So yes the current form is slow because it does it fully on scalars but we have most of the infra to change that now.

But if you do let the jac=true keep running it should finish and give the right result still.

1 Like

That sounds great! Thanks for the update @ChrisRackauckas

Out of curiosity: Is there any way how I could contribute to this change? Or would it just slow down the process to coordinate with someone new? I’d be very interested in seeing these changes happen for my own research, but at the moment I don’t know where it would make sense for me to look into.

SymbolicUtils v4 should merge today: feat: V4 by AayushSabharwal · Pull Request #794 · JuliaSymbolics/SymbolicUtils.jl · GitHub

But we could use some help with the downstream. All of the Vector{Any} in MTK/Symbolics should now be concretely BasicSymbolic. Then the MethodOfLines change is a bigger one. If you’re up for that, then we can help you figure it out. It just should create @arrayop expressions.

Thanks! I will try to understand what exactly changed in v4 from the issue and PR, and how to propagate that to MTK and Symbolics like you suggested. Let’s see how that goes :sweat_smile: