# ModelingToolkit change parameter vector size based on structural parameter

**URL:** https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914
**Category:** General Usage
**Tags:** question, modelingtoolkit
**Created:** [February 8, 2024, 8:54am UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914 "2024-02-08T08:54:04Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)
#### Post date: [February 8, 2024, 8:54am UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914/1 "2024-02-08T08:54:04Z")

</div>

Hi all, I’m trying to model a nonlinear component with `@mtkmodel` in `ModelingToolkit`.

The base model with a given nonlinerity order (3 in this case) is

```julia
@mtkmodel NLComponent begin
    @parameters begin
        r[1:3]
    end

    @components begin
        origin = Flange()
        target = Flange()
    end

    @variables begin
        l(t)
        c(t)
    end

    @equations begin
        l ~ origin.s - target.s
        c ~ -(sum(r[p] * l^p for p in axes(r, 1)))
    end
end

```

While that works fine, I’m trying to allow the component to support generic polynomial non-linearity. I tried to make this work with a `structural_parameter` to specify the order of the non-linearity, though it would have been even better to have the size be inferred from the size of `r` directly, but that does not seem feasible.

```julia
@mtkmodel NLComponent begin
    @structural_parameters begin
        n = 1
    end
    @parameters begin
        r[1:n]
    end

    @components begin
        origin = Flange()
        target = Flange()
    end

    @variables begin
        l(t)
        c(t)
    end

    @equations begin
        l ~ origin.s - target.s
        c ~ -(sum(r[p] * l^p for p in axes(r, 1)))
    end
end

```

However that does not work as well and fails with

> ERROR: LoadError: promotion of types Int64 and Symbol failed to change any arguments  
> Stacktrace:  
> [1] error(::String, ::String, ::String)  
> @ Base .\error.jl:44  
> [2] sametype\_error(input::Tuple{Int64, Symbol})  
> @ Base .\promotion.jl:417  
> [3] not\_sametype(x::Tuple{Int64, Symbol}, y::Tuple{Int64, Symbol})  
> @ Base .\promotion.jl:411  
> [4] promote  
> @ .\promotion.jl:394 [inlined]  
> [5] UnitRange(start::Int64, stop::Symbol)  
> @ Base .\range.jl:408  
> [6] (::ModelingToolkit.var"#174#175")(i::Expr)  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:181  
> [7] iterate(g::Base.Generator, s::Vararg{Any})  
> @ Base .\generator.jl:47 [inlined]  
> [8] \_collect(c::SubArray{…}, itr::Base.Generator{…}, ::Base.EltypeUnknown, isz::Base.HasShape{…})  
> @ Base .\array.jl:854  
> [9] collect\_similar  
> @ .\array.jl:763 [inlined]  
> [10] map  
> @ .\abstractarray.jl:3282 [inlined]  
> [11] parse\_variable\_def!(dict::Dict{…}, mod::Module, arg::Expr, varclass::Symbol, kwargs::Set{…}; def::Nothing, indices::Nothing)  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:181  
> [12] parse\_variable\_def!  
> @ D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:109 [inlined]  
> [13] parse\_variable\_arg(dict::Dict{Symbol, Any}, mod::Module, arg::Expr, varclass::Symbol, kwargs::Set{Any})  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:428  
> [14] parse\_variable\_arg!(exprs::Vector{…}, vs::Vector{…}, dict::Dict{…}, mod::Module, arg::Expr, varclass::Symbol, kwargs::Set{…})  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:422  
> [15] parse\_variables!(exprs::Vector{…}, vs::Vector{…}, dict::Dict{…}, mod::Module, body::Expr, varclass::Symbol, kwargs::Set{…})  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:533  
> [16] parse\_model!(exprs::Vector{…}, comps::Vector{…}, ext::Base.RefValue{…}, eqs::Vector{…}, icon::Base.RefValue{…}, vs::Vector{…}, ps::Vector{…}, sps::Vector{…}, dict::Dict{…}, mod::Module, arg::Expr, kwargs::Set{…})  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:292  
> [17] \_model\_macro(mod::Module, name::Symbol, expr::Expr, isconnector::Bool)  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:55  
> [18] var"@mtkmodel"( **source** ::LineNumberNode, **module** ::Module, name::Symbol, body::Any)  
> @ ModelingToolkit D:\<user\>.julia\packages\ModelingToolkit\Gpzyo\src\systems\model\_parsing.jl:31

I thought that `structural_parameters` where designed for such branching of the code, but I’m probably using them the wrong way.  
Side note, `@structural_parameters` does not seem to be exported in `ModelingToolkit` v8.75.0

---

<div class="post-metadata">

### Author: ![ven-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ven-k/32/11915_2.png) [@ven-k](https://discourse.julialang.org/u/ven-k)
#### Post date: [February 8, 2024, 9:43am UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914/2 "2024-02-08T09:43:08Z")

</div>

Yeah, I have noticed this error. RN, parameter and variable array length should be defined while defining the model.

I plan to change of couple of things to allow users to pass array length.

---

<div class="post-metadata">

### Author: ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)
#### Post date: [February 8, 2024, 9:57am UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914/3 "2024-02-08T09:57:38Z")

</div>

Thanks, do you want me to open an issue ? Can you confirm there is no problem with writing the summation this way in the `@equations` block ?

---

<div class="post-metadata">

### Author: ![ven-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ven-k/32/11915_2.png) [@ven-k](https://discourse.julialang.org/u/ven-k)
#### Post date: [February 8, 2024, 2:59pm UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914/4 "2024-02-08T14:59:27Z")

</div>

I’ve created this: [Allow variable array length for parameters in `@mtkmodel` · Issue #2453 · SciML/ModelingToolkit.jl · GitHub](https://github.com/SciML/ModelingToolkit.jl/issues/2453)

The equations came out

```julia
julia> equations(nlc)
2-element Vector{Equation}:
 l(t) ~ -target₊s(t) + origin₊s(t)
 c(t) ~ -r[1]*l(t) - r[2]*(l(t)^2) - r[3]*(l(t)^3)

```

Looks good to me.

---

<div class="post-metadata">

### Author: ![fabianmueller](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabianmueller/32/202905_2.png) [@fabianmueller](https://discourse.julialang.org/u/fabianmueller)
#### Post date: [June 15, 2024, 6:30pm UTC](https://discourse.julialang.org/t/modelingtoolkit-change-parameter-vector-size-based-on-structural-parameter/109914/5 "2024-06-15T18:30:39Z")

</div>

Referring also to: [Cannot use structural parameter as array size · Issue #2704 · SciML/ModelingToolkit.jl (github.com)](https://github.com/SciML/ModelingToolkit.jl/issues/2704)

When I put the parameters and variables declaration out of the mtkmodel macro it works:

```julia
nr_species = 3
nr_inputs = 2

@parameters begin
    A[1:nr_species, 1:nr_inputs]
end

@variables begin
    c(t)[1:nr_species]
    u(t)[1:nr_inputs]
end

@mtkmodel Model begin

    @equations begin
        D(c) ~ A * u
        u ~ [1.0, 2.0]
    end
end

@mtkbuild sys = Model()

```

However, defining it inside the macro results in the error:

```julia
nr_species = 3
nr_inputs = 2

@mtkmodel Model begin

    @parameters begin
        A[1:nr_species, 1:nr_inputs]
    end
    
    @variables begin
        c(t)[1:nr_species]
        u(t)[1:nr_inputs]
    end
    
    @equations begin
        D(c) ~ A * u
        u ~ [1.0, 2.0]
    end
end

@mtkbuild sys = Model()

```

Is there any problem with using the first code? Since I would like to be able to change the order of the model based on some user input.
