Skip to content

Commit 761f5ea

Browse files
feat: allow remade initialization systems to be incomplete
1 parent 083a639 commit 761f5ea

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem,
12941294
fully_determined = nothing,
12951295
check_units = true,
12961296
use_scc = true,
1297+
allow_incomplete = false,
12971298
kwargs...) where {iip, specialize}
12981299
if !iscomplete(sys)
12991300
error("A completed system is required. Call `complete` or `structural_simplify` on the system before creating an `ODEProblem`")
@@ -1335,7 +1336,13 @@ function InitializationProblem{iip, specialize}(sys::AbstractSystem,
13351336
# TODO: throw on uninitialized arrays
13361337
filter!(x -> !(x isa Symbolics.Arr), uninit)
13371338
if !isempty(uninit)
1338-
throw(IncompleteInitializationError(uninit))
1339+
allow_incomplete || throw(IncompleteInitializationError(uninit))
1340+
# for incomplete initialization, we will add the missing variables as parameters.
1341+
# they will be updated by `update_initializeprob!` and `initializeprobmap` will
1342+
# use them to construct the new `u0`.
1343+
newparams = map(toparam, uninit)
1344+
append!(get_ps(isys), newparams)
1345+
isys = complete(isys)
13391346
end
13401347

13411348
neqs = length(equations(isys))

src/systems/nonlinear/initializesystem.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ function SciMLBase.remake_initialization_data(
317317
u0map[dvs[i]] = newu0[i]
318318
end
319319
end
320+
# ensure all unknowns have guesses in case they weren't given one
321+
# and become solvable
322+
for i in eachindex(dvs)
323+
haskey(guesses, dvs[i]) && continue
324+
guesses[dvs[i]] = newu0[i]
325+
end
320326
if p === missing
321327
# the user didn't pass `p` to `remake`, so they want to retain
322328
# existing values. Fill all parameters in `pmap` so that none of
@@ -341,7 +347,8 @@ function SciMLBase.remake_initialization_data(
341347
op, missing_unknowns, missing_pars = build_operating_point(
342348
u0map, pmap, defs, cmap, dvs, ps)
343349
kws = maybe_build_initialization_problem(
344-
sys, op, u0map, pmap, t0, defs, guesses, missing_unknowns; use_scc, initialization_eqs)
350+
sys, op, u0map, pmap, t0, defs, guesses, missing_unknowns;
351+
use_scc, initialization_eqs, allow_incomplete = true)
345352
return get(kws, :initialization_data, nothing)
346353
end
347354

src/systems/problem_utils.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,10 @@ function maybe_build_initialization_problem(
545545
(!is_time_dependent(sys) || t !== nothing)
546546
initializeprob = ModelingToolkit.InitializationProblem(
547547
sys, t, u0map, pmap; guesses, kwargs...)
548-
initializeprobmap = getu(initializeprob, unknowns(sys))
548+
549+
all_init_syms = Set(all_symbols(initializeprob))
550+
solved_unknowns = filter(var -> var in all_init_syms, unknowns(sys))
551+
initializeprobmap = getu(initializeprob, solved_unknowns)
549552

550553
punknowns = [p
551554
for p in all_variable_symbols(initializeprob)

test/initializationsystem.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,3 +1282,27 @@ end
12821282

12831283
@test SciMLBase.successful_retcode(solve(newprob))
12841284
end
1285+
1286+
@testset "Issue#3295: Incomplete initialization of pure-ODE systems" begin
1287+
@variables X(t) Y(t)
1288+
@parameters p d
1289+
eqs = [
1290+
D(X) ~ p - d * X,
1291+
D(Y) ~ p - d * Y
1292+
]
1293+
@mtkbuild osys = ODESystem(eqs, t)
1294+
1295+
# Make problem.
1296+
u0_vals = [X => 4, Y => 5.0]
1297+
tspan = (0.0, 10.0)
1298+
p_vals = [p => 1.0, d => 0.1]
1299+
oprob = ODEProblem(osys, u0_vals, tspan, p_vals)
1300+
integ = init(oprob)
1301+
@test integ[X] 4.0
1302+
@test integ[Y] 5.0
1303+
# Attempt to `remake`.
1304+
rp = remake(oprob; u0 = [Y => 7])
1305+
integ = init(rp)
1306+
@test integ[X] 4.0
1307+
@test integ[Y] 7.0
1308+
end

0 commit comments

Comments
 (0)