Skip to content

Commit 99dcab2

Browse files
authored
Merge pull request #173 from SciML/pl/symbolic_bool
Pl/symbolic bool
2 parents 8ca157c + 751c5c5 commit 99dcab2

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/reactions.jl

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ function get_massaction(kl::Num, reactants::Union{Vector{Num}, Nothing},
177177

178178
check_args(::Val{false}, x::SymbolicUtils.BasicSymbolic{Real}) = isspecies(x) ? NaN : 0 # Species vs Parameter leaf node
179179
check_args(::Real) = 0 # Real leaf node
180+
check_args(::SymbolicUtils.BasicSymbolic{Bool}) = NaN
180181
check_args(x) = throw(ErrorException("Cannot handle $(typeof(x)) types.")) # Unknow leaf node
181182

182183
if isnothing(reactants) && isnothing(stoich)

src/rules.jl

+45-1
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,56 @@ function get_rules(model)
2121
algeqs, obseqs, raterules
2222
end
2323

24+
function extensive_kinetic_math(m::SBML.Model, formula::SBML.Math)
25+
SBML.interpret_math( # TODO: move this to SBML.jl
26+
formula,
27+
map_apply = (x, rec) -> SBML.MathApply(x.fn, rec.(x.args)),
28+
map_const = identity,
29+
map_ident = (x::SBML.MathIdent) -> begin
30+
haskey(m.reactions, x.id) && return m.reactions[x.id].kinetic_math
31+
haskey(m.species, x.id) || return x
32+
sp = m.species[x.id]
33+
sp.only_substance_units && return x
34+
if isnothing(m.compartments[sp.compartment].size) &&
35+
!seemsdefined(sp.compartment, m)
36+
if m.compartments[sp.compartment].spatial_dimensions == 0
37+
# If the compartment ID doesn't seem directly defined anywhere
38+
# and it is a zero-dimensional unsized compartment, just avoid
39+
# any sizing questions.
40+
return x
41+
else
42+
# In case the compartment is expected to be defined, complain.
43+
throw(
44+
DomainError(
45+
sp.compartment,
46+
"compartment size is insufficiently defined"
47+
),
48+
)
49+
end
50+
else
51+
# Now we are sure that the model either has the compartment with
52+
# constant size, or the definition is easily reachable. So just use
53+
# the compartment ID as a variable to compute the concentration (or
54+
# area-centration etc, with different dimensionalities) by dividing
55+
# it.
56+
return SBML.MathApply("/", [x, SBML.MathIdent(sp.compartment)])
57+
end
58+
end,
59+
map_lambda = (x, _) -> error(
60+
ErrorException("converting lambdas to extensive kinetic math is not supported"),
61+
),
62+
map_time = identity,
63+
map_avogadro = identity,
64+
map_value = identity
65+
)
66+
end
67+
2468
function get_var_and_assignment(model, rule)
2569
if !haskey(merge(model.species, model.compartments, model.parameters), rule.variable)
2670
error("Cannot find target for rule with ID `$(rule.variable)`")
2771
end
2872
var = create_var(rule.variable, IV)
29-
math = SBML.extensive_kinetic_math(model, rule.math)
73+
math = extensive_kinetic_math(model, rule.math)
3074
vc = get_volume_correction(model, rule.variable)
3175
if !isnothing(vc)
3276
math = SBML.MathApply("*", [SBML.MathIdent(vc), math])

test/reactions.jl

+1
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,5 @@ m = SBML.Model(species = Dict("s" => s), reactions = Dict("r1" => r))
139139

140140
@test isnan(SBMLToolkit.get_massaction(k1 * s1 * s2, [s1], [1]))
141141
@test isnan(SBMLToolkit.get_massaction(k1 + c1, [s1], [1]))
142+
@test isnan(SBMLToolkit.get_massaction(s1 + ifelse(s1 < k1, s1, k1), [s1], [1]))
142143
@test_throws ErrorException SBMLToolkit.get_massaction(k1, nothing, [1])

0 commit comments

Comments
 (0)