Catalyst.jl icon indicating copy to clipboard operation
Catalyst.jl copied to clipboard

Explicitly mark variable-rate reactions

Open kaandocal opened this issue 1 year ago • 8 comments

I'm currently implementing a model where some species evolve according to ODEs and some according to the SSA. This causes some reactions to have variable rates (due to the ODEs), even if their rate only depends on other species, not on t . Currently Catalyst does not recognise this in assemble_jumps, leading to wrong simulations. It would be nice if we could mark certain species as time-variable to ensure that Catalyst treats them as such.

For now a simple solution is to create a variable-rate dummy reaction of the form t < 0, 0 --> X, but this is not ideal.

(A tutorial or example code on such models might be a good addition to the documentation, my implementation is very haphazard. I can share some of my code later to see if that could make its way in)

kaandocal avatar Aug 28 '24 04:08 kaandocal

Can you give a MWE. Are your ODEs written for @variables or @species in your code?

isaacsas avatar Aug 28 '24 10:08 isaacsas

You should be hitting this error as what you are trying is not officially supported yet: https://github.com/SciML/Catalyst.jl/blob/3bd4ea57eb31b5896120454898530b71fad16bb6/src/reactionsystem_conversions.jl#L321

isaacsas avatar Aug 28 '24 10:08 isaacsas

As a note, this is one of the things that would need to be updated once this is allowed: https://github.com/SciML/Catalyst.jl/blob/3bd4ea57eb31b5896120454898530b71fad16bb6/src/reactionsystem_conversions.jl#L336

isaacsas avatar Aug 28 '24 10:08 isaacsas

More generally, your comment and other recent ones seem to suggest that it is time with V14 finally out to start seriously working on hybrid model support.

isaacsas avatar Aug 28 '24 10:08 isaacsas

Everyone is asking for it 😅. The codes are basically ready. Just need to find a bit of time.

ChrisRackauckas avatar Aug 28 '24 11:08 ChrisRackauckas

It should be straightforward for a static model version as a first step, but we need to add MTK system support for it too. A simple callback-based dynamic version that uses a bit mask to indicate where a reaction currently lives should then be a straightforward follow up.

isaacsas avatar Aug 28 '24 11:08 isaacsas

My example code is below. It's a bit messy as I cannot use Coevolve :

using Catalyst
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D

using JumpProcesses
using OrdinaryDiffEq

rn = @reaction_network begin
    @species A(t)
    A, 0 --> X
    t < 0, 0 --> A
end

osys = complete(ODESystem([ D(rn.A) ~ 1, D(rn.X) ~ 0 ], Catalyst.get_iv(rn), Catalyst.unknowns(rn), Catalyst.parameters(rn); name=:osys))

jsys = complete(convert(JumpSystem, rn))

oprob = ODEProblem(osys, [ rn.X => 0, rn.A => 0 ], (0, 10.))  # using symbolic parameter assignments causes an error in `varmap_to_vars`

jinp = JumpInputs(jsys, oprob)
jprob = JumpProblem(jinp, Direct())

solve(jprob, Midpoint())

The output is:

retcode: Success
Interpolation: 3rd order Hermite
t: 7-element Vector{Float64}:
  0.0
  9.999999999999999e-5
  0.0010999999999999998
  0.011099999999999997
  0.11109999999999996
  1.1110999999999995
 10.0
u: 7-element Vector{Vector{Float64}}:
 [0.0, 0.0]
 [9.999999999999999e-5, 0.0]
 [0.0010999999999999998, 0.0]
 [0.011099999999999997, 0.0]
 [0.11109999999999996, 0.0]
 [1.1110999999999995, 0.0]
 [10.0, 0.0]

Note that X stays at 0. Upon inspection, we find that jprob.variable_jumps is empty. I'm not sure about the details, but the reaction is treated as a jump with discrete aggregation. Adding the dummy reaction t < 0, 0 --> A fixes this (jprob now contains two variable jumps/with continuous aggregation).

NB: I'm using @species as @variables gives the following error:

ERROR: Conversion to JumpSystem currently requires all unknowns to be species.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] assemble_jumps(rs::ReactionSystem{Catalyst.NetworkProperties{…}}; combinatoric_ratelaws::Bool)
   @ Catalyst ~/.julia/packages/Catalyst/3S7C4/src/reactionsystem_conversions.jl:321
 [3] convert(::Type{…}, rs::ReactionSystem{…}; name::Symbol, combinatoric_ratelaws::Bool, remove_conserved::Nothing, checks::Bool, default_u0::Dict{…}, default_p::Dict{…}, defaults::Dict{…}, kwargs::@Kwargs{})
   @ Catalyst ~/.julia/packages/Catalyst/3S7C4/src/reactionsystem_conversions.jl:689
 [4] convert(::Type{JumpSystem}, rs::ReactionSystem{Catalyst.NetworkProperties{Int64, SymbolicUtils.BasicSymbolic{Real}}})
   @ Catalyst ~/.julia/packages/Catalyst/3S7C4/src/reactionsystem_conversions.jl:672

kaandocal avatar Aug 29 '24 03:08 kaandocal

@kaandocal you might want to update to the latest JumpProcesses as I found a bug with reinitializing the initial condition when calling solve many times in a loop.

isaacsas avatar Sep 02 '24 17:09 isaacsas

https://github.com/SciML/ModelingToolkit.jl/pull/3181 should enable support for such models in MTK, and then we can add an interface here.

isaacsas avatar Nov 04 '24 22:11 isaacsas

https://github.com/SciML/ModelingToolkit.jl/pull/3181 should add this to MTK, and https://github.com/SciML/Catalyst.jl/issues/1112 is where we will discuss the interface. This should, if setup correctly, be handled automatically, but may require some modification to the current code to classify reactions.

isaacsas avatar Nov 11 '24 17:11 isaacsas

Closing as we will handle/discuss this in the new issue I linked.

isaacsas avatar Nov 11 '24 17:11 isaacsas