Skip to content

Commit 86a3a53

Browse files
Merge pull request #4040 from cmhyett/mtkmodel_analysis_pts
Simple bypass to allow APs to be unitless with unitful connections
2 parents d21996b + 3017d91 commit 86a3a53

File tree

3 files changed

+122
-16
lines changed

3 files changed

+122
-16
lines changed

src/systems/unit_check.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,17 @@ function _validate(terms::Vector, labels::Vector{String}; info::String = "")
213213
valid
214214
end
215215

216+
function _validate(ap::AnalysisPoint; info::String = "")
217+
is_valid = false
218+
if (ap.outputs == nothing)
219+
is_valid = true
220+
else
221+
conn_eq = connect(ap.input, ap.outputs...)
222+
is_valid = _validate(conn_eq.rhs, info=info)
223+
end
224+
return is_valid
225+
end
226+
216227
function _validate(conn::Connection; info::String = "")
217228
valid = true
218229
syss = get_systems(conn)
@@ -277,7 +288,7 @@ function validate(jumps::Vector{JumpType}, t::Symbolic)
277288
end
278289

279290
function validate(eq::Union{Inequality, Equation}; info::String = "")
280-
if typeof(eq.lhs) == Connection
291+
if typeof(eq.lhs) <: Union{Connection, AnalysisPoint}
281292
_validate(eq.rhs; info)
282293
else
283294
_validate([eq.lhs, eq.rhs], ["left", "right"]; info)

src/systems/validation.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module UnitfulUnitCheck
22

33
using ..ModelingToolkit, Symbolics, SciMLBase, Unitful, RecursiveArrayTools
44
using ..ModelingToolkit: ValidationError,
5-
ModelingToolkit, Connection, instream, JumpType, VariableUnit,
5+
ModelingToolkit, Connection, instream, JumpType, VariableUnit, AnalysisPoint,
66
get_systems,
77
Conditional, Comparison
88
using JumpProcesses: MassActionJump, ConstantRateJump, VariableRateJump
@@ -182,6 +182,17 @@ function _validate(terms::Vector, labels::Vector{String}; info::String = "")
182182
valid
183183
end
184184

185+
function _validate(ap::AnalysisPoint; info::String = "")
186+
is_valid = false
187+
if (ap.outputs == nothing)
188+
is_valid = true
189+
else
190+
conn_eq = connect(ap.input, ap.outputs...)
191+
is_valid = _validate(conn_eq.rhs, info=info)
192+
end
193+
return is_valid
194+
end
195+
185196
function _validate(conn::Connection; info::String = "")
186197
valid = true
187198
syss = get_systems(conn)
@@ -242,7 +253,7 @@ function validate(jumps::Vector{JumpType}, t::Symbolic)
242253
end
243254

244255
function validate(eq::MT.Equation; info::String = "")
245-
if typeof(eq.lhs) == Connection
256+
if typeof(eq.lhs) <: Union{AnalysisPoint, Connection}
246257
_validate(eq.rhs; info)
247258
else
248259
_validate([eq.lhs, eq.rhs], ["left", "right"]; info)

test/analysis_points.jl

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,100 @@
1-
using ModelingToolkit, ModelingToolkitStandardLibrary.Blocks, ControlSystemsBase
2-
using ModelingToolkitStandardLibrary.Mechanical.Rotational
3-
using ModelingToolkitStandardLibrary.Blocks
4-
using OrdinaryDiffEq, LinearAlgebra
5-
using Test
1+
using ModelingToolkit
62
using ModelingToolkit: t_nounits as t, D_nounits as D, AnalysisPoint, AbstractSystem
73
import ModelingToolkit as MTK
4+
using ModelingToolkitStandardLibrary
5+
using ModelingToolkitStandardLibrary.Blocks
6+
using ModelingToolkitStandardLibrary.Mechanical.Rotational
7+
using ControlSystemsBase
88
import ControlSystemsBase as CS
9+
using OrdinaryDiffEq, LinearAlgebra
10+
using Test
911
using Symbolics: NAMESPACE_SEPARATOR
12+
using Unitful
13+
14+
@testset "AnalysisPoint is ignored when verifying units" begin
15+
# no units first
16+
@mtkmodel FirstOrderTest begin
17+
@components begin
18+
in = Step()
19+
fb = Feedback()
20+
fo = SecondOrder(k = 1, w = 1, d = 0.1)
21+
end
22+
@equations begin
23+
connect(in.output, :u, fb.input1)
24+
connect(fb.output, :e, fo.input)
25+
connect(fo.output, :y, fb.input2)
26+
end
27+
end
28+
@named model = FirstOrderTest()
29+
@test model isa System
30+
31+
@connector function UnitfulOutput(; name)
32+
vars = @variables begin
33+
u(t), [unit=u"m", output=true]
34+
end
35+
return System(Equation[], t, vars, []; name)
36+
end
37+
@connector function UnitfulInput(; name)
38+
vars = @variables begin
39+
u(t), [unit=u"m", input=true]
40+
end
41+
return System(Equation[], t, vars, []; name)
42+
end
43+
@component function UnitfulBlock(; name)
44+
pars = @parameters begin
45+
offset, [unit=u"m"]
46+
start_time
47+
height, [unit=u"m"]
48+
duration
49+
end
50+
systems = @named begin
51+
output = UnitfulOutput()
52+
end
53+
eqs = [
54+
output.u ~ offset + height*(0.5 + (1/pi)*atan(1e5*(t - start_time)))
55+
]
56+
return System(eqs, t, [], pars; systems, name)
57+
end
58+
@mtkmodel TestAPAroundUnits begin
59+
@components begin
60+
input = UnitfulInput()
61+
end
62+
@variables begin
63+
output(t), [output=true, unit=u"m^2"]
64+
end
65+
@components begin
66+
ub = UnitfulBlock()
67+
end
68+
@equations begin
69+
connect(ub.output, :ap, input)
70+
output ~ input.u^2
71+
end
72+
end
73+
@named sys = TestAPAroundUnits()
74+
@test sys isa System
75+
76+
@mtkmodel TestAPWithNoOutputs begin
77+
@components begin
78+
input = UnitfulInput()
79+
end
80+
@variables begin
81+
output(t), [output=true, unit=u"m^2"]
82+
end
83+
@components begin
84+
ub = UnitfulBlock()
85+
end
86+
@equations begin
87+
connect(ub.output, :ap, input)
88+
output ~ input.u^2
89+
end
90+
end
91+
@named sys2 = TestAPWithNoOutputs()
92+
@test sys2 isa System
93+
end
1094

1195
@testset "AnalysisPoint is lowered to `connect`" begin
1296
@named P = FirstOrder(k = 1, T = 1)
13-
@named C = Gain(; k = -1)
97+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = -1)
1498

1599
ap = AnalysisPoint(:plant_input)
16100
eqs = [connect(P.output, C.input)
@@ -30,7 +114,7 @@ end
30114

31115
@testset "Inverse causality throws a warning" begin
32116
@named P = FirstOrder(k = 1, T = 1)
33-
@named C = Gain(; k = -1)
117+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = -1)
34118

35119
ap = AnalysisPoint(:plant_input)
36120
@test_warn ["1-th argument", "plant_input", "not a output"] connect(
@@ -41,7 +125,7 @@ end
41125
# also tests `connect(input, name::Symbol, outputs...)` syntax
42126
@testset "AnalysisPoint is accessible via `getproperty`" begin
43127
@named P = FirstOrder(k = 1, T = 1)
44-
@named C = Gain(; k = -1)
128+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = -1)
45129

46130
eqs = [connect(P.output, C.input), connect(C.output, :plant_input, P.input)]
47131
sys_ap = System(eqs, t, systems = [P, C], name = :hej)
@@ -61,7 +145,7 @@ end
61145
### Ported from MTKStdlib
62146

63147
@named P = FirstOrder(k = 1, T = 1)
64-
@named C = Gain(; k = -1)
148+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = -1)
65149

66150
ap = AnalysisPoint(:plant_input)
67151
eqs = [connect(P.output, C.input), connect(C.output, ap, P.input)]
@@ -266,7 +350,7 @@ end
266350

267351
@testset "Duplicate `connect` statements across subsystems with AP transforms - standard `connect`" begin
268352
@named P = FirstOrder(k = 1, T = 1)
269-
@named C = Gain(; k = 1)
353+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = 1)
270354
@named add = Blocks.Add(k2 = -1)
271355

272356
eqs = [connect(P.output, :plant_output, add.input2)
@@ -302,7 +386,7 @@ end
302386

303387
@testset "Duplicate `connect` statements across subsystems with AP transforms - causal variable `connect`" begin
304388
@named P = FirstOrder(k = 1, T = 1)
305-
@named C = Gain(; k = 1)
389+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = 1)
306390
@named add = Blocks.Add(k2 = -1)
307391

308392
eqs = [connect(P.output.u, :plant_output, add.input2.u)
@@ -338,7 +422,7 @@ end
338422

339423
@testset "Duplicate `connect` statements across subsystems with AP transforms - mixed `connect`" begin
340424
@named P = FirstOrder(k = 1, T = 1)
341-
@named C = Gain(; k = 1)
425+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = 1)
342426
@named add = Blocks.Add(k2 = -1)
343427

344428
eqs = [connect(P.output.u, :plant_output, add.input2.u)
@@ -460,7 +544,7 @@ end
460544

461545
@testset "multiple analysis points" begin
462546
@named P = FirstOrder(k = 1, T = 1)
463-
@named C = Gain(; k = 1)
547+
@named C = ModelingToolkitStandardLibrary.Blocks.Gain(; k = 1)
464548
@named add = Blocks.Add(k2 = -1)
465549

466550
eqs = [connect(P.output, :plant_output, add.input2)

0 commit comments

Comments
 (0)