Skip to content

Commit b6a9a04

Browse files
authored
Merge pull request #798 from SciML/handle_units
Handle units
2 parents 18f5d3a + 384b2e8 commit b6a9a04

File tree

8 files changed

+262
-142
lines changed

8 files changed

+262
-142
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ version = "13.5.1"
66
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
77
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
88
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
9+
DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821"
910
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1011
JumpProcesses = "ccbc3e58-028d-4f4c-8cd5-9ae44345cda5"
1112
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
@@ -38,9 +39,10 @@ BifurcationKit = "0.3"
3839
DataStructures = "0.18"
3940
DiffEqBase = "6.83.0"
4041
DocStringExtensions = "0.8, 0.9"
42+
DynamicQuantities = "0.13.2"
4143
Graphs = "1.4"
42-
JumpProcesses = "9.3.2"
4344
HomotopyContinuation = "2.9"
45+
JumpProcesses = "9.3.2"
4446
LaTeXStrings = "1.3.0"
4547
Latexify = "0.14, 0.15, 0.16"
4648
MacroTools = "0.5.5"

src/Catalyst.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ using JumpProcesses: JumpProcesses,
1313
# ModelingToolkit imports and convenience functions we use
1414
using ModelingToolkit
1515
const MT = ModelingToolkit
16-
using Unitful
16+
using DynamicQuantities#, Unitful # Having Unitful here as well currently gives an error.
17+
18+
1719
@reexport using ModelingToolkit
1820
using Symbolics
1921

src/networkapi.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,7 @@ function validate(rs::ReactionSystem, info::String = "")
16141614

16151615
# no units for species, time or parameters then assume validated
16161616
if (specunits in (MT.unitless, nothing)) && (timeunits in (MT.unitless, nothing))
1617-
all(u == 1.0 for u in ModelingToolkit.get_unit(get_ps(rs))) || return true
1617+
all(u == 1.0 for u in ModelingToolkit.get_unit(get_ps(rs))) && return true
16181618
end
16191619

16201620
rateunits = specunits / timeunits
@@ -1624,12 +1624,21 @@ function validate(rs::ReactionSystem, info::String = "")
16241624
rxunits *= get_unit(sub)^rx.substoich[i]
16251625
end
16261626

1627-
if !isequal(rxunits, rateunits)
1628-
validated = false
1629-
@warn(string("Reaction rate laws are expected to have units of ", rateunits,
1630-
" however, ", rx, " has units of ", rxunits, "."))
1627+
# Checks that the reaction's combined units is correct, if not, throws a warning.
1628+
# Needs additional checks because for cases: (1.0^n) and (1.0^n1)*(1.0^n2).
1629+
# These are not considered (be default) considered equal to `1.0` for unitless reactions.
1630+
isequal(rxunits, rateunits) && continue
1631+
if istree(rxunits)
1632+
unitless_exp(rxunits) && continue
1633+
(operation(rxunits) == *) && all(unitless_exp(arg) for arg in arguments(rxunits)) && continue
16311634
end
1635+
validated = false
1636+
@warn(string("Reaction rate laws are expected to have units of ", rateunits, " however, ",
1637+
rx, " has units of ", rxunits, "."))
16321638
end
16331639

16341640
validated
16351641
end
1642+
1643+
# Checks if a unit consist of exponents with base 1 (and is this unitless).
1644+
unitless_exp(u) = istree(u) && (operation(u) == ^) && (arguments(u)[1] == 1)

src/reactionsystem.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,9 @@ struct ReactionSystem{V <: NetworkProperties} <:
563563

564564
if isempty(sivs) && (checks == true || (checks & MT.CheckUnits) > 0)
565565
if !all(u == 1.0 for u in ModelingToolkit.get_unit([unknowns; ps; iv]))
566-
nonrx_eqs = Equation[eq for eq in eqs if eq isa Equation]
567-
check_units(nonrx_eqs)
566+
for eq in eqs
567+
(eq isa Equation) && check_units(eq)
568+
end
568569
end
569570
end
570571

test/miscellaneous_tests/symbolic_stoichiometry.jl

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,37 +217,39 @@ let
217217
d, Y --> 0
218218
end
219219

220-
u0 = [:X => 1, :Y => 1]
221-
ps_int = [:p => 1.0, :n1 => 3, :n2 => 4, :d => 0.5]
222-
ps_dec = [:p => 1.0, :n1 => 0.5, :n2 => 2.5, :d => 0.5]
220+
u0 = [:X => 8, :Y => 8]
221+
ps_int = (:p => 2.0, :k => 0.01, :n1 => 3, :n2 => 4, :d => 0.2)
222+
ps_dec = [:p => 2.0, :k => 0.01, :n1 => 0.5, :n2 => 2.5, :d => 0.2]
223223
tspan = (0.0, 10.0)
224224

225225
# Test ODE simulations with integer coefficients.
226226
oprob_int = ODEProblem(rs_int, u0, tspan, ps_int)
227227
oprob_int_ref = ODEProblem(rs_ref_int, u0, tspan, ps_int)
228-
@test solve(oprob_int, Tsit5()) == solve(oprob_int_ref, Tsit5())
228+
@test solve(oprob_int, Tsit5()) solve(oprob_int_ref, Tsit5())
229229

230230
# Test ODE simulations with decimal coefficients.
231231
oprob_dec = ODEProblem(rs_dec, u0, tspan, ps_dec; combinatoric_ratelaws = false)
232232
oprob_dec_ref = ODEProblem(rs_ref_dec, u0, tspan, ps_dec; combinatoric_ratelaws = false)
233-
@test solve(oprob_dec, Tsit5()) == solve(oprob_dec_ref, Tsit5())
233+
@test solve(oprob_dec, Tsit5()) solve(oprob_dec_ref, Tsit5())
234234

235235
# Test SDE simulations with integer coefficients.
236236
sprob_int = SDEProblem(rs_int, u0, tspan, ps_int)
237237
sprob_int_ref = SDEProblem(rs_ref_int, u0, tspan, ps_int)
238-
@test solve(sprob_int, ImplicitEM(); seed) == solve(sprob_int_ref, ImplicitEM(); seed)
238+
@test solve(sprob_int, ImplicitEM(); seed) solve(sprob_int_ref, ImplicitEM(); seed)
239239

240240
# Test SDE simulations with decimal coefficients.
241241
sprob_dec = SDEProblem(rs_dec, u0, tspan, ps_dec; combinatoric_ratelaws = false)
242242
sprob_dec_ref = SDEProblem(rs_ref_dec, u0, tspan, ps_dec; combinatoric_ratelaws = false)
243-
@test solve(sprob_dec, ImplicitEM(); seed) == solve(sprob_dec_ref, ImplicitEM(); seed)
243+
@test solve(sprob_dec, ImplicitEM(); seed) solve(sprob_dec_ref, ImplicitEM(); seed)
244244

245245
# Tests jump simulations with integer coefficients.
246-
dprob_int = DiscreteProblem(rs_int, u0, tspan, ps_int)
247-
dprob_int_ref = DiscreteProblem(rs_ref_int, u0, tspan, ps_int)
246+
dprob_int = DiscreteProblem(rs_int, u0, (0.0, 100000.0), ps_int)
247+
dprob_int_ref = DiscreteProblem(rs_ref_int, u0, (0.0, 100000.0), ps_int)
248248
jprob_int = JumpProblem(rs_int, dprob_int, Direct(); rng)
249249
jprob_int_ref = JumpProblem(rs_ref_int, dprob_int_ref, Direct(); rng)
250-
@test solve(jprob_int, SSAStepper(); seed) == solve(jprob_int_ref, SSAStepper(); seed)
250+
sol_int = solve(jprob_int, SSAStepper(); seed)
251+
sol_int_ref = solve(jprob_int_ref, SSAStepper(); seed)
252+
@test mean(sol_int[:Y]) mean(sol_int_ref[:Y]) atol = 1e-2 rtol = 1e-2
251253
end
252254

253255
# Check that jump simulations (implemented with and without symbolic stoichiometries) yield simulations

0 commit comments

Comments
 (0)