# Mass Spring Damper with BlockSystems.jl

**URL:** <https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981>\
**Category:** General Usage\
**Created:** [April 27, 2023, 4:04am UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981 "2023-04-27T04:04:18Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![bryaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryaan/32/36858_2.png) [@bryaan](https://discourse.julialang.org/u/bryaan)\
**Post date:** [April 27, 2023, 4:04am UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981/1 "2023-04-27T04:04:19Z")

</div>

How does one add a proportional constant k and a damping constant b to this IOBlock to setup a spring mass damper transfer function?

```julia
using BlockSystems
using ModelingToolkit

@parameters t M F(t)
@variables x(t) v(t)
D = Differential(t)

msd = IOBlock([D(v) ~ F/M, D(x) ~ v], # define the equation
                     [F], # inputs of the system
                     [x], # outputs of the system
                     name = :msd)

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [April 27, 2023, 6:23am UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981/2 "2023-04-27T06:23:31Z")

</div>

> [@bryaan](#):
>
> `D(v) ~ F/M, D(x) ~ v`

You’d have to modify those equations to include the stiffness and damping terms.

Alternatively, if you want to use a component-based modeling approach, you could use ModelingToolkit directly. An example building a MSD system can be found [here](https://help.juliahub.com/juliasimcontrol/dev/examples/mtk_control/)

---

<div class="post-metadata">

**Author:** ![bryaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryaan/32/36858_2.png) [@bryaan](https://discourse.julialang.org/u/bryaan)\
**Post date:** [April 27, 2023, 3:28pm UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981/3 "2023-04-27T15:28:44Z")

</div>

This is what I came up with.

```julia
spacecraft = IOBlock([D(v) ~ -(KK/M)*x + -(B/M)*v + (F/M), D(x) ~ v], # define the equation
                     [F], # inputs of the system
                     [x], # outputs of the system
                     name = :spacecraft)

```

Now how do I set the K and B variables in the ODE Solver? They go in the p vector right? But what determines the ordering?

From the spacecraft [example](https://github.com/hexaeder/BlockSystems.jl/blob/main/examples/spacecraft.jl):

```julia
p = [0.5, 1.0] # K, m # Here we need to add KK and B 
u0 = [0.0, 0.0] # altitude, v
tspan = (0.0, 30.0)
prob = ODEProblem(odefun, u0, tspan, p)
sol = solve(prob, Tsit5())

```

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [April 28, 2023, 6:03am UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981/4 "2023-04-28T06:03:33Z")

</div>

I’ve created `BlockSystems.jl` at a time where component based modeling was far more complicated in vanilla MTK than it is now. Since it is/was highly specialized for my specific usecase I would not necessarily recommend it for starting a new project now – i think it is worth using MTK directly. Eventually I want to revisit BlockSystems to make it a much thinner MTK wrapper than it is now, but that for sure will be quite breaking.

If you still want to use BlockSystems: in order to solve the system you always have to generate a callable Julia function based on the symbolic model. You can use [`generate_io_function`](https://github.com/hexaeder/BlockSystems.jl/blob/9bd369954b18ca66936fb1d833f00fde108beca2/src/function_generation.jl#L3-L36) for a low level interface or

```julia
odefun = ODEFunction(iob::IOBlock; f_states=Symbol[], f_params=Symbol[])

```

for a more high level interface. The ordering of states and parameters can be passed explicitly. Otherwise they’ll match the order of `iob.iparams` (the internal parameters) and `states = vcat(iob.outputs, iob.istates)` (stacked vector of output states and internal states).

However in order to create a ODEFunction/ODEProblem you need to close all the inputs first. There are plenty options to do that, either create other blocks and connect them or use something like

```julia
@variables t
@parameters omega
closed_spacecraft = set_input(spacecraft, F => sin(omega * t))

```

to direclty close the input with that specific function. Now `closed_spacecraft.iparams` should show `[:omega, :KK, :B]` in some order.

If you don’t want to specify the parameters at solve time you may also bake them into the generated code by something like

```julia
closed_spacecraft = replace_vars(closed_spacecraft, :omega=>10, :B=>4)

```

which would leave you with a single free parameter `:KK` and so on.

---

<div class="post-metadata">

**Author:** ![bryaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryaan/32/36858_2.png) [@bryaan](https://discourse.julialang.org/u/bryaan)\
**Post date:** [April 29, 2023, 1:51am UTC](https://discourse.julialang.org/t/mass-spring-damper-with-blocksystems-jl/97981/5 "2023-04-29T01:51:27Z")

</div>

Thanks for the info. Im also looking at ControlSystems.jl and related libs.

Will have to try what you have suggested.
