# \[NEW\] SimpleSim.jl: A minimalist Julia package for modular dynamical systems simulation

**URL:** <https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308>\
**Category:** Package Announcements\
**Tags:** dynamical-systems, simulations, controlsystems\
**Created:** [October 14, 2024, 10:14pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308 "2024-10-14T22:14:50Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 14, 2024, 10:14pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/1 "2024-10-14T22:14:50Z")

</div>

Hello everyone,

I’m very happy to announce my first larger Julia package `SimpleSim.jl` which is now available on the Julia package registry!

`SimpleSim.jl` aims at being a lightweight simulation engine 100% written in Julia with support for systems described by (continuous-time) ordinary differential equations or discrete-time processes.  
Hence, the package can be used to simulate most physical and digital systems, which makes it perfect for robotics but also other areas.

Below, I will briefly describe how the package works for anyone only reading on Julia discourse.  
If you want to learn more, please read the [documentation](https://janneshb.github.io/SimpleSim.jl/). All features currently available are documented there in a lot more detail.

The package itself lives in [this GitHub repo](https://github.com/janneshb/SimpleSim.jl).

## Overview of Features

- Simulation/numerical solutions of ordinary differential equations
- Integrated support for different ODE solvers (Euler, Heun, RK4, Adaptive RKF45)
- Simulation of discrete processes
- Simulation of models with both continous-time processes (ODEs) and discrete-time processes (“hybrid” models)
- Zero-crossing detection for continuous-time system states
- Random variable handling for repeatable results
- Support for nested model structures

## How it works

The main point of interaction with the package is the `simulate` function. Let’s say you have set up a model object `my_model` that contains all of the physics and processes you want to simulate (more on that later). Then, simulating that model can be done by running

```julia-auto
data = simulate(my_model, T = 10 // 1)

```

where `T` denotes the total time the simulation will be run for.

The package does not export any types and only very few functions/macros. The whole “design process” of what a model could look like is left up to the user.  
For example, if you want to simulate a continuous-time ODE system, `SimpleSim.jl` only expects your model to have the named fields `p`, `fc` and `yc`. The field `p` can contain model parameters, or it can be set to `nothing` if parameters aren’t needed.  
`fc` defines the models behavior. It should contain a function taking the arguments `(x, u, p, t)` for the current state, input, parameters and time of the model, and returns the state derivative. `yc` takes the same arguments, but returns the current system output.

For example, if you want to simulate a falling object without air resistance, i.e. a double integrator of the gravitational constant, a complete model and simulation looks like this:

```julia-auto
falling_object = (
    p = (g = 9.81,)
    fc = (z, u, p, t) -> [z[2], -p.g],
    yc = (z, u, p, t) -> z[1],
)
data = simulate(falling_object, T = 3 // 1, xc0 = [0, 0])

```

These few lines of code will create a valid `SimpleSim.jl` model and will simulate it for 3 seconds.  
The resulting `data` object has the fields `tcs`, `xcs` and `ycs` which contain the time, state and output evolution of the system.

If you want to simulate a more complex system, it may make sense to define your own types. Just make sure your model provides the necessary named fields as interfaces for `SimpleSim.jl`.  
If you are just using `SimpleSim.jl` to numerically solve an ODE, then defining a model as a `NamedTuple` (like above) works just fine.

## Some Simple Examples

An extension of the “falling object” example from above is a ball bouncing down a flight of stairs. This example also makes use of `SimpleSim.jl`’s zero-crossing detection feature.  
 ![Bouncing Ball](https://global.discourse-cdn.com/julialang/original/3X/6/5/6523c6ab57b8da1bee25e64f0e96b60a31866dc4.gif)

An example of a discrete process would be the random walk below. This example also uses `SimplSim.jl`’s random variable handling.  
 ![Random Walk](https://global.discourse-cdn.com/julialang/original/3X/d/1/d1bb1bc93d54269f182deda4137559b20ddea1e2.gif)

I have written quite a few more examples, which you can find in the [project repo](https://github.com/janneshb/SimpleSim.jl/tree/main/examples). I will make sure to document these examples a bit better soon. Especially the more complex and nested models `SimpleSim.jl` is capable of handling are not very well documented at the moment.

## Nested Models

A key feature of `SimpleSim.jl`’s is its support for nested models. For example, if you want to simulate a whole airplane, you don’t have to set up a single differential equation that describes every aspect of the aircraft’s behavior. Instead, you model each component of the system separately and define separate models. Then, you use a supermodel that “calls” your components and makes sure they receive the correct inputs. Nesting on multiple levels is also possible.

The support for nested models may be `SimpleSim.jl`’s most powerful feature. It allows you to implement models in a very similar way to how you would draw block diagrams. If you want to learn more about this, please read the [documentation](https://janneshb.github.io/SimpleSim.jl/) and take a look at the [examples](https://github.com/janneshb/SimpleSim.jl/tree/main/examples).

## What I still want to improve

All core features are implemented and fully functional (I think). But of course there are still things that I would like to improve and you are more than welcome to contribute.  
I have listed a few ideas for future work on the issues page on GitHub.

If you have read all the way until here, let me know what you think! 🙂  
Best,  
Jannes

---

<div class="post-metadata">

**Author:** ![tuckermcclure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tuckermcclure/32/1187_2.png) [@tuckermcclure](https://discourse.julialang.org/u/tuckermcclure)\
**Post date:** [October 16, 2024, 4:19pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/2 "2024-10-16T16:19:01Z")

</div>

Nice! Thank you for sharing this, @janneshb. I’m going to share with a few folks that have been looking for something like this.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [October 16, 2024, 5:03pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/3 "2024-10-16T17:03:14Z")

</div>

One question I have is: What could ModelingToolkit and co learn from your package? I think ModelingToolkit still does not support hybrid systems well.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 16, 2024, 5:12pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/4 "2024-10-16T17:12:33Z")

</div>

I don’t think `ModelingToolkit` supports hybrid systems. Its system types are always distinctly ODE/PDE/Discrete etc. (correct me if I’m wrong).  
So, as you said, that’s already something `SimpleSim` has over `ModelingToolkit`.

But in my opinion the best things about `SimpleSim` are:

- Nested models. You can implement a discrete or continuos-time model as a submodel of another continuous time model. This allows you to build very complex models in a very realistic way and `SimpleSim` will take care of all the annoying stuff, such as ensuring that discrete-time systems are only updated according to their defined sampling time. This feature is something that I’ve always missed and maybe the main reason I hadn’t uninstalled Matlab/Simulink until very recently.
- It doesn’t do _everything_. Some of the existing packages can do a _lot_. Like ODEs, PDEs, stochastic systems, complex implicit nonlinear systems and so on. `SimpleSim` focuses solely on solving explicit ODEs and discrete-time processes. This may seem like a disadvantage, but I think it makes it a lot easier to get started with `SimpleSim`. Of course, this doesn’t mean that the package will never be extended to do more in the future.

---

<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:** [October 16, 2024, 5:15pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/5 "2024-10-16T17:15:02Z")

</div>

ModelingToolkit does support hybrid systems but the support is very patchy and incomplete at the moment. Some of the functionality is located here [ModelingToolkitSampledData.jl](https://juliacomputing.github.io/ModelingToolkitSampledData.jl/dev/), but this is not yet released.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 16, 2024, 5:19pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/6 "2024-10-16T17:19:47Z")

</div>

Interesting, thanks for sharing.

Ultimately, I didn’t build `SimpleSim` to replace any of the existing packages and tools. If you are looking for something specific that’s available in `DynamicalSystems.jl`, `ModelingToolkit.jl` etc. then that’s what you should use.

But the reality is that most users won’t need a lot of the features offered by these packages and `SimpleSim` offers a lightweight alternative with a low entrance barrier, while still providing a powerful simulation engine with a broad spectrum of features.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 16, 2024, 5:32pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/7 "2024-10-16T17:32:33Z")

</div>

I encourage anyone reading this to just play around with the package a little bit. It’s much easier to see the difference in “user experience” that way.

And definitely let me know what you think! 🙂

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [October 16, 2024, 9:24pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/8 "2024-10-16T21:24:47Z")

</div>

Hi @janneshb , thanks for sharing your work for the community! Since you explicitly ask for feedback I will contribute my two cents (but I am sorry in advance as I typically challenge people when asked for feedback…).

> [@janneshb](#):
>
> If you are looking for something specific that’s available in `DynamicalSystems.jl`, `ModelingToolkit.jl` etc. then that’s what you should use.

An important note here is that DynamicalSystems.jl has nothing to do with modelling. It is a library that you use to analyze an _already built model_. It doesn’t help you build it. So in a sense it is entirely orthogonal with SimpleSim.jl. But…

I saw that in SimpleSim.jl you really started from scratch. Even re-wrote ODE solvers like RK4. It also appears to me that SimpleSim.jl made a deliberate choice to not conform the “state functions” f/g to the format that is currently established by SciML of `f(u, p, t)` with u state, p parameter, and t time. Why this choice was made I don’t understand, especially because such a choice is purely convention driven; any format is equally good as any other, and the only format that can be better is the one people already use. Which motivates the following…

Can a model created by SimpleSim.jl be casted into the standard form used by OrdinaryDiffEq.jl / DynamicalSystems.jl of a single state function `f(u, p, t)`? If not, that is hurting your users. You are missing out on really large tools for _analyzing_ (not building and simulating) dynamical systems. Not only DynamicalSystems.jl but also the parameter sensitivity stuff in SciML among many others. Some of these stuff don’t even exist in other programming languages so they are a genuine Julia advantage and actual reason people switch to Julia in the first place. And there doesn’t appear to be any fundamental reason on why SimpleSim.jl should be missing out on all this stuff.

Generally speaking I think it is good that there are alternative simulation softwares in a programming language. I am just raising my concerns after the brief view I had of the documentation. And my concerns come because I think that there should be attempts to make everything compatible with each other to the extent possible and meaningful.

* * *

If I can give some feedback into the existing documentation, it would be the following:

First, would be to consider removing the sentence

> “`SimpleSim.jl` does not export any types.”

It is technically true, but me it sounds missleading. Sure, you don’t export a new type, but you expect all input to be of the exact type `NamedTuple{...}{:fc, :yc, :p, ...}` with all field names being exactly specified. To my eyes this has no difference to making a custom type with fields `fc, yc, p` and I would argue it is probably more safe to have a type in the first place since so much specificity is enforced.

Also, why do you need to have `fc` for continuous systems and `fd` for discrete, instead of using `f` for both? Same for `xc0` and `xd0`?

Second to be more transparent in the introduction page. Why does the fields of the named tuple are named `fd, yd` instead of `fd, gd` since one function is `f` and the other is `g`. Why is `u` expected as an input to both functions? What even is `u`? It is not the state of the dynamical system, that’s `x`. What’s `y`? `y` is not used in the equation of `x`, so y is not even needed to be computed in this equation:

![image](https://global.discourse-cdn.com/julialang/original/3X/e/f/ef94a6f6b5c02d456cabef1d41ed389537f75eb0.png)

as you can solve for your state variable without `y`. In the whole introduction page it is never stated what `u` is. Is `u` a time forcing? If yes, why does the `f` function _also_ depend on time `t`? Is `y` an **observable** of the dynamical system? If so, why would it be in the equations **defining** the dynamical system? If it is an observable it can be obtained _after_ or _during_ the system is simulated; not when it is defined.

As someone with a background in dynamical systems, I am actually confused about how I would write my dynamical system in the form expected by this library as it brings ambiguity with the multiple ways to introduce time dependence and the odd `y` equation that isn’t actually required to solve the system.

* * *

Lastly, I want to address the following because I’ve heard it before

> [@janneshb](#):
>
> `SimpleSim` focuses solely on solving explicit ODEs and discrete-time processes. This may seem like a disadvantage, but I think it makes it a lot easier to get started with `SimpleSim`.

> … the reality is that most users won’t need a lot of the features offered by these packages and `SimpleSim` offers a lightweight alternative with a low entrance barrier …

This doesn’t stand up to me as clear cut as presented. Just because something has features people don’t need it isn’t a negative for them. What matters is that it has features they _do_ need. If it has all the features they do need, all the extra features are a potential positive as in the future they may need much more features as their project evolves.

The entrance barrier is not something decided by the total number of features of a software. It is something dictated primarily by the documentation and design of a software. If the small and introductory subset of features is accessible by being designed intuitively and documented well in a dedicated self-contained page, then it shouldn’t matter at all if there is an entire universe of hard-to-understand advanced features in another documentation page. When I look at the tutorial for simulating the Lorenz-63 system with OrdinaryDiffEq.jl, there is nothing complex there. And there is also no ambiguity there either. Honestly, it is super trivial, despite OrdinaryDiffEq.jl genuinely being a massively complex library.

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 16, 2024, 10:12pm UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/9 "2024-10-16T22:12:46Z")

</div>

Hey @Datseris,  
I must admit I got a bit excited when I saw that you commented on here; big fan of your work. So thanks for taking the time!

First, let me explain why I did a few things the way I did in a little bit more detail.

> An important note here is that [DynamicalSystems.jl](https://juliahub.com/ui/Packages/General/DynamicalSystems) has nothing to do with modelling.

Yes, `SimpleSim.jl` aims at providing a simulation framework, not an analysis framework for nonlinear systems like your `DynamicalSystems.jl` does. So the packages only have very little overlap.

> It also appears to me that [SimpleSim.jl](https://juliahub.com/ui/Packages/General/SimpleSim) made a deliberate choice to not conform the “state functions” f/g to the format that is currently established by SciML of `f(u, p, t)`.

Indeed. `SimpleSim` separates _states_ from _inputs_. This is very helpful, especially when designing control systems, or just systems with feedback in general. That was the main use case I had in mind for `SimpleSim` (mostly because that is my own area of research). Systems without the need for inputs can simply get passed `nothing` for the input at all times. Sometimes, we can just extend the idea of a state vector to also contain inputs, but if you frequently work with systems that need inputs, it’s helpful to take care of them explicitly.  
I would actually say that the fact that SciML (etc.) don’t have explicit support for inputs built in is a huge disadvantage.

> Can a model created by [SimpleSim.jl](https://juliahub.com/ui/Packages/General/SimpleSim) be casted into the standard form used by [OrdinaryDiffEq.jl](https://juliahub.com/ui/Packages/General/OrdinaryDiffEq) / [DynamicalSystems.jl](https://juliahub.com/ui/Packages/General/DynamicalSystems) of a single state function `f(u, p, t)` ?

Currently, no. Or rather, you would have to write the function to cast a `SimpleSim` model into `OrdinaryDiffEq` form yourself. This is a great idea for a feature, though. I will add that to the list.  
One minor issue I can see with this, however, is that `SimpleSim` doesn’t export any types, neither concrete nor abstract. So, a feature like this would have to be a function `to_standard_form(...)` and cannot overload the `convert` function. But this is not a deal breaker.

> I would argue it is probably more safe to have a type in the first place since so much specificity is enforced.

Leaving this up to the user was a very deliberate choice.  
But maybe `SimpleSim` could export types `CTModel`, `DTModel` and `HybridModel`, also as guidance for people who don’t know the package well yet. It would still accept `NamedTuple` models or custom types with the same fieldnames, of course. I will think about this.

> Also, why do you need to have `fc` for continuous systems and `fd` for discrete, instead of using `f` for both? Same for `xc0` and `xd0` ?

`SimpleSim` supports models with both CT and DT dynamics (“hybrid models”). Therefore, this distinction is important.

> Why does the fields of the named tuple are named `fd, yd` instead of `fd, gd` since one function is `f` and the other is `g` .

This is a good point. `yc` should be named `gc`. The same is true for `yd`. This is something I will correct immediately, hoping that I’m still the only user of the package.

> Why is `u` expected as an input to both functions? What even is `u` ? What’s `y` ?

`x` is the state, `u` is the input, `y` is the output.  
The input function can be whatever you want and is passed to `simulate` as a `(t) -> ...` function.  
If you don’t need it, `SimpleSim` will just call `fc` etc. with `u = nothing`. But if you do need an explicit input, it’s a very useful feature to have, in my opinion.

`y` is simply computed as a function of `x`, `u`, `p` and `t`. Again, if you don’t need an “output” of your system, you can simply pass `(x, u, p, t) -> x` for `yc` and get back the whole state vector. But it can be useful to have a separate output that isn’t the state vector itself; for example when simulating a sensor that “knows” about the true state but the output is some partial or noisy version of the state.  
This is again very helpful when simulating real-world systems for controller synthesis.  
Also, the `yc` function is very important when building nested models, as any submodels have to be called from within a parent model’s `yc` function. This is because `yc` preserves the current model’s state. The same is not true for `fc` functions.

> As someone with a background in dynamical systems, I am actually confused about how I would write my dynamical system in the form expected by this library

Do you have a specific example in mind? `y` and `u` can be ignored, if you have no need for them.  
For example, the forced Van-Der-Pol oscillator in the `SimpleSim` convention is shown below.

```julia
fc_vdp = (x, u, p, t) -> [x[2], p.ε * (1 - x[1]^2) * x[2] - x[1] - u]
yc_vdp = (x, u, p, t) -> x
van_der_pol_oscillator = (
    p = (ε = 0.3),
    fc = fc_vdp,
    yc = yc_vdp,
)

```

Now, if you want to simulate the oscillator with a forcing `u(t) = A sin(w*t)` for 10 seconds, you can call `simulate` as follows.

```julia
A = 1.5
w = 1.0
forcing = (t) -> A * sin(w*t)
data = simulate(van_der_pol_oscillator, T = 10 // 1, xc0 = [0, 1], uc = forcing)

```

You could omit the input `u` and compute the forcing inside `fc` using `t`, I think this is what you meant. But having `u` as an explicit input enables other features, such as [nested models](https://janneshb.github.io/SimpleSim.jl/dev/manual/nested_sims/).  
Note that you can only omit `uc` or `ud` from `simulate`. The structure of `fc` and `yc` must include `u`.

> The entrance barrier is not something decided by the total number of features of a software.

I agree. Currently, `SimpleSim` lacks some of the features of `OrdinaryDiffEq` and other packages. I just meant that the features it _is_ lacking are probably not missed by the majority of users. But that may only reflect my view on the topic. I think the way to alleviate the lack of complex features is to build an interface to `OrdinaryDiffEq` and SciML in general. This comes back to one of your earlier comments.  
Having an interface would allow simpl(er) systems to be simulated with `SimpleSim` without any additional dependencies, while complex systems could leverage the “best of both worlds”.

Thank you so much for taking the time to review `SimpleSim`. I really appreciate the detailed feedback and I’m sure some of it will make it into the package.

Best,  
Jannes

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 17, 2024, 12:04am UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/10 "2024-10-17T00:04:15Z")

</div>

**Update:**  
I just released v0.1.4 introducing the breaking change renaming `yc` to `gc` and `yd` to `gd`, which is more consistent with the nomenclature used in the documentation.  
Also this helps avoid confusion between functions (`fc`/`gc`/`fd`/`gd`) and data (`xcs`/`ycs`/`xds`/`yds`).

---

<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:** [October 17, 2024, 4:22am UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/11 "2024-10-17T04:22:10Z")

</div>

> [@Datseris](#):
>
> Can a model created by [SimpleSim.jl](https://juliahub.com/ui/Packages/General/SimpleSim) be casted into the standard form used by [OrdinaryDiffEq.jl](https://juliahub.com/ui/Packages/General/OrdinaryDiffEq) / [DynamicalSystems.jl](https://juliahub.com/ui/Packages/General/DynamicalSystems) of a single state function `f(u, p, t)`? If not, that is hurting your users. You are missing out on really large tools for _analyzing_ (not building and simulating) dynamical systems.

I think you are missing an important point here, elaborated upon by @janneshb above, we are dealing with input-output systems here. ModelingToolkit also adds the input u and the output y where they are needed, for example: [Input output · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/dev/basics/InputOutput/)

> [@Datseris](#):
>
> As someone with a background in dynamical systems, I am actually confused about how I would write my dynamical system in the form expected by this library as it brings ambiguity with the multiple ways to introduce time dependence and the odd `y` equation that isn’t actually required to solve the system.

The particular format  
 ![io](https://global.discourse-cdn.com/julialang/original/3X/e/f/ef94a6f6b5c02d456cabef1d41ed389537f75eb0.png)  
is _extremely common_, you will find it

- [Input output · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/dev/basics/InputOutput/)
- [Creating Systems · ControlSystems.jl](https://juliacontrol.github.io/ControlSystems.jl/stable/man/creating_systems/#State-Space-Systems)
- [How to write a customized environment? · ReinforcementLearning.jl](https://juliareinforcementlearning.org/docs/How_to_write_a_customized_environment/)
- [Home · ControlSystemIdentification Documentation](https://baggepinnen.github.io/ControlSystemIdentification.jl/dev/)
- [Introduction · TrajectoryOptimization](https://rexlab.ri.cmu.edu/TrajectoryOptimization.jl/stable/)
- [Home · SeeToDee Documentation](https://baggepinnen.github.io/SeeToDee.jl/dev/)
- [Home · LowLevelParticleFilters Documentation](https://baggepinnen.github.io/LowLevelParticleFilters.jl/dev/)
- [Building model · ReachabilityAnalysis.jl](https://juliareach.github.io/ReachabilityAnalysis.jl/dev/generated_examples/Building/)
- [Nonlinear Design · ModelPredictiveControl.jl](https://juliacontrol.github.io/ModelPredictiveControl.jl/dev/manual/nonlinmpc/)
- [Quick Ex#2: Moon Lander · NLOptControl.jl](https://juliampc.github.io/NLOptControl.jl/latest/tutorials/MoonLander/main.html)
- [GitHub - thowell/DirectTrajectoryOptimization.jl: A Julia package for constrained trajectory optimization using direct methods.](https://github.com/thowell/DirectTrajectoryOptimization.jl)
- [Nonlinear and time-varying systems · IterativeLearningControl2 Documentation](https://baggepinnen.github.io/IterativeLearningControl2.jl/dev/non_lti/#Nonlinear-systems)

Also, you may be familiar with diagrams like this?  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/8/e8d21cb6ea997eb8756ae17dce694be9fcd78d8f.png)  
notice how these blocks have an _input_ and an _output_, not only an internal _state_?

---

<div class="post-metadata">

**Author:** ![janneshb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janneshb/32/36035_2.png) [@janneshb](https://discourse.julialang.org/u/janneshb)\
**Post date:** [October 17, 2024, 11:52am UTC](https://discourse.julialang.org/t/new-simplesim-jl-a-minimalist-julia-package-for-modular-dynamical-systems-simulation/121308/12 "2024-10-17T11:52:20Z")

</div>

Hi @baggepinnen, thanks for your comment!  
Happy to have some Julia legends united in the comment section 😉

This all seems to depend on your specific background. For control systems it’s invaluable to have explicit _inputs_ and _outputs_. In other fields they might be unnecessary.

As I said before, you can just leave the input unused, but it may be worth considering adding support for functions `(x, p, t) -> ...`, if that’s something a lot of people ask for.
