Skip to content

Commit c9d98cc

Browse files
committed
save progress
1 parent 0cf2781 commit c9d98cc

File tree

8 files changed

+97
-131
lines changed

8 files changed

+97
-131
lines changed

docs/src/api/catalyst_api.md

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,6 @@ species
157157
nonspecies
158158
reactionparams
159159
reactions
160-
is_reaction
161-
is_alg_equation
162-
is_diff_equation
163-
alg_equations
164-
diff_equations
165-
has_alg_equations
166-
has_diff_equations
167-
get_alg_eqs
168-
get_diff_eqs
169-
has_alg_eqs
170-
has_diff_eqs
171160
numspecies
172161
numparams
173162
numreactions

src/Catalyst.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ import ModelingToolkit: check_variables,
3737
check_parameters, _iszero, _merge, check_units,
3838
get_unit, check_equations, iscomplete
3939

40+
# Event-related MTK stuff.
41+
import ModelingToolkit: PresetTimeCallback
42+
4043
import Base: (==), hash, size, getindex, setindex, isless, Sort.defalg, length, show
4144
import MacroTools, Graphs
4245
import Graphs: DiGraph, SimpleGraph, SimpleDiGraph, vertices, edges, add_vertices!, nv, ne
4346
import DataStructures: OrderedDict, OrderedSet
4447
import Parameters: @with_kw_noshow
48+
import Symbolics: occursin, wrap
4549

4650
# globals for the modulate
4751
function default_time_deriv()
@@ -88,7 +92,6 @@ export mm, mmr, hill, hillr, hillar
8892
# functions to query network properties
8993
include("networkapi.jl")
9094
export species, nonspecies, reactionparams, reactions, speciesmap, paramsmap
91-
export has_diff_equations, diff_equations, has_alg_equations, alg_equations
9295
export numspecies, numreactions, numreactionparams, setdefaults!, symmap_to_varmap
9396
export make_empty_network, addspecies!, addparam!, addreaction!, reactionparamsmap
9497
export dependants, dependents, substoichmat, prodstoichmat, netstoichmat

src/networkapi.jl

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -586,93 +586,6 @@ symmap_to_varmap(sys, symmap) = symmap
586586
#error("symmap_to_varmap requires a Dict, AbstractArray or Tuple to map Symbols to values.")
587587

588588

589-
### Equation Handling Accessors ###
590-
591-
"""
592-
is_reaction(eq::Equation)
593-
594-
Returns `true` if the input is a `Reaction`, else false.
595-
"""
596-
function is_reaction(eq::Equation)
597-
return eq isa Reaction
598-
end
599-
600-
"""
601-
is_alg_equation(eq::Equation)
602-
603-
Returns `true` if the input is an algebraic equation that does not contain any differentials.
604-
"""
605-
function is_alg_equation(eq)
606-
return isdefined(eq, :lhs) && isdefined(eq, :rhs) && !is_diff_equation(eq)
607-
end
608-
609-
"""
610-
is_diff_equation(eq::Equation)
611-
612-
Returns `true` if the input is an that contains at least one differential.
613-
"""
614-
function is_diff_equation(eq)
615-
isdefined(eq, :lhs) && occursin(is_derivative, wrap(eq.lhs)) && (return true)
616-
isdefined(eq, :rhs) && occursin(is_derivative, wrap(eq.rhs)) && (return true)
617-
return false
618-
end
619-
620-
"""
621-
alg_equations(rs)
622-
623-
Returns all the algebraic equations (that does not contain differnetials) in `rs` and its subsystems.
624-
"""
625-
alg_equations(rs) = filter(is_alg_equation, equations(rs))
626-
627-
"""
628-
diff_equations(rs)
629-
630-
Returns all the differnetials equations (equations that contain differnetials) in `rs` and its subsystems.
631-
"""
632-
diff_equations(rs) = filter(is_diff_equation, equations(rs))
633-
634-
"""
635-
has_alg_equations(rs)
636-
637-
Returns true if `rs` (or any of its subsystems) has an algebraic equation (that does not contain a differential).
638-
"""
639-
has_alg_equations(rs) = any(is_alg_equation, equations(rs))
640-
641-
"""
642-
has_diff_equations(rs)
643-
644-
Returns true if `rs` (or any of its subsystems) has a differnetials equations (equations that contain differnetials) .
645-
"""
646-
has_diff_equations(rs) = any(is_diff_equation, equations(rs))
647-
648-
"""
649-
get_alg_eqs(rs)
650-
651-
Returns all the algebraic equations (that does not contain differnetials) in `rs` and (but not its subsystems).
652-
"""
653-
get_alg_eqs(rs) = filter(is_alg_equation, get_eqs(rs))
654-
655-
"""
656-
diff_equations(rs)
657-
658-
Returns all the differnetial equations (equations that contain differnetials) in `rs` (but not its subsystems).
659-
"""
660-
get_diff_eqs(rs) = filter(is_diff_equation, get_eqs(rs))
661-
662-
"""
663-
has_alg_equations(rs)
664-
665-
Returns true if `rs` has an algebraic equation (that does not contain a differential). Does not consider subsystems.
666-
"""
667-
has_alg_eqs(rs) = any(is_alg_equation, get_eqs(rs))
668-
669-
"""
670-
has_diff_equations(rs)
671-
672-
Returns true if `rs` has a differnetial equations (equations that contain differnetials). Does not consider subsystems.
673-
"""
674-
has_diff_eqs(rs) = any(is_diff_equation, get_eqs(rs))
675-
676589
######################## reaction complexes and reaction rates ###############################
677590

678591
"""

src/reaction_network.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,13 +879,13 @@ function read_events_option(options, event_type::Symbol)
879879
for arg in events_input.args
880880
# Formatting error checks.
881881
# NOTE: Maybe we should move these deeper into the system (rather than the DSL), throwing errors more generally?
882-
if (arg.head != :call) || (arg.args[1] != :(=>)) || length(arg.args) != 3
882+
if (arg isa Expr) && (arg.head != :call) || (arg.args[1] != :(=>)) || length(arg.args) != 3
883883
error("Events should be on form `condition => affect`, separated by a `=>`. This appears not to be the case for: $(arg).")
884884
end
885-
if (arg.args[2] != :call) && (event_type == :continuous_events)
885+
if (arg isa Expr) && (arg.args[2] isa Expr) && (arg.args[2].head != :vect) && (event_type == :continuous_events)
886886
error("The condition part of continious events (the left-hand side) must be a vector. This is not the case for: $(arg).")
887887
end
888-
if arg.args[3] != :call
888+
if (arg isa Expr) && (arg.args[3] isa Expr) && (arg.args[3].head != :vect)
889889
error("The affect part of all events (the righ-hand side) must be a vector. This is not the case for: $(arg).")
890890
end
891891

src/reactionsystem.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,12 @@ function isbcbalanced(rx::Reaction)
309309
true
310310
end
311311

312+
### Reaction Acessor Functions ###
313+
314+
# Overwrites functions in ModelingToolkit to give the correct input.
315+
is_diff_equation(rx::Reaction) = false
316+
is_alg_equation(rx::Reaction) = false
317+
312318
################################## Reaction Complexes ####################################
313319

314320
"""
@@ -1678,13 +1684,14 @@ function DiffEqBase.ODEProblem(rs::ReactionSystem, u0, tspan,
16781684
pmap = symmap_to_varmap(rs, p)
16791685
osys = convert(ODESystem, rs; name, combinatoric_ratelaws, include_zero_odes, checks,
16801686
remove_conserved)
1681-
osys = complete(osys)
16821687

16831688
# Handles potential Differential algebraic equations.
16841689
if structural_simplify
16851690
(osys = MT.structural_simplify(osys))
1686-
# elseif has_alg_equations(rs)
1687-
# error("The input ReactionSystem has algebraic equations. This requires setting `structural_simplify=true` within `ODEProblem` call.")
1691+
elseif has_alg_equations(rs)
1692+
error("The input ReactionSystem has algebraic equations. This requires setting `structural_simplify=true` within `ODEProblem` call.")
1693+
else
1694+
osys = complete(osys)
16881695
end
16891696

16901697
return ODEProblem(osys, u0map, tspan, pmap, args...; check_length, kwargs...)

test/dsl/dsl_options.jl

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
### Prepares Tests ###
44

55
# Fetch packages.
6-
using Catalyst, ModelingToolkit, OrdinaryDiffEq, Plots, Test
6+
using Catalyst, ModelingToolkit, OrdinaryDiffEq, StochasticDiffEq, Plots, Test
77
using Symbolics: unwrap
88

9+
# Sets stable rng number.
10+
using StableRNGs
11+
rng = StableRNG(12345)
12+
seed = rand(rng, 1:100)
13+
914
# Sets the default `t` to use.
1015
t = default_t()
1116

@@ -770,7 +775,7 @@ end
770775

771776
# Checks hierarchical model.
772777
let
773-
base_rn = @reaction_network begin
778+
base_rn = @network_component begin
774779
@variables V1(t)
775780
@equations begin
776781
X*3V1 ~ X - 2
@@ -779,15 +784,15 @@ let
779784
end
780785
@unpack X, V1, p, d = base_rn
781786

782-
internal_rn = @reaction_network begin
787+
internal_rn = @network_component begin
783788
@variables V2(t)
784789
@equations begin
785790
X*4V2 ~ X - 3
786791
end
787792
(p,d), 0 <--> X
788793
end
789794

790-
rn = compose(base_rn, [internal_rn])
795+
rn = complete(compose(base_rn, [internal_rn]))
791796

792797
u0 = [V1 => 1.0, X => 3.0, internal_rn.V2 => 2.0, internal_rn.X => 4.0]
793798
ps = [p => 1.0, d => 0.2, internal_rn.p => 2.0, internal_rn.d => 0.5]
@@ -877,7 +882,7 @@ let
877882
@discrete_events begin
878883
2.0 => [dX ~ dX + 0.1, dY ~ dY + dY_up]
879884
[1.0, 5.0] => [p ~ p - 0.1]
880-
[Z > Y, Z > X] => [Z ~ Z - 0.1]
885+
(Z > Y) => [Z ~ Z - 0.1]
881886
end
882887

883888
(p, dX), 0 <--> X
@@ -901,9 +906,9 @@ let
901906
discrete_events = [
902907
2.0 => [dX ~ dX + 0.1, dY ~ dY + dY_up]
903908
[1.0, 5.0] => [p ~ p - 0.1]
904-
[Z > Y, Z > X] => [Z ~ Z - 0.1]
909+
(Z > Y) => [Z ~ Z - 0.1]
905910
]
906-
rn_prog = ReactionSystem([rx1, rx2, eq], t; continuous_events, discrete_events, name=:rn)
911+
rn_prog = ReactionSystem(rxs, t; continuous_events, discrete_events, name=:rn)
907912

908913
# Tests that approaches yield identical results.
909914
@test isequal(rn_dsl, rn_prog)
@@ -929,19 +934,19 @@ let
929934
[5.0, 10.0] => [X ~ X + 100.0]
930935
end
931936
@continuous_events begin
932-
[X - 90.0] => [X ~ X + 10.0]
937+
[X ~ 90.0] => [X ~ X + 10.0]
933938
end
934939
(p, d), 0 <--> X
935940
end
936-
cb_disc = PresetTimeCallback([5.0, 10.0], int -> (int[:X] += 100.0))
941+
cb_disc = ModelingToolkit.PresetTimeCallback([5.0, 10.0], int -> (int[:X] += 100.0))
937942
cb_cont = ContinuousCallback((u, t, int) -> (u[1] - 90.0), int -> (int[:X] += 10.0))
938943

939-
# Simulates models,.
944+
# Simulates models.
940945
u0 = [:X => 100.0]
941946
tspan = (0.0, 50.0)
942947
ps = [:p => 100.0, :d => 1.0]
943-
sol = solve(SDEProblem(rn, u0, tspan, ps), ImplicitEM(); seed = 1234, callback = CallbackSet(cb_disc, cb_cont))
944-
sol_events = solve(SDEProblem(rn_events, u0, tspan, ps), ImplicitEM(); seed = 1234)
948+
sol = solve(SDEProblem(rn, u0, tspan, ps), ImplicitEM(); seed, callback = CallbackSet(cb_disc, cb_cont))
949+
sol_events = solve(SDEProblem(rn_events, u0, tspan, ps), ImplicitEM(); seed)
945950

946951
@test sol == sol_events
947952
end

test/miscellaneous_tests/events.jl

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,90 @@ D = default_time_deriv()
1111

1212
# Test discrete event is propagated to ODE solver correctly.
1313
let
14-
# Creates model.
14+
# Creates model (essentially a jagged oscillation, where `V` is reset to 1.0 every `1.0` time units).
1515
@variables V(t)=1.0
1616
eqs = [D(V) ~ V]
1717
discrete_events = [1.0 => [V ~ 1.0]]
18-
rxs = [(@reaction $V, 0 --> A), (@reaction 1.0, A --> 0)]
18+
rxs = [
19+
@reaction $V, 0 --> A
20+
@reaction 1.0, A --> 0
21+
]
1922
@named rs = ReactionSystem([rxs; eqs], t; discrete_events)
20-
rs = complete(rs)
21-
@test length(ModelingToolkit.discrete_events(rs)) == 1
2223
@test length(ModelingToolkit.continuous_events(rs)) == 0
24+
@test length(ModelingToolkit.discrete_events(rs)) == 1
2325

2426
# Tests in simulation.
25-
setdefaults!(rs, [:A => 0.0])
26-
osys = complete(convert(ODESystem, rs))
27+
osys = complete(convert(ODESystem, complete(rs)))
28+
@test length(ModelingToolkit.continuous_events(osys)) == 0
2729
@test length(ModelingToolkit.discrete_events(osys)) == 1
28-
oprob = ODEProblem(osys, [], (0.0, 20.0))
30+
oprob = ODEProblem(osys, [osys.A => 0.0], (0.0, 20.0))
2931
sol = solve(oprob, Tsit5())
30-
@test sol(10 + 10 * eps(), idxs = V) 1.0
32+
@test sol(10 + 10*eps(), idxs = V) 1.0
3133
end
3234

3335
# Test continuous event is propagated to the ODE solver.
3436
let
35-
# Creates model.
37+
# Creates model (a production/degradation system, but both reactions stop at `t=2.5`).
3638
@parameters α=5.0 β=1.0
37-
@species V(t) = 0.0
38-
rxs = [Reaction(α, nothing, [V]), Reaction(β, [V], nothing)]
39+
@species V(t)=0.0
40+
rxs = [
41+
Reaction(α, nothing, [V]),
42+
Reaction(β, [V], nothing)
43+
]
3944
continuous_events = [V ~ 2.5] =>~ 0, β ~ 0]
4045
@named rs = ReactionSystem(rxs, t; continuous_events)
41-
rs = complete(rs)
42-
@test length(ModelingToolkit.discrete_events(rs)) == 0
4346
@test length(ModelingToolkit.continuous_events(rs)) == 1
47+
@test length(ModelingToolkit.discrete_events(rs)) == 0
4448

4549
# Tests in simulation.
46-
osys = convert(ODESystem, rs)
50+
osys = complete(convert(ODESystem, complete(rs)))
4751
@test length(ModelingToolkit.continuous_events(osys)) == 1
52+
@test length(ModelingToolkit.discrete_events(osys)) == 0
4853
oprob = ODEProblem(rs, [], (0.0, 20.0))
4954
sol = solve(oprob, Tsit5())
5055
@test sol(20.0, idxs = V) 2.5
5156
end
57+
58+
let
59+
# Creates model.
60+
@parameters p d α = 1.0
61+
@species X(t) A(t) = 2
62+
@variables a(t) = 3
63+
rxs = [
64+
Reaction(p, nothing, [X]),
65+
Reaction(d, [X], nothing)
66+
]
67+
continuous_events = [(a == t) => A ~ A + α]
68+
discrete_events = [2.0 => A ~ α + a]
69+
@named rs_ce = ReactionSystem(rxs, t; continuous_events)
70+
@named rs_de = ReactionSystem(rxs, t; discrete_events)
71+
continuous_events = [(a == t) => A ~ A + a]
72+
discrete_events = [2.0 => A ~ α + a]
73+
@named rs_ce_de = ReactionSystem(rxs, t; continuous_events, discrete_events)
74+
rs_ce = complete(rs_ce)
75+
rs_de = complete(rs_de)
76+
rs_ce_de = complete(rs_ce_de)
77+
78+
79+
# Tests model content.
80+
issetequal(species(rs_ce), [X, A])
81+
issetequal(species(rs_de), [X, A])
82+
issetequal(species(rs_ce_de), [X, A])
83+
issetequal(unknowns(rs_ce), [X, A, a])
84+
issetequal(unknowns(rs_de), [X, A, a])
85+
issetequal(unknowns(rs_ce_de), [X, A, a])
86+
issetequal(parameters(rs_ce), [p, d, α])
87+
issetequal(parameters(rs_de), [p, d, α])
88+
issetequal(parameters(rs_ce_de), [p, d, α])
89+
90+
# Tests that species/variables/parameters can be accessed correctly one a MTK structure have been created.
91+
u0 = [X => 1]
92+
tspan = (0.0, 10.0)
93+
ps = [p => 10.0, d => 0.2]
94+
for XProb in [ODEProblem, SDEProblem, DiscreteProblem], rs in [rs_ce, rs_de, rs_ce_de]
95+
prob = XProb(rs, u0, (0.0, 10.0), ps)
96+
@test prob[A] == 2
97+
@test prob[a] == 3
98+
@test prob.ps[α] == 1.0
99+
end
100+
end

test/reactionsystem_structure/hybrid_equation_reaction_systems.jl

Whitespace-only changes.

0 commit comments

Comments
 (0)