Skip to content

Commit 9ed1b73

Browse files
test: add extensive modelingtoolkitize tests
1 parent a8bae3c commit 9ed1b73

File tree

1 file changed

+169
-3
lines changed

1 file changed

+169
-3
lines changed

test/modelingtoolkitize.jl

Lines changed: 169 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using OrdinaryDiffEq, ModelingToolkit, DataStructures, Test
22
using Optimization, RecursiveArrayTools, OptimizationOptimJL
3+
using LabelledArrays, SymbolicIndexingInterface
4+
using ModelingToolkit: t_nounits as t, D_nounits as D
5+
using SciMLBase: parameterless_type
36

47
N = 32
58
const xyd_brusselator = range(0, stop = 1, length = N)
@@ -252,7 +255,6 @@ u0 = @LArray [9998.0, 1.0, 1.0, 1.0] (:S, :I, :R, :C)
252255
problem = ODEProblem(SIR!, u0, tspan, p)
253256
sys = complete(modelingtoolkitize(problem))
254257

255-
@parameters t
256258
@test all(isequal.(parameters(sys), getproperty.(@variables(β, η, ω, φ, σ, μ), :val)))
257259
@test all(isequal.(Symbol.(unknowns(sys)), Symbol.(@variables(S(t), I(t), R(t), C(t)))))
258260

@@ -291,9 +293,8 @@ sys = modelingtoolkitize(prob)
291293
@test [ModelingToolkit.defaults(sys)[s] for s in parameters(sys)] == [10, 20]
292294
@test ModelingToolkit.has_tspan(sys)
293295

294-
@parameters t sig=10 rho=28.0 beta=8 / 3
296+
@parameters sig=10 rho=28.0 beta=8 / 3
295297
@variables x(t)=100 y(t)=1.0 z(t)=1
296-
D = Differential(t)
297298

298299
eqs = [D(x) ~ sig * (y - x),
299300
D(y) ~ x * (rho - z) - y,
@@ -307,3 +308,168 @@ noiseeqs = [0.1 * x,
307308
prob = SDEProblem(complete(sys))
308309
sys = modelingtoolkitize(prob)
309310
@test ModelingToolkit.has_tspan(sys)
311+
312+
@testset "Explicit variable names" begin
313+
function fn(du, u, p::NamedTuple, t)
314+
du[1] = u[1] + p.a * u[2]
315+
du[2] = u[2] + p.b * u[1]
316+
end
317+
function fn(du, u, p::AbstractDict, t)
318+
du[1] = u[1] + p[:a] * u[2]
319+
du[2] = u[2] + p[:b] * u[1]
320+
end
321+
function fn(du, u, p, t)
322+
du[1] = u[1] + p[1] * u[2]
323+
du[2] = u[2] + p[2] * u[1]
324+
end
325+
function fn(du, u, p::Real, t)
326+
du[1] = u[1] + p * u[2]
327+
du[2] = u[2] + p * u[1]
328+
end
329+
function nl_fn(u, p::NamedTuple)
330+
[u[1] + p.a * u[2], u[2] + p.b * u[1]]
331+
end
332+
function nl_fn(u, p::AbstractDict)
333+
[u[1] + p[:a] * u[2], u[2] + p[:b] * u[1]]
334+
end
335+
function nl_fn(u, p)
336+
[u[1] + p[1] * u[2], u[2] + p[2] * u[1]]
337+
end
338+
function nl_fn(u, p::Real)
339+
[u[1] + p * u[2], u[2] + p * u[1]]
340+
end
341+
params = (a = 1, b = 1)
342+
odeprob = ODEProblem(fn, [1 1], (0, 1), params)
343+
nlprob = NonlinearProblem(nl_fn, [1, 1], params)
344+
optprob = OptimizationProblem(nl_fn, [1, 1], params)
345+
346+
@testset "$(parameterless_type(prob))" for prob in [optprob]
347+
sys = modelingtoolkitize(prob, u_names = [:a, :b])
348+
@test is_variable(sys, sys.a)
349+
@test is_variable(sys, sys.b)
350+
@test is_variable(sys, :a)
351+
@test is_variable(sys, :b)
352+
353+
@test_throws ["unknowns", "2", "does not match", "names", "3"] modelingtoolkitize(
354+
prob, u_names = [:a, :b, :c])
355+
for (pvals, pnames) in [
356+
([1, 2], [:p, :q]),
357+
((1, 2), [:p, :q]),
358+
([1, 2], Dict(1 => :p, 2 => :q)),
359+
((1, 2), Dict(1 => :p, 2 => :q)),
360+
(1.0, :p),
361+
(1.0, [:p]),
362+
(1.0, Dict(1 => :p)),
363+
(Dict(:a => 2, :b => 4), Dict(:a => :p, :b => :q)),
364+
(LVector(a = 1, b = 2), [:p, :q]),
365+
(SLVector(a = 1, b = 2), [:p, :q]),
366+
(LVector(a = 1, b = 2), Dict(1 => :p, 2 => :q)),
367+
(SLVector(a = 1, b = 2), Dict(1 => :p, 2 => :q)),
368+
((a = 1, b = 2), (a = :p, b = :q)),
369+
((a = 1, b = 2), Dict(:a => :p, :b => :q))
370+
]
371+
if pvals isa NamedTuple && prob isa OptimizationProblem
372+
continue
373+
end
374+
sys = modelingtoolkitize(
375+
remake(prob, p = pvals, interpret_symbolicmap = false), p_names = pnames)
376+
if pnames isa Symbol
377+
@test is_parameter(sys, pnames)
378+
continue
379+
end
380+
for p in values(pnames)
381+
@test is_parameter(sys, p)
382+
end
383+
end
384+
385+
for (pvals, pnames) in [
386+
([1, 2], [:p, :q, :r]),
387+
((1, 2), [:p, :q, :r]),
388+
([1, 2], Dict(1 => :p, 2 => :q, 3 => :r)),
389+
((1, 2), Dict(1 => :p, 2 => :q, 3 => :r)),
390+
(1.0, [:p, :q]),
391+
(1.0, Dict(1 => :p, 2 => :q)),
392+
(Dict(:a => 2, :b => 4), Dict(:a => :p, :b => :q, :c => :r)),
393+
(LVector(a = 1, b = 2), [:p, :q, :r]),
394+
(SLVector(a = 1, b = 2), [:p, :q, :r]),
395+
(LVector(a = 1, b = 2), Dict(1 => :p, 2 => :q, 3 => :r)),
396+
(SLVector(a = 1, b = 2), Dict(1 => :p, 2 => :q, 3 => :r)),
397+
((a = 1, b = 2), (a = :p, b = :q, c = :r)),
398+
((a = 1, b = 2), Dict(:a => :p, :b => :q, :c => :r))
399+
]
400+
newprob = remake(prob, p = pvals, interpret_symbolicmap = false)
401+
@test_throws [
402+
"parameters", "$(length(pvals))", "does not match", "$(length(pnames))"] modelingtoolkitize(
403+
newprob, p_names = pnames)
404+
end
405+
406+
sc = SymbolCache([:a, :b], [:p, :q])
407+
sci_f = parameterless_type(prob.f)(prob.f.f, sys = sc)
408+
newprob = remake(prob, f = sci_f, p = [1, 2])
409+
sys = modelingtoolkitize(newprob)
410+
@test is_variable(sys, sys.a)
411+
@test is_variable(sys, sys.b)
412+
@test is_variable(sys, :a)
413+
@test is_variable(sys, :b)
414+
@test is_parameter(sys, sys.p)
415+
@test is_parameter(sys, sys.q)
416+
@test is_parameter(sys, :p)
417+
@test is_parameter(sys, :q)
418+
end
419+
420+
@testset "From MTK model" begin
421+
@testset "ODE" begin
422+
@variables x(t)=1.0 y(t)=2.0
423+
@parameters p=3.0 q=4.0
424+
@mtkbuild sys = ODESystem([D(x) ~ p * y, D(y) ~ q * x], t)
425+
prob1 = ODEProblem(sys, [], (0.0, 5.0))
426+
newsys = complete(modelingtoolkitize(prob1))
427+
@test is_variable(newsys, newsys.x)
428+
@test is_variable(newsys, newsys.y)
429+
@test is_parameter(newsys, newsys.p)
430+
@test is_parameter(newsys, newsys.q)
431+
prob2 = ODEProblem(newsys, [], (0.0, 5.0))
432+
433+
sol1 = solve(prob1, Tsit5())
434+
sol2 = solve(prob2, Tsit5())
435+
@test sol1 sol2
436+
end
437+
@testset "Nonlinear" begin
438+
@variables x=1.0 y=2.0
439+
@parameters p=3.0 q=4.0
440+
@mtkbuild nlsys = NonlinearSystem([0 ~ p * y^2 + x, 0 ~ x + exp(x) * q])
441+
prob1 = NonlinearProblem(nlsys, [])
442+
newsys = complete(modelingtoolkitize(prob1))
443+
@test is_variable(newsys, newsys.x)
444+
@test is_variable(newsys, newsys.y)
445+
@test is_parameter(newsys, newsys.p)
446+
@test is_parameter(newsys, newsys.q)
447+
prob2 = NonlinearProblem(newsys, [])
448+
449+
sol1 = solve(prob1)
450+
sol2 = solve(prob2)
451+
@test sol1 sol2
452+
end
453+
@testset "Optimization" begin
454+
@variables begin
455+
x = 1.0, [bounds = (-2.0, 10.0)]
456+
y = 2.0, [bounds = (-1.0, 10.0)]
457+
end
458+
@parameters p=3.0 q=4.0
459+
loss = (p - x)^2 + q * (y - x^2)^2
460+
@mtkbuild optsys = OptimizationSystem(loss, [x, y], [p, q])
461+
prob1 = OptimizationProblem(optsys, [], grad = true, hess = true)
462+
newsys = complete(modelingtoolkitize(prob1))
463+
@test is_variable(newsys, newsys.x)
464+
@test is_variable(newsys, newsys.y)
465+
@test is_parameter(newsys, newsys.p)
466+
@test is_parameter(newsys, newsys.q)
467+
prob2 = OptimizationProblem(newsys, [], grad = true, hess = true)
468+
469+
sol1 = solve(prob1, GradientDescent())
470+
sol2 = solve(prob2, GradientDescent())
471+
472+
@test sol1 sol2
473+
end
474+
end
475+
end

0 commit comments

Comments
 (0)