@@ -264,15 +264,25 @@ function get_node_variables!(node_variables, u_ode,
264264end
265265
266266"""
267- semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan)
267+ semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan;
268+ jac_prototype_parabolic::Union{AbstractMatrix, Nothing} = nothing,
269+ colorvec_parabolic::Union{AbstractVector, Nothing} = nothing)
268270
269271Wrap the semidiscretization `semi` as a split ODE problem in the time interval `tspan`
270272that can be passed to `solve` from the [SciML ecosystem](https://diffeq.sciml.ai/latest/).
271273The parabolic right-hand side is the first function of the split ODE problem and
272274will be used by default by the implicit part of IMEX methods from the
273275SciML ecosystem.
276+
277+ Optional keyword arguments:
278+ - `jac_prototype_parabolic`: Expected to come from [SparseConnectivityTracer.jl](https://github.com/adrhill/SparseConnectivityTracer.jl).
279+ Specifies the sparsity structure of the parabolic function's Jacobian to enable e.g. efficient implicit time stepping.
280+ - `colorvec_parabolic`: Expected to come from [SparseMatrixColorings.jl](https://github.com/gdalle/SparseMatrixColorings.jl).
281+ Allows for even faster Jacobian computation. Not necessarily required when `jac_prototype_parabolic` is given.
274282"""
275283function semidiscretize (semi:: SemidiscretizationHyperbolicParabolic , tspan;
284+ jac_prototype_parabolic:: Union{AbstractMatrix, Nothing} = nothing ,
285+ colorvec_parabolic:: Union{AbstractVector, Nothing} = nothing ,
276286 reset_threads = true )
277287 # Optionally reset Polyester.jl threads. See
278288 # https://github.com/trixi-framework/Trixi.jl/issues/1583
@@ -286,15 +296,36 @@ function semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan;
286296 # mpi_isparallel() && MPI.Barrier(mpi_comm())
287297 # See https://github.com/trixi-framework/Trixi.jl/issues/328
288298 iip = true # is-inplace, i.e., we modify a vector when calling rhs_parabolic!, rhs!
289- # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
290- # first function implicitly and the second one explicitly. Thus, we pass the
291- # stiffer parabolic function first.
292- return SplitODEProblem {iip} (rhs_parabolic!, rhs!, u0_ode, tspan, semi)
299+
300+ # Check if Jacobian prototype is provided for sparse Jacobian
301+ if jac_prototype_parabolic != = nothing
302+ # Convert `jac_prototype_parabolic` to real type, as seen here:
303+ # https://docs.sciml.ai/DiffEqDocs/stable/tutorials/advanced_ode_example/#Declaring-a-Sparse-Jacobian-with-Automatic-Sparsity-Detection
304+ parabolic_ode = SciMLBase. ODEFunction (rhs_parabolic!,
305+ jac_prototype = convert .(eltype (u0_ode),
306+ jac_prototype_parabolic),
307+ colorvec = colorvec_parabolic) # coloring vector is optional
308+
309+ # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
310+ # first function implicitly and the second one explicitly. Thus, we pass the
311+ # stiffer parabolic function first.
312+ return SplitODEProblem {iip} (parabolic_ode, rhs!, u0_ode, tspan, semi)
313+ else
314+ # We could also construct an `ODEFunction` without the Jacobian here,
315+ # but we stick to the more light-weight direct in-place function `rhs_parabolic!`.
316+
317+ # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
318+ # first function implicitly and the second one explicitly. Thus, we pass the
319+ # stiffer parabolic function first.
320+ return SplitODEProblem {iip} (rhs_parabolic!, rhs!, u0_ode, tspan, semi)
321+ end
293322end
294323
295324"""
296325 semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan,
297- restart_file::AbstractString)
326+ restart_file::AbstractString;
327+ jac_prototype_parabolic::Union{AbstractMatrix, Nothing} = nothing,
328+ colorvec_parabolic::Union{AbstractVector, Nothing} = nothing)
298329
299330Wrap the semidiscretization `semi` as a split ODE problem in the time interval `tspan`
300331that can be passed to `solve` from the [SciML ecosystem](https://diffeq.sciml.ai/latest/).
@@ -303,9 +334,17 @@ will be used by default by the implicit part of IMEX methods from the
303334SciML ecosystem.
304335
305336The initial condition etc. is taken from the `restart_file`.
337+
338+ Optional keyword arguments:
339+ - `jac_prototype_parabolic`: Expected to come from [SparseConnectivityTracer.jl](https://github.com/adrhill/SparseConnectivityTracer.jl).
340+ Specifies the sparsity structure of the parabolic function's Jacobian to enable e.g. efficient implicit time stepping.
341+ - `colorvec_parabolic`: Expected to come from [SparseMatrixColorings.jl](https://github.com/gdalle/SparseMatrixColorings.jl).
342+ Allows for even faster Jacobian computation. Not necessarily required when `jac_prototype_parabolic` is given.
306343"""
307344function semidiscretize (semi:: SemidiscretizationHyperbolicParabolic , tspan,
308345 restart_file:: AbstractString ;
346+ jac_prototype_parabolic:: Union{AbstractMatrix, Nothing} = nothing ,
347+ colorvec_parabolic:: Union{AbstractVector, Nothing} = nothing ,
309348 reset_threads = true )
310349 # Optionally reset Polyester.jl threads. See
311350 # https://github.com/trixi-framework/Trixi.jl/issues/1583
@@ -319,10 +358,29 @@ function semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan,
319358 # mpi_isparallel() && MPI.Barrier(mpi_comm())
320359 # See https://github.com/trixi-framework/Trixi.jl/issues/328
321360 iip = true # is-inplace, i.e., we modify a vector when calling rhs_parabolic!, rhs!
322- # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
323- # first function implicitly and the second one explicitly. Thus, we pass the
324- # stiffer parabolic function first.
325- return SplitODEProblem {iip} (rhs_parabolic!, rhs!, u0_ode, tspan, semi)
361+
362+ # Check if Jacobian prototype is provided for sparse Jacobian
363+ if jac_prototype_parabolic != = nothing
364+ # Convert `jac_prototype_parabolic` to real type, as seen here:
365+ # https://docs.sciml.ai/DiffEqDocs/stable/tutorials/advanced_ode_example/#Declaring-a-Sparse-Jacobian-with-Automatic-Sparsity-Detection
366+ parabolic_ode = SciMLBase. ODEFunction (rhs_parabolic!,
367+ jac_prototype = convert .(eltype (u0_ode),
368+ jac_prototype_parabolic),
369+ colorvec = colorvec_parabolic) # coloring vector is optional
370+
371+ # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
372+ # first function implicitly and the second one explicitly. Thus, we pass the
373+ # stiffer parabolic function first.
374+ return SplitODEProblem {iip} (parabolic_ode, rhs!, u0_ode, tspan, semi)
375+ else
376+ # We could also construct an `ODEFunction` without the Jacobian here,
377+ # but we stick to the more light-weight direct in-place function `rhs_parabolic!`.
378+
379+ # Note that the IMEX time integration methods of OrdinaryDiffEq.jl treat the
380+ # first function implicitly and the second one explicitly. Thus, we pass the
381+ # stiffer parabolic function first.
382+ return SplitODEProblem {iip} (rhs_parabolic!, rhs!, u0_ode, tspan, semi)
383+ end
326384end
327385
328386function rhs! (du_ode, u_ode, semi:: SemidiscretizationHyperbolicParabolic , t)
0 commit comments