# @unpack from Catalyst reaction system and unused variables

**URL:** <https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766>\
**Category:** Chemistry\
**Tags:** modelingtoolkit, catalyst\
**Created:** [February 26, 2024, 10:36am UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766 "2024-02-26T10:36:06Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![johannesnauta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johannesnauta/32/47434_2.png) [@johannesnauta](https://discourse.julialang.org/u/johannesnauta)\
**Post date:** [February 26, 2024, 10:36am UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/1 "2024-02-26T10:36:06Z")

</div>

Hi all. I have happily been using `Catalyst.jl` (and of course related packages, such as `ModelingToolkit.jl` and `DifferentialEquations.jl`), but when remaking problems while using `EnsembleProblem` I encountered some odd behavior. In general, when I am making my reaction systems, many of the parameters end up being unused. That means, when I use the `@variables a[1:N]` to create `N` variables, these come back when I use the `@unpack` macro, even though the parameters are not in the reaction system.

To illustrate this, consider the following simple MWE of logistic growth

```julia
using Catalyst

N = 4
@variables t
@species (x(t))[1:N]
@parameters a[1:N]

rxs = Array{Any}(undef, N)

for n in 1:N
    if n != 4
        rxs[n] = Reaction(a[n]*(1-x[n]), [x[n]], [x[n]], [1], [2])
    else
        rxs[n] = Reaction(1, [x[n]], [x[n]], [1], [2])
    end
end

@named rs = ReactionSystem(rxs)

```

In this example I have not used `a[4]`, and indeed when doing `parameters(rs)` this parameter does not appear in the parameters.

```julia
julia> parameters(rs)
3-element Vector{SymbolicUtils.BasicSymbolic{Real}}:
 a[1]
 a[2]
 a[3]

```

Yet, when using the `@unpack` macro, it does

```julia
julia> @unpack a = rs; a
a[1:4]

```

This becomes strange when using `remake(...)` as I am basically specify the value of (in my case, many) parameters that are not even in the reaction system. While I can potentially filter `a` by using the reaction system directly, e.g. something along the lines of

```julia
julia> p = Symbolics.Num.(ModelingToolkit.parameters(prob.f.sys))
julia> [_a => avalues for _a in a if any(isequal.(_a, p))]

```

this imposes a _heavy_ computation time burden as `any(...)` of course needs to loop over the array until it finds some. As I have large systems with many parameters these loops slow down my code by a lot.

So,

1. is there a way of extracting/unpacking only the parameters that are present in the reaction system?, and
2. why does `@unpack` also unpack these variables even though they are not contained in the reaction system?

Many thanks.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 1:54pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/2 "2024-02-26T13:54:39Z")

</div>

Do you see the same issue with a directly defined `ODESystem`? Catalyst doesn’t really do anything different from ModelingToolkit as far as I am aware (in fact, `@unpack` is from ModelingToolkit where it is defined for general `AbstractSystem`s), so I think this is likely an issue with how the macro is defined in ModelingToolkit.

Also, keep in mind that ModelingToolkit just released a major, new breaking version (V9), and Catalyst does not support it yet. So this behavior may now be completely different on V9. I’d suggest seeing if ModelingToolkit V9 has fixed this issue for a normal `ODESystem`, and if not, open an issue about it there. If it is fixed then Catalyst V14 should automatically pick up whatever changes ModelingToolkit has made.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 1:56pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/3 "2024-02-26T13:56:34Z")

</div>

The `@unpack` behavior you are seeing may actually be the desired behavior in V9 of MTK now – you are declaring an array parameter so it may no longer treat the components as separate individual parameters internally (I think there have been some changes in that regard).

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 2:06pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/4 "2024-02-26T14:06:57Z")

</div>

Some other things you could try

- Filter and save the list of `a`’s from `parameters(rs)` to later use in `remake` at system construction (so you only need to do it once).
- Use namespaced indexing, i.e. right after building your system complete it, `rs = complete(rs)`, and then use `rs.a[2]` to access a given variable.
- Finally, `remake` itself may have some issues currently. The change to using `SymbolicIndexingInterface` led to many code changes in SciMLBase, and `remake` in particular still hasn’t been fully fixed I think. (But I’m not sure what does/doesn’t work currently.)

---

<div class="post-metadata">

**Author:** ![johannesnauta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johannesnauta/32/47434_2.png) [@johannesnauta](https://discourse.julialang.org/u/johannesnauta)\
**Post date:** [February 26, 2024, 3:04pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/5 "2024-02-26T15:04:19Z")

</div>

Yeah I believe when making an `ODESystem` the problem persists, e.g.

```julia
julia> odesys = ModelingToolkit.convert(ODESystem, rs)
Model rs with 4 equations
States (4):
  (x(t))[1]
  (x(t))[2]
  (x(t))[3]
  (x(t))[4]
Parameters (3):
  a[1]
  a[2]
  a[3]

julia> @unpack a = odesys;

julia> a
a[1:4]

```

---

<div class="post-metadata">

**Author:** ![johannesnauta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johannesnauta/32/47434_2.png) [@johannesnauta](https://discourse.julialang.org/u/johannesnauta)\
**Post date:** [February 26, 2024, 3:06pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/6 "2024-02-26T15:06:38Z")

</div>

I can indeed understand why this might be desired behavior. After all, one might want to set different parameters (or parameter indices) to 0 depending on the run, for example. When excluding these from the parameter list this becomes more troublesome I would say. Although I feel like one should be able to declare an array parameter where only specific elements of the array are non-zero. It happens in my systems a lot, where the array (or matrix) parameters of the systems are in reality relatively sparse.

I will try the suggested things. The first one was already on my list, but I am still not sure what to pass to the `prob_func` when declaring the `EnsembleProblem`. I assumed that, in general, “global” variables are not desirable so that I had to extract the relevant parameters from the `ODEProblem` (or `prob.f.sys`, or similar).

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 3:19pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/7 "2024-02-26T15:19:10Z")

</div>

Make a parametric function-like object to store whatever data you need, and then define it as your `prob_func`, see [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects) for example. This avoids a global variable to store the `a`s.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 3:20pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/8 "2024-02-26T15:20:57Z")

</div>

More generally, if you feel there are interface issues in updating parameters within an array parameter I would encourage you to open an issue on ModelingToolkit for further discussion.

---

<div class="post-metadata">

**Author:** ![johannesnauta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johannesnauta/32/47434_2.png) [@johannesnauta](https://discourse.julialang.org/u/johannesnauta)\
**Post date:** [February 26, 2024, 3:21pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/9 "2024-02-26T15:21:47Z")

</div>

Will do in the future.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [February 26, 2024, 3:26pm UTC](https://discourse.julialang.org/t/unpack-from-catalyst-reaction-system-and-unused-variables/110766/10 "2024-02-26T15:26:27Z")

</div>

Sounds good! Array parameters have been clunky for a while. I think MTKv9 is / has addressed this by trying to make how they work more uniform and simple, but I’m not sure if all the planned updates with respect to array parameters are completed now.
