Skip to content

Commit 0e742f7

Browse files
committed
Merge branch 'master' into myb/nonsq
2 parents 13d6228 + 5bb8d10 commit 0e742f7

File tree

9 files changed

+26
-24
lines changed

9 files changed

+26
-24
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelingToolkit"
22
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
33
authors = ["Yingbo Ma <[email protected]>", "Chris Rackauckas <[email protected]> and contributors"]
4-
version = "9.5.0"
4+
version = "9.6.0"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"

docs/src/tutorials/SampledData.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ k = ShiftIndex(clock)
3939
4040
eqs = [
4141
x(k) ~ 0.5x(k - 1) + u(k - 1),
42-
y(k) ~ x(k - 1)
42+
y ~ x
4343
]
4444
```
4545

@@ -49,13 +49,13 @@ A few things to note in this basic example:
4949
- `x` and `u` are automatically inferred to be discrete-time variables, since they appear in an equation with a discrete-time [`ShiftIndex`](@ref) `k`.
5050
- `y` is also automatically inferred to be a discrete-time-time variable, since it appears in an equation with another discrete-time variable `x`. `x,u,y` all belong to the same discrete-time partition, i.e., they are all updated at the same *instantaneous point in time* at which the clock ticks.
5151
- The equation `y ~ x` does not use any shift index, this is equivalent to `y(k) ~ x(k)`, i.e., discrete-time variables without shift index are assumed to refer to the variable at the current time step.
52-
- The equation `x(k) ~ 0.5x(k-1) + u(k-1)` indicates how `x` is updated, i.e., what the value of `x` will be at the *current* time step in terms of the *past* value. The output `y`, is given by the value of `x` at the *past* time step, i.e., `y(k) ~ x(k-1)`. If this logic was implemented in an imperative programming style, the logic would thus be
52+
- The equation `x(k) ~ 0.5x(k-1) + u(k-1)` indicates how `x` is updated, i.e., what the value of `x` will be at the *current* time step in terms of the *past* value. The output `y`, is given by the value of `x` at the *current* time step, i.e., `y(k) ~ x(k)`. If this logic was implemented in an imperative programming style, the logic would thus be
5353

5454
```julia
5555
function discrete_step(x, u)
56-
y = x # y is assigned the current value of x, y(k) = x(k-1)
5756
x = 0.5x + u # x is updated to a new value, i.e., x(k) is computed
58-
return x, y # The state x now refers to x at the current time step, x(k), while y refers to x at the past time step, y(k) = x(k-1)
57+
y = x # y is assigned the current value of x, y(k) = x(k)
58+
return x, y # The state x now refers to x at the current time step, x(k), and y equals x, y(k) = x(k)
5959
end
6060
```
6161

@@ -68,22 +68,21 @@ eqs = [
6868
]
6969
```
7070

71-
but the use of positive time shifts is not yet supported.
72-
Instead, we have *shifted all indices* by `-1`, resulting in exactly the same difference equations. However, the next system is *not equivalent* to the previous one:
71+
but the use of positive time shifts is not yet supported. Instead, we *shifted all indices* by `-1` above, resulting in exactly the same difference equations. However, the next system is *not equivalent* to the previous one:
7372

7473
```@example clocks
7574
eqs = [
76-
x(k) ~ 0.5x(k - 1) + u(k - 1),
75+
x(k) ~ 0.5x(k - 1) + u(k),
7776
y ~ x
7877
]
7978
```
8079

81-
In this last example, `y` refers to the updated `x(k)`, i.e., this system is equivalent to
80+
In this last example, `u(k)` refers to the input at the new time point `k`., this system is equivalent to
8281

8382
```
8483
eqs = [
85-
x(k+1) ~ 0.5x(k) + u(k),
86-
y(k+1) ~ x(k+1)
84+
x(k+1) ~ 0.5x(k) + u(k+1),
85+
y(k) ~ x(k)
8786
]
8887
```
8988

docs/src/tutorials/parameter_identifiability.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ After that, we are ready to check the system for local identifiability:
6969
```julia
7070
# query local identifiability
7171
# we pass the ode-system
72-
local_id_all = assess_local_identifiability(de, p = 0.99)
72+
local_id_all = assess_local_identifiability(de, prob_threshold = 0.99)
7373
```
7474

7575
We can see that all unknowns (except $x_7$) and all parameters are locally identifiable with probability 0.99.
@@ -78,7 +78,7 @@ Let's try to check specific parameters and their combinations
7878

7979
```julia
8080
to_check = [de.k5, de.k7, de.k10 / de.k9, de.k5 + de.k6]
81-
local_id_some = assess_local_identifiability(de, funcs_to_check = to_check, p = 0.99)
81+
local_id_some = assess_local_identifiability(de, funcs_to_check = to_check, prob_threshold = 0.99)
8282
```
8383

8484
Notice that in this case, everything (except the unknown variable $x_7$) is locally identifiable, including combinations such as $k_{10}/k_9, k_5+k_6$
@@ -183,7 +183,7 @@ end
183183
# check only 2 parameters
184184
to_check = [ode.b, ode.c]
185185

186-
global_id = assess_identifiability(ode, funcs_to_check = to_check, p = 0.9)
186+
global_id = assess_identifiability(ode, funcs_to_check = to_check, prob_threshold = 0.9)
187187
```
188188

189189
Both parameters `b, c` are globally identifiable with probability `0.9` in this case.

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -870,12 +870,15 @@ function process_DEProblem(constructor, sys::AbstractODESystem, u0map, parammap;
870870
if eltype(u0map) <: Number
871871
u0map = unknowns(sys) .=> u0map
872872
end
873+
if isempty(u0map)
874+
u0map = Dict()
875+
end
873876
initializeprob = ModelingToolkit.InitializationProblem(
874877
sys, t, u0map, parammap; guesses, warn_initialize_determined)
875878
initializeprobmap = getu(initializeprob, unknowns(sys))
876879

877-
zerovars = setdiff(unknowns(sys), keys(defaults(sys))) .=> 0.0
878-
trueinit = identity.([zerovars; u0map])
880+
zerovars = Dict(setdiff(unknowns(sys), keys(defaults(sys))) .=> 0.0)
881+
trueinit = collect(merge(zerovars, eltype(u0map) <: Pair ? todict(u0map) : u0map))
879882
u0map isa StaticArraysCore.StaticArray &&
880883
(trueinit = SVector{length(trueinit)}(trueinit))
881884
else
@@ -913,7 +916,6 @@ function process_DEProblem(constructor, sys::AbstractODESystem, u0map, parammap;
913916
du0 = nothing
914917
ddvs = nothing
915918
end
916-
917919
check_eqs_u0(eqs, dvs, u0; kwargs...)
918920

919921
f = constructor(sys, dvs, ps, u0; ddvs = ddvs, tgrad = tgrad, jac = jac,

src/systems/systemstructure.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ function _structural_simplify!(state::TearingState, io; simplify = false,
630630
if has_io
631631
ModelingToolkit.markio!(state, orig_inputs, io...)
632632
end
633-
if io !== nothing || any(isinput, state.fullvars)
633+
if io !== nothing
634634
state, input_idxs = ModelingToolkit.inputs_to_parameters!(state, io)
635635
else
636636
input_idxs = 0:-1 # Empty range

test/input_output_handling.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ end
5050
@test !is_bound(sys31, sys1.v[2])
5151

5252
# simplification turns input variables into parameters
53-
ssys = structural_simplify(sys)
53+
ssys, _ = structural_simplify(sys, ([u], []))
5454
@test ModelingToolkit.isparameter(unbound_inputs(ssys)[])
5555
@test !is_bound(ssys, u)
5656
@test u Set(unbound_inputs(ssys))
@@ -236,7 +236,7 @@ i = findfirst(isequal(u[1]), out)
236236
@variables x(t) u(t) [input = true]
237237
eqs = [D(x) ~ u]
238238
@named sys = ODESystem(eqs, t)
239-
@test_nowarn structural_simplify(sys)
239+
@test_nowarn structural_simplify(sys, ([u], []))
240240

241241
#=
242242
## Disturbance input handling

test/reduction.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ eqs = [D(x) ~ σ * (y - x)
234234
u ~ z + a]
235235

236236
lorenz1 = ODESystem(eqs, t, name = :lorenz1)
237-
lorenz1_reduced = structural_simplify(lorenz1)
237+
lorenz1_reduced, _ = structural_simplify(lorenz1, ([z], []))
238238
@test z in Set(parameters(lorenz1_reduced))
239239

240240
# #2064

test/serialization.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ probexpr = ODEProblemExpr{true}(ss, [capacitor.v => 0.0], (0, 0.1); observedfun_
6565
prob_obs = eval(probexpr)
6666
sol_obs = solve(prob_obs, ImplicitEuler())
6767
@show all_obs
68-
@test_broken sol_obs[all_obs] == sol[all_obs]
68+
@test sol_obs[all_obs] == sol[all_obs]

test/structural_transformation/tearing.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,10 @@ prob.f(du, u, pr, tt)
164164
@test du[u[2], u[1] + sin(u[2]) - pr * tt] atol=1e-5
165165

166166
# test the initial guess is respected
167-
@named sys = ODESystem(eqs, t, defaults = Dict(z => Inf))
167+
@named sys = ODESystem(eqs, t, defaults = Dict(z => NaN))
168168
infprob = ODEProblem(structural_simplify(sys), [x => 1.0], (0, 1.0), [p => 0.2])
169-
@test_throws Any infprob.f(du, infprob.u0, pr, tt)
169+
infprob.f(du, infprob.u0, pr, tt)
170+
@test any(isnan, du)
170171

171172
sol1 = solve(prob, RosShamp4(), reltol = 8e-7)
172173
sol2 = solve(ODEProblem{false}((u, p, t) -> [-asin(u[1] - pr * t)],

0 commit comments

Comments
 (0)