|  | 
| 1 |  | -using ModelingToolkit, SymbolicIndexingInterface | 
|  | 1 | +using ModelingToolkit, SymbolicIndexingInterface, SciMLStructures | 
| 2 | 2 | using ModelingToolkit: t_nounits as t | 
| 3 | 3 | 
 | 
| 4 | 4 | # Ensure indexes of array symbolics are cached appropriately | 
| @@ -43,3 +43,52 @@ ic = ModelingToolkit.get_index_cache(sys) | 
| 43 | 43 | @test isequal(ic.symbol_to_variable[:x], x) | 
| 44 | 44 | @test isequal(ic.symbol_to_variable[:y], y) | 
| 45 | 45 | @test isequal(ic.symbol_to_variable[:z], z) | 
|  | 46 | + | 
|  | 47 | +@testset "tunable_parameters is ordered" begin | 
|  | 48 | +    @parameters p q[1:3] r[1:2, 1:2] s [tunable = false] | 
|  | 49 | +    @named sys = ODESystem(Equation[], t, [], [p, q, r, s]) | 
|  | 50 | +    sys = complete(sys) | 
|  | 51 | +    @test all(splat(isequal), zip(tunable_parameters(sys), parameters(sys)[1:3])) | 
|  | 52 | + | 
|  | 53 | +    offset = 1 | 
|  | 54 | +    for par in tunable_parameters(sys) | 
|  | 55 | +        idx = parameter_index(sys, par) | 
|  | 56 | +        @test idx.portion isa SciMLStructures.Tunable | 
|  | 57 | +        if Symbolics.isarraysymbolic(par) | 
|  | 58 | +            @test vec(idx.idx) == offset:(offset + length(par) - 1) | 
|  | 59 | +        else | 
|  | 60 | +            @test idx.idx == offset | 
|  | 61 | +        end | 
|  | 62 | +        offset += length(par) | 
|  | 63 | +    end | 
|  | 64 | +end | 
|  | 65 | + | 
|  | 66 | +@testset "reorder_dimension_by_tunables" begin | 
|  | 67 | +    @parameters p q[1:3] r[1:2, 1:2] s [tunable = false] | 
|  | 68 | +    @named sys = ODESystem(Equation[], t, [], [p, q, r, s]) | 
|  | 69 | +    src = ones(8) | 
|  | 70 | +    dst = zeros(8) | 
|  | 71 | +    # system must be complete... | 
|  | 72 | +    @test_throws ArgumentError reorder_dimension_by_tunables!(dst, sys, src, [p, q, r]) | 
|  | 73 | +    @test_throws ArgumentError reorder_dimension_by_tunables(sys, src, [p, q, r]) | 
|  | 74 | +    sys = complete(sys; split = false) | 
|  | 75 | +    # with split = true... | 
|  | 76 | +    @test_throws ArgumentError reorder_dimension_by_tunables!(dst, sys, src, [p, q, r]) | 
|  | 77 | +    @test_throws ArgumentError reorder_dimension_by_tunables(sys, src, [p, q, r]) | 
|  | 78 | +    sys = complete(sys) | 
|  | 79 | +    # and the arrays must have matching size | 
|  | 80 | +    @test_throws ArgumentError reorder_dimension_by_tunables!( | 
|  | 81 | +        zeros(2, 4), sys, src, [p, q, r]) | 
|  | 82 | + | 
|  | 83 | +    ps = MTKParameters(sys, [p => 1.0, q => 3ones(3), r => 4ones(2, 2), s => 0.0]) | 
|  | 84 | +    src = ps.tunable | 
|  | 85 | +    reorder_dimension_by_tunables!(dst, sys, src, [q, r, p]) | 
|  | 86 | +    @test dst ≈ vcat(3ones(3), 4ones(4), 1.0) | 
|  | 87 | +    @test reorder_dimension_by_tunables(sys, src, [r, p, q]) ≈ vcat(4ones(4), 1.0, 3ones(3)) | 
|  | 88 | +    reorder_dimension_by_tunables!(dst, sys, src, [q[1], r[:, 1], q[2], r[:, 2], q[3], p]) | 
|  | 89 | +    @test dst ≈ vcat(3.0, 4ones(2), 3.0, 4ones(2), 3.0, 1.0) | 
|  | 90 | +    src = stack([copy(ps.tunable) for i in 1:5]; dims = 1) | 
|  | 91 | +    dst = zeros(size(src)) | 
|  | 92 | +    reorder_dimension_by_tunables!(dst, sys, src, [r, q, p]; dim = 2) | 
|  | 93 | +    @test dst ≈ stack([vcat(4ones(4), 3ones(3), 1.0) for i in 1:5]; dims = 1) | 
|  | 94 | +end | 
0 commit comments