Skip to content

Commit c0823f5

Browse files
author
Lucas Morton
committed
Bypassing units check against noise terms & LHS/RHS of equations that are zero. Also using DimensionError instead of ArgumentError s.t. catching is easier; hacking it to show the terms & units.
1 parent 0c3066d commit c0823f5

File tree

2 files changed

+33
-30
lines changed

2 files changed

+33
-30
lines changed

src/systems/validation.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ function get_units(x::Symbolic)
2121
return base == 1 ? 1 : operation(x)(base, pargs[2])
2222
elseif x isa Add # Cannot simply add the units b/c they may differ in magnitude (eg, kg vs g)
2323
terms = get_units.(arguments(x))
24-
firstunit = unit(terms[1])
24+
firstunit = 1*unit(terms[1])
2525
for other in terms[2:end]
26-
unit(other) == firstunit || throw(ArgumentError("Units mismatch: [$x] with units [$terms]."))
26+
isequal(1 * unit(other), firstunit) || throw(Unitful.DimensionError(x, terms))
2727
end
2828
return 1 * firstunit
2929
elseif operation(x) == Symbolics._mapreduce
@@ -45,7 +45,7 @@ function safe_get_units(term, info)
4545
catch err
4646
if err isa Unitful.DimensionError
4747
@warn("$info: $(err.x) and $(err.y) are not dimensionally compatible.")
48-
elseif err isa MethodError #TODO: filter for only instances where the arguments are unitful
48+
elseif err isa MethodError
4949
@warn("$info: no method matching $(err.f) for arguments $(typeof.(err.args)).")
5050
else
5151
rethrow()
@@ -58,11 +58,17 @@ function _validate(terms::Vector, labels::Vector{String}; info::String = "")
5858
equnits = safe_get_units.(terms, info*", ".*labels)
5959
allthere = all(map(x -> x!==nothing, equnits))
6060
allmatching = true
61+
first_unit = nothing
6162
if allthere
62-
for idx in 2:length(equnits)
63-
if !isequal(equnits[1], equnits[idx])
64-
allmatching = false
65-
@warn("$info: units $(equnits[1]) for $(labels[1]) and $(equnits[idx]) for $(labels[idx]) do not match.")
63+
for idx in 1:length(equnits)
64+
if !isequal(terms[idx],0)
65+
if first_unit === nothing
66+
first_unit = equnits[idx]
67+
elseif !isequal(first_unit, equnits[idx])
68+
allmatching = false
69+
@warn("$info: units $(equnits[1]) for $(labels[1]) and $(equnits[idx]) for $(labels[idx]) do not match.")
70+
71+
end
6672
end
6773
end
6874
end

test/units.jl

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ D = Differential(t)
1919
@test MT.get_units(E/τ) == 1.0u"MW"
2020
@test MT.get_units(2*P) == 1.0u"MW"
2121
@test MT.get_units(t/τ) == 1.0
22-
@test MT.get_units(P - E/τ)/1.0u"MW" == 1.0
22+
@test MT.get_units(P - E/τ) == 1.0u"MW"
2323

2424
@test MT.get_units(1.0^(t/τ)) == 1.0
2525
@test MT.get_units(exp(t/τ)) == 1.0
@@ -37,14 +37,11 @@ eqs = [D(E) ~ P - E/τ
3737
@test MT.validate(eqs[1])
3838
@test MT.validate(eqs[2])
3939
@test MT.validate(eqs)
40-
sys = ODESystem(eqs)
41-
sys = ODESystem(eqs, t, [P, E], [τ])
40+
@named sys = ODESystem(eqs)
41+
@named sys = ODESystem(eqs, t, [P, E], [τ])
4242

4343
@test !MT.validate(D(D(E)) ~ P)
4444
@test !MT.validate(0 ~ P + E*τ)
45-
@test_logs (:warn,) MT.validate(0 ~ P + E*τ)
46-
@test_logs (:warn,) MT.validate(P + E*τ ~ 0)
47-
@test_logs (:warn,) MT.validate(P ~ 0)
4845

4946
#Unit-free
5047
@variables x y z u
@@ -56,7 +53,7 @@ eqs = [0 ~ σ*(y - x)]
5653
@variables t x[1:3,1:3](t)
5754
D = Differential(t)
5855
eqs = D.(x) .~ x
59-
ODESystem(eqs)
56+
ODESystem(eqs,name=:sys)
6057

6158
# Array ops
6259
using Symbolics: unwrap, wrap
@@ -69,7 +66,7 @@ eqs = [
6966
collect(D.(x) ~ x)
7067
D(y) ~ norm(x)*y
7168
]
72-
ODESystem(eqs, t, [sts...;], [ps...;])
69+
ODESystem(eqs, t, [sts...;], [ps...;],name=:sys)
7370

7471
#= Not supported yet b/c iterate doesn't work on unitful array
7572
# Array ops with units
@@ -99,7 +96,7 @@ D = Difference(t; dt = 0.1u"s")
9996
eqs = [
10097
δ(x) ~ a*x
10198
]
102-
de = ODESystem(eqs, t, [x, y], [a])
99+
de = ODESystem(eqs, t, [x, y], [a],name=:sys)
103100

104101

105102
@parameters t
@@ -111,15 +108,15 @@ eqs = [D(y[1]) ~ -k[1]*y[1] + k[3]*y[2]*y[3],
111108
D(y[2]) ~ k[1]*y[1] - k[3]*y[2]*y[3] - k[2]*y[2]^2,
112109
0 ~ y[1] + y[2] + y[3] - 1]
113110

114-
sys = ODESystem(eqs,t,y,k)
111+
@named sys = ODESystem(eqs,t,y,k)
115112

116113
# Nonlinear system
117114
@parameters a [unit = u"kg"^-1]
118115
@variables x [unit = u"kg"]
119116
eqs = [
120117
0 ~ a*x
121118
]
122-
nls = NonlinearSystem(eqs, [x], [a])
119+
@named nls = NonlinearSystem(eqs, [x], [a])
123120

124121
# SDE test w/ noise vector
125122
@parameters τ [unit = u"ms"] Q [unit = u"MW"]
@@ -130,11 +127,11 @@ eqs = [D(E) ~ P - E/τ
130127

131128
noiseeqs = [0.1u"MW",
132129
0.1u"MW"]
133-
sys = SDESystem(eqs, noiseeqs, t, [P, E], [τ, Q])
130+
@named sys = SDESystem(eqs, noiseeqs, t, [P, E], [τ, Q])
134131
# With noise matrix
135132
noiseeqs = [0.1u"MW" 0.1u"MW"
136133
0.1u"MW" 0.1u"MW"]
137-
sys = SDESystem(eqs,noiseeqs, t, [P, E], [τ, Q])
134+
@named sys = SDESystem(eqs,noiseeqs, t, [P, E], [τ, Q])
138135

139136
noiseeqs = [0.1u"MW" 0.1u"MW"
140137
0.1u"MW" 0.1u"s"]
@@ -146,24 +143,24 @@ noiseeqs = [0.1u"MW" 0.1u"MW"
146143
D = Differential(t)
147144
eqs = [D(L) ~ v,
148145
V ~ L^3]
149-
sys = ODESystem(eqs)
146+
@named sys = ODESystem(eqs)
150147
sys_simple = structural_simplify(sys)
151148

152149
eqs = [D(V) ~ r,
153150
V ~ L^3]
154-
sys = ODESystem(eqs)
151+
@named sys = ODESystem(eqs)
155152
sys_simple = structural_simplify(sys)
156153

157154
@variables V [unit = u"m"^3] L [unit = u"m"]
158-
@parameters v [unit = u"m/s"] r [unit =u"m"^3/u"s"] t [unit = u"s"]
155+
@parameters v [unit = u"m/s"] r [unit = u"m"^3/u"s"] t [unit = u"s"]
159156
eqs = [V ~ r*t,
160157
V ~ L^3]
161-
sys = NonlinearSystem(eqs, [V, L], [t, r])
158+
@named sys = NonlinearSystem(eqs, [V, L], [t, r])
162159
sys_simple = structural_simplify(sys)
163160

164161
eqs = [L ~ v*t,
165162
V ~ L^3]
166-
sys = NonlinearSystem(eqs, [V,L], [t,r])
163+
@named sys = NonlinearSystem(eqs, [V,L], [t,r])
167164
sys_simple = structural_simplify(sys)
168165

169166
#Jump System
@@ -175,25 +172,25 @@ rate₂ = γ*I
175172
affect₂ = [I ~ I - 1u"mol", R ~ R + 1u"mol"]
176173
j₁ = ConstantRateJump(rate₁, affect₁)
177174
j₂ = VariableRateJump(rate₂, affect₂)
178-
js = JumpSystem([j₁, j₂], t, [S, I, R], [β, γ])
175+
js = JumpSystem([j₁, j₂], t, [S, I, R], [β, γ],name=:sys)
179176

180177
affect_wrong = [S ~ S - 1u"mol", I ~ I + 1]
181178
j_wrong = ConstantRateJump(rate₁, affect_wrong)
182-
@test_throws ArgumentError JumpSystem([j_wrong, j₂], t, [S, I, R], [β, γ])
179+
@test_throws ArgumentError JumpSystem([j_wrong, j₂], t, [S, I, R], [β, γ],name=:sys)
183180

184181
rate_wrong = γ^2*I
185182
j_wrong = ConstantRateJump(rate_wrong, affect₂)
186-
@test_throws ArgumentError JumpSystem([j₁, j_wrong], t, [S, I, R], [β, γ])
183+
@test_throws ArgumentError JumpSystem([j₁, j_wrong], t, [S, I, R], [β, γ],name=:sys)
187184

188185
# mass action jump tests for SIR model
189186
maj1 = MassActionJump(2*β/2, [S => 1, I => 1], [S => -1, I => 1])
190187
maj2 = MassActionJump(γ, [I => 1], [I => -1, R => 1])
191-
js3 = JumpSystem([maj1, maj2], t, [S,I,R], [β,γ])
188+
@named js3 = JumpSystem([maj1, maj2], t, [S,I,R], [β,γ])
192189

193190
#Test unusual jump system
194191
@parameters β γ t
195192
@variables S(t) I(t) R(t)
196193

197194
maj1 = MassActionJump(2.0, [0 => 1], [S => 1])
198195
maj2 = MassActionJump(γ, [S => 1], [S => -1])
199-
js4 = JumpSystem([maj1, maj2], t, [S], [β, γ])
196+
@named js4 = JumpSystem([maj1, maj2], t, [S], [β, γ])

0 commit comments

Comments
 (0)