Skip to content

Commit 3b8e8ed

Browse files
authored
Merge pull request #2152 from SciML/bgc/dummy_init
missing variable defaults function
2 parents 6db9402 + 0192046 commit 3b8e8ed

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

docs/src/basics/FAQ.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,36 @@ function loss(p)
9696
sum(abs2, sol)
9797
end
9898
```
99+
100+
# ERROR: ArgumentError: SymbolicUtils.BasicSymbolic{Real}[xˍt(t)] are missing from the variable map.
101+
102+
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.
103+
104+
```
105+
@variables t
106+
sts = @variables x1(t)=0.0 x2(t)=0.0 x3(t)=0.0 x4(t)=0.0
107+
D = Differential(t)
108+
eqs = [x1 + x2 + 1 ~ 0
109+
x1 + x2 + x3 + 2 ~ 0
110+
x1 + D(x3) + x4 + 3 ~ 0
111+
2 * D(D(x1)) + D(D(x2)) + D(D(x3)) + D(x4) + 4 ~ 0]
112+
@named sys = ODESystem(eqs, t)
113+
sys = structural_simplify(sys)
114+
prob = ODEProblem(sys, [], (0,1))
115+
```
116+
117+
We can solve this problem by using the `missing_variable_defaults()` function
118+
119+
```
120+
prob = ODEProblem(sys, ModelingToolkit.missing_variable_defaults(sys), (0,1))
121+
```
122+
123+
This function provides 0 for the default values, which is a safe assumption for dummy derivatives of most models. However, the 2nd arument allows for a different default value or values to be used if needed.
124+
125+
```
126+
julia> ModelingToolkit.missing_variable_defaults(sys, [1,2,3])
127+
3-element Vector{Pair}:
128+
x1ˍt(t) => 1
129+
x2ˍtt(t) => 2
130+
x3ˍtt(t) => 3
131+
```

src/systems/abstractsystem.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,3 +1756,31 @@ Base.:(∘)(sys1::AbstractSystem, sys2::AbstractSystem) = compose(sys1, sys2)
17561756
function UnPack.unpack(sys::ModelingToolkit.AbstractSystem, ::Val{p}) where {p}
17571757
getproperty(sys, p; namespace = false)
17581758
end
1759+
1760+
"""
1761+
missing_variable_defaults(sys::AbstractSystem, default = 0.0)
1762+
1763+
returns a `Vector{Pair}` of variables set to `default` which are missing from `get_defaults(sys)`. The `default` argument can be a single value or vector to set the missing defaults respectively.
1764+
"""
1765+
function missing_variable_defaults(sys::AbstractSystem, default = 0.0)
1766+
varmap = get_defaults(sys)
1767+
varmap = Dict(Symbolics.diff2term(value(k)) => value(varmap[k]) for k in keys(varmap))
1768+
missingvars = setdiff(states(sys), keys(varmap))
1769+
ds = Pair[]
1770+
1771+
n = length(missingvars)
1772+
1773+
if default isa Vector
1774+
@assert length(default)==n "`default` size ($(length(default))) should match the number of missing variables: $n"
1775+
end
1776+
1777+
for (i, missingvar) in enumerate(missingvars)
1778+
if default isa Vector
1779+
push!(ds, missingvar => default[i])
1780+
else
1781+
push!(ds, missingvar => default)
1782+
end
1783+
end
1784+
1785+
return ds
1786+
end

test/odesystem.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,18 @@ let
853853

854854
@named sys = ODESystem(eqs, t, u, ps)
855855
@test_nowarn simpsys = structural_simplify(sys)
856+
857+
sys = structural_simplify(sys)
858+
859+
u0 = ModelingToolkit.missing_variable_defaults(sys)
860+
u0_expected = Pair[s => 0.0 for s in states(sys)]
861+
@test string(u0) == string(u0_expected)
862+
863+
u0 = ModelingToolkit.missing_variable_defaults(sys, [1, 2])
864+
u0_expected = Pair[s => i for (i, s) in enumerate(states(sys))]
865+
@test string(u0) == string(u0_expected)
866+
867+
@test_nowarn ODEProblem(sys, u0, (0, 1))
856868
end
857869

858870
# https://github.com/SciML/ModelingToolkit.jl/issues/1583

0 commit comments

Comments
 (0)