From 72ffd1e941a8ed7c94b0aadd1ca0305d8c29f8f8 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 14:12:42 +0200 Subject: [PATCH 01/17] Refactor show() --- src/systems/abstractsystem.jl | 115 +++++++++++++--------------------- 1 file changed, 44 insertions(+), 71 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index b6e2a79c3e..c9d0116434 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1883,84 +1883,57 @@ function n_extra_equations(sys::AbstractSystem) nextras = n_outer_stream_variables + length(ceqs) end -function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem) +function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = true) + limit = get(io, :limit, false) # if output should be limited, + rows = first(displaysize(io)) ÷ 5 # then allocate ≈1/5 of display height to each list + + # Print name + printstyled(io, "Model $(nameof(sys))"; bold) + + # Print equations eqs = equations(sys) - vars = unknowns(sys) - nvars = length(vars) if eqs isa AbstractArray && eltype(eqs) <: Equation neqs = count(eq -> !(eq.lhs isa Connection), eqs) - Base.printstyled(io, "Model $(nameof(sys)) with $neqs "; bold = true) - nextras = n_extra_equations(sys) - if nextras > 0 - Base.printstyled(io, "("; bold = true) - Base.printstyled(io, neqs + nextras; bold = true, color = :magenta) - Base.printstyled(io, ") "; bold = true) - end - Base.printstyled(io, "equations\n"; bold = true) - else - Base.printstyled(io, "Model $(nameof(sys))\n"; bold = true) - end - # The reduced equations are usually very long. It's not that useful to print - # them. - #Base.print_matrix(io, eqs) - #println(io) - - rows = first(displaysize(io)) ÷ 5 - limit = get(io, :limit, false) - - Base.printstyled(io, "Unknowns ($nvars):"; bold = true) - nrows = min(nvars, limit ? rows : nvars) - limited = nrows < length(vars) - defs = has_defaults(sys) ? defaults(sys) : nothing - for i in 1:nrows - s = vars[i] - print(io, "\n ", s) - - if defs !== nothing - val = get(defs, s, nothing) - if val !== nothing - print(io, " [defaults to ") - show( - IOContext(io, :compact => true, :limit => true, - :displaysize => (1, displaysize(io)[2])), - val) - print(io, "]") - end - description = getdescription(s) - if description !== nothing && description != "" - print(io, ": ", description) - end - end - end - limited && print(io, "\n⋮") - println(io) - - vars = parameters(sys) - nvars = length(vars) - Base.printstyled(io, "Parameters ($nvars):"; bold = true) - nrows = min(nvars, limit ? rows : nvars) - limited = nrows < length(vars) - for i in 1:nrows - s = vars[i] - print(io, "\n ", s) - - if defs !== nothing - val = get(defs, s, nothing) - if val !== nothing - print(io, " [defaults to ") - show( - IOContext(io, :compact => true, :limit => true, - :displaysize => (1, displaysize(io)[2])), - val) - print(io, "]") + next = n_extra_equations(sys) + ntot = neqs + next + ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) + neqs > 0 && print(io, "\n $neqs solvable … see equations(sys) for all") + next > 0 && print(io, "\n $next extra") + #Base.print_matrix(io, eqs) # usually too long and not useful to print all equations + end + + # Print variables + for varfunc in [unknowns, parameters] + vars = varfunc(sys) + nvars = length(vars) + nvars == 0 && continue # skip + header = titlecase(String(nameof(varfunc))) # e.g. "Unknowns" + printstyled(io, "\n$header ($nvars):"; bold) + nrows = min(nvars, limit ? rows : nvars) + defs = has_defaults(sys) ? defaults(sys) : nothing + for i in 1:nrows + s = vars[i] + print(io, "\n ", s) + if !isnothing(defs) + val = get(defs, s, nothing) + if !isnothing(val) + print(io, " [defaults to ") + show( + IOContext(io, :compact => true, :limit => true, + :displaysize => (1, displaysize(io)[2])), + val) + print(io, "]") + end + desc = getdescription(s) end - description = getdescription(s) - if description !== nothing && description != "" - print(io, ": ", description) + if !isnothing(desc) && desc != "" + print(io, ": ", desc) end end + limited = nrows < nvars + limited && print(io, "\n ⋮") # too many variables to print end - limited && print(io, "\n⋮") + return nothing end From c23cd6234da57e37d7235cc7e764017366279240 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 14:29:21 +0200 Subject: [PATCH 02/17] Include observed equations --- src/systems/abstractsystem.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index c9d0116434..2712611c82 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1894,10 +1894,12 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t eqs = equations(sys) if eqs isa AbstractArray && eltype(eqs) <: Equation neqs = count(eq -> !(eq.lhs isa Connection), eqs) + nobs = has_observed(sys) ? length(observed(sys)) : 0 next = n_extra_equations(sys) - ntot = neqs + next + ntot = neqs + nobs + next ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) - neqs > 0 && print(io, "\n $neqs solvable … see equations(sys) for all") + neqs > 0 && print(io, "\n $neqs solvable") + nobs > 0 && print(io, "\n $nobs observed") next > 0 && print(io, "\n $next extra") #Base.print_matrix(io, eqs) # usually too long and not useful to print all equations end From 8d7a65269c8e63d254b05be253fc6112ea4d6aa9 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 15:18:09 +0200 Subject: [PATCH 03/17] Show subsystem names --- src/systems/abstractsystem.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 2712611c82..117c37a70d 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1890,6 +1890,14 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t # Print name printstyled(io, "Model $(nameof(sys))"; bold) + # Print subsystems # TODO: limit + subs = nameof.(ModelingToolkit.get_systems(sys)) + nsubs = length(subs) + nsubs > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) + for sub in subs + print(io, "\n ", sub) + end + # Print equations eqs = equations(sys) if eqs isa AbstractArray && eltype(eqs) <: Equation From ffc43d2a923d8654b17910bba0f55c94dc91171a Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 16:18:57 +0200 Subject: [PATCH 04/17] Add description to all systems --- src/systems/abstractsystem.jl | 1 + src/systems/diffeqs/odesystem.jl | 11 ++++++++--- src/systems/diffeqs/sdesystem.jl | 15 ++++++++++----- src/systems/discrete_system/discrete_system.jl | 12 +++++++++--- src/systems/jumps/jumpsystem.jl | 9 ++++++--- src/systems/nonlinear/nonlinearsystem.jl | 12 +++++++++--- src/systems/optimization/constraints_system.jl | 11 ++++++++--- src/systems/optimization/optimizationsystem.jl | 9 ++++++--- src/systems/pde/pdesystem.jl | 7 ++++++- 9 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 117c37a70d..2bc3335b81 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -986,6 +986,7 @@ for prop in [:eqs :ps :tspan :name + :description :var_to_name :ctrls :defaults diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index ec2c5f8157..b59f08878c 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -79,6 +79,10 @@ struct ODESystem <: AbstractODESystem """ name::Symbol """ + A description of the system. + """ + description::String + """ The internal systems. These are required to have unique names. """ systems::Vector{ODESystem} @@ -178,7 +182,7 @@ struct ODESystem <: AbstractODESystem parent::Any function ODESystem(tag, deqs, iv, dvs, ps, tspan, var_to_name, ctrls, observed, tgrad, - jac, ctrl_jac, Wfact, Wfact_t, name, systems, defaults, guesses, + jac, ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, guesses, torn_matching, initializesystem, initialization_eqs, schedule, connector_type, preface, cevents, devents, parameter_dependencies, @@ -199,7 +203,7 @@ struct ODESystem <: AbstractODESystem check_units(u, deqs) end new(tag, deqs, iv, dvs, ps, tspan, var_to_name, ctrls, observed, tgrad, jac, - ctrl_jac, Wfact, Wfact_t, name, systems, defaults, guesses, torn_matching, + ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, guesses, torn_matching, initializesystem, initialization_eqs, schedule, connector_type, preface, cevents, devents, parameter_dependencies, metadata, gui_metadata, is_dde, tearing_state, substitutions, complete, index_cache, @@ -213,6 +217,7 @@ function ODESystem(deqs::AbstractVector{<:Equation}, iv, dvs, ps; systems = ODESystem[], tspan = nothing, name = nothing, + description = "", default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), @@ -290,7 +295,7 @@ function ODESystem(deqs::AbstractVector{<:Equation}, iv, dvs, ps; end ODESystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), deqs, iv′, dvs′, ps′, tspan, var_to_name, ctrl′, observed, tgrad, jac, - ctrl_jac, Wfact, Wfact_t, name, systems, defaults, guesses, nothing, initializesystem, + ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, guesses, nothing, initializesystem, initialization_eqs, schedule, connector_type, preface, cont_callbacks, disc_callbacks, parameter_dependencies, metadata, gui_metadata, is_dde, checks = checks) diff --git a/src/systems/diffeqs/sdesystem.jl b/src/systems/diffeqs/sdesystem.jl index 0d73aaf313..8343f35e17 100644 --- a/src/systems/diffeqs/sdesystem.jl +++ b/src/systems/diffeqs/sdesystem.jl @@ -80,6 +80,10 @@ struct SDESystem <: AbstractODESystem """ name::Symbol """ + A description of the system. + """ + description::String + """ The internal systems. These are required to have unique names. """ systems::Vector{SDESystem} @@ -142,7 +146,7 @@ struct SDESystem <: AbstractODESystem function SDESystem(tag, deqs, neqs, iv, dvs, ps, tspan, var_to_name, ctrls, observed, tgrad, jac, - ctrl_jac, Wfact, Wfact_t, name, systems, defaults, connector_type, + ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, connector_type, cevents, devents, parameter_dependencies, metadata = nothing, gui_metadata = nothing, complete = false, index_cache = nothing, parent = nothing, is_scalar_noise = false, is_dde = false, @@ -168,7 +172,7 @@ struct SDESystem <: AbstractODESystem end new(tag, deqs, neqs, iv, dvs, ps, tspan, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, - Wfact, Wfact_t, name, systems, defaults, connector_type, cevents, devents, + Wfact, Wfact_t, name, description, systems, defaults, connector_type, cevents, devents, parameter_dependencies, metadata, gui_metadata, complete, index_cache, parent, is_scalar_noise, is_dde, isscheduled) end @@ -183,6 +187,7 @@ function SDESystem(deqs::AbstractVector{<:Equation}, neqs::AbstractArray, iv, dv default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), name = nothing, + description = "", connector_type = nothing, checks = true, continuous_events = nothing, @@ -234,7 +239,7 @@ function SDESystem(deqs::AbstractVector{<:Equation}, neqs::AbstractArray, iv, dv end SDESystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), deqs, neqs, iv′, dvs′, ps′, tspan, var_to_name, ctrl′, observed, tgrad, jac, - ctrl_jac, Wfact, Wfact_t, name, systems, defaults, connector_type, + ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, connector_type, cont_callbacks, disc_callbacks, parameter_dependencies, metadata, gui_metadata, complete, index_cache, parent, is_scalar_noise, is_dde; checks = checks) end @@ -349,7 +354,7 @@ function stochastic_integral_transform(sys::SDESystem, correction_factor) end SDESystem(deqs, get_noiseeqs(sys), get_iv(sys), unknowns(sys), parameters(sys), - name = name, parameter_dependencies = parameter_dependencies(sys), checks = false) + name = name, description = get_description(sys), parameter_dependencies = parameter_dependencies(sys), checks = false) end """ @@ -457,7 +462,7 @@ function Girsanov_transform(sys::SDESystem, u; θ0 = 1.0) # return modified SDE System SDESystem(deqs, noiseeqs, get_iv(sys), unknown_vars, parameters(sys); defaults = Dict(θ => θ0), observed = [weight ~ θ / θ0], - name = name, parameter_dependencies = parameter_dependencies(sys), + name = name, description = get_description(sys), parameter_dependencies = parameter_dependencies(sys), checks = false) end diff --git a/src/systems/discrete_system/discrete_system.jl b/src/systems/discrete_system/discrete_system.jl index b09ecf5c4c..5e7ae46a08 100644 --- a/src/systems/discrete_system/discrete_system.jl +++ b/src/systems/discrete_system/discrete_system.jl @@ -42,6 +42,10 @@ struct DiscreteSystem <: AbstractTimeDependentSystem """ name::Symbol """ + A description of the system. + """ + description::String + """ The internal systems. These are required to have unique names. """ systems::Vector{DiscreteSystem} @@ -95,7 +99,7 @@ struct DiscreteSystem <: AbstractTimeDependentSystem function DiscreteSystem(tag, discreteEqs, iv, dvs, ps, tspan, var_to_name, observed, - name, + name, description, systems, defaults, preface, connector_type, parameter_dependencies = Equation[], metadata = nothing, gui_metadata = nothing, tearing_state = nothing, substitutions = nothing, @@ -111,7 +115,7 @@ struct DiscreteSystem <: AbstractTimeDependentSystem u = __get_unit_type(dvs, ps, iv) check_units(u, discreteEqs) end - new(tag, discreteEqs, iv, dvs, ps, tspan, var_to_name, observed, name, + new(tag, discreteEqs, iv, dvs, ps, tspan, var_to_name, observed, name, description, systems, defaults, preface, connector_type, parameter_dependencies, metadata, gui_metadata, @@ -128,6 +132,7 @@ function DiscreteSystem(eqs::AbstractVector{<:Equation}, iv, dvs, ps; systems = DiscreteSystem[], tspan = nothing, name = nothing, + description = "", default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), @@ -164,7 +169,7 @@ function DiscreteSystem(eqs::AbstractVector{<:Equation}, iv, dvs, ps; throw(ArgumentError("System names must be unique.")) end DiscreteSystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), - eqs, iv′, dvs′, ps′, tspan, var_to_name, observed, name, systems, + eqs, iv′, dvs′, ps′, tspan, var_to_name, observed, name, description, systems, defaults, preface, connector_type, parameter_dependencies, metadata, gui_metadata, kwargs...) end @@ -221,6 +226,7 @@ function flatten(sys::DiscreteSystem, noeqs = false) observed = observed(sys), defaults = defaults(sys), name = nameof(sys), + description = get_description(sys), checks = false) end end diff --git a/src/systems/jumps/jumpsystem.jl b/src/systems/jumps/jumpsystem.jl index a714d4b364..98253569d2 100644 --- a/src/systems/jumps/jumpsystem.jl +++ b/src/systems/jumps/jumpsystem.jl @@ -74,6 +74,8 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem observed::Vector{Equation} """The name of the system.""" name::Symbol + """A description of the system.""" + description::String """The internal systems. These are required to have unique names.""" systems::Vector{JumpSystem} """ @@ -116,7 +118,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem index_cache::Union{Nothing, IndexCache} isscheduled::Bool - function JumpSystem{U}(tag, ap::U, iv, unknowns, ps, var_to_name, observed, name, + function JumpSystem{U}(tag, ap::U, iv, unknowns, ps, var_to_name, observed, name, description, systems, defaults, connector_type, devents, parameter_dependencies, metadata = nothing, gui_metadata = nothing, @@ -131,7 +133,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem u = __get_unit_type(unknowns, ps, iv) check_units(u, ap, iv) end - new{U}(tag, ap, iv, unknowns, ps, var_to_name, observed, name, systems, defaults, + new{U}(tag, ap, iv, unknowns, ps, var_to_name, observed, name, description, systems, defaults, connector_type, devents, parameter_dependencies, metadata, gui_metadata, complete, index_cache, isscheduled) end @@ -147,6 +149,7 @@ function JumpSystem(eqs, iv, unknowns, ps; default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), name = nothing, + description = "", connector_type = nothing, checks = true, continuous_events = nothing, @@ -193,7 +196,7 @@ function JumpSystem(eqs, iv, unknowns, ps; disc_callbacks = SymbolicDiscreteCallbacks(discrete_events) parameter_dependencies, ps = process_parameter_dependencies(parameter_dependencies, ps) JumpSystem{typeof(ap)}(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), - ap, value(iv), unknowns, ps, var_to_name, observed, name, systems, + ap, value(iv), unknowns, ps, var_to_name, observed, name, description, systems, defaults, connector_type, disc_callbacks, parameter_dependencies, metadata, gui_metadata, checks = checks) end diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index d9ad826a2c..07c73798f4 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -44,6 +44,10 @@ struct NonlinearSystem <: AbstractTimeIndependentSystem """ name::Symbol """ + A description of the system. + """ + description::String + """ The internal systems. These are required to have unique names. """ systems::Vector{NonlinearSystem} @@ -91,7 +95,7 @@ struct NonlinearSystem <: AbstractTimeIndependentSystem parent::Any isscheduled::Bool - function NonlinearSystem(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, + function NonlinearSystem(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, parameter_dependencies = Equation[], metadata = nothing, gui_metadata = nothing, @@ -102,7 +106,7 @@ struct NonlinearSystem <: AbstractTimeIndependentSystem u = __get_unit_type(unknowns, ps) check_units(u, eqs) end - new(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, systems, defaults, + new(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, parameter_dependencies, metadata, gui_metadata, tearing_state, substitutions, complete, index_cache, parent, isscheduled) end @@ -111,6 +115,7 @@ end function NonlinearSystem(eqs, unknowns, ps; observed = [], name = nothing, + description = "", default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), @@ -157,7 +162,7 @@ function NonlinearSystem(eqs, unknowns, ps; parameter_dependencies, ps = process_parameter_dependencies( parameter_dependencies, ps) NonlinearSystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), - eqs, unknowns, ps, var_to_name, observed, jac, name, systems, defaults, + eqs, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, parameter_dependencies, metadata, gui_metadata, checks = checks) end @@ -554,6 +559,7 @@ function flatten(sys::NonlinearSystem, noeqs = false) observed = observed(sys), defaults = defaults(sys), name = nameof(sys), + description = get_description(sys), checks = false) end end diff --git a/src/systems/optimization/constraints_system.jl b/src/systems/optimization/constraints_system.jl index f9176df3a2..054244e005 100644 --- a/src/systems/optimization/constraints_system.jl +++ b/src/systems/optimization/constraints_system.jl @@ -45,6 +45,10 @@ struct ConstraintsSystem <: AbstractTimeIndependentSystem """ name::Symbol """ + A description of the system. + """ + description::String + """ The internal systems. These are required to have unique names. """ systems::Vector{ConstraintsSystem} @@ -79,7 +83,7 @@ struct ConstraintsSystem <: AbstractTimeIndependentSystem index_cache::Union{Nothing, IndexCache} function ConstraintsSystem(tag, constraints, unknowns, ps, var_to_name, observed, jac, - name, + name, description, systems, defaults, connector_type, metadata = nothing, tearing_state = nothing, substitutions = nothing, @@ -89,7 +93,7 @@ struct ConstraintsSystem <: AbstractTimeIndependentSystem u = __get_unit_type(unknowns, ps) check_units(u, constraints) end - new(tag, constraints, unknowns, ps, var_to_name, observed, jac, name, systems, + new(tag, constraints, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, metadata, tearing_state, substitutions, complete, index_cache) end @@ -100,6 +104,7 @@ equations(sys::ConstraintsSystem) = constraints(sys) # needed for Base.show function ConstraintsSystem(constraints, unknowns, ps; observed = [], name = nothing, + description = "", default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), @@ -142,7 +147,7 @@ function ConstraintsSystem(constraints, unknowns, ps; isempty(observed) || collect_var_to_name!(var_to_name, (eq.lhs for eq in observed)) ConstraintsSystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), - cstr, unknowns, ps, var_to_name, observed, jac, name, systems, + cstr, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, metadata, checks = checks) end diff --git a/src/systems/optimization/optimizationsystem.jl b/src/systems/optimization/optimizationsystem.jl index 22488e8bad..1f543dc8d1 100644 --- a/src/systems/optimization/optimizationsystem.jl +++ b/src/systems/optimization/optimizationsystem.jl @@ -37,6 +37,8 @@ struct OptimizationSystem <: AbstractOptimizationSystem constraints::Vector{Union{Equation, Inequality}} """The name of the system.""" name::Symbol + """A description of the system.""" + description::String """The internal systems. These are required to have unique names.""" systems::Vector{OptimizationSystem} """ @@ -67,7 +69,7 @@ struct OptimizationSystem <: AbstractOptimizationSystem isscheduled::Bool function OptimizationSystem(tag, op, unknowns, ps, var_to_name, observed, - constraints, name, systems, defaults, metadata = nothing, + constraints, name, description, systems, defaults, metadata = nothing, gui_metadata = nothing, complete = false, index_cache = nothing, parent = nothing, isscheduled = false; checks::Union{Bool, Int} = true) @@ -78,7 +80,7 @@ struct OptimizationSystem <: AbstractOptimizationSystem check_units(u, constraints) end new(tag, op, unknowns, ps, var_to_name, observed, - constraints, name, systems, defaults, metadata, gui_metadata, complete, + constraints, name, description, systems, defaults, metadata, gui_metadata, complete, index_cache, parent, isscheduled) end end @@ -92,6 +94,7 @@ function OptimizationSystem(op, unknowns, ps; default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)), name = nothing, + description = "", systems = OptimizationSystem[], checks = true, metadata = nothing, @@ -125,7 +128,7 @@ function OptimizationSystem(op, unknowns, ps; op′, unknowns′, ps′, var_to_name, observed, constraints, - name, systems, defaults, metadata, gui_metadata; + name, description, systems, defaults, metadata, gui_metadata; checks = checks) end diff --git a/src/systems/pde/pdesystem.jl b/src/systems/pde/pdesystem.jl index 7aa3f29191..eac540e401 100644 --- a/src/systems/pde/pdesystem.jl +++ b/src/systems/pde/pdesystem.jl @@ -78,6 +78,10 @@ struct PDESystem <: ModelingToolkit.AbstractMultivariateSystem """ name::Symbol """ + A description of the system. + """ + description::String + """ Metadata for the system, to be used by downstream packages. """ metadata::Any @@ -96,6 +100,7 @@ struct PDESystem <: ModelingToolkit.AbstractMultivariateSystem gui_metadata = nothing, eval_module = @__MODULE__, checks::Union{Bool, Int} = true, + description = "", name) if checks == true || (checks & CheckUnits) > 0 u = __get_unit_type(dvs, ivs, ps) @@ -127,7 +132,7 @@ struct PDESystem <: ModelingToolkit.AbstractMultivariateSystem end new(eqs, bcs, domain, ivs, dvs, ps, defaults, connector_type, systems, analytic, - analytic_func, name, metadata, gui_metadata) + analytic_func, name, description, metadata, gui_metadata) end end From 428bc8d0a760392b5e9c686322d4139541fe69ed Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 16:23:02 +0200 Subject: [PATCH 05/17] Extend system descriptions --- src/systems/abstractsystem.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 2bc3335b81..0dbe67b2a5 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -2972,12 +2972,13 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol = nam cevs = union(get_continuous_events(basesys), get_continuous_events(sys)) devs = union(get_discrete_events(basesys), get_discrete_events(sys)) defs = merge(get_defaults(basesys), get_defaults(sys)) # prefer `sys` + desc = join(filter(desc -> !isempty(desc), get_description.([sys, basesys])), " ") # concatenate non-empty descriptions with space meta = union_nothing(get_metadata(basesys), get_metadata(sys)) syss = union(get_systems(basesys), get_systems(sys)) args = length(ivs) == 0 ? (eqs, sts, ps) : (eqs, ivs[1], sts, ps) kwargs = (parameter_dependencies = dep_ps, observed = obs, continuous_events = cevs, discrete_events = devs, defaults = defs, systems = syss, metadata = meta, - name = name, gui_metadata = gui_metadata) + name = name, description = desc, gui_metadata = gui_metadata) # collect fields specific to some system types if basesys isa ODESystem From 59e23d4ea47b7172e9c5f2b4806c2a800b664e54 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 16:32:33 +0200 Subject: [PATCH 06/17] Show system and subsystem descriptions --- src/systems/abstractsystem.jl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 0dbe67b2a5..1d8b085afe 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1888,15 +1888,26 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t limit = get(io, :limit, false) # if output should be limited, rows = first(displaysize(io)) ÷ 5 # then allocate ≈1/5 of display height to each list - # Print name - printstyled(io, "Model $(nameof(sys))"; bold) + # Print name and description + desc = get_description(sys) + printstyled(io, "Model ", nameof(sys), ":"; bold) + !isempty(desc) && print(io, " ", desc) - # Print subsystems # TODO: limit - subs = nameof.(ModelingToolkit.get_systems(sys)) + # Print subsystems + subs = get_systems(sys) nsubs = length(subs) nsubs > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) for sub in subs - print(io, "\n ", sub) + name = String(nameof(sub)) + print(io, "\n ", name) + desc = get_description(sub) + if !isempty(desc) + maxlen = displaysize(io)[2] - length(name) - 6 # remaining length of line + if limit && length(desc) > maxlen + desc = chop(desc, tail = length(desc) - maxlen) * "…" # too long + end + print(io, ": ", desc) + end end # Print equations From cc926f9c9665062c951230c6b1c83a32195999f6 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 18:31:31 +0200 Subject: [PATCH 07/17] Limit number of subsystems shown --- src/systems/abstractsystem.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 1d8b085afe..f98cc316f7 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1896,8 +1896,10 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t # Print subsystems subs = get_systems(sys) nsubs = length(subs) - nsubs > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) - for sub in subs + nrows = min(nsubs, limit ? rows : nsubs) + nrows > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) + for i in 1:nrows + sub = subs[i] name = String(nameof(sub)) print(io, "\n ", name) desc = get_description(sub) @@ -1909,6 +1911,8 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t print(io, ": ", desc) end end + limited = nrows < nsubs + limited && print(io, "\n ⋮") # too many variables to print # Print equations eqs = equations(sys) From b02abba138af18f2d01bc6d28a8878429dca33d0 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 19:06:29 +0200 Subject: [PATCH 08/17] Pass description through flatten() --- src/systems/diffeqs/odesystem.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index b59f08878c..155ee211db 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -398,6 +398,7 @@ function flatten(sys::ODESystem, noeqs = false) discrete_events = discrete_events(sys), defaults = defaults(sys), name = nameof(sys), + description = get_description(sys), initialization_eqs = initialization_equations(sys), is_dde = is_dde(sys), checks = false) From db9348c9e67d2168576a73fda956c5d4f3f19468 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Thu, 17 Oct 2024 19:50:47 +0200 Subject: [PATCH 09/17] Hint to inspection functions when only parts of a system is shown --- src/systems/abstractsystem.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index f98cc316f7..c79f805819 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1884,7 +1884,7 @@ function n_extra_equations(sys::AbstractSystem) nextras = n_outer_stream_variables + length(ceqs) end -function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = true) +function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = true, bold = true) limit = get(io, :limit, false) # if output should be limited, rows = first(displaysize(io)) ÷ 5 # then allocate ≈1/5 of display height to each list @@ -1898,6 +1898,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t nsubs = length(subs) nrows = min(nsubs, limit ? rows : nsubs) nrows > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) + nrows > 0 && hint && print(io, " see ModelingToolkit.get_systems(sys)") for i in 1:nrows sub = subs[i] name = String(nameof(sub)) @@ -1912,7 +1913,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t end end limited = nrows < nsubs - limited && print(io, "\n ⋮") # too many variables to print + limited && print(io, "\n ⋮") # too many to print # Print equations eqs = equations(sys) @@ -1922,6 +1923,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t next = n_extra_equations(sys) ntot = neqs + nobs + next ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) + ntot > 0 && hint && print(io, " see equations(sys)") neqs > 0 && print(io, "\n $neqs solvable") nobs > 0 && print(io, "\n $nobs observed") next > 0 && print(io, "\n $next extra") @@ -1935,6 +1937,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t nvars == 0 && continue # skip header = titlecase(String(nameof(varfunc))) # e.g. "Unknowns" printstyled(io, "\n$header ($nvars):"; bold) + hint && print(io, " see $(nameof(varfunc))(sys)") nrows = min(nvars, limit ? rows : nvars) defs = has_defaults(sys) ? defaults(sys) : nothing for i in 1:nrows @@ -1957,7 +1960,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; bold = t end end limited = nrows < nvars - limited && print(io, "\n ⋮") # too many variables to print + limited && printstyled(io, "\n ⋮") # too many variables to print end return nothing From d473a73b28ca7eb13b8be058995ddde8f31d2377 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Fri, 18 Oct 2024 11:20:37 +0200 Subject: [PATCH 10/17] Export hierarchy(sys) to print subsystem hierarchy --- src/ModelingToolkit.jl | 2 +- src/systems/abstractsystem.jl | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 2f57bb1765..7687122a61 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -243,7 +243,7 @@ export Equation, ConstrainedEquation export Term, Sym export SymScope, LocalScope, ParentScope, DelayParentScope, GlobalScope export independent_variable, equations, controls, observed, full_equations -export initialization_equations, guesses, defaults, parameter_dependencies +export initialization_equations, guesses, defaults, parameter_dependencies, hierarchy export structural_simplify, expand_connections, linearize, linearization_function export calculate_jacobian, generate_jacobian, generate_function, generate_custom_function diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index c79f805819..d8ee0337c8 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1898,7 +1898,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t nsubs = length(subs) nrows = min(nsubs, limit ? rows : nsubs) nrows > 0 && printstyled(io, "\nSubsystems ($(nsubs)):"; bold) - nrows > 0 && hint && print(io, " see ModelingToolkit.get_systems(sys)") + nrows > 0 && hint && print(io, " see hierarchy(sys)") for i in 1:nrows sub = subs[i] name = String(nameof(sub)) @@ -2902,12 +2902,22 @@ function Base.showerror(io::IO, e::HybridSystemNotSupportedException) print(io, "HybridSystemNotSupportedException: ", e.msg) end -function AbstractTrees.children(sys::ModelingToolkit.AbstractSystem) +function AbstractTrees.children(sys::AbstractSystem) ModelingToolkit.get_systems(sys) end -function AbstractTrees.printnode(io::IO, sys::ModelingToolkit.AbstractSystem) - print(io, nameof(sys)) +function AbstractTrees.printnode(io::IO, sys::AbstractSystem; describe = false, bold = false) + printstyled(io, nameof(sys); bold) + describe && !isempty(get_description(sys)) && print(io, ": ", get_description(sys)) end +""" + hierarchy(sys::AbstractSystem; describe = false, bold = describe, kwargs...) + +Print a tree of a system's hierarchy of subsystems. +""" +function hierarchy(sys::AbstractSystem; describe = false, bold = describe, kwargs...) + print_tree(sys; printnode_kw = (describe = describe, bold = bold), kwargs...) +end + function Base.IteratorEltype(::Type{<:TreeIterator{ModelingToolkit.AbstractSystem}}) Base.HasEltype() end From b3f3faf2b941bb9112b19c757bef8f173a1e77c9 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Fri, 18 Oct 2024 17:02:24 +0200 Subject: [PATCH 11/17] Fix format --- src/systems/abstractsystem.jl | 3 ++- src/systems/diffeqs/odesystem.jl | 3 ++- src/systems/diffeqs/sdesystem.jl | 9 ++++++--- src/systems/jumps/jumpsystem.jl | 6 ++++-- src/systems/nonlinear/nonlinearsystem.jl | 6 ++++-- src/systems/optimization/constraints_system.jl | 3 ++- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index d8ee0337c8..f1646861ee 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -2905,7 +2905,8 @@ end function AbstractTrees.children(sys::AbstractSystem) ModelingToolkit.get_systems(sys) end -function AbstractTrees.printnode(io::IO, sys::AbstractSystem; describe = false, bold = false) +function AbstractTrees.printnode( + io::IO, sys::AbstractSystem; describe = false, bold = false) printstyled(io, nameof(sys); bold) describe && !isempty(get_description(sys)) && print(io, ": ", get_description(sys)) end diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 155ee211db..b901275121 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -295,7 +295,8 @@ function ODESystem(deqs::AbstractVector{<:Equation}, iv, dvs, ps; end ODESystem(Threads.atomic_add!(SYSTEM_COUNT, UInt(1)), deqs, iv′, dvs′, ps′, tspan, var_to_name, ctrl′, observed, tgrad, jac, - ctrl_jac, Wfact, Wfact_t, name, description, systems, defaults, guesses, nothing, initializesystem, + ctrl_jac, Wfact, Wfact_t, name, description, systems, + defaults, guesses, nothing, initializesystem, initialization_eqs, schedule, connector_type, preface, cont_callbacks, disc_callbacks, parameter_dependencies, metadata, gui_metadata, is_dde, checks = checks) diff --git a/src/systems/diffeqs/sdesystem.jl b/src/systems/diffeqs/sdesystem.jl index 8343f35e17..e8a72b81cb 100644 --- a/src/systems/diffeqs/sdesystem.jl +++ b/src/systems/diffeqs/sdesystem.jl @@ -172,7 +172,8 @@ struct SDESystem <: AbstractODESystem end new(tag, deqs, neqs, iv, dvs, ps, tspan, var_to_name, ctrls, observed, tgrad, jac, ctrl_jac, - Wfact, Wfact_t, name, description, systems, defaults, connector_type, cevents, devents, + Wfact, Wfact_t, name, description, systems, + defaults, connector_type, cevents, devents, parameter_dependencies, metadata, gui_metadata, complete, index_cache, parent, is_scalar_noise, is_dde, isscheduled) end @@ -354,7 +355,8 @@ function stochastic_integral_transform(sys::SDESystem, correction_factor) end SDESystem(deqs, get_noiseeqs(sys), get_iv(sys), unknowns(sys), parameters(sys), - name = name, description = get_description(sys), parameter_dependencies = parameter_dependencies(sys), checks = false) + name = name, description = get_description(sys), + parameter_dependencies = parameter_dependencies(sys), checks = false) end """ @@ -462,7 +464,8 @@ function Girsanov_transform(sys::SDESystem, u; θ0 = 1.0) # return modified SDE System SDESystem(deqs, noiseeqs, get_iv(sys), unknown_vars, parameters(sys); defaults = Dict(θ => θ0), observed = [weight ~ θ / θ0], - name = name, description = get_description(sys), parameter_dependencies = parameter_dependencies(sys), + name = name, description = get_description(sys), + parameter_dependencies = parameter_dependencies(sys), checks = false) end diff --git a/src/systems/jumps/jumpsystem.jl b/src/systems/jumps/jumpsystem.jl index 98253569d2..6409609a10 100644 --- a/src/systems/jumps/jumpsystem.jl +++ b/src/systems/jumps/jumpsystem.jl @@ -118,7 +118,8 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem index_cache::Union{Nothing, IndexCache} isscheduled::Bool - function JumpSystem{U}(tag, ap::U, iv, unknowns, ps, var_to_name, observed, name, description, + function JumpSystem{U}( + tag, ap::U, iv, unknowns, ps, var_to_name, observed, name, description, systems, defaults, connector_type, devents, parameter_dependencies, metadata = nothing, gui_metadata = nothing, @@ -133,7 +134,8 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem u = __get_unit_type(unknowns, ps, iv) check_units(u, ap, iv) end - new{U}(tag, ap, iv, unknowns, ps, var_to_name, observed, name, description, systems, defaults, + new{U}(tag, ap, iv, unknowns, ps, var_to_name, + observed, name, description, systems, defaults, connector_type, devents, parameter_dependencies, metadata, gui_metadata, complete, index_cache, isscheduled) end diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index 07c73798f4..f1b438f0bb 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -95,7 +95,8 @@ struct NonlinearSystem <: AbstractTimeIndependentSystem parent::Any isscheduled::Bool - function NonlinearSystem(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, description, + function NonlinearSystem( + tag, eqs, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, connector_type, parameter_dependencies = Equation[], metadata = nothing, gui_metadata = nothing, @@ -106,7 +107,8 @@ struct NonlinearSystem <: AbstractTimeIndependentSystem u = __get_unit_type(unknowns, ps) check_units(u, eqs) end - new(tag, eqs, unknowns, ps, var_to_name, observed, jac, name, description, systems, defaults, + new(tag, eqs, unknowns, ps, var_to_name, observed, + jac, name, description, systems, defaults, connector_type, parameter_dependencies, metadata, gui_metadata, tearing_state, substitutions, complete, index_cache, parent, isscheduled) end diff --git a/src/systems/optimization/constraints_system.jl b/src/systems/optimization/constraints_system.jl index 054244e005..a2756994ac 100644 --- a/src/systems/optimization/constraints_system.jl +++ b/src/systems/optimization/constraints_system.jl @@ -93,7 +93,8 @@ struct ConstraintsSystem <: AbstractTimeIndependentSystem u = __get_unit_type(unknowns, ps) check_units(u, constraints) end - new(tag, constraints, unknowns, ps, var_to_name, observed, jac, name, description, systems, + new(tag, constraints, unknowns, ps, var_to_name, + observed, jac, name, description, systems, defaults, connector_type, metadata, tearing_state, substitutions, complete, index_cache) end From b5b1a8a1665c9ccdb2f2d7e12cf49735d1c51e63 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 18:49:02 +0200 Subject: [PATCH 12/17] Dispatch on ODESystem to print initialization equation count --- src/systems/diffeqs/odesystem.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index b901275121..7055da3ac9 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -704,3 +704,15 @@ function add_accumulations(sys::ODESystem, vars::Vector{<:Pair}) @set! sys.unknowns = [get_unknowns(sys); avars] @set! sys.defaults = merge(get_defaults(sys), Dict(a => 0.0 for a in avars)) end + +function Base.show(io::IO, mime::MIME"text/plain", sys::ODESystem; hint = true, bold = true) + # Print general AbstractSystem information + invoke(Base.show, Tuple{typeof(io), typeof(mime), AbstractSystem}, io, mime, sys; hint, bold) + + # Print initialization equations (unique to ODESystems) + nini = length(initialization_equations(sys)) + nini > 0 && printstyled(io, "\nInitialization equations ($nini):"; bold) + nini > 0 && hint && print(io, " see initialization_equations(sys)") + + return nothing +end From 2bc4b161a83a16c347a264fc4a83a6bad3a6d00e Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 19:31:37 +0200 Subject: [PATCH 13/17] Distinguish standard and connecting equations; rename and document n_extra_equations() --- src/systems/abstractsystem.jl | 21 +++++++++++++-------- test/components.jl | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index f1646861ee..a84beb05da 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1856,8 +1856,14 @@ function get_or_construct_tearing_state(sys) state end -# TODO: what about inputs? -function n_extra_equations(sys::AbstractSystem) +""" + n_expanded_connection_equations(sys::AbstractSystem) + +Returns the number of equations that the connections in `sys` expands to. +Equivalent to `length(equations(expand_connections(sys))) - length(filter(eq -> !(eq.lhs isa Connection), equations(sys)))`. +""" +function n_expanded_connection_equations(sys::AbstractSystem) + # TODO: what about inputs? isconnector(sys) && return length(get_unknowns(sys)) sys, (csets, _) = generate_connection_set(sys) ceqs, instream_csets = generate_connection_equations_and_stream_connections(csets) @@ -1919,14 +1925,13 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t eqs = equations(sys) if eqs isa AbstractArray && eltype(eqs) <: Equation neqs = count(eq -> !(eq.lhs isa Connection), eqs) + next = n_expanded_connection_equations(sys) nobs = has_observed(sys) ? length(observed(sys)) : 0 - next = n_extra_equations(sys) - ntot = neqs + nobs + next + ntot = neqs + next + nobs ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) - ntot > 0 && hint && print(io, " see equations(sys)") - neqs > 0 && print(io, "\n $neqs solvable") - nobs > 0 && print(io, "\n $nobs observed") - next > 0 && print(io, "\n $next extra") + neqs > 0 && print(io, "\n $neqs standard", hint ? ": see equations(sys)" : "") + next > 0 && print(io, "\n $next connecting", hint ? ": see equations(expand_connections(sys))" : "") + nobs > 0 && print(io, "\n $nobs observed", hint ? ": see observed(sys)" : "") #Base.print_matrix(io, eqs) # usually too long and not useful to print all equations end diff --git a/test/components.jl b/test/components.jl index 965578e0c5..ea63e3e758 100644 --- a/test/components.jl +++ b/test/components.jl @@ -41,7 +41,7 @@ end completed_rc_model = complete(rc_model) @test isequal(completed_rc_model.resistor.n.i, resistor.n.i) -@test ModelingToolkit.n_extra_equations(capacitor) == 2 +@test ModelingToolkit.n_expanded_connection_equations(capacitor) == 2 @test length(equations(structural_simplify(rc_model, allow_parameter = false))) == 2 sys = structural_simplify(rc_model) @test_throws ModelingToolkit.RepeatedStructuralSimplificationError structural_simplify(sys) From f7e956f45547e3cd500cd070ab6dce1c6d77f150 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 19:34:59 +0200 Subject: [PATCH 14/17] Add description to AbstractSystem documentation --- docs/src/basics/AbstractSystem.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/basics/AbstractSystem.md b/docs/src/basics/AbstractSystem.md index 2161613353..e68a7bb94e 100644 --- a/docs/src/basics/AbstractSystem.md +++ b/docs/src/basics/AbstractSystem.md @@ -63,6 +63,7 @@ Optionally, a system could have: - `get_defaults(sys)`: A `Dict` that maps variables into their default values for the current-level system. - `get_noiseeqs(sys)`: Noise equations of the current-level system. + - `get_description(sys)`: A string that describes what a system represents. - `get_metadata(sys)`: Any metadata about the system or its origin to be used by downstream packages. Note that if you know a system is an `AbstractTimeDependentSystem` you could use `get_iv` to get the From f57535113531300b6bc474646e7b6b57b1158020 Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 19:52:24 +0200 Subject: [PATCH 15/17] Always check if AbstractSystems have a description --- src/systems/abstractsystem.jl | 9 +++++---- src/systems/diffeqs/odesystem.jl | 2 +- src/systems/diffeqs/sdesystem.jl | 4 ++-- src/systems/discrete_system/discrete_system.jl | 2 +- src/systems/nonlinear/nonlinearsystem.jl | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index a84beb05da..1a3c725166 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -498,6 +498,7 @@ end Substitutions(subs, deps) = Substitutions(subs, deps, nothing) Base.nameof(sys::AbstractSystem) = getfield(sys, :name) +description(sys::AbstractSystem) = has_description(sys) ? get_description(sys) : "" #Deprecated function independent_variable(sys::AbstractSystem) @@ -1895,7 +1896,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t rows = first(displaysize(io)) ÷ 5 # then allocate ≈1/5 of display height to each list # Print name and description - desc = get_description(sys) + desc = description(sys) printstyled(io, "Model ", nameof(sys), ":"; bold) !isempty(desc) && print(io, " ", desc) @@ -1909,7 +1910,7 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t sub = subs[i] name = String(nameof(sub)) print(io, "\n ", name) - desc = get_description(sub) + desc = description(sub) if !isempty(desc) maxlen = displaysize(io)[2] - length(name) - 6 # remaining length of line if limit && length(desc) > maxlen @@ -2913,7 +2914,7 @@ end function AbstractTrees.printnode( io::IO, sys::AbstractSystem; describe = false, bold = false) printstyled(io, nameof(sys); bold) - describe && !isempty(get_description(sys)) && print(io, ": ", get_description(sys)) + describe && !isempty(description(sys)) && print(io, ": ", description(sys)) end """ hierarchy(sys::AbstractSystem; describe = false, bold = describe, kwargs...) @@ -3006,7 +3007,7 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol = nam cevs = union(get_continuous_events(basesys), get_continuous_events(sys)) devs = union(get_discrete_events(basesys), get_discrete_events(sys)) defs = merge(get_defaults(basesys), get_defaults(sys)) # prefer `sys` - desc = join(filter(desc -> !isempty(desc), get_description.([sys, basesys])), " ") # concatenate non-empty descriptions with space + desc = join(filter(desc -> !isempty(desc), description.([sys, basesys])), " ") # concatenate non-empty descriptions with space meta = union_nothing(get_metadata(basesys), get_metadata(sys)) syss = union(get_systems(basesys), get_systems(sys)) args = length(ivs) == 0 ? (eqs, sts, ps) : (eqs, ivs[1], sts, ps) diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 7055da3ac9..2341927ff1 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -399,7 +399,7 @@ function flatten(sys::ODESystem, noeqs = false) discrete_events = discrete_events(sys), defaults = defaults(sys), name = nameof(sys), - description = get_description(sys), + description = description(sys), initialization_eqs = initialization_equations(sys), is_dde = is_dde(sys), checks = false) diff --git a/src/systems/diffeqs/sdesystem.jl b/src/systems/diffeqs/sdesystem.jl index e8a72b81cb..9f3814774f 100644 --- a/src/systems/diffeqs/sdesystem.jl +++ b/src/systems/diffeqs/sdesystem.jl @@ -355,7 +355,7 @@ function stochastic_integral_transform(sys::SDESystem, correction_factor) end SDESystem(deqs, get_noiseeqs(sys), get_iv(sys), unknowns(sys), parameters(sys), - name = name, description = get_description(sys), + name = name, description = description(sys), parameter_dependencies = parameter_dependencies(sys), checks = false) end @@ -464,7 +464,7 @@ function Girsanov_transform(sys::SDESystem, u; θ0 = 1.0) # return modified SDE System SDESystem(deqs, noiseeqs, get_iv(sys), unknown_vars, parameters(sys); defaults = Dict(θ => θ0), observed = [weight ~ θ / θ0], - name = name, description = get_description(sys), + name = name, description = description(sys), parameter_dependencies = parameter_dependencies(sys), checks = false) end diff --git a/src/systems/discrete_system/discrete_system.jl b/src/systems/discrete_system/discrete_system.jl index 5e7ae46a08..3e220998cb 100644 --- a/src/systems/discrete_system/discrete_system.jl +++ b/src/systems/discrete_system/discrete_system.jl @@ -226,7 +226,7 @@ function flatten(sys::DiscreteSystem, noeqs = false) observed = observed(sys), defaults = defaults(sys), name = nameof(sys), - description = get_description(sys), + description = description(sys), checks = false) end end diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index f1b438f0bb..3b0e4b7e92 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -561,7 +561,7 @@ function flatten(sys::NonlinearSystem, noeqs = false) observed = observed(sys), defaults = defaults(sys), name = nameof(sys), - description = get_description(sys), + description = description(sys), checks = false) end end From 668bffae6b1744bf31cd44e9f75a88778ace515c Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 20:44:09 +0200 Subject: [PATCH 16/17] Show separate Observed: category instead of mashing it in Equations: --- src/systems/abstractsystem.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 1a3c725166..ddaeb172f3 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1927,12 +1927,10 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t if eqs isa AbstractArray && eltype(eqs) <: Equation neqs = count(eq -> !(eq.lhs isa Connection), eqs) next = n_expanded_connection_equations(sys) - nobs = has_observed(sys) ? length(observed(sys)) : 0 - ntot = neqs + next + nobs + ntot = neqs + next ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) neqs > 0 && print(io, "\n $neqs standard", hint ? ": see equations(sys)" : "") next > 0 && print(io, "\n $next connecting", hint ? ": see equations(expand_connections(sys))" : "") - nobs > 0 && print(io, "\n $nobs observed", hint ? ": see observed(sys)" : "") #Base.print_matrix(io, eqs) # usually too long and not useful to print all equations end @@ -1969,6 +1967,11 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t limited && printstyled(io, "\n ⋮") # too many variables to print end + # Print observed + nobs = has_observed(sys) ? length(observed(sys)) : 0 + nobs > 0 && printstyled(io, "\nObserved ($nobs):"; bold) + nobs > 0 && hint && print(io, " see observed(sys)") + return nothing end From efad630bd65ed1ba74c0a640f1a5045a6a27af2a Mon Sep 17 00:00:00 2001 From: Herman Sletmoen Date: Sun, 20 Oct 2024 23:58:12 +0200 Subject: [PATCH 17/17] Format --- src/systems/abstractsystem.jl | 6 ++++-- src/systems/diffeqs/odesystem.jl | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index ddaeb172f3..226c4ff55d 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -1891,7 +1891,8 @@ function n_expanded_connection_equations(sys::AbstractSystem) nextras = n_outer_stream_variables + length(ceqs) end -function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = true, bold = true) +function Base.show( + io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = true, bold = true) limit = get(io, :limit, false) # if output should be limited, rows = first(displaysize(io)) ÷ 5 # then allocate ≈1/5 of display height to each list @@ -1930,7 +1931,8 @@ function Base.show(io::IO, mime::MIME"text/plain", sys::AbstractSystem; hint = t ntot = neqs + next ntot > 0 && printstyled(io, "\nEquations ($ntot):"; bold) neqs > 0 && print(io, "\n $neqs standard", hint ? ": see equations(sys)" : "") - next > 0 && print(io, "\n $next connecting", hint ? ": see equations(expand_connections(sys))" : "") + next > 0 && print(io, "\n $next connecting", + hint ? ": see equations(expand_connections(sys))" : "") #Base.print_matrix(io, eqs) # usually too long and not useful to print all equations end diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 2341927ff1..2176e53d55 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -707,7 +707,8 @@ end function Base.show(io::IO, mime::MIME"text/plain", sys::ODESystem; hint = true, bold = true) # Print general AbstractSystem information - invoke(Base.show, Tuple{typeof(io), typeof(mime), AbstractSystem}, io, mime, sys; hint, bold) + invoke(Base.show, Tuple{typeof(io), typeof(mime), AbstractSystem}, + io, mime, sys; hint, bold) # Print initialization equations (unique to ODESystems) nini = length(initialization_equations(sys))