Skip to content

Commit afd55cb

Browse files
feat: support arbitrary independent variables in parse_variable
1 parent 3c728a3 commit afd55cb

File tree

2 files changed

+62
-64
lines changed

2 files changed

+62
-64
lines changed

src/systems/abstractsystem.jl

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,14 +3295,18 @@ Roughly supports the following CFG:
32953295
varname = "D(" varname ")" | arrvar | maybe_dummy_var
32963296
arrvar = maybe_dummy_var "[idxs...]"
32973297
idxs = int | int "," idxs
3298-
maybe_dummy_var = namespacedvar | namespacedvar "(t)" |
3299-
namespacedvar "(t)" "ˍ" ts | namespacedvar "ˍ" ts |
3300-
namespacedvar "ˍ" ts "(t)"
3301-
ts = "t" | "t" ts
3298+
maybe_dummy_var = namespacedvar | namespacedvar "(" iv ")" |
3299+
namespacedvar "(" iv ")" "ˍ" ts | namespacedvar "ˍ" ts |
3300+
namespacedvar "ˍ" ts "(" iv ")"
3301+
ts = iv | iv ts
33023302
namespacedvar = ident "₊" namespacedvar | ident "." namespacedvar | ident
33033303
```
3304+
3305+
Where `iv` is the independent variable, `int` is an integer and `ident` is an identifier.
33043306
"""
33053307
function parse_variable(sys::AbstractSystem, str::AbstractString)
3308+
iv = has_iv(sys) ? string(getname(get_iv(sys))) : nothing
3309+
33063310
# I'd write a regex to validate `str`, but https://xkcd.com/1171/
33073311
str = strip(str)
33083312
derivative_level = 0
@@ -3320,25 +3324,22 @@ function parse_variable(sys::AbstractSystem, str::AbstractString)
33203324
arr_idxs = map(Base.Fix1(parse, Int), eachsplit(idxs_str, ","))
33213325
end
33223326

3323-
if endswith(str, "(t)")
3324-
str = _string_view_inner(str, 0, 3)
3327+
if iv !== nothing && endswith(str, "($iv)")
3328+
str = _string_view_inner(str, 0, 2 + length(iv))
33253329
end
33263330

33273331
dummyderivative_level = 0
3328-
if (dd_idx = findfirst('ˍ', str)) !== nothing
3329-
t_idx = nextind(str, dd_idx)
3330-
while checkbounds(Bool, str, t_idx)
3331-
if str[t_idx] != 't'
3332-
throw(ArgumentError("Dummy derivative must be 'ˍ' followed by one or more 't'."))
3333-
end
3332+
if iv !== nothing && (dd_idx = findfirst('ˍ', str)) !== nothing
3333+
t_idx = findnext(iv, str, dd_idx)
3334+
while t_idx !== nothing
33343335
dummyderivative_level += 1
3335-
t_idx = nextind(str, t_idx)
3336+
t_idx = findnext(iv, str, nextind(str, last(t_idx)))
33363337
end
33373338
str = view(str, firstindex(str):prevind(str, dd_idx))
33383339
end
33393340

3340-
if endswith(str, "(t)")
3341-
str = _string_view_inner(str, 0, 3)
3341+
if iv !== nothing && endswith(str, "($iv)")
3342+
str = _string_view_inner(str, 0, 2 + length(iv))
33423343
end
33433344

33443345
cur = sys

test/variable_utils.jl

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -43,98 +43,95 @@ ts = collect_ivs([eq])
4343
@test length(res) == 3
4444
end
4545

46-
@testset "parse_variable" begin
47-
@mtkmodel Lorenz begin
46+
@testset "parse_variable with iv: $iv" for iv in [t, only(@independent_variables tt)]
47+
D = Differential(iv)
48+
function Lorenz(; name)
4849
@variables begin
49-
x(t)
50-
y(t)
51-
z(t)
50+
x(iv)
51+
y(iv)
52+
z(iv)
5253
end
5354
@parameters begin
5455
σ
5556
ρ
5657
β
5758
end
58-
@equations begin
59-
D(D(x)) ~ σ * (y - x)
60-
D(y) ~ x *- z) - y
61-
D(z) ~ x * y - β * z
62-
end
59+
sys = ODESystem(
60+
[D(D(x)) ~ σ * (y - x)
61+
D(y) ~ x *- z) - y
62+
D(z) ~ x * y - β * z], iv; name)
6363
end
64-
@mtkmodel ArrSys begin
64+
function ArrSys(; name)
6565
@variables begin
66-
x(t)[1:2]
66+
x(iv)[1:2]
6767
end
6868
@parameters begin
6969
p[1:2, 1:2]
7070
end
71-
@equations begin
72-
D(D(x)) ~ p * x
73-
end
71+
sys = ODESystem([D(D(x)) ~ p * x], iv; name)
7472
end
75-
@mtkmodel Outer begin
76-
@components begin
77-
😄 = Lorenz()
78-
arr = ArrSys()
79-
end
73+
function Outer(; name)
74+
@named 😄 = Lorenz()
75+
@named arr = ArrSys()
76+
sys = ODESystem(Equation[], iv; name, systems = [😄, arr])
8077
end
8178

8279
@mtkbuild sys = Outer()
8380
for (str, var) in [
8481
# unicode system, scalar variable
8582
("😄.x", sys.😄.x),
86-
("😄.x(t)", sys.😄.x),
83+
("😄.x($iv)", sys.😄.x),
8784
("😄₊x", sys.😄.x),
88-
("😄₊x(t)", sys.😄.x),
85+
("😄₊x($iv)", sys.😄.x),
8986
# derivative
9087
("D(😄.x)", D(sys.😄.x)),
91-
("D(😄.x(t))", D(sys.😄.x)),
88+
("D(😄.x($iv))", D(sys.😄.x)),
9289
("D(😄₊x)", D(sys.😄.x)),
93-
("D(😄₊x(t))", D(sys.😄.x)),
90+
("D(😄₊x($iv))", D(sys.😄.x)),
9491
# other derivative
95-
("😄.xˍt", D(sys.😄.x)),
96-
("😄.x(t)ˍt", D(sys.😄.x)),
97-
("😄₊xˍt", D(sys.😄.x)),
98-
("😄₊x(t)ˍt", D(sys.😄.x)),
92+
("😄.$iv", D(sys.😄.x)),
93+
("😄.x($iv$iv", D(sys.😄.x)),
94+
("😄₊$iv", D(sys.😄.x)),
95+
("😄₊x($iv$iv", D(sys.😄.x)),
9996
# scalar parameter
10097
("😄.σ", sys.😄.σ),
10198
("😄₊σ", sys.😄.σ),
10299
# array variable
103100
("arr.x", sys.arr.x),
104101
("arr₊x", sys.arr.x),
105-
("arr.x(t)", sys.arr.x),
106-
("arr₊x(t)", sys.arr.x),
102+
("arr.x($iv)", sys.arr.x),
103+
("arr₊x($iv)", sys.arr.x),
107104
# getindex
108105
("arr.x[1]", sys.arr.x[1]),
109106
("arr₊x[1]", sys.arr.x[1]),
110-
("arr.x(t)[1]", sys.arr.x[1]),
111-
("arr₊x(t)[1]", sys.arr.x[1]),
107+
("arr.x($iv)[1]", sys.arr.x[1]),
108+
("arr₊x($iv)[1]", sys.arr.x[1]),
112109
# derivative
113-
("D(arr.x(t))", D(sys.arr.x)),
114-
("D(arr₊x(t))", D(sys.arr.x)),
110+
("D(arr.x($iv))", D(sys.arr.x)),
111+
("D(arr₊x($iv))", D(sys.arr.x)),
115112
("D(arr.x[1])", D(sys.arr.x[1])),
116113
("D(arr₊x[1])", D(sys.arr.x[1])),
117-
("D(arr.x(t)[1])", D(sys.arr.x[1])),
118-
("D(arr₊x(t)[1])", D(sys.arr.x[1])),
114+
("D(arr.x($iv)[1])", D(sys.arr.x[1])),
115+
("D(arr₊x($iv)[1])", D(sys.arr.x[1])),
119116
# other derivative
120-
("arr.xˍt", D(sys.arr.x)),
121-
("arr₊xˍt", D(sys.arr.x)),
122-
("arr.xˍt(t)", D(sys.arr.x)),
123-
("arr₊xˍt(t)", D(sys.arr.x)),
124-
("arr.xˍt[1]", D(sys.arr.x[1])),
125-
("arr₊xˍt[1]", D(sys.arr.x[1])),
126-
("arr.xˍt(t)[1]", D(sys.arr.x[1])),
127-
("arr₊xˍt(t)[1]", D(sys.arr.x[1])),
128-
("arr.x(t)ˍt", D(sys.arr.x)),
129-
("arr₊x(t)ˍt", D(sys.arr.x)),
130-
("arr.x(t)ˍt[1]", D(sys.arr.x[1])),
131-
("arr₊x(t)ˍt[1]", D(sys.arr.x[1])),
117+
("arr.$iv", D(sys.arr.x)),
118+
("arr₊$iv", D(sys.arr.x)),
119+
("arr.$iv($iv)", D(sys.arr.x)),
120+
("arr₊$iv($iv)", D(sys.arr.x)),
121+
("arr.$iv[1]", D(sys.arr.x[1])),
122+
("arr₊$iv[1]", D(sys.arr.x[1])),
123+
("arr.$iv($iv)[1]", D(sys.arr.x[1])),
124+
("arr₊$iv($iv)[1]", D(sys.arr.x[1])),
125+
("arr.x($iv$iv", D(sys.arr.x)),
126+
("arr₊x($iv$iv", D(sys.arr.x)),
127+
("arr.x($iv$iv[1]", D(sys.arr.x[1])),
128+
("arr₊x($iv$iv[1]", D(sys.arr.x[1])),
132129
# array parameter
133130
("arr.p", sys.arr.p),
134131
("arr₊p", sys.arr.p),
135132
("arr.p[1, 2]", sys.arr.p[1, 2]),
136133
("arr₊p[1, 2]", sys.arr.p[1, 2])
137134
]
138-
isequal(parse_variable(sys, str), var)
135+
@test isequal(parse_variable(sys, str), var)
139136
end
140137
end

0 commit comments

Comments
 (0)