|  | 
| 1 | 1 | using ModelingToolkit, OrdinaryDiffEq, DataInterpolations, DynamicQuantities, Test | 
| 2 | 2 | using ModelingToolkitStandardLibrary.Blocks: RealInput, RealOutput | 
|  | 3 | +using SymbolicUtils: symtype | 
| 3 | 4 | 
 | 
| 4 | 5 | @independent_variables t | 
| 5 | 6 | D = Differential(t) | 
|  | 
| 328 | 329 |            D(x) ~ y] | 
| 329 | 330 |     @test issetequal(equations(asys), eqs) | 
| 330 | 331 | end | 
|  | 332 | + | 
|  | 333 | +abstract type AbstractFoo end | 
|  | 334 | + | 
|  | 335 | +struct Bar <: AbstractFoo end | 
|  | 336 | +struct Baz <: AbstractFoo end | 
|  | 337 | + | 
|  | 338 | +foofn(x) = 4 | 
|  | 339 | +@register_symbolic foofn(x::AbstractFoo) | 
|  | 340 | + | 
|  | 341 | +@testset "`respecialize`" begin | 
|  | 342 | +    @parameters p::AbstractFoo p2(t)::AbstractFoo = p q[1:2]::AbstractFoo r | 
|  | 343 | +    rp, | 
|  | 344 | +    rp2 = let | 
|  | 345 | +        only(@parameters p::Bar), | 
|  | 346 | +        SymbolicUtils.term(operation(p2), arguments(p2)...; type = Baz) | 
|  | 347 | +    end | 
|  | 348 | +    @variables x(t) = 1.0 | 
|  | 349 | +    @named sys1 = System([D(x) ~ foofn(p) + foofn(p2) + x], t, [x], [p, p2, q, r]) | 
|  | 350 | + | 
|  | 351 | +    @test_throws ["completed systems"] respecialize(sys1) | 
|  | 352 | +    @test_throws ["completed systems"] respecialize(sys1, []) | 
|  | 353 | +    @test_throws ["split systems"] respecialize(complete(sys1; split = false)) | 
|  | 354 | +    @test_throws ["split systems"] respecialize(complete(sys1; split = false), []) | 
|  | 355 | + | 
|  | 356 | +    sys = complete(sys1) | 
|  | 357 | + | 
|  | 358 | +    @test_throws ["Parameter p", "associated value"] respecialize(sys) | 
|  | 359 | +    @test_throws ["Parameter p", "associated value"] respecialize(sys, [p]) | 
|  | 360 | + | 
|  | 361 | +    @test_throws ["Parameter p2", "symbolic default"] respecialize(sys, [p2]) | 
|  | 362 | + | 
|  | 363 | +    sys2 = respecialize(sys, [p => Bar()]) | 
|  | 364 | +    @test ModelingToolkit.iscomplete(sys2) | 
|  | 365 | +    @test ModelingToolkit.is_split(sys2) | 
|  | 366 | +    ps = ModelingToolkit.get_ps(sys2) | 
|  | 367 | +    idx = findfirst(isequal(rp), ps) | 
|  | 368 | +    @test defaults(sys2)[rp] == Bar() | 
|  | 369 | +    @test symtype(ps[idx]) <: Bar | 
|  | 370 | +    ic = ModelingToolkit.get_index_cache(sys2) | 
|  | 371 | +    @test any(x -> x.type == Bar && x.length == 1, ic.nonnumeric_buffer_sizes) | 
|  | 372 | +    prob = ODEProblem(sys2, [p2 => Bar(), q => [Bar(), Bar()], r => 1], (0.0, 1.0)) | 
|  | 373 | +    @test any(x -> x isa Vector{Bar} && length(x) == 1, prob.p.nonnumeric) | 
|  | 374 | + | 
|  | 375 | +    defaults(sys)[p2] = Baz() | 
|  | 376 | +    sys2 = respecialize(sys, [p => Bar()]; all = true) | 
|  | 377 | +    @test ModelingToolkit.iscomplete(sys2) | 
|  | 378 | +    @test ModelingToolkit.is_split(sys2) | 
|  | 379 | +    ps = ModelingToolkit.get_ps(sys2) | 
|  | 380 | +    idx = findfirst(isequal(rp2), ps) | 
|  | 381 | +    @test defaults(sys2)[rp2] == Baz() | 
|  | 382 | +    @test symtype(ps[idx]) <: Baz | 
|  | 383 | +    ic = ModelingToolkit.get_index_cache(sys2) | 
|  | 384 | +    @test any(x -> x.type == Baz && x.length == 1, ic.nonnumeric_buffer_sizes) | 
|  | 385 | +    delete!(defaults(sys), p2) | 
|  | 386 | +    prob = ODEProblem(sys2, [q => [Bar(), Bar()], r => 1], (0.0, 1.0)) | 
|  | 387 | +    @test any(x -> x isa Vector{Bar} && length(x) == 1, prob.p.nonnumeric) | 
|  | 388 | +    @test any(x -> x isa Vector{Baz} && length(x) == 1, prob.p.nonnumeric) | 
|  | 389 | + | 
|  | 390 | +    @test_throws ["Numeric types cannot be respecialized"] respecialize(sys, [r => 1]) | 
|  | 391 | +    @test_throws ["array symbolics"] respecialize(sys, [q => Bar[Bar(), Bar()]]) | 
|  | 392 | +    @test_throws ["scalarized array"] respecialize(sys, [q[1] => Bar()]) | 
|  | 393 | + | 
|  | 394 | +    @parameters foo::AbstractFoo | 
|  | 395 | +    @test_throws ["does not exist"] respecialize(sys, [foo => Bar()]) | 
|  | 396 | +end | 
0 commit comments