Skip to content

Commit

Permalink
Merge pull request #3027 from SciML/double_ss_error
Browse files Browse the repository at this point in the history
Throw an error if structural simplification is applied twice
  • Loading branch information
ChrisRackauckas authored Sep 9, 2024
2 parents 2937584 + d84a211 commit 2f518c4
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/Tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
group:
- InterfaceI
- InterfaceII
- SymbolicIndexingInterface
- Extended
- Extensions
- Downstream
- RegressionI
Expand Down
9 changes: 9 additions & 0 deletions src/systems/systems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ function System(eqs::AbstractVector{<:Equation}, iv, args...; name = nothing,
ODESystem(eqs, iv, args...; name, kw..., checks = false)
end

const REPEATED_SIMPLIFICATION_MESSAGE = "Structural simplification cannot be applied to a completed system. Double simplification is not allowed."

struct RepeatedStructuralSimplificationError <: Exception end

function Base.showerror(io::IO, e::RepeatedStructuralSimplificationError)
print(io, REPEATED_SIMPLIFICATION_MESSAGE)
end

"""
$(SIGNATURES)
Expand All @@ -21,6 +29,7 @@ function structural_simplify(
sys::AbstractSystem, io = nothing; simplify = false, split = true,
allow_symbolic = false, allow_parameter = true, conservative = false, fully_determined = true,
kwargs...)
iscomplete(sys) && throw(RepeatedStructuralSimplificationError())
newsys′ = __structural_simplify(sys, io; simplify,
allow_symbolic, allow_parameter, conservative, fully_determined,
kwargs...)
Expand Down
1 change: 0 additions & 1 deletion test/downstream/linearize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ matrices = linfun([1.0], Dict(p => 3.0), 1.0)
@parameters p
eqs = [0 ~ x * log(y) - p]
@named sys = ODESystem(eqs, t; defaults = [p => 1.0])
sys = complete(sys)
@test_nowarn linearize(
sys, [x], []; op = Dict(x => 1.0), allow_input_derivatives = true)
end
2 changes: 1 addition & 1 deletion test/initial_values.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@ end
@variables x(t)
@parameters p
@mtkbuild sys = ODESystem([D(x) ~ p], t; defaults = [x => t, p => 2t])
prob = ODEProblem(structural_simplify(sys), [], (1.0, 2.0), [])
prob = ODEProblem(sys, [], (1.0, 2.0), [])
@test prob[x] == 1.0
@test prob.ps[p] == 2.0
8 changes: 4 additions & 4 deletions test/input_output_handling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,12 @@ disturbed_input = ins[1]
dist_integ,
ins)

augmented_sys = complete(augmented_sys)
getter_sys = complete(augmented_sys)
matrices, ssys = linearize(augmented_sys,
[
augmented_sys.u,
augmented_sys.input.u[2],
augmented_sys.d
getter_sys.u,
getter_sys.input.u[2],
getter_sys.d
], outs)
@test matrices.A [A [1; 0]; zeros(1, 2) -0.001]
@test matrices.B == I
Expand Down
12 changes: 6 additions & 6 deletions test/mtkparameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ function level1()
eqs = [D(x) ~ p1 * x - p2 * x * y
D(y) ~ -p3 * y + p4 * x * y]

sys = structural_simplify(complete(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4])))
sys = structural_simplify(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))
prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys)
end

Expand All @@ -158,8 +158,8 @@ function level2()
eqs = [D(x) ~ p1 * x - p23[1] * x * y
D(y) ~ -p23[2] * y + p4 * x * y]

sys = structural_simplify(complete(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4])))
sys = structural_simplify(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))
prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys)
end

Expand All @@ -172,8 +172,8 @@ function level3()
eqs = [D(x) ~ p1 * x - p23[1] * x * y
D(y) ~ -p23[2] * y + p4 * x * y]

sys = structural_simplify(complete(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4])))
sys = structural_simplify(ODESystem(
eqs, t, tspan = (0, 3.0), name = :sys, parameter_dependencies = [y0 => 2p4]))
prob = ODEProblem{true, SciMLBase.FullSpecialize}(sys)
end

Expand Down
1 change: 0 additions & 1 deletion test/nonlinearsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ end
0 ~ z - cos(x),
0 ~ x * y]
@named ns = NonlinearSystem(eqs, [x, y, z], [])
ns = complete(ns)
vs = [unknowns(ns); parameters(ns)]
ss_mtk = structural_simplify(ns)
prob = NonlinearProblem(ss_mtk, vs .=> 1.0)
Expand Down
5 changes: 0 additions & 5 deletions test/reduction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@ __x = x
# Reduced Flattened System

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))
@test isequal(observed(reduced_system), observed(reduced_system2))
@test setdiff(unknowns(reduced_system),
[s
a
Expand Down
35 changes: 20 additions & 15 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,62 @@ end
@safetestset "Unitful Quantities Test" include("units.jl")
@safetestset "LabelledArrays Test" include("labelledarrays.jl")
@safetestset "Mass Matrix Test" include("mass_matrix.jl")
@safetestset "SteadyStateSystem Test" include("steadystatesystems.jl")
@safetestset "SDESystem Test" include("sdesystem.jl")
@safetestset "DDESystem Test" include("dde.jl")
@safetestset "NonlinearSystem Test" include("nonlinearsystem.jl")
@safetestset "InitializationSystem Test" include("initializationsystem.jl")
@safetestset "Guess Propagation" include("guess_propagation.jl")
@safetestset "Hierarchical Initialization Equations" include("hierarchical_initialization_eqs.jl")
@safetestset "PDE Construction Test" include("pde.jl")
@safetestset "JumpSystem Test" include("jumpsystem.jl")
@safetestset "Constraints Test" include("constraints.jl")
@safetestset "Reduction Test" include("reduction.jl")
@safetestset "Split Parameters Test" include("split_parameters.jl")
@safetestset "StaticArrays Test" include("static_arrays.jl")
@safetestset "Components Test" include("components.jl")
@safetestset "Model Parsing Test" include("model_parsing.jl")
@safetestset "print_tree" include("print_tree.jl")
@safetestset "Error Handling" include("error_handling.jl")
@safetestset "StructuralTransformations" include("structural_transformation/runtests.jl")
@safetestset "State Selection Test" include("state_selection.jl")
@safetestset "Symbolic Event Test" include("symbolic_events.jl")
@safetestset "Stream Connect Test" include("stream_connectors.jl")
@safetestset "Domain Connect Test" include("domain_connectors.jl")
@safetestset "Lowering Integration Test" include("lowering_solving.jl")
@safetestset "Test Big System Usage" include("bigsystem.jl")
@safetestset "Dependency Graph Test" include("dep_graphs.jl")
@safetestset "Function Registration Test" include("function_registration.jl")
@safetestset "Precompiled Modules Test" include("precompile_test.jl")
@safetestset "Variable Utils Test" include("variable_utils.jl")
@safetestset "Variable Metadata Test" include("test_variable_metadata.jl")
@safetestset "DAE Jacobians Test" include("dae_jacobian.jl")
@safetestset "Jacobian Sparsity" include("jacobiansparsity.jl")
@safetestset "Modelingtoolkitize Test" include("modelingtoolkitize.jl")
@safetestset "OptimizationSystem Test" include("optimizationsystem.jl")
@safetestset "FuncAffect Test" include("funcaffect.jl")
@safetestset "Constants Test" include("constants.jl")
@safetestset "Parameter Dependency Test" include("parameter_dependencies.jl")
@safetestset "Generate Custom Function Test" include("generate_custom_function.jl")
@safetestset "Initial Values Test" include("initial_values.jl")
@safetestset "Discrete System" include("discrete_system.jl")
@safetestset "Equation Type Accessors Test" include("equation_type_accessors.jl")
@safetestset "Equations with complex values" include("complex.jl")
end
end

if GROUP == "All" || GROUP == "InterfaceI" || GROUP == "SymbolicIndexingInterface"
if GROUP == "All" || GROUP == "InterfaceII"
@testset "InterfaceII" begin
@safetestset "Variable Utils Test" include("variable_utils.jl")
@safetestset "Variable Metadata Test" include("test_variable_metadata.jl")
@safetestset "OptimizationSystem Test" include("optimizationsystem.jl")
@safetestset "Discrete System" include("discrete_system.jl")
@safetestset "SteadyStateSystem Test" include("steadystatesystems.jl")
@safetestset "SDESystem Test" include("sdesystem.jl")
@safetestset "DDESystem Test" include("dde.jl")
@safetestset "NonlinearSystem Test" include("nonlinearsystem.jl")
@safetestset "PDE Construction Test" include("pde.jl")
@safetestset "JumpSystem Test" include("jumpsystem.jl")
@safetestset "print_tree" include("print_tree.jl")
@safetestset "Constraints Test" include("constraints.jl")
end
end

if GROUP == "All" || GROUP == "SymbolicIndexingInterface"
@safetestset "SymbolicIndexingInterface test" include("symbolic_indexing_interface.jl")
@safetestset "SciML Problem Input Test" include("sciml_problem_inputs.jl")
@safetestset "MTKParameters Test" include("mtkparameters.jl")
end

if GROUP == "All" || GROUP == "InterfaceII"
if GROUP == "All" || GROUP == "Extended"
@safetestset "Test Big System Usage" include("bigsystem.jl")
println("C compilation test requires gcc available in the path!")
@safetestset "C Compilation Test" include("ccompile.jl")
@testset "Distributed Test" include("distributed.jl")
Expand Down
19 changes: 19 additions & 0 deletions test/structural_transformation/errors.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using Test

@mtkmodel FOL begin
@parameters begin
τ = 3.0 # parameters
end
@variables begin
x(t) = 0.0 # dependent variables
end
@equations begin
D(x) ~ (1 - x) / τ
end
end

@named rc_model = FOL()
sys = structural_simplify(rc_model)
@test_throws ModelingToolkit.RepeatedStructuralSimplificationError structural_simplify(sys)
3 changes: 3 additions & 0 deletions test/structural_transformation/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ end
@safetestset "Bareiss" begin
include("bareiss.jl")
end
@safetestset "Errors" begin
include("errors.jl")
end
4 changes: 2 additions & 2 deletions test/symbolic_events.jl
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,11 @@ continuous_events = [[x ~ 0] => [vx ~ -vx]
D(vx) ~ -9.8
D(vy) ~ -0.01vy], t; continuous_events)

ball = structural_simplify(ball)
ball_split = structural_simplify(ball)
ball_nosplit = structural_simplify(ball; split = false)

tspan = (0.0, 5.0)
prob = ODEProblem(ball, Pair[], tspan)
prob = ODEProblem(ball_split, Pair[], tspan)
prob_nosplit = ODEProblem(ball_nosplit, Pair[], tspan)

cb = get_callback(prob)
Expand Down

0 comments on commit 2f518c4

Please sign in to comment.