Skip to content

Commit 9616b01

Browse files
Merge pull request #273 from SciML/validation
add unit validation of equations
2 parents 7f051bb + ce79f03 commit 9616b01

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1717
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
1818
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1919
TreeViews = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7"
20+
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2021

2122
[compat]
2223
DiffEqBase = "6"

src/ModelingToolkit.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module ModelingToolkit
22

33
using DiffEqBase, Distributed
44
using StaticArrays, LinearAlgebra, SparseArrays
5-
using Latexify
5+
using Latexify, Unitful
66
using MacroTools
77

88
using MacroTools
@@ -92,6 +92,7 @@ include("systems/diffeqs/sdesystem.jl")
9292
include("systems/diffeqs/abstractodesystem.jl")
9393
include("systems/diffeqs/first_order_transform.jl")
9494
include("systems/diffeqs/modelingtoolkitize.jl")
95+
include("systems/diffeqs/validation.jl")
9596
include("systems/nonlinear/nonlinear_system.jl")
9697
include("systems/pde/pdesystem.jl")
9798
include("systems/reaction/reactionsystem.jl")

src/systems/diffeqs/validation.jl

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
isintermediate(eq::Equation) = !(isa(eq.lhs, Operation) && isa(eq.lhs.op, Differential))
1+
Base.:*(x::Expression,y::Unitful.AbstractQuantity) = x * ModelingToolkit.Constant(y)
22

3-
struct ODEExpr # dⁿx/dtⁿ = rhs
4-
x::Variable
5-
n::Int
6-
rhs::Expression
3+
instantiate(x::ModelingToolkit.Constant) = x.value
4+
instantiate(x::ModelingToolkit.Variable{Number}) = 1.0
5+
instantiate(x::ModelingToolkit.Variable) = oneunit(1*ModelingToolkit.vartype(x))
6+
function instantiate(x::ModelingToolkit.Operation)
7+
if x.op isa Variable
8+
return instantiate(x.op)
9+
elseif x.op isa Differential
10+
instantiate(x.args[1])/instantiate(x.args[1].args[1])
11+
else
12+
x.op(instantiate.(x.args)...)
13+
end
714
end
8-
function Base.convert(::Type{ODEExpr},eq::Equation)
9-
isintermediate(eq) && throw(ArgumentError("intermediate equation received"))
10-
(x, t, n) = flatten_differential(eq.lhs)
11-
(isa(t, Operation) && isa(t.op, Variable) && isempty(t.args)) ||
12-
throw(ArgumentError("invalid independent variable $t"))
13-
(isa(x, Operation) && isa(x.op, Variable) && length(x.args) == 1 && isequal(first(x.args), t)) ||
14-
throw(ArgumentError("invalid dependent variable $x"))
15-
return t.op, ODEExpr(x.op, n, eq.rhs)
15+
16+
function validate(eq::ModelingToolkit.Equation)
17+
try
18+
return typeof(instantiate(eq.lhs)) == typeof(instantiate(eq.rhs))
19+
catch
20+
return false
21+
end
22+
end
23+
24+
function validate(sys::AbstractODESystem)
25+
all(validate.(equations(sys)))
1626
end
17-
Base.:(==)(a::ODEExpr, b::ODEExpr) = isequal((a.x, a.n, a.rhs), (b.x, b.n, b.rhs))

test/units.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using ModelingToolkit, Unitful
2+
using Test
3+
4+
t = Variable{u"s"}(:t)()
5+
x = Variable{u"kg"}(:x)(t)
6+
y = Variable{u"kg"}(:y)(t)
7+
D = Differential(t)
8+
9+
eq1 = x ~ y*t
10+
eq2 = x*10u"s" ~ y*t
11+
12+
@test ModelingToolkit.instantiate(t) == 1u"s"
13+
@test ModelingToolkit.instantiate(x) == 1u"kg"
14+
@test ModelingToolkit.instantiate(y) == 1u"kg"
15+
16+
@test !ModelingToolkit.validate(eq1)
17+
@test ModelingToolkit.validate(eq2)
18+
19+
eqs = [
20+
D(x) ~ y/t
21+
D(y) ~ (x*y)/(t*10u"kg")
22+
]
23+
24+
sys = ODESystem(eqs,t,[x,y],[])
25+
@test ModelingToolkit.validate(sys)

0 commit comments

Comments
 (0)