Skip to content

Expand the connector in simplification time #1314

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

Closed
wants to merge 21 commits into from
Closed
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
14 changes: 1 addition & 13 deletions examples/electrical_components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,10 @@ using ModelingToolkit, OrdinaryDiffEq

@parameters t
@connector function Pin(;name)
sts = @variables v(t)=1.0 i(t)=1.0
sts = @variables v(t)=1.0 i(t)=1.0 [connect = Flow]
ODESystem(Equation[], t, sts, []; name=name)
end

function ModelingToolkit.connect(::Type{Pin}, ps...)
eqs = [
0 ~ sum(p->p.i, ps) # KCL
]
# KVL
for i in 1:length(ps)-1
push!(eqs, ps[i].v ~ ps[i+1].v)
end

return eqs
end

function Ground(;name)
@named g = Pin()
eqs = [g.v ~ 0]
Expand Down
3 changes: 2 additions & 1 deletion examples/rc_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ V = 1.0
rc_eqs = [
connect(source.p, resistor.p)
connect(resistor.n, capacitor.p)
connect(capacitor.n, source.n, ground.g)
connect(capacitor.n, source.n)
connect(capacitor.n, ground.g)
]

@named rc_model = ODESystem(rc_eqs, t)
Expand Down
3 changes: 2 additions & 1 deletion examples/serial_inductor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ eqs = [
connect(source.p, resistor.p)
connect(resistor.n, inductor1.p)
connect(inductor1.n, inductor2.p)
connect(source.n, inductor2.n, ground.g)
connect(source.n, inductor2.n)
connect(inductor2.n, ground.g)
]

@named ll_model = ODESystem(eqs, t)
Expand Down
10 changes: 5 additions & 5 deletions src/ModelingToolkit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ if !isdefined(Graphs, :IncrementalCycleTracker)
end

include("systems/abstractsystem.jl")
include("systems/connectors.jl")

include("systems/diffeqs/odesystem.jl")
include("systems/diffeqs/sdesystem.jl")
Expand Down Expand Up @@ -157,8 +158,6 @@ for S in subtypes(ModelingToolkit.AbstractSystem)
@eval convert_system(::Type{<:$S}, sys::$S) = sys
end

struct Flow end

export AbstractTimeDependentSystem, AbstractTimeIndependentSystem, AbstractMultivariateSystem
export ODESystem, ODEFunction, ODEFunctionExpr, ODEProblemExpr, convert_system
export DAEFunctionExpr, DAEProblemExpr
Expand All @@ -173,7 +172,8 @@ export SteadyStateProblem, SteadyStateProblemExpr
export JumpProblem, DiscreteProblem
export NonlinearSystem, OptimizationSystem
export ControlSystem
export alias_elimination, flatten, connect, @connector
export alias_elimination, flatten
export connect, @connector, Connection, Flow, Stream, instream
export ode_order_lowering, liouville_transform
export runge_kutta_discretize
export PDESystem
Expand All @@ -182,7 +182,7 @@ export Equation, ConstrainedEquation
export Term, Sym
export SymScope, LocalScope, ParentScope, GlobalScope
export independent_variables, independent_variable, states, parameters, equations, controls, observed, structure
export structural_simplify
export structural_simplify, expand_connections
export DiscreteSystem, DiscreteProblem

export calculate_jacobian, generate_jacobian, generate_function
Expand All @@ -204,7 +204,7 @@ export toexpr, get_variables
export simplify, substitute
export build_function
export modelingtoolkitize
export @variables, @parameters, Flow
export @variables, @parameters
export @named, @nonamespace, @namespace, extend, compose

end # module
78 changes: 9 additions & 69 deletions src/systems/abstractsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ for prop in [
:domain
:ivs
:dvs
:connection_type
:connector_type
:connections
:preface
]
fname1 = Symbol(:get_, prop)
Expand Down Expand Up @@ -282,7 +283,7 @@ function getvar(sys::AbstractSystem, name::Symbol; namespace=false)
elseif !isempty(systems)
i = findfirst(x->nameof(x)==name, systems)
if i !== nothing
return namespace ? rename(systems[i], renamespace(sys, name)) : systems[i]
return namespace ? renamespace(sys, systems[i]) : systems[i]
end
end

Expand Down Expand Up @@ -355,6 +356,7 @@ GlobalScope(sym::Union{Num, Symbolic}) = setmetadata(sym, SymScope, GlobalScope(

renamespace(sys, eq::Equation) = namespace_equation(eq, sys)

renamespace(names::AbstractVector, x) = foldr(renamespace, names, init=x)
function renamespace(sys, x)
x = unwrap(x)
if x isa Symbolic
Expand All @@ -367,6 +369,8 @@ function renamespace(sys, x)
x
end
end
elseif x isa AbstractSystem
rename(x, renamespace(sys, nameof(x)))
else
Symbol(getname(sys), :₊, x)
end
Expand Down Expand Up @@ -854,6 +858,7 @@ topological sort of the observed equations. When `simplify=true`, the `simplify`
function will be applied during the tearing process.
"""
function structural_simplify(sys::AbstractSystem; simplify=false)
sys = expand_connections(sys)
sys = initialize_system_structure(alias_elimination(sys))
check_consistency(sys)
if sys isa ODESystem
Expand Down Expand Up @@ -905,71 +910,6 @@ function check_eqs_u0(eqs, dvs, u0; check_length=true, kwargs...)
return nothing
end

###
### Connectors
###

function with_connection_type(expr)
@assert expr isa Expr && (expr.head == :function || (expr.head == :(=) &&
expr.args[1] isa Expr &&
expr.args[1].head == :call))

sig = expr.args[1]
body = expr.args[2]

fname = sig.args[1]
args = sig.args[2:end]

quote
struct $fname
$(gensym()) -> 1 # this removes the default constructor
end
function $fname($(args...))
function f()
$body
end
res = f()
$isdefined(res, :connection_type) ? $Setfield.@set!(res.connection_type = $fname) : res
end
end
end

macro connector(expr)
esc(with_connection_type(expr))
end

promote_connect_rule(::Type{T}, ::Type{S}) where {T, S} = Union{}
promote_connect_rule(::Type{T}, ::Type{T}) where {T} = T
promote_connect_type(t1::Type, t2::Type, ts::Type...) = promote_connect_type(promote_connect_rule(t1, t2), ts...)
@inline function promote_connect_type(::Type{T}, ::Type{S}) where {T,S}
promote_connect_result(
T,
S,
promote_connect_rule(T,S),
promote_connect_rule(S,T)
)
end

promote_connect_result(::Type, ::Type, ::Type{T}, ::Type{Union{}}) where {T} = T
promote_connect_result(::Type, ::Type, ::Type{Union{}}, ::Type{S}) where {S} = S
promote_connect_result(::Type, ::Type, ::Type{T}, ::Type{T}) where {T} = T
function promote_connect_result(::Type{T}, ::Type{S}, ::Type{P1}, ::Type{P2}) where {T,S,P1,P2}
throw(ArgumentError("connection promotion for $T and $S resulted in $P1 and $P2. " *
"Define promotion only in one direction."))
end

throw_connector_promotion(T, S) = throw(ArgumentError("Don't know how to connect systems of type $S and $T"))
promote_connect_result(::Type{T},::Type{S},::Type{Union{}},::Type{Union{}}) where {T,S} = throw_connector_promotion(T,S)

promote_connect_type(::Type{T}, ::Type{T}) where {T} = T
function promote_connect_type(T, S)
error("Don't know how to connect systems of type $S and $T")
end

function connect(syss...)
connect(promote_connect_type(map(get_connection_type, syss)...), syss...)
end

###
### Inheritance & composition
###
Expand All @@ -990,7 +930,7 @@ function Base.hash(sys::AbstractSystem, s::UInt)
end

"""
$(TYPEDSIGNATURES)
$(TYPEDSIGNATURES)

entend the `basesys` with `sys`, the resulting system would inherit `sys`'s name
by default.
Expand Down Expand Up @@ -1026,7 +966,7 @@ end
Base.:(&)(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol=nameof(sys)) = extend(sys, basesys; name=name)

"""
$(SIGNATURES)
$(SIGNATURES)

compose multiple systems together. The resulting system would inherit the first
system's name.
Expand Down
Loading