From da60fbf6e707ba78b05c3e80ae40eb0efb63a493 Mon Sep 17 00:00:00 2001 From: vyudu Date: Fri, 18 Apr 2025 18:02:18 -0400 Subject: [PATCH 01/18] refactor: remove input_idxs output --- src/inputoutput.jl | 18 ++++++------ src/systems/clock_inference.jl | 13 +++++++++ src/systems/systems.jl | 18 +++++++----- src/systems/systemstructure.jl | 51 +++++++++++++++------------------- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 28b60b13dc..ebd3e25af6 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -179,9 +179,6 @@ The return values also include the chosen state-realization (the remaining unkno If `disturbance_inputs` is an array of variables, the generated dynamics function will preserve any state and dynamics associated with disturbance inputs, but the disturbance inputs themselves will (by default) not be included as inputs to the generated function. The use case for this is to generate dynamics for state observers that estimate the influence of unmeasured disturbances, and thus require unknown variables for the disturbance model, but without disturbance inputs since the disturbances are not available for measurement. To add an input argument corresponding to the disturbance inputs, either include the disturbance inputs among the control inputs, or set `disturbance_argument=true`, in which case an additional input argument `w` is added to the generated function `(x,u,p,t,w)->rhs`. -!!! note "Un-simplified system" - This function expects `sys` to be un-simplified, i.e., `structural_simplify` or `@mtkbuild` should not be called on the system before passing it into this function. `generate_control_function` calls a special version of `structural_simplify` internally. - # Example ``` @@ -201,15 +198,17 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu eval_expression = false, eval_module = @__MODULE__, kwargs...) - isempty(inputs) && @warn("No unbound inputs were found in system.") + # Remove this when the ControlFunction gets merged. + if !iscomplete(sys) + error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating the control function.") + end + isempty(inputs) && @warn("No unbound inputs were found in system.") if disturbance_inputs !== nothing # add to inputs for the purposes of io processing inputs = [inputs; disturbance_inputs] end - sys, _ = io_preprocessing(sys, inputs, []; simplify, kwargs...) - dvs = unknowns(sys) ps = parameters(sys; initial_parameters = true) ps = setdiff(ps, inputs) @@ -257,8 +256,11 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu (; f, dvs, ps, io_sys = sys) end -function inputs_to_parameters!(state::TransformationState, io) - check_bound = io === nothing +""" +Turn input variables into parameters of the system. +""" +function inputs_to_parameters!(state::TransformationState, inputsyms) + check_bound = inputsyms === nothing @unpack structure, fullvars, sys = state @unpack var_to_diff, graph, solvable_graph = structure @assert solvable_graph === nothing diff --git a/src/systems/clock_inference.jl b/src/systems/clock_inference.jl index b535773061..42fe28f7c7 100644 --- a/src/systems/clock_inference.jl +++ b/src/systems/clock_inference.jl @@ -1,7 +1,11 @@ struct ClockInference{S} + """Tearing state.""" ts::S + """The time domain (discrete clock, continuous) of each equation.""" eq_domain::Vector{TimeDomain} + """The output time domain (discrete clock, continuous) of each variable.""" var_domain::Vector{TimeDomain} + """The set of variables with concrete domains.""" inferred::BitSet end @@ -67,6 +71,9 @@ function substitute_sample_time(ex, dt) end end +""" +Update the equation-to-time domain mapping by inferring the time domain from the variables. +""" function infer_clocks!(ci::ClockInference) @unpack ts, eq_domain, var_domain, inferred = ci @unpack var_to_diff, graph = ts.structure @@ -132,6 +139,9 @@ function is_time_domain_conversion(v) input_timedomain(o) != output_timedomain(o) end +""" +For multi-clock systems, create a separate system for each clock in the system, along with associated equations. Return the updated tearing state, and the sets of clocked variables associated with each time domain. +""" function split_system(ci::ClockInference{S}) where {S} @unpack ts, eq_domain, var_domain, inferred = ci fullvars = get_fullvars(ts) @@ -143,11 +153,14 @@ function split_system(ci::ClockInference{S}) where {S} cid_to_eq = Vector{Int}[] var_to_cid = Vector{Int}(undef, ndsts(graph)) cid_to_var = Vector{Int}[] + # cid_counter = number of clocks cid_counter = Ref(0) for (i, d) in enumerate(eq_domain) cid = let cid_counter = cid_counter, id_to_clock = id_to_clock, continuous_id = continuous_id + # Fill the clock_to_id dict as you go, + # ContinuousClock() => 1, ... get!(clock_to_id, d) do cid = (cid_counter[] += 1) push!(id_to_clock, d) diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 52f93afb9b..e27916d994 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -26,13 +26,16 @@ topological sort of the observed equations in `sys`. + `fully_determined=true` controls whether or not an error will be thrown if the number of equations don't match the number of inputs, outputs, and equations. + `sort_eqs=true` controls whether equations are sorted lexicographically before simplification or not. """ -function structural_simplify( - sys::AbstractSystem, io = nothing; additional_passes = [], simplify = false, split = true, +function mtkbuild( + sys::AbstractSystem; additional_passes = [], simplify = false, split = true, allow_symbolic = false, allow_parameter = true, conservative = false, fully_determined = true, + inputs = nothing, outputs = nothing, + disturbance_inputs = nothing, kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) - newsys′ = __structural_simplify(sys, io; simplify, + newsys′ = __structural_simplify(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, + inputs, outputs, disturbance_inputs, kwargs...) if newsys′ isa Tuple @assert length(newsys′) == 2 @@ -70,8 +73,9 @@ function __structural_simplify(sys::SDESystem, args...; kwargs...) return __structural_simplify(ODESystem(sys), args...; kwargs...) end -function __structural_simplify( - sys::AbstractSystem, io = nothing; simplify = false, sort_eqs = true, +function __structural_simplify(sys::AbstractSystem; simplify = false, + inputs = nothing, outputs = nothing, + disturbance_inputs = nothing, kwargs...) sys = expand_connections(sys) state = TearingState(sys; sort_eqs) @@ -90,7 +94,7 @@ function __structural_simplify( end end if isempty(brown_vars) - return structural_simplify!(state, io; simplify, kwargs...) + return structural_simplify!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) else Is = Int[] Js = Int[] @@ -123,7 +127,7 @@ function __structural_simplify( if !iszero(new_idxs[i]) && invview(var_to_diff)[i] === nothing] # TODO: IO is not handled. - ode_sys = structural_simplify(sys, io; simplify, kwargs...) + ode_sys = structural_simplify(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) eqs = equations(ode_sys) sorted_g_rows = zeros(Num, length(eqs), size(g, 2)) for (i, eq) in enumerate(eqs) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index e0feb0d34d..aa544c8db1 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -657,29 +657,22 @@ function Base.show(io::IO, mime::MIME"text/plain", ms::MatchedSystemStructure) printstyled(io, " SelectedState") end -# TODO: clean up -function merge_io(io, inputs) - isempty(inputs) && return io - if io === nothing - io = (inputs, []) - else - io = ([inputs; io[1]], io[2]) - end - return io -end - -function structural_simplify!(state::TearingState, io = nothing; simplify = false, +function structural_simplify!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = true, + inputs = nothing, outputs = nothing, + disturbance_inputs = nothing, kwargs...) + if state.sys isa ODESystem ci = ModelingToolkit.ClockInference(state) ci = ModelingToolkit.infer_clocks!(ci) time_domains = merge(Dict(state.fullvars .=> ci.var_domain), Dict(default_toterm.(state.fullvars) .=> ci.var_domain)) - tss, inputs, continuous_id, id_to_clock = ModelingToolkit.split_system(ci) - cont_io = merge_io(io, inputs[continuous_id]) - sys, input_idxs = _structural_simplify!(tss[continuous_id], cont_io; simplify, + tss, clocked_inputs, continuous_id, id_to_clock = ModelingToolkit.split_system(ci) + cont_inputs = [inputs; clocked_inputs[continuous_id]] + sys = _structural_simplify!(tss[continuous_id]; simplify, check_consistency, fully_determined, + cont_inputs, outputs, disturbance_inputs, kwargs...) if length(tss) > 1 if continuous_id > 0 @@ -695,8 +688,9 @@ function structural_simplify!(state::TearingState, io = nothing; simplify = fals discrete_subsystems[i] = sys continue end - dist_io = merge_io(io, inputs[i]) - ss, = _structural_simplify!(state, dist_io; simplify, check_consistency, + disc_inputs = [inputs; clocked_inputs[i]] + ss, = _structural_simplify!(state; simplify, check_consistency, + disc_inputs, outputs, disturbance_inputs, fully_determined, kwargs...) append!(appended_parameters, inputs[i], unknowns(ss)) discrete_subsystems[i] = ss @@ -713,32 +707,31 @@ function structural_simplify!(state::TearingState, io = nothing; simplify = fals for sym in get_ps(sys)] @set! sys.ps = ps else - sys, input_idxs = _structural_simplify!(state, io; simplify, check_consistency, + sys = _structural_simplify!(state; simplify, check_consistency, + inputs, outputs, disturbance_inputs, fully_determined, kwargs...) end - has_io = io !== nothing - return has_io ? (sys, input_idxs) : sys + return sys end -function _structural_simplify!(state::TearingState, io; simplify = false, +function _structural_simplify!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = false, dummy_derivative = true, + inputs = nothing, outputs = nothing, + disturbance_inputs = nothing, kwargs...) if fully_determined isa Bool check_consistency &= fully_determined else check_consistency = true end - has_io = io !== nothing + has_io = inputs !== nothing || outputs !== nothing orig_inputs = Set() if has_io - ModelingToolkit.markio!(state, orig_inputs, io...) - end - if io !== nothing - state, input_idxs = ModelingToolkit.inputs_to_parameters!(state, io) - else - input_idxs = 0:-1 # Empty range + ModelingToolkit.markio!(state, orig_inputs, inputs, outputs) + state = ModelingToolkit.inputs_to_parameters!(state, inputs) end + sys, mm = ModelingToolkit.alias_elimination!(state; kwargs...) if check_consistency fully_determined = ModelingToolkit.check_consistency( @@ -761,5 +754,5 @@ function _structural_simplify!(state::TearingState, io; simplify = false, fullunknowns = [observables(sys); unknowns(sys)] @set! sys.observed = ModelingToolkit.topsort_equations(observed(sys), fullunknowns) - ModelingToolkit.invalidate_cache!(sys), input_idxs + ModelingToolkit.invalidate_cache!(sys) end From 9b676bd92c1c4834cf7f172c74b6ab98e0da8b1e Mon Sep 17 00:00:00 2001 From: vyudu Date: Mon, 21 Apr 2025 14:42:16 -0400 Subject: [PATCH 02/18] refactor: require simplify system for linearization --- docs/src/basics/Linearization.md | 17 ++++------ src/linearization.jl | 55 ++++++++++++++++---------------- src/systems/abstractsystem.jl | 15 --------- 3 files changed, 35 insertions(+), 52 deletions(-) diff --git a/docs/src/basics/Linearization.md b/docs/src/basics/Linearization.md index 1c06ce72d4..78b6d5925d 100644 --- a/docs/src/basics/Linearization.md +++ b/docs/src/basics/Linearization.md @@ -15,7 +15,7 @@ y &= Cx + Du \end{aligned} ``` -The `linearize` function expects the user to specify the inputs ``u`` and the outputs ``y`` using the syntax shown in the example below. The system model is *not* supposed to be simplified before calling `linearize`: +The `linearize` function expects the user to specify the inputs ``u`` and the outputs ``y`` using the syntax shown in the example below. ## Example @@ -29,7 +29,7 @@ eqs = [u ~ kp * (r - y) # P controller D(x) ~ -x + u # First-order plant y ~ x] # Output equation -@named sys = ODESystem(eqs, t) # Do not call @mtkbuild when linearizing +@mtkbuild sys = ODESystem(eqs, t) # Do not call @mtkbuild when linearizing matrices, simplified_sys = linearize(sys, [r], [y]) # Linearize from r to y matrices ``` @@ -45,10 +45,6 @@ using ModelingToolkit: inputs, outputs The model above has 4 variables but only three equations, there is no equation specifying the value of `r` since `r` is an input. This means that only unbalanced models can be linearized, or in other words, models that are balanced and can be simulated _cannot_ be linearized. To learn more about this, see [How to linearize a ModelingToolkit model (YouTube)](https://www.youtube.com/watch?v=-XOux-2XDGI&t=395s). Also see [ModelingToolkitStandardLibrary: Linear analysis](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/linear_analysis/) for utilities that make linearization of completed models easier. -!!! note "Un-simplified system" - - Linearization expects `sys` to be un-simplified, i.e., `structural_simplify` or `@mtkbuild` should not be called on the system before linearizing. - ## Operating point The operating point to linearize around can be specified with the keyword argument `op` like this: `op = Dict(x => 1, r => 2)`. The operating point may include specification of unknown variables, input variables and parameters. For variables that are not specified in `op`, the default value specified in the model will be used if available, if no value is specified, an error is thrown. @@ -79,14 +75,15 @@ eqs = [D(x) ~ v y.u ~ x] @named duffing = ODESystem(eqs, t, systems = [y, u], defaults = [u.u => 0]) +duffing = structural_simplify(duffing, inputs = [u.u], outputs = [y.u]) # pass a constant value for `x`, since it is the variable we will change in operating points -linfun, simplified_sys = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); +linfun = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); -println(linearize(simplified_sys, linfun; op = Dict(x => 1.0))) -println(linearize(simplified_sys, linfun; op = Dict(x => 0.0))) +println(linearize(duffing, linfun; op = Dict(x => 1.0))) +println(linearize(duffing, linfun; op = Dict(x => 0.0))) -@time linearize(simplified_sys, linfun; op = Dict(x => 0.0)) +@time linearize(duffing, linfun; op = Dict(x => 0.0)) nothing # hide ``` diff --git a/src/linearization.jl b/src/linearization.jl index 77f4422b63..2e958ecc73 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -1,5 +1,5 @@ """ - lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; simplify = false, initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) + lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) Return a function that linearizes the system `sys`. The function [`linearize`](@ref) provides a higher-level and easier to use interface. @@ -22,7 +22,6 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ - `sys`: An [`ODESystem`](@ref). This function will automatically apply simplification passes on `sys` and return the resulting `simplified_sys`. - `inputs`: A vector of variables that indicate the inputs of the linearized input-output model. - `outputs`: A vector of variables that indicate the outputs of the linearized input-output model. - - `simplify`: Apply simplification in tearing. - `initialize`: If true, a check is performed to ensure that the operating point is consistent (satisfies algebraic equations). If the op is not consistent, initialization is performed. - `initialization_solver_alg`: A NonlinearSolve algorithm to use for solving for a feasible set of state and algebraic variables that satisfies the specified operating point. - `autodiff`: An `ADType` supported by DifferentiationInterface.jl to use for calculating the necessary jacobians. Defaults to using `AutoForwardDiff()` @@ -31,7 +30,7 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ See also [`linearize`](@ref) which provides a higher-level interface. """ function linearization_function(sys::AbstractSystem, inputs, - outputs; simplify = false, + outputs; initialize = true, initializealg = nothing, initialization_abstol = 1e-5, @@ -58,16 +57,7 @@ function linearization_function(sys::AbstractSystem, inputs, outputs = mapreduce(vcat, outputs; init = []) do var symbolic_type(var) == ArraySymbolic() ? collect(var) : [var] end - ssys, diff_idxs, alge_idxs, input_idxs = io_preprocessing(sys, inputs, outputs; - simplify, - kwargs...) - if zero_dummy_der - dummyder = setdiff(unknowns(ssys), unknowns(sys)) - defs = Dict(x => 0.0 for x in dummyder) - @set! ssys.defaults = merge(defs, defaults(ssys)) - op = merge(defs, op) - end - sys = ssys + diff_idxs, alge_idxs = eq_idxs(sys) if initializealg === nothing initializealg = initialize ? OverrideInit() : NoInit() @@ -87,9 +77,9 @@ function linearization_function(sys::AbstractSystem, inputs, p = parameter_values(prob) t0 = current_time(prob) - inputvals = [p[idx] for idx in input_idxs] + inputvals = [prob.ps[i] for i in inputs] - hp_fun = let fun = h, setter = setp_oop(sys, input_idxs) + hp_fun = let fun = h, setter = setp_oop(sys, inputs) function hpf(du, input, u, p, t) p = setter(p, input) fun(du, u, p, t) @@ -113,7 +103,7 @@ function linearization_function(sys::AbstractSystem, inputs, # observed function is a `GeneratedFunctionWrapper` with iip component h_jac = PreparedJacobian{true}(h, similar(prob.u0, size(outputs)), autodiff, prob.u0, DI.Constant(p), DI.Constant(t0)) - pf_fun = let fun = prob.f, setter = setp_oop(sys, input_idxs) + pf_fun = let fun = prob.f, setter = setp_oop(sys, inputs) function pff(du, input, u, p, t) p = setter(p, input) SciMLBase.ParamJacobianWrapper(fun, t, u)(du, p) @@ -127,10 +117,22 @@ function linearization_function(sys::AbstractSystem, inputs, end lin_fun = LinearizationFunction( - diff_idxs, alge_idxs, input_idxs, length(unknowns(sys)), + diff_idxs, alge_idxs, length(unknowns(sys)), prob, h, u0 === nothing ? nothing : similar(u0), uf_jac, h_jac, pf_jac, hp_jac, initializealg, initialization_kwargs) - return lin_fun, sys + return lin_fun +end + +function eq_idxs(sys::AbstractSystem) + eqs = equations(sys) + alg_start_idx = findfirst(!isdiffeq, eqs) + if alg_start_idx === nothing + alg_start_idx = length(eqs) + 1 + end + diff_idxs = 1:(alg_start_idx - 1) + alge_idxs = alg_start_idx:length(eqs) + + diff_idxs, alge_idxs end """ @@ -206,7 +208,7 @@ struct LinearizationFunction{ The indexes of parameters in the linearized system which represent input variables. """ - input_idxs::II + inputs::II """ The number of unknowns in the linearized system. """ @@ -281,6 +283,7 @@ function (linfun::LinearizationFunction)(u, p, t) end fun = linfun.prob.f + input_vals = [linfun.prob.ps[i] for i in linfun.inputs] if u !== nothing # Handle systems without unknowns linfun.num_states == length(u) || error("Number of unknown variables ($(linfun.num_states)) does not match the number of input unknowns ($(length(u)))") @@ -294,15 +297,15 @@ function (linfun::LinearizationFunction)(u, p, t) end fg_xz = linfun.uf_jac(u, DI.Constant(p), DI.Constant(t)) h_xz = linfun.h_jac(u, DI.Constant(p), DI.Constant(t)) - fg_u = linfun.pf_jac([p[idx] for idx in linfun.input_idxs], + fg_u = linfun.pf_jac(input_vals, DI.Constant(u), DI.Constant(p), DI.Constant(t)) else linfun.num_states == 0 || error("Number of unknown variables (0) does not match the number of input unknowns ($(length(u)))") fg_xz = zeros(0, 0) - h_xz = fg_u = zeros(0, length(linfun.input_idxs)) + h_xz = fg_u = zeros(0, length(linfun.inputs)) end - h_u = linfun.hp_jac([p[idx] for idx in linfun.input_idxs], + h_u = linfun.hp_jac(input_vals, DI.Constant(u), DI.Constant(p), DI.Constant(t)) (f_x = fg_xz[linfun.diff_idxs, linfun.diff_idxs], f_z = fg_xz[linfun.diff_idxs, linfun.alge_idxs], @@ -461,7 +464,7 @@ function CommonSolve.solve(prob::LinearizationProblem; allow_input_derivatives = end """ - (; A, B, C, D), simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; simplify = false, allow_input_derivatives = false, kwargs...) + (; A, B, C, D), simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; allow_input_derivatives = false, kwargs...) Similar to [`linearize`](@ref), but returns symbolic matrices `A,B,C,D` rather than numeric. While `linearize` uses ForwardDiff to perform the linearization, this function uses `Symbolics.jacobian`. @@ -479,12 +482,10 @@ y &= h(x, z, u) where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. """ function linearize_symbolic(sys::AbstractSystem, inputs, - outputs; simplify = false, allow_input_derivatives = false, + outputs; allow_input_derivatives = false, eval_expression = false, eval_module = @__MODULE__, kwargs...) - sys, diff_idxs, alge_idxs, input_idxs = io_preprocessing( - sys, inputs, outputs; simplify, - kwargs...) + diff_idxs, alge_idxs = eq_idxs(sys) sts = unknowns(sys) t = get_iv(sys) ps = parameters(sys; initial_parameters = true) diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 1252367d2b..025199c92b 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -2484,21 +2484,6 @@ function eliminate_constants(sys::AbstractSystem) return sys end -function io_preprocessing(sys::AbstractSystem, inputs, - outputs; simplify = false, kwargs...) - sys, input_idxs = structural_simplify(sys, (inputs, outputs); simplify, kwargs...) - - eqs = equations(sys) - alg_start_idx = findfirst(!isdiffeq, eqs) - if alg_start_idx === nothing - alg_start_idx = length(eqs) + 1 - end - diff_idxs = 1:(alg_start_idx - 1) - alge_idxs = alg_start_idx:length(eqs) - - sys, diff_idxs, alge_idxs, input_idxs -end - @latexrecipe function f(sys::AbstractSystem) return latexify(equations(sys)) end From 0f6d9ba8108a8af6c36d5cbdf7dd798950db94b6 Mon Sep 17 00:00:00 2001 From: vyudu Date: Mon, 21 Apr 2025 16:28:55 -0400 Subject: [PATCH 03/18] use mtkbuild --- docs/src/basics/AbstractSystem.md | 2 +- docs/src/basics/Composition.md | 10 ++-- docs/src/basics/Debugging.md | 2 +- docs/src/basics/Events.md | 4 +- docs/src/basics/FAQ.md | 6 +- docs/src/basics/InputOutput.md | 4 -- docs/src/basics/Linearization.md | 2 +- docs/src/basics/MTKLanguage.md | 6 +- docs/src/basics/Precompilation.md | 2 +- docs/src/basics/Validation.md | 2 +- docs/src/comparison.md | 4 +- docs/src/examples/higher_order.md | 4 +- .../modelingtoolkitize_index_reduction.md | 4 +- docs/src/examples/spring_mass.md | 8 +-- docs/src/examples/tearing_parallelism.md | 6 +- docs/src/internals.md | 2 +- docs/src/systems/DiscreteSystem.md | 2 +- docs/src/systems/ImplicitDiscreteSystem.md | 2 +- docs/src/systems/JumpSystem.md | 2 +- docs/src/systems/NonlinearSystem.md | 2 +- docs/src/systems/ODESystem.md | 2 +- docs/src/systems/SDESystem.md | 2 +- docs/src/tutorials/acausal_components.md | 2 +- docs/src/tutorials/attractors.md | 2 +- .../tutorials/change_independent_variable.md | 8 +-- docs/src/tutorials/domain_connections.md | 8 +-- docs/src/tutorials/fmi.md | 6 +- docs/src/tutorials/initialization.md | 6 +- .../tutorials/programmatically_generating.md | 2 +- ext/MTKBifurcationKitExt.jl | 4 +- ext/MTKFMIExt.jl | 2 +- src/ModelingToolkit.jl | 4 +- src/inputoutput.jl | 2 +- src/linearization.jl | 26 +++++---- .../StructuralTransformations.jl | 2 +- src/structural_transformation/pantelides.jl | 2 +- .../symbolics_tearing.jl | 2 +- src/systems/abstractsystem.jl | 16 ++--- src/systems/diffeqs/abstractodesystem.jl | 34 +++++------ src/systems/diffeqs/basic_transformations.jl | 4 +- src/systems/diffeqs/odesystem.jl | 4 +- src/systems/diffeqs/sdesystem.jl | 10 ++-- .../discrete_system/discrete_system.jl | 4 +- .../implicit_discrete_system.jl | 4 +- src/systems/index_cache.jl | 4 +- src/systems/jumps/jumpsystem.jl | 8 +-- .../nonlinear/homotopy_continuation.jl | 4 +- src/systems/nonlinear/nonlinearsystem.jl | 24 ++++---- .../optimization/optimizationsystem.jl | 8 +-- src/systems/parameter_buffer.jl | 2 +- src/systems/systems.jl | 18 +++--- src/systems/systemstructure.jl | 12 ++-- src/utils.jl | 8 +-- test/accessor_functions.jl | 10 ++-- test/analysis_points.jl | 2 +- test/basic_transformations.jl | 20 +++---- test/clock.jl | 14 ++--- test/code_generation.jl | 2 +- test/components.jl | 26 ++++----- test/constants.jl | 6 +- test/dde.jl | 8 +-- test/debugging.jl | 4 +- test/discrete_system.jl | 4 +- test/domain_connectors.jl | 2 +- test/downstream/analysis_points.jl | 22 +++---- test/downstream/inversemodel.jl | 2 +- test/downstream/linearize.jl | 27 +++++---- test/downstream/test_disturbance_model.jl | 10 ++-- test/dq_units.jl | 8 +-- test/error_handling.jl | 4 +- test/extensions/ad.jl | 4 +- test/extensions/bifurcationkit.jl | 4 +- test/funcaffect.jl | 8 +-- test/guess_propagation.jl | 8 +-- test/hierarchical_initialization_eqs.jl | 2 +- test/if_lifting.jl | 6 +- test/initializationsystem.jl | 26 ++++----- test/input_output_handling.jl | 18 +++--- test/jumpsystem.jl | 2 +- test/modelingtoolkitize.jl | 2 +- test/mtkparameters.jl | 6 +- test/nonlinearsystem.jl | 20 +++---- test/odesystem.jl | 58 +++++++++---------- test/optimizationsystem.jl | 2 +- test/parameter_dependencies.jl | 4 +- test/reduction.jl | 28 ++++----- test/scc_nonlinear_problem.jl | 4 +- test/sciml_problem_inputs.jl | 2 +- test/sdesystem.jl | 14 ++--- test/split_parameters.jl | 4 +- test/state_selection.jl | 6 +- test/static_arrays.jl | 2 +- test/stream_connectors.jl | 12 ++-- .../index_reduction.jl | 4 +- test/structural_transformation/tearing.jl | 6 +- test/structural_transformation/utils.jl | 10 ++-- test/substitute_component.jl | 4 +- test/symbolic_events.jl | 48 +++++++-------- test/symbolic_indexing_interface.jl | 2 +- test/units.jl | 8 +-- test/variable_scope.jl | 2 +- 101 files changed, 414 insertions(+), 405 deletions(-) diff --git a/docs/src/basics/AbstractSystem.md b/docs/src/basics/AbstractSystem.md index d1707f822f..276fcb44f0 100644 --- a/docs/src/basics/AbstractSystem.md +++ b/docs/src/basics/AbstractSystem.md @@ -152,7 +152,7 @@ a lower level in the system. ## Namespacing By default, unsimplified systems will namespace variables accessed via `getproperty`. -Systems created via `@mtkbuild`, or ones passed through `structural_simplify` or +Systems created via `@mtkbuild`, or ones passed through `mtkbuild` or `complete` will not perform this namespacing. However, all of these processes modify the system in a variety of ways. To toggle namespacing without transforming any other property of the system, use `toggle_namespacing`. diff --git a/docs/src/basics/Composition.md b/docs/src/basics/Composition.md index d3de71d696..ba5fe48137 100644 --- a/docs/src/basics/Composition.md +++ b/docs/src/basics/Composition.md @@ -42,7 +42,7 @@ equations(connected) # Differential(t)(decay1₊x(t)) ~ decay1₊f(t) - (decay1₊a*(decay1₊x(t))) # Differential(t)(decay2₊x(t)) ~ decay2₊f(t) - (decay2₊a*(decay2₊x(t))) -simplified_sys = structural_simplify(connected) +simplified_sys = mtkbuild(connected) equations(simplified_sys) ``` @@ -84,7 +84,7 @@ example, let's say there is a variable `x` in `unknowns` and a variable `x` in `subsys`. We can declare that these two variables are the same by specifying their equality: `x ~ subsys.x` in the `eqs` for `sys`. This algebraic relationship can then be simplified by transformations -like `structural_simplify` which will be described later. +like `mtkbuild` which will be described later. ### Numerics with Composed Models @@ -169,7 +169,7 @@ parameters(level3) In many cases, the nicest way to build a model may leave a lot of unnecessary variables. Thus one may want to remove these equations -before numerically solving. The `structural_simplify` function removes +before numerically solving. The `mtkbuild` function removes these trivial equality relationships and trivial singularity equations, i.e. equations which result in `0~0` expressions, in over-specified systems. @@ -227,7 +227,7 @@ values. The user of this model can then solve this model simply by specifying the values at the highest level: ```@example compose -sireqn_simple = structural_simplify(sir) +sireqn_simple = mtkbuild(sir) equations(sireqn_simple) ``` @@ -251,7 +251,7 @@ sol[reqn.R] ## Tearing Problem Construction Some system types (specifically `NonlinearSystem`) can be further -reduced if `structural_simplify` has already been applied to them. This is done +reduced if `mtkbuild` has already been applied to them. This is done by using the alternative problem constructors (`BlockNonlinearProblem`). In these cases, the constructor uses the knowledge of the strongly connected components calculated during the process of simplification diff --git a/docs/src/basics/Debugging.md b/docs/src/basics/Debugging.md index 6e2d471461..45384ecf9c 100644 --- a/docs/src/basics/Debugging.md +++ b/docs/src/basics/Debugging.md @@ -13,7 +13,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = [D(u1) ~ -√(u1), D(u2) ~ -√(u2), D(u3) ~ -√(u3)] defaults = [u1 => 1.0, u2 => 2.0, u3 => 3.0] @named sys = ODESystem(eqs, t; defaults) -sys = structural_simplify(sys) +sys = mtkbuild(sys) ``` This problem causes the ODE solver to crash: diff --git a/docs/src/basics/Events.md b/docs/src/basics/Events.md index 3a76f478f1..125588540b 100644 --- a/docs/src/basics/Events.md +++ b/docs/src/basics/Events.md @@ -472,7 +472,7 @@ to the system. ```@example events @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_disable, furnace_enable]) -ss = structural_simplify(sys) +ss = mtkbuild(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 10.0)) sol = solve(prob, Tsit5()) plot(sol) @@ -585,7 +585,7 @@ We can now simulate the encoder. ```@example events @named sys = ODESystem( eqs, t, [theta, omega], params; continuous_events = [qAevt, qBevt]) -ss = structural_simplify(sys) +ss = mtkbuild(sys) prob = ODEProblem(ss, [theta => 0.0], (0.0, pi)) sol = solve(prob, Tsit5(); dtmax = 0.01) sol.ps[cnt] diff --git a/docs/src/basics/FAQ.md b/docs/src/basics/FAQ.md index 10671299c6..52152b761b 100644 --- a/docs/src/basics/FAQ.md +++ b/docs/src/basics/FAQ.md @@ -28,7 +28,7 @@ are similarly undocumented. Following is the list of behaviors that should be re - `setindex!(::MTKParameters, value, ::ParameterIndex)` can be used to set the value of a parameter with the given index. - `parameter_values(sys, sym)` will return a `ParameterIndex` object if `sys` has been - `complete`d (through `structural_simplify`, `complete` or `@mtkbuild`). + `complete`d (through `mtkbuild`, `complete` or `@mtkbuild`). - `copy(::MTKParameters)` is defined and duplicates the parameter object, including the memory used by the underlying buffers. @@ -194,7 +194,7 @@ p, replace, alias = SciMLStructures.canonicalize(Tunable(), prob.p) # ERROR: ArgumentError: SymbolicUtils.BasicSymbolic{Real}[xˍt(t)] are missing from the variable map. -This error can come up after running `structural_simplify` on a system that generates dummy derivatives (i.e. variables with `ˍt`). For example, here even though all the variables are defined with initial values, the `ODEProblem` generation will throw an error that defaults are missing from the variable map. +This error can come up after running `mtkbuild` on a system that generates dummy derivatives (i.e. variables with `ˍt`). For example, here even though all the variables are defined with initial values, the `ODEProblem` generation will throw an error that defaults are missing from the variable map. ```julia using ModelingToolkit @@ -206,7 +206,7 @@ eqs = [x1 + x2 + 1 ~ 0 x1 + D(x3) + x4 + 3 ~ 0 2 * D(D(x1)) + D(D(x2)) + D(D(x3)) + D(x4) + 4 ~ 0] @named sys = ODESystem(eqs, t) -sys = structural_simplify(sys) +sys = mtkbuild(sys) prob = ODEProblem(sys, [], (0, 1)) ``` diff --git a/docs/src/basics/InputOutput.md b/docs/src/basics/InputOutput.md index 4dc5a3d50f..d6108d7cc4 100644 --- a/docs/src/basics/InputOutput.md +++ b/docs/src/basics/InputOutput.md @@ -28,10 +28,6 @@ ModelingToolkit can generate the dynamics of a system, the function ``M\dot x = This function takes a vector of variables that are to be considered inputs, i.e., part of the vector ``u``. Alongside returning the function ``f``, [`ModelingToolkit.generate_control_function`](@ref) also returns the chosen state realization of the system after simplification. This vector specifies the order of the state variables ``x``, while the user-specified vector `u` specifies the order of the input variables ``u``. -!!! note "Un-simplified system" - - This function expects `sys` to be un-simplified, i.e., `structural_simplify` or `@mtkbuild` should not be called on the system before passing it into this function. `generate_control_function` calls a special version of `structural_simplify` internally. - ### Example: The following example implements a simple first-order system with an input `u` and state `x`. The function `f` is generated using `generate_control_function`, and the function `f` is then tested with random input and state values. diff --git a/docs/src/basics/Linearization.md b/docs/src/basics/Linearization.md index 78b6d5925d..a95f2b0104 100644 --- a/docs/src/basics/Linearization.md +++ b/docs/src/basics/Linearization.md @@ -75,7 +75,7 @@ eqs = [D(x) ~ v y.u ~ x] @named duffing = ODESystem(eqs, t, systems = [y, u], defaults = [u.u => 0]) -duffing = structural_simplify(duffing, inputs = [u.u], outputs = [y.u]) +duffing = mtkbuild(duffing, inputs = [u.u], outputs = [y.u]) # pass a constant value for `x`, since it is the variable we will change in operating points linfun = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); diff --git a/docs/src/basics/MTKLanguage.md b/docs/src/basics/MTKLanguage.md index e91f2bcb67..db5ce3b723 100644 --- a/docs/src/basics/MTKLanguage.md +++ b/docs/src/basics/MTKLanguage.md @@ -535,10 +535,10 @@ This is equivalent to: ```julia @named model = CustomModel() -sys = structural_simplify(model) +sys = mtkbuild(model) ``` -Pass keyword arguments to `structural_simplify` using the following syntax: +Pass keyword arguments to `mtkbuild` using the following syntax: ```julia @mtkbuild sys=CustomModel() fully_determined=false @@ -548,5 +548,5 @@ This is equivalent to: ```julia @named model = CustomModel() -sys = structural_simplify(model; fully_determined = false) +sys = mtkbuild(model; fully_determined = false) ``` diff --git a/docs/src/basics/Precompilation.md b/docs/src/basics/Precompilation.md index 97111f0d6b..88a425710a 100644 --- a/docs/src/basics/Precompilation.md +++ b/docs/src/basics/Precompilation.md @@ -22,7 +22,7 @@ using ModelingToolkit @variables x(ModelingToolkit.t_nounits) @named sys = ODESystem([ModelingToolkit.D_nounits(x) ~ -x + 1], ModelingToolkit.t_nounits) -prob = ODEProblem(structural_simplify(sys), [x => 30.0], (0, 100), [], +prob = ODEProblem(mtkbuild(sys), [x => 30.0], (0, 100), [], eval_expression = true, eval_module = @__MODULE__) end diff --git a/docs/src/basics/Validation.md b/docs/src/basics/Validation.md index 79c5d0d214..39a51ccf68 100644 --- a/docs/src/basics/Validation.md +++ b/docs/src/basics/Validation.md @@ -112,7 +112,7 @@ ps = @parameters s=-1 [unit = u"cm"] c=c [unit = u"cm"] eqs = [D(a) ~ dummycomplex(c, s);] sys = ODESystem( eqs, t, [sts...;], [ps...;], name = :sys, checks = ~ModelingToolkit.CheckUnits) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) ``` ## `DynamicQuantities` Literals diff --git a/docs/src/comparison.md b/docs/src/comparison.md index 52d5ab2f70..0bf88b72c3 100644 --- a/docs/src/comparison.md +++ b/docs/src/comparison.md @@ -12,7 +12,7 @@ - All current Modelica compiler implementations are fixed and not extendable by the users from the Modelica language itself. For example, the Dymola compiler [shares its symbolic processing pipeline](https://www.claytex.com/tech-blog/model-translation-and-symbolic-manipulation/), - which is roughly equivalent to the `dae_index_lowering` and `structural_simplify` + which is roughly equivalent to the `dae_index_lowering` and `mtkbuild` of ModelingToolkit.jl. ModelingToolkit.jl is an open and hackable transformation system which allows users to add new non-standard transformations and control the order of application. @@ -90,7 +90,7 @@ [Dymola symbolic processing pipeline](https://www.claytex.com/tech-blog/model-translation-and-symbolic-manipulation/) with some improvements. ModelingToolkit.jl has an open transformation pipeline that allows for users to extend and reorder transformation passes, where - `structural_simplify` is an adaptation of the Modia.jl-improved alias elimination + `mtkbuild` is an adaptation of the Modia.jl-improved alias elimination and tearing algorithms. - Both Modia and ModelingToolkit generate `DAEProblem` and `ODEProblem` forms for solving with [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/). diff --git a/docs/src/examples/higher_order.md b/docs/src/examples/higher_order.md index fac707525f..6bdffb2ace 100644 --- a/docs/src/examples/higher_order.md +++ b/docs/src/examples/higher_order.md @@ -4,7 +4,7 @@ ModelingToolkit has a system for transformations of mathematical systems. These transformations allow for symbolically changing the representation of the model to problems that are easier to numerically solve. One simple to demonstrate transformation, is -`structural_simplify`, which does a lot of tricks, one being the +`mtkbuild`, which does a lot of tricks, one being the transformation that turns an Nth order ODE into N coupled 1st order ODEs. @@ -43,7 +43,7 @@ and this syntax extends to `N`-th order. Also, we can use `*` or `∘` to compos `Differential`s, like `Differential(t) * Differential(x)`. Now let's transform this into the `ODESystem` of first order components. -We do this by calling `structural_simplify`: +We do this by calling `mtkbuild`: Now we can directly numerically solve the lowered system. Note that, following the original problem, the solution requires knowing the diff --git a/docs/src/examples/modelingtoolkitize_index_reduction.md b/docs/src/examples/modelingtoolkitize_index_reduction.md index b19ea46701..40204c3a5f 100644 --- a/docs/src/examples/modelingtoolkitize_index_reduction.md +++ b/docs/src/examples/modelingtoolkitize_index_reduction.md @@ -29,7 +29,7 @@ p = [9.8, 1] tspan = (0, 10.0) pendulum_prob = ODEProblem(pendulum_fun!, u0, tspan, p) traced_sys = modelingtoolkitize(pendulum_prob) -pendulum_sys = structural_simplify(dae_index_lowering(traced_sys)) +pendulum_sys = mtkbuild(dae_index_lowering(traced_sys)) prob = ODEProblem(pendulum_sys, [], tspan) sol = solve(prob, Rodas5P(), abstol = 1e-8, reltol = 1e-8) plot(sol, idxs = unknowns(traced_sys)) @@ -157,7 +157,7 @@ numerical solver. Let's try that out: ```@example indexred traced_sys = modelingtoolkitize(pendulum_prob) -pendulum_sys = structural_simplify(dae_index_lowering(traced_sys)) +pendulum_sys = mtkbuild(dae_index_lowering(traced_sys)) prob = ODEProblem(pendulum_sys, Pair[], tspan) sol = solve(prob, Rodas5P()) diff --git a/docs/src/examples/spring_mass.md b/docs/src/examples/spring_mass.md index 355e5c20b2..e9c6b4f908 100644 --- a/docs/src/examples/spring_mass.md +++ b/docs/src/examples/spring_mass.md @@ -45,7 +45,7 @@ eqs = [connect_spring(spring, mass.pos, center) @named _model = ODESystem(eqs, t, [spring.x; spring.dir; mass.pos], []) @named model = compose(_model, mass, spring) -sys = structural_simplify(model) +sys = mtkbuild(model) prob = ODEProblem(sys, [], (0.0, 3.0)) sol = solve(prob, Rosenbrock23()) @@ -153,10 +153,10 @@ parameters(model) ### Simplifying and solving this system -This system can be solved directly as a DAE using [one of the DAE solvers from DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/solvers/dae_solve/). However, we can symbolically simplify the system first beforehand. Running `structural_simplify` eliminates unnecessary variables from the model to give the leanest numerical representation of the system. +This system can be solved directly as a DAE using [one of the DAE solvers from DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/solvers/dae_solve/). However, we can symbolically simplify the system first beforehand. Running `mtkbuild` eliminates unnecessary variables from the model to give the leanest numerical representation of the system. ```@example component -sys = structural_simplify(model) +sys = mtkbuild(model) equations(sys) ``` @@ -177,7 +177,7 @@ sol = solve(prob, Rosenbrock23()) plot(sol) ``` -What if we want the timeseries of a different variable? That information is not lost! Instead, `structural_simplify` simply changes unknown variables into `observed` variables. +What if we want the timeseries of a different variable? That information is not lost! Instead, `mtkbuild` simply changes unknown variables into `observed` variables. ```@example component observed(sys) diff --git a/docs/src/examples/tearing_parallelism.md b/docs/src/examples/tearing_parallelism.md index 9540e610bd..688b47917f 100644 --- a/docs/src/examples/tearing_parallelism.md +++ b/docs/src/examples/tearing_parallelism.md @@ -1,7 +1,7 @@ # Exposing More Parallelism By Tearing Algebraic Equations in ODESystems Sometimes it can be very non-trivial to parallelize a system. In this tutorial, -we will demonstrate how to make use of `structural_simplify` to expose more +we will demonstrate how to make use of `mtkbuild` to expose more parallelism in the solution process and parallelize the resulting simulation. ## The Component Library @@ -122,7 +122,7 @@ Now let's say we want to expose a bit more parallelism via running tearing. How do we do that? ```@example tearing -sys = structural_simplify(big_rc) +sys = mtkbuild(big_rc) ``` Done, that's it. There's no more to it. @@ -175,5 +175,5 @@ so this is better than trying to do it by hand. After performing this, you can construct the `ODEProblem` and set `parallel_form` to use the exposed parallelism in multithreaded function -constructions, but this showcases why `structural_simplify` is so important +constructions, but this showcases why `mtkbuild` is so important to that process. diff --git a/docs/src/internals.md b/docs/src/internals.md index 00b29f1a64..2db7fd8bc6 100644 --- a/docs/src/internals.md +++ b/docs/src/internals.md @@ -18,7 +18,7 @@ and are then used to generate the `observed` equation found in the variable when necessary. In this sense, there is an equivalence between observables and the variable elimination system. -The procedure for variable elimination inside [`structural_simplify`](@ref) is +The procedure for variable elimination inside [`mtkbuild`](@ref) is 1. [`ModelingToolkit.initialize_system_structure`](@ref). 2. [`ModelingToolkit.alias_elimination`](@ref). This step moves equations into `observed(sys)`. diff --git a/docs/src/systems/DiscreteSystem.md b/docs/src/systems/DiscreteSystem.md index f8a71043ab..e787b8f004 100644 --- a/docs/src/systems/DiscreteSystem.md +++ b/docs/src/systems/DiscreteSystem.md @@ -17,7 +17,7 @@ DiscreteSystem ## Transformations ```@docs; canonical=false -structural_simplify +mtkbuild ``` ## Problem Constructors diff --git a/docs/src/systems/ImplicitDiscreteSystem.md b/docs/src/systems/ImplicitDiscreteSystem.md index d69f88f106..13910f3995 100644 --- a/docs/src/systems/ImplicitDiscreteSystem.md +++ b/docs/src/systems/ImplicitDiscreteSystem.md @@ -17,7 +17,7 @@ ImplicitDiscreteSystem ## Transformations ```@docs; canonical=false -structural_simplify +mtkbuild ``` ## Problem Constructors diff --git a/docs/src/systems/JumpSystem.md b/docs/src/systems/JumpSystem.md index 5bd0d50602..2db9246f70 100644 --- a/docs/src/systems/JumpSystem.md +++ b/docs/src/systems/JumpSystem.md @@ -17,7 +17,7 @@ JumpSystem ## Transformations ```@docs; canonical=false -structural_simplify +mtkbuild ``` ## Analyses diff --git a/docs/src/systems/NonlinearSystem.md b/docs/src/systems/NonlinearSystem.md index 06d587b1b9..2a470f0820 100644 --- a/docs/src/systems/NonlinearSystem.md +++ b/docs/src/systems/NonlinearSystem.md @@ -16,7 +16,7 @@ NonlinearSystem ## Transformations ```@docs; canonical=false -structural_simplify +mtkbuild alias_elimination tearing ``` diff --git a/docs/src/systems/ODESystem.md b/docs/src/systems/ODESystem.md index 24e2952fc5..ce6149edeb 100644 --- a/docs/src/systems/ODESystem.md +++ b/docs/src/systems/ODESystem.md @@ -27,7 +27,7 @@ ODESystem ## Transformations ```@docs -structural_simplify +mtkbuild ode_order_lowering dae_index_lowering change_independent_variable diff --git a/docs/src/systems/SDESystem.md b/docs/src/systems/SDESystem.md index 5789d2d9cb..2f51528a51 100644 --- a/docs/src/systems/SDESystem.md +++ b/docs/src/systems/SDESystem.md @@ -33,7 +33,7 @@ sde = SDESystem(ode, noiseeqs) ## Transformations ```@docs; canonical=false -structural_simplify +mtkbuild alias_elimination ``` diff --git a/docs/src/tutorials/acausal_components.md b/docs/src/tutorials/acausal_components.md index 751b678dae..4e0f14fc63 100644 --- a/docs/src/tutorials/acausal_components.md +++ b/docs/src/tutorials/acausal_components.md @@ -323,7 +323,7 @@ plot(sol) By default, this plots only the unknown variables that had to be solved for. However, what if we wanted to plot the timeseries of a different variable? Do not worry, that information was not thrown away! Instead, transformations -like `structural_simplify` simply change unknown variables into observables which are +like `mtkbuild` simply change unknown variables into observables which are defined by `observed` equations. ```@example acausal diff --git a/docs/src/tutorials/attractors.md b/docs/src/tutorials/attractors.md index 317384b01a..24649d307d 100644 --- a/docs/src/tutorials/attractors.md +++ b/docs/src/tutorials/attractors.md @@ -42,7 +42,7 @@ Because our dynamical system is super simple, we will directly make an `ODESyste ```@example Attractors @named modlorenz = ODESystem(eqs, t) -ssys = structural_simplify(modlorenz) +ssys = mtkbuild(modlorenz) # The timespan given to the problem is irrelevant for DynamicalSystems.jl prob = ODEProblem(ssys, [], (0.0, 1.0), []) ``` diff --git a/docs/src/tutorials/change_independent_variable.md b/docs/src/tutorials/change_independent_variable.md index d55639a669..18b6f75bb3 100644 --- a/docs/src/tutorials/change_independent_variable.md +++ b/docs/src/tutorials/change_independent_variable.md @@ -25,7 +25,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = [D(D(y)) ~ -g, D(x) ~ v] initialization_eqs = [D(x) ~ D(y)] # 45° initial angle M1 = ODESystem(eqs, t; initialization_eqs, name = :M) -M1s = structural_simplify(M1) +M1s = mtkbuild(M1) @assert length(equations(M1s)) == 3 # hide M1s # hide ``` @@ -44,7 +44,7 @@ This transformation is well-defined for any non-zero horizontal velocity $v$, so ```@example changeivar M2 = change_independent_variable(M1, x) -M2s = structural_simplify(M2; allow_symbolic = true) +M2s = mtkbuild(M2; allow_symbolic = true) # a sanity test on the 10 x/y variables that are accessible to the user # hide @assert allequal([x, M1s.x]) # hide @assert allequal([M2.x, M2s.x]) # hide @@ -97,7 +97,7 @@ eqs = [Ω ~ r.Ω + m.Ω + Λ.Ω, D(a) ~ √(Ω) * a^2] initialization_eqs = [Λ.Ω + r.Ω + m.Ω ~ 1] M1 = ODESystem(eqs, t, [Ω, a], []; initialization_eqs, name = :M) M1 = compose(M1, r, m, Λ) -M1s = structural_simplify(M1) +M1s = mtkbuild(M1) ``` Of course, we can solve this ODE as it is: @@ -137,7 +137,7 @@ M3 = change_independent_variable(M2, b, [Da(b) ~ exp(-b), a ~ exp(b)]) We can now solve and plot the ODE in terms of $b$: ```@example changeivar -M3s = structural_simplify(M3; allow_symbolic = true) +M3s = mtkbuild(M3; allow_symbolic = true) prob = ODEProblem(M3s, [M3s.r.Ω => 5e-5, M3s.m.Ω => 0.3], (0, -15), []) sol = solve(prob, Tsit5()) @assert Symbol(sol.retcode) == :Success # surrounding text assumes the solution was successful # hide diff --git a/docs/src/tutorials/domain_connections.md b/docs/src/tutorials/domain_connections.md index d6dc2d8781..ff124ce481 100644 --- a/docs/src/tutorials/domain_connections.md +++ b/docs/src/tutorials/domain_connections.md @@ -115,10 +115,10 @@ end nothing #hide ``` -To see how the domain works, we can examine the set parameter values for each of the ports `src.port` and `vol.port`. First we assemble the system using `structural_simplify()` and then check the default value of `vol.port.ρ`, whichs points to the setter value `fluid₊ρ`. Likewise, `src.port.ρ`, will also point to the setter value `fluid₊ρ`. Therefore, there is now only 1 defined density value `fluid₊ρ` which sets the density for the connected network. +To see how the domain works, we can examine the set parameter values for each of the ports `src.port` and `vol.port`. First we assemble the system using `mtkbuild()` and then check the default value of `vol.port.ρ`, whichs points to the setter value `fluid₊ρ`. Likewise, `src.port.ρ`, will also point to the setter value `fluid₊ρ`. Therefore, there is now only 1 defined density value `fluid₊ρ` which sets the density for the connected network. ```@repl domain -sys = structural_simplify(odesys) +sys = mtkbuild(odesys) ModelingToolkit.defaults(sys)[odesys.vol.port.ρ] ``` @@ -181,7 +181,7 @@ end nothing #hide ``` -After running `structural_simplify()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfere with the mathematical equations of the system, since no unknown variables are connected. +After running `mtkbuild()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfere with the mathematical equations of the system, since no unknown variables are connected. ```@example domain @component function ActuatorSystem1(; name) @@ -252,7 +252,7 @@ end nothing #hide ``` -When `structural_simplify()` is applied to this system it can be seen that the defaults are missing for `res.port_b` and `vol.port`. +When `mtkbuild()` is applied to this system it can be seen that the defaults are missing for `res.port_b` and `vol.port`. ```@repl domain ModelingToolkit.defaults(ressys)[ressys.res.port_a.ρ] diff --git a/docs/src/tutorials/fmi.md b/docs/src/tutorials/fmi.md index ef00477c78..9015f91987 100644 --- a/docs/src/tutorials/fmi.md +++ b/docs/src/tutorials/fmi.md @@ -76,7 +76,7 @@ initialization semantics. We can simulate this model like any other ModelingToolkit system. ```@repl fmi -sys = structural_simplify(model) +sys = mtkbuild(model) prob = ODEProblem(sys, [sys.mass__s => 0.5, sys.mass__v => 0.0], (0.0, 5.0)) sol = solve(prob, Tsit5()) ``` @@ -104,11 +104,11 @@ constant until the next time the callback triggers. The periodic interval must b `communication_step_size` keyword argument. A smaller step size typically leads to less error but is more computationally expensive. -This model alone does not have any differential variables, and calling `structural_simplify` will lead +This model alone does not have any differential variables, and calling `mtkbuild` will lead to an `ODESystem` with no unknowns. ```@example fmi -structural_simplify(inner) +mtkbuild(inner) ``` Simulating this model will cause the OrdinaryDiffEq integrator to immediately finish, and will not diff --git a/docs/src/tutorials/initialization.md b/docs/src/tutorials/initialization.md index ba733e0bfb..8712262cbc 100644 --- a/docs/src/tutorials/initialization.md +++ b/docs/src/tutorials/initialization.md @@ -380,7 +380,7 @@ with observables, those observables are too treated as initial equations. We can resulting simplified system via the command: ```@example init -isys = structural_simplify(isys; fully_determined = false) +isys = mtkbuild(isys; fully_determined = false) ``` Note `fully_determined=false` allows for the simplification to occur when the number of equations @@ -392,7 +392,7 @@ isys = ModelingToolkit.generate_initializesystem( ``` ```@example init -isys = structural_simplify(isys; fully_determined = false) +isys = mtkbuild(isys; fully_determined = false) ``` ```@example init @@ -504,7 +504,7 @@ eqs = [D(x) ~ α * x - β * x * y z ~ x + y] @named sys = ODESystem(eqs, t) -simpsys = structural_simplify(sys) +simpsys = mtkbuild(sys) tspan = (0.0, 10.0) ``` diff --git a/docs/src/tutorials/programmatically_generating.md b/docs/src/tutorials/programmatically_generating.md index 9fc1db1834..6abba4dd3d 100644 --- a/docs/src/tutorials/programmatically_generating.md +++ b/docs/src/tutorials/programmatically_generating.md @@ -47,7 +47,7 @@ eqs = [D(x) ~ (h - x) / τ] # create an array of equations # Perform the standard transformations and mark the model complete # Note: Complete models cannot be subsystems of other models! -fol = structural_simplify(model) +fol = mtkbuild(model) prob = ODEProblem(fol, [], (0.0, 10.0), []) using OrdinaryDiffEq sol = solve(prob) diff --git a/ext/MTKBifurcationKitExt.jl b/ext/MTKBifurcationKitExt.jl index 0b9f104d9b..e0e9cbf8fe 100644 --- a/ext/MTKBifurcationKitExt.jl +++ b/ext/MTKBifurcationKitExt.jl @@ -92,7 +92,7 @@ function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem, jac = true, kwargs...) if !ModelingToolkit.iscomplete(nsys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `BifurcationProblem`") end @set! nsys.index_cache = nothing # force usage of a parameter vector instead of `MTKParameters` # Creates F and J functions. @@ -146,7 +146,7 @@ end # When input is a ODESystem. function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...) if !ModelingToolkit.iscomplete(osys) - error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`") + error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating a `BifurcationProblem`") end nsys = NonlinearSystem([0 ~ eq.rhs for eq in full_equations(osys)], unknowns(osys), diff --git a/ext/MTKFMIExt.jl b/ext/MTKFMIExt.jl index 5cfe9a82ef..4501bbcbaf 100644 --- a/ext/MTKFMIExt.jl +++ b/ext/MTKFMIExt.jl @@ -127,7 +127,7 @@ function MTK.FMIComponent(::Val{Ver}; fmu = nothing, tolerance = 1e-6, # no differential variables __mtk_internal_u = Float64[] elseif type == :ME - # to avoid running into `structural_simplify` warnings about array variables + # to avoid running into `mtkbuild` warnings about array variables # and some unfortunate circular dependency issues, ME FMUs use an array of # symbolics instead. This is also not worse off in performance # because the former approach would allocate anyway. diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 205c9dd477..e247a1d43b 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -226,7 +226,7 @@ PrecompileTools.@compile_workload begin using ModelingToolkit @variables x(ModelingToolkit.t_nounits) @named sys = ODESystem([ModelingToolkit.D_nounits(x) ~ -x], ModelingToolkit.t_nounits) - prob = ODEProblem(structural_simplify(sys), [x => 30.0], (0, 100), [], jac = true) + prob = ODEProblem(mtkbuild(sys), [x => 30.0], (0, 100), [], jac = true) @mtkmodel __testmod__ begin @constants begin c = 1.0 @@ -299,7 +299,7 @@ export Term, Sym 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, +export mtkbuild, expand_connections, linearize, linearization_function, LinearizationProblem export solve diff --git a/src/inputoutput.jl b/src/inputoutput.jl index ebd3e25af6..5030b7d0eb 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -201,7 +201,7 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu # Remove this when the ControlFunction gets merged. if !iscomplete(sys) - error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating the control function.") + error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the control function.") end isempty(inputs) && @warn("No unbound inputs were found in system.") if disturbance_inputs !== nothing diff --git a/src/linearization.jl b/src/linearization.jl index 2e958ecc73..3bfe7eaef5 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -1,5 +1,5 @@ """ - lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) + lin_fun = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) Return a function that linearizes the system `sys`. The function [`linearize`](@ref) provides a higher-level and easier to use interface. @@ -15,7 +15,7 @@ y &= h(x, z, u) where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. To obtain a linear statespace representation, see [`linearize`](@ref). The input argument `variables` is a vector defining the operating point, corresponding to `unknowns(simplified_sys)` and `p` is a vector corresponding to the parameters of `simplified_sys`. Note: all variables in `inputs` have been converted to parameters in `simplified_sys`. -The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occurring input or output variables replaced with the variables provided in arguments `inputs` and `outputs`. The unknowns of this system also indicate the order of the unknowns that holds for the linearized matrices. +The `simplified_sys` has undergone [`mtkbuild`](@ref) and had any occurring input or output variables replaced with the variables provided in arguments `inputs` and `outputs`. The unknowns of this system also indicate the order of the unknowns that holds for the linearized matrices. # Arguments: @@ -29,8 +29,8 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ See also [`linearize`](@ref) which provides a higher-level interface. """ -function linearization_function(sys::AbstractSystem, inputs, - outputs; +function linearization_function(sys::AbstractSystem, inputs = unbound_inputs(sys), + outputs = unbound_outputs(sys); initialize = true, initializealg = nothing, initialization_abstol = 1e-5, @@ -45,6 +45,9 @@ function linearization_function(sys::AbstractSystem, inputs, guesses = Dict(), warn_empty_op = true, kwargs...) + if !iscomplete(sys) + error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the linearization.") + end op = Dict(op) if isempty(op) && warn_empty_op @warn "An empty operating point was passed to `linearization_function`. An operating point containing the variables that will be changed in `linearize` should be provided. Disable this warning by passing `warn_empty_op = false`." @@ -481,10 +484,13 @@ y &= h(x, z, u) ``` where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. """ -function linearize_symbolic(sys::AbstractSystem, inputs, - outputs; allow_input_derivatives = false, +function linearize_symbolic(sys::AbstractSystem, inputs = unbound_inputs(sys), + outputs = unbound_outputs(sys); allow_input_derivatives = false, eval_expression = false, eval_module = @__MODULE__, kwargs...) + if !iscomplete(sys) + error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the linearization.") + end diff_idxs, alge_idxs = eq_idxs(sys) sts = unknowns(sys) t = get_iv(sys) @@ -543,7 +549,7 @@ function linearize_symbolic(sys::AbstractSystem, inputs, end end - (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys + (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u) end function markio!(state, orig_inputs, inputs, outputs; check = true) @@ -710,17 +716,17 @@ function linearize(sys, lin_fun::LinearizationFunction; t = 0.0, return solve(prob; allow_input_derivatives) end -function linearize(sys, inputs, outputs; op = Dict(), t = 0.0, +function linearize(sys, inputs = unbound_inputs(sys), outputs = unbound_outputs(sys); op = Dict(), t = 0.0, allow_input_derivatives = false, zero_dummy_der = false, kwargs...) - lin_fun, ssys = linearization_function(sys, + lin_fun = linearization_function(sys, inputs, outputs; zero_dummy_der, op, kwargs...) - linearize(ssys, lin_fun; op, t, allow_input_derivatives), ssys + linearize(sys, lin_fun; op, t, allow_input_derivatives) end """ diff --git a/src/structural_transformation/StructuralTransformations.jl b/src/structural_transformation/StructuralTransformations.jl index 4adc817ef8..0b8b2eddcb 100644 --- a/src/structural_transformation/StructuralTransformations.jl +++ b/src/structural_transformation/StructuralTransformations.jl @@ -35,7 +35,7 @@ import ModelingToolkit: var_derivative!, var_derivative_graph! using Graphs using ModelingToolkit: algeqs, EquationsView, SystemStructure, TransformationState, TearingState, - structural_simplify!, + structural_simplification!, isdiffvar, isdervar, isalgvar, isdiffeq, algeqs, is_only_discrete, dervars_range, diffvars_range, algvars_range, DiffGraph, complete!, diff --git a/src/structural_transformation/pantelides.jl b/src/structural_transformation/pantelides.jl index 585c4a29d1..335c7d52cd 100644 --- a/src/structural_transformation/pantelides.jl +++ b/src/structural_transformation/pantelides.jl @@ -210,7 +210,7 @@ end dae_index_lowering(sys::ODESystem; kwargs...) -> ODESystem Perform the Pantelides algorithm to transform a higher index DAE to an index 1 -DAE. `kwargs` are forwarded to [`pantelides!`](@ref). End users are encouraged to call [`structural_simplify`](@ref) +DAE. `kwargs` are forwarded to [`pantelides!`](@ref). End users are encouraged to call [`mtkbuild`](@ref) instead, which calls this function internally. """ function dae_index_lowering(sys::ODESystem; kwargs...) diff --git a/src/structural_transformation/symbolics_tearing.jl b/src/structural_transformation/symbolics_tearing.jl index 548c7da519..7b554f97d1 100644 --- a/src/structural_transformation/symbolics_tearing.jl +++ b/src/structural_transformation/symbolics_tearing.jl @@ -1018,7 +1018,7 @@ end tearing(sys; simplify=false) Tear the nonlinear equations in system. When `simplify=true`, we simplify the -new residual equations after tearing. End users are encouraged to call [`structural_simplify`](@ref) +new residual equations after tearing. End users are encouraged to call [`mtkbuild`](@ref) instead, which calls this function internally. """ function tearing(sys::AbstractSystem, state = TearingState(sys); mm = nothing, diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 025199c92b..8559151747 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -157,7 +157,7 @@ may be subsetted using `dvs` and `ps`. All `kwargs` are passed to the internal [`build_function`](@ref) call. The returned function can be called as `f(u, p, t)` or `f(du, u, p, t)` for time-dependent systems and `f(u, p)` or `f(du, u, p)` for time-independent systems. If `split=true` (the default) was passed to [`complete`](@ref), -[`structural_simplify`](@ref) or [`@mtkbuild`](@ref), `p` is expected to be an `MTKParameters` +[`mtkbuild`](@ref) or [`@mtkbuild`](@ref), `p` is expected to be an `MTKParameters` object. """ function generate_custom_function(sys::AbstractSystem, exprs, dvs = unknowns(sys), @@ -165,7 +165,7 @@ function generate_custom_function(sys::AbstractSystem, exprs, dvs = unknowns(sys expression = Val{true}, eval_expression = false, eval_module = @__MODULE__, cachesyms::Tuple = (), kwargs...) if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system.") + error("A completed system is required. Call `complete` or `mtkbuild` on the system.") end p = (reorder_parameters(sys, unwrap.(ps))..., cachesyms...) isscalar = !(exprs isa AbstractArray) @@ -771,7 +771,7 @@ function complete( newparams = OrderedSet() iv = has_iv(sys) ? get_iv(sys) : nothing collect_scoped_vars!(newunknowns, newparams, sys, iv; depth = -1) - # don't update unknowns to not disturb `structural_simplify` order + # don't update unknowns to not disturb `mtkbuild` order # `GlobalScope`d unknowns will be picked up and added there @set! sys.ps = unique!(vcat(get_ps(sys), collect(newparams))) @@ -1196,7 +1196,7 @@ end Denotes that a variable belongs to the root system in the hierarchy, regardless of which equations of subsystems in the hierarchy it is involved in. Variables with this scope are never namespaced and only added to the unknowns/parameters of a system when calling -`complete` or `structural_simplify`. +`complete` or `mtkbuild`. """ struct GlobalScope <: SymScope end @@ -2416,7 +2416,7 @@ macro mtkbuild(exprs...) else kwargs = (Expr(:parameters, kwargs...),) end - call_expr = Expr(:call, structural_simplify, kwargs..., name) + call_expr = Expr(:call, mtkbuild, kwargs..., name) esc(quote $named_expr $name = $call_expr @@ -2455,7 +2455,7 @@ function debug_system( functions = Set(functions) # more efficient "in" lookup end if has_systems(sys) && !isempty(get_systems(sys)) - error("debug_system(sys) only works on systems with no sub-systems! Consider flattening it with flatten(sys) or structural_simplify(sys) first.") + error("debug_system(sys) only works on systems with no sub-systems! Consider flattening it with flatten(sys) or mtkbuild(sys) first.") end if has_eqs(sys) eqs = debug_sub.(equations(sys), Ref(functions); kw...) @@ -2552,10 +2552,10 @@ end function check_array_equations_unknowns(eqs, dvs) if any(eq -> eq isa Equation && Symbolics.isarraysymbolic(eq.lhs), eqs) - throw(ArgumentError("The system has array equations. Call `structural_simplify` to handle such equations or scalarize them manually.")) + throw(ArgumentError("The system has array equations. Call `mtkbuild` to handle such equations or scalarize them manually.")) end if any(x -> Symbolics.isarraysymbolic(x), dvs) - throw(ArgumentError("The system has array unknowns. Call `structural_simplify` to handle this or scalarize them manually.")) + throw(ArgumentError("The system has array unknowns. Call `mtkbuild` to handle this or scalarize them manually.")) end end diff --git a/src/systems/diffeqs/abstractodesystem.jl b/src/systems/diffeqs/abstractodesystem.jl index d9e8b05eeb..96dbae0762 100644 --- a/src/systems/diffeqs/abstractodesystem.jl +++ b/src/systems/diffeqs/abstractodesystem.jl @@ -364,7 +364,7 @@ function DiffEqBase.ODEFunction{iip, specialize}(sys::AbstractODESystem, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunction`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEFunction`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, checkbounds = checkbounds, cse, @@ -469,7 +469,7 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys) cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEFunction`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEFunction`") end f_gen = generate_function(sys, dvs, ps; implicit_dae = true, expression = Val{true}, cse, @@ -529,7 +529,7 @@ function DiffEqBase.DDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys) cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DDEFunction`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `DDEFunction`") end f_gen = generate_function(sys, dvs, ps; isdde = true, expression = Val{true}, @@ -554,7 +554,7 @@ function DiffEqBase.SDDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `SDDEFunction`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `SDDEFunction`") end f_gen = generate_function(sys, dvs, ps; isdde = true, expression = Val{true}, @@ -598,7 +598,7 @@ function ODEFunctionExpr{iip, specialize}(sys::AbstractODESystem, dvs = unknowns observedfun_exp = nothing, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunctionExpr`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...) @@ -688,7 +688,7 @@ function DAEFunctionExpr{iip}(sys::AbstractODESystem, dvs = unknowns(sys), sparse = false, simplify = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DAEFunctionExpr`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `DAEFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, implicit_dae = true, kwargs...) @@ -784,7 +784,7 @@ function DiffEqBase.ODEProblem{iip, specialize}(sys::AbstractODESystem, u0map = eval_module = @__MODULE__, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEProblem`") end if !isnothing(get_constraintsystem(sys)) @@ -900,7 +900,7 @@ function SciMLBase.BVProblem{iip, specialize}(sys::AbstractODESystem, u0map = [] cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `BVProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `BVProblem`") end !isnothing(callback) && error("BVP solvers do not support callbacks.") @@ -1014,7 +1014,7 @@ function DiffEqBase.DAEProblem{iip}(sys::AbstractODESystem, du0map, u0map, tspan warn_initialize_determined = true, check_length = true, eval_expression = false, eval_module = @__MODULE__, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblem`.") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEProblem`.") end if !isempty(get_costs(sys)) && !allow_cost @@ -1066,7 +1066,7 @@ function DiffEqBase.DDEProblem{iip}(sys::AbstractODESystem, u0map = [], cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DDEProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DDEProblem`") end f, u0, p = process_SciMLProblem(DDEFunction{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1106,7 +1106,7 @@ function DiffEqBase.SDDEProblem{iip}(sys::AbstractODESystem, u0map = [], cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SDDEProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SDDEProblem`") end f, u0, p = process_SciMLProblem(SDDEFunction{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1167,7 +1167,7 @@ function ODEProblemExpr{iip}(sys::AbstractODESystem, u0map, tspan, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `ODEProblemExpr`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `ODEProblemExpr`") end f, u0, p = process_SciMLProblem( ODEFunctionExpr{iip}, sys, u0map, parammap; check_length, @@ -1214,7 +1214,7 @@ function DAEProblemExpr{iip}(sys::AbstractODESystem, du0map, u0map, tspan, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblemExpr`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEProblemExpr`") end f, du0, u0, p = process_SciMLProblem(DAEFunctionExpr{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1266,7 +1266,7 @@ function DiffEqBase.SteadyStateProblem{iip}(sys::AbstractODESystem, u0map, parammap = SciMLBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SteadyStateProblem`") end f, u0, p = process_SciMLProblem(ODEFunction{iip}, sys, u0map, parammap; steady_state = true, @@ -1298,7 +1298,7 @@ function SteadyStateProblemExpr{iip}(sys::AbstractODESystem, u0map, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblemExpr`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SteadyStateProblemExpr`") end f, u0, p = process_SciMLProblem(ODEFunctionExpr{iip}, sys, u0map, parammap; steady_state = true, @@ -1449,7 +1449,7 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem, algebraic_only = false, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`") + error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEProblem`") end if isempty(u0map) && get_initializesystem(sys) !== nothing isys = get_initializesystem(sys; initialization_eqs, check_units) @@ -1474,7 +1474,7 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem, end if simplify_system - isys = structural_simplify(isys; fully_determined) + isys = mtkbuild(isys; fully_determined) end ts = get_tearing_state(isys) diff --git a/src/systems/diffeqs/basic_transformations.jl b/src/systems/diffeqs/basic_transformations.jl index a08c83ffb6..cf8c3a35f1 100644 --- a/src/systems/diffeqs/basic_transformations.jl +++ b/src/systems/diffeqs/basic_transformations.jl @@ -74,7 +74,7 @@ Any extra equations `eqs` involving the new and old independent variables will b # Usage before structural simplification The variable change must take place before structural simplification. -In following calls to `structural_simplify`, consider passing `allow_symbolic = true` to avoid undesired constraint equations between between dummy variables. +In following calls to `mtkbuild`, consider passing `allow_symbolic = true` to avoid undesired constraint equations between between dummy variables. # Usage with non-autonomous systems @@ -99,7 +99,7 @@ julia> @named M = ODESystem([D(D(y)) ~ -9.81, D(D(x)) ~ 0.0], t); julia> M = change_independent_variable(M, x); -julia> M = structural_simplify(M; allow_symbolic = true); +julia> M = mtkbuild(M; allow_symbolic = true); julia> unknowns(M) 3-element Vector{SymbolicUtils.BasicSymbolic{Real}}: diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 01b0ca5fbb..62966c0c81 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -579,7 +579,7 @@ function build_explicit_observed_function(sys, ts; if inputs === nothing inputs = () else - ps = setdiff(ps, inputs) # Inputs have been converted to parameters by io_preprocessing, remove those from the parameter list + ps = setdiff(ps, inputs) # Inputs have been converted to parameters, remove those from the parameter list inputs = (inputs,) end if disturbance_inputs !== nothing @@ -662,7 +662,7 @@ end # We have a stand-alone function to convert a `NonlinearSystem` or `ODESystem` # to an `ODESystem` to connect systems, and we later can reply on -# `structural_simplify` to convert `ODESystem`s to `NonlinearSystem`s. +# `mtkbuild` to convert `ODESystem`s to `NonlinearSystem`s. """ $(TYPEDSIGNATURES) diff --git a/src/systems/diffeqs/sdesystem.jl b/src/systems/diffeqs/sdesystem.jl index c5299c28be..4ce6b9605c 100644 --- a/src/systems/diffeqs/sdesystem.jl +++ b/src/systems/diffeqs/sdesystem.jl @@ -600,7 +600,7 @@ function DiffEqBase.SDEFunction{iip, specialize}(sys::SDESystem, dvs = unknowns( checkbounds = false, initialization_data = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunction`") + error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEFunction`") end dvs = scalarize.(dvs) @@ -720,7 +720,7 @@ function SDEFunctionExpr{iip}(sys::SDESystem, dvs = unknowns(sys), sparse = false, linenumbers = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunctionExpr`") + error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEFunctionExpr`") end idx = iip ? 2 : 1 f = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...)[idx] @@ -788,7 +788,7 @@ function DiffEqBase.SDEProblem{iip, specialize}( sparsenoise = nothing, check_length = true, callback = nothing, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblem`") + error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEProblem`") end f, u0, p = process_SciMLProblem( @@ -824,7 +824,7 @@ end function DiffEqBase.SDEProblem(sys::ODESystem, args...; kwargs...) if any(ModelingToolkit.isbrownian, unknowns(sys)) - error("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `structural_simplify` before a SDEProblem can be constructed.") + error("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `mtkbuild` before a SDEProblem can be constructed.") else error("Cannot construct SDEProblem from a normal ODESystem.") end @@ -886,7 +886,7 @@ function SDEProblemExpr{iip}(sys::SDESystem, u0map, tspan, sparsenoise = nothing, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblemExpr`") + error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEProblemExpr`") end f, u0, p = process_SciMLProblem( SDEFunctionExpr{iip}, sys, u0map, parammap; check_length, diff --git a/src/systems/discrete_system/discrete_system.jl b/src/systems/discrete_system/discrete_system.jl index 5f7c986659..94abaa596d 100644 --- a/src/systems/discrete_system/discrete_system.jl +++ b/src/systems/discrete_system/discrete_system.jl @@ -311,7 +311,7 @@ function SciMLBase.DiscreteProblem( kwargs... ) if !iscomplete(sys) - error("A completed `DiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") + error("A completed `DiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") end dvs = unknowns(sys) ps = parameters(sys) @@ -363,7 +363,7 @@ function SciMLBase.DiscreteFunction{iip, specialize}( analytic = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `DiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") + error("A completed `DiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, cse, kwargs...) diff --git a/src/systems/discrete_system/implicit_discrete_system.jl b/src/systems/discrete_system/implicit_discrete_system.jl index 3956c089d4..6440d5cce9 100644 --- a/src/systems/discrete_system/implicit_discrete_system.jl +++ b/src/systems/discrete_system/implicit_discrete_system.jl @@ -330,7 +330,7 @@ function SciMLBase.ImplicitDiscreteProblem( kwargs... ) if !iscomplete(sys) - error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `ImplicitDiscreteProblem`.") + error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `ImplicitDiscreteProblem`.") end dvs = unknowns(sys) ps = parameters(sys) @@ -372,7 +372,7 @@ function SciMLBase.ImplicitDiscreteFunction{iip, specialize}( analytic = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `ImplicitDiscreteProblem`") + error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `ImplicitDiscreteProblem`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, cse, kwargs...) diff --git a/src/systems/index_cache.jl b/src/systems/index_cache.jl index d0b687c212..8d051f4b2c 100644 --- a/src/systems/index_cache.jl +++ b/src/systems/index_cache.jl @@ -653,10 +653,10 @@ See also: [`MTKParameters`](@ref), [`tunable_parameters`](@ref), [`reorder_dimen function reorder_dimension_by_tunables!( dest::AbstractArray, sys::AbstractSystem, arr::AbstractArray, syms; dim = 1) if !iscomplete(sys) - throw(ArgumentError("A completed system is required. Call `complete` or `structural_simplify` on the system.")) + throw(ArgumentError("A completed system is required. Call `complete` or `mtkbuild` on the system.")) end if !has_index_cache(sys) || (ic = get_index_cache(sys)) === nothing - throw(ArgumentError("The system does not have an index cache. Call `complete` or `structural_simplify` on the system with `split = true`.")) + throw(ArgumentError("The system does not have an index cache. Call `complete` or `mtkbuild` on the system with `split = true`.")) end if size(dest) != size(arr) throw(ArgumentError("Source and destination arrays must have the same size. Got source array with size $(size(arr)) and destination with size $(size(dest)).")) diff --git a/src/systems/jumps/jumpsystem.jl b/src/systems/jumps/jumpsystem.jl index 06f5e1b623..8a5997d235 100644 --- a/src/systems/jumps/jumpsystem.jl +++ b/src/systems/jumps/jumpsystem.jl @@ -401,7 +401,7 @@ function DiffEqBase.DiscreteProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, cse = true, kwargs...) if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") end if has_equations(sys) || (!isempty(continuous_events(sys))) @@ -446,7 +446,7 @@ function DiscreteProblemExpr{iip}(sys::JumpSystem, u0map, tspan::Union{Tuple, No parammap = DiffEqBase.NullParameters(); kwargs...) where {iip} if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblemExpr`") + error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblemExpr`") end _, u0, p = process_SciMLProblem(EmptySciMLFunction, sys, u0map, parammap; @@ -492,7 +492,7 @@ function DiffEqBase.ODEProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, Nothi eval_module = @__MODULE__, cse = true, kwargs...) if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") end # forward everything to be an ODESystem but the jumps and discrete events @@ -535,7 +535,7 @@ function JumpProcesses.JumpProblem(js::JumpSystem, prob, aggregator = JumpProcesses.NullAggregator(); callback = nothing, eval_expression = false, eval_module = @__MODULE__, kwargs...) if !iscomplete(js) - error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `JumpProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `JumpProblem`") end unknowntoid = Dict(value(unknown) => i for (i, unknown) in enumerate(unknowns(js))) eqs = equations(js) diff --git a/src/systems/nonlinear/homotopy_continuation.jl b/src/systems/nonlinear/homotopy_continuation.jl index 9a77779103..796fce0c2d 100644 --- a/src/systems/nonlinear/homotopy_continuation.jl +++ b/src/systems/nonlinear/homotopy_continuation.jl @@ -492,7 +492,7 @@ function SciMLBase.HomotopyNonlinearFunction{iip, specialize}( p = nothing, fraction_cancel_fn = SymbolicUtils.simplify_fractions, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `HomotopyContinuationFunction`") end transformation = PolynomialTransformation(sys) if transformation isa NotPolynomialError @@ -553,7 +553,7 @@ function HomotopyContinuationProblem{iip, spec}( sys::NonlinearSystem, u0map, pmap = SciMLBase.NullParameters(); kwargs...) where {iip, spec} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `HomotopyContinuationProblem`") end f, u0, p = process_SciMLProblem( HomotopyNonlinearFunction{iip, spec}, sys, u0map, pmap; kwargs...) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index 7146fb6b5e..a5e0779813 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -383,7 +383,7 @@ function SciMLBase.NonlinearFunction{iip}(sys::NonlinearSystem, dvs = unknowns(s initialization_data = nothing, cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearFunction`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, cse, kwargs...) f_oop, f_iip = eval_or_rgf.(f_gen; eval_expression, eval_module) @@ -430,7 +430,7 @@ function SciMLBase.IntervalNonlinearFunction( p = nothing, eval_expression = false, eval_module = @__MODULE__, initialization_data = nothing, kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearFunction`") end if !isone(length(dvs)) || !isone(length(equations(sys))) error("`IntervalNonlinearFunction` only supports systems with a single equation and a single unknown.") @@ -472,7 +472,7 @@ function NonlinearFunctionExpr{iip}(sys::NonlinearSystem, dvs = unknowns(sys), sparse = false, simplify = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearFunctionExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...) f = :($(GeneratedFunctionWrapper{(2, 2, is_split(sys))})($f_oop, $f_iip)) @@ -521,7 +521,7 @@ function IntervalNonlinearFunctionExpr( sys::NonlinearSystem, dvs = unknowns(sys), ps = parameters(sys), u0 = nothing; p = nothing, linenumbers = false, kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearFunctionExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearFunctionExpr`") end if !isone(length(dvs)) || !isone(length(equations(sys))) error("`IntervalNonlinearFunctionExpr` only supports systems with a single equation and a single unknown.") @@ -558,7 +558,7 @@ function DiffEqBase.NonlinearProblem{iip}(sys::NonlinearSystem, u0map, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblem`") end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -592,7 +592,7 @@ function DiffEqBase.NonlinearLeastSquaresProblem{iip}(sys::NonlinearSystem, u0ma parammap = DiffEqBase.NullParameters(); check_length = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearLeastSquaresProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearLeastSquaresProblem`") end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -676,11 +676,11 @@ function SciMLBase.SCCNonlinearProblem{iip}(sys::NonlinearSystem, u0map, parammap = SciMLBase.NullParameters(); eval_expression = false, eval_module = @__MODULE__, cse = true, kwargs...) where {iip} if !iscomplete(sys) || get_tearing_state(sys) === nothing - error("A simplified `NonlinearSystem` is required. Call `structural_simplify` on the system before creating an `SCCNonlinearProblem`.") + error("A simplified `NonlinearSystem` is required. Call `mtkbuild` on the system before creating an `SCCNonlinearProblem`.") end if !is_split(sys) - error("The system has been simplified with `split = false`. `SCCNonlinearProblem` is not compatible with this system. Pass `split = true` to `structural_simplify` to use `SCCNonlinearProblem`.") + error("The system has been simplified with `split = false`. `SCCNonlinearProblem` is not compatible with this system. Pass `split = true` to `mtkbuild` to use `SCCNonlinearProblem`.") end ts = get_tearing_state(sys) @@ -857,7 +857,7 @@ symbolically calculating numerical enhancements. function DiffEqBase.IntervalNonlinearProblem(sys::NonlinearSystem, uspan::NTuple{2}, parammap = SciMLBase.NullParameters(); kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearProblem`") end if !isone(length(unknowns(sys))) || !isone(length(equations(sys))) error("`IntervalNonlinearProblem` only supports with a single equation and a single unknown.") @@ -893,7 +893,7 @@ function NonlinearProblemExpr{iip}(sys::NonlinearSystem, u0map, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -933,7 +933,7 @@ function NonlinearLeastSquaresProblemExpr{iip}(sys::NonlinearSystem, u0map, check_length = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -958,7 +958,7 @@ numerical enhancements. function IntervalNonlinearProblemExpr(sys::NonlinearSystem, uspan::NTuple{2}, parammap = SciMLBase.NullParameters(); kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearProblemExpr`") end if !isone(length(unknowns(sys))) || !isone(length(equations(sys))) error("`IntervalNonlinearProblemExpr` only supports with a single equation and a single unknown.") diff --git a/src/systems/optimization/optimizationsystem.jl b/src/systems/optimization/optimizationsystem.jl index bfe15b62d7..b7cc541ed7 100644 --- a/src/systems/optimization/optimizationsystem.jl +++ b/src/systems/optimization/optimizationsystem.jl @@ -303,7 +303,7 @@ function DiffEqBase.OptimizationProblem{iip}(sys::OptimizationSystem, u0map, checks = true, cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `OptimizationSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `OptimizationProblem`") + error("A completed `OptimizationSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `OptimizationProblem`") end if haskey(kwargs, :lcons) || haskey(kwargs, :ucons) Base.depwarn( @@ -544,7 +544,7 @@ function OptimizationProblemExpr{iip}(sys::OptimizationSystem, u0map, eval_expression = false, eval_module = @__MODULE__, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `OptimizationSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `OptimizationProblemExpr`") + error("A completed `OptimizationSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `OptimizationProblemExpr`") end if haskey(kwargs, :lcons) || haskey(kwargs, :ucons) Base.depwarn( @@ -726,7 +726,7 @@ function OptimizationProblemExpr{iip}(sys::OptimizationSystem, u0map, end end -function structural_simplify(sys::OptimizationSystem; split = true, kwargs...) +function mtkbuild(sys::OptimizationSystem; split = true, kwargs...) sys = flatten(sys) cons = constraints(sys) econs = Equation[] @@ -739,7 +739,7 @@ function structural_simplify(sys::OptimizationSystem; split = true, kwargs...) end end nlsys = NonlinearSystem(econs, unknowns(sys), parameters(sys); name = :___tmp_nlsystem) - snlsys = structural_simplify(nlsys; fully_determined = false, kwargs...) + snlsys = mtkbuild(nlsys; fully_determined = false, kwargs...) obs = observed(snlsys) subs = Dict(eq.lhs => eq.rhs for eq in observed(snlsys)) seqs = equations(snlsys) diff --git a/src/systems/parameter_buffer.jl b/src/systems/parameter_buffer.jl index 6142c95776..fa2bce9289 100644 --- a/src/systems/parameter_buffer.jl +++ b/src/systems/parameter_buffer.jl @@ -23,7 +23,7 @@ dependent systems. It is only required if the symbolic expressions also use the variable of the system. This requires that `complete` has been called on the system (usually via -`structural_simplify` or `@mtkbuild`) and the keyword `split = true` was passed (which is +`mtkbuild` or `@mtkbuild`) and the keyword `split = true` was passed (which is the default behavior). """ function MTKParameters( diff --git a/src/systems/systems.jl b/src/systems/systems.jl index e27916d994..ac96ad9c2a 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -33,7 +33,7 @@ function mtkbuild( disturbance_inputs = nothing, kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) - newsys′ = __structural_simplify(sys; simplify, + newsys′ = __structural_simplification(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, inputs, outputs, disturbance_inputs, kwargs...) @@ -65,15 +65,15 @@ function mtkbuild( end end -function __structural_simplify(sys::JumpSystem, args...; kwargs...) +function __structural_simplification(sys::JumpSystem, args...; kwargs...) return sys end -function __structural_simplify(sys::SDESystem, args...; kwargs...) - return __structural_simplify(ODESystem(sys), args...; kwargs...) +function __structural_simplification(sys::SDESystem, args...; kwargs...) + return __structural_simplification(ODESystem(sys), args...; kwargs...) end -function __structural_simplify(sys::AbstractSystem; simplify = false, +function __structural_simplification(sys::AbstractSystem; simplify = false, inputs = nothing, outputs = nothing, disturbance_inputs = nothing, kwargs...) @@ -94,7 +94,7 @@ function __structural_simplify(sys::AbstractSystem; simplify = false, end end if isempty(brown_vars) - return structural_simplify!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) + return structural_simplification!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) else Is = Int[] Js = Int[] @@ -127,7 +127,7 @@ function __structural_simplify(sys::AbstractSystem; simplify = false, if !iszero(new_idxs[i]) && invview(var_to_diff)[i] === nothing] # TODO: IO is not handled. - ode_sys = structural_simplify(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) + ode_sys = structural_simplification(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) eqs = equations(ode_sys) sorted_g_rows = zeros(Num, length(eqs), size(g, 2)) for (i, eq) in enumerate(eqs) @@ -170,7 +170,7 @@ end """ $(TYPEDSIGNATURES) -Given a system that has been simplified via `structural_simplify`, return a `Dict` mapping +Given a system that has been simplified via `mtkbuild`, return a `Dict` mapping variables of the system to equations that are used to solve for them. This includes observed variables. @@ -186,7 +186,7 @@ function map_variables_to_equations(sys::AbstractSystem; rename_dummy_derivative end ts = get_tearing_state(sys) if ts === nothing - throw(ArgumentError("`map_variables_to_equations` requires a simplified system. Call `structural_simplify` on the system before calling this function.")) + throw(ArgumentError("`map_variables_to_equations` requires a simplified system. Call `mtkbuild` on the system before calling this function.")) end dummy_sub = Dict() diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index aa544c8db1..03ced79c73 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -24,7 +24,7 @@ function quick_cancel_expr(expr) kws...))(expr) end -export SystemStructure, TransformationState, TearingState, structural_simplify! +export SystemStructure, TransformationState, TearingState, structural_simplification! export isdiffvar, isdervar, isalgvar, isdiffeq, algeqs, is_only_discrete export dervars_range, diffvars_range, algvars_range export DiffGraph, complete! @@ -657,7 +657,7 @@ function Base.show(io::IO, mime::MIME"text/plain", ms::MatchedSystemStructure) printstyled(io, " SelectedState") end -function structural_simplify!(state::TearingState; simplify = false, +function structural_simplification!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = true, inputs = nothing, outputs = nothing, disturbance_inputs = nothing, @@ -670,7 +670,7 @@ function structural_simplify!(state::TearingState; simplify = false, Dict(default_toterm.(state.fullvars) .=> ci.var_domain)) tss, clocked_inputs, continuous_id, id_to_clock = ModelingToolkit.split_system(ci) cont_inputs = [inputs; clocked_inputs[continuous_id]] - sys = _structural_simplify!(tss[continuous_id]; simplify, + sys = _structural_simplification!(tss[continuous_id]; simplify, check_consistency, fully_determined, cont_inputs, outputs, disturbance_inputs, kwargs...) @@ -689,7 +689,7 @@ function structural_simplify!(state::TearingState; simplify = false, continue end disc_inputs = [inputs; clocked_inputs[i]] - ss, = _structural_simplify!(state; simplify, check_consistency, + ss, = _structural_simplification!(state; simplify, check_consistency, disc_inputs, outputs, disturbance_inputs, fully_determined, kwargs...) append!(appended_parameters, inputs[i], unknowns(ss)) @@ -707,14 +707,14 @@ function structural_simplify!(state::TearingState; simplify = false, for sym in get_ps(sys)] @set! sys.ps = ps else - sys = _structural_simplify!(state; simplify, check_consistency, + sys = _structural_simplification!(state; simplify, check_consistency, inputs, outputs, disturbance_inputs, fully_determined, kwargs...) end return sys end -function _structural_simplify!(state::TearingState; simplify = false, +function _structural_simplification!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = false, dummy_derivative = true, inputs = nothing, outputs = nothing, diff --git a/src/utils.jl b/src/utils.jl index 2b3cbedab0..d1645783eb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -159,7 +159,7 @@ function check_lhs(eq::Equation, op, dvs::Set) v = unwrap(eq.lhs) _iszero(v) && return (operation(v) isa op && only(arguments(v)) in dvs) && return - error("$v is not a valid LHS. Please run structural_simplify before simulation.") + error("$v is not a valid LHS. Please run mtkbuild before simulation.") end check_lhs(eqs, op, dvs::Set) = for eq in eqs @@ -323,7 +323,7 @@ Throw error when difference/derivative operation occurs in the R.H.S. optext = "derivative" end msg = "The $optext variable must be isolated to the left-hand " * - "side of the equation like `$opvar ~ ...`. You may want to use `structural_simplify` or the DAE form.\nGot $eq." + "side of the equation like `$opvar ~ ...`. You may want to use `mtkbuild` or the DAE form.\nGot $eq." throw(InvalidSystemException(msg)) end @@ -359,10 +359,10 @@ function check_operator_variables(eqs, op::T) where {T} is_tmp_fine = iszero(nd) end is_tmp_fine || - error("The LHS cannot contain nondifferentiated variables. Please run `structural_simplify` or use the DAE form.\nGot $eq") + error("The LHS cannot contain nondifferentiated variables. Please run `mtkbuild` or use the DAE form.\nGot $eq") for v in tmp v in ops && - error("The LHS operator must be unique. Please run `structural_simplify` or use the DAE form. $v appears in LHS more than once.") + error("The LHS operator must be unique. Please run `mtkbuild` or use the DAE form. $v appears in LHS more than once.") push!(ops, v) end empty!(tmp) diff --git a/test/accessor_functions.jl b/test/accessor_functions.jl index 7ce477155b..3f5a22f34c 100644 --- a/test/accessor_functions.jl +++ b/test/accessor_functions.jl @@ -68,10 +68,10 @@ let sys_mid2_comp = complete(sys_mid2) sys_mid1_comp = complete(sys_mid1) sys_top_comp = complete(sys_top) - sys_bot_ss = structural_simplify(sys_bot) - sys_mid2_ss = structural_simplify(sys_mid2) - sys_mid1_ss = structural_simplify(sys_mid1) - sys_top_ss = structural_simplify(sys_top) + sys_bot_ss = mtkbuild(sys_bot) + sys_mid2_ss = mtkbuild(sys_mid2) + sys_mid1_ss = mtkbuild(sys_mid1) + sys_top_ss = mtkbuild(sys_top) # Checks `parameters1. @test all_sets_equal(parameters.([sys_bot, sys_bot_comp, sys_bot_ss])..., [d, p_bot]) @@ -98,7 +98,7 @@ let @test all(sym_issubset(parameters_toplevel(sys), get_ps(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) - # Checks `unknowns`. O(t) is eliminated by `structural_simplify` and + # Checks `unknowns`. O(t) is eliminated by `mtkbuild` and # must be considered separately. @test all_sets_equal(unknowns.([sys_bot, sys_bot_comp])..., [O, Y, X_bot]) @test all_sets_equal(unknowns.([sys_bot_ss])..., [Y, X_bot]) diff --git a/test/analysis_points.jl b/test/analysis_points.jl index e36afc02f7..e52ac9e1a7 100644 --- a/test/analysis_points.jl +++ b/test/analysis_points.jl @@ -67,7 +67,7 @@ sys = ODESystem(eqs, t, systems = [P, C], name = :hej) nonamespace_sys = toggle_namespacing(nested_sys, false) @testset "simplifies and solves" begin - ssys = structural_simplify(sys) + ssys = mtkbuild(sys) prob = ODEProblem(ssys, [P.x => 1], (0, 10)) sol = solve(prob, Rodas5()) @test norm(sol.u[1]) >= 1 diff --git a/test/basic_transformations.jl b/test/basic_transformations.jl index 544a89cd29..4419f508df 100644 --- a/test/basic_transformations.jl +++ b/test/basic_transformations.jl @@ -50,8 +50,8 @@ end M1 = ODESystem(eqs, t; initialization_eqs, name = :M) M2 = change_independent_variable(M1, s) - M1 = structural_simplify(M1; allow_symbolic = true) - M2 = structural_simplify(M2; allow_symbolic = true) + M1 = mtkbuild(M1; allow_symbolic = true) + M2 = mtkbuild(M2; allow_symbolic = true) prob1 = ODEProblem(M1, [M1.s => 1.0], (1.0, 4.0), []) prob2 = ODEProblem(M2, [], (1.0, 2.0), []) sol1 = solve(prob1, Tsit5(); reltol = 1e-10, abstol = 1e-10) @@ -100,9 +100,9 @@ end extraeqs = [Differential(M2.a)(b) ~ exp(-b), M2.a ~ exp(b)] M3 = change_independent_variable(M2, b, extraeqs) - M1 = structural_simplify(M1) - M2 = structural_simplify(M2; allow_symbolic = true) - M3 = structural_simplify(M3; allow_symbolic = true) + M1 = mtkbuild(M1) + M2 = mtkbuild(M2; allow_symbolic = true) + M3 = mtkbuild(M3; allow_symbolic = true) @test length(unknowns(M3)) == length(unknowns(M2)) == length(unknowns(M1)) - 1 end @@ -120,7 +120,7 @@ end @parameters g=9.81 v # gravitational acceleration and constant horizontal velocity Mt = ODESystem([D(D(y)) ~ -g, D(x) ~ v], t; name = :M) # gives (x, y) as function of t, ... Mx = change_independent_variable(Mt, x; add_old_diff = true) # ... but we want y as a function of x - Mx = structural_simplify(Mx; allow_symbolic = true) + Mx = mtkbuild(Mx; allow_symbolic = true) Dx = Differential(Mx.x) u0 = [Mx.y => 0.0, Dx(Mx.y) => 1.0, Mx.t => 0.0] p = [v => 10.0] @@ -134,7 +134,7 @@ end @parameters g = 9.81 # gravitational acceleration Mt = ODESystem([D(D(y)) ~ -g, D(D(x)) ~ 0], t; name = :M) # gives (x, y) as function of t, ... Mx = change_independent_variable(Mt, x; add_old_diff = true) # ... but we want y as a function of x - Mx = structural_simplify(Mx; allow_symbolic = true) + Mx = mtkbuild(Mx; allow_symbolic = true) Dx = Differential(Mx.x) u0 = [Mx.y => 0.0, Dx(Mx.y) => 1.0, Mx.t => 0.0, Mx.xˍt => 10.0] prob = ODEProblem(Mx, u0, (0.0, 20.0), []) # 1 = dy/dx = (dy/dt)/(dx/dt) means equal initial horizontal and vertical velocities @@ -152,7 +152,7 @@ end ] M1 = ODESystem(eqs, t; name = :M) M2 = change_independent_variable(M1, x; add_old_diff = true) - @test_nowarn structural_simplify(M2) + @test_nowarn mtkbuild(M2) # Compare to pen-and-paper result @variables x xˍt(x) xˍt(x) y(x) t(x) @@ -198,7 +198,7 @@ end ]) _f = LinearInterpolation([1.0, 1.0], [-100.0, +100.0]) # constant value 1 - M2s = structural_simplify(M2; allow_symbolic = true) + M2s = mtkbuild(M2; allow_symbolic = true) prob = ODEProblem(M2s, [M2s.y => 0.0], (1.0, 4.0), [fc => _f, f => _f]) sol = solve(prob, Tsit5(); abstol = 1e-5) @test isapprox(sol(4.0, idxs = M2.y), 12.0; atol = 1e-5) # Anal solution is D(y) ~ 12 => y(t) ~ 12*t + C => y(x) ~ 12*√(x) + C. With y(x=1)=0 => 12*(√(x)-1), so y(x=4) ~ 12 @@ -207,7 +207,7 @@ end @testset "Change independent variable (errors)" begin @variables x(t) y z(y) w(t) v(t) M = ODESystem([D(x) ~ 1, v ~ x], t; name = :M) - Ms = structural_simplify(M) + Ms = mtkbuild(M) @test_throws "structurally simplified" change_independent_variable(Ms, y) @test_throws "not a function of" change_independent_variable(M, y) @test_throws "not a function of" change_independent_variable(M, z) diff --git a/test/clock.jl b/test/clock.jl index c6051a52a8..296afa899d 100644 --- a/test/clock.jl +++ b/test/clock.jl @@ -65,10 +65,10 @@ By inference: ci, varmap = infer_clocks(sys) eqmap = ci.eq_domain tss, inputs, continuous_id = ModelingToolkit.split_system(deepcopy(ci)) -sss, = ModelingToolkit._structural_simplify!( +sss, = ModelingToolkit._mtkbuild!( deepcopy(tss[continuous_id]), (inputs[continuous_id], ())) @test equations(sss) == [D(x) ~ u - x] -sss, = ModelingToolkit._structural_simplify!(deepcopy(tss[1]), (inputs[1], ())) +sss, = ModelingToolkit._mtkbuild!(deepcopy(tss[1]), (inputs[1], ())) @test isempty(equations(sss)) d = Clock(dt) k = ShiftIndex(d) @@ -115,7 +115,7 @@ eqs = [yd ~ Sample(dt)(y) D(x) ~ -x + u y ~ x] @named sys = ODESystem(eqs, t) -@test_throws ModelingToolkit.HybridSystemNotSupportedException ss=structural_simplify(sys); +@test_throws ModelingToolkit.HybridSystemNotSupportedException ss=mtkbuild(sys); @test_skip begin Tf = 1.0 @@ -128,7 +128,7 @@ eqs = [yd ~ Sample(dt)(y) [kp => 1.0; ud(k - 1) => 2.1; ud(k - 2) => 2.0]) # recreate problem to empty saved values sol = solve(prob, Tsit5(), kwargshandle = KeywordArgSilent) - ss_nosplit = structural_simplify(sys; split = false) + ss_nosplit = mtkbuild(sys; split = false) prob_nosplit = ODEProblem(ss_nosplit, [x => 0.1], (0.0, Tf), [kp => 1.0; ud(k - 1) => 2.1; ud(k - 2) => 2.0]) int = init(prob_nosplit, Tsit5(); kwargshandle = KeywordArgSilent) @@ -294,8 +294,8 @@ eqs = [yd ~ Sample(dt)(y) @test varmap[y] == ContinuousClock() @test varmap[u] == ContinuousClock() - ss = structural_simplify(cl) - ss_nosplit = structural_simplify(cl; split = false) + ss = mtkbuild(cl) + ss_nosplit = mtkbuild(cl; split = false) if VERSION >= v"1.7" prob = ODEProblem(ss, [x => 0.0], (0.0, 1.0), [kp => 1.0]) @@ -426,7 +426,7 @@ eqs = [yd ~ Sample(dt)(y) @test varmap[_model.feedback.output.u] == d @test varmap[_model.feedback.input2.u] == d - ssys = structural_simplify(model) + ssys = mtkbuild(model) Tf = 0.2 timevec = 0:(d.dt):Tf diff --git a/test/code_generation.jl b/test/code_generation.jl index cf3d660b81..83d324cce3 100644 --- a/test/code_generation.jl +++ b/test/code_generation.jl @@ -70,7 +70,7 @@ end @parameters p[1:2] (f::Function)(..) @named sys = ODESystem( [D(x[0]) ~ p[1] * x[0] + x[2], D(x[1]) ~ p[2] * f(x) + x[2]], t) - sys, = structural_simplify(sys, ([x[2]], [])) + sys, = mtkbuild(sys, ([x[2]], [])) @test is_parameter(sys, x[2]) prob = ODEProblem(sys, [x[0] => 1.0, x[1] => 1.0], (0.0, 1.0), [p => ones(2), f => sum, x[2] => 2.0]) diff --git a/test/components.jl b/test/components.jl index 0ae5327bde..2c470d9ccc 100644 --- a/test/components.jl +++ b/test/components.jl @@ -42,9 +42,9 @@ end completed_rc_model = complete(rc_model) @test isequal(completed_rc_model.resistor.n.i, resistor.n.i) @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) +@test length(equations(mtkbuild(rc_model, allow_parameter = false))) == 2 +sys = mtkbuild(rc_model) +@test_throws ModelingToolkit.RepeatedStructuralSimplificationError mtkbuild(sys) @test length(equations(sys)) == 1 check_contract(sys) @test !isempty(ModelingToolkit.defaults(sys)) @@ -69,7 +69,7 @@ let @named _rc_model = ODESystem(rc_eqs, t) @named rc_model = compose(_rc_model, [resistor, capacitor, source, ground]) - sys = structural_simplify(rc_model) + sys = mtkbuild(rc_model) u0 = [ capacitor.v => 0.0 ] @@ -93,7 +93,7 @@ let @named _rc_model2 = ODESystem(rc_eqs2, t) @named rc_model2 = compose(_rc_model2, [resistor, resistor2, capacitor, source, ground]) - sys2 = structural_simplify(rc_model2) + sys2 = mtkbuild(rc_model2) prob2 = ODEProblem(sys2, [source.p.i => 0.0], (0, 10.0), guesses = u0) sol2 = solve(prob2, Rosenbrock23()) @test sol2[source.p.i] ≈ sol2[rc_model2.source.p.i] ≈ -sol2[capacitor.i] @@ -127,7 +127,7 @@ eqs = [connect(source.p, rc_comp.p) @named sys_inner_outer = compose(sys′, [ground, source, rc_comp]) @test_nowarn show(IOBuffer(), MIME"text/plain"(), sys_inner_outer) expand_connections(sys_inner_outer, debug = true) -sys_inner_outer = structural_simplify(sys_inner_outer) +sys_inner_outer = mtkbuild(sys_inner_outer) @test !isempty(ModelingToolkit.defaults(sys_inner_outer)) u0 = [rc_comp.capacitor.v => 0.0] prob = ODEProblem(sys_inner_outer, u0, (0, 10.0), sparse = true) @@ -150,7 +150,7 @@ sol = solve(prob, Tsit5()) #plot(sol) include("../examples/serial_inductor.jl") -sys = structural_simplify(ll_model) +sys = mtkbuild(ll_model) @test length(equations(sys)) == 2 u0 = unknowns(sys) .=> 0 @test_nowarn ODEProblem( @@ -159,7 +159,7 @@ prob = DAEProblem(sys, D.(unknowns(sys)) .=> 0, [], (0, 0.5), guesses = u0) sol = solve(prob, DFBDF()) @test sol.retcode == SciMLBase.ReturnCode.Success -sys2 = structural_simplify(ll2_model) +sys2 = mtkbuild(ll2_model) @test length(equations(sys2)) == 3 u0 = unknowns(sys) .=> 0 prob = ODEProblem(sys, u0, (0, 10.0)) @@ -233,7 +233,7 @@ function Circuit(; name) end @named foo = Circuit() -@test structural_simplify(foo) isa ModelingToolkit.AbstractSystem +@test mtkbuild(foo) isa ModelingToolkit.AbstractSystem # BLT tests using LinearAlgebra @@ -289,7 +289,7 @@ rc_eqs = [connect(capacitor.n, resistor.p) @named _rc_model = ODESystem(rc_eqs, t) @named rc_model = compose(_rc_model, [resistor, capacitor, ground]) -sys = structural_simplify(rc_model) +sys = mtkbuild(rc_model) prob = ODEProblem(sys, u0, (0, 10.0)) sol = solve(prob, Tsit5()) @@ -334,7 +334,7 @@ end end @named outer = Outer() - simp = structural_simplify(outer) + simp = mtkbuild(outer) @test sort(propertynames(outer)) == [:inner, :t, :x] @test propertynames(simp) == propertynames(outer) @@ -351,7 +351,7 @@ end @test_throws ArgumentError outer.inner₊p end -@testset "`getproperty` on `structural_simplify(complete(sys))`" begin +@testset "`getproperty` on `mtkbuild(complete(sys))`" begin @mtkmodel Foo begin @variables begin x(t) @@ -367,7 +367,7 @@ end end @named bar = Bar() cbar = complete(bar) - ss = structural_simplify(cbar) + ss = mtkbuild(cbar) @test isequal(cbar.foo.x, ss.foo.x) end diff --git a/test/constants.jl b/test/constants.jl index f2c4fdaa86..3e48c83f59 100644 --- a/test/constants.jl +++ b/test/constants.jl @@ -17,12 +17,12 @@ sol = solve(prob, Tsit5()) newsys = MT.eliminate_constants(sys) @test isequal(equations(newsys), [D(x) ~ 1]) -# Test structural_simplify substitutions & observed values +# Test mtkbuild substitutions & observed values eqs = [D(x) ~ 1, w ~ a] @named sys = ODESystem(eqs, t) # Now eliminate the constants first -simp = structural_simplify(sys) +simp = mtkbuild(sys) @test equations(simp) == [D(x) ~ 1.0] #Constant with units @@ -34,7 +34,7 @@ UMT.get_unit(β) D = Differential(t) eqs = [D(x) ~ β] @named sys = ODESystem(eqs, t) -simp = structural_simplify(sys) +simp = mtkbuild(sys) @test isempty(MT.collect_constants(nothing)) diff --git a/test/dde.jl b/test/dde.jl index c7561e6c24..e94e4aa5d0 100644 --- a/test/dde.jl +++ b/test/dde.jl @@ -119,11 +119,11 @@ eqs = [osc1.jcn ~ osc2.delx, @test ModelingToolkit.is_dde(coupledOsc2) @test !is_markovian(coupledOsc2) for coupledOsc in [coupledOsc, coupledOsc2] - local sys = structural_simplify(coupledOsc) + local sys = mtkbuild(coupledOsc) @test length(equations(sys)) == 4 @test length(unknowns(sys)) == 4 end -sys = structural_simplify(coupledOsc) +sys = mtkbuild(coupledOsc) prob = DDEProblem(sys, [], (0.0, 10.0); constant_lags = [sys.osc1.τ, sys.osc2.τ]) sol = solve(prob, MethodOfSteps(Tsit5())) obsfn = ModelingToolkit.build_explicit_observed_function( @@ -178,7 +178,7 @@ end eqs = [D(x(t)) ~ -w * x(t - τ)] @named sys = System(eqs, t) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob = DDEProblem(sys, [], @@ -191,7 +191,7 @@ end @brownian r eqs = [D(x(t)) ~ -w * x(t - τ) + r] @named sys = System(eqs, t) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob = SDDEProblem(sys, [], (0.0, 10.0), diff --git a/test/debugging.jl b/test/debugging.jl index a55684737c..3a3cbd5d88 100644 --- a/test/debugging.jl +++ b/test/debugging.jl @@ -6,8 +6,8 @@ using ModelingToolkit: t_nounits as t, D_nounits as D, ASSERTION_LOG_VARIABLE @brownian a @named inner_ode = ODESystem(D(x) ~ -sqrt(x), t; assertions = [(x > 0) => "ohno"]) @named inner_sde = System([D(x) ~ -sqrt(x) + a], t; assertions = [(x > 0) => "ohno"]) -sys_ode = structural_simplify(inner_ode) -sys_sde = structural_simplify(inner_sde) +sys_ode = mtkbuild(inner_ode) +sys_sde = mtkbuild(inner_sde) @testset "assertions are present in generated `f`" begin @testset "$(typeof(sys))" for (Problem, sys, alg) in [ diff --git a/test/discrete_system.jl b/test/discrete_system.jl index b0e2481e56..b183fdca62 100644 --- a/test/discrete_system.jl +++ b/test/discrete_system.jl @@ -31,7 +31,7 @@ eqs = [S ~ S(k - 1) - infection * h, # System @named sys = DiscreteSystem(eqs, t, [S, I, R], [c, nsteps, δt, β, γ]) -syss = structural_simplify(sys) +syss = mtkbuild(sys) @test syss == syss df = DiscreteFunction(syss) @@ -254,7 +254,7 @@ end @variables x(t) y(t) k = ShiftIndex(t) @named sys = DiscreteSystem([x ~ x^2 + y^2, y ~ x(k - 1) + y(k - 1)], t) -@test_throws ["algebraic equations", "ImplicitDiscreteSystem"] structural_simplify(sys) +@test_throws ["algebraic equations", "ImplicitDiscreteSystem"] mtkbuild(sys) @testset "Passing `nothing` to `u0`" begin @variables x(t) = 1 diff --git a/test/domain_connectors.jl b/test/domain_connectors.jl index 9a43d2938f..736abfc81f 100644 --- a/test/domain_connectors.jl +++ b/test/domain_connectors.jl @@ -148,7 +148,7 @@ esys = ModelingToolkit.expand_connections(odesys) csys = complete(odesys) -sys = structural_simplify(odesys) +sys = mtkbuild(odesys) @test length(equations(sys)) == length(unknowns(sys)) sys_defs = ModelingToolkit.defaults(sys) diff --git a/test/downstream/analysis_points.jl b/test/downstream/analysis_points.jl index 29b9aad512..fddadd20c4 100644 --- a/test/downstream/analysis_points.jl +++ b/test/downstream/analysis_points.jl @@ -60,7 +60,7 @@ import ControlSystemsBase as CS filt.xd => 0.0 ]) - sys = structural_simplify(closed_loop) + sys = mtkbuild(closed_loop) prob = ODEProblem(sys, unknowns(sys) .=> 0.0, (0.0, 4.0)) sol = solve(prob, Rodas5P(), reltol = 1e-6, abstol = 1e-9) @@ -100,8 +100,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the structural_simplify works correctly - ssys = structural_simplify(sys_outer) + # test first that the mtkbuild works correctly + ssys = mtkbuild(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -136,8 +136,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the structural_simplify works correctly - ssys = structural_simplify(sys_outer) + # test first that the mtkbuild works correctly + ssys = mtkbuild(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -172,8 +172,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the structural_simplify works correctly - ssys = structural_simplify(sys_outer) + # test first that the mtkbuild works correctly + ssys = mtkbuild(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -363,7 +363,7 @@ end sys_normal = normal_test_system() -prob = ODEProblem(structural_simplify(sys_normal), [], (0.0, 10.0)) +prob = ODEProblem(mtkbuild(sys_normal), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices_normal, _ = get_sensitivity(sys_normal, sys_normal.normal_inner.ap) @@ -384,7 +384,7 @@ matrices_normal, _ = get_sensitivity(sys_normal, sys_normal.normal_inner.ap) connect(inner.back.output, :ap, inner.F1.input)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) + prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) @@ -408,7 +408,7 @@ end connect(inner.back.output.u, :ap, inner.F1.input.u)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) + prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) @@ -432,7 +432,7 @@ end connect(inner.back.output.u, :ap, inner.F1.input.u)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) + prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) diff --git a/test/downstream/inversemodel.jl b/test/downstream/inversemodel.jl index 32d5ee87ec..0251c43e38 100644 --- a/test/downstream/inversemodel.jl +++ b/test/downstream/inversemodel.jl @@ -110,7 +110,7 @@ end end end; @named model = InverseControlledTank() -ssys = structural_simplify(model) +ssys = mtkbuild(model) cm = complete(model) op = Dict( diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index 16df29f834..45574ec8c4 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -13,11 +13,12 @@ eqs = [u ~ kp * (r - y) y ~ x] @named sys = ODESystem(eqs, t) +sys = mtkbuild(sys, inputs = [r], outputs = [y]) -lsys, ssys = linearize(sys, [r], [y]) +lsys = linearize(sys, [r], [y]) lprob = LinearizationProblem(sys, [r], [y]) lsys2 = solve(lprob) -lsys3, _ = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) +lsys3 = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) @test lsys.A[] == lsys2.A[] == lsys3.A[] == -2 @test lsys.B[] == lsys2.B[] == lsys3.B[] == 1 @@ -86,11 +87,12 @@ connections = [f.y ~ c.r # filtered reference to controller reference p.y ~ c.y] @named cl = ODESystem(connections, t, systems = [f, c, p]) +cl = mtkbuild(cl, inputs = [f.u], outputs = [p.x]) -lsys0, ssys = linearize(cl, [f.u], [p.x]) +lsys0, ssys = linearize(cl) desired_order = [f.x, p.x] lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(ssys), desired_order) -lsys1, ssys = linearize(cl, [f.u], [p.x]; autodiff = AutoFiniteDiff()) +lsys1, ssys = linearize(cl; autodiff = AutoFiniteDiff()) lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(ssys), desired_order) @test lsys.A == lsys2.A == [-2 0; 1 -2] @@ -199,7 +201,7 @@ lsys, ssys = linearize(sat, [u], [y]) # @test substitute(lsyss.D, ModelingToolkit.defaults(sat)) == lsys.D # outside the linear region the derivative is 0 -lsys, ssys = linearize(sat, [u], [y]; op = Dict(u => 2)) +lsys = linearize(sat, [u], [y]; op = Dict(u => 2)) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @@ -265,8 +267,9 @@ closed_loop = ODESystem(connections, t, systems = [model, pid, filt, sensor, r, filt.x => 0.0, filt.xd => 0.0 ]) +closed_loop = mtkbuild(closed_loop, inputs = :r, outputs = :y) -@test_nowarn linearize(closed_loop, :r, :y; warn_empty_op = false) +@test_nowarn linearize(closed_loop; warn_empty_op = false) # https://discourse.julialang.org/t/mtk-change-in-linearize/115760/3 @mtkmodel Tank_noi begin @@ -296,6 +299,7 @@ end @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi +tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize(tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2)) @@ -304,13 +308,14 @@ m_ss = 2.4000000003229878 @parameters p = 1.0 eqs = [D(x) ~ p * u, x ~ y] @named sys = ODESystem(eqs, t) +sys = mtkbuild(sys, inputs = [u]) -matrices1, _ = linearize(sys, [u], []; op = Dict(x => 2.0)) -matrices2, _ = linearize(sys, [u], []; op = Dict(y => 2.0)) +matrices1 = linearize(sys; op = Dict(x => 2.0)) +matrices2 = linearize(sys; op = Dict(y => 2.0)) @test matrices1 == matrices2 # Ensure parameter values passed as `Dict` are respected -linfun, _ = linearization_function(sys, [u], []; op = Dict(x => 2.0)) +linfun = linearization_function(sys, [u], []; op = Dict(x => 2.0)) matrices = linfun([1.0], Dict(p => 3.0), 1.0) # this would be 1 if the parameter value isn't respected @test matrices.f_u[] == 3.0 @@ -326,7 +331,7 @@ end @parameters p eqs = [0 ~ x * log(y) - p] @named sys = ODESystem(eqs, t; defaults = [p => 1.0]) - sys = complete(sys) + sys = mtkbuild(sys, inputs = [x]) @test_throws ModelingToolkit.MissingVariablesError linearize( sys, [x], []; op = Dict(x => 1.0), allow_input_derivatives = true) @test_nowarn linearize( @@ -337,6 +342,7 @@ end @testset "Symbolic values for parameters in `linearize`" begin @named tank_noi = Tank_noi() @unpack md_i, h, m, ρ, A, K = tank_noi + tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize( tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) @@ -345,6 +351,7 @@ end @testset "Warn on empty operating point" begin @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi + tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_warn ["empty operating point", "warn_empty_op"] linearize( tank_noi, [md_i], [h]; p = [md_i => 1.0]) diff --git a/test/downstream/test_disturbance_model.jl b/test/downstream/test_disturbance_model.jl index 97276437e2..937000d28a 100644 --- a/test/downstream/test_disturbance_model.jl +++ b/test/downstream/test_disturbance_model.jl @@ -55,7 +55,7 @@ end end @named model = ModelWithInputs() # Model with load disturbance -ssys = structural_simplify(model) +ssys = mtkbuild(model) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) # plot(sol) @@ -94,10 +94,10 @@ dist(; name) = ODESystem(1 / s; name) end @named model_with_disturbance = SystemModelWithDisturbanceModel() -# ssys = structural_simplify(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here +# ssys = mtkbuild(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here # lsys2 = named_ss(model_with_disturbance, [:u, :d1], # [P.inertia1.phi, P.inertia2.phi, P.inertia1.w, P.inertia2.w]) -ssys = structural_simplify(model_with_disturbance) +ssys = mtkbuild(model_with_disturbance) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) @test SciMLBase.successful_retcode(sol) @@ -137,10 +137,10 @@ dist3(; name) = ODESystem(ss(1 + 10 / s, balance = false); name) end @named model_with_disturbance = SystemModelWithDisturbanceModel() -# ssys = structural_simplify(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here +# ssys = mtkbuild(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here # lsys3 = named_ss(model_with_disturbance, [:u, :d1], # [P.inertia1.phi, P.inertia2.phi, P.inertia1.w, P.inertia2.w]) -ssys = structural_simplify(model_with_disturbance) +ssys = mtkbuild(model_with_disturbance) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) @test SciMLBase.successful_retcode(sol) diff --git a/test/dq_units.jl b/test/dq_units.jl index 3c59c479c1..cd5396b10d 100644 --- a/test/dq_units.jl +++ b/test/dq_units.jl @@ -113,24 +113,24 @@ noiseeqs = [0.1us"W" 0.1us"W" eqs = [D(L) ~ v, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) eqs = [D(V) ~ r, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) @variables V [unit = u"m"^3] L [unit = u"m"] @parameters v [unit = u"m/s"] r [unit = u"m"^3 / u"s"] eqs = [V ~ r * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) eqs = [L ~ v * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) #Jump System @parameters β [unit = u"(mol^2*s)^-1"] γ [unit = u"(mol*s)^-1"] jumpmol [ diff --git a/test/error_handling.jl b/test/error_handling.jl index 59aa6b79a1..4a7941aab3 100644 --- a/test/error_handling.jl +++ b/test/error_handling.jl @@ -42,7 +42,7 @@ rc_eqs = [connect(source.p, resistor.p) connect(capacitor.n, source.n)] @named rc_model = ODESystem(rc_eqs, t, systems = [resistor, capacitor, source]) -@test_throws ModelingToolkit.ExtraVariablesSystemException structural_simplify(rc_model) +@test_throws ModelingToolkit.ExtraVariablesSystemException mtkbuild(rc_model) @named source2 = OverdefinedConstantVoltage(V = V, I = V / R) rc_eqs2 = [connect(source2.p, resistor.p) @@ -50,4 +50,4 @@ rc_eqs2 = [connect(source2.p, resistor.p) connect(capacitor.n, source2.n)] @named rc_model2 = ODESystem(rc_eqs2, t, systems = [resistor, capacitor, source2]) -@test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(rc_model2) +@test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(rc_model2) diff --git a/test/extensions/ad.jl b/test/extensions/ad.jl index adaf6117c6..69b14d15ec 100644 --- a/test/extensions/ad.jl +++ b/test/extensions/ad.jl @@ -46,7 +46,7 @@ end Th0 => (4 / 11)^(1 / 3) * Tγ0, Tγ0 => (15 / π^2 * ργ0 * (2 * h)^2 / 7)^(1 / 4) / 5 ]) - sys = structural_simplify(sys) + sys = mtkbuild(sys) function x_at_0(θ) prob = ODEProblem(sys, [sys.x => 1.0], (0.0, 1.0), [sys.ργ0 => θ[1], sys.h => θ[2]]) @@ -111,7 +111,7 @@ fwd, back = ChainRulesCore.rrule(remake_buffer, sys, ps, idxs, vals) eqs = [D(D(y)) ~ -9.81] initialization_eqs = [y^2 ~ 0] # initialize y = 0 in a way that builds an initialization problem @named sys = ODESystem(eqs, t; initialization_eqs) - sys = structural_simplify(sys) + sys = mtkbuild(sys) # Find initial throw velocity that reaches exactly 10 m after 1 s dprob0 = ODEProblem(sys, [D(y) => NaN], (0.0, 1.0), []; guesses = [y => 0.0]) diff --git a/test/extensions/bifurcationkit.jl b/test/extensions/bifurcationkit.jl index 629edf46a6..101efb202b 100644 --- a/test/extensions/bifurcationkit.jl +++ b/test/extensions/bifurcationkit.jl @@ -97,14 +97,14 @@ end # Checks that default parameter values are accounted for. # Checks that observables (that depend on other observables, as in this case) are accounted for. let - # Creates model, and uses `structural_simplify` to generate observables. + # Creates model, and uses `mtkbuild` to generate observables. @parameters μ p=2 @variables x(t) y(t) z(t) eqs = [0 ~ μ - x^3 + 2x^2, 0 ~ p * μ - y, 0 ~ y - z] @named nsys = NonlinearSystem(eqs, [x, y, z], [μ, p]) - nsys = structural_simplify(nsys) + nsys = mtkbuild(nsys) # Creates BifurcationProblem. bif_par = μ diff --git a/test/funcaffect.jl b/test/funcaffect.jl index 3004044d61..e6a0d1c7f9 100644 --- a/test/funcaffect.jl +++ b/test/funcaffect.jl @@ -129,7 +129,7 @@ s1 = compose( ODESystem(Equation[], t, [], [], name = :s1, discrete_events = 1.0 => (affect4!, [resistor.v], [], [], ctx)), resistor) -s2 = structural_simplify(s1) +s2 = mtkbuild(s1) prob = ODEProblem(s2, [resistor.v => 10.0], (0, 2.01)) sol = solve(prob, Tsit5()) @test ctx[1] == 2 @@ -148,7 +148,7 @@ end ]) rc_model = compose(rc_model, [resistor, capacitor, source, ground]) -sys = structural_simplify(rc_model) +sys = mtkbuild(rc_model) u0 = [capacitor.v => 0.0 capacitor.p.i => 0.0 resistor.v => 0.0] @@ -187,7 +187,7 @@ rc_eqs2 = [connect(source.p, resistor.p) @named rc_model2 = ODESystem(rc_eqs2, t) rc_model2 = compose(rc_model2, [resistor, capacitor2, source, ground]) -sys2 = structural_simplify(rc_model2) +sys2 = mtkbuild(rc_model2) u0 = [capacitor2.v => 0.0 capacitor2.p.i => 0.0 resistor.v => 0.0] @@ -276,7 +276,7 @@ end [y ~ zr] => (bb_affect!, [v], [], [], nothing) ]) -bb_sys = structural_simplify(bb_model) +bb_sys = mtkbuild(bb_model) @test only(ModelingToolkit.affects(ModelingToolkit.continuous_events(bb_sys))) isa ModelingToolkit.FunctionalAffect diff --git a/test/guess_propagation.jl b/test/guess_propagation.jl index 738e930adc..ae188ba2df 100644 --- a/test/guess_propagation.jl +++ b/test/guess_propagation.jl @@ -11,7 +11,7 @@ eqs = [D(x) ~ 1 initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(structural_simplify(sys)) +sys = complete(mtkbuild(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -28,7 +28,7 @@ eqs = [D(x) ~ 1 initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(structural_simplify(sys)) +sys = complete(mtkbuild(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -46,7 +46,7 @@ eqs = [D(x) ~ a] initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(structural_simplify(sys)) +sys = complete(mtkbuild(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -66,7 +66,7 @@ eqs = [D(x) ~ a, initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(structural_simplify(sys)) +sys = complete(mtkbuild(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) diff --git a/test/hierarchical_initialization_eqs.jl b/test/hierarchical_initialization_eqs.jl index 1e3109a66e..022c5c4431 100644 --- a/test/hierarchical_initialization_eqs.jl +++ b/test/hierarchical_initialization_eqs.jl @@ -140,7 +140,7 @@ syslist = ModelingToolkit.get_systems(model) @test length(ModelingToolkit.initialization_equations(model)) == 2 u0 = [] -prob = ODEProblem(structural_simplify(model), u0, (0.0, 10.0)) +prob = ODEProblem(mtkbuild(model), u0, (0.0, 10.0)) sol = solve(prob, Rodas5P()) @test length(sol.u[end]) == 2 @test length(equations(prob.f.initializeprob.f.sys)) == 0 diff --git a/test/if_lifting.jl b/test/if_lifting.jl index 9c58e676d0..b6f5ac3387 100644 --- a/test/if_lifting.jl +++ b/test/if_lifting.jl @@ -13,9 +13,9 @@ using ModelingToolkit: t_nounits as t, D_nounits as D, IfLifting, no_if_lift end end @named sys = SimpleAbs() - ss1 = structural_simplify(sys) + ss1 = mtkbuild(sys) @test length(equations(ss1)) == 1 - ss2 = structural_simplify(sys, additional_passes = [IfLifting]) + ss2 = mtkbuild(sys, additional_passes = [IfLifting]) @test length(equations(ss2)) == 1 @test length(parameters(ss2)) == 1 @test operation(only(equations(ss2)).rhs) === ifelse @@ -71,7 +71,7 @@ end end @named sys = BigModel() - ss = structural_simplify(sys, additional_passes = [IfLifting]) + ss = mtkbuild(sys, additional_passes = [IfLifting]) ps = parameters(ss) @test length(ps) == 9 diff --git a/test/initializationsystem.jl b/test/initializationsystem.jl index 5c36fcba3e..2d90940983 100644 --- a/test/initializationsystem.jl +++ b/test/initializationsystem.jl @@ -415,7 +415,7 @@ sol = solve(prob, Tsit5()) D(z) ~ x * y - β * z] @named sys = ODESystem(eqs, t) - sys = structural_simplify(sys) + sys = mtkbuild(sys) u0 = [D(x) => 2.0, x => 1.0, @@ -444,7 +444,7 @@ eqs = [D(x) ~ α * x - β * x * y z ~ x + y] @named sys = ODESystem(eqs, t) -simpsys = structural_simplify(sys) +simpsys = mtkbuild(sys) tspan = (0.0, 10.0) prob = ODEProblem(simpsys, [D(x) => 0.0, y => 0.0], tspan, guesses = [x => 0.0]) @@ -477,7 +477,7 @@ prob = ODEProblem(pend, [x => 1], (0.0, 1.5), [g => 1], guesses = [λ => 0, y => 1], initialization_eqs = [y ~ 1]) unsimp = generate_initializesystem(pend; u0map = [x => 1], initialization_eqs = [y ~ 1]) -sys = structural_simplify(unsimp; fully_determined = false) +sys = mtkbuild(unsimp; fully_determined = false) @test length(equations(sys)) in (3, 4) # could be either depending on tearing # Extend two systems with initialization equations and guesses @@ -493,7 +493,7 @@ sys = extend(sysx, sysy) @testset "Error on missing defaults" begin @variables x(t) y(t) @named sys = ODESystem([x^2 + y^2 ~ 25, D(x) ~ 1], t) - ssys = structural_simplify(sys) + ssys = mtkbuild(sys) @test_throws ModelingToolkit.MissingVariablesError ODEProblem( ssys, [x => 3], (0, 1), []) # y should have a guess end @@ -504,7 +504,7 @@ end # system 1 should solve to x = 1 ics1 = [x => 1] - sys1 = ODESystem([D(x) ~ 0], t; defaults = ics1, name = :sys1) |> structural_simplify + sys1 = ODESystem([D(x) ~ 0], t; defaults = ics1, name = :sys1) |> mtkbuild prob1 = ODEProblem(sys1, [], (0.0, 1.0), []) sol1 = solve(prob1, Tsit5()) @test all(sol1[x] .== 1) @@ -513,7 +513,7 @@ end sys2 = extend( sys1, ODESystem([D(y) ~ 0], t; initialization_eqs = [y ~ 2], name = :sys2) - ) |> structural_simplify + ) |> mtkbuild ics2 = unknowns(sys1) .=> 2 # should be equivalent to "ics2 = [x => 2]" prob2 = ODEProblem(sys2, ics2, (0.0, 1.0), []; fully_determined = true) sol2 = solve(prob2, Tsit5()) @@ -525,12 +525,12 @@ end @variables x(t) sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [x ~ 0, D(x) ~ 1], name = :sys) |> - structural_simplify + mtkbuild @test_nowarn ODEProblem(sys, [], (0.0, 1.0), []) sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [x ~ 0, D(D(x)) ~ 0], name = :sys) |> - structural_simplify + mtkbuild @test_nowarn ODEProblem(sys, [D(x) => 1.0], (0.0, 1.0), []) end @@ -541,7 +541,7 @@ end sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [D(x)^2 ~ 1, x ~ 0], guesses = [D(x) => sign], name = :sys - ) |> structural_simplify + ) |> mtkbuild prob = ODEProblem(sys, [], (0.0, 1.0), []) sol = solve(prob, Tsit5()) @test sol(1.0, idxs = sys.x) ≈ sign # system with D(x(0)) = ±1 should solve to x(1) = ±1 @@ -582,7 +582,7 @@ sol = solve(oprob_2nd_order_2, Rosenbrock23()) # retcode: Success @testset "Vector in initial conditions" begin @variables x(t)[1:5] y(t)[1:5] @named sys = ODESystem([D(x) ~ x, D(y) ~ y], t; initialization_eqs = [y ~ -x]) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob = ODEProblem(sys, [sys.x => ones(5)], (0.0, 1.0), []) sol = solve(prob, Tsit5(), reltol = 1e-4) @test all(sol(1.0, idxs = sys.x) .≈ +exp(1)) && all(sol(1.0, idxs = sys.y) .≈ -exp(1)) @@ -1145,7 +1145,7 @@ end end model = dc_motor() - sys = structural_simplify(model) + sys = mtkbuild(model) prob = ODEProblem(sys, [sys.L1.i => 0.0], (0, 6.0)) @@ -1250,7 +1250,7 @@ end @parameters a = 1 @named sys = ODESystem([D(x) ~ 0, D(y) ~ x + a], t; initialization_eqs = [y ~ a]) - ssys = structural_simplify(sys) + ssys = mtkbuild(sys) prob = ODEProblem(ssys, [], (0, 1), []) @test SciMLBase.successful_retcode(solve(prob)) @@ -1355,7 +1355,7 @@ end continuous_events = [ [y ~ 0.5] => (stop!, [y], [], [], nothing) ]) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob0 = ODEProblem(sys, [x => NaN], (0.0, 1.0), []) # final_x(x0) is equivalent to x0 + 0.5 diff --git a/test/input_output_handling.jl b/test/input_output_handling.jl index 693a00b9ad..0a211de9de 100644 --- a/test/input_output_handling.jl +++ b/test/input_output_handling.jl @@ -7,10 +7,10 @@ using ModelingToolkit: t_nounits as t, D_nounits as D @variables xx(t) some_input(t) [input = true] eqs = [D(xx) ~ some_input] @named model = ODESystem(eqs, t) -@test_throws ExtraVariablesSystemException structural_simplify(model, ((), ())) +@test_throws ExtraVariablesSystemException mtkbuild(model, ((), ())) if VERSION >= v"1.8" err = "In particular, the unset input(s) are:\n some_input(t)" - @test_throws err structural_simplify(model, ((), ())) + @test_throws err mtkbuild(model, ((), ())) end # Test input handling @@ -50,7 +50,7 @@ end @test !is_bound(sys31, sys1.v[2]) # simplification turns input variables into parameters -ssys, _ = structural_simplify(sys, ([u], [])) +ssys, _ = mtkbuild(sys, ([u], [])) @test ModelingToolkit.isparameter(unbound_inputs(ssys)[]) @test !is_bound(ssys, u) @test u ∈ Set(unbound_inputs(ssys)) @@ -88,7 +88,7 @@ fsys4 = flatten(sys4) @variables x(t) y(t) [output = true] @test isoutput(y) @named sys = ODESystem([D(x) ~ -x, y ~ x], t) # both y and x are unbound -syss = structural_simplify(sys) # This makes y an observed variable +syss = mtkbuild(sys) # This makes y an observed variable @named sys2 = ODESystem([D(x) ~ -sys.x, y ~ sys.y], t, systems = [sys]) @@ -106,7 +106,7 @@ syss = structural_simplify(sys) # This makes y an observed variable @test isequal(unbound_outputs(sys2), [y]) @test isequal(bound_outputs(sys2), [sys.y]) -syss = structural_simplify(sys2) +syss = mtkbuild(sys2) @test !is_bound(syss, y) @test !is_bound(syss, x) @@ -281,7 +281,7 @@ i = findfirst(isequal(u[1]), out) @variables x(t) u(t) [input = true] eqs = [D(x) ~ u] @named sys = ODESystem(eqs, t) -@test_nowarn structural_simplify(sys, ([u], [])) +@test_nowarn mtkbuild(sys, ([u], [])) #= ## Disturbance input handling @@ -366,7 +366,7 @@ eqs = [D(y₁) ~ -k₁ * y₁ + k₃ * y₂ * y₃ + u1 @named sys = ODESystem(eqs, t) m_inputs = [u[1], u[2]] m_outputs = [y₂] -sys_simp, input_idxs = structural_simplify(sys, (; inputs = m_inputs, outputs = m_outputs)) +sys_simp, input_idxs = mtkbuild(sys, (; inputs = m_inputs, outputs = m_outputs)) @test isequal(unknowns(sys_simp), collect(x[1:2])) @test length(input_idxs) == 2 @@ -384,12 +384,12 @@ sys_simp, input_idxs = structural_simplify(sys, (; inputs = m_inputs, outputs = ], t, systems = [int, gain, c, fb]) -sys = structural_simplify(model) +sys = mtkbuild(model) @test length(unknowns(sys)) == length(equations(sys)) == 1 ## Disturbance models when plant has multiple inputs using ModelingToolkit, LinearAlgebra -using ModelingToolkit: DisturbanceModel, io_preprocessing, get_iv, get_disturbance_system +using ModelingToolkit: DisturbanceModel, get_iv, get_disturbance_system using ModelingToolkitStandardLibrary.Blocks A, C = [randn(2, 2) for i in 1:2] B = [1.0 0; 0 1.0] diff --git a/test/jumpsystem.jl b/test/jumpsystem.jl index 6c96055270..488b9396f6 100644 --- a/test/jumpsystem.jl +++ b/test/jumpsystem.jl @@ -269,7 +269,7 @@ dp4 = DiscreteProblem(js4, u0, tspan) @test_nowarn jp3 = JumpProblem(js3, dp3, Direct()) @test_nowarn jp4 = JumpProblem(js4, dp4, Direct()) -# Ensure `structural_simplify` (and `@mtkbuild`) works on JumpSystem (by doing nothing) +# Ensure `mtkbuild` (and `@mtkbuild`) works on JumpSystem (by doing nothing) # Issue#2558 @parameters k @variables X(t) diff --git a/test/modelingtoolkitize.jl b/test/modelingtoolkitize.jl index db99cc91a4..4ce25602d2 100644 --- a/test/modelingtoolkitize.jl +++ b/test/modelingtoolkitize.jl @@ -440,7 +440,7 @@ prob = NonlinearLeastSquaresProblem( NonlinearFunction(nlls!, resid_prototype = zeros(3)), u0) sys = modelingtoolkitize(prob) @test length(equations(sys)) == 3 -@test length(equations(structural_simplify(sys; fully_determined = false))) == 0 +@test length(equations(mtkbuild(sys; fully_determined = false))) == 0 @testset "`modelingtoolkitize(::SDEProblem)` sets defaults" begin function sdeg!(du, u, p, t) diff --git a/test/mtkparameters.jl b/test/mtkparameters.jl index 55de0768e0..10bda707d2 100644 --- a/test/mtkparameters.jl +++ b/test/mtkparameters.jl @@ -170,7 +170,7 @@ function level1() eqs = [D(x) ~ p1 * x - p2 * x * y D(y) ~ -p3 * y + p4 * x * y] - sys = structural_simplify(complete(ODESystem( + sys = mtkbuild(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end @@ -184,7 +184,7 @@ function level2() eqs = [D(x) ~ p1 * x - p23[1] * x * y D(y) ~ -p23[2] * y + p4 * x * y] - sys = structural_simplify(complete(ODESystem( + sys = mtkbuild(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end @@ -198,7 +198,7 @@ function level3() eqs = [D(x) ~ p1 * x - p23[1] * x * y D(y) ~ -p23[2] * y + p4 * x * y] - sys = structural_simplify(complete(ODESystem( + sys = mtkbuild(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end diff --git a/test/nonlinearsystem.jl b/test/nonlinearsystem.jl index a315371141..06f0122724 100644 --- a/test/nonlinearsystem.jl +++ b/test/nonlinearsystem.jl @@ -121,7 +121,7 @@ using OrdinaryDiffEq D = Differential(t) @named subsys = convert_system(ODESystem, lorenz1, t) @named sys = ODESystem([D(subsys.x) ~ subsys.x + subsys.x], t, systems = [subsys]) -sys = structural_simplify(sys) +sys = mtkbuild(sys) u0 = [subsys.x => 1, subsys.z => 2.0, subsys.y => 1.0] prob = ODEProblem(sys, u0, (0, 1.0), [subsys.σ => 1, subsys.ρ => 2, subsys.β => 3]) sol = solve(prob, FBDF(), reltol = 1e-7, abstol = 1e-7) @@ -198,7 +198,7 @@ eq = [v1 ~ sin(2pi * t * h) v2 ~ i2 i1 ~ i2] @named sys = ODESystem(eq, t) -@test length(equations(structural_simplify(sys))) == 0 +@test length(equations(mtkbuild(sys))) == 0 @testset "Issue: 1504" begin @variables u[1:4] @@ -257,7 +257,7 @@ end @named ns = NonlinearSystem(eqs, [x, y, z], []) ns = complete(ns) vs = [unknowns(ns); parameters(ns)] - ss_mtk = structural_simplify(ns) + ss_mtk = mtkbuild(ns) prob = NonlinearProblem(ss_mtk, vs .=> 1.0) sol = solve(prob) @test_nowarn sol[unknowns(ns)] @@ -277,16 +277,16 @@ sys = @test_nowarn NonlinearSystem(alg_eqs; name = :name) @parameters u3 u4 eqs = [u3 ~ u1 + u2, u4 ~ 2 * (u1 + u2), u3 + u4 ~ 3 * (u1 + u2)] @named ns = NonlinearSystem(eqs, [u1, u2], [u3, u4]) -sys = structural_simplify(ns; fully_determined = false) +sys = mtkbuild(ns; fully_determined = false) @test length(unknowns(sys)) == 1 # Conservative @variables X(t) alg_eqs = [1 ~ 2X] @named ns = NonlinearSystem(alg_eqs) -sys = structural_simplify(ns) +sys = mtkbuild(ns) @test length(equations(sys)) == 0 -sys = structural_simplify(ns; conservative = true) +sys = mtkbuild(ns; conservative = true) @test length(equations(sys)) == 1 # https://github.com/SciML/ModelingToolkit.jl/issues/2858 @@ -338,7 +338,7 @@ end -1 1/2 -1] b = [1, -2, 0] @named sys = NonlinearSystem(A * x ~ b, [x], []) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob = NonlinearProblem(sys, unknowns(sys) .=> 0.0) sol = solve(prob) @test all(sol[x] .≈ A \ b) @@ -349,8 +349,8 @@ end @parameters p @named sys = NonlinearSystem([x ~ 1, x^2 - p ~ 0]) for sys in [ - structural_simplify(sys, fully_determined = false), - structural_simplify(sys, fully_determined = false, split = false) + mtkbuild(sys, fully_determined = false), + mtkbuild(sys, fully_determined = false, split = false) ] @test length(equations(sys)) == 1 @test length(unknowns(sys)) == 0 @@ -424,7 +424,7 @@ end @test ModelingToolkit.iscomplete(nlsys) @test ModelingToolkit.is_split(nlsys) - sys3 = structural_simplify(sys) + sys3 = mtkbuild(sys) nlsys = NonlinearSystem(sys3) @test length(equations(nlsys)) == length(ModelingToolkit.observed(nlsys)) == 1 diff --git a/test/odesystem.jl b/test/odesystem.jl index f5fef1fd6f..27a1a3432e 100644 --- a/test/odesystem.jl +++ b/test/odesystem.jl @@ -478,7 +478,7 @@ end let @variables x(t)[1:3, 1:3] @named sys = ODESystem(D.(x) .~ x, t) - @test_nowarn structural_simplify(sys) + @test_nowarn mtkbuild(sys) end # Array vars @@ -489,7 +489,7 @@ ps = @parameters p[1:3] = [1, 2, 3] eqs = [collect(D.(x) .~ x) D(y) ~ norm(collect(x)) * y - x[1]] @named sys = ODESystem(eqs, t, sts, ps) -sys = structural_simplify(sys) +sys = mtkbuild(sys) @test isequal(@nonamespace(sys.x), x) @test isequal(@nonamespace(sys.y), y) @test isequal(@nonamespace(sys.p), p) @@ -661,7 +661,7 @@ let D(x[2]) ~ -x[1] - 0.5 * x[2] + k y ~ 0.9 * x[1] + x[2]] @named sys = ODESystem(eqs, t, vcat(x, [y]), [k], defaults = Dict(x .=> 0)) - sys = structural_simplify(sys) + sys = mtkbuild(sys) u0 = [0.5, 0] du0 = 0 .* copy(u0) @@ -743,7 +743,7 @@ let 0 ~ q / C - R * F] @named sys = ODESystem(eqs, t) - @test length(equations(structural_simplify(sys))) == 2 + @test length(equations(mtkbuild(sys))) == 2 end let @@ -778,12 +778,12 @@ let @named sys1 = ODESystem(eqs, t) @named sys2 = ODESystem(eqs2, t) @named sys3 = ODESystem(eqs3, t) - ssys3 = structural_simplify(sys3) + ssys3 = mtkbuild(sys3) @named sys4 = ODESystem(eqs4, t) @test ModelingToolkit.isisomorphic(sys1, sys2) @test !ModelingToolkit.isisomorphic(sys1, sys3) - @test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call structural_simplify in isisomorphic + @test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call mtkbuild in isisomorphic @test !ModelingToolkit.isisomorphic(sys1, sys4) # 1281 @@ -801,7 +801,7 @@ let spm ~ 0 sph ~ a] @named sys = ODESystem(eqs, t, vars, pars) - @test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(sys) + @test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(sys) end # 1561 @@ -825,9 +825,9 @@ let ps = [] @named sys = ODESystem(eqs, t, u, ps) - @test_nowarn simpsys = structural_simplify(sys) + @test_nowarn simpsys = mtkbuild(sys) - sys = structural_simplify(sys) + sys = mtkbuild(sys) u0 = ModelingToolkit.missing_variable_defaults(sys) u0_expected = Pair[s => 0.0 for s in unknowns(sys)] @@ -913,7 +913,7 @@ let @named connected = ODESystem(connections, t) @named sys_con = compose(connected, sys, ctrl) - sys_simp = structural_simplify(sys_con) + sys_simp = mtkbuild(sys_con) true_eqs = [D(sys.x) ~ sys.v D(sys.v) ~ ctrl.kv * sys.v + ctrl.kx * sys.x] @test issetequal(full_equations(sys_simp), true_eqs) @@ -924,7 +924,7 @@ let @variables y(t) = 1 @parameters pp = -1 @named sys4 = ODESystem([D(x) ~ -y; D(y) ~ 1 + pp * y + x], t) - sys4s = structural_simplify(sys4) + sys4s = mtkbuild(sys4) prob = ODEProblem(sys4s, [x => 1.0, D(x) => 1.0], (0, 1.0)) @test string.(unknowns(prob.f.sys)) == ["x(t)", "y(t)"] @test string.(parameters(prob.f.sys)) == ["pp"] @@ -963,7 +963,7 @@ let @parameters pp = -1 der = Differential(t) @named sys4 = ODESystem([der(x) ~ -y; der(y) ~ 1 + pp * y + x], t) - sys4s = structural_simplify(sys4) + sys4s = mtkbuild(sys4) prob = ODEProblem(sys4s, [x => 1.0, D(x) => 1.0], (0, 1.0)) @test !isnothing(prob.f.sys) end @@ -999,7 +999,7 @@ let # Issue https://github.com/SciML/ModelingToolkit.jl/issues/2322 sys = ODESystem(eqs, t; name = :kjshdf) - sys_simp = structural_simplify(sys) + sys_simp = mtkbuild(sys) @test a ∈ keys(ModelingToolkit.defaults(sys_simp)) @@ -1140,7 +1140,7 @@ orig_vars = unknowns(sys) @named outer = ODESystem( [D(y) ~ sys.x + t, 0 ~ t + y - sys.x * y], t, [y], []; systems = [sys]) @test ModelingToolkit.guesses(outer)[sys.x] == 1.0 -outer = structural_simplify(outer) +outer = mtkbuild(outer) @test ModelingToolkit.get_guesses(outer)[sys.x] == 1.0 prob = ODEProblem(outer, [outer.y => 2.0], (0.0, 10.0)) int = init(prob, Rodas4()) @@ -1176,7 +1176,7 @@ end @testset "Non-1-indexed variable array (issue #2670)" begin @variables x(t)[0:1] # 0-indexed variable array @named sys = ODESystem([x[0] ~ 0.0, D(x[1]) ~ x[0]], t, [x], []) - @test_nowarn sys = structural_simplify(sys) + @test_nowarn sys = mtkbuild(sys) @test equations(sys) == [D(x[1]) ~ 0.0] end @@ -1190,7 +1190,7 @@ end @testset "ForwardDiff through ODEProblem constructor" begin @parameters P @variables x(t) - sys = structural_simplify(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) + sys = mtkbuild(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) function x_at_1(P) prob = ODEProblem(sys, [x => P], (0.0, 1.0), [sys.P => P]) @@ -1203,7 +1203,7 @@ end @testset "Inplace observed functions" begin @parameters P @variables x(t) - sys = structural_simplify(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) + sys = mtkbuild(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) obsfn = ModelingToolkit.build_explicit_observed_function( sys, [x + 1, x + P, x + t], return_inplace = true)[2] ps = ModelingToolkit.MTKParameters(sys, [P => 2.0]) @@ -1240,7 +1240,7 @@ end initialization_eqs = [x ~ T] guesses = [x => 0.0] @named sys2 = ODESystem(eqs, T; initialization_eqs, guesses) - prob2 = ODEProblem(structural_simplify(sys2), [], (1.0, 2.0), []) + prob2 = ODEProblem(mtkbuild(sys2), [], (1.0, 2.0), []) sol2 = solve(prob2) @test all(sol2[x] .== 1.0) end @@ -1265,7 +1265,7 @@ end eqs = [D(x) ~ 0, y ~ x, D(z) ~ 0] defaults = [x => 1, z => y] @named sys = ODESystem(eqs, t; defaults) - ssys = structural_simplify(sys) + ssys = mtkbuild(sys) prob = ODEProblem(ssys, [], (0.0, 1.0), []) @test prob[x] == prob[y] == prob[z] == 1.0 @@ -1274,7 +1274,7 @@ end eqs = [D(x) ~ 0, y ~ y0 / x, D(z) ~ y] defaults = [y0 => 1, x => 1, z => y] @named sys = ODESystem(eqs, t; defaults) - ssys = structural_simplify(sys) + ssys = mtkbuild(sys) prob = ODEProblem(ssys, [], (0.0, 1.0), []) @test prob[x] == prob[y] == prob[z] == 1.0 end @@ -1285,11 +1285,11 @@ end @named sys = ODESystem( [D(u) ~ (sum(u) + sum(x) + sum(p) + sum(o)) * x, o ~ prod(u) * x], t, [u..., x..., o...], [p...]) - sys1, = structural_simplify(sys, ([x...], [])) + sys1, = mtkbuild(sys, ([x...], [])) fn1, = ModelingToolkit.generate_function(sys1; expression = Val{false}) ps = MTKParameters(sys1, [x => 2ones(2), p => 3ones(2, 2)]) @test_nowarn fn1(ones(4), ps, 4.0) - sys2, = structural_simplify(sys, ([x...], []); split = false) + sys2, = mtkbuild(sys, ([x...], []); split = false) fn2, = ModelingToolkit.generate_function(sys2; expression = Val{false}) ps = zeros(8) setp(sys2, x)(ps, 2ones(2)) @@ -1373,10 +1373,10 @@ end @named outersys = ODESystem( [D(innersys.y) ~ innersys.y + p4], t; parameter_dependencies = [p4 ~ 3p3], defaults = [p3 => 3.0, p4 => 9.0], guesses = [p4 => 10.0], systems = [innersys]) - @test_nowarn structural_simplify(outersys) + @test_nowarn mtkbuild(outersys) @parameters p5 sys2 = substitute(outersys, [p4 => p5]) - @test_nowarn structural_simplify(sys2) + @test_nowarn mtkbuild(sys2) @test length(equations(sys2)) == 2 @test length(parameters(sys2)) == 2 @test length(full_parameters(sys2)) == 4 @@ -1398,7 +1398,7 @@ end o[2] ~ sum(p) * sum(x)] @named sys = ODESystem(eqs, t, [u..., x..., o], [p...]) - sys1, = structural_simplify(sys, ([x...], [o...]), split = false) + sys1, = mtkbuild(sys, ([x...], [o...]), split = false) @test_nowarn ModelingToolkit.build_explicit_observed_function(sys1, u; inputs = [x...]) @@ -1436,7 +1436,7 @@ end @test_nowarn ODEProblem(sys, [], (0.0, 1.0)) else @test_throws [ - r"array (equations|unknowns)", "structural_simplify", "scalarize"] ODEProblem( + r"array (equations|unknowns)", "mtkbuild", "scalarize"] ODEProblem( sys, [], (0.0, 1.0)) end end @@ -1449,7 +1449,7 @@ end @test_nowarn ODEProblem(sys, [], (0.0, 1.0)) else @test_throws [ - r"array (equations|unknowns)", "structural_simplify", "scalarize"] ODEProblem( + r"array (equations|unknowns)", "mtkbuild", "scalarize"] ODEProblem( sys, [], (0.0, 1.0)) end end @@ -1632,7 +1632,7 @@ end @test lowered_vars == expected_vars end -@testset "dae_order_lowering test with structural_simplify" begin +@testset "dae_order_lowering test with mtkbuild" begin @variables x(t) y(t) z(t) @parameters M b k eqs = [ @@ -1647,7 +1647,7 @@ end default_p = [M => 1.0, b => 1.0, k => 1.0] @named dae_sys = ODESystem(eqs, t, [x, y, z], ps; defaults = [default_u0; default_p]) - simplified_dae_sys = structural_simplify(dae_sys) + simplified_dae_sys = mtkbuild(dae_sys) lowered_dae_sys = dae_order_lowering(simplified_dae_sys) lowered_dae_sys = complete(lowered_dae_sys) diff --git a/test/optimizationsystem.jl b/test/optimizationsystem.jl index 2ec9516721..9d6053a45b 100644 --- a/test/optimizationsystem.jl +++ b/test/optimizationsystem.jl @@ -85,7 +85,7 @@ end z ~ y - x^2 z^2 + y^2 ≲ 1.0] @named sys = OptimizationSystem(loss, [x, y, z], [a, b], constraints = cons) - sys = structural_simplify(sys) + sys = mtkbuild(sys) prob = OptimizationProblem(sys, [x => 0.0, y => 0.0, z => 0.0], [a => 1.0, b => 1.0], grad = true, hess = true, cons_j = true, cons_h = true) sol = solve(prob, IPNewton()) diff --git a/test/parameter_dependencies.jl b/test/parameter_dependencies.jl index 31881e1ca8..beffacc83f 100644 --- a/test/parameter_dependencies.jl +++ b/test/parameter_dependencies.jl @@ -170,7 +170,7 @@ end # (https://github.com/SciML/ModelingToolkit.jl/pull/2978) @inferred ModelingToolkit.parameter_dependencies(sys1) - sys = structural_simplify(sys1) + sys = mtkbuild(sys1) prob = ODEProblem(sys, [], (0.0, 1.0)) sol = solve(prob) @@ -192,7 +192,7 @@ end eqs = [D(y) ~ i(t) + p] @named model = ODESystem(eqs, t, [y], [p, i]; parameter_dependencies = [i ~ CallableFoo(p)]) - sys = structural_simplify(model) + sys = mtkbuild(model) prob = ODEProblem(sys, [], (0.0, 1.0)) sol = solve(prob, Tsit5()) diff --git a/test/reduction.jl b/test/reduction.jl index fa9029a652..1f0028fc6e 100644 --- a/test/reduction.jl +++ b/test/reduction.jl @@ -30,7 +30,7 @@ eqs = [D(x) ~ σ * (y - x) lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_aliased = structural_simplify(lorenz1) +lorenz1_aliased = mtkbuild(lorenz1) io = IOBuffer(); show(io, MIME("text/plain"), lorenz1_aliased); str = String(take!(io)); @@ -74,8 +74,8 @@ __x = x # Reduced Flattened System -reduced_system = structural_simplify(connected) -reduced_system2 = structural_simplify(tearing_substitution(structural_simplify(tearing_substitution(structural_simplify(connected))))) +reduced_system = mtkbuild(connected) +reduced_system2 = mtkbuild(tearing_substitution(mtkbuild(tearing_substitution(mtkbuild(connected))))) @test isempty(setdiff(unknowns(reduced_system), unknowns(reduced_system2))) @test isequal(equations(tearing_substitution(reduced_system)), equations(reduced_system2)) @@ -133,7 +133,7 @@ let pc.y_c ~ ol.y] @named connected = ODESystem(connections, t, systems = [ol, pc]) @test equations(connected) isa Vector{Equation} - reduced_sys = structural_simplify(connected) + reduced_sys = mtkbuild(connected) ref_eqs = [D(ol.x) ~ ol.a * ol.x + ol.b * ol.u 0 ~ pc.k_P * ol.y - ol.u] #@test ref_eqs == equations(reduced_sys) @@ -144,7 +144,7 @@ let @variables x(t) @named sys = ODESystem([0 ~ D(x) + x], t, [x], []) #@test_throws ModelingToolkit.InvalidSystemException ODEProblem(sys, [1.0], (0, 10.0)) - sys = structural_simplify(sys) + sys = mtkbuild(sys) #@test_nowarn ODEProblem(sys, [1.0], (0, 10.0)) end @@ -155,7 +155,7 @@ eqs = [u1 ~ u2 u3 ~ u1 + u2 + p u3 ~ hypot(u1, u2) * p] @named sys = NonlinearSystem(eqs, [u1, u2, u3], [p]) -reducedsys = structural_simplify(sys) +reducedsys = mtkbuild(sys) @test length(observed(reducedsys)) == 2 u0 = [u2 => 1] @@ -175,7 +175,7 @@ N = 5 A = reshape(1:(N^2), N, N) eqs = xs ~ A * xs @named sys′ = NonlinearSystem(eqs, [xs], []) -sys = structural_simplify(sys′) +sys = mtkbuild(sys′) @test length(equations(sys)) == 3 && length(observed(sys)) == 2 # issue 958 @@ -189,7 +189,7 @@ eqs = [D(E) ~ k₋₁ * C - k₁ * E * S E₀ ~ E + C] @named sys = ODESystem(eqs, t, [E, C, S, P], [k₁, k₂, k₋₁, E₀]) -@test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(sys) +@test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(sys) # Example 5 from Pantelides' original paper params = collect(@parameters y1(t) y2(t)) @@ -198,7 +198,7 @@ eqs = [0 ~ x + sin(u1 + u2) D(x) ~ x + y1 cos(x) ~ sin(y2)] @named sys = ODESystem(eqs, t, sts, params) -@test_throws ModelingToolkit.InvalidSystemException structural_simplify(sys) +@test_throws ModelingToolkit.InvalidSystemException mtkbuild(sys) # issue #963 @variables v47(t) v57(t) v66(t) v25(t) i74(t) i75(t) i64(t) i71(t) v1(t) v2(t) @@ -215,7 +215,7 @@ eq = [v47 ~ v1 0 ~ i64 + i71] @named sys0 = ODESystem(eq, t) -sys = structural_simplify(sys0) +sys = mtkbuild(sys0) @test length(equations(sys)) == 1 eq = equations(tearing_substitution(sys))[1] vv = only(unknowns(sys)) @@ -233,7 +233,7 @@ eqs = [D(x) ~ σ * (y - x) u ~ z + a] lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_reduced, _ = structural_simplify(lorenz1, ([z], [])) +lorenz1_reduced, _ = mtkbuild(lorenz1, ([z], [])) @test z in Set(parameters(lorenz1_reduced)) # #2064 @@ -242,7 +242,7 @@ eqs = [D(x) ~ x D(y) ~ y D(z) ~ t] @named model = ODESystem(eqs, t) -sys = structural_simplify(model) +sys = mtkbuild(model) Js = ModelingToolkit.jacobian_sparsity(sys) @test size(Js) == (3, 3) @test Js == Diagonal([1, 1, 0]) @@ -275,7 +275,7 @@ new_sys = alias_elimination(sys) eqs = [x ~ 0 D(x) ~ x + y] @named sys = ODESystem(eqs, t, [x, y], []) -ss = structural_simplify(sys) +ss = mtkbuild(sys) @test isempty(equations(ss)) @test sort(string.(observed(ss))) == ["x(t) ~ 0.0" "xˍt(t) ~ 0.0" @@ -285,5 +285,5 @@ eqs = [D(D(x)) ~ -x] @named sys = ODESystem(eqs, t, [x], []) ss = alias_elimination(sys) @test length(equations(ss)) == length(unknowns(ss)) == 1 -ss = structural_simplify(sys) +ss = mtkbuild(sys) @test length(equations(ss)) == length(unknowns(ss)) == 2 diff --git a/test/scc_nonlinear_problem.jl b/test/scc_nonlinear_problem.jl index b2b326d090..ecd5af5f8a 100644 --- a/test/scc_nonlinear_problem.jl +++ b/test/scc_nonlinear_problem.jl @@ -22,9 +22,9 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = 0 .~ eqs @named model = NonlinearSystem(eqs) @test_throws ["simplified", "required"] SCCNonlinearProblem(model, []) - _model = structural_simplify(model; split = false) + _model = mtkbuild(model; split = false) @test_throws ["not compatible"] SCCNonlinearProblem(_model, []) - model = structural_simplify(model) + model = mtkbuild(model) prob = NonlinearProblem(model, [u => zeros(8)]) sccprob = SCCNonlinearProblem(model, [u => zeros(8)]) sol1 = solve(prob, NewtonRaphson()) diff --git a/test/sciml_problem_inputs.jl b/test/sciml_problem_inputs.jl index bfa560cda3..671cf8832e 100644 --- a/test/sciml_problem_inputs.jl +++ b/test/sciml_problem_inputs.jl @@ -37,7 +37,7 @@ begin MassActionJump(k2, [Z => 1], [Y => 1, Z => -1]) ] - # Create systems (without structural_simplify, since that might modify systems to affect intended tests). + # Create systems (without mtkbuild, since that might modify systems to affect intended tests). osys = complete(ODESystem(diff_eqs, t; name = :osys)) ssys = complete(SDESystem( diff_eqs, noise_eqs, t, [X, Y, Z], [kp, kd, k1, k2]; name = :ssys)) diff --git a/test/sdesystem.jl b/test/sdesystem.jl index b031a2f5ab..05d424efba 100644 --- a/test/sdesystem.jl +++ b/test/sdesystem.jl @@ -596,7 +596,7 @@ eqs = [D(x) ~ σ * (y - x) + x * β, D(y) ~ x * (ρ - z) - y + y * β + x * η, D(z) ~ x * y - β * z + (x * z) * β] @named sys1 = System(eqs, tt) -sys1 = structural_simplify(sys1) +sys1 = mtkbuild(sys1) drift_eqs = [D(x) ~ σ * (y - x), D(y) ~ x * (ρ - z) - y, @@ -794,13 +794,13 @@ end input ~ 0.0] sys = System(eqs, t, sts, ps; name = :name) - sys = structural_simplify(sys) + sys = mtkbuild(sys) @test ModelingToolkit.get_noiseeqs(sys) ≈ [1.0] prob = SDEProblem(sys, [], (0.0, 1.0), []) @test_nowarn solve(prob, RKMil()) end -@testset "Observed variables retained after `structural_simplify`" begin +@testset "Observed variables retained after `mtkbuild`" begin @variables x(t) y(t) z(t) @brownian a @mtkbuild sys = System([D(x) ~ x + a, D(y) ~ y + a, z ~ x + y], t) @@ -859,7 +859,7 @@ end end end -@testset "`structural_simplify(::SDESystem)`" begin +@testset "`mtkbuild(::SDESystem)`" begin @variables x(t) y(t) @mtkbuild sys = SDESystem( [D(x) ~ x, y ~ 2x], [x, 0], t, [x, y], []; is_scalar_noise = true) @@ -947,7 +947,7 @@ end @test ssys1 !== ssys2 end -@testset "Error when constructing SDESystem without `structural_simplify`" begin +@testset "Error when constructing SDESystem without `mtkbuild`" begin @parameters σ ρ β @variables x(tt) y(tt) z(tt) @brownian a @@ -961,8 +961,8 @@ end u0map = [x => 1.0, y => 0.0, z => 0.0] parammap = [σ => 10.0, β => 26.0, ρ => 2.33] - @test_throws ErrorException("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `structural_simplify` before a SDEProblem can be constructed.") SDEProblem( + @test_throws ErrorException("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `mtkbuild` before a SDEProblem can be constructed.") SDEProblem( de, u0map, (0.0, 100.0), parammap) - de = structural_simplify(de) + de = mtkbuild(de) @test SDEProblem(de, u0map, (0.0, 100.0), parammap) isa SDEProblem end diff --git a/test/split_parameters.jl b/test/split_parameters.jl index 18fdb49a48..74286e2843 100644 --- a/test/split_parameters.jl +++ b/test/split_parameters.jl @@ -82,7 +82,7 @@ eqs = [y ~ src.output.u @named sys = ODESystem(eqs, t, vars, []; systems = [int, src]) s = complete(sys) -sys = structural_simplify(sys) +sys = mtkbuild(sys) prob = ODEProblem( sys, [], (0.0, t_end), [s.src.interpolator => Interpolator(x, dt)]; tofloat = false) @@ -108,7 +108,7 @@ eqs = [D(y) ~ dy * a ddy ~ sin(t) * c] @named model = ODESystem(eqs, t, vars, pars) -sys = structural_simplify(model; split = false) +sys = mtkbuild(model; split = false) tspan = (0.0, t_end) prob = ODEProblem(sys, [], tspan, []; build_initializeprob = false) diff --git a/test/state_selection.jl b/test/state_selection.jl index a8d3e57773..f0b5a89e59 100644 --- a/test/state_selection.jl +++ b/test/state_selection.jl @@ -118,7 +118,7 @@ let @named system = System(L = 10) @unpack supply_pipe, return_pipe = system - sys = structural_simplify(system) + sys = mtkbuild(system) u0 = [ sys.supply_pipe.v => 0.1, sys.return_pipe.v => 0.1, D(supply_pipe.v) => 0.0, D(return_pipe.fluid_port_a.m) => 0.0, @@ -169,7 +169,7 @@ let @named trans = ODESystem(eqs, t) - sys = structural_simplify(trans) + sys = mtkbuild(trans) n = 3 u = 0 * ones(n) @@ -274,7 +274,7 @@ let # solution ------------------------------------------------------------------- @named catapult = ODESystem(eqs, t, vars, params, defaults = defs) - sys = structural_simplify(catapult) + sys = mtkbuild(catapult) prob = ODEProblem(sys, [], (0.0, 0.1), [l_2f => 0.55, damp => 1e7]; jac = true) @test solve(prob, Rodas4()).retcode == ReturnCode.Success end diff --git a/test/static_arrays.jl b/test/static_arrays.jl index 61177e5ab2..e7807694a4 100644 --- a/test/static_arrays.jl +++ b/test/static_arrays.jl @@ -9,7 +9,7 @@ eqs = [D(D(x)) ~ σ * (y - x), D(z) ~ x * y - β * z] @named sys = ODESystem(eqs, t) -sys = structural_simplify(sys) +sys = mtkbuild(sys) u0 = @SVector [D(x) => 2.0, x => 1.0, diff --git a/test/stream_connectors.jl b/test/stream_connectors.jl index 834ebce1a7..e76a9fa4b4 100644 --- a/test/stream_connectors.jl +++ b/test/stream_connectors.jl @@ -134,7 +134,7 @@ eqns = [domain_connect(fluid, n1m1.port_a) @named n1m1Test = ODESystem(eqns, t, [], []; systems = [fluid, n1m1, pipe, sink]) -@test_nowarn structural_simplify(n1m1Test) +@test_nowarn mtkbuild(n1m1Test) @unpack source, port_a = n1m1 ssort(eqs) = sort(eqs, by = string) @test ssort(equations(expand_connections(n1m1))) == ssort([0 ~ port_a.m_flow @@ -205,7 +205,7 @@ eqns = [connect(n1m2.port_a, sink1.port) @named sys = ODESystem(eqns, t) @named n1m2Test = compose(sys, n1m2, sink1, sink2) -@test_nowarn structural_simplify(n1m2Test) +@test_nowarn mtkbuild(n1m2Test) @named n1m2 = N1M2() @named pipe1 = AdiabaticStraightPipe() @@ -220,7 +220,7 @@ eqns = [connect(n1m2.port_a, pipe1.port_a) @named sys = ODESystem(eqns, t) @named n1m2AltTest = compose(sys, n1m2, pipe1, pipe2, sink1, sink2) -@test_nowarn structural_simplify(n1m2AltTest) +@test_nowarn mtkbuild(n1m2AltTest) # N2M2 model and test code. function N2M2(; name, @@ -249,7 +249,7 @@ eqns = [connect(source.port, n2m2.port_a) @named sys = ODESystem(eqns, t) @named n2m2Test = compose(sys, n2m2, source, sink) -@test_nowarn structural_simplify(n2m2Test) +@test_nowarn mtkbuild(n2m2Test) # stream var @named sp1 = TwoPhaseFluidPort() @@ -472,7 +472,7 @@ csys = complete(two_fluid_system) @test Symbol(sys_defs[csys.volume_a.H.rho]) == Symbol(csys.fluid_a.rho) @test Symbol(sys_defs[csys.volume_b.H.rho]) == Symbol(csys.fluid_b.rho) -@test_nowarn structural_simplify(two_fluid_system) +@test_nowarn mtkbuild(two_fluid_system) function OneFluidSystem(; name) pars = [] @@ -510,4 +510,4 @@ csys = complete(one_fluid_system) @test Symbol(sys_defs[csys.volume_a.H.rho]) == Symbol(csys.fluid.rho) @test Symbol(sys_defs[csys.volume_b.H.rho]) == Symbol(csys.fluid.rho) -@test_nowarn structural_simplify(one_fluid_system) +@test_nowarn mtkbuild(one_fluid_system) diff --git a/test/structural_transformation/index_reduction.jl b/test/structural_transformation/index_reduction.jl index f9d6037022..a3634e7a28 100644 --- a/test/structural_transformation/index_reduction.jl +++ b/test/structural_transformation/index_reduction.jl @@ -133,7 +133,7 @@ let pss_pendulum = partial_state_selection(pendulum) @test_broken length(equations(pss_pendulum)) == 3 end -let sys = structural_simplify(pendulum2) +let sys = mtkbuild(pendulum2) @test length(equations(sys)) == 5 @test length(unknowns(sys)) == 5 @@ -160,7 +160,7 @@ let D(D(y)) ~ λ * y - g x^2 + y^2 ~ 1] @named pend = ODESystem(eqs, t) - sys = complete(structural_simplify(pend; dummy_derivative = false)) + sys = complete(mtkbuild(pend; dummy_derivative = false)) prob = ODEProblem( sys, [x => 1, y => 0, D(x) => 0.0], (0.0, 10.0), [g => 1], guesses = [λ => 0.0]) sol = solve(prob, Rodas5P()) diff --git a/test/structural_transformation/tearing.jl b/test/structural_transformation/tearing.jl index e9cd92ec94..9e83c117e7 100644 --- a/test/structural_transformation/tearing.jl +++ b/test/structural_transformation/tearing.jl @@ -148,7 +148,7 @@ eqs = [D(x) ~ z * h 0 ~ x - y 0 ~ sin(z) + y - p * t] @named daesys = ODESystem(eqs, t) -newdaesys = structural_simplify(daesys) +newdaesys = mtkbuild(daesys) @test equations(newdaesys) == [D(x) ~ z; 0 ~ y + sin(z) - p * t] @test equations(tearing_substitution(newdaesys)) == [D(x) ~ z; 0 ~ x + sin(z) - p * t] @test isequal(unknowns(newdaesys), [x, z]) @@ -165,7 +165,7 @@ prob.f(du, u, pr, tt) # test the initial guess is respected @named sys = ODESystem(eqs, t, defaults = Dict(z => NaN)) -infprob = ODEProblem(structural_simplify(sys), [x => 1.0], (0, 1.0), [p => 0.2]) +infprob = ODEProblem(mtkbuild(sys), [x => 1.0], (0, 1.0), [p => 0.2]) infprob.f(du, infprob.u0, pr, tt) @test any(isnan, du) @@ -196,7 +196,7 @@ calculate_tgrad(ms_model) u0 = [mass.s => 0.0 mass.v => 1.0] -sys = structural_simplify(ms_model) +sys = mtkbuild(ms_model) @test ModelingToolkit.get_jac(sys)[] === ModelingToolkit.EMPTY_JAC @test ModelingToolkit.get_tgrad(sys)[] === ModelingToolkit.EMPTY_TGRAD prob_complex = ODEProblem(sys, u0, (0, 1.0)) diff --git a/test/structural_transformation/utils.jl b/test/structural_transformation/utils.jl index b5335ad6b1..347756caba 100644 --- a/test/structural_transformation/utils.jl +++ b/test/structural_transformation/utils.jl @@ -122,14 +122,14 @@ end @named sys = ODESystem( [D(x) ~ z[1] + z[2] + foo(z)[1], y[1] ~ 2t, y[2] ~ 3t, z ~ foo(y)], t) - sys1 = structural_simplify(sys; cse_hack = false) + sys1 = mtkbuild(sys; cse_hack = false) @test length(observed(sys1)) == 6 @test !any(observed(sys1)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.getindex_wrapper end - sys2 = structural_simplify(sys; array_hack = false) + sys2 = mtkbuild(sys; array_hack = false) @test length(observed(sys2)) == 5 @test !any(observed(sys2)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.change_origin @@ -143,14 +143,14 @@ end @named sys = ODESystem( [D(x) ~ z[1] + z[2] + foo(z)[1] + w, y[1] ~ 2t, y[2] ~ 3t, z ~ foo(y)], t) - sys1 = structural_simplify(sys; cse_hack = false, fully_determined = false) + sys1 = mtkbuild(sys; cse_hack = false, fully_determined = false) @test length(observed(sys1)) == 6 @test !any(observed(sys1)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.getindex_wrapper end - sys2 = structural_simplify(sys; array_hack = false, fully_determined = false) + sys2 = mtkbuild(sys; array_hack = false, fully_determined = false) @test length(observed(sys2)) == 5 @test !any(observed(sys2)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.change_origin @@ -163,7 +163,7 @@ end @named sys = ODESystem([D(x) ~ x, y ~ x + t], t) value = Ref(0) pass(sys; kwargs...) = (value[] += 1; return sys) - structural_simplify(sys; additional_passes = [pass]) + mtkbuild(sys; additional_passes = [pass]) @test value[] == 1 end diff --git a/test/substitute_component.jl b/test/substitute_component.jl index 9fb254136b..ad458d34cd 100644 --- a/test/substitute_component.jl +++ b/test/substitute_component.jl @@ -59,8 +59,8 @@ end @named reference = RC() - sys1 = structural_simplify(rcsys) - sys2 = structural_simplify(reference) + sys1 = mtkbuild(rcsys) + sys2 = mtkbuild(reference) @test isequal(unknowns(sys1), unknowns(sys2)) @test isequal(equations(sys1), equations(sys2)) diff --git a/test/symbolic_events.jl b/test/symbolic_events.jl index 9099d32d14..cc576ce0be 100644 --- a/test/symbolic_events.jl +++ b/test/symbolic_events.jl @@ -445,7 +445,7 @@ affect = [v ~ -v] @test getfield(ball, :continuous_events)[] == SymbolicContinuousCallback(Equation[x ~ 0], Equation[v ~ -v]) -ball = structural_simplify(ball) +ball = mtkbuild(ball) @test length(ModelingToolkit.continuous_events(ball)) == 1 @@ -468,8 +468,8 @@ continuous_events = [[x ~ 0] => [vx ~ -vx] D(vy) ~ -0.01vy], t; continuous_events) _ball = ball -ball = structural_simplify(_ball) -ball_nosplit = structural_simplify(_ball; split = false) +ball = mtkbuild(_ball) +ball_nosplit = mtkbuild(_ball; split = false) tspan = (0.0, 5.0) prob = ODEProblem(ball, Pair[], tspan) @@ -511,8 +511,8 @@ continuous_events = [ D(vx) ~ -1 D(vy) ~ 0], t; continuous_events) -ball_nosplit = structural_simplify(ball) -ball = structural_simplify(ball) +ball_nosplit = mtkbuild(ball) +ball = mtkbuild(ball) tspan = (0.0, 5.0) prob = ODEProblem(ball, Pair[], tspan) @@ -537,7 +537,7 @@ eq = [vs ~ sin(2pi * t) D(vmeasured) ~ 0.0] ev = [sin(20pi * t) ~ 0.0] => [vmeasured ~ v] @named sys = ODESystem(eq, t, continuous_events = ev) -sys = structural_simplify(sys) +sys = mtkbuild(sys) prob = ODEProblem(sys, zeros(2), (0.0, 5.1)) sol = solve(prob, Tsit5()) @test all(minimum((0:0.05:5) .- sol.t', dims = 2) .< 0.0001) # test that the solver stepped every 0.05s as dictated by event @@ -584,7 +584,7 @@ function Model(u, d = 0) @named model = compose(_model, mass1, mass2, sd) end model = Model(sin(30t)) -sys = structural_simplify(model) +sys = mtkbuild(model) @test isempty(ModelingToolkit.continuous_events(sys)) let @@ -823,7 +823,7 @@ let eqs = [oscce.F ~ 0] @named eqs_sys = ODESystem(eqs, t) @named oneosc_ce = compose(eqs_sys, oscce) - oneosc_ce_simpl = structural_simplify(oneosc_ce) + oneosc_ce_simpl = mtkbuild(oneosc_ce) prob = ODEProblem(oneosc_ce_simpl, [], (0.0, 2.0), []) sol = solve(prob, Tsit5(), saveat = 0.1) @@ -845,7 +845,7 @@ end evt2 = ModelingToolkit.SymbolicContinuousCallback( [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) required_crossings_c1 = [π / 2, 3 * π / 2] @@ -867,7 +867,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = (record_crossings, [c2 => :v], [], [], cr2n)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) c1_pc = filter((<=)(0) ∘ sin, required_crossings_c1) @@ -891,7 +891,7 @@ end evt2 = ModelingToolkit.SymbolicContinuousCallback( [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = nothing) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test maximum(abs.(c1_pc .- first.(cr1p))) < 1e-5 @@ -910,7 +910,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = (record_crossings, [c2 => :v], [], [], cr2n)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) c1_pc = filter((<=)(0) ∘ sin, required_crossings_c1) @@ -934,7 +934,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) required_crossings_c1 = [π / 2, 3 * π / 2] @@ -954,7 +954,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) @test maximum(abs.(first.(cr1) .- required_crossings_c1)) < 1e-4 @@ -972,7 +972,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt2, evt1]) - trigsys_ss = structural_simplify(trigsys) + trigsys_ss = mtkbuild(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) @test maximum(abs.(first.(cr1) .- required_crossings_c1)) < 1e-4 @@ -1102,7 +1102,7 @@ end end) @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_off, furnace_enable]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test all(sol[temp][sol.t .> 1.0] .<= 0.79) && all(sol[temp][sol.t .> 1.0] .>= 0.49) @@ -1122,7 +1122,7 @@ end end) @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_off, furnace_enable]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test all(sol[temp][sol.t .> 1.0] .<= 0.79) && all(sol[temp][sol.t .> 1.0] .>= 0.49) @@ -1143,7 +1143,7 @@ end @set! x.furnace_on = false end) @named sys = ODESystem(eqs, t, [temp], params; continuous_events = [furnace_off]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) @test_logs (:warn, "The symbols Any[:furnace_on] are declared as both observed and modified; this is a code smell because it becomes easy to confuse them and assign/not assign a value.") prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1160,7 +1160,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) @test_throws "refers to missing variable(s)" prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1173,7 +1173,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) @test_throws "refers to missing variable(s)" prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1185,7 +1185,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) prob = ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @test_throws "Tried to write back to" solve(prob, Tsit5()) @@ -1245,7 +1245,7 @@ end end; rootfind = SciMLBase.RightRootFind) @named sys = ODESystem( eqs, t, [theta, omega], params; continuous_events = [qAevt, qBevt]) - ss = structural_simplify(sys) + ss = mtkbuild(sys) prob = ODEProblem(ss, [theta => 1e-5], (0.0, pi)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test getp(sol, cnt)(sol) == 198 # we get 2 pulses per phase cycle (cos 0 crossing) and we go to 100 cycles; we miss a few due to the initial state @@ -1415,13 +1415,13 @@ end @named wd1 = weird1(0.021) @named wd2 = weird2(0.021) - sys1 = structural_simplify(ODESystem([], t; name = :parent, + sys1 = mtkbuild(ODESystem([], t; name = :parent, discrete_events = [0.01 => ModelingToolkit.ImperativeAffect( modified = (; θs = reduce(vcat, [[wd1.θ]])), ctx = [1]) do m, o, c, i @set! m.θs[1] = c[] += 1 end], systems = [wd1])) - sys2 = structural_simplify(ODESystem([], t; name = :parent, + sys2 = mtkbuild(ODESystem([], t; name = :parent, discrete_events = [0.01 => ModelingToolkit.ImperativeAffect( modified = (; θs = reduce(vcat, [[wd2.θ]])), ctx = [1]) do m, o, c, i @set! m.θs[1] = c[] += 1 diff --git a/test/symbolic_indexing_interface.jl b/test/symbolic_indexing_interface.jl index 8b3da5fd72..39ea2e84c2 100644 --- a/test/symbolic_indexing_interface.jl +++ b/test/symbolic_indexing_interface.jl @@ -220,7 +220,7 @@ end @variables x(t) y(t) z(t) @parameters a @named sys = ODESystem([D(x) ~ a * x, y ~ 2x, z ~ 0.0], t) - sys = structural_simplify(sys, split = false) + sys = mtkbuild(sys, split = false) for sym in [x, y, z, x + y, x + a, y / x] @test only(get_all_timeseries_indexes(sys, sym)) == ContinuousTimeseries() end diff --git a/test/units.jl b/test/units.jl index ff0cd42ac3..d9a29547a9 100644 --- a/test/units.jl +++ b/test/units.jl @@ -140,24 +140,24 @@ D = Differential(t) eqs = [D(L) ~ v, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) eqs = [D(V) ~ r, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) @variables V [unit = u"m"^3] L [unit = u"m"] @parameters v [unit = u"m/s"] r [unit = u"m"^3 / u"s"] t [unit = u"s"] eqs = [V ~ r * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) eqs = [L ~ v * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = structural_simplify(sys) +sys_simple = mtkbuild(sys) #Jump System @parameters β [unit = u"(mol^2*s)^-1"] γ [unit = u"(mol*s)^-1"] t [unit = u"s"] jumpmol [ diff --git a/test/variable_scope.jl b/test/variable_scope.jl index 59647bf441..1df75c0bf1 100644 --- a/test/variable_scope.jl +++ b/test/variable_scope.jl @@ -125,7 +125,7 @@ defs = ModelingToolkit.defaults(bar) sys4 = complete(sys3) @test length(unknowns(sys4)) == 3 @test length(parameters(sys4)) == 4 - sys5 = structural_simplify(sys3) + sys5 = mtkbuild(sys3) @test length(unknowns(sys5)) == 4 @test any(isequal(x4), unknowns(sys5)) @test length(parameters(sys5)) == 4 From fe0f93afb556f5957c459b0a2de468ae9102fa80 Mon Sep 17 00:00:00 2001 From: vyudu Date: Mon, 21 Apr 2025 23:44:47 -0400 Subject: [PATCH 04/18] fix: fix linearization tests --- src/inputoutput.jl | 16 +++++++--------- src/linearization.jl | 6 +++--- src/systems/analysis_points.jl | 4 ++++ src/systems/diffeqs/odesystem.jl | 10 +++++----- src/systems/systems.jl | 8 ++++---- src/systems/systemstructure.jl | 12 ++++++------ test/downstream/linearize.jl | 32 +++++++++++++++++--------------- 7 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 5030b7d0eb..89d27cb729 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -163,7 +163,7 @@ has_var(ex, x) = x ∈ Set(get_variables(ex)) (f_oop, f_ip), x_sym, p_sym, io_sys = generate_control_function( sys::AbstractODESystem, inputs = unbound_inputs(sys), - disturbance_inputs = nothing; + disturbance_inputs = Any[]; implicit_dae = false, simplify = false, ) @@ -289,7 +289,7 @@ function inputs_to_parameters!(state::TransformationState, inputsyms) push!(new_fullvars, v) end end - ninputs == 0 && return (state, 1:0) + ninputs == 0 && return state nvars = ndsts(graph) - ninputs new_graph = BipartiteGraph(nsrcs(graph), nvars, Val(false)) @@ -318,14 +318,13 @@ function inputs_to_parameters!(state::TransformationState, inputsyms) @set! sys.unknowns = setdiff(unknowns(sys), keys(input_to_parameters)) ps = parameters(sys) - if io !== nothing - inputs, = io + if inputsyms !== nothing # Change order of new parameters to correspond to user-provided order in argument `inputs` d = Dict{Any, Int}() for (i, inp) in enumerate(new_parameters) d[inp] = i end - permutation = [d[i] for i in inputs] + permutation = [d[i] for i in inputsyms] new_parameters = new_parameters[permutation] end @@ -334,8 +333,7 @@ function inputs_to_parameters!(state::TransformationState, inputsyms) @set! state.sys = sys @set! state.fullvars = new_fullvars @set! state.structure = structure - base_params = length(ps) - return state, (base_params + 1):(base_params + length(new_parameters)) # (1:length(new_parameters)) .+ base_params + return state end """ @@ -361,7 +359,7 @@ function get_disturbance_system(dist::DisturbanceModel{<:ODESystem}) end """ - (f_oop, f_ip), augmented_sys, dvs, p = add_input_disturbance(sys, dist::DisturbanceModel, inputs = nothing) + (f_oop, f_ip), augmented_sys, dvs, p = add_input_disturbance(sys, dist::DisturbanceModel, inputs = Any[]) Add a model of an unmeasured disturbance to `sys`. The disturbance model is an instance of [`DisturbanceModel`](@ref). @@ -410,7 +408,7 @@ model_outputs = [model.inertia1.w, model.inertia2.w, model.inertia1.phi, model.i `f_oop` will have an extra state corresponding to the integrator in the disturbance model. This state will not be affected by any input, but will affect the dynamics from where it enters, in this case it will affect additively from `model.torque.tau.u`. """ -function add_input_disturbance(sys, dist::DisturbanceModel, inputs = nothing; kwargs...) +function add_input_disturbance(sys, dist::DisturbanceModel, inputs = Any[]; kwargs...) t = get_iv(sys) @variables d(t)=0 [disturbance = true] @variables u(t)=0 [input = true] # New system input diff --git a/src/linearization.jl b/src/linearization.jl index 3bfe7eaef5..cbc538a881 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -120,7 +120,7 @@ function linearization_function(sys::AbstractSystem, inputs = unbound_inputs(sys end lin_fun = LinearizationFunction( - diff_idxs, alge_idxs, length(unknowns(sys)), + diff_idxs, alge_idxs, inputs, length(unknowns(sys)), prob, h, u0 === nothing ? nothing : similar(u0), uf_jac, h_jac, pf_jac, hp_jac, initializealg, initialization_kwargs) return lin_fun @@ -397,7 +397,7 @@ Construct a `LinearizationProblem` for linearizing the system `sys` with the giv All other keyword arguments are forwarded to `linearization_function`. """ function LinearizationProblem(sys::AbstractSystem, inputs, outputs; t = 0.0, kwargs...) - linfun, _ = linearization_function(sys, inputs, outputs; kwargs...) + linfun = linearization_function(sys, inputs, outputs; kwargs...) return LinearizationProblem(linfun, t) end @@ -764,7 +764,7 @@ Permute the state representation of `sys` obtained from [`linearize`](@ref) so t Example: ``` -lsys, ssys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]) +lsys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]) desired_order = [int.x, der.x] # Unknowns that are present in unknowns(ssys) lsys = ModelingToolkit.reorder_unknowns(lsys, unknowns(ssys), desired_order) ``` diff --git a/src/systems/analysis_points.jl b/src/systems/analysis_points.jl index 0d1a2830cf..ce2e778b93 100644 --- a/src/systems/analysis_points.jl +++ b/src/systems/analysis_points.jl @@ -596,9 +596,13 @@ Add an input without an additional output variable. PerturbOutput(ap::AnalysisPoint) = PerturbOutput(ap, false) function apply_transformation(tf::PerturbOutput, sys::AbstractSystem) + @show "ok" + @show tf.ap modify_nested_subsystem(sys, tf.ap) do ap_sys # get analysis point + @show tf.ap ap_idx = analysis_point_index(ap_sys, tf.ap) + @show ap_idx ap_idx === nothing && error("Analysis point $(nameof(tf.ap)) not found in system $(nameof(sys)).") # modified equations diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 62966c0c81..75ee49b7cd 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -472,7 +472,7 @@ Generates a function that computes the observed value(s) `ts` in the system `sys - `eval_expression = false`: If true and `expression = false`, evaluates the returned function in the module `eval_module` - `output_type = Array` the type of the array generated by a out-of-place vector-valued function - `param_only = false` if true, only allow the generated function to access system parameters -- `inputs = nothing` additinoal symbolic variables that should be provided to the generated function +- `inputs = Any[]` additional symbolic variables that should be provided to the generated function - `checkbounds = true` checks bounds if true when destructuring parameters - `op = Operator` sets the recursion terminator for the walk done by `vars` to identify the variables that appear in `ts`. See the documentation for `vars` for more detail. - `throw = true` if true, throw an error when generating a function for `ts` that reference variables that do not exist. @@ -502,8 +502,8 @@ For example, a function `g(op, unknowns, p..., inputs, t)` will be the in-place an array of inputs `inputs` is given, and `param_only` is false for a time-dependent system. """ function build_explicit_observed_function(sys, ts; - inputs = nothing, - disturbance_inputs = nothing, + inputs = Any[], + disturbance_inputs = Any[], disturbance_argument = false, expression = false, eval_expression = false, @@ -576,13 +576,13 @@ function build_explicit_observed_function(sys, ts; else (unknowns(sys),) end - if inputs === nothing + if isempty(inputs) inputs = () else ps = setdiff(ps, inputs) # Inputs have been converted to parameters, remove those from the parameter list inputs = (inputs,) end - if disturbance_inputs !== nothing + if !isempty(disturbance_inputs) # Disturbance inputs may or may not be included as inputs, depending on disturbance_argument ps = setdiff(ps, disturbance_inputs) end diff --git a/src/systems/systems.jl b/src/systems/systems.jl index ac96ad9c2a..3e938578d6 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -29,8 +29,8 @@ topological sort of the observed equations in `sys`. function mtkbuild( sys::AbstractSystem; additional_passes = [], simplify = false, split = true, allow_symbolic = false, allow_parameter = true, conservative = false, fully_determined = true, - inputs = nothing, outputs = nothing, - disturbance_inputs = nothing, + inputs = Any[], outputs = Any[], + disturbance_inputs = Any[], kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) newsys′ = __structural_simplification(sys; simplify, @@ -74,8 +74,8 @@ function __structural_simplification(sys::SDESystem, args...; kwargs...) end function __structural_simplification(sys::AbstractSystem; simplify = false, - inputs = nothing, outputs = nothing, - disturbance_inputs = nothing, + inputs = Any[], outputs = Any[], + disturbance_inputs = Any[], kwargs...) sys = expand_connections(sys) state = TearingState(sys; sort_eqs) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index 03ced79c73..0c929c4bb3 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -659,8 +659,8 @@ end function structural_simplification!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = true, - inputs = nothing, outputs = nothing, - disturbance_inputs = nothing, + inputs = Any[], outputs = Any[], + disturbance_inputs = Any[], kwargs...) if state.sys isa ODESystem @@ -672,7 +672,7 @@ function structural_simplification!(state::TearingState; simplify = false, cont_inputs = [inputs; clocked_inputs[continuous_id]] sys = _structural_simplification!(tss[continuous_id]; simplify, check_consistency, fully_determined, - cont_inputs, outputs, disturbance_inputs, + inputs = cont_inputs, outputs, disturbance_inputs, kwargs...) if length(tss) > 1 if continuous_id > 0 @@ -690,7 +690,7 @@ function structural_simplification!(state::TearingState; simplify = false, end disc_inputs = [inputs; clocked_inputs[i]] ss, = _structural_simplification!(state; simplify, check_consistency, - disc_inputs, outputs, disturbance_inputs, + inputs = disc_inputs, outputs, disturbance_inputs, fully_determined, kwargs...) append!(appended_parameters, inputs[i], unknowns(ss)) discrete_subsystems[i] = ss @@ -717,8 +717,8 @@ end function _structural_simplification!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = false, dummy_derivative = true, - inputs = nothing, outputs = nothing, - disturbance_inputs = nothing, + inputs = Any[], outputs = Any[], + disturbance_inputs = Any[], kwargs...) if fully_determined isa Bool check_consistency &= fully_determined diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index 45574ec8c4..c90b324db4 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -25,14 +25,14 @@ lsys3 = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) @test lsys.C[] == lsys2.C[] == lsys3.C[] == 1 @test lsys.D[] == lsys2.D[] == lsys3.D[] == 0 -lsys, ssys = linearize(sys, [r], [r]) +lsys = linearize(sys, [r], [r]) @test lsys.A[] == -2 @test lsys.B[] == 1 @test lsys.C[] == 0 @test lsys.D[] == 1 -lsys, ssys = linearize(sys, r, r) # Test allow scalars +lsys = linearize(sys, r, r) # Test allow scalars @test lsys.A[] == -2 @test lsys.B[] == 1 @@ -89,11 +89,11 @@ connections = [f.y ~ c.r # filtered reference to controller reference @named cl = ODESystem(connections, t, systems = [f, c, p]) cl = mtkbuild(cl, inputs = [f.u], outputs = [p.x]) -lsys0, ssys = linearize(cl) +lsys0 = linearize(cl, [f.u], [p.x]) desired_order = [f.x, p.x] -lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(ssys), desired_order) -lsys1, ssys = linearize(cl; autodiff = AutoFiniteDiff()) -lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(ssys), desired_order) +lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(cl), desired_order) +lsys1 = linearize(cl, [f.u], [p.x]; autodiff = AutoFiniteDiff()) +lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(cl), desired_order) @test lsys.A == lsys2.A == [-2 0; 1 -2] @test lsys.B == lsys2.B == reshape([1, 0], 2, 1) @@ -101,7 +101,7 @@ lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(ssys), desired_order) @test lsys.D[] == lsys2.D[] == 0 ## Symbolic linearization -lsyss, _ = ModelingToolkit.linearize_symbolic(cl, [f.u], [p.x]) +lsyss = ModelingToolkit.linearize_symbolic(cl, [f.u], [p.x]) @test ModelingToolkit.fixpoint_sub(lsyss.A, ModelingToolkit.defaults(cl)) == lsys.A @test ModelingToolkit.fixpoint_sub(lsyss.B, ModelingToolkit.defaults(cl)) == lsys.B @@ -116,11 +116,12 @@ Nd = 10 @named pid = LimPID(; k, Ti, Td, Nd) @unpack reference, measurement, ctr_output = pid -lsys0, ssys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]; +pid = mtkbuild(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) +lsys0 = linearize(pid, [reference.u, measurement.u], [ctr_output.u]; op = Dict(reference.u => 0.0, measurement.u => 0.0)) @unpack int, der = pid desired_order = [int.x, der.x] -lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(ssys), desired_order) +lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(pid), desired_order) @test lsys.A == [0 0; 0 -10] @test lsys.B == [2 -2; 10 -10] @@ -150,12 +151,12 @@ lsys = ModelingToolkit.reorder_unknowns(lsys, desired_order, reverse(desired_ord ## Test that there is a warning when input is misspecified if VERSION >= v"1.8" - @test_throws "Some specified inputs were not found" linearize(pid, + @test_throws "Some parameters are missing from the variable map." linearize(pid, [ pid.reference.u, pid.measurement.u ], [ctr_output.u]) - @test_throws "Some specified outputs were not found" linearize(pid, + @test_throws "Some parameters are missing from the variable map." linearize(pid, [ reference.u, measurement.u @@ -186,15 +187,16 @@ function saturation(; y_max, y_min = y_max > 0 ? -y_max : -Inf, name) ODESystem(eqs, t, name = name) end @named sat = saturation(; y_max = 1) +sat = mtkbuild(sat, inputs = [u], outputs = [y]) # inside the linear region, the function is identity @unpack u, y = sat -lsys, ssys = linearize(sat, [u], [y]) +lsys = linearize(sat, [u], [y]) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @test lsys.D[] == 1 -@test_skip lsyss, _ = ModelingToolkit.linearize_symbolic(sat, [u], [y]) # Code gen replaces ifelse with if statements causing symbolic evaluation to fail +@test_skip lsyss = ModelingToolkit.linearize_symbolic(sat, [u], [y]) # Code gen replaces ifelse with if statements causing symbolic evaluation to fail # @test substitute(lsyss.A, ModelingToolkit.defaults(sat)) == lsys.A # @test substitute(lsyss.B, ModelingToolkit.defaults(sat)) == lsys.B # @test substitute(lsyss.C, ModelingToolkit.defaults(sat)) == lsys.C @@ -267,9 +269,9 @@ closed_loop = ODESystem(connections, t, systems = [model, pid, filt, sensor, r, filt.x => 0.0, filt.xd => 0.0 ]) -closed_loop = mtkbuild(closed_loop, inputs = :r, outputs = :y) +closed_loop = mtkbuild(closed_loop) -@test_nowarn linearize(closed_loop; warn_empty_op = false) +@test_nowarn linearize(closed_loop, :r, :y; warn_empty_op = false) # https://discourse.julialang.org/t/mtk-change-in-linearize/115760/3 @mtkmodel Tank_noi begin From 7fb4e5aeda0dfb773ad3ffe93e78ec1f620d98bc Mon Sep 17 00:00:00 2001 From: vyudu Date: Tue, 22 Apr 2025 00:15:19 -0400 Subject: [PATCH 05/18] fix: simplify if not simplified --- src/linearization.jl | 2 +- test/downstream/linearize.jl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/linearization.jl b/src/linearization.jl index cbc538a881..db3939d7b2 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -46,7 +46,7 @@ function linearization_function(sys::AbstractSystem, inputs = unbound_inputs(sys warn_empty_op = true, kwargs...) if !iscomplete(sys) - error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the linearization.") + sys = mtkbuild(sys; inputs, outputs) end op = Dict(op) if isempty(op) && warn_empty_op diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index c90b324db4..738cae70fe 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -269,7 +269,6 @@ closed_loop = ODESystem(connections, t, systems = [model, pid, filt, sensor, r, filt.x => 0.0, filt.xd => 0.0 ]) -closed_loop = mtkbuild(closed_loop) @test_nowarn linearize(closed_loop, :r, :y; warn_empty_op = false) From d45a4b7276bfaa93427f112e24bcacf348976cc3 Mon Sep 17 00:00:00 2001 From: vyudu Date: Tue, 22 Apr 2025 00:28:54 -0400 Subject: [PATCH 06/18] revert rename --- docs/src/basics/AbstractSystem.md | 2 +- docs/src/basics/Composition.md | 10 ++-- docs/src/basics/Debugging.md | 2 +- docs/src/basics/Events.md | 4 +- docs/src/basics/FAQ.md | 6 +- docs/src/basics/InputOutput.md | 4 ++ docs/src/basics/Linearization.md | 2 +- docs/src/basics/MTKLanguage.md | 6 +- docs/src/basics/Precompilation.md | 2 +- docs/src/basics/Validation.md | 2 +- docs/src/comparison.md | 4 +- docs/src/examples/higher_order.md | 4 +- .../modelingtoolkitize_index_reduction.md | 4 +- docs/src/examples/spring_mass.md | 8 +-- docs/src/examples/tearing_parallelism.md | 6 +- docs/src/internals.md | 2 +- docs/src/systems/DiscreteSystem.md | 2 +- docs/src/systems/ImplicitDiscreteSystem.md | 2 +- docs/src/systems/JumpSystem.md | 2 +- docs/src/systems/NonlinearSystem.md | 2 +- docs/src/systems/ODESystem.md | 2 +- docs/src/systems/SDESystem.md | 2 +- docs/src/tutorials/acausal_components.md | 2 +- docs/src/tutorials/attractors.md | 2 +- .../tutorials/change_independent_variable.md | 8 +-- docs/src/tutorials/domain_connections.md | 8 +-- docs/src/tutorials/fmi.md | 6 +- docs/src/tutorials/initialization.md | 6 +- .../tutorials/programmatically_generating.md | 2 +- ext/MTKBifurcationKitExt.jl | 4 +- ext/MTKFMIExt.jl | 2 +- src/ModelingToolkit.jl | 4 +- src/inputoutput.jl | 2 +- src/linearization.jl | 23 ++++---- .../StructuralTransformations.jl | 2 +- src/structural_transformation/pantelides.jl | 2 +- .../symbolics_tearing.jl | 2 +- src/systems/abstractsystem.jl | 16 ++--- src/systems/diffeqs/abstractodesystem.jl | 34 +++++------ src/systems/diffeqs/basic_transformations.jl | 4 +- src/systems/diffeqs/odesystem.jl | 4 +- src/systems/diffeqs/sdesystem.jl | 10 ++-- .../discrete_system/discrete_system.jl | 4 +- .../implicit_discrete_system.jl | 4 +- src/systems/index_cache.jl | 4 +- src/systems/jumps/jumpsystem.jl | 8 +-- .../nonlinear/homotopy_continuation.jl | 4 +- src/systems/nonlinear/nonlinearsystem.jl | 24 ++++---- .../optimization/optimizationsystem.jl | 8 +-- src/systems/parameter_buffer.jl | 2 +- src/systems/systems.jl | 16 ++--- src/systems/systemstructure.jl | 10 ++-- src/utils.jl | 8 +-- test/accessor_functions.jl | 10 ++-- test/analysis_points.jl | 2 +- test/basic_transformations.jl | 20 +++---- test/clock.jl | 14 ++--- test/code_generation.jl | 2 +- test/components.jl | 26 ++++----- test/constants.jl | 6 +- test/dde.jl | 8 +-- test/debugging.jl | 4 +- test/discrete_system.jl | 4 +- test/domain_connectors.jl | 2 +- test/downstream/analysis_points.jl | 22 +++---- test/downstream/inversemodel.jl | 2 +- test/downstream/linearize.jl | 20 +++---- test/downstream/test_disturbance_model.jl | 10 ++-- test/dq_units.jl | 8 +-- test/error_handling.jl | 4 +- test/extensions/ad.jl | 4 +- test/extensions/bifurcationkit.jl | 4 +- test/funcaffect.jl | 8 +-- test/guess_propagation.jl | 8 +-- test/hierarchical_initialization_eqs.jl | 2 +- test/if_lifting.jl | 6 +- test/initializationsystem.jl | 26 ++++----- test/input_output_handling.jl | 18 +++--- test/jumpsystem.jl | 2 +- test/modelingtoolkitize.jl | 2 +- test/mtkparameters.jl | 6 +- test/nonlinearsystem.jl | 20 +++---- test/odesystem.jl | 58 +++++++++---------- test/optimizationsystem.jl | 2 +- test/parameter_dependencies.jl | 4 +- test/reduction.jl | 28 ++++----- test/scc_nonlinear_problem.jl | 4 +- test/sciml_problem_inputs.jl | 2 +- test/sdesystem.jl | 14 ++--- test/split_parameters.jl | 4 +- test/state_selection.jl | 6 +- test/static_arrays.jl | 2 +- test/stream_connectors.jl | 12 ++-- .../index_reduction.jl | 4 +- test/structural_transformation/tearing.jl | 6 +- test/structural_transformation/utils.jl | 10 ++-- test/substitute_component.jl | 4 +- test/symbolic_events.jl | 48 +++++++-------- test/symbolic_indexing_interface.jl | 2 +- test/units.jl | 8 +-- test/variable_scope.jl | 2 +- 101 files changed, 400 insertions(+), 405 deletions(-) diff --git a/docs/src/basics/AbstractSystem.md b/docs/src/basics/AbstractSystem.md index 276fcb44f0..d1707f822f 100644 --- a/docs/src/basics/AbstractSystem.md +++ b/docs/src/basics/AbstractSystem.md @@ -152,7 +152,7 @@ a lower level in the system. ## Namespacing By default, unsimplified systems will namespace variables accessed via `getproperty`. -Systems created via `@mtkbuild`, or ones passed through `mtkbuild` or +Systems created via `@mtkbuild`, or ones passed through `structural_simplify` or `complete` will not perform this namespacing. However, all of these processes modify the system in a variety of ways. To toggle namespacing without transforming any other property of the system, use `toggle_namespacing`. diff --git a/docs/src/basics/Composition.md b/docs/src/basics/Composition.md index ba5fe48137..d3de71d696 100644 --- a/docs/src/basics/Composition.md +++ b/docs/src/basics/Composition.md @@ -42,7 +42,7 @@ equations(connected) # Differential(t)(decay1₊x(t)) ~ decay1₊f(t) - (decay1₊a*(decay1₊x(t))) # Differential(t)(decay2₊x(t)) ~ decay2₊f(t) - (decay2₊a*(decay2₊x(t))) -simplified_sys = mtkbuild(connected) +simplified_sys = structural_simplify(connected) equations(simplified_sys) ``` @@ -84,7 +84,7 @@ example, let's say there is a variable `x` in `unknowns` and a variable `x` in `subsys`. We can declare that these two variables are the same by specifying their equality: `x ~ subsys.x` in the `eqs` for `sys`. This algebraic relationship can then be simplified by transformations -like `mtkbuild` which will be described later. +like `structural_simplify` which will be described later. ### Numerics with Composed Models @@ -169,7 +169,7 @@ parameters(level3) In many cases, the nicest way to build a model may leave a lot of unnecessary variables. Thus one may want to remove these equations -before numerically solving. The `mtkbuild` function removes +before numerically solving. The `structural_simplify` function removes these trivial equality relationships and trivial singularity equations, i.e. equations which result in `0~0` expressions, in over-specified systems. @@ -227,7 +227,7 @@ values. The user of this model can then solve this model simply by specifying the values at the highest level: ```@example compose -sireqn_simple = mtkbuild(sir) +sireqn_simple = structural_simplify(sir) equations(sireqn_simple) ``` @@ -251,7 +251,7 @@ sol[reqn.R] ## Tearing Problem Construction Some system types (specifically `NonlinearSystem`) can be further -reduced if `mtkbuild` has already been applied to them. This is done +reduced if `structural_simplify` has already been applied to them. This is done by using the alternative problem constructors (`BlockNonlinearProblem`). In these cases, the constructor uses the knowledge of the strongly connected components calculated during the process of simplification diff --git a/docs/src/basics/Debugging.md b/docs/src/basics/Debugging.md index 45384ecf9c..6e2d471461 100644 --- a/docs/src/basics/Debugging.md +++ b/docs/src/basics/Debugging.md @@ -13,7 +13,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = [D(u1) ~ -√(u1), D(u2) ~ -√(u2), D(u3) ~ -√(u3)] defaults = [u1 => 1.0, u2 => 2.0, u3 => 3.0] @named sys = ODESystem(eqs, t; defaults) -sys = mtkbuild(sys) +sys = structural_simplify(sys) ``` This problem causes the ODE solver to crash: diff --git a/docs/src/basics/Events.md b/docs/src/basics/Events.md index 125588540b..3a76f478f1 100644 --- a/docs/src/basics/Events.md +++ b/docs/src/basics/Events.md @@ -472,7 +472,7 @@ to the system. ```@example events @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_disable, furnace_enable]) -ss = mtkbuild(sys) +ss = structural_simplify(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 10.0)) sol = solve(prob, Tsit5()) plot(sol) @@ -585,7 +585,7 @@ We can now simulate the encoder. ```@example events @named sys = ODESystem( eqs, t, [theta, omega], params; continuous_events = [qAevt, qBevt]) -ss = mtkbuild(sys) +ss = structural_simplify(sys) prob = ODEProblem(ss, [theta => 0.0], (0.0, pi)) sol = solve(prob, Tsit5(); dtmax = 0.01) sol.ps[cnt] diff --git a/docs/src/basics/FAQ.md b/docs/src/basics/FAQ.md index 52152b761b..10671299c6 100644 --- a/docs/src/basics/FAQ.md +++ b/docs/src/basics/FAQ.md @@ -28,7 +28,7 @@ are similarly undocumented. Following is the list of behaviors that should be re - `setindex!(::MTKParameters, value, ::ParameterIndex)` can be used to set the value of a parameter with the given index. - `parameter_values(sys, sym)` will return a `ParameterIndex` object if `sys` has been - `complete`d (through `mtkbuild`, `complete` or `@mtkbuild`). + `complete`d (through `structural_simplify`, `complete` or `@mtkbuild`). - `copy(::MTKParameters)` is defined and duplicates the parameter object, including the memory used by the underlying buffers. @@ -194,7 +194,7 @@ p, replace, alias = SciMLStructures.canonicalize(Tunable(), prob.p) # ERROR: ArgumentError: SymbolicUtils.BasicSymbolic{Real}[xˍt(t)] are missing from the variable map. -This error can come up after running `mtkbuild` on a system that generates dummy derivatives (i.e. variables with `ˍt`). For example, here even though all the variables are defined with initial values, the `ODEProblem` generation will throw an error that defaults are missing from the variable map. +This error can come up after running `structural_simplify` on a system that generates dummy derivatives (i.e. variables with `ˍt`). For example, here even though all the variables are defined with initial values, the `ODEProblem` generation will throw an error that defaults are missing from the variable map. ```julia using ModelingToolkit @@ -206,7 +206,7 @@ eqs = [x1 + x2 + 1 ~ 0 x1 + D(x3) + x4 + 3 ~ 0 2 * D(D(x1)) + D(D(x2)) + D(D(x3)) + D(x4) + 4 ~ 0] @named sys = ODESystem(eqs, t) -sys = mtkbuild(sys) +sys = structural_simplify(sys) prob = ODEProblem(sys, [], (0, 1)) ``` diff --git a/docs/src/basics/InputOutput.md b/docs/src/basics/InputOutput.md index d6108d7cc4..4dc5a3d50f 100644 --- a/docs/src/basics/InputOutput.md +++ b/docs/src/basics/InputOutput.md @@ -28,6 +28,10 @@ ModelingToolkit can generate the dynamics of a system, the function ``M\dot x = This function takes a vector of variables that are to be considered inputs, i.e., part of the vector ``u``. Alongside returning the function ``f``, [`ModelingToolkit.generate_control_function`](@ref) also returns the chosen state realization of the system after simplification. This vector specifies the order of the state variables ``x``, while the user-specified vector `u` specifies the order of the input variables ``u``. +!!! note "Un-simplified system" + + This function expects `sys` to be un-simplified, i.e., `structural_simplify` or `@mtkbuild` should not be called on the system before passing it into this function. `generate_control_function` calls a special version of `structural_simplify` internally. + ### Example: The following example implements a simple first-order system with an input `u` and state `x`. The function `f` is generated using `generate_control_function`, and the function `f` is then tested with random input and state values. diff --git a/docs/src/basics/Linearization.md b/docs/src/basics/Linearization.md index a95f2b0104..78b6d5925d 100644 --- a/docs/src/basics/Linearization.md +++ b/docs/src/basics/Linearization.md @@ -75,7 +75,7 @@ eqs = [D(x) ~ v y.u ~ x] @named duffing = ODESystem(eqs, t, systems = [y, u], defaults = [u.u => 0]) -duffing = mtkbuild(duffing, inputs = [u.u], outputs = [y.u]) +duffing = structural_simplify(duffing, inputs = [u.u], outputs = [y.u]) # pass a constant value for `x`, since it is the variable we will change in operating points linfun = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); diff --git a/docs/src/basics/MTKLanguage.md b/docs/src/basics/MTKLanguage.md index db5ce3b723..e91f2bcb67 100644 --- a/docs/src/basics/MTKLanguage.md +++ b/docs/src/basics/MTKLanguage.md @@ -535,10 +535,10 @@ This is equivalent to: ```julia @named model = CustomModel() -sys = mtkbuild(model) +sys = structural_simplify(model) ``` -Pass keyword arguments to `mtkbuild` using the following syntax: +Pass keyword arguments to `structural_simplify` using the following syntax: ```julia @mtkbuild sys=CustomModel() fully_determined=false @@ -548,5 +548,5 @@ This is equivalent to: ```julia @named model = CustomModel() -sys = mtkbuild(model; fully_determined = false) +sys = structural_simplify(model; fully_determined = false) ``` diff --git a/docs/src/basics/Precompilation.md b/docs/src/basics/Precompilation.md index 88a425710a..97111f0d6b 100644 --- a/docs/src/basics/Precompilation.md +++ b/docs/src/basics/Precompilation.md @@ -22,7 +22,7 @@ using ModelingToolkit @variables x(ModelingToolkit.t_nounits) @named sys = ODESystem([ModelingToolkit.D_nounits(x) ~ -x + 1], ModelingToolkit.t_nounits) -prob = ODEProblem(mtkbuild(sys), [x => 30.0], (0, 100), [], +prob = ODEProblem(structural_simplify(sys), [x => 30.0], (0, 100), [], eval_expression = true, eval_module = @__MODULE__) end diff --git a/docs/src/basics/Validation.md b/docs/src/basics/Validation.md index 39a51ccf68..79c5d0d214 100644 --- a/docs/src/basics/Validation.md +++ b/docs/src/basics/Validation.md @@ -112,7 +112,7 @@ ps = @parameters s=-1 [unit = u"cm"] c=c [unit = u"cm"] eqs = [D(a) ~ dummycomplex(c, s);] sys = ODESystem( eqs, t, [sts...;], [ps...;], name = :sys, checks = ~ModelingToolkit.CheckUnits) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) ``` ## `DynamicQuantities` Literals diff --git a/docs/src/comparison.md b/docs/src/comparison.md index 0bf88b72c3..52d5ab2f70 100644 --- a/docs/src/comparison.md +++ b/docs/src/comparison.md @@ -12,7 +12,7 @@ - All current Modelica compiler implementations are fixed and not extendable by the users from the Modelica language itself. For example, the Dymola compiler [shares its symbolic processing pipeline](https://www.claytex.com/tech-blog/model-translation-and-symbolic-manipulation/), - which is roughly equivalent to the `dae_index_lowering` and `mtkbuild` + which is roughly equivalent to the `dae_index_lowering` and `structural_simplify` of ModelingToolkit.jl. ModelingToolkit.jl is an open and hackable transformation system which allows users to add new non-standard transformations and control the order of application. @@ -90,7 +90,7 @@ [Dymola symbolic processing pipeline](https://www.claytex.com/tech-blog/model-translation-and-symbolic-manipulation/) with some improvements. ModelingToolkit.jl has an open transformation pipeline that allows for users to extend and reorder transformation passes, where - `mtkbuild` is an adaptation of the Modia.jl-improved alias elimination + `structural_simplify` is an adaptation of the Modia.jl-improved alias elimination and tearing algorithms. - Both Modia and ModelingToolkit generate `DAEProblem` and `ODEProblem` forms for solving with [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/). diff --git a/docs/src/examples/higher_order.md b/docs/src/examples/higher_order.md index 6bdffb2ace..fac707525f 100644 --- a/docs/src/examples/higher_order.md +++ b/docs/src/examples/higher_order.md @@ -4,7 +4,7 @@ ModelingToolkit has a system for transformations of mathematical systems. These transformations allow for symbolically changing the representation of the model to problems that are easier to numerically solve. One simple to demonstrate transformation, is -`mtkbuild`, which does a lot of tricks, one being the +`structural_simplify`, which does a lot of tricks, one being the transformation that turns an Nth order ODE into N coupled 1st order ODEs. @@ -43,7 +43,7 @@ and this syntax extends to `N`-th order. Also, we can use `*` or `∘` to compos `Differential`s, like `Differential(t) * Differential(x)`. Now let's transform this into the `ODESystem` of first order components. -We do this by calling `mtkbuild`: +We do this by calling `structural_simplify`: Now we can directly numerically solve the lowered system. Note that, following the original problem, the solution requires knowing the diff --git a/docs/src/examples/modelingtoolkitize_index_reduction.md b/docs/src/examples/modelingtoolkitize_index_reduction.md index 40204c3a5f..b19ea46701 100644 --- a/docs/src/examples/modelingtoolkitize_index_reduction.md +++ b/docs/src/examples/modelingtoolkitize_index_reduction.md @@ -29,7 +29,7 @@ p = [9.8, 1] tspan = (0, 10.0) pendulum_prob = ODEProblem(pendulum_fun!, u0, tspan, p) traced_sys = modelingtoolkitize(pendulum_prob) -pendulum_sys = mtkbuild(dae_index_lowering(traced_sys)) +pendulum_sys = structural_simplify(dae_index_lowering(traced_sys)) prob = ODEProblem(pendulum_sys, [], tspan) sol = solve(prob, Rodas5P(), abstol = 1e-8, reltol = 1e-8) plot(sol, idxs = unknowns(traced_sys)) @@ -157,7 +157,7 @@ numerical solver. Let's try that out: ```@example indexred traced_sys = modelingtoolkitize(pendulum_prob) -pendulum_sys = mtkbuild(dae_index_lowering(traced_sys)) +pendulum_sys = structural_simplify(dae_index_lowering(traced_sys)) prob = ODEProblem(pendulum_sys, Pair[], tspan) sol = solve(prob, Rodas5P()) diff --git a/docs/src/examples/spring_mass.md b/docs/src/examples/spring_mass.md index e9c6b4f908..355e5c20b2 100644 --- a/docs/src/examples/spring_mass.md +++ b/docs/src/examples/spring_mass.md @@ -45,7 +45,7 @@ eqs = [connect_spring(spring, mass.pos, center) @named _model = ODESystem(eqs, t, [spring.x; spring.dir; mass.pos], []) @named model = compose(_model, mass, spring) -sys = mtkbuild(model) +sys = structural_simplify(model) prob = ODEProblem(sys, [], (0.0, 3.0)) sol = solve(prob, Rosenbrock23()) @@ -153,10 +153,10 @@ parameters(model) ### Simplifying and solving this system -This system can be solved directly as a DAE using [one of the DAE solvers from DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/solvers/dae_solve/). However, we can symbolically simplify the system first beforehand. Running `mtkbuild` eliminates unnecessary variables from the model to give the leanest numerical representation of the system. +This system can be solved directly as a DAE using [one of the DAE solvers from DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/solvers/dae_solve/). However, we can symbolically simplify the system first beforehand. Running `structural_simplify` eliminates unnecessary variables from the model to give the leanest numerical representation of the system. ```@example component -sys = mtkbuild(model) +sys = structural_simplify(model) equations(sys) ``` @@ -177,7 +177,7 @@ sol = solve(prob, Rosenbrock23()) plot(sol) ``` -What if we want the timeseries of a different variable? That information is not lost! Instead, `mtkbuild` simply changes unknown variables into `observed` variables. +What if we want the timeseries of a different variable? That information is not lost! Instead, `structural_simplify` simply changes unknown variables into `observed` variables. ```@example component observed(sys) diff --git a/docs/src/examples/tearing_parallelism.md b/docs/src/examples/tearing_parallelism.md index 688b47917f..9540e610bd 100644 --- a/docs/src/examples/tearing_parallelism.md +++ b/docs/src/examples/tearing_parallelism.md @@ -1,7 +1,7 @@ # Exposing More Parallelism By Tearing Algebraic Equations in ODESystems Sometimes it can be very non-trivial to parallelize a system. In this tutorial, -we will demonstrate how to make use of `mtkbuild` to expose more +we will demonstrate how to make use of `structural_simplify` to expose more parallelism in the solution process and parallelize the resulting simulation. ## The Component Library @@ -122,7 +122,7 @@ Now let's say we want to expose a bit more parallelism via running tearing. How do we do that? ```@example tearing -sys = mtkbuild(big_rc) +sys = structural_simplify(big_rc) ``` Done, that's it. There's no more to it. @@ -175,5 +175,5 @@ so this is better than trying to do it by hand. After performing this, you can construct the `ODEProblem` and set `parallel_form` to use the exposed parallelism in multithreaded function -constructions, but this showcases why `mtkbuild` is so important +constructions, but this showcases why `structural_simplify` is so important to that process. diff --git a/docs/src/internals.md b/docs/src/internals.md index 2db7fd8bc6..00b29f1a64 100644 --- a/docs/src/internals.md +++ b/docs/src/internals.md @@ -18,7 +18,7 @@ and are then used to generate the `observed` equation found in the variable when necessary. In this sense, there is an equivalence between observables and the variable elimination system. -The procedure for variable elimination inside [`mtkbuild`](@ref) is +The procedure for variable elimination inside [`structural_simplify`](@ref) is 1. [`ModelingToolkit.initialize_system_structure`](@ref). 2. [`ModelingToolkit.alias_elimination`](@ref). This step moves equations into `observed(sys)`. diff --git a/docs/src/systems/DiscreteSystem.md b/docs/src/systems/DiscreteSystem.md index e787b8f004..f8a71043ab 100644 --- a/docs/src/systems/DiscreteSystem.md +++ b/docs/src/systems/DiscreteSystem.md @@ -17,7 +17,7 @@ DiscreteSystem ## Transformations ```@docs; canonical=false -mtkbuild +structural_simplify ``` ## Problem Constructors diff --git a/docs/src/systems/ImplicitDiscreteSystem.md b/docs/src/systems/ImplicitDiscreteSystem.md index 13910f3995..d69f88f106 100644 --- a/docs/src/systems/ImplicitDiscreteSystem.md +++ b/docs/src/systems/ImplicitDiscreteSystem.md @@ -17,7 +17,7 @@ ImplicitDiscreteSystem ## Transformations ```@docs; canonical=false -mtkbuild +structural_simplify ``` ## Problem Constructors diff --git a/docs/src/systems/JumpSystem.md b/docs/src/systems/JumpSystem.md index 2db9246f70..5bd0d50602 100644 --- a/docs/src/systems/JumpSystem.md +++ b/docs/src/systems/JumpSystem.md @@ -17,7 +17,7 @@ JumpSystem ## Transformations ```@docs; canonical=false -mtkbuild +structural_simplify ``` ## Analyses diff --git a/docs/src/systems/NonlinearSystem.md b/docs/src/systems/NonlinearSystem.md index 2a470f0820..06d587b1b9 100644 --- a/docs/src/systems/NonlinearSystem.md +++ b/docs/src/systems/NonlinearSystem.md @@ -16,7 +16,7 @@ NonlinearSystem ## Transformations ```@docs; canonical=false -mtkbuild +structural_simplify alias_elimination tearing ``` diff --git a/docs/src/systems/ODESystem.md b/docs/src/systems/ODESystem.md index ce6149edeb..24e2952fc5 100644 --- a/docs/src/systems/ODESystem.md +++ b/docs/src/systems/ODESystem.md @@ -27,7 +27,7 @@ ODESystem ## Transformations ```@docs -mtkbuild +structural_simplify ode_order_lowering dae_index_lowering change_independent_variable diff --git a/docs/src/systems/SDESystem.md b/docs/src/systems/SDESystem.md index 2f51528a51..5789d2d9cb 100644 --- a/docs/src/systems/SDESystem.md +++ b/docs/src/systems/SDESystem.md @@ -33,7 +33,7 @@ sde = SDESystem(ode, noiseeqs) ## Transformations ```@docs; canonical=false -mtkbuild +structural_simplify alias_elimination ``` diff --git a/docs/src/tutorials/acausal_components.md b/docs/src/tutorials/acausal_components.md index 4e0f14fc63..751b678dae 100644 --- a/docs/src/tutorials/acausal_components.md +++ b/docs/src/tutorials/acausal_components.md @@ -323,7 +323,7 @@ plot(sol) By default, this plots only the unknown variables that had to be solved for. However, what if we wanted to plot the timeseries of a different variable? Do not worry, that information was not thrown away! Instead, transformations -like `mtkbuild` simply change unknown variables into observables which are +like `structural_simplify` simply change unknown variables into observables which are defined by `observed` equations. ```@example acausal diff --git a/docs/src/tutorials/attractors.md b/docs/src/tutorials/attractors.md index 24649d307d..317384b01a 100644 --- a/docs/src/tutorials/attractors.md +++ b/docs/src/tutorials/attractors.md @@ -42,7 +42,7 @@ Because our dynamical system is super simple, we will directly make an `ODESyste ```@example Attractors @named modlorenz = ODESystem(eqs, t) -ssys = mtkbuild(modlorenz) +ssys = structural_simplify(modlorenz) # The timespan given to the problem is irrelevant for DynamicalSystems.jl prob = ODEProblem(ssys, [], (0.0, 1.0), []) ``` diff --git a/docs/src/tutorials/change_independent_variable.md b/docs/src/tutorials/change_independent_variable.md index 18b6f75bb3..d55639a669 100644 --- a/docs/src/tutorials/change_independent_variable.md +++ b/docs/src/tutorials/change_independent_variable.md @@ -25,7 +25,7 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = [D(D(y)) ~ -g, D(x) ~ v] initialization_eqs = [D(x) ~ D(y)] # 45° initial angle M1 = ODESystem(eqs, t; initialization_eqs, name = :M) -M1s = mtkbuild(M1) +M1s = structural_simplify(M1) @assert length(equations(M1s)) == 3 # hide M1s # hide ``` @@ -44,7 +44,7 @@ This transformation is well-defined for any non-zero horizontal velocity $v$, so ```@example changeivar M2 = change_independent_variable(M1, x) -M2s = mtkbuild(M2; allow_symbolic = true) +M2s = structural_simplify(M2; allow_symbolic = true) # a sanity test on the 10 x/y variables that are accessible to the user # hide @assert allequal([x, M1s.x]) # hide @assert allequal([M2.x, M2s.x]) # hide @@ -97,7 +97,7 @@ eqs = [Ω ~ r.Ω + m.Ω + Λ.Ω, D(a) ~ √(Ω) * a^2] initialization_eqs = [Λ.Ω + r.Ω + m.Ω ~ 1] M1 = ODESystem(eqs, t, [Ω, a], []; initialization_eqs, name = :M) M1 = compose(M1, r, m, Λ) -M1s = mtkbuild(M1) +M1s = structural_simplify(M1) ``` Of course, we can solve this ODE as it is: @@ -137,7 +137,7 @@ M3 = change_independent_variable(M2, b, [Da(b) ~ exp(-b), a ~ exp(b)]) We can now solve and plot the ODE in terms of $b$: ```@example changeivar -M3s = mtkbuild(M3; allow_symbolic = true) +M3s = structural_simplify(M3; allow_symbolic = true) prob = ODEProblem(M3s, [M3s.r.Ω => 5e-5, M3s.m.Ω => 0.3], (0, -15), []) sol = solve(prob, Tsit5()) @assert Symbol(sol.retcode) == :Success # surrounding text assumes the solution was successful # hide diff --git a/docs/src/tutorials/domain_connections.md b/docs/src/tutorials/domain_connections.md index ff124ce481..d6dc2d8781 100644 --- a/docs/src/tutorials/domain_connections.md +++ b/docs/src/tutorials/domain_connections.md @@ -115,10 +115,10 @@ end nothing #hide ``` -To see how the domain works, we can examine the set parameter values for each of the ports `src.port` and `vol.port`. First we assemble the system using `mtkbuild()` and then check the default value of `vol.port.ρ`, whichs points to the setter value `fluid₊ρ`. Likewise, `src.port.ρ`, will also point to the setter value `fluid₊ρ`. Therefore, there is now only 1 defined density value `fluid₊ρ` which sets the density for the connected network. +To see how the domain works, we can examine the set parameter values for each of the ports `src.port` and `vol.port`. First we assemble the system using `structural_simplify()` and then check the default value of `vol.port.ρ`, whichs points to the setter value `fluid₊ρ`. Likewise, `src.port.ρ`, will also point to the setter value `fluid₊ρ`. Therefore, there is now only 1 defined density value `fluid₊ρ` which sets the density for the connected network. ```@repl domain -sys = mtkbuild(odesys) +sys = structural_simplify(odesys) ModelingToolkit.defaults(sys)[odesys.vol.port.ρ] ``` @@ -181,7 +181,7 @@ end nothing #hide ``` -After running `mtkbuild()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfere with the mathematical equations of the system, since no unknown variables are connected. +After running `structural_simplify()` on `actsys2`, the defaults will show that `act.port_a.ρ` points to `fluid_a₊ρ` and `act.port_b.ρ` points to `fluid_b₊ρ`. This is a special case, in most cases a hydraulic system will have only 1 fluid, however this simple system has 2 separate domain networks. Therefore, we can connect a single fluid to both networks. This does not interfere with the mathematical equations of the system, since no unknown variables are connected. ```@example domain @component function ActuatorSystem1(; name) @@ -252,7 +252,7 @@ end nothing #hide ``` -When `mtkbuild()` is applied to this system it can be seen that the defaults are missing for `res.port_b` and `vol.port`. +When `structural_simplify()` is applied to this system it can be seen that the defaults are missing for `res.port_b` and `vol.port`. ```@repl domain ModelingToolkit.defaults(ressys)[ressys.res.port_a.ρ] diff --git a/docs/src/tutorials/fmi.md b/docs/src/tutorials/fmi.md index 9015f91987..ef00477c78 100644 --- a/docs/src/tutorials/fmi.md +++ b/docs/src/tutorials/fmi.md @@ -76,7 +76,7 @@ initialization semantics. We can simulate this model like any other ModelingToolkit system. ```@repl fmi -sys = mtkbuild(model) +sys = structural_simplify(model) prob = ODEProblem(sys, [sys.mass__s => 0.5, sys.mass__v => 0.0], (0.0, 5.0)) sol = solve(prob, Tsit5()) ``` @@ -104,11 +104,11 @@ constant until the next time the callback triggers. The periodic interval must b `communication_step_size` keyword argument. A smaller step size typically leads to less error but is more computationally expensive. -This model alone does not have any differential variables, and calling `mtkbuild` will lead +This model alone does not have any differential variables, and calling `structural_simplify` will lead to an `ODESystem` with no unknowns. ```@example fmi -mtkbuild(inner) +structural_simplify(inner) ``` Simulating this model will cause the OrdinaryDiffEq integrator to immediately finish, and will not diff --git a/docs/src/tutorials/initialization.md b/docs/src/tutorials/initialization.md index 8712262cbc..ba733e0bfb 100644 --- a/docs/src/tutorials/initialization.md +++ b/docs/src/tutorials/initialization.md @@ -380,7 +380,7 @@ with observables, those observables are too treated as initial equations. We can resulting simplified system via the command: ```@example init -isys = mtkbuild(isys; fully_determined = false) +isys = structural_simplify(isys; fully_determined = false) ``` Note `fully_determined=false` allows for the simplification to occur when the number of equations @@ -392,7 +392,7 @@ isys = ModelingToolkit.generate_initializesystem( ``` ```@example init -isys = mtkbuild(isys; fully_determined = false) +isys = structural_simplify(isys; fully_determined = false) ``` ```@example init @@ -504,7 +504,7 @@ eqs = [D(x) ~ α * x - β * x * y z ~ x + y] @named sys = ODESystem(eqs, t) -simpsys = mtkbuild(sys) +simpsys = structural_simplify(sys) tspan = (0.0, 10.0) ``` diff --git a/docs/src/tutorials/programmatically_generating.md b/docs/src/tutorials/programmatically_generating.md index 6abba4dd3d..9fc1db1834 100644 --- a/docs/src/tutorials/programmatically_generating.md +++ b/docs/src/tutorials/programmatically_generating.md @@ -47,7 +47,7 @@ eqs = [D(x) ~ (h - x) / τ] # create an array of equations # Perform the standard transformations and mark the model complete # Note: Complete models cannot be subsystems of other models! -fol = mtkbuild(model) +fol = structural_simplify(model) prob = ODEProblem(fol, [], (0.0, 10.0), []) using OrdinaryDiffEq sol = solve(prob) diff --git a/ext/MTKBifurcationKitExt.jl b/ext/MTKBifurcationKitExt.jl index e0e9cbf8fe..0b9f104d9b 100644 --- a/ext/MTKBifurcationKitExt.jl +++ b/ext/MTKBifurcationKitExt.jl @@ -92,7 +92,7 @@ function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem, jac = true, kwargs...) if !ModelingToolkit.iscomplete(nsys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `BifurcationProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`") end @set! nsys.index_cache = nothing # force usage of a parameter vector instead of `MTKParameters` # Creates F and J functions. @@ -146,7 +146,7 @@ end # When input is a ODESystem. function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...) if !ModelingToolkit.iscomplete(osys) - error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating a `BifurcationProblem`") + error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`") end nsys = NonlinearSystem([0 ~ eq.rhs for eq in full_equations(osys)], unknowns(osys), diff --git a/ext/MTKFMIExt.jl b/ext/MTKFMIExt.jl index 4501bbcbaf..5cfe9a82ef 100644 --- a/ext/MTKFMIExt.jl +++ b/ext/MTKFMIExt.jl @@ -127,7 +127,7 @@ function MTK.FMIComponent(::Val{Ver}; fmu = nothing, tolerance = 1e-6, # no differential variables __mtk_internal_u = Float64[] elseif type == :ME - # to avoid running into `mtkbuild` warnings about array variables + # to avoid running into `structural_simplify` warnings about array variables # and some unfortunate circular dependency issues, ME FMUs use an array of # symbolics instead. This is also not worse off in performance # because the former approach would allocate anyway. diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index e247a1d43b..205c9dd477 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -226,7 +226,7 @@ PrecompileTools.@compile_workload begin using ModelingToolkit @variables x(ModelingToolkit.t_nounits) @named sys = ODESystem([ModelingToolkit.D_nounits(x) ~ -x], ModelingToolkit.t_nounits) - prob = ODEProblem(mtkbuild(sys), [x => 30.0], (0, 100), [], jac = true) + prob = ODEProblem(structural_simplify(sys), [x => 30.0], (0, 100), [], jac = true) @mtkmodel __testmod__ begin @constants begin c = 1.0 @@ -299,7 +299,7 @@ export Term, Sym export SymScope, LocalScope, ParentScope, GlobalScope export independent_variable, equations, controls, observed, full_equations export initialization_equations, guesses, defaults, parameter_dependencies, hierarchy -export mtkbuild, expand_connections, linearize, linearization_function, +export structural_simplify, expand_connections, linearize, linearization_function, LinearizationProblem export solve diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 89d27cb729..c03da22abf 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -201,7 +201,7 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu # Remove this when the ControlFunction gets merged. if !iscomplete(sys) - error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the control function.") + error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating the control function.") end isempty(inputs) && @warn("No unbound inputs were found in system.") if disturbance_inputs !== nothing diff --git a/src/linearization.jl b/src/linearization.jl index db3939d7b2..eb06d142f3 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -1,5 +1,5 @@ """ - lin_fun = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) + lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) Return a function that linearizes the system `sys`. The function [`linearize`](@ref) provides a higher-level and easier to use interface. @@ -15,7 +15,7 @@ y &= h(x, z, u) where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. To obtain a linear statespace representation, see [`linearize`](@ref). The input argument `variables` is a vector defining the operating point, corresponding to `unknowns(simplified_sys)` and `p` is a vector corresponding to the parameters of `simplified_sys`. Note: all variables in `inputs` have been converted to parameters in `simplified_sys`. -The `simplified_sys` has undergone [`mtkbuild`](@ref) and had any occurring input or output variables replaced with the variables provided in arguments `inputs` and `outputs`. The unknowns of this system also indicate the order of the unknowns that holds for the linearized matrices. +The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occurring input or output variables replaced with the variables provided in arguments `inputs` and `outputs`. The unknowns of this system also indicate the order of the unknowns that holds for the linearized matrices. # Arguments: @@ -29,8 +29,8 @@ The `simplified_sys` has undergone [`mtkbuild`](@ref) and had any occurring inpu See also [`linearize`](@ref) which provides a higher-level interface. """ -function linearization_function(sys::AbstractSystem, inputs = unbound_inputs(sys), - outputs = unbound_outputs(sys); +function linearization_function(sys::AbstractSystem, inputs, + outputs; initialize = true, initializealg = nothing, initialization_abstol = 1e-5, @@ -484,13 +484,10 @@ y &= h(x, z, u) ``` where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. """ -function linearize_symbolic(sys::AbstractSystem, inputs = unbound_inputs(sys), - outputs = unbound_outputs(sys); allow_input_derivatives = false, +function linearize_symbolic(sys::AbstractSystem, inputs, + outputs; allow_input_derivatives = false, eval_expression = false, eval_module = @__MODULE__, kwargs...) - if !iscomplete(sys) - error("A completed `ODESystem` is required. Call `complete` or `mtkbuild` on the system before creating the linearization.") - end diff_idxs, alge_idxs = eq_idxs(sys) sts = unknowns(sys) t = get_iv(sys) @@ -549,7 +546,7 @@ function linearize_symbolic(sys::AbstractSystem, inputs = unbound_inputs(sys), end end - (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u) + (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys end function markio!(state, orig_inputs, inputs, outputs; check = true) @@ -716,17 +713,17 @@ function linearize(sys, lin_fun::LinearizationFunction; t = 0.0, return solve(prob; allow_input_derivatives) end -function linearize(sys, inputs = unbound_inputs(sys), outputs = unbound_outputs(sys); op = Dict(), t = 0.0, +function linearize(sys, inputs, outputs; op = Dict(), t = 0.0, allow_input_derivatives = false, zero_dummy_der = false, kwargs...) - lin_fun = linearization_function(sys, + lin_fun, ssys = linearization_function(sys, inputs, outputs; zero_dummy_der, op, kwargs...) - linearize(sys, lin_fun; op, t, allow_input_derivatives) + linearize(ssys, lin_fun; op, t, allow_input_derivatives), ssys end """ diff --git a/src/structural_transformation/StructuralTransformations.jl b/src/structural_transformation/StructuralTransformations.jl index 0b8b2eddcb..4adc817ef8 100644 --- a/src/structural_transformation/StructuralTransformations.jl +++ b/src/structural_transformation/StructuralTransformations.jl @@ -35,7 +35,7 @@ import ModelingToolkit: var_derivative!, var_derivative_graph! using Graphs using ModelingToolkit: algeqs, EquationsView, SystemStructure, TransformationState, TearingState, - structural_simplification!, + structural_simplify!, isdiffvar, isdervar, isalgvar, isdiffeq, algeqs, is_only_discrete, dervars_range, diffvars_range, algvars_range, DiffGraph, complete!, diff --git a/src/structural_transformation/pantelides.jl b/src/structural_transformation/pantelides.jl index 335c7d52cd..585c4a29d1 100644 --- a/src/structural_transformation/pantelides.jl +++ b/src/structural_transformation/pantelides.jl @@ -210,7 +210,7 @@ end dae_index_lowering(sys::ODESystem; kwargs...) -> ODESystem Perform the Pantelides algorithm to transform a higher index DAE to an index 1 -DAE. `kwargs` are forwarded to [`pantelides!`](@ref). End users are encouraged to call [`mtkbuild`](@ref) +DAE. `kwargs` are forwarded to [`pantelides!`](@ref). End users are encouraged to call [`structural_simplify`](@ref) instead, which calls this function internally. """ function dae_index_lowering(sys::ODESystem; kwargs...) diff --git a/src/structural_transformation/symbolics_tearing.jl b/src/structural_transformation/symbolics_tearing.jl index 7b554f97d1..548c7da519 100644 --- a/src/structural_transformation/symbolics_tearing.jl +++ b/src/structural_transformation/symbolics_tearing.jl @@ -1018,7 +1018,7 @@ end tearing(sys; simplify=false) Tear the nonlinear equations in system. When `simplify=true`, we simplify the -new residual equations after tearing. End users are encouraged to call [`mtkbuild`](@ref) +new residual equations after tearing. End users are encouraged to call [`structural_simplify`](@ref) instead, which calls this function internally. """ function tearing(sys::AbstractSystem, state = TearingState(sys); mm = nothing, diff --git a/src/systems/abstractsystem.jl b/src/systems/abstractsystem.jl index 8559151747..025199c92b 100644 --- a/src/systems/abstractsystem.jl +++ b/src/systems/abstractsystem.jl @@ -157,7 +157,7 @@ may be subsetted using `dvs` and `ps`. All `kwargs` are passed to the internal [`build_function`](@ref) call. The returned function can be called as `f(u, p, t)` or `f(du, u, p, t)` for time-dependent systems and `f(u, p)` or `f(du, u, p)` for time-independent systems. If `split=true` (the default) was passed to [`complete`](@ref), -[`mtkbuild`](@ref) or [`@mtkbuild`](@ref), `p` is expected to be an `MTKParameters` +[`structural_simplify`](@ref) or [`@mtkbuild`](@ref), `p` is expected to be an `MTKParameters` object. """ function generate_custom_function(sys::AbstractSystem, exprs, dvs = unknowns(sys), @@ -165,7 +165,7 @@ function generate_custom_function(sys::AbstractSystem, exprs, dvs = unknowns(sys expression = Val{true}, eval_expression = false, eval_module = @__MODULE__, cachesyms::Tuple = (), kwargs...) if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system.") + error("A completed system is required. Call `complete` or `structural_simplify` on the system.") end p = (reorder_parameters(sys, unwrap.(ps))..., cachesyms...) isscalar = !(exprs isa AbstractArray) @@ -771,7 +771,7 @@ function complete( newparams = OrderedSet() iv = has_iv(sys) ? get_iv(sys) : nothing collect_scoped_vars!(newunknowns, newparams, sys, iv; depth = -1) - # don't update unknowns to not disturb `mtkbuild` order + # don't update unknowns to not disturb `structural_simplify` order # `GlobalScope`d unknowns will be picked up and added there @set! sys.ps = unique!(vcat(get_ps(sys), collect(newparams))) @@ -1196,7 +1196,7 @@ end Denotes that a variable belongs to the root system in the hierarchy, regardless of which equations of subsystems in the hierarchy it is involved in. Variables with this scope are never namespaced and only added to the unknowns/parameters of a system when calling -`complete` or `mtkbuild`. +`complete` or `structural_simplify`. """ struct GlobalScope <: SymScope end @@ -2416,7 +2416,7 @@ macro mtkbuild(exprs...) else kwargs = (Expr(:parameters, kwargs...),) end - call_expr = Expr(:call, mtkbuild, kwargs..., name) + call_expr = Expr(:call, structural_simplify, kwargs..., name) esc(quote $named_expr $name = $call_expr @@ -2455,7 +2455,7 @@ function debug_system( functions = Set(functions) # more efficient "in" lookup end if has_systems(sys) && !isempty(get_systems(sys)) - error("debug_system(sys) only works on systems with no sub-systems! Consider flattening it with flatten(sys) or mtkbuild(sys) first.") + error("debug_system(sys) only works on systems with no sub-systems! Consider flattening it with flatten(sys) or structural_simplify(sys) first.") end if has_eqs(sys) eqs = debug_sub.(equations(sys), Ref(functions); kw...) @@ -2552,10 +2552,10 @@ end function check_array_equations_unknowns(eqs, dvs) if any(eq -> eq isa Equation && Symbolics.isarraysymbolic(eq.lhs), eqs) - throw(ArgumentError("The system has array equations. Call `mtkbuild` to handle such equations or scalarize them manually.")) + throw(ArgumentError("The system has array equations. Call `structural_simplify` to handle such equations or scalarize them manually.")) end if any(x -> Symbolics.isarraysymbolic(x), dvs) - throw(ArgumentError("The system has array unknowns. Call `mtkbuild` to handle this or scalarize them manually.")) + throw(ArgumentError("The system has array unknowns. Call `structural_simplify` to handle this or scalarize them manually.")) end end diff --git a/src/systems/diffeqs/abstractodesystem.jl b/src/systems/diffeqs/abstractodesystem.jl index 96dbae0762..d9e8b05eeb 100644 --- a/src/systems/diffeqs/abstractodesystem.jl +++ b/src/systems/diffeqs/abstractodesystem.jl @@ -364,7 +364,7 @@ function DiffEqBase.ODEFunction{iip, specialize}(sys::AbstractODESystem, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEFunction`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunction`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, checkbounds = checkbounds, cse, @@ -469,7 +469,7 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys) cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEFunction`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEFunction`") end f_gen = generate_function(sys, dvs, ps; implicit_dae = true, expression = Val{true}, cse, @@ -529,7 +529,7 @@ function DiffEqBase.DDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys) cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `DDEFunction`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DDEFunction`") end f_gen = generate_function(sys, dvs, ps; isdde = true, expression = Val{true}, @@ -554,7 +554,7 @@ function DiffEqBase.SDDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `SDDEFunction`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `SDDEFunction`") end f_gen = generate_function(sys, dvs, ps; isdde = true, expression = Val{true}, @@ -598,7 +598,7 @@ function ODEFunctionExpr{iip, specialize}(sys::AbstractODESystem, dvs = unknowns observedfun_exp = nothing, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEFunctionExpr`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...) @@ -688,7 +688,7 @@ function DAEFunctionExpr{iip}(sys::AbstractODESystem, dvs = unknowns(sys), sparse = false, simplify = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `DAEFunctionExpr`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DAEFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, implicit_dae = true, kwargs...) @@ -784,7 +784,7 @@ function DiffEqBase.ODEProblem{iip, specialize}(sys::AbstractODESystem, u0map = eval_module = @__MODULE__, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`") end if !isnothing(get_constraintsystem(sys)) @@ -900,7 +900,7 @@ function SciMLBase.BVProblem{iip, specialize}(sys::AbstractODESystem, u0map = [] cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `BVProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `BVProblem`") end !isnothing(callback) && error("BVP solvers do not support callbacks.") @@ -1014,7 +1014,7 @@ function DiffEqBase.DAEProblem{iip}(sys::AbstractODESystem, du0map, u0map, tspan warn_initialize_determined = true, check_length = true, eval_expression = false, eval_module = @__MODULE__, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEProblem`.") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblem`.") end if !isempty(get_costs(sys)) && !allow_cost @@ -1066,7 +1066,7 @@ function DiffEqBase.DDEProblem{iip}(sys::AbstractODESystem, u0map = [], cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DDEProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DDEProblem`") end f, u0, p = process_SciMLProblem(DDEFunction{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1106,7 +1106,7 @@ function DiffEqBase.SDDEProblem{iip}(sys::AbstractODESystem, u0map = [], cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SDDEProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SDDEProblem`") end f, u0, p = process_SciMLProblem(SDDEFunction{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1167,7 +1167,7 @@ function ODEProblemExpr{iip}(sys::AbstractODESystem, u0map, tspan, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `ODEProblemExpr`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `ODEProblemExpr`") end f, u0, p = process_SciMLProblem( ODEFunctionExpr{iip}, sys, u0map, parammap; check_length, @@ -1214,7 +1214,7 @@ function DAEProblemExpr{iip}(sys::AbstractODESystem, du0map, u0map, tspan, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `DAEProblemExpr`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblemExpr`") end f, du0, u0, p = process_SciMLProblem(DAEFunctionExpr{iip}, sys, u0map, parammap; t = tspan !== nothing ? tspan[1] : tspan, @@ -1266,7 +1266,7 @@ function DiffEqBase.SteadyStateProblem{iip}(sys::AbstractODESystem, u0map, parammap = SciMLBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SteadyStateProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblem`") end f, u0, p = process_SciMLProblem(ODEFunction{iip}, sys, u0map, parammap; steady_state = true, @@ -1298,7 +1298,7 @@ function SteadyStateProblemExpr{iip}(sys::AbstractODESystem, u0map, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating a `SteadyStateProblemExpr`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblemExpr`") end f, u0, p = process_SciMLProblem(ODEFunctionExpr{iip}, sys, u0map, parammap; steady_state = true, @@ -1449,7 +1449,7 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem, algebraic_only = false, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed system is required. Call `complete` or `mtkbuild` on the system before creating an `ODEProblem`") + error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`") end if isempty(u0map) && get_initializesystem(sys) !== nothing isys = get_initializesystem(sys; initialization_eqs, check_units) @@ -1474,7 +1474,7 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem, end if simplify_system - isys = mtkbuild(isys; fully_determined) + isys = structural_simplify(isys; fully_determined) end ts = get_tearing_state(isys) diff --git a/src/systems/diffeqs/basic_transformations.jl b/src/systems/diffeqs/basic_transformations.jl index cf8c3a35f1..a08c83ffb6 100644 --- a/src/systems/diffeqs/basic_transformations.jl +++ b/src/systems/diffeqs/basic_transformations.jl @@ -74,7 +74,7 @@ Any extra equations `eqs` involving the new and old independent variables will b # Usage before structural simplification The variable change must take place before structural simplification. -In following calls to `mtkbuild`, consider passing `allow_symbolic = true` to avoid undesired constraint equations between between dummy variables. +In following calls to `structural_simplify`, consider passing `allow_symbolic = true` to avoid undesired constraint equations between between dummy variables. # Usage with non-autonomous systems @@ -99,7 +99,7 @@ julia> @named M = ODESystem([D(D(y)) ~ -9.81, D(D(x)) ~ 0.0], t); julia> M = change_independent_variable(M, x); -julia> M = mtkbuild(M; allow_symbolic = true); +julia> M = structural_simplify(M; allow_symbolic = true); julia> unknowns(M) 3-element Vector{SymbolicUtils.BasicSymbolic{Real}}: diff --git a/src/systems/diffeqs/odesystem.jl b/src/systems/diffeqs/odesystem.jl index 75ee49b7cd..1b07b034af 100644 --- a/src/systems/diffeqs/odesystem.jl +++ b/src/systems/diffeqs/odesystem.jl @@ -579,7 +579,7 @@ function build_explicit_observed_function(sys, ts; if isempty(inputs) inputs = () else - ps = setdiff(ps, inputs) # Inputs have been converted to parameters, remove those from the parameter list + ps = setdiff(ps, inputs) # Inputs have been converted to parameters by io_preprocessing, remove those from the parameter list inputs = (inputs,) end if !isempty(disturbance_inputs) @@ -662,7 +662,7 @@ end # We have a stand-alone function to convert a `NonlinearSystem` or `ODESystem` # to an `ODESystem` to connect systems, and we later can reply on -# `mtkbuild` to convert `ODESystem`s to `NonlinearSystem`s. +# `structural_simplify` to convert `ODESystem`s to `NonlinearSystem`s. """ $(TYPEDSIGNATURES) diff --git a/src/systems/diffeqs/sdesystem.jl b/src/systems/diffeqs/sdesystem.jl index 4ce6b9605c..c5299c28be 100644 --- a/src/systems/diffeqs/sdesystem.jl +++ b/src/systems/diffeqs/sdesystem.jl @@ -600,7 +600,7 @@ function DiffEqBase.SDEFunction{iip, specialize}(sys::SDESystem, dvs = unknowns( checkbounds = false, initialization_data = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEFunction`") + error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunction`") end dvs = scalarize.(dvs) @@ -720,7 +720,7 @@ function SDEFunctionExpr{iip}(sys::SDESystem, dvs = unknowns(sys), sparse = false, linenumbers = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEFunctionExpr`") + error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunctionExpr`") end idx = iip ? 2 : 1 f = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...)[idx] @@ -788,7 +788,7 @@ function DiffEqBase.SDEProblem{iip, specialize}( sparsenoise = nothing, check_length = true, callback = nothing, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEProblem`") + error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblem`") end f, u0, p = process_SciMLProblem( @@ -824,7 +824,7 @@ end function DiffEqBase.SDEProblem(sys::ODESystem, args...; kwargs...) if any(ModelingToolkit.isbrownian, unknowns(sys)) - error("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `mtkbuild` before a SDEProblem can be constructed.") + error("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `structural_simplify` before a SDEProblem can be constructed.") else error("Cannot construct SDEProblem from a normal ODESystem.") end @@ -886,7 +886,7 @@ function SDEProblemExpr{iip}(sys::SDESystem, u0map, tspan, sparsenoise = nothing, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `SDESystem` is required. Call `complete` or `mtkbuild` on the system before creating an `SDEProblemExpr`") + error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblemExpr`") end f, u0, p = process_SciMLProblem( SDEFunctionExpr{iip}, sys, u0map, parammap; check_length, diff --git a/src/systems/discrete_system/discrete_system.jl b/src/systems/discrete_system/discrete_system.jl index 94abaa596d..5f7c986659 100644 --- a/src/systems/discrete_system/discrete_system.jl +++ b/src/systems/discrete_system/discrete_system.jl @@ -311,7 +311,7 @@ function SciMLBase.DiscreteProblem( kwargs... ) if !iscomplete(sys) - error("A completed `DiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") + error("A completed `DiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") end dvs = unknowns(sys) ps = parameters(sys) @@ -363,7 +363,7 @@ function SciMLBase.DiscreteFunction{iip, specialize}( analytic = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `DiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") + error("A completed `DiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, cse, kwargs...) diff --git a/src/systems/discrete_system/implicit_discrete_system.jl b/src/systems/discrete_system/implicit_discrete_system.jl index 6440d5cce9..3956c089d4 100644 --- a/src/systems/discrete_system/implicit_discrete_system.jl +++ b/src/systems/discrete_system/implicit_discrete_system.jl @@ -330,7 +330,7 @@ function SciMLBase.ImplicitDiscreteProblem( kwargs... ) if !iscomplete(sys) - error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `ImplicitDiscreteProblem`.") + error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `ImplicitDiscreteProblem`.") end dvs = unknowns(sys) ps = parameters(sys) @@ -372,7 +372,7 @@ function SciMLBase.ImplicitDiscreteFunction{iip, specialize}( analytic = nothing, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `ImplicitDiscreteProblem`") + error("A completed `ImplicitDiscreteSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `ImplicitDiscreteProblem`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, expression_module = eval_module, cse, kwargs...) diff --git a/src/systems/index_cache.jl b/src/systems/index_cache.jl index 8d051f4b2c..d0b687c212 100644 --- a/src/systems/index_cache.jl +++ b/src/systems/index_cache.jl @@ -653,10 +653,10 @@ See also: [`MTKParameters`](@ref), [`tunable_parameters`](@ref), [`reorder_dimen function reorder_dimension_by_tunables!( dest::AbstractArray, sys::AbstractSystem, arr::AbstractArray, syms; dim = 1) if !iscomplete(sys) - throw(ArgumentError("A completed system is required. Call `complete` or `mtkbuild` on the system.")) + throw(ArgumentError("A completed system is required. Call `complete` or `structural_simplify` on the system.")) end if !has_index_cache(sys) || (ic = get_index_cache(sys)) === nothing - throw(ArgumentError("The system does not have an index cache. Call `complete` or `mtkbuild` on the system with `split = true`.")) + throw(ArgumentError("The system does not have an index cache. Call `complete` or `structural_simplify` on the system with `split = true`.")) end if size(dest) != size(arr) throw(ArgumentError("Source and destination arrays must have the same size. Got source array with size $(size(arr)) and destination with size $(size(dest)).")) diff --git a/src/systems/jumps/jumpsystem.jl b/src/systems/jumps/jumpsystem.jl index 8a5997d235..06f5e1b623 100644 --- a/src/systems/jumps/jumpsystem.jl +++ b/src/systems/jumps/jumpsystem.jl @@ -401,7 +401,7 @@ function DiffEqBase.DiscreteProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, cse = true, kwargs...) if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") end if has_equations(sys) || (!isempty(continuous_events(sys))) @@ -446,7 +446,7 @@ function DiscreteProblemExpr{iip}(sys::JumpSystem, u0map, tspan::Union{Tuple, No parammap = DiffEqBase.NullParameters(); kwargs...) where {iip} if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblemExpr`") + error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblemExpr`") end _, u0, p = process_SciMLProblem(EmptySciMLFunction, sys, u0map, parammap; @@ -492,7 +492,7 @@ function DiffEqBase.ODEProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, Nothi eval_module = @__MODULE__, cse = true, kwargs...) if !iscomplete(sys) - error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `DiscreteProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`") end # forward everything to be an ODESystem but the jumps and discrete events @@ -535,7 +535,7 @@ function JumpProcesses.JumpProblem(js::JumpSystem, prob, aggregator = JumpProcesses.NullAggregator(); callback = nothing, eval_expression = false, eval_module = @__MODULE__, kwargs...) if !iscomplete(js) - error("A completed `JumpSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `JumpProblem`") + error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `JumpProblem`") end unknowntoid = Dict(value(unknown) => i for (i, unknown) in enumerate(unknowns(js))) eqs = equations(js) diff --git a/src/systems/nonlinear/homotopy_continuation.jl b/src/systems/nonlinear/homotopy_continuation.jl index 796fce0c2d..9a77779103 100644 --- a/src/systems/nonlinear/homotopy_continuation.jl +++ b/src/systems/nonlinear/homotopy_continuation.jl @@ -492,7 +492,7 @@ function SciMLBase.HomotopyNonlinearFunction{iip, specialize}( p = nothing, fraction_cancel_fn = SymbolicUtils.simplify_fractions, cse = true, kwargs...) where {iip, specialize} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `HomotopyContinuationFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationFunction`") end transformation = PolynomialTransformation(sys) if transformation isa NotPolynomialError @@ -553,7 +553,7 @@ function HomotopyContinuationProblem{iip, spec}( sys::NonlinearSystem, u0map, pmap = SciMLBase.NullParameters(); kwargs...) where {iip, spec} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `HomotopyContinuationProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationProblem`") end f, u0, p = process_SciMLProblem( HomotopyNonlinearFunction{iip, spec}, sys, u0map, pmap; kwargs...) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index a5e0779813..7146fb6b5e 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -383,7 +383,7 @@ function SciMLBase.NonlinearFunction{iip}(sys::NonlinearSystem, dvs = unknowns(s initialization_data = nothing, cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearFunction`") end f_gen = generate_function(sys, dvs, ps; expression = Val{true}, cse, kwargs...) f_oop, f_iip = eval_or_rgf.(f_gen; eval_expression, eval_module) @@ -430,7 +430,7 @@ function SciMLBase.IntervalNonlinearFunction( p = nothing, eval_expression = false, eval_module = @__MODULE__, initialization_data = nothing, kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearFunction`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearFunction`") end if !isone(length(dvs)) || !isone(length(equations(sys))) error("`IntervalNonlinearFunction` only supports systems with a single equation and a single unknown.") @@ -472,7 +472,7 @@ function NonlinearFunctionExpr{iip}(sys::NonlinearSystem, dvs = unknowns(sys), sparse = false, simplify = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearFunctionExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearFunctionExpr`") end f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...) f = :($(GeneratedFunctionWrapper{(2, 2, is_split(sys))})($f_oop, $f_iip)) @@ -521,7 +521,7 @@ function IntervalNonlinearFunctionExpr( sys::NonlinearSystem, dvs = unknowns(sys), ps = parameters(sys), u0 = nothing; p = nothing, linenumbers = false, kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearFunctionExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearFunctionExpr`") end if !isone(length(dvs)) || !isone(length(equations(sys))) error("`IntervalNonlinearFunctionExpr` only supports systems with a single equation and a single unknown.") @@ -558,7 +558,7 @@ function DiffEqBase.NonlinearProblem{iip}(sys::NonlinearSystem, u0map, parammap = DiffEqBase.NullParameters(); check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblem`") end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -592,7 +592,7 @@ function DiffEqBase.NonlinearLeastSquaresProblem{iip}(sys::NonlinearSystem, u0ma parammap = DiffEqBase.NullParameters(); check_length = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearLeastSquaresProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearLeastSquaresProblem`") end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -676,11 +676,11 @@ function SciMLBase.SCCNonlinearProblem{iip}(sys::NonlinearSystem, u0map, parammap = SciMLBase.NullParameters(); eval_expression = false, eval_module = @__MODULE__, cse = true, kwargs...) where {iip} if !iscomplete(sys) || get_tearing_state(sys) === nothing - error("A simplified `NonlinearSystem` is required. Call `mtkbuild` on the system before creating an `SCCNonlinearProblem`.") + error("A simplified `NonlinearSystem` is required. Call `structural_simplify` on the system before creating an `SCCNonlinearProblem`.") end if !is_split(sys) - error("The system has been simplified with `split = false`. `SCCNonlinearProblem` is not compatible with this system. Pass `split = true` to `mtkbuild` to use `SCCNonlinearProblem`.") + error("The system has been simplified with `split = false`. `SCCNonlinearProblem` is not compatible with this system. Pass `split = true` to `structural_simplify` to use `SCCNonlinearProblem`.") end ts = get_tearing_state(sys) @@ -857,7 +857,7 @@ symbolically calculating numerical enhancements. function DiffEqBase.IntervalNonlinearProblem(sys::NonlinearSystem, uspan::NTuple{2}, parammap = SciMLBase.NullParameters(); kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearProblem`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearProblem`") end if !isone(length(unknowns(sys))) || !isone(length(equations(sys))) error("`IntervalNonlinearProblem` only supports with a single equation and a single unknown.") @@ -893,7 +893,7 @@ function NonlinearProblemExpr{iip}(sys::NonlinearSystem, u0map, check_length = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -933,7 +933,7 @@ function NonlinearLeastSquaresProblemExpr{iip}(sys::NonlinearSystem, u0map, check_length = false, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `NonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; check_length, kwargs...) @@ -958,7 +958,7 @@ numerical enhancements. function IntervalNonlinearProblemExpr(sys::NonlinearSystem, uspan::NTuple{2}, parammap = SciMLBase.NullParameters(); kwargs...) if !iscomplete(sys) - error("A completed `NonlinearSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `IntervalNonlinearProblemExpr`") + error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `IntervalNonlinearProblemExpr`") end if !isone(length(unknowns(sys))) || !isone(length(equations(sys))) error("`IntervalNonlinearProblemExpr` only supports with a single equation and a single unknown.") diff --git a/src/systems/optimization/optimizationsystem.jl b/src/systems/optimization/optimizationsystem.jl index b7cc541ed7..bfe15b62d7 100644 --- a/src/systems/optimization/optimizationsystem.jl +++ b/src/systems/optimization/optimizationsystem.jl @@ -303,7 +303,7 @@ function DiffEqBase.OptimizationProblem{iip}(sys::OptimizationSystem, u0map, checks = true, cse = true, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `OptimizationSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `OptimizationProblem`") + error("A completed `OptimizationSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `OptimizationProblem`") end if haskey(kwargs, :lcons) || haskey(kwargs, :ucons) Base.depwarn( @@ -544,7 +544,7 @@ function OptimizationProblemExpr{iip}(sys::OptimizationSystem, u0map, eval_expression = false, eval_module = @__MODULE__, kwargs...) where {iip} if !iscomplete(sys) - error("A completed `OptimizationSystem` is required. Call `complete` or `mtkbuild` on the system before creating a `OptimizationProblemExpr`") + error("A completed `OptimizationSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `OptimizationProblemExpr`") end if haskey(kwargs, :lcons) || haskey(kwargs, :ucons) Base.depwarn( @@ -726,7 +726,7 @@ function OptimizationProblemExpr{iip}(sys::OptimizationSystem, u0map, end end -function mtkbuild(sys::OptimizationSystem; split = true, kwargs...) +function structural_simplify(sys::OptimizationSystem; split = true, kwargs...) sys = flatten(sys) cons = constraints(sys) econs = Equation[] @@ -739,7 +739,7 @@ function mtkbuild(sys::OptimizationSystem; split = true, kwargs...) end end nlsys = NonlinearSystem(econs, unknowns(sys), parameters(sys); name = :___tmp_nlsystem) - snlsys = mtkbuild(nlsys; fully_determined = false, kwargs...) + snlsys = structural_simplify(nlsys; fully_determined = false, kwargs...) obs = observed(snlsys) subs = Dict(eq.lhs => eq.rhs for eq in observed(snlsys)) seqs = equations(snlsys) diff --git a/src/systems/parameter_buffer.jl b/src/systems/parameter_buffer.jl index fa2bce9289..6142c95776 100644 --- a/src/systems/parameter_buffer.jl +++ b/src/systems/parameter_buffer.jl @@ -23,7 +23,7 @@ dependent systems. It is only required if the symbolic expressions also use the variable of the system. This requires that `complete` has been called on the system (usually via -`mtkbuild` or `@mtkbuild`) and the keyword `split = true` was passed (which is +`structural_simplify` or `@mtkbuild`) and the keyword `split = true` was passed (which is the default behavior). """ function MTKParameters( diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 3e938578d6..7e47a21e75 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -33,7 +33,7 @@ function mtkbuild( disturbance_inputs = Any[], kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) - newsys′ = __structural_simplification(sys; simplify, + newsys′ = __structural_simplify(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, inputs, outputs, disturbance_inputs, kwargs...) @@ -65,12 +65,12 @@ function mtkbuild( end end -function __structural_simplification(sys::JumpSystem, args...; kwargs...) +function __structural_simplify(sys::JumpSystem, args...; kwargs...) return sys end -function __structural_simplification(sys::SDESystem, args...; kwargs...) - return __structural_simplification(ODESystem(sys), args...; kwargs...) +function __structural_simplify(sys::SDESystem, args...; kwargs...) + return __structural_simplify(ODESystem(sys), args...; kwargs...) end function __structural_simplification(sys::AbstractSystem; simplify = false, @@ -94,7 +94,7 @@ function __structural_simplification(sys::AbstractSystem; simplify = false, end end if isempty(brown_vars) - return structural_simplification!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) + return structural_simplify!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) else Is = Int[] Js = Int[] @@ -127,7 +127,7 @@ function __structural_simplification(sys::AbstractSystem; simplify = false, if !iszero(new_idxs[i]) && invview(var_to_diff)[i] === nothing] # TODO: IO is not handled. - ode_sys = structural_simplification(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) + ode_sys = structural_simplify(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) eqs = equations(ode_sys) sorted_g_rows = zeros(Num, length(eqs), size(g, 2)) for (i, eq) in enumerate(eqs) @@ -170,7 +170,7 @@ end """ $(TYPEDSIGNATURES) -Given a system that has been simplified via `mtkbuild`, return a `Dict` mapping +Given a system that has been simplified via `structural_simplify`, return a `Dict` mapping variables of the system to equations that are used to solve for them. This includes observed variables. @@ -186,7 +186,7 @@ function map_variables_to_equations(sys::AbstractSystem; rename_dummy_derivative end ts = get_tearing_state(sys) if ts === nothing - throw(ArgumentError("`map_variables_to_equations` requires a simplified system. Call `mtkbuild` on the system before calling this function.")) + throw(ArgumentError("`map_variables_to_equations` requires a simplified system. Call `structural_simplify` on the system before calling this function.")) end dummy_sub = Dict() diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index 0c929c4bb3..bbad46217e 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -24,7 +24,7 @@ function quick_cancel_expr(expr) kws...))(expr) end -export SystemStructure, TransformationState, TearingState, structural_simplification! +export SystemStructure, TransformationState, TearingState, structural_simplify! export isdiffvar, isdervar, isalgvar, isdiffeq, algeqs, is_only_discrete export dervars_range, diffvars_range, algvars_range export DiffGraph, complete! @@ -657,7 +657,7 @@ function Base.show(io::IO, mime::MIME"text/plain", ms::MatchedSystemStructure) printstyled(io, " SelectedState") end -function structural_simplification!(state::TearingState; simplify = false, +function structural_simplify!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = true, inputs = Any[], outputs = Any[], disturbance_inputs = Any[], @@ -670,7 +670,7 @@ function structural_simplification!(state::TearingState; simplify = false, Dict(default_toterm.(state.fullvars) .=> ci.var_domain)) tss, clocked_inputs, continuous_id, id_to_clock = ModelingToolkit.split_system(ci) cont_inputs = [inputs; clocked_inputs[continuous_id]] - sys = _structural_simplification!(tss[continuous_id]; simplify, + sys = _structural_simplify!(tss[continuous_id]; simplify, check_consistency, fully_determined, inputs = cont_inputs, outputs, disturbance_inputs, kwargs...) @@ -707,14 +707,14 @@ function structural_simplification!(state::TearingState; simplify = false, for sym in get_ps(sys)] @set! sys.ps = ps else - sys = _structural_simplification!(state; simplify, check_consistency, + sys = _structural_simplify!(state; simplify, check_consistency, inputs, outputs, disturbance_inputs, fully_determined, kwargs...) end return sys end -function _structural_simplification!(state::TearingState; simplify = false, +function _structural_simplify!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = false, dummy_derivative = true, inputs = Any[], outputs = Any[], diff --git a/src/utils.jl b/src/utils.jl index d1645783eb..2b3cbedab0 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -159,7 +159,7 @@ function check_lhs(eq::Equation, op, dvs::Set) v = unwrap(eq.lhs) _iszero(v) && return (operation(v) isa op && only(arguments(v)) in dvs) && return - error("$v is not a valid LHS. Please run mtkbuild before simulation.") + error("$v is not a valid LHS. Please run structural_simplify before simulation.") end check_lhs(eqs, op, dvs::Set) = for eq in eqs @@ -323,7 +323,7 @@ Throw error when difference/derivative operation occurs in the R.H.S. optext = "derivative" end msg = "The $optext variable must be isolated to the left-hand " * - "side of the equation like `$opvar ~ ...`. You may want to use `mtkbuild` or the DAE form.\nGot $eq." + "side of the equation like `$opvar ~ ...`. You may want to use `structural_simplify` or the DAE form.\nGot $eq." throw(InvalidSystemException(msg)) end @@ -359,10 +359,10 @@ function check_operator_variables(eqs, op::T) where {T} is_tmp_fine = iszero(nd) end is_tmp_fine || - error("The LHS cannot contain nondifferentiated variables. Please run `mtkbuild` or use the DAE form.\nGot $eq") + error("The LHS cannot contain nondifferentiated variables. Please run `structural_simplify` or use the DAE form.\nGot $eq") for v in tmp v in ops && - error("The LHS operator must be unique. Please run `mtkbuild` or use the DAE form. $v appears in LHS more than once.") + error("The LHS operator must be unique. Please run `structural_simplify` or use the DAE form. $v appears in LHS more than once.") push!(ops, v) end empty!(tmp) diff --git a/test/accessor_functions.jl b/test/accessor_functions.jl index 3f5a22f34c..7ce477155b 100644 --- a/test/accessor_functions.jl +++ b/test/accessor_functions.jl @@ -68,10 +68,10 @@ let sys_mid2_comp = complete(sys_mid2) sys_mid1_comp = complete(sys_mid1) sys_top_comp = complete(sys_top) - sys_bot_ss = mtkbuild(sys_bot) - sys_mid2_ss = mtkbuild(sys_mid2) - sys_mid1_ss = mtkbuild(sys_mid1) - sys_top_ss = mtkbuild(sys_top) + sys_bot_ss = structural_simplify(sys_bot) + sys_mid2_ss = structural_simplify(sys_mid2) + sys_mid1_ss = structural_simplify(sys_mid1) + sys_top_ss = structural_simplify(sys_top) # Checks `parameters1. @test all_sets_equal(parameters.([sys_bot, sys_bot_comp, sys_bot_ss])..., [d, p_bot]) @@ -98,7 +98,7 @@ let @test all(sym_issubset(parameters_toplevel(sys), get_ps(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) - # Checks `unknowns`. O(t) is eliminated by `mtkbuild` and + # Checks `unknowns`. O(t) is eliminated by `structural_simplify` and # must be considered separately. @test all_sets_equal(unknowns.([sys_bot, sys_bot_comp])..., [O, Y, X_bot]) @test all_sets_equal(unknowns.([sys_bot_ss])..., [Y, X_bot]) diff --git a/test/analysis_points.jl b/test/analysis_points.jl index e52ac9e1a7..e36afc02f7 100644 --- a/test/analysis_points.jl +++ b/test/analysis_points.jl @@ -67,7 +67,7 @@ sys = ODESystem(eqs, t, systems = [P, C], name = :hej) nonamespace_sys = toggle_namespacing(nested_sys, false) @testset "simplifies and solves" begin - ssys = mtkbuild(sys) + ssys = structural_simplify(sys) prob = ODEProblem(ssys, [P.x => 1], (0, 10)) sol = solve(prob, Rodas5()) @test norm(sol.u[1]) >= 1 diff --git a/test/basic_transformations.jl b/test/basic_transformations.jl index 4419f508df..544a89cd29 100644 --- a/test/basic_transformations.jl +++ b/test/basic_transformations.jl @@ -50,8 +50,8 @@ end M1 = ODESystem(eqs, t; initialization_eqs, name = :M) M2 = change_independent_variable(M1, s) - M1 = mtkbuild(M1; allow_symbolic = true) - M2 = mtkbuild(M2; allow_symbolic = true) + M1 = structural_simplify(M1; allow_symbolic = true) + M2 = structural_simplify(M2; allow_symbolic = true) prob1 = ODEProblem(M1, [M1.s => 1.0], (1.0, 4.0), []) prob2 = ODEProblem(M2, [], (1.0, 2.0), []) sol1 = solve(prob1, Tsit5(); reltol = 1e-10, abstol = 1e-10) @@ -100,9 +100,9 @@ end extraeqs = [Differential(M2.a)(b) ~ exp(-b), M2.a ~ exp(b)] M3 = change_independent_variable(M2, b, extraeqs) - M1 = mtkbuild(M1) - M2 = mtkbuild(M2; allow_symbolic = true) - M3 = mtkbuild(M3; allow_symbolic = true) + M1 = structural_simplify(M1) + M2 = structural_simplify(M2; allow_symbolic = true) + M3 = structural_simplify(M3; allow_symbolic = true) @test length(unknowns(M3)) == length(unknowns(M2)) == length(unknowns(M1)) - 1 end @@ -120,7 +120,7 @@ end @parameters g=9.81 v # gravitational acceleration and constant horizontal velocity Mt = ODESystem([D(D(y)) ~ -g, D(x) ~ v], t; name = :M) # gives (x, y) as function of t, ... Mx = change_independent_variable(Mt, x; add_old_diff = true) # ... but we want y as a function of x - Mx = mtkbuild(Mx; allow_symbolic = true) + Mx = structural_simplify(Mx; allow_symbolic = true) Dx = Differential(Mx.x) u0 = [Mx.y => 0.0, Dx(Mx.y) => 1.0, Mx.t => 0.0] p = [v => 10.0] @@ -134,7 +134,7 @@ end @parameters g = 9.81 # gravitational acceleration Mt = ODESystem([D(D(y)) ~ -g, D(D(x)) ~ 0], t; name = :M) # gives (x, y) as function of t, ... Mx = change_independent_variable(Mt, x; add_old_diff = true) # ... but we want y as a function of x - Mx = mtkbuild(Mx; allow_symbolic = true) + Mx = structural_simplify(Mx; allow_symbolic = true) Dx = Differential(Mx.x) u0 = [Mx.y => 0.0, Dx(Mx.y) => 1.0, Mx.t => 0.0, Mx.xˍt => 10.0] prob = ODEProblem(Mx, u0, (0.0, 20.0), []) # 1 = dy/dx = (dy/dt)/(dx/dt) means equal initial horizontal and vertical velocities @@ -152,7 +152,7 @@ end ] M1 = ODESystem(eqs, t; name = :M) M2 = change_independent_variable(M1, x; add_old_diff = true) - @test_nowarn mtkbuild(M2) + @test_nowarn structural_simplify(M2) # Compare to pen-and-paper result @variables x xˍt(x) xˍt(x) y(x) t(x) @@ -198,7 +198,7 @@ end ]) _f = LinearInterpolation([1.0, 1.0], [-100.0, +100.0]) # constant value 1 - M2s = mtkbuild(M2; allow_symbolic = true) + M2s = structural_simplify(M2; allow_symbolic = true) prob = ODEProblem(M2s, [M2s.y => 0.0], (1.0, 4.0), [fc => _f, f => _f]) sol = solve(prob, Tsit5(); abstol = 1e-5) @test isapprox(sol(4.0, idxs = M2.y), 12.0; atol = 1e-5) # Anal solution is D(y) ~ 12 => y(t) ~ 12*t + C => y(x) ~ 12*√(x) + C. With y(x=1)=0 => 12*(√(x)-1), so y(x=4) ~ 12 @@ -207,7 +207,7 @@ end @testset "Change independent variable (errors)" begin @variables x(t) y z(y) w(t) v(t) M = ODESystem([D(x) ~ 1, v ~ x], t; name = :M) - Ms = mtkbuild(M) + Ms = structural_simplify(M) @test_throws "structurally simplified" change_independent_variable(Ms, y) @test_throws "not a function of" change_independent_variable(M, y) @test_throws "not a function of" change_independent_variable(M, z) diff --git a/test/clock.jl b/test/clock.jl index 296afa899d..c6051a52a8 100644 --- a/test/clock.jl +++ b/test/clock.jl @@ -65,10 +65,10 @@ By inference: ci, varmap = infer_clocks(sys) eqmap = ci.eq_domain tss, inputs, continuous_id = ModelingToolkit.split_system(deepcopy(ci)) -sss, = ModelingToolkit._mtkbuild!( +sss, = ModelingToolkit._structural_simplify!( deepcopy(tss[continuous_id]), (inputs[continuous_id], ())) @test equations(sss) == [D(x) ~ u - x] -sss, = ModelingToolkit._mtkbuild!(deepcopy(tss[1]), (inputs[1], ())) +sss, = ModelingToolkit._structural_simplify!(deepcopy(tss[1]), (inputs[1], ())) @test isempty(equations(sss)) d = Clock(dt) k = ShiftIndex(d) @@ -115,7 +115,7 @@ eqs = [yd ~ Sample(dt)(y) D(x) ~ -x + u y ~ x] @named sys = ODESystem(eqs, t) -@test_throws ModelingToolkit.HybridSystemNotSupportedException ss=mtkbuild(sys); +@test_throws ModelingToolkit.HybridSystemNotSupportedException ss=structural_simplify(sys); @test_skip begin Tf = 1.0 @@ -128,7 +128,7 @@ eqs = [yd ~ Sample(dt)(y) [kp => 1.0; ud(k - 1) => 2.1; ud(k - 2) => 2.0]) # recreate problem to empty saved values sol = solve(prob, Tsit5(), kwargshandle = KeywordArgSilent) - ss_nosplit = mtkbuild(sys; split = false) + ss_nosplit = structural_simplify(sys; split = false) prob_nosplit = ODEProblem(ss_nosplit, [x => 0.1], (0.0, Tf), [kp => 1.0; ud(k - 1) => 2.1; ud(k - 2) => 2.0]) int = init(prob_nosplit, Tsit5(); kwargshandle = KeywordArgSilent) @@ -294,8 +294,8 @@ eqs = [yd ~ Sample(dt)(y) @test varmap[y] == ContinuousClock() @test varmap[u] == ContinuousClock() - ss = mtkbuild(cl) - ss_nosplit = mtkbuild(cl; split = false) + ss = structural_simplify(cl) + ss_nosplit = structural_simplify(cl; split = false) if VERSION >= v"1.7" prob = ODEProblem(ss, [x => 0.0], (0.0, 1.0), [kp => 1.0]) @@ -426,7 +426,7 @@ eqs = [yd ~ Sample(dt)(y) @test varmap[_model.feedback.output.u] == d @test varmap[_model.feedback.input2.u] == d - ssys = mtkbuild(model) + ssys = structural_simplify(model) Tf = 0.2 timevec = 0:(d.dt):Tf diff --git a/test/code_generation.jl b/test/code_generation.jl index 83d324cce3..cf3d660b81 100644 --- a/test/code_generation.jl +++ b/test/code_generation.jl @@ -70,7 +70,7 @@ end @parameters p[1:2] (f::Function)(..) @named sys = ODESystem( [D(x[0]) ~ p[1] * x[0] + x[2], D(x[1]) ~ p[2] * f(x) + x[2]], t) - sys, = mtkbuild(sys, ([x[2]], [])) + sys, = structural_simplify(sys, ([x[2]], [])) @test is_parameter(sys, x[2]) prob = ODEProblem(sys, [x[0] => 1.0, x[1] => 1.0], (0.0, 1.0), [p => ones(2), f => sum, x[2] => 2.0]) diff --git a/test/components.jl b/test/components.jl index 2c470d9ccc..0ae5327bde 100644 --- a/test/components.jl +++ b/test/components.jl @@ -42,9 +42,9 @@ end completed_rc_model = complete(rc_model) @test isequal(completed_rc_model.resistor.n.i, resistor.n.i) @test ModelingToolkit.n_expanded_connection_equations(capacitor) == 2 -@test length(equations(mtkbuild(rc_model, allow_parameter = false))) == 2 -sys = mtkbuild(rc_model) -@test_throws ModelingToolkit.RepeatedStructuralSimplificationError mtkbuild(sys) +@test length(equations(structural_simplify(rc_model, allow_parameter = false))) == 2 +sys = structural_simplify(rc_model) +@test_throws ModelingToolkit.RepeatedStructuralSimplificationError structural_simplify(sys) @test length(equations(sys)) == 1 check_contract(sys) @test !isempty(ModelingToolkit.defaults(sys)) @@ -69,7 +69,7 @@ let @named _rc_model = ODESystem(rc_eqs, t) @named rc_model = compose(_rc_model, [resistor, capacitor, source, ground]) - sys = mtkbuild(rc_model) + sys = structural_simplify(rc_model) u0 = [ capacitor.v => 0.0 ] @@ -93,7 +93,7 @@ let @named _rc_model2 = ODESystem(rc_eqs2, t) @named rc_model2 = compose(_rc_model2, [resistor, resistor2, capacitor, source, ground]) - sys2 = mtkbuild(rc_model2) + sys2 = structural_simplify(rc_model2) prob2 = ODEProblem(sys2, [source.p.i => 0.0], (0, 10.0), guesses = u0) sol2 = solve(prob2, Rosenbrock23()) @test sol2[source.p.i] ≈ sol2[rc_model2.source.p.i] ≈ -sol2[capacitor.i] @@ -127,7 +127,7 @@ eqs = [connect(source.p, rc_comp.p) @named sys_inner_outer = compose(sys′, [ground, source, rc_comp]) @test_nowarn show(IOBuffer(), MIME"text/plain"(), sys_inner_outer) expand_connections(sys_inner_outer, debug = true) -sys_inner_outer = mtkbuild(sys_inner_outer) +sys_inner_outer = structural_simplify(sys_inner_outer) @test !isempty(ModelingToolkit.defaults(sys_inner_outer)) u0 = [rc_comp.capacitor.v => 0.0] prob = ODEProblem(sys_inner_outer, u0, (0, 10.0), sparse = true) @@ -150,7 +150,7 @@ sol = solve(prob, Tsit5()) #plot(sol) include("../examples/serial_inductor.jl") -sys = mtkbuild(ll_model) +sys = structural_simplify(ll_model) @test length(equations(sys)) == 2 u0 = unknowns(sys) .=> 0 @test_nowarn ODEProblem( @@ -159,7 +159,7 @@ prob = DAEProblem(sys, D.(unknowns(sys)) .=> 0, [], (0, 0.5), guesses = u0) sol = solve(prob, DFBDF()) @test sol.retcode == SciMLBase.ReturnCode.Success -sys2 = mtkbuild(ll2_model) +sys2 = structural_simplify(ll2_model) @test length(equations(sys2)) == 3 u0 = unknowns(sys) .=> 0 prob = ODEProblem(sys, u0, (0, 10.0)) @@ -233,7 +233,7 @@ function Circuit(; name) end @named foo = Circuit() -@test mtkbuild(foo) isa ModelingToolkit.AbstractSystem +@test structural_simplify(foo) isa ModelingToolkit.AbstractSystem # BLT tests using LinearAlgebra @@ -289,7 +289,7 @@ rc_eqs = [connect(capacitor.n, resistor.p) @named _rc_model = ODESystem(rc_eqs, t) @named rc_model = compose(_rc_model, [resistor, capacitor, ground]) -sys = mtkbuild(rc_model) +sys = structural_simplify(rc_model) prob = ODEProblem(sys, u0, (0, 10.0)) sol = solve(prob, Tsit5()) @@ -334,7 +334,7 @@ end end @named outer = Outer() - simp = mtkbuild(outer) + simp = structural_simplify(outer) @test sort(propertynames(outer)) == [:inner, :t, :x] @test propertynames(simp) == propertynames(outer) @@ -351,7 +351,7 @@ end @test_throws ArgumentError outer.inner₊p end -@testset "`getproperty` on `mtkbuild(complete(sys))`" begin +@testset "`getproperty` on `structural_simplify(complete(sys))`" begin @mtkmodel Foo begin @variables begin x(t) @@ -367,7 +367,7 @@ end end @named bar = Bar() cbar = complete(bar) - ss = mtkbuild(cbar) + ss = structural_simplify(cbar) @test isequal(cbar.foo.x, ss.foo.x) end diff --git a/test/constants.jl b/test/constants.jl index 3e48c83f59..f2c4fdaa86 100644 --- a/test/constants.jl +++ b/test/constants.jl @@ -17,12 +17,12 @@ sol = solve(prob, Tsit5()) newsys = MT.eliminate_constants(sys) @test isequal(equations(newsys), [D(x) ~ 1]) -# Test mtkbuild substitutions & observed values +# Test structural_simplify substitutions & observed values eqs = [D(x) ~ 1, w ~ a] @named sys = ODESystem(eqs, t) # Now eliminate the constants first -simp = mtkbuild(sys) +simp = structural_simplify(sys) @test equations(simp) == [D(x) ~ 1.0] #Constant with units @@ -34,7 +34,7 @@ UMT.get_unit(β) D = Differential(t) eqs = [D(x) ~ β] @named sys = ODESystem(eqs, t) -simp = mtkbuild(sys) +simp = structural_simplify(sys) @test isempty(MT.collect_constants(nothing)) diff --git a/test/dde.jl b/test/dde.jl index e94e4aa5d0..c7561e6c24 100644 --- a/test/dde.jl +++ b/test/dde.jl @@ -119,11 +119,11 @@ eqs = [osc1.jcn ~ osc2.delx, @test ModelingToolkit.is_dde(coupledOsc2) @test !is_markovian(coupledOsc2) for coupledOsc in [coupledOsc, coupledOsc2] - local sys = mtkbuild(coupledOsc) + local sys = structural_simplify(coupledOsc) @test length(equations(sys)) == 4 @test length(unknowns(sys)) == 4 end -sys = mtkbuild(coupledOsc) +sys = structural_simplify(coupledOsc) prob = DDEProblem(sys, [], (0.0, 10.0); constant_lags = [sys.osc1.τ, sys.osc2.τ]) sol = solve(prob, MethodOfSteps(Tsit5())) obsfn = ModelingToolkit.build_explicit_observed_function( @@ -178,7 +178,7 @@ end eqs = [D(x(t)) ~ -w * x(t - τ)] @named sys = System(eqs, t) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob = DDEProblem(sys, [], @@ -191,7 +191,7 @@ end @brownian r eqs = [D(x(t)) ~ -w * x(t - τ) + r] @named sys = System(eqs, t) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob = SDDEProblem(sys, [], (0.0, 10.0), diff --git a/test/debugging.jl b/test/debugging.jl index 3a3cbd5d88..a55684737c 100644 --- a/test/debugging.jl +++ b/test/debugging.jl @@ -6,8 +6,8 @@ using ModelingToolkit: t_nounits as t, D_nounits as D, ASSERTION_LOG_VARIABLE @brownian a @named inner_ode = ODESystem(D(x) ~ -sqrt(x), t; assertions = [(x > 0) => "ohno"]) @named inner_sde = System([D(x) ~ -sqrt(x) + a], t; assertions = [(x > 0) => "ohno"]) -sys_ode = mtkbuild(inner_ode) -sys_sde = mtkbuild(inner_sde) +sys_ode = structural_simplify(inner_ode) +sys_sde = structural_simplify(inner_sde) @testset "assertions are present in generated `f`" begin @testset "$(typeof(sys))" for (Problem, sys, alg) in [ diff --git a/test/discrete_system.jl b/test/discrete_system.jl index b183fdca62..b0e2481e56 100644 --- a/test/discrete_system.jl +++ b/test/discrete_system.jl @@ -31,7 +31,7 @@ eqs = [S ~ S(k - 1) - infection * h, # System @named sys = DiscreteSystem(eqs, t, [S, I, R], [c, nsteps, δt, β, γ]) -syss = mtkbuild(sys) +syss = structural_simplify(sys) @test syss == syss df = DiscreteFunction(syss) @@ -254,7 +254,7 @@ end @variables x(t) y(t) k = ShiftIndex(t) @named sys = DiscreteSystem([x ~ x^2 + y^2, y ~ x(k - 1) + y(k - 1)], t) -@test_throws ["algebraic equations", "ImplicitDiscreteSystem"] mtkbuild(sys) +@test_throws ["algebraic equations", "ImplicitDiscreteSystem"] structural_simplify(sys) @testset "Passing `nothing` to `u0`" begin @variables x(t) = 1 diff --git a/test/domain_connectors.jl b/test/domain_connectors.jl index 736abfc81f..9a43d2938f 100644 --- a/test/domain_connectors.jl +++ b/test/domain_connectors.jl @@ -148,7 +148,7 @@ esys = ModelingToolkit.expand_connections(odesys) csys = complete(odesys) -sys = mtkbuild(odesys) +sys = structural_simplify(odesys) @test length(equations(sys)) == length(unknowns(sys)) sys_defs = ModelingToolkit.defaults(sys) diff --git a/test/downstream/analysis_points.jl b/test/downstream/analysis_points.jl index fddadd20c4..29b9aad512 100644 --- a/test/downstream/analysis_points.jl +++ b/test/downstream/analysis_points.jl @@ -60,7 +60,7 @@ import ControlSystemsBase as CS filt.xd => 0.0 ]) - sys = mtkbuild(closed_loop) + sys = structural_simplify(closed_loop) prob = ODEProblem(sys, unknowns(sys) .=> 0.0, (0.0, 4.0)) sol = solve(prob, Rodas5P(), reltol = 1e-6, abstol = 1e-9) @@ -100,8 +100,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the mtkbuild works correctly - ssys = mtkbuild(sys_outer) + # test first that the structural_simplify works correctly + ssys = structural_simplify(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -136,8 +136,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the mtkbuild works correctly - ssys = mtkbuild(sys_outer) + # test first that the structural_simplify works correctly + ssys = structural_simplify(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -172,8 +172,8 @@ end connect(F.output, sys_inner.add.input1)] sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer) - # test first that the mtkbuild works correctly - ssys = mtkbuild(sys_outer) + # test first that the structural_simplify works correctly + ssys = structural_simplify(sys_outer) prob = ODEProblem(ssys, Pair[], (0, 10)) @test_nowarn solve(prob, Rodas5()) @@ -363,7 +363,7 @@ end sys_normal = normal_test_system() -prob = ODEProblem(mtkbuild(sys_normal), [], (0.0, 10.0)) +prob = ODEProblem(structural_simplify(sys_normal), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices_normal, _ = get_sensitivity(sys_normal, sys_normal.normal_inner.ap) @@ -384,7 +384,7 @@ matrices_normal, _ = get_sensitivity(sys_normal, sys_normal.normal_inner.ap) connect(inner.back.output, :ap, inner.F1.input)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) + prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) @@ -408,7 +408,7 @@ end connect(inner.back.output.u, :ap, inner.F1.input.u)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) + prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) @@ -432,7 +432,7 @@ end connect(inner.back.output.u, :ap, inner.F1.input.u)] @named sys = ODESystem(eqs2, t; systems = [inner, step]) - prob = ODEProblem(mtkbuild(sys), [], (0.0, 10.0)) + prob = ODEProblem(structural_simplify(sys), [], (0.0, 10.0)) @test SciMLBase.successful_retcode(solve(prob, Rodas5P())) matrices, _ = get_sensitivity(sys, sys.ap) diff --git a/test/downstream/inversemodel.jl b/test/downstream/inversemodel.jl index 0251c43e38..32d5ee87ec 100644 --- a/test/downstream/inversemodel.jl +++ b/test/downstream/inversemodel.jl @@ -110,7 +110,7 @@ end end end; @named model = InverseControlledTank() -ssys = mtkbuild(model) +ssys = structural_simplify(model) cm = complete(model) op = Dict( diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index 738cae70fe..40cb277236 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -13,12 +13,11 @@ eqs = [u ~ kp * (r - y) y ~ x] @named sys = ODESystem(eqs, t) -sys = mtkbuild(sys, inputs = [r], outputs = [y]) -lsys = linearize(sys, [r], [y]) +lsys, ssys = linearize(sys, [r], [y]) lprob = LinearizationProblem(sys, [r], [y]) lsys2 = solve(lprob) -lsys3 = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) +lsys3, _ = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) @test lsys.A[] == lsys2.A[] == lsys3.A[] == -2 @test lsys.B[] == lsys2.B[] == lsys3.B[] == 1 @@ -87,7 +86,6 @@ connections = [f.y ~ c.r # filtered reference to controller reference p.y ~ c.y] @named cl = ODESystem(connections, t, systems = [f, c, p]) -cl = mtkbuild(cl, inputs = [f.u], outputs = [p.x]) lsys0 = linearize(cl, [f.u], [p.x]) desired_order = [f.x, p.x] @@ -203,7 +201,7 @@ lsys = linearize(sat, [u], [y]) # @test substitute(lsyss.D, ModelingToolkit.defaults(sat)) == lsys.D # outside the linear region the derivative is 0 -lsys = linearize(sat, [u], [y]; op = Dict(u => 2)) +lsys, ssys = linearize(sat, [u], [y]; op = Dict(u => 2)) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @@ -300,7 +298,6 @@ end @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi -tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize(tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2)) @@ -309,14 +306,13 @@ m_ss = 2.4000000003229878 @parameters p = 1.0 eqs = [D(x) ~ p * u, x ~ y] @named sys = ODESystem(eqs, t) -sys = mtkbuild(sys, inputs = [u]) -matrices1 = linearize(sys; op = Dict(x => 2.0)) -matrices2 = linearize(sys; op = Dict(y => 2.0)) +matrices1, _ = linearize(sys, [u], []; op = Dict(x => 2.0)) +matrices2, _ = linearize(sys, [u], []; op = Dict(y => 2.0)) @test matrices1 == matrices2 # Ensure parameter values passed as `Dict` are respected -linfun = linearization_function(sys, [u], []; op = Dict(x => 2.0)) +linfun, _ = linearization_function(sys, [u], []; op = Dict(x => 2.0)) matrices = linfun([1.0], Dict(p => 3.0), 1.0) # this would be 1 if the parameter value isn't respected @test matrices.f_u[] == 3.0 @@ -332,7 +328,7 @@ end @parameters p eqs = [0 ~ x * log(y) - p] @named sys = ODESystem(eqs, t; defaults = [p => 1.0]) - sys = mtkbuild(sys, inputs = [x]) + sys = complete(sys) @test_throws ModelingToolkit.MissingVariablesError linearize( sys, [x], []; op = Dict(x => 1.0), allow_input_derivatives = true) @test_nowarn linearize( @@ -343,7 +339,6 @@ end @testset "Symbolic values for parameters in `linearize`" begin @named tank_noi = Tank_noi() @unpack md_i, h, m, ρ, A, K = tank_noi - tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize( tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) @@ -352,7 +347,6 @@ end @testset "Warn on empty operating point" begin @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi - tank_noi = mtkbuild(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_warn ["empty operating point", "warn_empty_op"] linearize( tank_noi, [md_i], [h]; p = [md_i => 1.0]) diff --git a/test/downstream/test_disturbance_model.jl b/test/downstream/test_disturbance_model.jl index 937000d28a..97276437e2 100644 --- a/test/downstream/test_disturbance_model.jl +++ b/test/downstream/test_disturbance_model.jl @@ -55,7 +55,7 @@ end end @named model = ModelWithInputs() # Model with load disturbance -ssys = mtkbuild(model) +ssys = structural_simplify(model) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) # plot(sol) @@ -94,10 +94,10 @@ dist(; name) = ODESystem(1 / s; name) end @named model_with_disturbance = SystemModelWithDisturbanceModel() -# ssys = mtkbuild(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here +# ssys = structural_simplify(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here # lsys2 = named_ss(model_with_disturbance, [:u, :d1], # [P.inertia1.phi, P.inertia2.phi, P.inertia1.w, P.inertia2.w]) -ssys = mtkbuild(model_with_disturbance) +ssys = structural_simplify(model_with_disturbance) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) @test SciMLBase.successful_retcode(sol) @@ -137,10 +137,10 @@ dist3(; name) = ODESystem(ss(1 + 10 / s, balance = false); name) end @named model_with_disturbance = SystemModelWithDisturbanceModel() -# ssys = mtkbuild(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here +# ssys = structural_simplify(open_loop(model_with_disturbance, :d)) # Open loop worked, but it's a bit awkward that we have to use it here # lsys3 = named_ss(model_with_disturbance, [:u, :d1], # [P.inertia1.phi, P.inertia2.phi, P.inertia1.w, P.inertia2.w]) -ssys = mtkbuild(model_with_disturbance) +ssys = structural_simplify(model_with_disturbance) prob = ODEProblem(ssys, [], (0.0, 10.0)) sol = solve(prob, Tsit5()) @test SciMLBase.successful_retcode(sol) diff --git a/test/dq_units.jl b/test/dq_units.jl index cd5396b10d..3c59c479c1 100644 --- a/test/dq_units.jl +++ b/test/dq_units.jl @@ -113,24 +113,24 @@ noiseeqs = [0.1us"W" 0.1us"W" eqs = [D(L) ~ v, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) eqs = [D(V) ~ r, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) @variables V [unit = u"m"^3] L [unit = u"m"] @parameters v [unit = u"m/s"] r [unit = u"m"^3 / u"s"] eqs = [V ~ r * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) eqs = [L ~ v * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) #Jump System @parameters β [unit = u"(mol^2*s)^-1"] γ [unit = u"(mol*s)^-1"] jumpmol [ diff --git a/test/error_handling.jl b/test/error_handling.jl index 4a7941aab3..59aa6b79a1 100644 --- a/test/error_handling.jl +++ b/test/error_handling.jl @@ -42,7 +42,7 @@ rc_eqs = [connect(source.p, resistor.p) connect(capacitor.n, source.n)] @named rc_model = ODESystem(rc_eqs, t, systems = [resistor, capacitor, source]) -@test_throws ModelingToolkit.ExtraVariablesSystemException mtkbuild(rc_model) +@test_throws ModelingToolkit.ExtraVariablesSystemException structural_simplify(rc_model) @named source2 = OverdefinedConstantVoltage(V = V, I = V / R) rc_eqs2 = [connect(source2.p, resistor.p) @@ -50,4 +50,4 @@ rc_eqs2 = [connect(source2.p, resistor.p) connect(capacitor.n, source2.n)] @named rc_model2 = ODESystem(rc_eqs2, t, systems = [resistor, capacitor, source2]) -@test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(rc_model2) +@test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(rc_model2) diff --git a/test/extensions/ad.jl b/test/extensions/ad.jl index 69b14d15ec..adaf6117c6 100644 --- a/test/extensions/ad.jl +++ b/test/extensions/ad.jl @@ -46,7 +46,7 @@ end Th0 => (4 / 11)^(1 / 3) * Tγ0, Tγ0 => (15 / π^2 * ργ0 * (2 * h)^2 / 7)^(1 / 4) / 5 ]) - sys = mtkbuild(sys) + sys = structural_simplify(sys) function x_at_0(θ) prob = ODEProblem(sys, [sys.x => 1.0], (0.0, 1.0), [sys.ργ0 => θ[1], sys.h => θ[2]]) @@ -111,7 +111,7 @@ fwd, back = ChainRulesCore.rrule(remake_buffer, sys, ps, idxs, vals) eqs = [D(D(y)) ~ -9.81] initialization_eqs = [y^2 ~ 0] # initialize y = 0 in a way that builds an initialization problem @named sys = ODESystem(eqs, t; initialization_eqs) - sys = mtkbuild(sys) + sys = structural_simplify(sys) # Find initial throw velocity that reaches exactly 10 m after 1 s dprob0 = ODEProblem(sys, [D(y) => NaN], (0.0, 1.0), []; guesses = [y => 0.0]) diff --git a/test/extensions/bifurcationkit.jl b/test/extensions/bifurcationkit.jl index 101efb202b..629edf46a6 100644 --- a/test/extensions/bifurcationkit.jl +++ b/test/extensions/bifurcationkit.jl @@ -97,14 +97,14 @@ end # Checks that default parameter values are accounted for. # Checks that observables (that depend on other observables, as in this case) are accounted for. let - # Creates model, and uses `mtkbuild` to generate observables. + # Creates model, and uses `structural_simplify` to generate observables. @parameters μ p=2 @variables x(t) y(t) z(t) eqs = [0 ~ μ - x^3 + 2x^2, 0 ~ p * μ - y, 0 ~ y - z] @named nsys = NonlinearSystem(eqs, [x, y, z], [μ, p]) - nsys = mtkbuild(nsys) + nsys = structural_simplify(nsys) # Creates BifurcationProblem. bif_par = μ diff --git a/test/funcaffect.jl b/test/funcaffect.jl index e6a0d1c7f9..3004044d61 100644 --- a/test/funcaffect.jl +++ b/test/funcaffect.jl @@ -129,7 +129,7 @@ s1 = compose( ODESystem(Equation[], t, [], [], name = :s1, discrete_events = 1.0 => (affect4!, [resistor.v], [], [], ctx)), resistor) -s2 = mtkbuild(s1) +s2 = structural_simplify(s1) prob = ODEProblem(s2, [resistor.v => 10.0], (0, 2.01)) sol = solve(prob, Tsit5()) @test ctx[1] == 2 @@ -148,7 +148,7 @@ end ]) rc_model = compose(rc_model, [resistor, capacitor, source, ground]) -sys = mtkbuild(rc_model) +sys = structural_simplify(rc_model) u0 = [capacitor.v => 0.0 capacitor.p.i => 0.0 resistor.v => 0.0] @@ -187,7 +187,7 @@ rc_eqs2 = [connect(source.p, resistor.p) @named rc_model2 = ODESystem(rc_eqs2, t) rc_model2 = compose(rc_model2, [resistor, capacitor2, source, ground]) -sys2 = mtkbuild(rc_model2) +sys2 = structural_simplify(rc_model2) u0 = [capacitor2.v => 0.0 capacitor2.p.i => 0.0 resistor.v => 0.0] @@ -276,7 +276,7 @@ end [y ~ zr] => (bb_affect!, [v], [], [], nothing) ]) -bb_sys = mtkbuild(bb_model) +bb_sys = structural_simplify(bb_model) @test only(ModelingToolkit.affects(ModelingToolkit.continuous_events(bb_sys))) isa ModelingToolkit.FunctionalAffect diff --git a/test/guess_propagation.jl b/test/guess_propagation.jl index ae188ba2df..738e930adc 100644 --- a/test/guess_propagation.jl +++ b/test/guess_propagation.jl @@ -11,7 +11,7 @@ eqs = [D(x) ~ 1 initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(mtkbuild(sys)) +sys = complete(structural_simplify(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -28,7 +28,7 @@ eqs = [D(x) ~ 1 initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(mtkbuild(sys)) +sys = complete(structural_simplify(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -46,7 +46,7 @@ eqs = [D(x) ~ a] initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(mtkbuild(sys)) +sys = complete(structural_simplify(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) @@ -66,7 +66,7 @@ eqs = [D(x) ~ a, initialization_eqs = [1 ~ exp(1 + x)] @named sys = ODESystem(eqs, t; initialization_eqs) -sys = complete(mtkbuild(sys)) +sys = complete(structural_simplify(sys)) tspan = (0.0, 0.2) prob = ODEProblem(sys, [], tspan, []) diff --git a/test/hierarchical_initialization_eqs.jl b/test/hierarchical_initialization_eqs.jl index 022c5c4431..1e3109a66e 100644 --- a/test/hierarchical_initialization_eqs.jl +++ b/test/hierarchical_initialization_eqs.jl @@ -140,7 +140,7 @@ syslist = ModelingToolkit.get_systems(model) @test length(ModelingToolkit.initialization_equations(model)) == 2 u0 = [] -prob = ODEProblem(mtkbuild(model), u0, (0.0, 10.0)) +prob = ODEProblem(structural_simplify(model), u0, (0.0, 10.0)) sol = solve(prob, Rodas5P()) @test length(sol.u[end]) == 2 @test length(equations(prob.f.initializeprob.f.sys)) == 0 diff --git a/test/if_lifting.jl b/test/if_lifting.jl index b6f5ac3387..9c58e676d0 100644 --- a/test/if_lifting.jl +++ b/test/if_lifting.jl @@ -13,9 +13,9 @@ using ModelingToolkit: t_nounits as t, D_nounits as D, IfLifting, no_if_lift end end @named sys = SimpleAbs() - ss1 = mtkbuild(sys) + ss1 = structural_simplify(sys) @test length(equations(ss1)) == 1 - ss2 = mtkbuild(sys, additional_passes = [IfLifting]) + ss2 = structural_simplify(sys, additional_passes = [IfLifting]) @test length(equations(ss2)) == 1 @test length(parameters(ss2)) == 1 @test operation(only(equations(ss2)).rhs) === ifelse @@ -71,7 +71,7 @@ end end @named sys = BigModel() - ss = mtkbuild(sys, additional_passes = [IfLifting]) + ss = structural_simplify(sys, additional_passes = [IfLifting]) ps = parameters(ss) @test length(ps) == 9 diff --git a/test/initializationsystem.jl b/test/initializationsystem.jl index 2d90940983..5c36fcba3e 100644 --- a/test/initializationsystem.jl +++ b/test/initializationsystem.jl @@ -415,7 +415,7 @@ sol = solve(prob, Tsit5()) D(z) ~ x * y - β * z] @named sys = ODESystem(eqs, t) - sys = mtkbuild(sys) + sys = structural_simplify(sys) u0 = [D(x) => 2.0, x => 1.0, @@ -444,7 +444,7 @@ eqs = [D(x) ~ α * x - β * x * y z ~ x + y] @named sys = ODESystem(eqs, t) -simpsys = mtkbuild(sys) +simpsys = structural_simplify(sys) tspan = (0.0, 10.0) prob = ODEProblem(simpsys, [D(x) => 0.0, y => 0.0], tspan, guesses = [x => 0.0]) @@ -477,7 +477,7 @@ prob = ODEProblem(pend, [x => 1], (0.0, 1.5), [g => 1], guesses = [λ => 0, y => 1], initialization_eqs = [y ~ 1]) unsimp = generate_initializesystem(pend; u0map = [x => 1], initialization_eqs = [y ~ 1]) -sys = mtkbuild(unsimp; fully_determined = false) +sys = structural_simplify(unsimp; fully_determined = false) @test length(equations(sys)) in (3, 4) # could be either depending on tearing # Extend two systems with initialization equations and guesses @@ -493,7 +493,7 @@ sys = extend(sysx, sysy) @testset "Error on missing defaults" begin @variables x(t) y(t) @named sys = ODESystem([x^2 + y^2 ~ 25, D(x) ~ 1], t) - ssys = mtkbuild(sys) + ssys = structural_simplify(sys) @test_throws ModelingToolkit.MissingVariablesError ODEProblem( ssys, [x => 3], (0, 1), []) # y should have a guess end @@ -504,7 +504,7 @@ end # system 1 should solve to x = 1 ics1 = [x => 1] - sys1 = ODESystem([D(x) ~ 0], t; defaults = ics1, name = :sys1) |> mtkbuild + sys1 = ODESystem([D(x) ~ 0], t; defaults = ics1, name = :sys1) |> structural_simplify prob1 = ODEProblem(sys1, [], (0.0, 1.0), []) sol1 = solve(prob1, Tsit5()) @test all(sol1[x] .== 1) @@ -513,7 +513,7 @@ end sys2 = extend( sys1, ODESystem([D(y) ~ 0], t; initialization_eqs = [y ~ 2], name = :sys2) - ) |> mtkbuild + ) |> structural_simplify ics2 = unknowns(sys1) .=> 2 # should be equivalent to "ics2 = [x => 2]" prob2 = ODEProblem(sys2, ics2, (0.0, 1.0), []; fully_determined = true) sol2 = solve(prob2, Tsit5()) @@ -525,12 +525,12 @@ end @variables x(t) sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [x ~ 0, D(x) ~ 1], name = :sys) |> - mtkbuild + structural_simplify @test_nowarn ODEProblem(sys, [], (0.0, 1.0), []) sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [x ~ 0, D(D(x)) ~ 0], name = :sys) |> - mtkbuild + structural_simplify @test_nowarn ODEProblem(sys, [D(x) => 1.0], (0.0, 1.0), []) end @@ -541,7 +541,7 @@ end sys = ODESystem( [D(D(x)) ~ 0], t; initialization_eqs = [D(x)^2 ~ 1, x ~ 0], guesses = [D(x) => sign], name = :sys - ) |> mtkbuild + ) |> structural_simplify prob = ODEProblem(sys, [], (0.0, 1.0), []) sol = solve(prob, Tsit5()) @test sol(1.0, idxs = sys.x) ≈ sign # system with D(x(0)) = ±1 should solve to x(1) = ±1 @@ -582,7 +582,7 @@ sol = solve(oprob_2nd_order_2, Rosenbrock23()) # retcode: Success @testset "Vector in initial conditions" begin @variables x(t)[1:5] y(t)[1:5] @named sys = ODESystem([D(x) ~ x, D(y) ~ y], t; initialization_eqs = [y ~ -x]) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob = ODEProblem(sys, [sys.x => ones(5)], (0.0, 1.0), []) sol = solve(prob, Tsit5(), reltol = 1e-4) @test all(sol(1.0, idxs = sys.x) .≈ +exp(1)) && all(sol(1.0, idxs = sys.y) .≈ -exp(1)) @@ -1145,7 +1145,7 @@ end end model = dc_motor() - sys = mtkbuild(model) + sys = structural_simplify(model) prob = ODEProblem(sys, [sys.L1.i => 0.0], (0, 6.0)) @@ -1250,7 +1250,7 @@ end @parameters a = 1 @named sys = ODESystem([D(x) ~ 0, D(y) ~ x + a], t; initialization_eqs = [y ~ a]) - ssys = mtkbuild(sys) + ssys = structural_simplify(sys) prob = ODEProblem(ssys, [], (0, 1), []) @test SciMLBase.successful_retcode(solve(prob)) @@ -1355,7 +1355,7 @@ end continuous_events = [ [y ~ 0.5] => (stop!, [y], [], [], nothing) ]) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob0 = ODEProblem(sys, [x => NaN], (0.0, 1.0), []) # final_x(x0) is equivalent to x0 + 0.5 diff --git a/test/input_output_handling.jl b/test/input_output_handling.jl index 0a211de9de..693a00b9ad 100644 --- a/test/input_output_handling.jl +++ b/test/input_output_handling.jl @@ -7,10 +7,10 @@ using ModelingToolkit: t_nounits as t, D_nounits as D @variables xx(t) some_input(t) [input = true] eqs = [D(xx) ~ some_input] @named model = ODESystem(eqs, t) -@test_throws ExtraVariablesSystemException mtkbuild(model, ((), ())) +@test_throws ExtraVariablesSystemException structural_simplify(model, ((), ())) if VERSION >= v"1.8" err = "In particular, the unset input(s) are:\n some_input(t)" - @test_throws err mtkbuild(model, ((), ())) + @test_throws err structural_simplify(model, ((), ())) end # Test input handling @@ -50,7 +50,7 @@ end @test !is_bound(sys31, sys1.v[2]) # simplification turns input variables into parameters -ssys, _ = mtkbuild(sys, ([u], [])) +ssys, _ = structural_simplify(sys, ([u], [])) @test ModelingToolkit.isparameter(unbound_inputs(ssys)[]) @test !is_bound(ssys, u) @test u ∈ Set(unbound_inputs(ssys)) @@ -88,7 +88,7 @@ fsys4 = flatten(sys4) @variables x(t) y(t) [output = true] @test isoutput(y) @named sys = ODESystem([D(x) ~ -x, y ~ x], t) # both y and x are unbound -syss = mtkbuild(sys) # This makes y an observed variable +syss = structural_simplify(sys) # This makes y an observed variable @named sys2 = ODESystem([D(x) ~ -sys.x, y ~ sys.y], t, systems = [sys]) @@ -106,7 +106,7 @@ syss = mtkbuild(sys) # This makes y an observed variable @test isequal(unbound_outputs(sys2), [y]) @test isequal(bound_outputs(sys2), [sys.y]) -syss = mtkbuild(sys2) +syss = structural_simplify(sys2) @test !is_bound(syss, y) @test !is_bound(syss, x) @@ -281,7 +281,7 @@ i = findfirst(isequal(u[1]), out) @variables x(t) u(t) [input = true] eqs = [D(x) ~ u] @named sys = ODESystem(eqs, t) -@test_nowarn mtkbuild(sys, ([u], [])) +@test_nowarn structural_simplify(sys, ([u], [])) #= ## Disturbance input handling @@ -366,7 +366,7 @@ eqs = [D(y₁) ~ -k₁ * y₁ + k₃ * y₂ * y₃ + u1 @named sys = ODESystem(eqs, t) m_inputs = [u[1], u[2]] m_outputs = [y₂] -sys_simp, input_idxs = mtkbuild(sys, (; inputs = m_inputs, outputs = m_outputs)) +sys_simp, input_idxs = structural_simplify(sys, (; inputs = m_inputs, outputs = m_outputs)) @test isequal(unknowns(sys_simp), collect(x[1:2])) @test length(input_idxs) == 2 @@ -384,12 +384,12 @@ sys_simp, input_idxs = mtkbuild(sys, (; inputs = m_inputs, outputs = m_outputs)) ], t, systems = [int, gain, c, fb]) -sys = mtkbuild(model) +sys = structural_simplify(model) @test length(unknowns(sys)) == length(equations(sys)) == 1 ## Disturbance models when plant has multiple inputs using ModelingToolkit, LinearAlgebra -using ModelingToolkit: DisturbanceModel, get_iv, get_disturbance_system +using ModelingToolkit: DisturbanceModel, io_preprocessing, get_iv, get_disturbance_system using ModelingToolkitStandardLibrary.Blocks A, C = [randn(2, 2) for i in 1:2] B = [1.0 0; 0 1.0] diff --git a/test/jumpsystem.jl b/test/jumpsystem.jl index 488b9396f6..6c96055270 100644 --- a/test/jumpsystem.jl +++ b/test/jumpsystem.jl @@ -269,7 +269,7 @@ dp4 = DiscreteProblem(js4, u0, tspan) @test_nowarn jp3 = JumpProblem(js3, dp3, Direct()) @test_nowarn jp4 = JumpProblem(js4, dp4, Direct()) -# Ensure `mtkbuild` (and `@mtkbuild`) works on JumpSystem (by doing nothing) +# Ensure `structural_simplify` (and `@mtkbuild`) works on JumpSystem (by doing nothing) # Issue#2558 @parameters k @variables X(t) diff --git a/test/modelingtoolkitize.jl b/test/modelingtoolkitize.jl index 4ce25602d2..db99cc91a4 100644 --- a/test/modelingtoolkitize.jl +++ b/test/modelingtoolkitize.jl @@ -440,7 +440,7 @@ prob = NonlinearLeastSquaresProblem( NonlinearFunction(nlls!, resid_prototype = zeros(3)), u0) sys = modelingtoolkitize(prob) @test length(equations(sys)) == 3 -@test length(equations(mtkbuild(sys; fully_determined = false))) == 0 +@test length(equations(structural_simplify(sys; fully_determined = false))) == 0 @testset "`modelingtoolkitize(::SDEProblem)` sets defaults" begin function sdeg!(du, u, p, t) diff --git a/test/mtkparameters.jl b/test/mtkparameters.jl index 10bda707d2..55de0768e0 100644 --- a/test/mtkparameters.jl +++ b/test/mtkparameters.jl @@ -170,7 +170,7 @@ function level1() eqs = [D(x) ~ p1 * x - p2 * x * y D(y) ~ -p3 * y + p4 * x * y] - sys = mtkbuild(complete(ODESystem( + sys = structural_simplify(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end @@ -184,7 +184,7 @@ function level2() eqs = [D(x) ~ p1 * x - p23[1] * x * y D(y) ~ -p23[2] * y + p4 * x * y] - sys = mtkbuild(complete(ODESystem( + sys = structural_simplify(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end @@ -198,7 +198,7 @@ function level3() eqs = [D(x) ~ p1 * x - p23[1] * x * y D(y) ~ -p23[2] * y + p4 * x * y] - sys = mtkbuild(complete(ODESystem( + sys = structural_simplify(complete(ODESystem( eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))) prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys) end diff --git a/test/nonlinearsystem.jl b/test/nonlinearsystem.jl index 06f0122724..a315371141 100644 --- a/test/nonlinearsystem.jl +++ b/test/nonlinearsystem.jl @@ -121,7 +121,7 @@ using OrdinaryDiffEq D = Differential(t) @named subsys = convert_system(ODESystem, lorenz1, t) @named sys = ODESystem([D(subsys.x) ~ subsys.x + subsys.x], t, systems = [subsys]) -sys = mtkbuild(sys) +sys = structural_simplify(sys) u0 = [subsys.x => 1, subsys.z => 2.0, subsys.y => 1.0] prob = ODEProblem(sys, u0, (0, 1.0), [subsys.σ => 1, subsys.ρ => 2, subsys.β => 3]) sol = solve(prob, FBDF(), reltol = 1e-7, abstol = 1e-7) @@ -198,7 +198,7 @@ eq = [v1 ~ sin(2pi * t * h) v2 ~ i2 i1 ~ i2] @named sys = ODESystem(eq, t) -@test length(equations(mtkbuild(sys))) == 0 +@test length(equations(structural_simplify(sys))) == 0 @testset "Issue: 1504" begin @variables u[1:4] @@ -257,7 +257,7 @@ end @named ns = NonlinearSystem(eqs, [x, y, z], []) ns = complete(ns) vs = [unknowns(ns); parameters(ns)] - ss_mtk = mtkbuild(ns) + ss_mtk = structural_simplify(ns) prob = NonlinearProblem(ss_mtk, vs .=> 1.0) sol = solve(prob) @test_nowarn sol[unknowns(ns)] @@ -277,16 +277,16 @@ sys = @test_nowarn NonlinearSystem(alg_eqs; name = :name) @parameters u3 u4 eqs = [u3 ~ u1 + u2, u4 ~ 2 * (u1 + u2), u3 + u4 ~ 3 * (u1 + u2)] @named ns = NonlinearSystem(eqs, [u1, u2], [u3, u4]) -sys = mtkbuild(ns; fully_determined = false) +sys = structural_simplify(ns; fully_determined = false) @test length(unknowns(sys)) == 1 # Conservative @variables X(t) alg_eqs = [1 ~ 2X] @named ns = NonlinearSystem(alg_eqs) -sys = mtkbuild(ns) +sys = structural_simplify(ns) @test length(equations(sys)) == 0 -sys = mtkbuild(ns; conservative = true) +sys = structural_simplify(ns; conservative = true) @test length(equations(sys)) == 1 # https://github.com/SciML/ModelingToolkit.jl/issues/2858 @@ -338,7 +338,7 @@ end -1 1/2 -1] b = [1, -2, 0] @named sys = NonlinearSystem(A * x ~ b, [x], []) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob = NonlinearProblem(sys, unknowns(sys) .=> 0.0) sol = solve(prob) @test all(sol[x] .≈ A \ b) @@ -349,8 +349,8 @@ end @parameters p @named sys = NonlinearSystem([x ~ 1, x^2 - p ~ 0]) for sys in [ - mtkbuild(sys, fully_determined = false), - mtkbuild(sys, fully_determined = false, split = false) + structural_simplify(sys, fully_determined = false), + structural_simplify(sys, fully_determined = false, split = false) ] @test length(equations(sys)) == 1 @test length(unknowns(sys)) == 0 @@ -424,7 +424,7 @@ end @test ModelingToolkit.iscomplete(nlsys) @test ModelingToolkit.is_split(nlsys) - sys3 = mtkbuild(sys) + sys3 = structural_simplify(sys) nlsys = NonlinearSystem(sys3) @test length(equations(nlsys)) == length(ModelingToolkit.observed(nlsys)) == 1 diff --git a/test/odesystem.jl b/test/odesystem.jl index 27a1a3432e..f5fef1fd6f 100644 --- a/test/odesystem.jl +++ b/test/odesystem.jl @@ -478,7 +478,7 @@ end let @variables x(t)[1:3, 1:3] @named sys = ODESystem(D.(x) .~ x, t) - @test_nowarn mtkbuild(sys) + @test_nowarn structural_simplify(sys) end # Array vars @@ -489,7 +489,7 @@ ps = @parameters p[1:3] = [1, 2, 3] eqs = [collect(D.(x) .~ x) D(y) ~ norm(collect(x)) * y - x[1]] @named sys = ODESystem(eqs, t, sts, ps) -sys = mtkbuild(sys) +sys = structural_simplify(sys) @test isequal(@nonamespace(sys.x), x) @test isequal(@nonamespace(sys.y), y) @test isequal(@nonamespace(sys.p), p) @@ -661,7 +661,7 @@ let D(x[2]) ~ -x[1] - 0.5 * x[2] + k y ~ 0.9 * x[1] + x[2]] @named sys = ODESystem(eqs, t, vcat(x, [y]), [k], defaults = Dict(x .=> 0)) - sys = mtkbuild(sys) + sys = structural_simplify(sys) u0 = [0.5, 0] du0 = 0 .* copy(u0) @@ -743,7 +743,7 @@ let 0 ~ q / C - R * F] @named sys = ODESystem(eqs, t) - @test length(equations(mtkbuild(sys))) == 2 + @test length(equations(structural_simplify(sys))) == 2 end let @@ -778,12 +778,12 @@ let @named sys1 = ODESystem(eqs, t) @named sys2 = ODESystem(eqs2, t) @named sys3 = ODESystem(eqs3, t) - ssys3 = mtkbuild(sys3) + ssys3 = structural_simplify(sys3) @named sys4 = ODESystem(eqs4, t) @test ModelingToolkit.isisomorphic(sys1, sys2) @test !ModelingToolkit.isisomorphic(sys1, sys3) - @test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call mtkbuild in isisomorphic + @test ModelingToolkit.isisomorphic(sys1, ssys3) # I don't call structural_simplify in isisomorphic @test !ModelingToolkit.isisomorphic(sys1, sys4) # 1281 @@ -801,7 +801,7 @@ let spm ~ 0 sph ~ a] @named sys = ODESystem(eqs, t, vars, pars) - @test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(sys) + @test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(sys) end # 1561 @@ -825,9 +825,9 @@ let ps = [] @named sys = ODESystem(eqs, t, u, ps) - @test_nowarn simpsys = mtkbuild(sys) + @test_nowarn simpsys = structural_simplify(sys) - sys = mtkbuild(sys) + sys = structural_simplify(sys) u0 = ModelingToolkit.missing_variable_defaults(sys) u0_expected = Pair[s => 0.0 for s in unknowns(sys)] @@ -913,7 +913,7 @@ let @named connected = ODESystem(connections, t) @named sys_con = compose(connected, sys, ctrl) - sys_simp = mtkbuild(sys_con) + sys_simp = structural_simplify(sys_con) true_eqs = [D(sys.x) ~ sys.v D(sys.v) ~ ctrl.kv * sys.v + ctrl.kx * sys.x] @test issetequal(full_equations(sys_simp), true_eqs) @@ -924,7 +924,7 @@ let @variables y(t) = 1 @parameters pp = -1 @named sys4 = ODESystem([D(x) ~ -y; D(y) ~ 1 + pp * y + x], t) - sys4s = mtkbuild(sys4) + sys4s = structural_simplify(sys4) prob = ODEProblem(sys4s, [x => 1.0, D(x) => 1.0], (0, 1.0)) @test string.(unknowns(prob.f.sys)) == ["x(t)", "y(t)"] @test string.(parameters(prob.f.sys)) == ["pp"] @@ -963,7 +963,7 @@ let @parameters pp = -1 der = Differential(t) @named sys4 = ODESystem([der(x) ~ -y; der(y) ~ 1 + pp * y + x], t) - sys4s = mtkbuild(sys4) + sys4s = structural_simplify(sys4) prob = ODEProblem(sys4s, [x => 1.0, D(x) => 1.0], (0, 1.0)) @test !isnothing(prob.f.sys) end @@ -999,7 +999,7 @@ let # Issue https://github.com/SciML/ModelingToolkit.jl/issues/2322 sys = ODESystem(eqs, t; name = :kjshdf) - sys_simp = mtkbuild(sys) + sys_simp = structural_simplify(sys) @test a ∈ keys(ModelingToolkit.defaults(sys_simp)) @@ -1140,7 +1140,7 @@ orig_vars = unknowns(sys) @named outer = ODESystem( [D(y) ~ sys.x + t, 0 ~ t + y - sys.x * y], t, [y], []; systems = [sys]) @test ModelingToolkit.guesses(outer)[sys.x] == 1.0 -outer = mtkbuild(outer) +outer = structural_simplify(outer) @test ModelingToolkit.get_guesses(outer)[sys.x] == 1.0 prob = ODEProblem(outer, [outer.y => 2.0], (0.0, 10.0)) int = init(prob, Rodas4()) @@ -1176,7 +1176,7 @@ end @testset "Non-1-indexed variable array (issue #2670)" begin @variables x(t)[0:1] # 0-indexed variable array @named sys = ODESystem([x[0] ~ 0.0, D(x[1]) ~ x[0]], t, [x], []) - @test_nowarn sys = mtkbuild(sys) + @test_nowarn sys = structural_simplify(sys) @test equations(sys) == [D(x[1]) ~ 0.0] end @@ -1190,7 +1190,7 @@ end @testset "ForwardDiff through ODEProblem constructor" begin @parameters P @variables x(t) - sys = mtkbuild(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) + sys = structural_simplify(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) function x_at_1(P) prob = ODEProblem(sys, [x => P], (0.0, 1.0), [sys.P => P]) @@ -1203,7 +1203,7 @@ end @testset "Inplace observed functions" begin @parameters P @variables x(t) - sys = mtkbuild(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) + sys = structural_simplify(ODESystem([D(x) ~ P], t, [x], [P]; name = :sys)) obsfn = ModelingToolkit.build_explicit_observed_function( sys, [x + 1, x + P, x + t], return_inplace = true)[2] ps = ModelingToolkit.MTKParameters(sys, [P => 2.0]) @@ -1240,7 +1240,7 @@ end initialization_eqs = [x ~ T] guesses = [x => 0.0] @named sys2 = ODESystem(eqs, T; initialization_eqs, guesses) - prob2 = ODEProblem(mtkbuild(sys2), [], (1.0, 2.0), []) + prob2 = ODEProblem(structural_simplify(sys2), [], (1.0, 2.0), []) sol2 = solve(prob2) @test all(sol2[x] .== 1.0) end @@ -1265,7 +1265,7 @@ end eqs = [D(x) ~ 0, y ~ x, D(z) ~ 0] defaults = [x => 1, z => y] @named sys = ODESystem(eqs, t; defaults) - ssys = mtkbuild(sys) + ssys = structural_simplify(sys) prob = ODEProblem(ssys, [], (0.0, 1.0), []) @test prob[x] == prob[y] == prob[z] == 1.0 @@ -1274,7 +1274,7 @@ end eqs = [D(x) ~ 0, y ~ y0 / x, D(z) ~ y] defaults = [y0 => 1, x => 1, z => y] @named sys = ODESystem(eqs, t; defaults) - ssys = mtkbuild(sys) + ssys = structural_simplify(sys) prob = ODEProblem(ssys, [], (0.0, 1.0), []) @test prob[x] == prob[y] == prob[z] == 1.0 end @@ -1285,11 +1285,11 @@ end @named sys = ODESystem( [D(u) ~ (sum(u) + sum(x) + sum(p) + sum(o)) * x, o ~ prod(u) * x], t, [u..., x..., o...], [p...]) - sys1, = mtkbuild(sys, ([x...], [])) + sys1, = structural_simplify(sys, ([x...], [])) fn1, = ModelingToolkit.generate_function(sys1; expression = Val{false}) ps = MTKParameters(sys1, [x => 2ones(2), p => 3ones(2, 2)]) @test_nowarn fn1(ones(4), ps, 4.0) - sys2, = mtkbuild(sys, ([x...], []); split = false) + sys2, = structural_simplify(sys, ([x...], []); split = false) fn2, = ModelingToolkit.generate_function(sys2; expression = Val{false}) ps = zeros(8) setp(sys2, x)(ps, 2ones(2)) @@ -1373,10 +1373,10 @@ end @named outersys = ODESystem( [D(innersys.y) ~ innersys.y + p4], t; parameter_dependencies = [p4 ~ 3p3], defaults = [p3 => 3.0, p4 => 9.0], guesses = [p4 => 10.0], systems = [innersys]) - @test_nowarn mtkbuild(outersys) + @test_nowarn structural_simplify(outersys) @parameters p5 sys2 = substitute(outersys, [p4 => p5]) - @test_nowarn mtkbuild(sys2) + @test_nowarn structural_simplify(sys2) @test length(equations(sys2)) == 2 @test length(parameters(sys2)) == 2 @test length(full_parameters(sys2)) == 4 @@ -1398,7 +1398,7 @@ end o[2] ~ sum(p) * sum(x)] @named sys = ODESystem(eqs, t, [u..., x..., o], [p...]) - sys1, = mtkbuild(sys, ([x...], [o...]), split = false) + sys1, = structural_simplify(sys, ([x...], [o...]), split = false) @test_nowarn ModelingToolkit.build_explicit_observed_function(sys1, u; inputs = [x...]) @@ -1436,7 +1436,7 @@ end @test_nowarn ODEProblem(sys, [], (0.0, 1.0)) else @test_throws [ - r"array (equations|unknowns)", "mtkbuild", "scalarize"] ODEProblem( + r"array (equations|unknowns)", "structural_simplify", "scalarize"] ODEProblem( sys, [], (0.0, 1.0)) end end @@ -1449,7 +1449,7 @@ end @test_nowarn ODEProblem(sys, [], (0.0, 1.0)) else @test_throws [ - r"array (equations|unknowns)", "mtkbuild", "scalarize"] ODEProblem( + r"array (equations|unknowns)", "structural_simplify", "scalarize"] ODEProblem( sys, [], (0.0, 1.0)) end end @@ -1632,7 +1632,7 @@ end @test lowered_vars == expected_vars end -@testset "dae_order_lowering test with mtkbuild" begin +@testset "dae_order_lowering test with structural_simplify" begin @variables x(t) y(t) z(t) @parameters M b k eqs = [ @@ -1647,7 +1647,7 @@ end default_p = [M => 1.0, b => 1.0, k => 1.0] @named dae_sys = ODESystem(eqs, t, [x, y, z], ps; defaults = [default_u0; default_p]) - simplified_dae_sys = mtkbuild(dae_sys) + simplified_dae_sys = structural_simplify(dae_sys) lowered_dae_sys = dae_order_lowering(simplified_dae_sys) lowered_dae_sys = complete(lowered_dae_sys) diff --git a/test/optimizationsystem.jl b/test/optimizationsystem.jl index 9d6053a45b..2ec9516721 100644 --- a/test/optimizationsystem.jl +++ b/test/optimizationsystem.jl @@ -85,7 +85,7 @@ end z ~ y - x^2 z^2 + y^2 ≲ 1.0] @named sys = OptimizationSystem(loss, [x, y, z], [a, b], constraints = cons) - sys = mtkbuild(sys) + sys = structural_simplify(sys) prob = OptimizationProblem(sys, [x => 0.0, y => 0.0, z => 0.0], [a => 1.0, b => 1.0], grad = true, hess = true, cons_j = true, cons_h = true) sol = solve(prob, IPNewton()) diff --git a/test/parameter_dependencies.jl b/test/parameter_dependencies.jl index beffacc83f..31881e1ca8 100644 --- a/test/parameter_dependencies.jl +++ b/test/parameter_dependencies.jl @@ -170,7 +170,7 @@ end # (https://github.com/SciML/ModelingToolkit.jl/pull/2978) @inferred ModelingToolkit.parameter_dependencies(sys1) - sys = mtkbuild(sys1) + sys = structural_simplify(sys1) prob = ODEProblem(sys, [], (0.0, 1.0)) sol = solve(prob) @@ -192,7 +192,7 @@ end eqs = [D(y) ~ i(t) + p] @named model = ODESystem(eqs, t, [y], [p, i]; parameter_dependencies = [i ~ CallableFoo(p)]) - sys = mtkbuild(model) + sys = structural_simplify(model) prob = ODEProblem(sys, [], (0.0, 1.0)) sol = solve(prob, Tsit5()) diff --git a/test/reduction.jl b/test/reduction.jl index 1f0028fc6e..fa9029a652 100644 --- a/test/reduction.jl +++ b/test/reduction.jl @@ -30,7 +30,7 @@ eqs = [D(x) ~ σ * (y - x) lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_aliased = mtkbuild(lorenz1) +lorenz1_aliased = structural_simplify(lorenz1) io = IOBuffer(); show(io, MIME("text/plain"), lorenz1_aliased); str = String(take!(io)); @@ -74,8 +74,8 @@ __x = x # Reduced Flattened System -reduced_system = mtkbuild(connected) -reduced_system2 = mtkbuild(tearing_substitution(mtkbuild(tearing_substitution(mtkbuild(connected))))) +reduced_system = structural_simplify(connected) +reduced_system2 = structural_simplify(tearing_substitution(structural_simplify(tearing_substitution(structural_simplify(connected))))) @test isempty(setdiff(unknowns(reduced_system), unknowns(reduced_system2))) @test isequal(equations(tearing_substitution(reduced_system)), equations(reduced_system2)) @@ -133,7 +133,7 @@ let pc.y_c ~ ol.y] @named connected = ODESystem(connections, t, systems = [ol, pc]) @test equations(connected) isa Vector{Equation} - reduced_sys = mtkbuild(connected) + reduced_sys = structural_simplify(connected) ref_eqs = [D(ol.x) ~ ol.a * ol.x + ol.b * ol.u 0 ~ pc.k_P * ol.y - ol.u] #@test ref_eqs == equations(reduced_sys) @@ -144,7 +144,7 @@ let @variables x(t) @named sys = ODESystem([0 ~ D(x) + x], t, [x], []) #@test_throws ModelingToolkit.InvalidSystemException ODEProblem(sys, [1.0], (0, 10.0)) - sys = mtkbuild(sys) + sys = structural_simplify(sys) #@test_nowarn ODEProblem(sys, [1.0], (0, 10.0)) end @@ -155,7 +155,7 @@ eqs = [u1 ~ u2 u3 ~ u1 + u2 + p u3 ~ hypot(u1, u2) * p] @named sys = NonlinearSystem(eqs, [u1, u2, u3], [p]) -reducedsys = mtkbuild(sys) +reducedsys = structural_simplify(sys) @test length(observed(reducedsys)) == 2 u0 = [u2 => 1] @@ -175,7 +175,7 @@ N = 5 A = reshape(1:(N^2), N, N) eqs = xs ~ A * xs @named sys′ = NonlinearSystem(eqs, [xs], []) -sys = mtkbuild(sys′) +sys = structural_simplify(sys′) @test length(equations(sys)) == 3 && length(observed(sys)) == 2 # issue 958 @@ -189,7 +189,7 @@ eqs = [D(E) ~ k₋₁ * C - k₁ * E * S E₀ ~ E + C] @named sys = ODESystem(eqs, t, [E, C, S, P], [k₁, k₂, k₋₁, E₀]) -@test_throws ModelingToolkit.ExtraEquationsSystemException mtkbuild(sys) +@test_throws ModelingToolkit.ExtraEquationsSystemException structural_simplify(sys) # Example 5 from Pantelides' original paper params = collect(@parameters y1(t) y2(t)) @@ -198,7 +198,7 @@ eqs = [0 ~ x + sin(u1 + u2) D(x) ~ x + y1 cos(x) ~ sin(y2)] @named sys = ODESystem(eqs, t, sts, params) -@test_throws ModelingToolkit.InvalidSystemException mtkbuild(sys) +@test_throws ModelingToolkit.InvalidSystemException structural_simplify(sys) # issue #963 @variables v47(t) v57(t) v66(t) v25(t) i74(t) i75(t) i64(t) i71(t) v1(t) v2(t) @@ -215,7 +215,7 @@ eq = [v47 ~ v1 0 ~ i64 + i71] @named sys0 = ODESystem(eq, t) -sys = mtkbuild(sys0) +sys = structural_simplify(sys0) @test length(equations(sys)) == 1 eq = equations(tearing_substitution(sys))[1] vv = only(unknowns(sys)) @@ -233,7 +233,7 @@ eqs = [D(x) ~ σ * (y - x) u ~ z + a] lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_reduced, _ = mtkbuild(lorenz1, ([z], [])) +lorenz1_reduced, _ = structural_simplify(lorenz1, ([z], [])) @test z in Set(parameters(lorenz1_reduced)) # #2064 @@ -242,7 +242,7 @@ eqs = [D(x) ~ x D(y) ~ y D(z) ~ t] @named model = ODESystem(eqs, t) -sys = mtkbuild(model) +sys = structural_simplify(model) Js = ModelingToolkit.jacobian_sparsity(sys) @test size(Js) == (3, 3) @test Js == Diagonal([1, 1, 0]) @@ -275,7 +275,7 @@ new_sys = alias_elimination(sys) eqs = [x ~ 0 D(x) ~ x + y] @named sys = ODESystem(eqs, t, [x, y], []) -ss = mtkbuild(sys) +ss = structural_simplify(sys) @test isempty(equations(ss)) @test sort(string.(observed(ss))) == ["x(t) ~ 0.0" "xˍt(t) ~ 0.0" @@ -285,5 +285,5 @@ eqs = [D(D(x)) ~ -x] @named sys = ODESystem(eqs, t, [x], []) ss = alias_elimination(sys) @test length(equations(ss)) == length(unknowns(ss)) == 1 -ss = mtkbuild(sys) +ss = structural_simplify(sys) @test length(equations(ss)) == length(unknowns(ss)) == 2 diff --git a/test/scc_nonlinear_problem.jl b/test/scc_nonlinear_problem.jl index ecd5af5f8a..b2b326d090 100644 --- a/test/scc_nonlinear_problem.jl +++ b/test/scc_nonlinear_problem.jl @@ -22,9 +22,9 @@ using ModelingToolkit: t_nounits as t, D_nounits as D eqs = 0 .~ eqs @named model = NonlinearSystem(eqs) @test_throws ["simplified", "required"] SCCNonlinearProblem(model, []) - _model = mtkbuild(model; split = false) + _model = structural_simplify(model; split = false) @test_throws ["not compatible"] SCCNonlinearProblem(_model, []) - model = mtkbuild(model) + model = structural_simplify(model) prob = NonlinearProblem(model, [u => zeros(8)]) sccprob = SCCNonlinearProblem(model, [u => zeros(8)]) sol1 = solve(prob, NewtonRaphson()) diff --git a/test/sciml_problem_inputs.jl b/test/sciml_problem_inputs.jl index 671cf8832e..bfa560cda3 100644 --- a/test/sciml_problem_inputs.jl +++ b/test/sciml_problem_inputs.jl @@ -37,7 +37,7 @@ begin MassActionJump(k2, [Z => 1], [Y => 1, Z => -1]) ] - # Create systems (without mtkbuild, since that might modify systems to affect intended tests). + # Create systems (without structural_simplify, since that might modify systems to affect intended tests). osys = complete(ODESystem(diff_eqs, t; name = :osys)) ssys = complete(SDESystem( diff_eqs, noise_eqs, t, [X, Y, Z], [kp, kd, k1, k2]; name = :ssys)) diff --git a/test/sdesystem.jl b/test/sdesystem.jl index 05d424efba..b031a2f5ab 100644 --- a/test/sdesystem.jl +++ b/test/sdesystem.jl @@ -596,7 +596,7 @@ eqs = [D(x) ~ σ * (y - x) + x * β, D(y) ~ x * (ρ - z) - y + y * β + x * η, D(z) ~ x * y - β * z + (x * z) * β] @named sys1 = System(eqs, tt) -sys1 = mtkbuild(sys1) +sys1 = structural_simplify(sys1) drift_eqs = [D(x) ~ σ * (y - x), D(y) ~ x * (ρ - z) - y, @@ -794,13 +794,13 @@ end input ~ 0.0] sys = System(eqs, t, sts, ps; name = :name) - sys = mtkbuild(sys) + sys = structural_simplify(sys) @test ModelingToolkit.get_noiseeqs(sys) ≈ [1.0] prob = SDEProblem(sys, [], (0.0, 1.0), []) @test_nowarn solve(prob, RKMil()) end -@testset "Observed variables retained after `mtkbuild`" begin +@testset "Observed variables retained after `structural_simplify`" begin @variables x(t) y(t) z(t) @brownian a @mtkbuild sys = System([D(x) ~ x + a, D(y) ~ y + a, z ~ x + y], t) @@ -859,7 +859,7 @@ end end end -@testset "`mtkbuild(::SDESystem)`" begin +@testset "`structural_simplify(::SDESystem)`" begin @variables x(t) y(t) @mtkbuild sys = SDESystem( [D(x) ~ x, y ~ 2x], [x, 0], t, [x, y], []; is_scalar_noise = true) @@ -947,7 +947,7 @@ end @test ssys1 !== ssys2 end -@testset "Error when constructing SDESystem without `mtkbuild`" begin +@testset "Error when constructing SDESystem without `structural_simplify`" begin @parameters σ ρ β @variables x(tt) y(tt) z(tt) @brownian a @@ -961,8 +961,8 @@ end u0map = [x => 1.0, y => 0.0, z => 0.0] parammap = [σ => 10.0, β => 26.0, ρ => 2.33] - @test_throws ErrorException("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `mtkbuild` before a SDEProblem can be constructed.") SDEProblem( + @test_throws ErrorException("SDESystem constructed by defining Brownian variables with @brownian must be simplified by calling `structural_simplify` before a SDEProblem can be constructed.") SDEProblem( de, u0map, (0.0, 100.0), parammap) - de = mtkbuild(de) + de = structural_simplify(de) @test SDEProblem(de, u0map, (0.0, 100.0), parammap) isa SDEProblem end diff --git a/test/split_parameters.jl b/test/split_parameters.jl index 74286e2843..18fdb49a48 100644 --- a/test/split_parameters.jl +++ b/test/split_parameters.jl @@ -82,7 +82,7 @@ eqs = [y ~ src.output.u @named sys = ODESystem(eqs, t, vars, []; systems = [int, src]) s = complete(sys) -sys = mtkbuild(sys) +sys = structural_simplify(sys) prob = ODEProblem( sys, [], (0.0, t_end), [s.src.interpolator => Interpolator(x, dt)]; tofloat = false) @@ -108,7 +108,7 @@ eqs = [D(y) ~ dy * a ddy ~ sin(t) * c] @named model = ODESystem(eqs, t, vars, pars) -sys = mtkbuild(model; split = false) +sys = structural_simplify(model; split = false) tspan = (0.0, t_end) prob = ODEProblem(sys, [], tspan, []; build_initializeprob = false) diff --git a/test/state_selection.jl b/test/state_selection.jl index f0b5a89e59..a8d3e57773 100644 --- a/test/state_selection.jl +++ b/test/state_selection.jl @@ -118,7 +118,7 @@ let @named system = System(L = 10) @unpack supply_pipe, return_pipe = system - sys = mtkbuild(system) + sys = structural_simplify(system) u0 = [ sys.supply_pipe.v => 0.1, sys.return_pipe.v => 0.1, D(supply_pipe.v) => 0.0, D(return_pipe.fluid_port_a.m) => 0.0, @@ -169,7 +169,7 @@ let @named trans = ODESystem(eqs, t) - sys = mtkbuild(trans) + sys = structural_simplify(trans) n = 3 u = 0 * ones(n) @@ -274,7 +274,7 @@ let # solution ------------------------------------------------------------------- @named catapult = ODESystem(eqs, t, vars, params, defaults = defs) - sys = mtkbuild(catapult) + sys = structural_simplify(catapult) prob = ODEProblem(sys, [], (0.0, 0.1), [l_2f => 0.55, damp => 1e7]; jac = true) @test solve(prob, Rodas4()).retcode == ReturnCode.Success end diff --git a/test/static_arrays.jl b/test/static_arrays.jl index e7807694a4..61177e5ab2 100644 --- a/test/static_arrays.jl +++ b/test/static_arrays.jl @@ -9,7 +9,7 @@ eqs = [D(D(x)) ~ σ * (y - x), D(z) ~ x * y - β * z] @named sys = ODESystem(eqs, t) -sys = mtkbuild(sys) +sys = structural_simplify(sys) u0 = @SVector [D(x) => 2.0, x => 1.0, diff --git a/test/stream_connectors.jl b/test/stream_connectors.jl index e76a9fa4b4..834ebce1a7 100644 --- a/test/stream_connectors.jl +++ b/test/stream_connectors.jl @@ -134,7 +134,7 @@ eqns = [domain_connect(fluid, n1m1.port_a) @named n1m1Test = ODESystem(eqns, t, [], []; systems = [fluid, n1m1, pipe, sink]) -@test_nowarn mtkbuild(n1m1Test) +@test_nowarn structural_simplify(n1m1Test) @unpack source, port_a = n1m1 ssort(eqs) = sort(eqs, by = string) @test ssort(equations(expand_connections(n1m1))) == ssort([0 ~ port_a.m_flow @@ -205,7 +205,7 @@ eqns = [connect(n1m2.port_a, sink1.port) @named sys = ODESystem(eqns, t) @named n1m2Test = compose(sys, n1m2, sink1, sink2) -@test_nowarn mtkbuild(n1m2Test) +@test_nowarn structural_simplify(n1m2Test) @named n1m2 = N1M2() @named pipe1 = AdiabaticStraightPipe() @@ -220,7 +220,7 @@ eqns = [connect(n1m2.port_a, pipe1.port_a) @named sys = ODESystem(eqns, t) @named n1m2AltTest = compose(sys, n1m2, pipe1, pipe2, sink1, sink2) -@test_nowarn mtkbuild(n1m2AltTest) +@test_nowarn structural_simplify(n1m2AltTest) # N2M2 model and test code. function N2M2(; name, @@ -249,7 +249,7 @@ eqns = [connect(source.port, n2m2.port_a) @named sys = ODESystem(eqns, t) @named n2m2Test = compose(sys, n2m2, source, sink) -@test_nowarn mtkbuild(n2m2Test) +@test_nowarn structural_simplify(n2m2Test) # stream var @named sp1 = TwoPhaseFluidPort() @@ -472,7 +472,7 @@ csys = complete(two_fluid_system) @test Symbol(sys_defs[csys.volume_a.H.rho]) == Symbol(csys.fluid_a.rho) @test Symbol(sys_defs[csys.volume_b.H.rho]) == Symbol(csys.fluid_b.rho) -@test_nowarn mtkbuild(two_fluid_system) +@test_nowarn structural_simplify(two_fluid_system) function OneFluidSystem(; name) pars = [] @@ -510,4 +510,4 @@ csys = complete(one_fluid_system) @test Symbol(sys_defs[csys.volume_a.H.rho]) == Symbol(csys.fluid.rho) @test Symbol(sys_defs[csys.volume_b.H.rho]) == Symbol(csys.fluid.rho) -@test_nowarn mtkbuild(one_fluid_system) +@test_nowarn structural_simplify(one_fluid_system) diff --git a/test/structural_transformation/index_reduction.jl b/test/structural_transformation/index_reduction.jl index a3634e7a28..f9d6037022 100644 --- a/test/structural_transformation/index_reduction.jl +++ b/test/structural_transformation/index_reduction.jl @@ -133,7 +133,7 @@ let pss_pendulum = partial_state_selection(pendulum) @test_broken length(equations(pss_pendulum)) == 3 end -let sys = mtkbuild(pendulum2) +let sys = structural_simplify(pendulum2) @test length(equations(sys)) == 5 @test length(unknowns(sys)) == 5 @@ -160,7 +160,7 @@ let D(D(y)) ~ λ * y - g x^2 + y^2 ~ 1] @named pend = ODESystem(eqs, t) - sys = complete(mtkbuild(pend; dummy_derivative = false)) + sys = complete(structural_simplify(pend; dummy_derivative = false)) prob = ODEProblem( sys, [x => 1, y => 0, D(x) => 0.0], (0.0, 10.0), [g => 1], guesses = [λ => 0.0]) sol = solve(prob, Rodas5P()) diff --git a/test/structural_transformation/tearing.jl b/test/structural_transformation/tearing.jl index 9e83c117e7..e9cd92ec94 100644 --- a/test/structural_transformation/tearing.jl +++ b/test/structural_transformation/tearing.jl @@ -148,7 +148,7 @@ eqs = [D(x) ~ z * h 0 ~ x - y 0 ~ sin(z) + y - p * t] @named daesys = ODESystem(eqs, t) -newdaesys = mtkbuild(daesys) +newdaesys = structural_simplify(daesys) @test equations(newdaesys) == [D(x) ~ z; 0 ~ y + sin(z) - p * t] @test equations(tearing_substitution(newdaesys)) == [D(x) ~ z; 0 ~ x + sin(z) - p * t] @test isequal(unknowns(newdaesys), [x, z]) @@ -165,7 +165,7 @@ prob.f(du, u, pr, tt) # test the initial guess is respected @named sys = ODESystem(eqs, t, defaults = Dict(z => NaN)) -infprob = ODEProblem(mtkbuild(sys), [x => 1.0], (0, 1.0), [p => 0.2]) +infprob = ODEProblem(structural_simplify(sys), [x => 1.0], (0, 1.0), [p => 0.2]) infprob.f(du, infprob.u0, pr, tt) @test any(isnan, du) @@ -196,7 +196,7 @@ calculate_tgrad(ms_model) u0 = [mass.s => 0.0 mass.v => 1.0] -sys = mtkbuild(ms_model) +sys = structural_simplify(ms_model) @test ModelingToolkit.get_jac(sys)[] === ModelingToolkit.EMPTY_JAC @test ModelingToolkit.get_tgrad(sys)[] === ModelingToolkit.EMPTY_TGRAD prob_complex = ODEProblem(sys, u0, (0, 1.0)) diff --git a/test/structural_transformation/utils.jl b/test/structural_transformation/utils.jl index 347756caba..b5335ad6b1 100644 --- a/test/structural_transformation/utils.jl +++ b/test/structural_transformation/utils.jl @@ -122,14 +122,14 @@ end @named sys = ODESystem( [D(x) ~ z[1] + z[2] + foo(z)[1], y[1] ~ 2t, y[2] ~ 3t, z ~ foo(y)], t) - sys1 = mtkbuild(sys; cse_hack = false) + sys1 = structural_simplify(sys; cse_hack = false) @test length(observed(sys1)) == 6 @test !any(observed(sys1)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.getindex_wrapper end - sys2 = mtkbuild(sys; array_hack = false) + sys2 = structural_simplify(sys; array_hack = false) @test length(observed(sys2)) == 5 @test !any(observed(sys2)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.change_origin @@ -143,14 +143,14 @@ end @named sys = ODESystem( [D(x) ~ z[1] + z[2] + foo(z)[1] + w, y[1] ~ 2t, y[2] ~ 3t, z ~ foo(y)], t) - sys1 = mtkbuild(sys; cse_hack = false, fully_determined = false) + sys1 = structural_simplify(sys; cse_hack = false, fully_determined = false) @test length(observed(sys1)) == 6 @test !any(observed(sys1)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.getindex_wrapper end - sys2 = mtkbuild(sys; array_hack = false, fully_determined = false) + sys2 = structural_simplify(sys; array_hack = false, fully_determined = false) @test length(observed(sys2)) == 5 @test !any(observed(sys2)) do eq iscall(eq.rhs) && operation(eq.rhs) == StructuralTransformations.change_origin @@ -163,7 +163,7 @@ end @named sys = ODESystem([D(x) ~ x, y ~ x + t], t) value = Ref(0) pass(sys; kwargs...) = (value[] += 1; return sys) - mtkbuild(sys; additional_passes = [pass]) + structural_simplify(sys; additional_passes = [pass]) @test value[] == 1 end diff --git a/test/substitute_component.jl b/test/substitute_component.jl index ad458d34cd..9fb254136b 100644 --- a/test/substitute_component.jl +++ b/test/substitute_component.jl @@ -59,8 +59,8 @@ end @named reference = RC() - sys1 = mtkbuild(rcsys) - sys2 = mtkbuild(reference) + sys1 = structural_simplify(rcsys) + sys2 = structural_simplify(reference) @test isequal(unknowns(sys1), unknowns(sys2)) @test isequal(equations(sys1), equations(sys2)) diff --git a/test/symbolic_events.jl b/test/symbolic_events.jl index cc576ce0be..9099d32d14 100644 --- a/test/symbolic_events.jl +++ b/test/symbolic_events.jl @@ -445,7 +445,7 @@ affect = [v ~ -v] @test getfield(ball, :continuous_events)[] == SymbolicContinuousCallback(Equation[x ~ 0], Equation[v ~ -v]) -ball = mtkbuild(ball) +ball = structural_simplify(ball) @test length(ModelingToolkit.continuous_events(ball)) == 1 @@ -468,8 +468,8 @@ continuous_events = [[x ~ 0] => [vx ~ -vx] D(vy) ~ -0.01vy], t; continuous_events) _ball = ball -ball = mtkbuild(_ball) -ball_nosplit = mtkbuild(_ball; split = false) +ball = structural_simplify(_ball) +ball_nosplit = structural_simplify(_ball; split = false) tspan = (0.0, 5.0) prob = ODEProblem(ball, Pair[], tspan) @@ -511,8 +511,8 @@ continuous_events = [ D(vx) ~ -1 D(vy) ~ 0], t; continuous_events) -ball_nosplit = mtkbuild(ball) -ball = mtkbuild(ball) +ball_nosplit = structural_simplify(ball) +ball = structural_simplify(ball) tspan = (0.0, 5.0) prob = ODEProblem(ball, Pair[], tspan) @@ -537,7 +537,7 @@ eq = [vs ~ sin(2pi * t) D(vmeasured) ~ 0.0] ev = [sin(20pi * t) ~ 0.0] => [vmeasured ~ v] @named sys = ODESystem(eq, t, continuous_events = ev) -sys = mtkbuild(sys) +sys = structural_simplify(sys) prob = ODEProblem(sys, zeros(2), (0.0, 5.1)) sol = solve(prob, Tsit5()) @test all(minimum((0:0.05:5) .- sol.t', dims = 2) .< 0.0001) # test that the solver stepped every 0.05s as dictated by event @@ -584,7 +584,7 @@ function Model(u, d = 0) @named model = compose(_model, mass1, mass2, sd) end model = Model(sin(30t)) -sys = mtkbuild(model) +sys = structural_simplify(model) @test isempty(ModelingToolkit.continuous_events(sys)) let @@ -823,7 +823,7 @@ let eqs = [oscce.F ~ 0] @named eqs_sys = ODESystem(eqs, t) @named oneosc_ce = compose(eqs_sys, oscce) - oneosc_ce_simpl = mtkbuild(oneosc_ce) + oneosc_ce_simpl = structural_simplify(oneosc_ce) prob = ODEProblem(oneosc_ce_simpl, [], (0.0, 2.0), []) sol = solve(prob, Tsit5(), saveat = 0.1) @@ -845,7 +845,7 @@ end evt2 = ModelingToolkit.SymbolicContinuousCallback( [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) required_crossings_c1 = [π / 2, 3 * π / 2] @@ -867,7 +867,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = (record_crossings, [c2 => :v], [], [], cr2n)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) c1_pc = filter((<=)(0) ∘ sin, required_crossings_c1) @@ -891,7 +891,7 @@ end evt2 = ModelingToolkit.SymbolicContinuousCallback( [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = nothing) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test maximum(abs.(c1_pc .- first.(cr1p))) < 1e-5 @@ -910,7 +910,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2p); affect_neg = (record_crossings, [c2 => :v], [], [], cr2n)) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) c1_pc = filter((<=)(0) ∘ sin, required_crossings_c1) @@ -934,7 +934,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5(); dtmax = 0.01) required_crossings_c1 = [π / 2, 3 * π / 2] @@ -954,7 +954,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt1, evt2]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) @test maximum(abs.(first.(cr1) .- required_crossings_c1)) < 1e-4 @@ -972,7 +972,7 @@ end [c2 ~ 0], (record_crossings, [c2 => :v], [], [], cr2); rootfind = SciMLBase.RightRootFind) @named trigsys = ODESystem(eqs, t; continuous_events = [evt2, evt1]) - trigsys_ss = mtkbuild(trigsys) + trigsys_ss = structural_simplify(trigsys) prob = ODEProblem(trigsys_ss, [], (0.0, 2π)) sol = solve(prob, Tsit5()) @test maximum(abs.(first.(cr1) .- required_crossings_c1)) < 1e-4 @@ -1102,7 +1102,7 @@ end end) @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_off, furnace_enable]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test all(sol[temp][sol.t .> 1.0] .<= 0.79) && all(sol[temp][sol.t .> 1.0] .>= 0.49) @@ -1122,7 +1122,7 @@ end end) @named sys = ODESystem( eqs, t, [temp], params; continuous_events = [furnace_off, furnace_enable]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) prob = ODEProblem(ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test all(sol[temp][sol.t .> 1.0] .<= 0.79) && all(sol[temp][sol.t .> 1.0] .>= 0.49) @@ -1143,7 +1143,7 @@ end @set! x.furnace_on = false end) @named sys = ODESystem(eqs, t, [temp], params; continuous_events = [furnace_off]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) @test_logs (:warn, "The symbols Any[:furnace_on] are declared as both observed and modified; this is a code smell because it becomes easy to confuse them and assign/not assign a value.") prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1160,7 +1160,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) @test_throws "refers to missing variable(s)" prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1173,7 +1173,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) @test_throws "refers to missing variable(s)" prob=ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @@ -1185,7 +1185,7 @@ end end) @named sys = ODESystem( eqs, t, [temp, tempsq], params; continuous_events = [furnace_off]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) prob = ODEProblem( ss, [temp => 0.0, furnace_on => true], (0.0, 100.0)) @test_throws "Tried to write back to" solve(prob, Tsit5()) @@ -1245,7 +1245,7 @@ end end; rootfind = SciMLBase.RightRootFind) @named sys = ODESystem( eqs, t, [theta, omega], params; continuous_events = [qAevt, qBevt]) - ss = mtkbuild(sys) + ss = structural_simplify(sys) prob = ODEProblem(ss, [theta => 1e-5], (0.0, pi)) sol = solve(prob, Tsit5(); dtmax = 0.01) @test getp(sol, cnt)(sol) == 198 # we get 2 pulses per phase cycle (cos 0 crossing) and we go to 100 cycles; we miss a few due to the initial state @@ -1415,13 +1415,13 @@ end @named wd1 = weird1(0.021) @named wd2 = weird2(0.021) - sys1 = mtkbuild(ODESystem([], t; name = :parent, + sys1 = structural_simplify(ODESystem([], t; name = :parent, discrete_events = [0.01 => ModelingToolkit.ImperativeAffect( modified = (; θs = reduce(vcat, [[wd1.θ]])), ctx = [1]) do m, o, c, i @set! m.θs[1] = c[] += 1 end], systems = [wd1])) - sys2 = mtkbuild(ODESystem([], t; name = :parent, + sys2 = structural_simplify(ODESystem([], t; name = :parent, discrete_events = [0.01 => ModelingToolkit.ImperativeAffect( modified = (; θs = reduce(vcat, [[wd2.θ]])), ctx = [1]) do m, o, c, i @set! m.θs[1] = c[] += 1 diff --git a/test/symbolic_indexing_interface.jl b/test/symbolic_indexing_interface.jl index 39ea2e84c2..8b3da5fd72 100644 --- a/test/symbolic_indexing_interface.jl +++ b/test/symbolic_indexing_interface.jl @@ -220,7 +220,7 @@ end @variables x(t) y(t) z(t) @parameters a @named sys = ODESystem([D(x) ~ a * x, y ~ 2x, z ~ 0.0], t) - sys = mtkbuild(sys, split = false) + sys = structural_simplify(sys, split = false) for sym in [x, y, z, x + y, x + a, y / x] @test only(get_all_timeseries_indexes(sys, sym)) == ContinuousTimeseries() end diff --git a/test/units.jl b/test/units.jl index d9a29547a9..ff0cd42ac3 100644 --- a/test/units.jl +++ b/test/units.jl @@ -140,24 +140,24 @@ D = Differential(t) eqs = [D(L) ~ v, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) eqs = [D(V) ~ r, V ~ L^3] @named sys = ODESystem(eqs, t) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) @variables V [unit = u"m"^3] L [unit = u"m"] @parameters v [unit = u"m/s"] r [unit = u"m"^3 / u"s"] t [unit = u"s"] eqs = [V ~ r * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) eqs = [L ~ v * t, V ~ L^3] @named sys = NonlinearSystem(eqs, [V, L], [t, r]) -sys_simple = mtkbuild(sys) +sys_simple = structural_simplify(sys) #Jump System @parameters β [unit = u"(mol^2*s)^-1"] γ [unit = u"(mol*s)^-1"] t [unit = u"s"] jumpmol [ diff --git a/test/variable_scope.jl b/test/variable_scope.jl index 1df75c0bf1..59647bf441 100644 --- a/test/variable_scope.jl +++ b/test/variable_scope.jl @@ -125,7 +125,7 @@ defs = ModelingToolkit.defaults(bar) sys4 = complete(sys3) @test length(unknowns(sys4)) == 3 @test length(parameters(sys4)) == 4 - sys5 = mtkbuild(sys3) + sys5 = structural_simplify(sys3) @test length(unknowns(sys5)) == 4 @test any(isequal(x4), unknowns(sys5)) @test length(parameters(sys5)) == 4 From 854846771e2e244901b41323a852eba8e501e132 Mon Sep 17 00:00:00 2001 From: vyudu Date: Tue, 22 Apr 2025 00:31:56 -0400 Subject: [PATCH 07/18] revert more renames --- src/linearization.jl | 2 +- src/systems/analysis_points.jl | 4 ---- src/systems/systems.jl | 2 +- test/downstream/linearize.jl | 4 ++-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/linearization.jl b/src/linearization.jl index eb06d142f3..242ca857d8 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -46,7 +46,7 @@ function linearization_function(sys::AbstractSystem, inputs, warn_empty_op = true, kwargs...) if !iscomplete(sys) - sys = mtkbuild(sys; inputs, outputs) + sys = structural_simplify(sys; inputs, outputs) end op = Dict(op) if isempty(op) && warn_empty_op diff --git a/src/systems/analysis_points.jl b/src/systems/analysis_points.jl index ce2e778b93..0d1a2830cf 100644 --- a/src/systems/analysis_points.jl +++ b/src/systems/analysis_points.jl @@ -596,13 +596,9 @@ Add an input without an additional output variable. PerturbOutput(ap::AnalysisPoint) = PerturbOutput(ap, false) function apply_transformation(tf::PerturbOutput, sys::AbstractSystem) - @show "ok" - @show tf.ap modify_nested_subsystem(sys, tf.ap) do ap_sys # get analysis point - @show tf.ap ap_idx = analysis_point_index(ap_sys, tf.ap) - @show ap_idx ap_idx === nothing && error("Analysis point $(nameof(tf.ap)) not found in system $(nameof(sys)).") # modified equations diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 7e47a21e75..bbf6cb17c1 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -26,7 +26,7 @@ topological sort of the observed equations in `sys`. + `fully_determined=true` controls whether or not an error will be thrown if the number of equations don't match the number of inputs, outputs, and equations. + `sort_eqs=true` controls whether equations are sorted lexicographically before simplification or not. """ -function mtkbuild( +function structural_simplify( sys::AbstractSystem; additional_passes = [], simplify = false, split = true, allow_symbolic = false, allow_parameter = true, conservative = false, fully_determined = true, inputs = Any[], outputs = Any[], diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index 40cb277236..bc675986e2 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -114,7 +114,7 @@ Nd = 10 @named pid = LimPID(; k, Ti, Td, Nd) @unpack reference, measurement, ctr_output = pid -pid = mtkbuild(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) +pid = structural_simplify(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) lsys0 = linearize(pid, [reference.u, measurement.u], [ctr_output.u]; op = Dict(reference.u => 0.0, measurement.u => 0.0)) @unpack int, der = pid @@ -185,7 +185,7 @@ function saturation(; y_max, y_min = y_max > 0 ? -y_max : -Inf, name) ODESystem(eqs, t, name = name) end @named sat = saturation(; y_max = 1) -sat = mtkbuild(sat, inputs = [u], outputs = [y]) +sat = structural_simplify(sat, inputs = [u], outputs = [y]) # inside the linear region, the function is identity @unpack u, y = sat lsys = linearize(sat, [u], [y]) From 80c19dcab1cff8caf9fe189ba353108a2e447d4d Mon Sep 17 00:00:00 2001 From: vyudu Date: Tue, 22 Apr 2025 12:51:03 -0400 Subject: [PATCH 08/18] correct tests --- src/linearization.jl | 18 ++++++------ src/systems/systems.jl | 8 +++--- test/downstream/linearize.jl | 54 +++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/linearization.jl b/src/linearization.jl index 242ca857d8..264d6b79a8 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -29,8 +29,8 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ See also [`linearize`](@ref) which provides a higher-level interface. """ -function linearization_function(sys::AbstractSystem, inputs, - outputs; +function linearization_function(sys::AbstractSystem, inputs = inputs(sys), + outputs = outputs(sys); initialize = true, initializealg = nothing, initialization_abstol = 1e-5, @@ -396,7 +396,7 @@ Construct a `LinearizationProblem` for linearizing the system `sys` with the giv All other keyword arguments are forwarded to `linearization_function`. """ -function LinearizationProblem(sys::AbstractSystem, inputs, outputs; t = 0.0, kwargs...) +function LinearizationProblem(sys::AbstractSystem, inputs = inputs(sys), outputs = outputs(sys); t = 0.0, kwargs...) linfun = linearization_function(sys, inputs, outputs; kwargs...) return LinearizationProblem(linfun, t) end @@ -484,8 +484,8 @@ y &= h(x, z, u) ``` where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. """ -function linearize_symbolic(sys::AbstractSystem, inputs, - outputs; allow_input_derivatives = false, +function linearize_symbolic(sys::AbstractSystem, inputs = inputs(sys), + outputs = outputs(sys); allow_input_derivatives = false, eval_expression = false, eval_module = @__MODULE__, kwargs...) diff_idxs, alge_idxs = eq_idxs(sys) @@ -546,7 +546,7 @@ function linearize_symbolic(sys::AbstractSystem, inputs, end end - (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys + (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u) end function markio!(state, orig_inputs, inputs, outputs; check = true) @@ -713,17 +713,17 @@ function linearize(sys, lin_fun::LinearizationFunction; t = 0.0, return solve(prob; allow_input_derivatives) end -function linearize(sys, inputs, outputs; op = Dict(), t = 0.0, +function linearize(sys, inputs = inputs(sys), outputs = outputs(sys); op = Dict(), t = 0.0, allow_input_derivatives = false, zero_dummy_der = false, kwargs...) - lin_fun, ssys = linearization_function(sys, + lin_fun = linearization_function(sys, inputs, outputs; zero_dummy_der, op, kwargs...) - linearize(ssys, lin_fun; op, t, allow_input_derivatives), ssys + linearize(sys, lin_fun; op, t, allow_input_derivatives) end """ diff --git a/src/systems/systems.jl b/src/systems/systems.jl index bbf6cb17c1..3ed8df6e99 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -33,7 +33,7 @@ function structural_simplify( disturbance_inputs = Any[], kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) - newsys′ = __structural_simplify(sys; simplify, + newsys′ = __structural_simplification(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, inputs, outputs, disturbance_inputs, kwargs...) @@ -65,12 +65,12 @@ function structural_simplify( end end -function __structural_simplify(sys::JumpSystem, args...; kwargs...) +function __structural_simplification(sys::JumpSystem, args...; kwargs...) return sys end -function __structural_simplify(sys::SDESystem, args...; kwargs...) - return __structural_simplify(ODESystem(sys), args...; kwargs...) +function __structural_simplification(sys::SDESystem, args...; kwargs...) + return __structural_simplification(ODESystem(sys), args...; kwargs...) end function __structural_simplification(sys::AbstractSystem; simplify = false, diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index bc675986e2..d51b0d17d6 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -13,18 +13,20 @@ eqs = [u ~ kp * (r - y) y ~ x] @named sys = ODESystem(eqs, t) +sys1 = structural_simplify(sys, inputs = [r], outputs = [y]) -lsys, ssys = linearize(sys, [r], [y]) -lprob = LinearizationProblem(sys, [r], [y]) +lsys = linearize(sys1) +lprob = LinearizationProblem(sys1) lsys2 = solve(lprob) -lsys3, _ = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) +lsys3 = linearize(sys1; autodiff = AutoFiniteDiff()) @test lsys.A[] == lsys2.A[] == lsys3.A[] == -2 @test lsys.B[] == lsys2.B[] == lsys3.B[] == 1 @test lsys.C[] == lsys2.C[] == lsys3.C[] == 1 @test lsys.D[] == lsys2.D[] == lsys3.D[] == 0 -lsys = linearize(sys, [r], [r]) +sys2 = structural_simplify(sys, inputs = [r], outputs = [r]) +lsys = linearize(sys2) @test lsys.A[] == -2 @test lsys.B[] == 1 @@ -86,8 +88,9 @@ connections = [f.y ~ c.r # filtered reference to controller reference p.y ~ c.y] @named cl = ODESystem(connections, t, systems = [f, c, p]) +cl = structural_simplify(cl, inputs = [f.u], outputs = [p.x]) -lsys0 = linearize(cl, [f.u], [p.x]) +lsys0 = linearize(cl) desired_order = [f.x, p.x] lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(cl), desired_order) lsys1 = linearize(cl, [f.u], [p.x]; autodiff = AutoFiniteDiff()) @@ -99,7 +102,7 @@ lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(cl), desired_order) @test lsys.D[] == lsys2.D[] == 0 ## Symbolic linearization -lsyss = ModelingToolkit.linearize_symbolic(cl, [f.u], [p.x]) +lsyss = ModelingToolkit.linearize_symbolic(cl) @test ModelingToolkit.fixpoint_sub(lsyss.A, ModelingToolkit.defaults(cl)) == lsys.A @test ModelingToolkit.fixpoint_sub(lsyss.B, ModelingToolkit.defaults(cl)) == lsys.B @@ -114,12 +117,11 @@ Nd = 10 @named pid = LimPID(; k, Ti, Td, Nd) @unpack reference, measurement, ctr_output = pid -pid = structural_simplify(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) -lsys0 = linearize(pid, [reference.u, measurement.u], [ctr_output.u]; - op = Dict(reference.u => 0.0, measurement.u => 0.0)) -@unpack int, der = pid +pid_s = structural_simplify(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) +lsys0 = linearize(pid_s; op = Dict(reference.u => 0.0, measurement.u => 0.0)) +@unpack int, der = pid_s desired_order = [int.x, der.x] -lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(pid), desired_order) +lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(pid_s), desired_order) @test lsys.A == [0 0; 0 -10] @test lsys.B == [2 -2; 10 -10] @@ -149,17 +151,17 @@ lsys = ModelingToolkit.reorder_unknowns(lsys, desired_order, reverse(desired_ord ## Test that there is a warning when input is misspecified if VERSION >= v"1.8" - @test_throws "Some parameters are missing from the variable map." linearize(pid, + @test_throws "Some specified inputs were not found in system. The following variables were not found " structural_simplify(pid, inputs = [ pid.reference.u, pid.measurement.u - ], [ctr_output.u]) - @test_throws "Some parameters are missing from the variable map." linearize(pid, - [ + ], outputs = [ctr_output.u]) + @test_throws "Some specified outputs were not found in system." structural_simplify(pid, + inputs = [ reference.u, measurement.u ], - [pid.ctr_output.u]) + outputs = [pid.ctr_output.u]) else # v1.6 does not have the feature to match error message @test_throws ErrorException linearize(pid, [ @@ -201,7 +203,7 @@ lsys = linearize(sat, [u], [y]) # @test substitute(lsyss.D, ModelingToolkit.defaults(sat)) == lsys.D # outside the linear region the derivative is 0 -lsys, ssys = linearize(sat, [u], [y]; op = Dict(u => 2)) +lsys = linearize(sat, [u], [y]; op = Dict(u => 2)) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @@ -307,12 +309,12 @@ m_ss = 2.4000000003229878 eqs = [D(x) ~ p * u, x ~ y] @named sys = ODESystem(eqs, t) -matrices1, _ = linearize(sys, [u], []; op = Dict(x => 2.0)) -matrices2, _ = linearize(sys, [u], []; op = Dict(y => 2.0)) +matrices1 = linearize(sys, [u], []; op = Dict(x => 2.0)) +matrices2 = linearize(sys, [u], []; op = Dict(y => 2.0)) @test matrices1 == matrices2 # Ensure parameter values passed as `Dict` are respected -linfun, _ = linearization_function(sys, [u], []; op = Dict(x => 2.0)) +linfun = linearization_function(sys, [u], []; op = Dict(x => 2.0)) matrices = linfun([1.0], Dict(p => 3.0), 1.0) # this would be 1 if the parameter value isn't respected @test matrices.f_u[] == 3.0 @@ -328,26 +330,28 @@ end @parameters p eqs = [0 ~ x * log(y) - p] @named sys = ODESystem(eqs, t; defaults = [p => 1.0]) - sys = complete(sys) + sys = structural_simplify(sys, inputs = [x]) @test_throws ModelingToolkit.MissingVariablesError linearize( - sys, [x], []; op = Dict(x => 1.0), allow_input_derivatives = true) + sys; op = Dict(x => 1.0), allow_input_derivatives = true) @test_nowarn linearize( - sys, [x], []; op = Dict(x => 1.0), guesses = Dict(y => 1.0), + sys; op = Dict(x => 1.0), guesses = Dict(y => 1.0), allow_input_derivatives = true) end @testset "Symbolic values for parameters in `linearize`" begin @named tank_noi = Tank_noi() @unpack md_i, h, m, ρ, A, K = tank_noi + tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize( - tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) + tank_noi; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) end @testset "Warn on empty operating point" begin @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi + tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_warn ["empty operating point", "warn_empty_op"] linearize( - tank_noi, [md_i], [h]; p = [md_i => 1.0]) + tank_noi; p = [md_i => 1.0]) end From e4774330528080d703f8cc312847cd20442a3878 Mon Sep 17 00:00:00 2001 From: vyudu Date: Tue, 22 Apr 2025 15:18:23 -0400 Subject: [PATCH 09/18] fix: require simplification again --- src/linearization.jl | 2 +- src/systems/analysis_points.jl | 9 +++++++-- src/systems/systems.jl | 4 ++++ test/downstream/linearize.jl | 7 +++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/linearization.jl b/src/linearization.jl index 264d6b79a8..097e05e79f 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -46,7 +46,7 @@ function linearization_function(sys::AbstractSystem, inputs = inputs(sys), warn_empty_op = true, kwargs...) if !iscomplete(sys) - sys = structural_simplify(sys; inputs, outputs) + error("A simplified `ODESystem` is required. Call `structural_simplify` on the system with the inputs and outputs before creating the linearization function.") end op = Dict(op) if isempty(op) && warn_empty_op diff --git a/src/systems/analysis_points.jl b/src/systems/analysis_points.jl index 0d1a2830cf..4e98592f43 100644 --- a/src/systems/analysis_points.jl +++ b/src/systems/analysis_points.jl @@ -928,8 +928,7 @@ function open_loop(sys, ap::Union{Symbol, AnalysisPoint}; system_modifier = iden return system_modifier(sys), vars end -function linearization_function(sys::AbstractSystem, - inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, +function ap_preprocessing(sys::AbstractSystem, inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, outputs; loop_openings = [], system_modifier = identity, kwargs...) loop_openings = Set(map(nameof, canonicalize_ap(sys, loop_openings))) inputs = canonicalize_ap(sys, inputs) @@ -958,7 +957,13 @@ function linearization_function(sys::AbstractSystem, end sys = handle_loop_openings(sys, map(AnalysisPoint, collect(loop_openings))) + sys, input_vars, output_vars +end +function linearization_function(sys::AbstractSystem, + inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, + outputs; loop_openings = [], system_modifier = identity, kwargs...) + sys, inputs, outputs = ap_preprocessing(sys; inputs, outputs, loop_openings, system_modifier, kwargs...) return linearization_function(system_modifier(sys), input_vars, output_vars; kwargs...) end diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 3ed8df6e99..755cb8c15f 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -33,6 +33,10 @@ function structural_simplify( disturbance_inputs = Any[], kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) + if inputs isa Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}} + sys, inputs, outputs = ap_preprocessing(sys, inputs, outputs, kwargs...) + end + newsys′ = __structural_simplification(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, inputs, outputs, disturbance_inputs, diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index d51b0d17d6..48e98b3efc 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -33,7 +33,7 @@ lsys = linearize(sys2) @test lsys.C[] == 0 @test lsys.D[] == 1 -lsys = linearize(sys, r, r) # Test allow scalars +lsys = linearize(sys2, r, r) # Test allow scalars @test lsys.A[] == -2 @test lsys.B[] == 1 @@ -270,7 +270,8 @@ closed_loop = ODESystem(connections, t, systems = [model, pid, filt, sensor, r, filt.xd => 0.0 ]) -@test_nowarn linearize(closed_loop, :r, :y; warn_empty_op = false) +closed_loop = structural_simplify(closed_loop, inputs = :r, outputs = :y) +linearize(closed_loop; warn_empty_op = false) # https://discourse.julialang.org/t/mtk-change-in-linearize/115760/3 @mtkmodel Tank_noi begin @@ -300,6 +301,7 @@ end @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi +tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize(tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2)) @@ -308,6 +310,7 @@ m_ss = 2.4000000003229878 @parameters p = 1.0 eqs = [D(x) ~ p * u, x ~ y] @named sys = ODESystem(eqs, t) +sys = structural_simplify(sys, inputs = [u]) matrices1 = linearize(sys, [u], []; op = Dict(x => 2.0)) matrices2 = linearize(sys, [u], []; op = Dict(y => 2.0)) From 85469809fe09cd6686b8618812fa8e7af20362d9 Mon Sep 17 00:00:00 2001 From: vyudu Date: Wed, 23 Apr 2025 10:49:28 -0400 Subject: [PATCH 10/18] reset test file --- test/downstream/linearize.jl | 71 ++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/test/downstream/linearize.jl b/test/downstream/linearize.jl index 48e98b3efc..16df29f834 100644 --- a/test/downstream/linearize.jl +++ b/test/downstream/linearize.jl @@ -13,27 +13,25 @@ eqs = [u ~ kp * (r - y) y ~ x] @named sys = ODESystem(eqs, t) -sys1 = structural_simplify(sys, inputs = [r], outputs = [y]) -lsys = linearize(sys1) -lprob = LinearizationProblem(sys1) +lsys, ssys = linearize(sys, [r], [y]) +lprob = LinearizationProblem(sys, [r], [y]) lsys2 = solve(lprob) -lsys3 = linearize(sys1; autodiff = AutoFiniteDiff()) +lsys3, _ = linearize(sys, [r], [y]; autodiff = AutoFiniteDiff()) @test lsys.A[] == lsys2.A[] == lsys3.A[] == -2 @test lsys.B[] == lsys2.B[] == lsys3.B[] == 1 @test lsys.C[] == lsys2.C[] == lsys3.C[] == 1 @test lsys.D[] == lsys2.D[] == lsys3.D[] == 0 -sys2 = structural_simplify(sys, inputs = [r], outputs = [r]) -lsys = linearize(sys2) +lsys, ssys = linearize(sys, [r], [r]) @test lsys.A[] == -2 @test lsys.B[] == 1 @test lsys.C[] == 0 @test lsys.D[] == 1 -lsys = linearize(sys2, r, r) # Test allow scalars +lsys, ssys = linearize(sys, r, r) # Test allow scalars @test lsys.A[] == -2 @test lsys.B[] == 1 @@ -88,13 +86,12 @@ connections = [f.y ~ c.r # filtered reference to controller reference p.y ~ c.y] @named cl = ODESystem(connections, t, systems = [f, c, p]) -cl = structural_simplify(cl, inputs = [f.u], outputs = [p.x]) -lsys0 = linearize(cl) +lsys0, ssys = linearize(cl, [f.u], [p.x]) desired_order = [f.x, p.x] -lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(cl), desired_order) -lsys1 = linearize(cl, [f.u], [p.x]; autodiff = AutoFiniteDiff()) -lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(cl), desired_order) +lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(ssys), desired_order) +lsys1, ssys = linearize(cl, [f.u], [p.x]; autodiff = AutoFiniteDiff()) +lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(ssys), desired_order) @test lsys.A == lsys2.A == [-2 0; 1 -2] @test lsys.B == lsys2.B == reshape([1, 0], 2, 1) @@ -102,7 +99,7 @@ lsys2 = ModelingToolkit.reorder_unknowns(lsys1, unknowns(cl), desired_order) @test lsys.D[] == lsys2.D[] == 0 ## Symbolic linearization -lsyss = ModelingToolkit.linearize_symbolic(cl) +lsyss, _ = ModelingToolkit.linearize_symbolic(cl, [f.u], [p.x]) @test ModelingToolkit.fixpoint_sub(lsyss.A, ModelingToolkit.defaults(cl)) == lsys.A @test ModelingToolkit.fixpoint_sub(lsyss.B, ModelingToolkit.defaults(cl)) == lsys.B @@ -117,11 +114,11 @@ Nd = 10 @named pid = LimPID(; k, Ti, Td, Nd) @unpack reference, measurement, ctr_output = pid -pid_s = structural_simplify(pid, inputs = [reference.u, measurement.u], outputs = [ctr_output.u]) -lsys0 = linearize(pid_s; op = Dict(reference.u => 0.0, measurement.u => 0.0)) -@unpack int, der = pid_s +lsys0, ssys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]; + op = Dict(reference.u => 0.0, measurement.u => 0.0)) +@unpack int, der = pid desired_order = [int.x, der.x] -lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(pid_s), desired_order) +lsys = ModelingToolkit.reorder_unknowns(lsys0, unknowns(ssys), desired_order) @test lsys.A == [0 0; 0 -10] @test lsys.B == [2 -2; 10 -10] @@ -151,17 +148,17 @@ lsys = ModelingToolkit.reorder_unknowns(lsys, desired_order, reverse(desired_ord ## Test that there is a warning when input is misspecified if VERSION >= v"1.8" - @test_throws "Some specified inputs were not found in system. The following variables were not found " structural_simplify(pid, inputs = + @test_throws "Some specified inputs were not found" linearize(pid, [ pid.reference.u, pid.measurement.u - ], outputs = [ctr_output.u]) - @test_throws "Some specified outputs were not found in system." structural_simplify(pid, - inputs = [ + ], [ctr_output.u]) + @test_throws "Some specified outputs were not found" linearize(pid, + [ reference.u, measurement.u ], - outputs = [pid.ctr_output.u]) + [pid.ctr_output.u]) else # v1.6 does not have the feature to match error message @test_throws ErrorException linearize(pid, [ @@ -187,23 +184,22 @@ function saturation(; y_max, y_min = y_max > 0 ? -y_max : -Inf, name) ODESystem(eqs, t, name = name) end @named sat = saturation(; y_max = 1) -sat = structural_simplify(sat, inputs = [u], outputs = [y]) # inside the linear region, the function is identity @unpack u, y = sat -lsys = linearize(sat, [u], [y]) +lsys, ssys = linearize(sat, [u], [y]) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @test lsys.D[] == 1 -@test_skip lsyss = ModelingToolkit.linearize_symbolic(sat, [u], [y]) # Code gen replaces ifelse with if statements causing symbolic evaluation to fail +@test_skip lsyss, _ = ModelingToolkit.linearize_symbolic(sat, [u], [y]) # Code gen replaces ifelse with if statements causing symbolic evaluation to fail # @test substitute(lsyss.A, ModelingToolkit.defaults(sat)) == lsys.A # @test substitute(lsyss.B, ModelingToolkit.defaults(sat)) == lsys.B # @test substitute(lsyss.C, ModelingToolkit.defaults(sat)) == lsys.C # @test substitute(lsyss.D, ModelingToolkit.defaults(sat)) == lsys.D # outside the linear region the derivative is 0 -lsys = linearize(sat, [u], [y]; op = Dict(u => 2)) +lsys, ssys = linearize(sat, [u], [y]; op = Dict(u => 2)) @test isempty(lsys.A) # there are no differential variables in this system @test isempty(lsys.B) @test isempty(lsys.C) @@ -270,8 +266,7 @@ closed_loop = ODESystem(connections, t, systems = [model, pid, filt, sensor, r, filt.xd => 0.0 ]) -closed_loop = structural_simplify(closed_loop, inputs = :r, outputs = :y) -linearize(closed_loop; warn_empty_op = false) +@test_nowarn linearize(closed_loop, :r, :y; warn_empty_op = false) # https://discourse.julialang.org/t/mtk-change-in-linearize/115760/3 @mtkmodel Tank_noi begin @@ -301,7 +296,6 @@ end @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi -tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize(tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2)) @@ -310,14 +304,13 @@ m_ss = 2.4000000003229878 @parameters p = 1.0 eqs = [D(x) ~ p * u, x ~ y] @named sys = ODESystem(eqs, t) -sys = structural_simplify(sys, inputs = [u]) -matrices1 = linearize(sys, [u], []; op = Dict(x => 2.0)) -matrices2 = linearize(sys, [u], []; op = Dict(y => 2.0)) +matrices1, _ = linearize(sys, [u], []; op = Dict(x => 2.0)) +matrices2, _ = linearize(sys, [u], []; op = Dict(y => 2.0)) @test matrices1 == matrices2 # Ensure parameter values passed as `Dict` are respected -linfun = linearization_function(sys, [u], []; op = Dict(x => 2.0)) +linfun, _ = linearization_function(sys, [u], []; op = Dict(x => 2.0)) matrices = linfun([1.0], Dict(p => 3.0), 1.0) # this would be 1 if the parameter value isn't respected @test matrices.f_u[] == 3.0 @@ -333,28 +326,26 @@ end @parameters p eqs = [0 ~ x * log(y) - p] @named sys = ODESystem(eqs, t; defaults = [p => 1.0]) - sys = structural_simplify(sys, inputs = [x]) + sys = complete(sys) @test_throws ModelingToolkit.MissingVariablesError linearize( - sys; op = Dict(x => 1.0), allow_input_derivatives = true) + sys, [x], []; op = Dict(x => 1.0), allow_input_derivatives = true) @test_nowarn linearize( - sys; op = Dict(x => 1.0), guesses = Dict(y => 1.0), + sys, [x], []; op = Dict(x => 1.0), guesses = Dict(y => 1.0), allow_input_derivatives = true) end @testset "Symbolic values for parameters in `linearize`" begin @named tank_noi = Tank_noi() @unpack md_i, h, m, ρ, A, K = tank_noi - tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_nowarn linearize( - tank_noi; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) + tank_noi, [md_i], [h]; op = Dict(m => m_ss, md_i => 2, ρ => A / K, A => 5)) end @testset "Warn on empty operating point" begin @named tank_noi = Tank_noi() @unpack md_i, h, m = tank_noi - tank_noi = structural_simplify(tank_noi, inputs = [md_i], outputs = [h]) m_ss = 2.4000000003229878 @test_warn ["empty operating point", "warn_empty_op"] linearize( - tank_noi; p = [md_i => 1.0]) + tank_noi, [md_i], [h]; p = [md_i => 1.0]) end From 2a688068a02f4d36d8a050bc887409e0d3c39d13 Mon Sep 17 00:00:00 2001 From: vyudu Date: Wed, 23 Apr 2025 11:07:16 -0400 Subject: [PATCH 11/18] revert src/linearization --- src/linearization.jl | 47 +++++++++++++++++++--------------- src/systems/analysis_points.jl | 10 ++------ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/linearization.jl b/src/linearization.jl index 097e05e79f..451f262476 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -1,5 +1,5 @@ """ - lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) + lin_fun, simplified_sys = linearization_function(sys::AbstractSystem, inputs, outputs; simplify = false, initialize = true, initialization_solver_alg = TrustRegion(), kwargs...) Return a function that linearizes the system `sys`. The function [`linearize`](@ref) provides a higher-level and easier to use interface. @@ -22,6 +22,7 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ - `sys`: An [`ODESystem`](@ref). This function will automatically apply simplification passes on `sys` and return the resulting `simplified_sys`. - `inputs`: A vector of variables that indicate the inputs of the linearized input-output model. - `outputs`: A vector of variables that indicate the outputs of the linearized input-output model. + - `simplify`: Apply simplification in tearing. - `initialize`: If true, a check is performed to ensure that the operating point is consistent (satisfies algebraic equations). If the op is not consistent, initialization is performed. - `initialization_solver_alg`: A NonlinearSolve algorithm to use for solving for a feasible set of state and algebraic variables that satisfies the specified operating point. - `autodiff`: An `ADType` supported by DifferentiationInterface.jl to use for calculating the necessary jacobians. Defaults to using `AutoForwardDiff()` @@ -29,8 +30,8 @@ The `simplified_sys` has undergone [`structural_simplify`](@ref) and had any occ See also [`linearize`](@ref) which provides a higher-level interface. """ -function linearization_function(sys::AbstractSystem, inputs = inputs(sys), - outputs = outputs(sys); +function linearization_function(sys::AbstractSystem, inputs, + outputs; simplify = false, initialize = true, initializealg = nothing, initialization_abstol = 1e-5, @@ -45,9 +46,6 @@ function linearization_function(sys::AbstractSystem, inputs = inputs(sys), guesses = Dict(), warn_empty_op = true, kwargs...) - if !iscomplete(sys) - error("A simplified `ODESystem` is required. Call `structural_simplify` on the system with the inputs and outputs before creating the linearization function.") - end op = Dict(op) if isempty(op) && warn_empty_op @warn "An empty operating point was passed to `linearization_function`. An operating point containing the variables that will be changed in `linearize` should be provided. Disable this warning by passing `warn_empty_op = false`." @@ -60,7 +58,15 @@ function linearization_function(sys::AbstractSystem, inputs = inputs(sys), outputs = mapreduce(vcat, outputs; init = []) do var symbolic_type(var) == ArraySymbolic() ? collect(var) : [var] end - diff_idxs, alge_idxs = eq_idxs(sys) + ssys = structural_simplify(sys; inputs, outputs, simplify, kwargs...) + diff_idxs, alge_idxs = eq_idxs(ssys) + if zero_dummy_der + dummyder = setdiff(unknowns(ssys), unknowns(sys)) + defs = Dict(x => 0.0 for x in dummyder) + @set! ssys.defaults = merge(defs, defaults(ssys)) + op = merge(defs, op) + end + sys = ssys if initializealg === nothing initializealg = initialize ? OverrideInit() : NoInit() @@ -123,7 +129,7 @@ function linearization_function(sys::AbstractSystem, inputs = inputs(sys), diff_idxs, alge_idxs, inputs, length(unknowns(sys)), prob, h, u0 === nothing ? nothing : similar(u0), uf_jac, h_jac, pf_jac, hp_jac, initializealg, initialization_kwargs) - return lin_fun + return lin_fun, sys end function eq_idxs(sys::AbstractSystem) @@ -197,7 +203,7 @@ A callable struct which linearizes a system. $(TYPEDFIELDS) """ struct LinearizationFunction{ - DI <: AbstractVector{Int}, AI <: AbstractVector{Int}, II, P <: ODEProblem, + DI <: AbstractVector{Int}, AI <: AbstractVector{Int}, I, P <: ODEProblem, H, C, J1, J2, J3, J4, IA <: SciMLBase.DAEInitializationAlgorithm, IK} """ The indexes of differential equations in the linearized system. @@ -211,7 +217,7 @@ struct LinearizationFunction{ The indexes of parameters in the linearized system which represent input variables. """ - inputs::II + inputs::I """ The number of unknowns in the linearized system. """ @@ -396,8 +402,8 @@ Construct a `LinearizationProblem` for linearizing the system `sys` with the giv All other keyword arguments are forwarded to `linearization_function`. """ -function LinearizationProblem(sys::AbstractSystem, inputs = inputs(sys), outputs = outputs(sys); t = 0.0, kwargs...) - linfun = linearization_function(sys, inputs, outputs; kwargs...) +function LinearizationProblem(sys::AbstractSystem, inputs, outputs; t = 0.0, kwargs...) + linfun, _ = linearization_function(sys, inputs, outputs; kwargs...) return LinearizationProblem(linfun, t) end @@ -467,7 +473,7 @@ function CommonSolve.solve(prob::LinearizationProblem; allow_input_derivatives = end """ - (; A, B, C, D), simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; allow_input_derivatives = false, kwargs...) + (; A, B, C, D), simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; simplify = false, allow_input_derivatives = false, kwargs...) Similar to [`linearize`](@ref), but returns symbolic matrices `A,B,C,D` rather than numeric. While `linearize` uses ForwardDiff to perform the linearization, this function uses `Symbolics.jacobian`. @@ -484,10 +490,11 @@ y &= h(x, z, u) ``` where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. """ -function linearize_symbolic(sys::AbstractSystem, inputs = inputs(sys), - outputs = outputs(sys); allow_input_derivatives = false, +function linearize_symbolic(sys::AbstractSystem, inputs, + outputs; simplify = false, allow_input_derivatives = false, eval_expression = false, eval_module = @__MODULE__, kwargs...) + sys = structural_simplify(sys; inputs, outputs, simplify, kwargs...) diff_idxs, alge_idxs = eq_idxs(sys) sts = unknowns(sys) t = get_iv(sys) @@ -546,7 +553,7 @@ function linearize_symbolic(sys::AbstractSystem, inputs = inputs(sys), end end - (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u) + (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys end function markio!(state, orig_inputs, inputs, outputs; check = true) @@ -713,17 +720,17 @@ function linearize(sys, lin_fun::LinearizationFunction; t = 0.0, return solve(prob; allow_input_derivatives) end -function linearize(sys, inputs = inputs(sys), outputs = outputs(sys); op = Dict(), t = 0.0, +function linearize(sys, inputs, outputs; op = Dict(), t = 0.0, allow_input_derivatives = false, zero_dummy_der = false, kwargs...) - lin_fun = linearization_function(sys, + lin_fun, ssys = linearization_function(sys, inputs, outputs; zero_dummy_der, op, kwargs...) - linearize(sys, lin_fun; op, t, allow_input_derivatives) + linearize(ssys, lin_fun; op, t, allow_input_derivatives), ssys end """ @@ -761,7 +768,7 @@ Permute the state representation of `sys` obtained from [`linearize`](@ref) so t Example: ``` -lsys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]) +lsys, ssys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]) desired_order = [int.x, der.x] # Unknowns that are present in unknowns(ssys) lsys = ModelingToolkit.reorder_unknowns(lsys, unknowns(ssys), desired_order) ``` diff --git a/src/systems/analysis_points.jl b/src/systems/analysis_points.jl index 4e98592f43..29f1e777ac 100644 --- a/src/systems/analysis_points.jl +++ b/src/systems/analysis_points.jl @@ -928,7 +928,8 @@ function open_loop(sys, ap::Union{Symbol, AnalysisPoint}; system_modifier = iden return system_modifier(sys), vars end -function ap_preprocessing(sys::AbstractSystem, inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, +function linearization_function(sys::AbstractSystem, + inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, outputs; loop_openings = [], system_modifier = identity, kwargs...) loop_openings = Set(map(nameof, canonicalize_ap(sys, loop_openings))) inputs = canonicalize_ap(sys, inputs) @@ -957,13 +958,6 @@ function ap_preprocessing(sys::AbstractSystem, inputs::Union{Symbol, Vector{Symb end sys = handle_loop_openings(sys, map(AnalysisPoint, collect(loop_openings))) - sys, input_vars, output_vars -end - -function linearization_function(sys::AbstractSystem, - inputs::Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}}, - outputs; loop_openings = [], system_modifier = identity, kwargs...) - sys, inputs, outputs = ap_preprocessing(sys; inputs, outputs, loop_openings, system_modifier, kwargs...) return linearization_function(system_modifier(sys), input_vars, output_vars; kwargs...) end From bd73108f5e329ad4a89c0534c1c2cb4487f10bc2 Mon Sep 17 00:00:00 2001 From: vyudu Date: Wed, 23 Apr 2025 11:10:29 -0400 Subject: [PATCH 12/18] reset doc file --- docs/src/basics/Linearization.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/src/basics/Linearization.md b/docs/src/basics/Linearization.md index 78b6d5925d..1c06ce72d4 100644 --- a/docs/src/basics/Linearization.md +++ b/docs/src/basics/Linearization.md @@ -15,7 +15,7 @@ y &= Cx + Du \end{aligned} ``` -The `linearize` function expects the user to specify the inputs ``u`` and the outputs ``y`` using the syntax shown in the example below. +The `linearize` function expects the user to specify the inputs ``u`` and the outputs ``y`` using the syntax shown in the example below. The system model is *not* supposed to be simplified before calling `linearize`: ## Example @@ -29,7 +29,7 @@ eqs = [u ~ kp * (r - y) # P controller D(x) ~ -x + u # First-order plant y ~ x] # Output equation -@mtkbuild sys = ODESystem(eqs, t) # Do not call @mtkbuild when linearizing +@named sys = ODESystem(eqs, t) # Do not call @mtkbuild when linearizing matrices, simplified_sys = linearize(sys, [r], [y]) # Linearize from r to y matrices ``` @@ -45,6 +45,10 @@ using ModelingToolkit: inputs, outputs The model above has 4 variables but only three equations, there is no equation specifying the value of `r` since `r` is an input. This means that only unbalanced models can be linearized, or in other words, models that are balanced and can be simulated _cannot_ be linearized. To learn more about this, see [How to linearize a ModelingToolkit model (YouTube)](https://www.youtube.com/watch?v=-XOux-2XDGI&t=395s). Also see [ModelingToolkitStandardLibrary: Linear analysis](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/linear_analysis/) for utilities that make linearization of completed models easier. +!!! note "Un-simplified system" + + Linearization expects `sys` to be un-simplified, i.e., `structural_simplify` or `@mtkbuild` should not be called on the system before linearizing. + ## Operating point The operating point to linearize around can be specified with the keyword argument `op` like this: `op = Dict(x => 1, r => 2)`. The operating point may include specification of unknown variables, input variables and parameters. For variables that are not specified in `op`, the default value specified in the model will be used if available, if no value is specified, an error is thrown. @@ -75,15 +79,14 @@ eqs = [D(x) ~ v y.u ~ x] @named duffing = ODESystem(eqs, t, systems = [y, u], defaults = [u.u => 0]) -duffing = structural_simplify(duffing, inputs = [u.u], outputs = [y.u]) # pass a constant value for `x`, since it is the variable we will change in operating points -linfun = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); +linfun, simplified_sys = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN)); -println(linearize(duffing, linfun; op = Dict(x => 1.0))) -println(linearize(duffing, linfun; op = Dict(x => 0.0))) +println(linearize(simplified_sys, linfun; op = Dict(x => 1.0))) +println(linearize(simplified_sys, linfun; op = Dict(x => 0.0))) -@time linearize(duffing, linfun; op = Dict(x => 0.0)) +@time linearize(simplified_sys, linfun; op = Dict(x => 0.0)) nothing # hide ``` From d49d3e94f18e695335e5ebf0678d8616689eb8f2 Mon Sep 17 00:00:00 2001 From: vyudu Date: Wed, 23 Apr 2025 11:15:54 -0400 Subject: [PATCH 13/18] revert rename --- src/systems/systems.jl | 14 +++++--------- src/systems/systemstructure.jl | 1 - 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 755cb8c15f..e61a4471a6 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -33,11 +33,7 @@ function structural_simplify( disturbance_inputs = Any[], kwargs...) isscheduled(sys) && throw(RepeatedStructuralSimplificationError()) - if inputs isa Union{Symbol, Vector{Symbol}, AnalysisPoint, Vector{AnalysisPoint}} - sys, inputs, outputs = ap_preprocessing(sys, inputs, outputs, kwargs...) - end - - newsys′ = __structural_simplification(sys; simplify, + newsys′ = __structural_simplify(sys; simplify, allow_symbolic, allow_parameter, conservative, fully_determined, inputs, outputs, disturbance_inputs, kwargs...) @@ -69,15 +65,15 @@ function structural_simplify( end end -function __structural_simplification(sys::JumpSystem, args...; kwargs...) +function __structural_simplify(sys::JumpSystem, args...; kwargs...) return sys end -function __structural_simplification(sys::SDESystem, args...; kwargs...) - return __structural_simplification(ODESystem(sys), args...; kwargs...) +function __structural_simplify(sys::SDESystem, args...; kwargs...) + return __structural_simplify(ODESystem(sys), args...; kwargs...) end -function __structural_simplification(sys::AbstractSystem; simplify = false, +function __structural_simplify(sys::AbstractSystem; simplify = false, inputs = Any[], outputs = Any[], disturbance_inputs = Any[], kwargs...) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index bbad46217e..e39ed38657 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -731,7 +731,6 @@ function _structural_simplify!(state::TearingState; simplify = false, ModelingToolkit.markio!(state, orig_inputs, inputs, outputs) state = ModelingToolkit.inputs_to_parameters!(state, inputs) end - sys, mm = ModelingToolkit.alias_elimination!(state; kwargs...) if check_consistency fully_determined = ModelingToolkit.check_consistency( From 513b312732a5e49772d7975e911f0b1a7bae7434 Mon Sep 17 00:00:00 2001 From: vyudu Date: Thu, 24 Apr 2025 15:37:58 -0400 Subject: [PATCH 14/18] test: test updates --- src/systems/systems.jl | 4 +--- test/clock.jl | 5 ++--- test/code_generation.jl | 2 +- test/input_output_handling.jl | 8 ++++---- test/odesystem.jl | 6 +++--- test/reduction.jl | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/systems/systems.jl b/src/systems/systems.jl index e61a4471a6..7b40a46a01 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -17,13 +17,11 @@ $(SIGNATURES) Structurally simplify algebraic equations in a system and compute the topological sort of the observed equations in `sys`. -### Optional Arguments: -+ optional argument `io` may take a tuple `(inputs, outputs)`. This will convert all `inputs` to parameters and allow them to be unconnected, i.e., simplification will allow models where `n_unknowns = n_equations - n_inputs`. - ### Optional Keyword Arguments: + When `simplify=true`, the `simplify` function will be applied during the tearing process. + `allow_symbolic=false`, `allow_parameter=true`, and `conservative=false` limit the coefficient types during tearing. In particular, `conservative=true` limits tearing to only solve for trivial linear systems where the coefficient has the absolute value of ``1``. + `fully_determined=true` controls whether or not an error will be thrown if the number of equations don't match the number of inputs, outputs, and equations. ++ `inputs`, `outputs` and `disturbance_inputs` are passed as keyword arguments.` All inputs` get converted to parameters and are allowed to be unconnected, allowing models where `n_unknowns = n_equations - n_inputs`. + `sort_eqs=true` controls whether equations are sorted lexicographically before simplification or not. """ function structural_simplify( diff --git a/test/clock.jl b/test/clock.jl index c6051a52a8..4fb9341d87 100644 --- a/test/clock.jl +++ b/test/clock.jl @@ -65,10 +65,9 @@ By inference: ci, varmap = infer_clocks(sys) eqmap = ci.eq_domain tss, inputs, continuous_id = ModelingToolkit.split_system(deepcopy(ci)) -sss, = ModelingToolkit._structural_simplify!( - deepcopy(tss[continuous_id]), (inputs[continuous_id], ())) +sss = ModelingToolkit._structural_simplify!(deepcopy(tss[continuous_id]), inputs = inputs[continuous_id], outputs = []) @test equations(sss) == [D(x) ~ u - x] -sss, = ModelingToolkit._structural_simplify!(deepcopy(tss[1]), (inputs[1], ())) +sss = ModelingToolkit._structural_simplify!(deepcopy(tss[1]), inputs = inputs[1], outputs = []) @test isempty(equations(sss)) d = Clock(dt) k = ShiftIndex(d) diff --git a/test/code_generation.jl b/test/code_generation.jl index cf3d660b81..3ef5ac3e11 100644 --- a/test/code_generation.jl +++ b/test/code_generation.jl @@ -70,7 +70,7 @@ end @parameters p[1:2] (f::Function)(..) @named sys = ODESystem( [D(x[0]) ~ p[1] * x[0] + x[2], D(x[1]) ~ p[2] * f(x) + x[2]], t) - sys, = structural_simplify(sys, ([x[2]], [])) + sys, = structural_simplify(sys, inputs = [x[2]], outputs = []) @test is_parameter(sys, x[2]) prob = ODEProblem(sys, [x[0] => 1.0, x[1] => 1.0], (0.0, 1.0), [p => ones(2), f => sum, x[2] => 2.0]) diff --git a/test/input_output_handling.jl b/test/input_output_handling.jl index 693a00b9ad..ee107dff4a 100644 --- a/test/input_output_handling.jl +++ b/test/input_output_handling.jl @@ -50,7 +50,7 @@ end @test !is_bound(sys31, sys1.v[2]) # simplification turns input variables into parameters -ssys, _ = structural_simplify(sys, ([u], [])) +ssys = structural_simplify(sys, inputs = [u], outputs = []) @test ModelingToolkit.isparameter(unbound_inputs(ssys)[]) @test !is_bound(ssys, u) @test u ∈ Set(unbound_inputs(ssys)) @@ -281,7 +281,7 @@ i = findfirst(isequal(u[1]), out) @variables x(t) u(t) [input = true] eqs = [D(x) ~ u] @named sys = ODESystem(eqs, t) -@test_nowarn structural_simplify(sys, ([u], [])) +@test_nowarn structural_simplify(sys, inputs = [u], outputs = []) #= ## Disturbance input handling @@ -366,9 +366,9 @@ eqs = [D(y₁) ~ -k₁ * y₁ + k₃ * y₂ * y₃ + u1 @named sys = ODESystem(eqs, t) m_inputs = [u[1], u[2]] m_outputs = [y₂] -sys_simp, input_idxs = structural_simplify(sys, (; inputs = m_inputs, outputs = m_outputs)) +sys_simp = structural_simplify(sys, inputs = m_inputs, outputs = m_outputs) @test isequal(unknowns(sys_simp), collect(x[1:2])) -@test length(input_idxs) == 2 +@test length(inputs(sys_simp)) == 2 # https://github.com/SciML/ModelingToolkit.jl/issues/1577 @named c = Constant(; k = 2) diff --git a/test/odesystem.jl b/test/odesystem.jl index f5fef1fd6f..08c37d30bc 100644 --- a/test/odesystem.jl +++ b/test/odesystem.jl @@ -1285,11 +1285,11 @@ end @named sys = ODESystem( [D(u) ~ (sum(u) + sum(x) + sum(p) + sum(o)) * x, o ~ prod(u) * x], t, [u..., x..., o...], [p...]) - sys1, = structural_simplify(sys, ([x...], [])) + sys1 = structural_simplify(sys, inputs = [x...], outputs = []) fn1, = ModelingToolkit.generate_function(sys1; expression = Val{false}) ps = MTKParameters(sys1, [x => 2ones(2), p => 3ones(2, 2)]) @test_nowarn fn1(ones(4), ps, 4.0) - sys2, = structural_simplify(sys, ([x...], []); split = false) + sys2 = structural_simplify(sys, inputs = [x...], outputs = [], split = false) fn2, = ModelingToolkit.generate_function(sys2; expression = Val{false}) ps = zeros(8) setp(sys2, x)(ps, 2ones(2)) @@ -1398,7 +1398,7 @@ end o[2] ~ sum(p) * sum(x)] @named sys = ODESystem(eqs, t, [u..., x..., o], [p...]) - sys1, = structural_simplify(sys, ([x...], [o...]), split = false) + sys1 = structural_simplify(sys, inputs = [x...], outputs = [o...], split = false) @test_nowarn ModelingToolkit.build_explicit_observed_function(sys1, u; inputs = [x...]) diff --git a/test/reduction.jl b/test/reduction.jl index fa9029a652..11992d29d6 100644 --- a/test/reduction.jl +++ b/test/reduction.jl @@ -233,7 +233,7 @@ eqs = [D(x) ~ σ * (y - x) u ~ z + a] lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_reduced, _ = structural_simplify(lorenz1, ([z], [])) +lorenz1_reduced, _ = structural_simplify(lorenz1, inputs = [z], outputs = []) @test z in Set(parameters(lorenz1_reduced)) # #2064 From b5ee07e1055a30b8ccb982f9e6fcd2b72641dc3a Mon Sep 17 00:00:00 2001 From: vyudu Date: Thu, 24 Apr 2025 17:35:48 -0400 Subject: [PATCH 15/18] fix input output tests --- src/inputoutput.jl | 13 +++++++------ src/linearization.jl | 9 ++++++++- src/systems/systems.jl | 1 - src/systems/systemstructure.jl | 4 ++-- src/variables.jl | 2 ++ test/input_output_handling.jl | 29 ++++++++++++++++------------- test/reduction.jl | 2 +- 7 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index c03da22abf..3dd96a03cf 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -197,10 +197,10 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu simplify = false, eval_expression = false, eval_module = @__MODULE__, + check_simplified = true, kwargs...) - # Remove this when the ControlFunction gets merged. - if !iscomplete(sys) + if check_simplified && !iscomplete(sys) error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating the control function.") end isempty(inputs) && @warn("No unbound inputs were found in system.") @@ -259,7 +259,7 @@ end """ Turn input variables into parameters of the system. """ -function inputs_to_parameters!(state::TransformationState, inputsyms) +function inputs_to_parameters!(state::TransformationState, inputsyms; is_disturbance = false) check_bound = inputsyms === nothing @unpack structure, fullvars, sys = state @unpack var_to_diff, graph, solvable_graph = structure @@ -414,7 +414,7 @@ function add_input_disturbance(sys, dist::DisturbanceModel, inputs = Any[]; kwar @variables u(t)=0 [input = true] # New system input dsys = get_disturbance_system(dist) - if inputs === nothing + if isempty(inputs) all_inputs = [u] else i = findfirst(isequal(dist.input), inputs) @@ -429,8 +429,9 @@ function add_input_disturbance(sys, dist::DisturbanceModel, inputs = Any[]; kwar dist.input ~ u + dsys.output.u[1]] augmented_sys = ODESystem(eqs, t, systems = [dsys], name = gensym(:outer)) augmented_sys = extend(augmented_sys, sys) + ssys = structural_simplify(augmented_sys, inputs = all_inputs, disturbance_inputs = [d]) - (f_oop, f_ip), dvs, p, io_sys = generate_control_function(augmented_sys, all_inputs, - [d]; kwargs...) + (f_oop, f_ip), dvs, p, io_sys = generate_control_function(ssys, all_inputs, + [d]; check_simplified = false, kwargs...) (f_oop, f_ip), augmented_sys, dvs, p, io_sys end diff --git a/src/linearization.jl b/src/linearization.jl index 451f262476..efbb3c3ab4 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -556,10 +556,11 @@ function linearize_symbolic(sys::AbstractSystem, inputs, (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys end -function markio!(state, orig_inputs, inputs, outputs; check = true) +function markio!(state, orig_inputs, inputs, outputs, disturbances; check = true) fullvars = get_fullvars(state) inputset = Dict{Any, Bool}(i => false for i in inputs) outputset = Dict{Any, Bool}(o => false for o in outputs) + disturbanceset = Dict{Any, Bool}(d => false for d in disturbances) for (i, v) in enumerate(fullvars) if v in keys(inputset) if v in keys(outputset) @@ -581,6 +582,12 @@ function markio!(state, orig_inputs, inputs, outputs; check = true) v = setio(v, false, false) fullvars[i] = v end + + if v in keys(disturbanceset) + v = setio(v, true, false) + v = setdisturbance(v, true) + fullvars[i] = v + end end if check ikeys = keys(filter(!last, inputset)) diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 7b40a46a01..acd2b4efc9 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -124,7 +124,6 @@ function __structural_simplify(sys::AbstractSystem; simplify = false, for (i, v) in enumerate(fullvars) if !iszero(new_idxs[i]) && invview(var_to_diff)[i] === nothing] - # TODO: IO is not handled. ode_sys = structural_simplify(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) eqs = equations(ode_sys) sorted_g_rows = zeros(Num, length(eqs), size(g, 2)) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index e39ed38657..2bae98cbdd 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -728,8 +728,8 @@ function _structural_simplify!(state::TearingState; simplify = false, has_io = inputs !== nothing || outputs !== nothing orig_inputs = Set() if has_io - ModelingToolkit.markio!(state, orig_inputs, inputs, outputs) - state = ModelingToolkit.inputs_to_parameters!(state, inputs) + ModelingToolkit.markio!(state, orig_inputs, inputs, outputs, disturbance_inputs) + state = ModelingToolkit.inputs_to_parameters!(state, [inputs; disturbance_inputs]) end sys, mm = ModelingToolkit.alias_elimination!(state; kwargs...) if check_consistency diff --git a/src/variables.jl b/src/variables.jl index f3dd16819d..cff5efa5e0 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -349,6 +349,8 @@ function isdisturbance(x) Symbolics.getmetadata(x, VariableDisturbance, false) end +setdisturbance(x, v) = setmetadata(x, VariableDisturbance, v) + function disturbances(sys) [filter(isdisturbance, unknowns(sys)); filter(isdisturbance, parameters(sys))] end diff --git a/test/input_output_handling.jl b/test/input_output_handling.jl index ee107dff4a..1a1c9a6b65 100644 --- a/test/input_output_handling.jl +++ b/test/input_output_handling.jl @@ -7,10 +7,10 @@ using ModelingToolkit: t_nounits as t, D_nounits as D @variables xx(t) some_input(t) [input = true] eqs = [D(xx) ~ some_input] @named model = ODESystem(eqs, t) -@test_throws ExtraVariablesSystemException structural_simplify(model, ((), ())) +@test_throws ExtraVariablesSystemException structural_simplify(model) if VERSION >= v"1.8" err = "In particular, the unset input(s) are:\n some_input(t)" - @test_throws err structural_simplify(model, ((), ())) + @test_throws err structural_simplify(model) end # Test input handling @@ -88,7 +88,7 @@ fsys4 = flatten(sys4) @variables x(t) y(t) [output = true] @test isoutput(y) @named sys = ODESystem([D(x) ~ -x, y ~ x], t) # both y and x are unbound -syss = structural_simplify(sys) # This makes y an observed variable +syss = structural_simplify(sys, outputs = [y]) # This makes y an observed variable @named sys2 = ODESystem([D(x) ~ -sys.x, y ~ sys.y], t, systems = [sys]) @@ -106,7 +106,7 @@ syss = structural_simplify(sys) # This makes y an observed variable @test isequal(unbound_outputs(sys2), [y]) @test isequal(bound_outputs(sys2), [sys.y]) -syss = structural_simplify(sys2) +syss = structural_simplify(sys2, outputs = [sys.y]) @test !is_bound(syss, y) @test !is_bound(syss, x) @@ -165,6 +165,7 @@ end ] @named sys = ODESystem(eqs, t) + sys = structural_simplify(sys, inputs = [u]) f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys; simplify, split) @test isequal(dvs[], x) @@ -182,8 +183,8 @@ end ] @named sys = ODESystem(eqs, t) - f, dvs, ps, io_sys = ModelingToolkit.generate_control_function( - sys, [u], [d]; simplify, split) + sys = structural_simplify(sys, inputs = [u], disturbance_inputs = [d]) + f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys; simplify, split) @test isequal(dvs[], x) @test isempty(ps) @@ -200,8 +201,8 @@ end ] @named sys = ODESystem(eqs, t) - f, dvs, ps, io_sys = ModelingToolkit.generate_control_function( - sys, [u], [d]; simplify, split, disturbance_argument = true) + sys = structural_simplify(sys, inputs = [u], disturbance_inputs = [d]) + f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys; simplify, split, disturbance_argument = true) @test isequal(dvs[], x) @test isempty(ps) @@ -265,9 +266,9 @@ eqs = [connect_sd(sd, mass1, mass2) @named _model = ODESystem(eqs, t) @named model = compose(_model, mass1, mass2, sd); +model = structural_simplify(model, inputs = [u]) f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(model, simplify = true) @test length(dvs) == 4 -@test length(ps) == length(parameters(model)) p = MTKParameters(io_sys, [io_sys.u => NaN]) x = ModelingToolkit.varmap_to_vars( merge(ModelingToolkit.defaults(model), @@ -389,7 +390,7 @@ sys = structural_simplify(model) ## Disturbance models when plant has multiple inputs using ModelingToolkit, LinearAlgebra -using ModelingToolkit: DisturbanceModel, io_preprocessing, get_iv, get_disturbance_system +using ModelingToolkit: DisturbanceModel, get_iv, get_disturbance_system using ModelingToolkitStandardLibrary.Blocks A, C = [randn(2, 2) for i in 1:2] B = [1.0 0; 0 1.0] @@ -433,6 +434,7 @@ matrices = ModelingToolkit.reorder_unknowns( ] @named sys = ODESystem(eqs, t) + sys = structural_simplify(sys, inputs = [u]) (; io_sys,) = ModelingToolkit.generate_control_function(sys, simplify = true) obsfn = ModelingToolkit.build_explicit_observed_function( io_sys, [x + u * t]; inputs = [u]) @@ -444,9 +446,9 @@ end @constants c = 2.0 @variables x(t) eqs = [D(x) ~ c * x] - @named sys = ODESystem(eqs, t, [x], []) + @mtkbuild sys = ODESystem(eqs, t, [x], []) - f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys, simplify = true) + f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys) @test f[1]([0.5], nothing, MTKParameters(io_sys, []), 0.0) ≈ [1.0] end @@ -455,7 +457,8 @@ end @parameters p(::Real) = (x -> 2x) eqs = [D(x) ~ -x + p(u)] @named sys = ODESystem(eqs, t) - f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys, simplify = true) + sys = structural_simplify(sys, inputs = [u]) + f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys) p = MTKParameters(io_sys, []) u = [1.0] x = [1.0] diff --git a/test/reduction.jl b/test/reduction.jl index 11992d29d6..9a515614d5 100644 --- a/test/reduction.jl +++ b/test/reduction.jl @@ -233,7 +233,7 @@ eqs = [D(x) ~ σ * (y - x) u ~ z + a] lorenz1 = ODESystem(eqs, t, name = :lorenz1) -lorenz1_reduced, _ = structural_simplify(lorenz1, inputs = [z], outputs = []) +lorenz1_reduced = structural_simplify(lorenz1, inputs = [z], outputs = []) @test z in Set(parameters(lorenz1_reduced)) # #2064 From 5f612057edb132e35fb471fc8cf616fb7d85ef3a Mon Sep 17 00:00:00 2001 From: vyudu Date: Fri, 25 Apr 2025 11:20:18 -0400 Subject: [PATCH 16/18] more test fixes --- src/inputoutput.jl | 2 +- test/code_generation.jl | 2 +- test/extensions/test_infiniteopt.jl | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 3dd96a03cf..6110e35951 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -163,7 +163,7 @@ has_var(ex, x) = x ∈ Set(get_variables(ex)) (f_oop, f_ip), x_sym, p_sym, io_sys = generate_control_function( sys::AbstractODESystem, inputs = unbound_inputs(sys), - disturbance_inputs = Any[]; + disturbance_inputs = disturbances(sys); implicit_dae = false, simplify = false, ) diff --git a/test/code_generation.jl b/test/code_generation.jl index 3ef5ac3e11..2fbf8f13d7 100644 --- a/test/code_generation.jl +++ b/test/code_generation.jl @@ -70,7 +70,7 @@ end @parameters p[1:2] (f::Function)(..) @named sys = ODESystem( [D(x[0]) ~ p[1] * x[0] + x[2], D(x[1]) ~ p[2] * f(x) + x[2]], t) - sys, = structural_simplify(sys, inputs = [x[2]], outputs = []) + sys = structural_simplify(sys, inputs = [x[2]], outputs = []) @test is_parameter(sys, x[2]) prob = ODEProblem(sys, [x[0] => 1.0, x[1] => 1.0], (0.0, 1.0), [p => ones(2), f => sum, x[2] => 2.0]) diff --git a/test/extensions/test_infiniteopt.jl b/test/extensions/test_infiniteopt.jl index e45aa0f2fd..f64f9c18f5 100644 --- a/test/extensions/test_infiniteopt.jl +++ b/test/extensions/test_infiniteopt.jl @@ -22,13 +22,14 @@ using ModelingToolkit: D_nounits as D, t_nounits as t, varmap_to_vars end @named model = Pendulum() model = complete(model) - inputs = [model.τ] +outputs = [model.y] + +model = structural_simplify(model; inputs, outputs) (f_oop, f_ip), dvs, psym, io_sys = ModelingToolkit.generate_control_function( - model, inputs, split = false) + model, split = false) -outputs = [model.y] -f_obs = ModelingToolkit.build_explicit_observed_function(io_sys, outputs; inputs = inputs) +f_obs = ModelingToolkit.build_explicit_observed_function(io_sys, [model.y]; inputs) expected_state_order = [model.θ, model.ω] permutation = [findfirst(isequal(x), expected_state_order) for x in dvs] # This maps our expected state order to the actual state order From 15a62366fa6048d43cf3efec4d917ee40e7dbab2 Mon Sep 17 00:00:00 2001 From: vyudu Date: Mon, 28 Apr 2025 16:12:50 -0400 Subject: [PATCH 17/18] fix: fix sort_eqs and check distrubances in markio --- src/inputoutput.jl | 15 ++------------- src/linearization.jl | 28 ++++++++++++++++++---------- src/systems/systems.jl | 1 + src/systems/systemstructure.jl | 2 +- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 6110e35951..0163c6d4df 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -259,7 +259,7 @@ end """ Turn input variables into parameters of the system. """ -function inputs_to_parameters!(state::TransformationState, inputsyms; is_disturbance = false) +function inputs_to_parameters!(state::TransformationState, inputsyms) check_bound = inputsyms === nothing @unpack structure, fullvars, sys = state @unpack var_to_diff, graph, solvable_graph = structure @@ -318,18 +318,7 @@ function inputs_to_parameters!(state::TransformationState, inputsyms; is_disturb @set! sys.unknowns = setdiff(unknowns(sys), keys(input_to_parameters)) ps = parameters(sys) - if inputsyms !== nothing - # Change order of new parameters to correspond to user-provided order in argument `inputs` - d = Dict{Any, Int}() - for (i, inp) in enumerate(new_parameters) - d[inp] = i - end - permutation = [d[i] for i in inputsyms] - new_parameters = new_parameters[permutation] - end - @set! sys.ps = [ps; new_parameters] - @set! state.sys = sys @set! state.fullvars = new_fullvars @set! state.structure = structure @@ -432,6 +421,6 @@ function add_input_disturbance(sys, dist::DisturbanceModel, inputs = Any[]; kwar ssys = structural_simplify(augmented_sys, inputs = all_inputs, disturbance_inputs = [d]) (f_oop, f_ip), dvs, p, io_sys = generate_control_function(ssys, all_inputs, - [d]; check_simplified = false, kwargs...) + [d]; kwargs...) (f_oop, f_ip), augmented_sys, dvs, p, io_sys end diff --git a/src/linearization.jl b/src/linearization.jl index efbb3c3ab4..12340435b8 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -132,14 +132,13 @@ function linearization_function(sys::AbstractSystem, inputs, return lin_fun, sys end +""" +Return the set of indexes of differential equations and algebraic equations in the simplified system. +""" function eq_idxs(sys::AbstractSystem) eqs = equations(sys) - alg_start_idx = findfirst(!isdiffeq, eqs) - if alg_start_idx === nothing - alg_start_idx = length(eqs) + 1 - end - diff_idxs = 1:(alg_start_idx - 1) - alge_idxs = alg_start_idx:length(eqs) + alge_idxs = findall(!isdiffeq, eqs) + diff_idxs = setdiff(1:length(eqs), alge_idxs) diff_idxs, alge_idxs end @@ -556,6 +555,9 @@ function linearize_symbolic(sys::AbstractSystem, inputs, (; A, B, C, D, f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u), sys end +""" +Modify the variable metadata of system variables to indicate which ones are inputs, outputs, and disturbances. Needed for `inputs`, `outputs`, `disturbances`, `unbound_inputs`, `unbound_outputs` to return the proper subsets. +""" function markio!(state, orig_inputs, inputs, outputs, disturbances; check = true) fullvars = get_fullvars(state) inputset = Dict{Any, Bool}(i => false for i in inputs) @@ -586,6 +588,7 @@ function markio!(state, orig_inputs, inputs, outputs, disturbances; check = true if v in keys(disturbanceset) v = setio(v, true, false) v = setdisturbance(v, true) + disturbanceset[v] = true fullvars[i] = v end end @@ -596,11 +599,16 @@ function markio!(state, orig_inputs, inputs, outputs, disturbances; check = true "Some specified inputs were not found in system. The following variables were not found ", ikeys) end - end - check && (all(values(outputset)) || - error( - "Some specified outputs were not found in system. The following Dict indicates the found variables ", + dkeys = keys(filter(!last, disturbanceset)) + if !isempty(dkeys) + error( + "Specified disturbance inputs were not found in system. The following variables were not found ", + ikeys) + end + (all(values(outputset)) || error( + "Some specified outputs were not found in system. The following Dict indicates the found variables ", outputset)) + end state, orig_inputs end diff --git a/src/systems/systems.jl b/src/systems/systems.jl index acd2b4efc9..59d2af6526 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -74,6 +74,7 @@ end function __structural_simplify(sys::AbstractSystem; simplify = false, inputs = Any[], outputs = Any[], disturbance_inputs = Any[], + sort_eqs = true, kwargs...) sys = expand_connections(sys) state = TearingState(sys; sort_eqs) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index 2bae98cbdd..e0502d8e2f 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -725,7 +725,7 @@ function _structural_simplify!(state::TearingState; simplify = false, else check_consistency = true end - has_io = inputs !== nothing || outputs !== nothing + has_io = !isempty(inputs) || !isempty(outputs) !== nothing || !isempty(disturbance_inputs) orig_inputs = Set() if has_io ModelingToolkit.markio!(state, orig_inputs, inputs, outputs, disturbance_inputs) From 7a234f1c4b9cd9838014a695780f35d66a56dc67 Mon Sep 17 00:00:00 2001 From: vyudu Date: Fri, 2 May 2025 12:49:43 -0400 Subject: [PATCH 18/18] format --- src/inputoutput.jl | 2 +- src/linearization.jl | 2 +- src/systems/systems.jl | 6 ++++-- src/systems/systemstructure.jl | 6 +++--- test/clock.jl | 6 ++++-- test/input_output_handling.jl | 3 ++- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/inputoutput.jl b/src/inputoutput.jl index 0163c6d4df..cc6eeab5e3 100644 --- a/src/inputoutput.jl +++ b/src/inputoutput.jl @@ -200,7 +200,7 @@ function generate_control_function(sys::AbstractODESystem, inputs = unbound_inpu check_simplified = true, kwargs...) # Remove this when the ControlFunction gets merged. - if check_simplified && !iscomplete(sys) + if check_simplified && !iscomplete(sys) error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating the control function.") end isempty(inputs) && @warn("No unbound inputs were found in system.") diff --git a/src/linearization.jl b/src/linearization.jl index 12340435b8..0c18cbcb5c 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -607,7 +607,7 @@ function markio!(state, orig_inputs, inputs, outputs, disturbances; check = true end (all(values(outputset)) || error( "Some specified outputs were not found in system. The following Dict indicates the found variables ", - outputset)) + outputset)) end state, orig_inputs end diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 59d2af6526..e417337a95 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -93,7 +93,8 @@ function __structural_simplify(sys::AbstractSystem; simplify = false, end end if isempty(brown_vars) - return structural_simplify!(state; simplify, inputs, outputs, disturbance_inputs, kwargs...) + return structural_simplify!( + state; simplify, inputs, outputs, disturbance_inputs, kwargs...) else Is = Int[] Js = Int[] @@ -125,7 +126,8 @@ function __structural_simplify(sys::AbstractSystem; simplify = false, for (i, v) in enumerate(fullvars) if !iszero(new_idxs[i]) && invview(var_to_diff)[i] === nothing] - ode_sys = structural_simplify(sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) + ode_sys = structural_simplify( + sys; simplify, inputs, outputs, disturbance_inputs, kwargs...) eqs = equations(ode_sys) sorted_g_rows = zeros(Num, length(eqs), size(g, 2)) for (i, eq) in enumerate(eqs) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index e0502d8e2f..08c95fbbb2 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -659,10 +659,9 @@ end function structural_simplify!(state::TearingState; simplify = false, check_consistency = true, fully_determined = true, warn_initialize_determined = true, - inputs = Any[], outputs = Any[], + inputs = Any[], outputs = Any[], disturbance_inputs = Any[], kwargs...) - if state.sys isa ODESystem ci = ModelingToolkit.ClockInference(state) ci = ModelingToolkit.infer_clocks!(ci) @@ -725,7 +724,8 @@ function _structural_simplify!(state::TearingState; simplify = false, else check_consistency = true end - has_io = !isempty(inputs) || !isempty(outputs) !== nothing || !isempty(disturbance_inputs) + has_io = !isempty(inputs) || !isempty(outputs) !== nothing || + !isempty(disturbance_inputs) orig_inputs = Set() if has_io ModelingToolkit.markio!(state, orig_inputs, inputs, outputs, disturbance_inputs) diff --git a/test/clock.jl b/test/clock.jl index 4fb9341d87..c4c64dbf90 100644 --- a/test/clock.jl +++ b/test/clock.jl @@ -65,9 +65,11 @@ By inference: ci, varmap = infer_clocks(sys) eqmap = ci.eq_domain tss, inputs, continuous_id = ModelingToolkit.split_system(deepcopy(ci)) -sss = ModelingToolkit._structural_simplify!(deepcopy(tss[continuous_id]), inputs = inputs[continuous_id], outputs = []) +sss = ModelingToolkit._structural_simplify!( + deepcopy(tss[continuous_id]), inputs = inputs[continuous_id], outputs = []) @test equations(sss) == [D(x) ~ u - x] -sss = ModelingToolkit._structural_simplify!(deepcopy(tss[1]), inputs = inputs[1], outputs = []) +sss = ModelingToolkit._structural_simplify!( + deepcopy(tss[1]), inputs = inputs[1], outputs = []) @test isempty(equations(sss)) d = Clock(dt) k = ShiftIndex(d) diff --git a/test/input_output_handling.jl b/test/input_output_handling.jl index 1a1c9a6b65..3efeb46868 100644 --- a/test/input_output_handling.jl +++ b/test/input_output_handling.jl @@ -202,7 +202,8 @@ end @named sys = ODESystem(eqs, t) sys = structural_simplify(sys, inputs = [u], disturbance_inputs = [d]) - f, dvs, ps, io_sys = ModelingToolkit.generate_control_function(sys; simplify, split, disturbance_argument = true) + f, dvs, ps, io_sys = ModelingToolkit.generate_control_function( + sys; simplify, split, disturbance_argument = true) @test isequal(dvs[], x) @test isempty(ps)