Skip to content

Commit ff8d231

Browse files
Merge pull request #2436 from AayushSabharwal/as/require-completed
refactor!: require systems to be `complete`d before creating `XProblem`/`XProblemExpr`
2 parents ce450b2 + a779f4b commit ff8d231

40 files changed

+202
-63
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 <mayingbo5@gmail.com>", "Chris Rackauckas <accounts@chrisrackauckas.com> and contributors"]
4-
version = "9.0.0"
4+
version = "8.76.0"
55

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

docs/src/basics/Events.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function UnitMassWithFriction(k; name)
7373
ODESystem(eqs, t; continuous_events = [v ~ 0], name) # when v = 0 there is a discontinuity
7474
end
7575
@named m = UnitMassWithFriction(0.7)
76-
prob = ODEProblem(m, Pair[], (0, 10pi))
76+
prob = ODEProblem(complete(m), Pair[], (0, 10pi))
7777
sol = solve(prob, Tsit5())
7878
plot(sol)
7979
```
@@ -244,7 +244,7 @@ u0 = [N => 0.0]
244244
tspan = (0.0, 20.0)
245245
p = [α => 100.0, tinject => 10.0, M => 50]
246246
@named osys = ODESystem(eqs, t, [N], [α, M, tinject]; discrete_events = injection)
247-
oprob = ODEProblem(osys, u0, tspan, p)
247+
oprob = ODEProblem(complete(osys), u0, tspan, p)
248248
sol = solve(oprob, Tsit5(); tstops = 10.0)
249249
plot(sol)
250250
```

docs/src/examples/parsing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ using ModelingToolkit, NonlinearSolve
2727
vars = union(ModelingToolkit.vars.(eqs)...)
2828
@named ns = NonlinearSystem(eqs, vars, [])
2929
30-
prob = NonlinearProblem(ns, [1.0, 1.0, 1.0])
30+
prob = NonlinearProblem(complete(ns), [1.0, 1.0, 1.0])
3131
sol = solve(prob, NewtonRaphson())
3232
```

docs/src/examples/sparse_jacobians.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Now let's use `modelingtoolkitize` to generate the symbolic version:
5555

5656
```@example sparsejac
5757
sys = modelingtoolkitize(prob);
58+
sys = complete(sys);
5859
nothing # hide
5960
```
6061

docs/src/tutorials/bifurcation_diagram_computation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ using ModelingToolkit
1313
eqs = [0 ~ μ * x - x^3 + α * y,
1414
0 ~ -y]
1515
@named nsys = NonlinearSystem(eqs, [x, y], [μ, α])
16+
nsys = complete(nsys)
1617
```
1718

1819
we wish to compute a bifurcation diagram for this system as we vary the parameter `μ`. For this, we need to provide the following information:
@@ -97,6 +98,7 @@ D = Differential(t)
9798
eqs = [D(x) ~ μ * x - y - x * (x^2 + y^2),
9899
D(y) ~ x + μ * y - y * (x^2 + y^2)]
99100
@named osys = ODESystem(eqs, t)
101+
osys = complete(osys)
100102
101103
bif_par = μ
102104
plot_var = x

docs/src/tutorials/modelingtoolkitize.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,5 @@ sys = modelingtoolkitize(prob)
5858
Using this, we can symbolically build the Jacobian and then rebuild the ODEProblem:
5959

6060
```@example mtkize
61-
prob_jac = ODEProblem(sys, [], (0.0, 1e5), jac = true)
61+
prob_jac = ODEProblem(complete(sys), [], (0.0, 1e5), jac = true)
6262
```

docs/src/tutorials/nonlinear.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ eqs = [0 ~ σ * (y - x),
1717
0 ~ x * (ρ - z) - y,
1818
0 ~ x * y - β * z]
1919
@named ns = NonlinearSystem(eqs, [x, y, z], [σ, ρ, β])
20+
ns = complete(ns)
2021
2122
guess = [x => 1.0,
2223
y => 0.0,

docs/src/tutorials/optimization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ u0 = [x => 1.0
5050
p = [a => 1.0
5151
b => 100.0]
5252
53-
prob = OptimizationProblem(sys, u0, p, grad = true, hess = true)
53+
prob = OptimizationProblem(complete(sys), u0, p, grad = true, hess = true)
5454
solve(prob, GradientDescent())
5555
```
5656

@@ -71,7 +71,7 @@ cons = [
7171
@named sys = OptimizationSystem(loss, [x, y], [a, b], constraints = cons)
7272
u0 = [x => 0.14
7373
y => 0.14]
74-
prob = OptimizationProblem(sys, u0, grad = true, hess = true, cons_j = true, cons_h = true)
74+
prob = OptimizationProblem(complete(sys), u0, grad = true, hess = true, cons_j = true, cons_h = true)
7575
solve(prob, IPNewton())
7676
```
7777

docs/src/tutorials/stochastic_diffeq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ noiseeqs = [0.1 * x,
2424
0.1 * z]
2525
2626
@named de = SDESystem(eqs, noiseeqs, t, [x, y, z], [σ, ρ, β])
27+
de = complete(de)
2728
2829
u0map = [
2930
x => 1.0,

ext/MTKBifurcationKitExt.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem,
8888
record_from_solution = BifurcationKit.record_sol_default,
8989
jac = true,
9090
kwargs...)
91+
if !ModelingToolkit.iscomplete(nsys)
92+
error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`")
93+
end
9194
# Creates F and J functions.
9295
ofun = NonlinearFunction(nsys; jac = jac)
9396
F = ofun.f
@@ -133,11 +136,14 @@ end
133136

134137
# When input is a ODESystem.
135138
function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...)
139+
if !ModelingToolkit.iscomplete(osys)
140+
error("A completed `ODESystem` is required. Call `complete` or `structural_simplify` on the system before creating a `BifurcationProblem`")
141+
end
136142
nsys = NonlinearSystem([0 ~ eq.rhs for eq in equations(osys)],
137143
unknowns(osys),
138144
parameters(osys);
139145
name = nameof(osys))
140-
return BifurcationKit.BifurcationProblem(nsys, args...; kwargs...)
146+
return BifurcationKit.BifurcationProblem(complete(nsys), args...; kwargs...)
141147
end
142148

143149
end # module

src/systems/abstractsystem.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,8 @@ information. E.g.
13301330
```julia-repl
13311331
julia> sys = debug_system(sys);
13321332
1333+
julia> sys = complete(sys);
1334+
13331335
julia> prob = ODEProblem(sys, [], (0, 1.0));
13341336
13351337
julia> du = zero(prob.u0);

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ function DiffEqBase.ODEFunction{iip, specialize}(sys::AbstractODESystem, dvs = u
308308
analytic = nothing,
309309
split_idxs = nothing,
310310
kwargs...) where {iip, specialize}
311+
if !iscomplete(sys)
312+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunction`")
313+
end
311314
f_gen = generate_function(sys, dvs, ps; expression = Val{eval_expression},
312315
expression_module = eval_module, checkbounds = checkbounds,
313316
kwargs...)
@@ -504,6 +507,9 @@ function DiffEqBase.DAEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys)
504507
eval_module = @__MODULE__,
505508
checkbounds = false,
506509
kwargs...) where {iip}
510+
if !iscomplete(sys)
511+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEFunction`")
512+
end
507513
f_gen = generate_function(sys, dvs, ps; implicit_dae = true,
508514
expression = Val{eval_expression},
509515
expression_module = eval_module, checkbounds = checkbounds,
@@ -579,6 +585,9 @@ function DiffEqBase.DDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys)
579585
eval_module = @__MODULE__,
580586
checkbounds = false,
581587
kwargs...) where {iip}
588+
if !iscomplete(sys)
589+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DDEFunction`")
590+
end
582591
f_gen = generate_function(sys, dvs, ps; isdde = true,
583592
expression = Val{true},
584593
expression_module = eval_module, checkbounds = checkbounds,
@@ -603,6 +612,9 @@ function DiffEqBase.SDDEFunction{iip}(sys::AbstractODESystem, dvs = unknowns(sys
603612
eval_module = @__MODULE__,
604613
checkbounds = false,
605614
kwargs...) where {iip}
615+
if !iscomplete(sys)
616+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `SDDEFunction`")
617+
end
606618
f_gen = generate_function(sys, dvs, ps; isdde = true,
607619
expression = Val{true},
608620
expression_module = eval_module, checkbounds = checkbounds,
@@ -656,6 +668,9 @@ function ODEFunctionExpr{iip}(sys::AbstractODESystem, dvs = unknowns(sys),
656668
sparsity = false,
657669
observedfun_exp = nothing,
658670
kwargs...) where {iip}
671+
if !iscomplete(sys)
672+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEFunctionExpr`")
673+
end
659674
f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...)
660675

661676
dict = Dict()
@@ -830,6 +845,9 @@ function DAEFunctionExpr{iip}(sys::AbstractODESystem, dvs = unknowns(sys),
830845
linenumbers = false,
831846
sparse = false, simplify = false,
832847
kwargs...) where {iip}
848+
if !iscomplete(sys)
849+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `DAEFunctionExpr`")
850+
end
833851
f_oop, f_iip = generate_function(sys, dvs, ps; expression = Val{true},
834852
implicit_dae = true, kwargs...)
835853
fsym = gensym(:f)
@@ -891,6 +909,9 @@ function DiffEqBase.ODEProblem{iip, specialize}(sys::AbstractODESystem, u0map =
891909
callback = nothing,
892910
check_length = true,
893911
kwargs...) where {iip, specialize}
912+
if !iscomplete(sys)
913+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`")
914+
end
894915
f, u0, p = process_DEProblem(ODEFunction{iip, specialize}, sys, u0map, parammap;
895916
t = tspan !== nothing ? tspan[1] : tspan,
896917
check_length, kwargs...)
@@ -959,6 +980,9 @@ end
959980
function DiffEqBase.DAEProblem{iip}(sys::AbstractODESystem, du0map, u0map, tspan,
960981
parammap = DiffEqBase.NullParameters();
961982
check_length = true, kwargs...) where {iip}
983+
if !iscomplete(sys)
984+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblem`")
985+
end
962986
f, du0, u0, p = process_DEProblem(DAEFunction{iip}, sys, u0map, parammap;
963987
implicit_dae = true, du0map = du0map, check_length,
964988
kwargs...)
@@ -984,6 +1008,9 @@ function DiffEqBase.DDEProblem{iip}(sys::AbstractODESystem, u0map = [],
9841008
callback = nothing,
9851009
check_length = true,
9861010
kwargs...) where {iip}
1011+
if !iscomplete(sys)
1012+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DDEProblem`")
1013+
end
9871014
f, u0, p = process_DEProblem(DDEFunction{iip}, sys, u0map, parammap;
9881015
t = tspan !== nothing ? tspan[1] : tspan,
9891016
symbolic_u0 = true,
@@ -1042,6 +1069,9 @@ function DiffEqBase.SDDEProblem{iip}(sys::AbstractODESystem, u0map = [],
10421069
check_length = true,
10431070
sparsenoise = nothing,
10441071
kwargs...) where {iip}
1072+
if !iscomplete(sys)
1073+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SDDEProblem`")
1074+
end
10451075
f, u0, p = process_DEProblem(SDDEFunction{iip}, sys, u0map, parammap;
10461076
t = tspan !== nothing ? tspan[1] : tspan,
10471077
symbolic_u0 = true,
@@ -1126,6 +1156,9 @@ struct ODEProblemExpr{iip} end
11261156
function ODEProblemExpr{iip}(sys::AbstractODESystem, u0map, tspan,
11271157
parammap = DiffEqBase.NullParameters(); check_length = true,
11281158
kwargs...) where {iip}
1159+
if !iscomplete(sys)
1160+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `ODEProblemExpr`")
1161+
end
11291162
f, u0, p = process_DEProblem(ODEFunctionExpr{iip}, sys, u0map, parammap; check_length,
11301163
kwargs...)
11311164
linenumbers = get(kwargs, :linenumbers, true)
@@ -1168,6 +1201,9 @@ struct DAEProblemExpr{iip} end
11681201
function DAEProblemExpr{iip}(sys::AbstractODESystem, du0map, u0map, tspan,
11691202
parammap = DiffEqBase.NullParameters(); check_length = true,
11701203
kwargs...) where {iip}
1204+
if !iscomplete(sys)
1205+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `DAEProblemExpr`")
1206+
end
11711207
f, du0, u0, p = process_DEProblem(DAEFunctionExpr{iip}, sys, u0map, parammap;
11721208
implicit_dae = true, du0map = du0map, check_length,
11731209
kwargs...)
@@ -1216,6 +1252,9 @@ end
12161252
function DiffEqBase.SteadyStateProblem{iip}(sys::AbstractODESystem, u0map,
12171253
parammap = SciMLBase.NullParameters();
12181254
check_length = true, kwargs...) where {iip}
1255+
if !iscomplete(sys)
1256+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblem`")
1257+
end
12191258
f, u0, p = process_DEProblem(ODEFunction{iip}, sys, u0map, parammap;
12201259
steady_state = true,
12211260
check_length, kwargs...)
@@ -1245,6 +1284,9 @@ function SteadyStateProblemExpr{iip}(sys::AbstractODESystem, u0map,
12451284
parammap = SciMLBase.NullParameters();
12461285
check_length = true,
12471286
kwargs...) where {iip}
1287+
if !iscomplete(sys)
1288+
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating a `SteadyStateProblemExpr`")
1289+
end
12481290
f, u0, p = process_DEProblem(ODEFunctionExpr{iip}, sys, u0map, parammap;
12491291
steady_state = true,
12501292
check_length, kwargs...)

src/systems/diffeqs/basic_transformations.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ u0 = [x => 1.0,
3131
y => 1.0,
3232
trJ => 1.0]
3333
34-
prob = ODEProblem(sys2,u0,tspan,p)
34+
prob = ODEProblem(complete(sys2),u0,tspan,p)
3535
sol = solve(prob,Tsit5())
3636
```
3737

src/systems/diffeqs/sdesystem.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ parammap = [
322322
β => 1.0
323323
]
324324
325-
probmod = SDEProblem(demod,u0modmap,(0.0,1.0),parammap)
325+
probmod = SDEProblem(complete(demod),u0modmap,(0.0,1.0),parammap)
326326
ensemble_probmod = EnsembleProblem(probmod;
327327
output_func = (sol,i) -> (g(sol[x,end])*sol[demod.weight,end],false),
328328
)
@@ -393,6 +393,9 @@ function DiffEqBase.SDEFunction{iip}(sys::SDESystem, dvs = unknowns(sys),
393393
jac = false, Wfact = false, eval_expression = true,
394394
checkbounds = false,
395395
kwargs...) where {iip}
396+
if !iscomplete(sys)
397+
error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunction`")
398+
end
396399
dvs = scalarize.(dvs)
397400
ps = scalarize.(ps)
398401

@@ -515,6 +518,9 @@ function SDEFunctionExpr{iip}(sys::SDESystem, dvs = unknowns(sys),
515518
jac = false, Wfact = false,
516519
sparse = false, linenumbers = false,
517520
kwargs...) where {iip}
521+
if !iscomplete(sys)
522+
error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEFunctionExpr`")
523+
end
518524
idx = iip ? 2 : 1
519525
f = generate_function(sys, dvs, ps; expression = Val{true}, kwargs...)[idx]
520526
g = generate_diffusion_function(sys, dvs, ps; expression = Val{true}, kwargs...)[idx]
@@ -573,6 +579,9 @@ function DiffEqBase.SDEProblem{iip}(sys::SDESystem, u0map = [], tspan = get_tspa
573579
parammap = DiffEqBase.NullParameters();
574580
sparsenoise = nothing, check_length = true,
575581
callback = nothing, kwargs...) where {iip}
582+
if !iscomplete(sys)
583+
error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblem`")
584+
end
576585
f, u0, p = process_DEProblem(SDEFunction{iip}, sys, u0map, parammap; check_length,
577586
kwargs...)
578587
cbs = process_events(sys; callback)
@@ -632,6 +641,9 @@ function SDEProblemExpr{iip}(sys::SDESystem, u0map, tspan,
632641
parammap = DiffEqBase.NullParameters();
633642
sparsenoise = nothing, check_length = true,
634643
kwargs...) where {iip}
644+
if !iscomplete(sys)
645+
error("A completed `SDESystem` is required. Call `complete` or `structural_simplify` on the system before creating an `SDEProblemExpr`")
646+
end
635647
f, u0, p = process_DEProblem(SDEFunctionExpr{iip}, sys, u0map, parammap; check_length,
636648
kwargs...)
637649
linenumbers = get(kwargs, :linenumbers, true)

src/systems/jumps/jumpsystem.jl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem
119119
connector_type, devents, metadata, gui_metadata, complete)
120120
end
121121
end
122+
JumpSystem(tag, ap, iv, states, ps, var_to_name, args...; kwargs...) = JumpSystem{typeof(ap)}(tag, ap, iv, states, ps, var_to_name, args...; kwargs...)
122123

123124
function JumpSystem(eqs, iv, unknowns, ps;
124125
observed = Equation[],
@@ -289,14 +290,17 @@ using DiffEqBase, JumpProcesses
289290
u₀map = [S => 999, I => 1, R => 0]
290291
parammap = [β => 0.1 / 1000, γ => 0.01]
291292
tspan = (0.0, 250.0)
292-
dprob = DiscreteProblem(js, u₀map, tspan, parammap)
293+
dprob = DiscreteProblem(complete(js), u₀map, tspan, parammap)
293294
```
294295
"""
295296
function DiffEqBase.DiscreteProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, Nothing},
296297
parammap = DiffEqBase.NullParameters();
297298
checkbounds = false,
298299
use_union = true,
299300
kwargs...)
301+
if !iscomplete(sys)
302+
error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`")
303+
end
300304
dvs = unknowns(sys)
301305
ps = parameters(sys)
302306

@@ -344,7 +348,7 @@ using DiffEqBase, JumpProcesses
344348
u₀map = [S => 999, I => 1, R => 0]
345349
parammap = [β => 0.1 / 1000, γ => 0.01]
346350
tspan = (0.0, 250.0)
347-
dprob = DiscreteProblem(js, u₀map, tspan, parammap)
351+
dprob = DiscreteProblem(complete(js), u₀map, tspan, parammap)
348352
```
349353
"""
350354
struct DiscreteProblemExpr{iip} end
@@ -353,6 +357,9 @@ function DiscreteProblemExpr{iip}(sys::JumpSystem, u0map, tspan::Union{Tuple, No
353357
parammap = DiffEqBase.NullParameters();
354358
use_union = false,
355359
kwargs...) where {iip}
360+
if !iscomplete(sys)
361+
error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblemExpr`")
362+
end
356363
dvs = unknowns(sys)
357364
ps = parameters(sys)
358365
defs = defaults(sys)
@@ -382,12 +389,15 @@ Generates a JumpProblem from a JumpSystem.
382389
Continuing the example from the [`DiscreteProblem`](@ref) definition:
383390
384391
```julia
385-
jprob = JumpProblem(js, dprob, Direct())
392+
jprob = JumpProblem(complete(js), dprob, Direct())
386393
sol = solve(jprob, SSAStepper())
387394
```
388395
"""
389396
function JumpProcesses.JumpProblem(js::JumpSystem, prob, aggregator; callback = nothing,
390397
kwargs...)
398+
if !iscomplete(js)
399+
error("A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `JumpProblem`")
400+
end
391401
unknowntoid = Dict(value(unknown) => i for (i, unknown) in enumerate(unknowns(js)))
392402
eqs = equations(js)
393403
invttype = prob.tspan[1] === nothing ? Float64 : typeof(1 / prob.tspan[2])

0 commit comments

Comments
 (0)