Skip to content

Commit c7ce86d

Browse files
Merge branch 'SciML:master' into testdocs
2 parents 5b25e8f + 005a58f commit c7ce86d

File tree

13 files changed

+94
-62
lines changed

13 files changed

+94
-62
lines changed

docs/src/model_creation/dsl_advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ Sometimes, one wishes to declare a large number of similar parameters or species
256256
using Catalyst # hide
257257
two_state_model = @reaction_network begin
258258
@parameters k[1:2]
259-
@species X(t)[1:2]
259+
@species (X(t))[1:2]
260260
(k[1],k[2]), X[1] <--> X[2]
261261
end
262262
```

docs/src/model_creation/examples/programmatic_generative_linear_pathway.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ t = default_t()
8484
@parameters τ
8585
function generate_lp(n)
8686
# Creates a vector `X` with n+1 species.
87-
@species X(t)[1:n+1]
87+
@species (X(t))[1:n+1]
8888
@species Xend(t)
8989
9090
# Generate

docs/src/model_creation/examples/smoluchowski_coagulation_equation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ for n = 1:nr
9898
[1, 1], [1]))
9999
end
100100
end
101-
@named rs = ReactionSystem(rx, t, collect(X), collect(k))
101+
@named rs = ReactionSystem(rx, t, collect(X), [k])
102102
rs = complete(rs)
103103
```
104104
We now convert the [`ReactionSystem`](@ref) into a `ModelingToolkit.JumpSystem`, and solve it using Gillespie's direct method. For details on other possible solvers (SSAs), see the [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/types/jump_types/) documentation

src/dsl.jl

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,12 @@ function make_reaction_system(ex::Expr; name = :(gensym(:ReactionSystem)))
369369
sexprs = get_sexpr(species_extracted, options; iv_symbols = ivs)
370370
vexprs = get_sexpr(vars_extracted, options, :variables; iv_symbols = ivs)
371371
pexprs = get_pexpr(parameters_extracted, options)
372-
ps, pssym = scalarize_macro(!isempty(parameters), pexprs, "ps")
373-
vars, varssym = scalarize_macro(!isempty(variables), vexprs, "vars")
374-
sps, spssym = scalarize_macro(!isempty(species), sexprs, "specs")
375-
comps, compssym = scalarize_macro(!isempty(compound_species), compound_expr, "comps")
372+
ps, pssym = assign_expr_to_var(!isempty(parameters), pexprs, "ps")
373+
vars, varssym = assign_expr_to_var(!isempty(variables), vexprs, "vars";
374+
scalarize = true)
375+
sps, spssym = assign_expr_to_var(!isempty(species), sexprs, "specs"; scalarize = true)
376+
comps, compssym = assign_expr_to_var(!isempty(compound_species), compound_expr,
377+
"comps"; scalarize = true)
376378
rxexprs = :(CatalystEqType[])
377379
for reaction in reactions
378380
push!(rxexprs.args, get_rxexprs(reaction))
@@ -591,14 +593,21 @@ function get_rxexprs(rxstruct)
591593
end
592594

593595
# takes a ModelingToolkit declaration macro like @parameters and returns an expression
594-
# that calls the macro and then scalarizes all the symbols created into a vector of Nums
595-
function scalarize_macro(nonempty, ex, name)
596+
# that calls the macro and saves it in a variable given by namesym based on name.
597+
# scalarizes if desired
598+
function assign_expr_to_var(nonempty, ex, name; scalarize = false)
596599
namesym = gensym(name)
597600
if nonempty
598-
symvec = gensym()
599-
ex = quote
600-
$symvec = $ex
601-
$namesym = reduce(vcat, Symbolics.scalarize($symvec))
601+
if scalarize
602+
symvec = gensym()
603+
ex = quote
604+
$symvec = $ex
605+
$namesym = reduce(vcat, Symbolics.scalarize($symvec))
606+
end
607+
else
608+
ex = quote
609+
$namesym = $ex
610+
end
602611
end
603612
else
604613
ex = :($namesym = Num[])

src/network_analysis.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,8 @@ function cache_conservationlaw_eqs!(rn::ReactionSystem, N::AbstractMatrix, col_o
657657
indepspecs = sts[indepidxs]
658658
depidxs = col_order[(r + 1):end]
659659
depspecs = sts[depidxs]
660-
constants = MT.unwrap.(MT.scalarize(only(
661-
@parameters $(CONSERVED_CONSTANT_SYMBOL)[1:nullity] [conserved = true])))
660+
constants = MT.unwrap(only(
661+
@parameters $(CONSERVED_CONSTANT_SYMBOL)[1:nullity] [conserved = true]))
662662

663663
conservedeqs = Equation[]
664664
constantdefs = Equation[]

src/reactionsystem.jl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,11 @@ function ReactionSystem(eqs, iv, unknowns, ps;
405405
sivs′ = if spatial_ivs === nothing
406406
Vector{typeof(iv′)}()
407407
else
408-
value.(MT.scalarize(spatial_ivs))
408+
value.(spatial_ivs)
409409
end
410-
unknowns′ = sort!(value.(MT.scalarize(unknowns)), by = !isspecies)
410+
unknowns′ = sort!(value.(unknowns), by = !isspecies)
411411
spcs = filter(isspecies, unknowns′)
412-
ps′ = value.(MT.scalarize(ps))
412+
ps′ = value.(ps)
413413

414414
# Checks that no (by Catalyst) forbidden symbols are used.
415415
allsyms = Iterators.flatten((ps′, unknowns′))
@@ -467,7 +467,7 @@ end
467467
# Two-argument constructor (reactions/equations and time variable).
468468
# Calls the `make_ReactionSystem_internal`, which in turn calls the four-argument constructor.
469469
function ReactionSystem(rxs::Vector, iv = Catalyst.DEFAULT_IV; kwargs...)
470-
make_ReactionSystem_internal(rxs, iv, Vector{Num}(), Vector{Num}(); kwargs...)
470+
make_ReactionSystem_internal(rxs, iv, [], []; kwargs...)
471471
end
472472

473473
# One-argument constructor. Creates an emtoy `ReactionSystem` from a time independent variable only.
@@ -485,24 +485,25 @@ function make_ReactionSystem_internal(rxs_and_eqs::Vector, iv, us_in, ps_in;
485485
spatial_ivs = nothing, continuous_events = [], discrete_events = [],
486486
observed = [], kwargs...)
487487

488-
# Filters away any potential observables from `states` and `spcs`.
489-
obs_vars = [obs_eq.lhs for obs_eq in observed]
490-
us_in = filter(u -> !any(isequal(u, obs_var) for obs_var in obs_vars), us_in)
488+
# Error if any observables have been declared a species or variable
489+
obs_vars = Set(obs_eq.lhs for obs_eq in observed)
490+
any(in(obs_vars), us_in) &&
491+
error("Found an observable in the list of unknowns. This is not allowed.")
491492

492493
# Creates a combined iv vector (iv and sivs). This is used later in the function (so that
493494
# independent variables can be excluded when encountered quantities are added to `us` and `ps`).
494495
t = value(iv)
495496
ivs = Set([t])
496497
if (spatial_ivs !== nothing)
497-
for siv in (MT.scalarize(spatial_ivs))
498+
for siv in (spatial_ivs)
498499
push!(ivs, value(siv))
499500
end
500501
end
501502

502503
# Initialises the new unknowns and parameter vectors.
503504
# Preallocates the `vars` set, which is used by `findvars!`
504-
us = OrderedSet{eltype(us_in)}(us_in)
505-
ps = OrderedSet{eltype(ps_in)}(ps_in)
505+
us = OrderedSet{Any}(us_in)
506+
ps = OrderedSet{Any}(ps_in)
506507
vars = OrderedSet()
507508

508509
# Extracts the reactions and equations from the combined reactions + equations input vector.
@@ -548,7 +549,22 @@ function make_ReactionSystem_internal(rxs_and_eqs::Vector, iv, us_in, ps_in;
548549

549550
# Converts the found unknowns and parameters to vectors.
550551
usv = collect(us)
551-
psv = collect(ps)
552+
553+
new_ps = OrderedSet()
554+
for p in ps
555+
if iscall(p) && operation(p) === getindex
556+
par = arguments(p)[begin]
557+
if Symbolics.shape(Symbolics.unwrap(par)) !== Symbolics.Unknown() &&
558+
all(par[i] in ps for i in eachindex(par))
559+
push!(new_ps, par)
560+
else
561+
push!(new_ps, p)
562+
end
563+
else
564+
push!(new_ps, p)
565+
end
566+
end
567+
psv = collect(new_ps)
552568

553569
# Passes the processed input into the next `ReactionSystem` call.
554570
ReactionSystem(fulleqs, t, usv, psv; spatial_ivs, continuous_events,

test/dsl/dsl_advanced_model_construction.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,23 @@ let
340340
k[1]*a+k[2], X[1] + V[1]*X[2] --> V[2]*W*Y + B*C
341341
end
342342

343-
@parameters k[1:3] a B
343+
@parameters k[1:2] a B
344344
@variables (V(t))[1:2] W(t)
345345
@species (X(t))[1:2] Y(t) C(t)
346346
rx = Reaction(k[1]*a+k[2], [X[1], X[2]], [Y, C], [1, V[1]], [V[2] * W, B])
347347
@named arrtest = ReactionSystem([rx], t)
348-
arrtest == rn
348+
@test arrtest == rn
349+
350+
rn = @reaction_network twostate begin
351+
@parameters k[1:2]
352+
@species (X(t))[1:2]
353+
(k[1],k[2]), X[1] <--> X[2]
354+
end
355+
356+
@parameters k[1:2]
357+
@species (X(t))[1:2]
358+
rx1 = Reaction(k[1], [X[1]], [X[2]])
359+
rx2 = Reaction(k[2], [X[2]], [X[1]])
360+
@named twostate = ReactionSystem([rx1, rx2], t)
361+
@test twostate == rn
349362
end

test/dsl/dsl_options.jl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ let
604604
k, 0 --> X1 + X2
605605
end
606606
@test isequal(observed(rn1)[1].rhs, observed(rn2)[1].rhs)
607-
@test isequal(observed(rn1)[1].lhs.metadata, observed(rn2)[1].lhs.metadata)
607+
@test_broken isequal(observed(rn1)[1].lhs.metadata, observed(rn2)[1].lhs.metadata)
608608
@test isequal(unknowns(rn1), unknowns(rn2))
609609

610610
# Case with metadata.
@@ -618,7 +618,7 @@ let
618618
k, 0 --> X1 + X2
619619
end
620620
@test isequal(observed(rn3)[1].rhs, observed(rn4)[1].rhs)
621-
@test isequal(observed(rn3)[1].lhs.metadata, observed(rn4)[1].lhs.metadata)
621+
@test_broken isequal(observed(rn3)[1].lhs.metadata, observed(rn4)[1].lhs.metadata)
622622
@test isequal(unknowns(rn3), unknowns(rn4))
623623
end
624624

@@ -822,10 +822,7 @@ let
822822
@variables X(t)
823823
@equations 2X ~ $c - X
824824
end)
825-
826-
u0 = [rn.X => 0.0]
827-
ps = []
828-
oprob = ODEProblem(rn, u0, (0.0, 100.0), ps; structural_simplify=true)
825+
oprob = ODEProblem(rn, [], (0.0, 100.0); structural_simplify=true)
829826
sol = solve(oprob, Tsit5(); abstol=1e-9, reltol=1e-9)
830827
@test sol[rn.X][end] 2.0
831828
end

test/network_analysis/conservation_laws.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ end
343343
let
344344
# Prepares the model.
345345
t = default_t()
346-
@species X(t)[1:2]
346+
@species (X(t))[1:2]
347347
@parameters k[1:2]
348348
rxs = [
349349
Reaction(k[1], [X[1]], [X[2]]),

test/reactionsystem_core/reactionsystem.jl

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,18 @@ rxs = [Reaction(k[1], nothing, [A]), # 0 -> A
4040
Reaction(k[19] * t, [A], [B]), # A -> B with non constant rate.
4141
Reaction(k[20] * t * A, [B, C], [D], [2, 1], [2]), # 2A +B -> 2C with non constant rate.
4242
]
43-
@named rs = ReactionSystem(rxs, t, [A, B, C, D], k)
43+
@named rs = ReactionSystem(rxs, t, [A, B, C, D], [k])
4444
rs = complete(rs)
4545
odesys = complete(convert(ODESystem, rs))
4646
sdesys = complete(convert(SDESystem, rs))
4747

4848
# Hard coded ODE rhs.
49-
function oderhs(u, k, t)
49+
function oderhs(u, kv, t)
5050
A = u[1]
5151
B = u[2]
5252
C = u[3]
5353
D = u[4]
54+
k = kv[1]
5455
du = zeros(eltype(u), 4)
5556
du[1] = k[1] - k[3] * A + k[4] * C + 2 * k[5] * C - k[6] * A * B + k[7] * B^2 / 2 -
5657
k[9] * A * B - k[10] * A^2 - k[11] * A^2 / 2 - k[12] * A * B^3 * C^4 / 144 -
@@ -68,11 +69,12 @@ function oderhs(u, k, t)
6869
end
6970

7071
# SDE noise coefs.
71-
function sdenoise(u, k, t)
72+
function sdenoise(u, kv, t)
7273
A = u[1]
7374
B = u[2]
7475
C = u[3]
7576
D = u[4]
77+
k = kv[1]
7678
G = zeros(eltype(u), length(k), length(u))
7779
z = zero(eltype(u))
7880

@@ -109,11 +111,12 @@ end
109111

110112
# Defaults test.
111113
let
112-
def_p = [ki => float(i) for (i, ki) in enumerate(k)]
114+
kvals = Float64.(1:length(k))
115+
def_p = [k => kvals]
113116
def_u0 = [A => 0.5, B => 1.0, C => 1.5, D => 2.0]
114117
defs = merge(Dict(def_p), Dict(def_u0))
115118

116-
@named rs = ReactionSystem(rxs, t, [A, B, C, D], k; defaults = defs)
119+
@named rs = ReactionSystem(rxs, t, [A, B, C, D], [k]; defaults = defs)
117120
rs = complete(rs)
118121
odesys = complete(convert(ODESystem, rs))
119122
sdesys = complete(convert(SDESystem, rs))
@@ -126,15 +129,11 @@ let
126129
defs
127130

128131
u0map = [A => 5.0]
129-
pmap = [k[1] => 5.0]
132+
kvals[1] = 5.0
133+
pmap = [k => kvals]
130134
prob = ODEProblem(rs, u0map, (0, 10.0), pmap)
131135
@test prob.ps[k[1]] == 5.0
132136
@test prob.u0[1] == 5.0
133-
u0 = [10.0, 11.0, 12.0, 13.0]
134-
ps = [float(x) for x in 100:119]
135-
prob = ODEProblem(rs, u0, (0, 10.0), ps)
136-
@test [prob.ps[k[i]] for i in 1:20] == ps
137-
@test prob.u0 == u0
138137
end
139138

140139
### Check ODE, SDE, and Jump Functions ###
@@ -181,7 +180,7 @@ let
181180
Reaction(k[19] * t, [D], [E]), # D -> E with non constant rate.
182181
Reaction(k[20] * t * A, [D, E], [F], [2, 1], [2]), # 2D + E -> 2F with non constant rate.
183182
]
184-
@named rs = ReactionSystem(rxs, t, [A, B, C, D, E, F], k)
183+
@named rs = ReactionSystem(rxs, t, [A, B, C, D, E, F], [k])
185184
rs = complete(rs)
186185
js = complete(convert(JumpSystem, rs))
187186

@@ -193,7 +192,7 @@ let
193192
@test all(map(i -> typeof(equations(js)[i]) <: JumpProcesses.VariableRateJump, vidxs))
194193

195194
p = rand(rng, length(k))
196-
pmap = parameters(js) .=> p
195+
pmap = [k => p]
197196
u0 = rand(rng, 2:10, 6)
198197
u0map = unknowns(js) .=> u0
199198
ttt = rand(rng)
@@ -392,7 +391,7 @@ end
392391
# Needs fix for https://github.com/JuliaSymbolics/Symbolics.jl/issues/842.
393392
let
394393
@parameters a
395-
@species A(t) B(t) C(t)[1:2]
394+
@species A(t) B(t) (C(t))[1:2]
396395
rx1 = Reaction(a, [A, C[1]], [C[2], B], [1, 2], [2, 3])
397396
io = IOBuffer()
398397
show(io, rx1)
@@ -868,11 +867,9 @@ end
868867
let
869868
@species (A(t))[1:20]
870869
using ModelingToolkit: value
871-
@test isspecies(value(A))
872-
@test isspecies(value(A[2]))
873-
Av = value.(ModelingToolkit.scalarize(A))
874-
@test isspecies(Av[2])
875-
@test isequal(value(Av[2]), value(A[2]))
870+
Av = value(A)
871+
@test isspecies(Av)
872+
@test all(i -> isspecies(Av[i]), 1:length(Av))
876873
end
877874

878875
# Test mixed models are formulated correctly.

0 commit comments

Comments
 (0)