|  | 
| 4 | 4 | using ModelingToolkit, Test | 
| 5 | 5 | using ModelingToolkit: t_nounits as t, D_nounits as D | 
| 6 | 6 | import ModelingToolkit: get_ps, get_unknowns, get_observed, get_eqs, get_continuous_events, | 
| 7 |  | -    get_discrete_events, namespace_equations | 
|  | 7 | +                        get_discrete_events, namespace_equations | 
| 8 | 8 | 
 | 
| 9 | 9 | # Creates helper functions. | 
| 10 | 10 | function all_sets_equal(args...) | 
|  | 
| 32 | 32 | 
 | 
| 33 | 33 |     # Creates the systems (individual and hierarchical). | 
| 34 | 34 |     eqs_top = [ | 
| 35 |  | -        D(X_top) ~ p_top - d*X_top, | 
|  | 35 | +        D(X_top) ~ p_top - d * X_top, | 
| 36 | 36 |         D(Y) ~ log(X_top) - Y^2 + 3.0, | 
| 37 |  | -        O ~ (p_top + d)*X_top + Y | 
|  | 37 | +        O ~ (p_top + d) * X_top + Y | 
| 38 | 38 |     ] | 
| 39 | 39 |     eqs_mid1 = [ | 
| 40 |  | -        D(X_mid1) ~ p_mid1 - d*X_mid1^2, | 
|  | 40 | +        D(X_mid1) ~ p_mid1 - d * X_mid1^2, | 
| 41 | 41 |         D(Y) ~ D(X_mid1) - Y^3, | 
| 42 |  | -        O ~ (p_mid1 + d)*X_mid1 + Y | 
|  | 42 | +        O ~ (p_mid1 + d) * X_mid1 + Y | 
| 43 | 43 |     ] | 
| 44 | 44 |     eqs_mid2 = [ | 
| 45 |  | -        D(X_mid2) ~ p_mid2 - d*X_mid2, | 
|  | 45 | +        D(X_mid2) ~ p_mid2 - d * X_mid2, | 
| 46 | 46 |         X_mid2^3 ~ log(X_mid2 + Y) - Y^2 + 3.0, | 
| 47 |  | -        O ~ (p_mid2 + d)*X_mid2 + Y | 
|  | 47 | +        O ~ (p_mid2 + d) * X_mid2 + Y | 
| 48 | 48 |     ] | 
| 49 | 49 |     eqs_bot = [ | 
| 50 |  | -        D(X_bot) ~ p_bot - d*X_bot, | 
|  | 50 | +        D(X_bot) ~ p_bot - d * X_bot, | 
| 51 | 51 |         D(Y) ~ -Y^3, | 
| 52 |  | -        O ~ (p_bot + d)*X_bot + Y | 
|  | 52 | +        O ~ (p_bot + d) * X_bot + Y | 
| 53 | 53 |     ] | 
| 54 | 54 |     cevs = [[t ~ 1.0] => [Y ~ Y + 2.0]] | 
| 55 | 55 |     devs = [(t == 2.0) => [Y ~ Y + 2.0]] | 
| 56 |  | -    @named sys_bot = ODESystem(eqs_bot, t; systems = [], continuous_events = cevs, discrete_events = devs) | 
| 57 |  | -    @named sys_mid2 = ODESystem(eqs_mid2, t; systems = [], continuous_events = cevs, discrete_events = devs) | 
| 58 |  | -    @named sys_mid1 = ODESystem(eqs_mid1, t; systems = [sys_bot], continuous_events = cevs, discrete_events = devs) | 
| 59 |  | -    @named sys_top = ODESystem(eqs_top, t; systems = [sys_mid1, sys_mid2], continuous_events = cevs, discrete_events = devs) | 
|  | 56 | +    @named sys_bot = ODESystem( | 
|  | 57 | +        eqs_bot, t; systems = [], continuous_events = cevs, discrete_events = devs) | 
|  | 58 | +    @named sys_mid2 = ODESystem( | 
|  | 59 | +        eqs_mid2, t; systems = [], continuous_events = cevs, discrete_events = devs) | 
|  | 60 | +    @named sys_mid1 = ODESystem( | 
|  | 61 | +        eqs_mid1, t; systems = [sys_bot], continuous_events = cevs, discrete_events = devs) | 
|  | 62 | +    @named sys_top = ODESystem(eqs_top, t; systems = [sys_mid1, sys_mid2], | 
|  | 63 | +        continuous_events = cevs, discrete_events = devs) | 
| 60 | 64 |     sys_bot_comp = complete(sys_bot) | 
| 61 | 65 |     sys_mid2_comp = complete(sys_mid2) | 
| 62 | 66 |     sys_mid1_comp = complete(sys_mid1) | 
|  | 
| 68 | 72 | 
 | 
| 69 | 73 |     # Checks `parameters` for `toplevel = false`. | 
| 70 | 74 |     @test all_sets_equal(parameters.([sys_bot, sys_bot_comp, sys_bot_ss])..., [d, p_bot]) | 
| 71 |  | -    @test all_sets_equal(parameters.([sys_mid1, sys_mid1_comp, sys_mid1_ss])..., [d, p_mid1, sys_bot.d, sys_bot.p_bot]) | 
| 72 |  | -    @test all_sets_equal(parameters.([sys_mid2, sys_mid2_comp, sys_mid2_ss])..., [d, p_mid2]) | 
| 73 |  | -    @test all_sets_equal(parameters.([sys_top, sys_top_comp, sys_top_ss])..., [d, p_top, sys_mid1.d, sys_mid1.p_mid1, sys_mid1.sys_bot.d, sys_mid1.sys_bot.p_bot, sys_mid2.d, sys_mid2.p_mid2]) | 
|  | 75 | +    @test all_sets_equal(parameters.([sys_mid1, sys_mid1_comp, sys_mid1_ss])..., | 
|  | 76 | +        [d, p_mid1, sys_bot.d, sys_bot.p_bot]) | 
|  | 77 | +    @test all_sets_equal( | 
|  | 78 | +        parameters.([sys_mid2, sys_mid2_comp, sys_mid2_ss])..., [d, p_mid2]) | 
|  | 79 | +    @test all_sets_equal(parameters.([sys_top, sys_top_comp, sys_top_ss])..., | 
|  | 80 | +        [d, p_top, sys_mid1.d, sys_mid1.p_mid1, sys_mid1.sys_bot.d, | 
|  | 81 | +            sys_mid1.sys_bot.p_bot, sys_mid2.d, sys_mid2.p_mid2]) | 
| 74 | 82 | 
 | 
| 75 | 83 |     # Checks `parameters`` for `toplevel = true`. Compares to known parameters and also checks that | 
| 76 | 84 |     # these are subset of what `get_ps` returns. | 
| 77 |  | -    @test all_sets_equal(parameters.([sys_bot, sys_bot_comp, sys_bot_ss]; toplevel = true)..., [d, p_bot]) | 
| 78 |  | -    @test_broken all_sets_equal(parameters.([sys_mid1, sys_mid1_comp, sys_mid1_ss]; toplevel = true)..., [d, p_mid1]) | 
| 79 |  | -    @test all_sets_equal(parameters.([sys_mid2, sys_mid2_comp, sys_mid2_ss]; toplevel = true)..., [d, p_mid2]) | 
| 80 |  | -    @test_broken all_sets_equal(parameters.([sys_top, sys_top_comp, sys_top_ss]; toplevel = true)..., [d, p_top]) | 
| 81 |  | -    @test all(sym_issubset(parameters(sys; toplevel = true), get_ps(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
|  | 85 | +    @test all_sets_equal( | 
|  | 86 | +        parameters.([sys_bot, sys_bot_comp, sys_bot_ss]; toplevel = true)..., [d, p_bot]) | 
|  | 87 | +    @test_broken all_sets_equal( | 
|  | 88 | +        parameters.([sys_mid1, sys_mid1_comp, sys_mid1_ss]; toplevel = true)..., | 
|  | 89 | +        [d, p_mid1]) | 
|  | 90 | +    @test all_sets_equal( | 
|  | 91 | +        parameters.([sys_mid2, sys_mid2_comp, sys_mid2_ss]; toplevel = true)..., | 
|  | 92 | +        [d, p_mid2]) | 
|  | 93 | +    @test_broken all_sets_equal( | 
|  | 94 | +        parameters.([sys_top, sys_top_comp, sys_top_ss]; toplevel = true)..., [d, p_top]) | 
|  | 95 | +    @test all(sym_issubset(parameters(sys; toplevel = true), get_ps(sys)) | 
|  | 96 | +    for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
| 82 | 97 | 
 | 
| 83 | 98 |     # Checks `unknowns` for `toplevel = false`. O(t) is eliminated by `structural_simplify` and | 
| 84 | 99 |     # must be considered separately. | 
| 85 | 100 |     @test all_sets_equal(unknowns.([sys_bot, sys_bot_comp])..., [O, Y, X_bot]) | 
| 86 | 101 |     @test all_sets_equal(unknowns.([sys_bot_ss])..., [Y, X_bot]) | 
| 87 |  | -    @test all_sets_equal(unknowns.([sys_mid1, sys_mid1_comp])..., [O, Y, X_mid1, sys_bot.Y, sys_bot.O, sys_bot.X_bot]) | 
|  | 102 | +    @test all_sets_equal(unknowns.([sys_mid1, sys_mid1_comp])..., | 
|  | 103 | +        [O, Y, X_mid1, sys_bot.Y, sys_bot.O, sys_bot.X_bot]) | 
| 88 | 104 |     @test all_sets_equal(unknowns.([sys_mid1_ss])..., [Y, X_mid1, sys_bot.Y, sys_bot.X_bot]) | 
| 89 | 105 |     @test all_sets_equal(unknowns.([sys_mid2, sys_mid2_comp])..., [O, Y, X_mid2]) | 
| 90 | 106 |     @test all_sets_equal(unknowns.([sys_mid2_ss])..., [Y, X_mid2]) | 
| 91 |  | -    @test all_sets_equal(unknowns.([sys_top, sys_top_comp])..., [O, Y, X_top, sys_mid1.O, sys_mid1.Y, sys_mid1.X_mid1, sys_mid1.sys_bot.O, sys_mid1.sys_bot.Y, sys_mid1.sys_bot.X_bot, sys_mid2.O, sys_mid2.Y, sys_mid2.X_mid2]) | 
| 92 |  | -    @test all_sets_equal(unknowns.([sys_top_ss])..., [Y, X_top, sys_mid1.Y, sys_mid1.X_mid1, sys_mid1.sys_bot.Y, sys_mid1.sys_bot.X_bot, sys_mid2.Y, sys_mid2.X_mid2]) | 
|  | 107 | +    @test all_sets_equal(unknowns.([sys_top, sys_top_comp])..., | 
|  | 108 | +        [O, Y, X_top, sys_mid1.O, sys_mid1.Y, sys_mid1.X_mid1, | 
|  | 109 | +            sys_mid1.sys_bot.O, sys_mid1.sys_bot.Y, sys_mid1.sys_bot.X_bot, | 
|  | 110 | +            sys_mid2.O, sys_mid2.Y, sys_mid2.X_mid2]) | 
|  | 111 | +    @test all_sets_equal(unknowns.([sys_top_ss])..., | 
|  | 112 | +        [Y, X_top, sys_mid1.Y, sys_mid1.X_mid1, sys_mid1.sys_bot.Y, | 
|  | 113 | +            sys_mid1.sys_bot.X_bot, sys_mid2.Y, sys_mid2.X_mid2]) | 
| 93 | 114 | 
 | 
| 94 | 115 |     # Checks `unknowns` for `toplevel = true`. Note that O is not eliminated here (as we go back | 
| 95 | 116 |     # to original parent system). Also checks that outputs are subsets of what `get_ps` returns.. | 
| 96 |  | -    @test all_sets_equal(unknowns.([sys_bot, sys_bot_comp, sys_bot_ss]; toplevel = true)..., [O, Y, X_bot]) | 
| 97 |  | -    @test all_sets_equal(unknowns.([sys_mid1, sys_mid1_comp]; toplevel = true)..., [O, Y, X_mid1]) | 
| 98 |  | -    @test all_sets_equal(unknowns.([sys_mid2, sys_mid2_comp]; toplevel = true)..., [O, Y, X_mid2]) | 
| 99 |  | -    @test all_sets_equal(unknowns.([sys_top, sys_top_comp]; toplevel = true)..., [O, Y, X_top]) | 
| 100 |  | -    @test all(sym_issubset(unknowns(sys; toplevel = true), get_unknowns(sys)) for sys in [sys_bot, sys_mid1, sys_mid2, sys_top]) | 
|  | 117 | +    @test all_sets_equal( | 
|  | 118 | +        unknowns.([sys_bot, sys_bot_comp, sys_bot_ss]; toplevel = true)..., [O, Y, X_bot]) | 
|  | 119 | +    @test all_sets_equal( | 
|  | 120 | +        unknowns.([sys_mid1, sys_mid1_comp]; toplevel = true)..., [O, Y, X_mid1]) | 
|  | 121 | +    @test all_sets_equal( | 
|  | 122 | +        unknowns.([sys_mid2, sys_mid2_comp]; toplevel = true)..., [O, Y, X_mid2]) | 
|  | 123 | +    @test all_sets_equal( | 
|  | 124 | +        unknowns.([sys_top, sys_top_comp]; toplevel = true)..., [O, Y, X_top]) | 
|  | 125 | +    @test all(sym_issubset(unknowns(sys; toplevel = true), get_unknowns(sys)) | 
|  | 126 | +    for sys in [sys_bot, sys_mid1, sys_mid2, sys_top]) | 
| 101 | 127 | 
 | 
| 102 | 128 |     # Checks `equations` for `toplevel = false`. Do not check ss equations as these might potentially | 
| 103 | 129 |     # be structurally simplified to new equations. | 
| 104 | 130 |     @test all_sets_equal(equations.([sys_bot, sys_bot_comp])..., eqs_bot) | 
| 105 |  | -    @test all_sets_equal(equations.([sys_mid1, sys_mid1_comp])..., [eqs_mid1; namespace_equations(sys_bot)]) | 
|  | 131 | +    @test all_sets_equal( | 
|  | 132 | +        equations.([sys_mid1, sys_mid1_comp])..., [eqs_mid1; namespace_equations(sys_bot)]) | 
| 106 | 133 |     @test all_sets_equal(equations.([sys_mid2, sys_mid2_comp])..., eqs_mid2) | 
| 107 |  | -    @test all_sets_equal(equations.([sys_top, sys_top_comp])..., [eqs_top; namespace_equations(sys_mid1); namespace_equations(sys_mid2)]) | 
|  | 134 | +    @test all_sets_equal(equations.([sys_top, sys_top_comp])..., | 
|  | 135 | +        [eqs_top; namespace_equations(sys_mid1); namespace_equations(sys_mid2)]) | 
| 108 | 136 | 
 | 
| 109 | 137 |     # Checks `equations` for `toplevel = true`. Do not check ss equations  directly as these | 
| 110 | 138 |     # might potentially be structurally simplified to new equations. | 
| 111 | 139 |     @test all_sets_equal(equations.([sys_bot, sys_bot_comp]; toplevel = true)..., eqs_bot) | 
| 112 |  | -    @test all_sets_equal(equations.([sys_mid1, sys_mid1_comp]; toplevel = true)..., eqs_mid1) | 
| 113 |  | -    @test all_sets_equal(equations.([sys_mid2, sys_mid2_comp]; toplevel = true)..., eqs_mid2) | 
|  | 140 | +    @test all_sets_equal( | 
|  | 141 | +        equations.([sys_mid1, sys_mid1_comp]; toplevel = true)..., eqs_mid1) | 
|  | 142 | +    @test all_sets_equal( | 
|  | 143 | +        equations.([sys_mid2, sys_mid2_comp]; toplevel = true)..., eqs_mid2) | 
| 114 | 144 |     @test all_sets_equal(equations.([sys_top, sys_top_comp]; toplevel = true)..., eqs_top) | 
| 115 |  | -    @test all(sym_issubset(equations(sys; toplevel = true), get_eqs(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
|  | 145 | +    @test all(sym_issubset(equations(sys; toplevel = true), get_eqs(sys)) | 
|  | 146 | +    for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
| 116 | 147 | 
 | 
| 117 | 148 |     # Checks `observed for `toplevel = false`. For non-ss systems, there are no observables. | 
| 118 |  | -    @test all_sets_equal(observed.([sys_bot, sys_bot_comp, sys_mid1, sys_mid1_comp, sys_mid2, sys_mid2_comp, sys_top, sys_top_comp])..., []) | 
|  | 149 | +    @test all_sets_equal( | 
|  | 150 | +        observed.([sys_bot, sys_bot_comp, sys_mid1, sys_mid1_comp, | 
|  | 151 | +            sys_mid2, sys_mid2_comp, sys_top, sys_top_comp])..., | 
|  | 152 | +        []) | 
| 119 | 153 |     @test issetequal(observed(sys_bot_ss), eqs_bot[3:3]) | 
| 120 |  | -    @test issetequal(observed(sys_mid1_ss), [eqs_mid1[3:3]; namespace_equations(sys_bot)[3:3]]) | 
|  | 154 | +    @test issetequal( | 
|  | 155 | +        observed(sys_mid1_ss), [eqs_mid1[3:3]; namespace_equations(sys_bot)[3:3]]) | 
| 121 | 156 |     @test issetequal(observed(sys_mid2_ss), eqs_mid2[3:3]) | 
| 122 |  | -    @test issetequal(observed(sys_top_ss), [eqs_top[3:3]; namespace_equations(sys_mid1)[3:3:6]; namespace_equations(sys_mid2)[3:3]]) | 
|  | 157 | +    @test issetequal(observed(sys_top_ss), | 
|  | 158 | +        [eqs_top[3:3]; namespace_equations(sys_mid1)[3:3:6]; | 
|  | 159 | +         namespace_equations(sys_mid2)[3:3]]) | 
| 123 | 160 | 
 | 
| 124 | 161 |     # Checks `observed` for `toplevel = true`. Again, for non-ss systems, there are no observables. | 
| 125 | 162 |     # Also checks that `toplevel = true` yields subset of `get_observed`. | 
| 126 |  | -    @test all_sets_equal(observed.([sys_bot, sys_bot_comp, sys_mid1, sys_mid1_comp, sys_mid2, sys_mid2_comp, sys_top, sys_top_comp]; toplevel = true)..., []) | 
|  | 163 | +    @test all_sets_equal( | 
|  | 164 | +        observed.( | 
|  | 165 | +            [sys_bot, sys_bot_comp, sys_mid1, sys_mid1_comp, | 
|  | 166 | +                sys_mid2, sys_mid2_comp, sys_top, sys_top_comp]; | 
|  | 167 | +            toplevel = true)..., | 
|  | 168 | +        []) | 
| 127 | 169 |     @test_broken issetequal(observed(sys_bot_ss; toplevel = true), eqs_bot[3:3]) | 
| 128 | 170 |     @test_broken issetequal(observed(sys_mid1_ss; toplevel = true), eqs_mid1[3:3]) | 
| 129 | 171 |     @test_broken issetequal(observed(sys_mid2_ss; toplevel = true), eqs_mid2[3:3]) | 
| 130 | 172 |     @test_broken issetequal(observed(sys_top_ss; toplevel = true), eqs_top[3:3]) | 
| 131 |  | -    @test all(sym_issubset(observed(sys; toplevel = true), get_observed(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
|  | 173 | +    @test all(sym_issubset(observed(sys; toplevel = true), get_observed(sys)) | 
|  | 174 | +    for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
| 132 | 175 | 
 | 
| 133 | 176 |     # Checks `continuous_events` and  `discrete_events` for `toplevel = true` (more straightforward | 
| 134 | 177 |     # as I stored the same singe event in all systems). Don't check for `toplevel = false` as | 
| 135 | 178 |     # technically not needed for these tests and name spacing the events is a mess. | 
| 136 | 179 |     mtk_cev = ModelingToolkit.SymbolicContinuousCallback.(cevs)[1] | 
| 137 | 180 |     mtk_dev = ModelingToolkit.SymbolicDiscreteCallback.(devs)[1] | 
| 138 |  | -    @test all_sets_equal(continuous_events.([sys_bot, sys_bot_comp, sys_bot_ss, sys_mid1, sys_mid1_comp, sys_mid1_ss, sys_mid2, sys_mid2_comp, sys_mid2_ss, sys_top, sys_top_comp, sys_top_ss]; toplevel = true)..., [mtk_cev]) | 
| 139 |  | -    @test all_sets_equal(discrete_events.([sys_bot, sys_bot_comp, sys_bot_ss, sys_mid1, sys_mid1_comp, sys_mid1_ss, sys_mid2, sys_mid2_comp, sys_mid2_ss, sys_top, sys_top_comp, sys_top_ss]; toplevel = true)..., [mtk_dev]) | 
| 140 |  | -    @test all(sym_issubset(continuous_events(sys; toplevel = true), get_continuous_events(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
| 141 |  | -    @test all(sym_issubset(discrete_events(sys; toplevel = true), get_discrete_events(sys)) for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
|  | 181 | +    @test all_sets_equal( | 
|  | 182 | +        continuous_events.( | 
|  | 183 | +            [sys_bot, sys_bot_comp, sys_bot_ss, sys_mid1, sys_mid1_comp, sys_mid1_ss, | 
|  | 184 | +                sys_mid2, sys_mid2_comp, sys_mid2_ss, sys_top, sys_top_comp, sys_top_ss]; | 
|  | 185 | +            toplevel = true)..., | 
|  | 186 | +        [mtk_cev]) | 
|  | 187 | +    @test all_sets_equal( | 
|  | 188 | +        discrete_events.( | 
|  | 189 | +            [sys_bot, sys_bot_comp, sys_bot_ss, sys_mid1, sys_mid1_comp, sys_mid1_ss, | 
|  | 190 | +                sys_mid2, sys_mid2_comp, sys_mid2_ss, sys_top, sys_top_comp, sys_top_ss]; | 
|  | 191 | +            toplevel = true)..., | 
|  | 192 | +        [mtk_dev]) | 
|  | 193 | +    @test all(sym_issubset( | 
|  | 194 | +                  continuous_events(sys; toplevel = true), get_continuous_events(sys)) | 
|  | 195 | +    for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
|  | 196 | +    @test all(sym_issubset(discrete_events(sys; toplevel = true), get_discrete_events(sys)) | 
|  | 197 | +    for sys in [sys_bot, sys_mid2, sys_mid1, sys_top]) | 
| 142 | 198 | end | 
0 commit comments