Skip to content

Commit 9cae625

Browse files
committed
Merge branch 'master' into sm/refactor
2 parents 3b0ec36 + 89fdee8 commit 9cae625

27 files changed

+160
-76
lines changed

docs/src/basics/AbstractSystem.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ It establishes a common set of functionality that is used between systems
77
from ODEs and chemical reactions, allowing users to have a common framework for
88
model manipulation and compilation.
99

10+
### Subtypes
11+
12+
There are three immediate subtypes of `AbstractSystem`, classified by how many independent variables each type has:
13+
* `AbstractTimeIndependentSystem`: has no independent variable (eg: `NonlinearSystem`)
14+
* `AbstractTimeDependentSystem`: has a single independent variable (eg: `ODESystem`)
15+
* `AbstractMultivariateSystem`: may have multiple independent variables (eg: `PDESystem`)
16+
1017
## Constructors and Naming
1118

1219
The `AbstractSystem` interface has a consistent method for constructing systems.
@@ -50,12 +57,11 @@ Optionally, a system could have:
5057
- `observed(sys)`: All observed equations of the system and its subsystems.
5158
- `get_observed(sys)`: Observed equations of the current-level system.
5259
- `get_defaults(sys)`: A `Dict` that maps variables into their default values.
53-
- `independent_variable(sys)`: The independent variable of a system.
60+
- `independent_variables(sys)`: The independent variables of a system.
5461
- `get_noiseeqs(sys)`: Noise equations of the current-level system.
5562

56-
Note that there's `get_iv(sys)`, but it is not advised to use, since it errors
57-
when the system has no field `iv`. `independent_variable(sys)` returns `nothing`
58-
for `NonlinearSystem`s.
63+
Note that if you know a system is an `AbstractTimeDependentSystem` you could use `get_iv` to get the
64+
unique independent variable directly, rather than using `independenent_variables(sys)[1]`, which is clunky and may cause problems if `sys` is an `AbstractMultivariateSystem` because there may be more than one independent variable. `AbstractTimeIndependentSystem`s do not have a method `get_iv`, and `independent_variables(sys)` will return a size-zero result for such. For an `AbstractMultivariateSystem`, `get_ivs` is equivalent.
5965

6066
A system could also have caches:
6167

docs/src/systems/JumpSystem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ JumpSystem
1111
- `get_eqs(sys)` or `equations(sys)`: The equations that define the jump system.
1212
- `get_states(sys)` or `states(sys)`: The set of states in the jump system.
1313
- `get_ps(sys)` or `parameters(sys)`: The parameters of the jump system.
14-
- `independent_variable(sys)`: The independent variable of the jump system.
14+
- `get_iv(sys)`: The independent variable of the jump system.
1515

1616
## Transformations
1717

docs/src/systems/ODESystem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ODESystem
1111
- `get_eqs(sys)` or `equations(sys)`: The equations that define the ODE.
1212
- `get_states(sys)` or `states(sys)`: The set of states in the ODE.
1313
- `get_ps(sys)` or `parameters(sys)`: The parameters of the ODE.
14-
- `independent_variable(sys)`: The independent variable of the ODE.
14+
- `get_iv(sys)`: The independent variable of the ODE.
1515

1616
## Transformations
1717

docs/src/systems/ReactionSystem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ ReactionSystem
4949
- `get_eqs(sys)` or `equations(sys)`: The reactions that define the system.
5050
- `get_states(sys)` or `states(sys)`: The set of chemical species in the system.
5151
- `get_ps(sys)` or `parameters(sys)`: The parameters of the system.
52-
- `independent_variable(sys)`: The independent variable of the
52+
- `get_iv(sys)`: The independent variable of the
5353
reaction system, usually time.
5454

5555
## Query Functions

docs/src/systems/SDESystem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sde = SDESystem(ode, noiseeqs)
1717
- `get_eqs(sys)` or `equations(sys)`: The equations that define the SDE.
1818
- `get_states(sys)` or `states(sys)`: The set of states in the SDE.
1919
- `get_ps(sys)` or `parameters(sys)`: The parameters of the SDE.
20-
- `independent_variable(sys)`: The independent variable of the SDE.
20+
- `get_iv(sys)`: The independent variable of the SDE.
2121

2222
## Transformations
2323

src/ModelingToolkit.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ $(TYPEDEF)
7878
TODO
7979
"""
8080
abstract type AbstractSystem end
81-
abstract type AbstractODESystem <: AbstractSystem end
81+
abstract type AbstractTimeDependentSystem <: AbstractSystem end
82+
abstract type AbstractTimeIndependentSystem <: AbstractSystem end
83+
abstract type AbstractODESystem <: AbstractTimeDependentSystem end
84+
abstract type AbstractMultivariateSystem <: AbstractSystem end
8285

8386
"""
8487
$(TYPEDSIGNATURES)
@@ -87,6 +90,8 @@ Get the set of independent variables for the given system.
8790
"""
8891
function independent_variables end
8992

93+
function independent_variable end
94+
9095
"""
9196
$(TYPEDSIGNATURES)
9297
@@ -149,6 +154,7 @@ end
149154

150155
struct Flow end
151156

157+
export AbstractTimeDependentSystem, AbstractTimeIndependentSystem, AbstractMultivariateSystem
152158
export ODESystem, ODEFunction, ODEFunctionExpr, ODEProblemExpr, convert_system
153159
export DAEFunctionExpr, DAEProblemExpr
154160
export SDESystem, SDEFunction, SDEFunctionExpr, SDESystemExpr
@@ -171,7 +177,7 @@ export Differential, expand_derivatives, @derivatives
171177
export Equation, ConstrainedEquation
172178
export Term, Sym
173179
export SymScope, LocalScope, ParentScope, GlobalScope
174-
export independent_variable, states, parameters, equations, controls, observed, structure
180+
export independent_variables, independent_variable, states, parameters, equations, controls, observed, structure
175181
export structural_simplify
176182
export DiscreteSystem, DiscreteProblem
177183

src/structural_transformation/StructuralTransformations.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ using SymbolicUtils.Rewriters
1313
using SymbolicUtils: similarterm, istree
1414

1515
using ModelingToolkit
16-
using ModelingToolkit: ODESystem, AbstractSystem, var_from_nested_derivative,
17-
Differential, states, equations, vars, Symbolic,
18-
diff2term, value, operation, arguments, Sym, Term,
19-
simplify, solve_for, isdiffeq, isdifferential,
16+
using ModelingToolkit: ODESystem, AbstractSystem,var_from_nested_derivative, Differential,
17+
states, equations, vars, Symbolic, diff2term, value,
18+
operation, arguments, Sym, Term, simplify, solve_for,
19+
isdiffeq, isdifferential, get_structure, get_iv, independent_variables,
2020
get_structure, defaults, InvalidSystemException,
2121
ExtraEquationsSystemException,
2222
ExtraVariablesSystemException

src/structural_transformation/codegen.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ function build_torn_function(
208208
out
209209
DestructuredArgs(states, inbounds=!checkbounds)
210210
DestructuredArgs(parameters(sys), inbounds=!checkbounds)
211-
independent_variable(sys)
211+
independent_variables(sys)
212212
],
213213
[],
214214
Let(
@@ -312,7 +312,7 @@ function build_observed_function(
312312
[
313313
DestructuredArgs(diffvars, inbounds=!checkbounds)
314314
DestructuredArgs(parameters(sys), inbounds=!checkbounds)
315-
independent_variable(sys)
315+
independent_variables(sys)
316316
],
317317
[],
318318
Let(

src/structural_transformation/pantelides.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
### Reassemble: structural information -> system
33
###
44

5-
function pantelides_reassemble(sys, eqassoc, assign)
5+
function pantelides_reassemble(sys::ODESystem, eqassoc, assign)
66
s = structure(sys)
77
@unpack fullvars, varassoc = s
88
# Step 1: write derivative equations
@@ -15,7 +15,7 @@ function pantelides_reassemble(sys, eqassoc, assign)
1515
fill!(out_vars, nothing)
1616
out_vars[1:length(fullvars)] .= fullvars
1717

18-
D = Differential(independent_variable(sys))
18+
D = Differential(get_iv(sys))
1919

2020
for (i, v) in enumerate(varassoc)
2121
# fullvars[v] = D(fullvars[i])
@@ -75,11 +75,11 @@ end
7575
7676
Perform Pantelides algorithm.
7777
"""
78-
function pantelides!(sys; maxiters = 8000)
78+
function pantelides!(sys::ODESystem; maxiters = 8000)
7979
s = structure(sys)
8080
# D(j) = assoc[j]
8181
@unpack graph, fullvars, varassoc = s
82-
iv = independent_variable(sys)
82+
iv = get_iv(sys)
8383
neqs = nsrcs(graph)
8484
nvars = length(varassoc)
8585
vcolor = falses(nvars)

src/systems/abstractsystem.jl

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
```julia
3-
calculate_tgrad(sys::AbstractSystem)
3+
calculate_tgrad(sys::AbstractTimeDependentSystem)
44
```
55
66
Calculate the time gradient of a system.
@@ -72,7 +72,7 @@ function calculate_hessian end
7272

7373
"""
7474
```julia
75-
generate_tgrad(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; kwargs...)
75+
generate_tgrad(sys::AbstractTimeDependentSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; kwargs...)
7676
```
7777
7878
Generates a function for the time gradient of a system. Extra arguments control
@@ -131,7 +131,28 @@ function generate_function end
131131

132132
Base.nameof(sys::AbstractSystem) = getfield(sys, :name)
133133

134-
independent_variable(sys::AbstractSystem) = isdefined(sys, :iv) ? getfield(sys, :iv) : nothing
134+
#Deprecated
135+
function independent_variable(sys::AbstractSystem)
136+
Base.depwarn("`independent_variable` is deprecated. Use `get_iv` or `independent_variables` instead.",:independent_variable)
137+
isdefined(sys, :iv) ? getfield(sys, :iv) : nothing
138+
end
139+
140+
#Treat the result as a vector of symbols always
141+
function independent_variables(sys::AbstractSystem)
142+
systype = typeof(sys)
143+
@warn "Please declare ($systype) as a subtype of `AbstractTimeDependentSystem`, `AbstractTimeIndependentSystem` or `AbstractMultivariateSystem`."
144+
if isdefined(sys, :iv)
145+
return [getfield(sys, :iv)]
146+
elseif isdefined(sys, :ivs)
147+
return getfield(sys,:ivs)
148+
else
149+
return []
150+
end
151+
end
152+
153+
independent_variables(sys::AbstractTimeDependentSystem) = [getfield(sys, :iv)]
154+
independent_variables(sys::AbstractTimeIndependentSystem) = []
155+
independent_variables(sys::AbstractMultivariateSystem) = getfield(sys, :ivs)
135156

136157
function structure(sys::AbstractSystem)
137158
s = get_structure(sys)
@@ -365,9 +386,9 @@ function namespace_assignment(eq::Assignment, sys)
365386
end
366387

367388
function namespace_expr(O, sys) where {T}
368-
iv = independent_variable(sys)
389+
ivs = independent_variables(sys)
369390
O = unwrap(O)
370-
if isequal(O, iv)
391+
if any(isequal(O), ivs)
371392
return O
372393
elseif isvariable(O)
373394
renamespace(sys, O)
@@ -547,9 +568,10 @@ function toexpr(sys::AbstractSystem)
547568
stmt = expr.args
548569

549570
name = Meta.quot(nameof(sys))
550-
iv = independent_variable(sys)
571+
ivs = independent_variables(sys)
551572
ivname = gensym(:iv)
552-
if iv !== nothing
573+
for iv in ivs
574+
ivname = gensym(:iv)
553575
push!(stmt, :($ivname = (@variables $(getname(iv)))[1]))
554576
end
555577

@@ -569,9 +591,12 @@ function toexpr(sys::AbstractSystem)
569591
defs_name = push_defaults!(stmt, defaults(sys), var2name)
570592

571593
if sys isa ODESystem
572-
push!(stmt, :($ODESystem($eqs_name, $ivname, $stsname, $psname; defaults=$defs_name, name=$name)))
594+
iv = get_iv(sys)
595+
ivname = gensym(:iv)
596+
push!(stmt, :($ivname = (@variables $(getname(iv)))[1]))
597+
push!(stmt, :($ODESystem($eqs_name, $ivname, $stsname, $psname; defaults = $defs_name, name=$name)))
573598
elseif sys isa NonlinearSystem
574-
push!(stmt, :($NonlinearSystem($eqs_name, $stsname, $psname; defaults=$defs_name, name=$name)))
599+
push!(stmt, :($NonlinearSystem($eqs_name, $stsname, $psname; defaults = $defs_name, name=$name)))
575600
end
576601

577602
striplines(expr) # keeping the line numbers is never helpful
@@ -928,7 +953,7 @@ function Base.hash(sys::AbstractSystem, s::UInt)
928953
s = foldr(hash, get_eqs(sys), init=s)
929954
end
930955
s = foldr(hash, get_observed(sys), init=s)
931-
s = hash(independent_variable(sys), s)
956+
s = hash(independent_variables(sys), s)
932957
return s
933958
end
934959

@@ -940,11 +965,13 @@ by default.
940965
"""
941966
function extend(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol=nameof(sys))
942967
T = SciMLBase.parameterless_type(basesys)
943-
iv = independent_variable(basesys)
944-
if iv === nothing
968+
ivs = independent_variables(basesys)
969+
if length(ivs) == 0
945970
sys = convert_system(T, sys)
971+
elseif length(ivs) == 1
972+
sys = convert_system(T, sys, ivs[1])
946973
else
947-
sys = convert_system(T, sys, iv)
974+
throw("Extending multivariate systems is not supported")
948975
end
949976

950977
eqs = union(equations(basesys), equations(sys))
@@ -954,10 +981,10 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol=nameo
954981
defs = merge(defaults(basesys), defaults(sys)) # prefer `sys`
955982
syss = union(get_systems(basesys), get_systems(sys))
956983

957-
if iv === nothing
958-
T(eqs, sts, ps, observed=obs, defaults=defs, name=name, systems=syss)
959-
else
960-
T(eqs, iv, sts, ps, observed=obs, defaults=defs, name=name, systems=syss)
984+
if length(ivs) == 0
985+
T(eqs, sts, ps, observed = obs, defaults = defs, name=name, systems = syss)
986+
elseif length(ivs) == 1
987+
T(eqs, ivs[1], sts, ps, observed = obs, defaults = defs, name = name, systems = syss)
961988
end
962989
end
963990

src/systems/control/controlsystem.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
abstract type AbstractControlSystem <: AbstractSystem end
1+
abstract type AbstractControlSystem <: AbstractTimeDependentSystem end
22

33
function namespace_controls(sys::AbstractControlSystem)
44
[rename(x,renamespace(nameof(sys),nameof(x))) for x in controls(sys)]

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ check_derivative_variables(eq) = check_operator_variables(eq, Differential)
8383
function generate_function(
8484
sys::AbstractODESystem, dvs = states(sys), ps = parameters(sys);
8585
implicit_dae=false,
86-
ddvs=implicit_dae ? map(Differential(independent_variable(sys)), dvs) : nothing,
86+
ddvs=implicit_dae ? map(Differential(get_iv(sys)), dvs) : nothing,
8787
kwargs...
8888
)
8989
# optimization
@@ -155,15 +155,15 @@ function generate_difference_cb(sys::ODESystem, dvs = states(sys), ps = paramete
155155
PeriodicCallback(cb_affect!, first(dts))
156156
end
157157

158-
function time_varying_as_func(x, sys)
158+
function time_varying_as_func(x, sys::AbstractTimeDependentSystem)
159159
# if something is not x(t) (the current state)
160160
# but is `x(t-1)` or something like that, pass in `x` as a callable function rather
161161
# than pass in a value in place of x(t).
162162
#
163163
# This is done by just making `x` the argument of the function.
164164
if istree(x) &&
165165
operation(x) isa Sym &&
166-
!(length(arguments(x)) == 1 && isequal(arguments(x)[1], independent_variable(sys)))
166+
!(length(arguments(x)) == 1 && isequal(arguments(x)[1], get_iv(sys)))
167167
return operation(x)
168168
end
169169
return x
@@ -299,7 +299,7 @@ function DiffEqBase.ODEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),
299299
mass_matrix = _M,
300300
jac_prototype = jac_prototype,
301301
syms = Symbol.(states(sys)),
302-
indepsym = Symbol(independent_variable(sys)),
302+
indepsym = Symbol(get_iv(sys)),
303303
observed = observedfun,
304304
)
305305
end
@@ -320,7 +320,7 @@ respectively.
320320
"""
321321
function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),
322322
ps = parameters(sys), u0 = nothing;
323-
ddvs=map(diff2term Differential(independent_variable(sys)), dvs),
323+
ddvs=map(diff2term Differential(get_iv(sys)), dvs),
324324
version = nothing,
325325
#=
326326
tgrad=false,
@@ -356,7 +356,7 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),
356356
f,
357357
syms = Symbol.(dvs),
358358
# missing fields in `DAEFunction`
359-
#indepsym = Symbol(independent_variable(sys)),
359+
#indepsym = Symbol(get_iv(sys)),
360360
#observed = observedfun,
361361
)
362362
end
@@ -453,7 +453,7 @@ function ODEFunctionExpr{iip}(sys::AbstractODESystem, dvs = states(sys),
453453
mass_matrix = M,
454454
jac_prototype = $jp_expr,
455455
syms = $(Symbol.(states(sys))),
456-
indepsym = $(QuoteNode(Symbol(independent_variable(sys)))),
456+
indepsym = $(QuoteNode(Symbol(get_iv(sys)))),
457457
)
458458
end
459459
!linenumbers ? striplines(ex) : ex
@@ -472,7 +472,7 @@ function process_DEProblem(constructor, sys::AbstractODESystem,u0map,parammap;
472472
dvs = states(sys)
473473
ps = parameters(sys)
474474
defs = defaults(sys)
475-
iv = independent_variable(sys)
475+
iv = get_iv(sys)
476476
if parammap isa Dict
477477
u0defs = merge(parammap, defs)
478478
elseif eltype(parammap) <: Pair

src/systems/diffeqs/basic_transformations.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ Optimal Transport Approach
4545
Abhishek Halder, Kooktae Lee, and Raktim Bhattacharya
4646
https://abhishekhalder.bitbucket.io/F16ACC2013Final.pdf
4747
"""
48-
function liouville_transform(sys)
49-
t = independent_variable(sys)
48+
function liouville_transform(sys::AbstractODESystem)
49+
t = get_iv(sys)
5050
@variables trJ
5151
D = ModelingToolkit.Differential(t)
5252
neweq = D(trJ) ~ trJ*-tr(calculate_jacobian(sys))

src/systems/diffeqs/first_order_transform.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Takes a Nth order ODESystem and returns a new ODESystem written in first order
55
form by defining new variables which represent the N-1 derivatives.
66
"""
77
function ode_order_lowering(sys::ODESystem)
8-
iv = independent_variable(sys)
8+
iv = get_iv(sys)
99
eqs_lowered, new_vars = ode_order_lowering(equations(sys), iv, states(sys))
1010
@set! sys.eqs = eqs_lowered
1111
@set! sys.states = new_vars

0 commit comments

Comments
 (0)