diff --git a/docs/src/basics/Composition.md b/docs/src/basics/Composition.md index 2e5d4be831..d3de71d696 100644 --- a/docs/src/basics/Composition.md +++ b/docs/src/basics/Composition.md @@ -135,16 +135,14 @@ 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 @@ -152,25 +150,19 @@ 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 diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 9f69458528..06f9cab7e1 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -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, diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 67bcbc88c0..a3b92d8b3a 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -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) @@ -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 diff --git a/src/utils.jl b/src/utils.jl index 1884a91c19..2b3cbedab0 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -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 diff --git a/test/jumpsystem.jl b/test/jumpsystem.jl index 9568990e73..a671585ff0 100644 --- a/test/jumpsystem.jl +++ b/test/jumpsystem.jl @@ -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() @@ -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 diff --git a/test/variable_scope.jl b/test/variable_scope.jl index bd1d3cb0cf..59647bf441 100644 --- a/test/variable_scope.jl +++ b/test/variable_scope.jl @@ -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 @@ -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 @@ -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