Skip to content

refactor: remove DelayParentScope #3564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions docs/src/basics/Composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,42 +135,34 @@ sys.y = u * 1.1
In a hierarchical system, variables of the subsystem get namespaced by the name of the system they are in. This prevents naming clashes, but also enforces that every unknown and parameter is local to the subsystem it is used in. In some cases it might be desirable to have variables and parameters that are shared between subsystems, or even global. This can be accomplished as follows.

```julia
@parameters a b c d e f
@parameters a b c d

# a is a local variable
b = ParentScope(b) # b is a variable that belongs to one level up in the hierarchy
c = ParentScope(ParentScope(c)) # ParentScope can be nested
d = DelayParentScope(d) # skips one level before applying ParentScope
e = DelayParentScope(e, 2) # second argument allows skipping N levels
f = GlobalScope(f)
d = GlobalScope(d)

p = [a, b, c, d, e, f]
p = [a, b, c, d]

level0 = ODESystem(Equation[], t, [], p; name = :level0)
level1 = ODESystem(Equation[], t, [], []; name = :level1) ∘ level0
parameters(level1)
#level0₊a
#b
#c
#level0₊d
#level0₊e
#f
#d
level2 = ODESystem(Equation[], t, [], []; name = :level2) ∘ level1
parameters(level2)
#level1₊level0₊a
#level1₊b
#c
#level0₊d
#level1₊level0₊e
#f
#d
level3 = ODESystem(Equation[], t, [], []; name = :level3) ∘ level2
parameters(level3)
#level2₊level1₊level0₊a
#level2₊level1₊b
#level2₊c
#level2₊level0₊d
#level1₊level0₊e
#f
#d
```

## Structural Simplify
Expand Down
2 changes: 1 addition & 1 deletion src/ModelingToolkit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ export PDESystem
export Differential, expand_derivatives, @derivatives
export Equation, ConstrainedEquation
export Term, Sym
export SymScope, LocalScope, ParentScope, DelayParentScope, GlobalScope
export SymScope, LocalScope, ParentScope, GlobalScope
export independent_variable, equations, controls, observed, full_equations
export initialization_equations, guesses, defaults, parameter_dependencies, hierarchy
export structural_simplify, expand_connections, linearize, linearization_function,
Expand Down
58 changes: 0 additions & 58 deletions src/systems/abstractsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1189,55 +1189,6 @@ function ParentScope(sym::Union{Num, Symbolic, Symbolics.Arr{Num}})
end
end

"""
$(TYPEDEF)

Denotes that a variable belongs to a system that is at least `N + 1` levels up in the
hierarchy from the system whose equations it is involved in. It is namespaced by the
first `N` parents and not namespaced by the `N+1`th parent in the hierarchy. The scope
of the variable after this point is given by `parent`.

In other words, this scope delays applying `ParentScope` by `N` levels, and applies
`LocalScope` in the meantime.

# Fields

$(TYPEDFIELDS)
"""
struct DelayParentScope <: SymScope
parent::SymScope
N::Int
end

"""
$(TYPEDSIGNATURES)

Apply `DelayParentScope` to `sym`, with a delay of `N` and `parent` being `LocalScope`.
"""
function DelayParentScope(sym::Union{Num, Symbolic, Symbolics.Arr{Num}}, N)
Base.depwarn(
"`DelayParentScope` is deprecated and will be removed soon", :DelayParentScope)
apply_to_variables(sym) do sym
if iscall(sym) && operation(sym) == getindex
args = arguments(sym)
a1 = setmetadata(args[1], SymScope,
DelayParentScope(getmetadata(value(args[1]), SymScope, LocalScope()), N))
maketerm(typeof(sym), operation(sym), [a1, args[2:end]...],
metadata(sym))
else
setmetadata(sym, SymScope,
DelayParentScope(getmetadata(value(sym), SymScope, LocalScope()), N))
end
end
end

"""
$(TYPEDSIGNATURES)

Apply `DelayParentScope` to `sym`, with a delay of `1` and `parent` being `LocalScope`.
"""
DelayParentScope(sym::Union{Num, Symbolic, Symbolics.Arr{Num}}) = DelayParentScope(sym, 1)

"""
$(TYPEDEF)

Expand Down Expand Up @@ -1290,15 +1241,6 @@ function renamespace(sys, x)
rename(x, renamespace(getname(sys), getname(x)))::T
elseif scope isa ParentScope
setmetadata(x, SymScope, scope.parent)::T
elseif scope isa DelayParentScope
if scope.N > 0
x = setmetadata(x, SymScope,
DelayParentScope(scope.parent, scope.N - 1))
rename(x, renamespace(getname(sys), getname(x)))::T
else
#rename(x, renamespace(getname(sys), getname(x)))
setmetadata(x, SymScope, scope.parent)::T
end
else # GlobalScope
x::T
end
Expand Down
2 changes: 0 additions & 2 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,6 @@ function check_scope_depth(scope, depth)
return depth == 0
elseif scope isa ParentScope
return depth > 0 && check_scope_depth(scope.parent, depth - 1)
elseif scope isa DelayParentScope
return depth >= scope.N && check_scope_depth(scope.parent, depth - scope.N - 1)
elseif scope isa GlobalScope
return depth == -1
end
Expand Down
22 changes: 10 additions & 12 deletions test/jumpsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,22 +378,20 @@ end

# scoping tests
let
@variables x1(t) x2(t) x3(t) x4(t) x5(t)
@variables x1(t) x2(t) x3(t) x4(t)
x2 = ParentScope(x2)
x3 = ParentScope(ParentScope(x3))
x4 = DelayParentScope(x4)
x5 = GlobalScope(x5)
@parameters p1 p2 p3 p4 p5
x4 = GlobalScope(x4)
@parameters p1 p2 p3 p4
p2 = ParentScope(p2)
p3 = ParentScope(ParentScope(p3))
p4 = DelayParentScope(p4)
p5 = GlobalScope(p5)
p4 = GlobalScope(p4)

j1 = ConstantRateJump(p1, [x1 ~ x1 + 1])
j2 = MassActionJump(p2, [x2 => 1], [x3 => -1])
j3 = VariableRateJump(p3, [x3 ~ x3 + 1, x4 ~ x4 + 1])
j4 = MassActionJump(p4 * p5, [x1 => 1, x5 => 1], [x1 => -1, x5 => -1, x2 => 1])
@named js = JumpSystem([j1, j2, j3, j4], t, [x1, x2, x3, x4, x5], [p1, p2, p3, p4, p5])
j4 = MassActionJump(p4 * p4, [x1 => 1, x4 => 1], [x1 => -1, x4 => -1, x2 => 1])
@named js = JumpSystem([j1, j2, j3, j4], t, [x1, x2, x3, x4], [p1, p2, p3, p4])

us = Set()
ps = Set()
Expand All @@ -414,13 +412,13 @@ let

empty!.((us, ps))
MT.collect_scoped_vars!(us, ps, js, iv; depth = 2)
@test issetequal(us, [x3, x4])
@test issetequal(ps, [p3, p4])
@test issetequal(us, [x3])
@test issetequal(ps, [p3])

empty!.((us, ps))
MT.collect_scoped_vars!(us, ps, js, iv; depth = -1)
@test issetequal(us, [x5])
@test issetequal(ps, [p5])
@test issetequal(us, [x4])
@test issetequal(ps, [p4])
end

# PDMP test
Expand Down
80 changes: 36 additions & 44 deletions test/variable_scope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ end
@test renamed([:foo :bar :baz], c) == Symbol("foo₊c")
@test renamed([:foo :bar :baz], d) == :d

@parameters a b c d e f
@parameters a b c d
p = [a
ParentScope(b)
ParentScope(ParentScope(c))
DelayParentScope(d)
DelayParentScope(e, 2)
GlobalScope(f)]
GlobalScope(d)]

level0 = ODESystem(Equation[], t, [], p; name = :level0)
level1 = ODESystem(Equation[], t, [], []; name = :level1) ∘ level0
Expand All @@ -69,9 +67,7 @@ ps = ModelingToolkit.getname.(parameters(level3))
@test isequal(ps[1], :level2₊level1₊level0₊a)
@test isequal(ps[2], :level2₊level1₊b)
@test isequal(ps[3], :level2₊c)
@test isequal(ps[4], :level2₊level0₊d)
@test isequal(ps[5], :level1₊level0₊e)
@test isequal(ps[6], :f)
@test isequal(ps[4], :d)

# Issue@2252
# Tests from PR#2354
Expand Down Expand Up @@ -102,40 +98,36 @@ defs = ModelingToolkit.defaults(bar)
@test defs[bar.p] == 2
@test isequal(defs[bar.foo.p], bar.p)

# Issue#3101
@variables x1(t) x2(t) x3(t) x4(t) x5(t)
x2 = ParentScope(x2)
x3 = ParentScope(ParentScope(x3))
x4 = DelayParentScope(x4)
x5 = GlobalScope(x5)
@parameters p1 p2 p3 p4 p5
p2 = ParentScope(p2)
p3 = ParentScope(ParentScope(p3))
p4 = DelayParentScope(p4)
p5 = GlobalScope(p5)

@named sys1 = ODESystem([D(x1) ~ p1, D(x2) ~ p2, D(x3) ~ p3, D(x4) ~ p4, D(x5) ~ p5], t)
@test isequal(x1, only(unknowns(sys1)))
@test isequal(p1, only(parameters(sys1)))
@named sys2 = ODESystem(Equation[], t; systems = [sys1])
@test length(unknowns(sys2)) == 2
@test any(isequal(x2), unknowns(sys2))
@test length(parameters(sys2)) == 2
@test any(isequal(p2), parameters(sys2))
@named sys3 = ODESystem(Equation[], t)
sys3 = sys3 ∘ sys2
@test length(unknowns(sys3)) == 4
@test any(isequal(x3), unknowns(sys3))
@test any(isequal(ModelingToolkit.renamespace(sys1, x4)), unknowns(sys3))
@test length(parameters(sys3)) == 4
@test any(isequal(p3), parameters(sys3))
@test any(isequal(ModelingToolkit.renamespace(sys1, p4)), parameters(sys3))
sys4 = complete(sys3)
@test length(unknowns(sys3)) == 4
@test length(parameters(sys4)) == 5
@test any(isequal(p5), parameters(sys4))
sys5 = structural_simplify(sys3)
@test length(unknowns(sys5)) == 5
@test any(isequal(x5), unknowns(sys5))
@test length(parameters(sys5)) == 5
@test any(isequal(p5), parameters(sys5))
@testset "Issue#3101" begin
@variables x1(t) x2(t) x3(t) x4(t)
x2 = ParentScope(x2)
x3 = ParentScope(ParentScope(x3))
x4 = GlobalScope(x4)
@parameters p1 p2 p3 p4
p2 = ParentScope(p2)
p3 = ParentScope(ParentScope(p3))
p4 = GlobalScope(p4)

@named sys1 = ODESystem([D(x1) ~ p1, D(x2) ~ p2, D(x3) ~ p3, D(x4) ~ p4], t)
@test isequal(x1, only(unknowns(sys1)))
@test isequal(p1, only(parameters(sys1)))
@named sys2 = ODESystem(Equation[], t; systems = [sys1])
@test length(unknowns(sys2)) == 2
@test any(isequal(x2), unknowns(sys2))
@test length(parameters(sys2)) == 2
@test any(isequal(p2), parameters(sys2))
@named sys3 = ODESystem(Equation[], t)
sys3 = sys3 ∘ sys2
@test length(unknowns(sys3)) == 3
@test any(isequal(x3), unknowns(sys3))
@test length(parameters(sys3)) == 3
@test any(isequal(p3), parameters(sys3))
sys4 = complete(sys3)
@test length(unknowns(sys4)) == 3
@test length(parameters(sys4)) == 4
sys5 = structural_simplify(sys3)
@test length(unknowns(sys5)) == 4
@test any(isequal(x4), unknowns(sys5))
@test length(parameters(sys5)) == 4
@test any(isequal(p4), parameters(sys5))
end
Loading