Sysdyn
System Dynamics modelling, simulation and diagramming in Python.
What is System Dynamics?
System Dynamics is a way of understanding how something changes over time by describing it in terms of what accumulates and the rates at which those accumulations fill and drain.
A population is the standard example. It grows because births add to it and shrinks because deaths remove from it. The population itself is a stock, a quantity that accumulates. Births and deaths are flows, the rates at which the stock changes. What makes such a system interesting is that the flows depend on the stock: the more people there are, the more births there are, so the population feeds back into its own growth.
That feedback is why these systems are worth simulating rather than reasoning about in your head. A handful of stocks and flows connected in a loop can behave in ways nobody predicts from looking at the parts, and the behaviour often turns out to come from the structure of the connections rather than from any single number in the model.
What is Sysdyn?
Two things that work together.
A Python package for building and simulating System Dynamics models. A flow is written as an ordinary Python function, and its argument names say what it depends on:
def births(population, birth_rate):
"""People born per unit of time."""
return population * birth_rate
Sysdyn reads those argument names to work out how the parts of a model connect, so nothing is written down twice. There is no separate equation language, and each function can be called and tested on its own like any other Python function.
A graphical application in which a model is built by drawing it, as a Stock and Flow diagram on a canvas, then checked, simulated and plotted without writing any Python.
Describing a model, checking it, and running it
from sysdyn import Flow, Model, Parameter, Stock, simulate
def births(population, birth_rate):
"""People born per year."""
return population * birth_rate
model = Model("Population", time_units="year")
model.add(Stock("population", 1000.0, units="people"))
model.add(Parameter("birth_rate", 0.03, units="1/year"))
model.add(Flow("births", births, to_stock="population",
units="people/year"))
print(model.problems()) # [] — nothing to object to
results = simulate(model, start_time=0.0, end_time=100.0, step_size=0.25)
print(results.values("population")[-1])
An equation may equally be written as text — Flow("births", "population * birth_rate", ...) — and only text can be read, which is what lets Sysdyn check
that the units of an equation are what it says they are.
Results come back as NumPy arrays, so they go straight into Matplotlib and
SciPy. The tutorial (docs/tutorial.rst in the source tree) works through a
complete example and explains how to tell whether an answer can be trusted.
What is in it
- stocks, flows, auxiliary variables and parameters, with mistakes reported before anything runs
- three fixed-step methods and six adaptive solvers, including ones for stiff models, and any solver of your own
step,pulseandramp, lookup tables, delays and smoothing, repeatable randomness, and locating the exact moment a threshold is crossed- conveyors, ovens and queues, for material that does not mix
- dimensions, matched by name rather than by position
- units, checked before a run: a flow against what it fills, and the arithmetic of an equation against what it claims to be
- a model built out of models somebody else wrote
- the whole visual language in the application, with undo, plots in their own windows, the numbers out as CSV and the model out as plain Python
The package does not need the graphical application
This matters enough to say on its own. The Python package is complete by itself: it needs no display and no graphical toolkit, so models can be written in plain Python files, kept under version control, and used alongside NumPy, SciPy and Matplotlib in the ordinary way.
The relationship runs one way only. The graphical application is built on top of the package's public interface, exactly as a user writing Python would use it, and holds no modelling or simulation logic of its own. So anything the application can do can also be done from Python, and choosing to draw a model never limits what can be done with it afterwards.
Requirements
- Python 3.11 or later
- NumPy 1.24 or later
- SciPy 1.10 or later
- Matplotlib 3.6 or later
The graphical application additionally needs tkinter, the standard library's
interface to the Tk toolkit. This cannot be installed from a package index
because it is supplied by the operating system. On Debian and its derivatives:
sudo apt install python3-tk
The Python package itself does not need it, and works on a machine with no graphical display at all.
Running the tests
From the top of the source tree:
python3 -m pytest
No installation and no virtual environment are needed. The test configuration
makes the package importable from src/ directly, so a freshly cloned copy of
the repository is ready to test as it stands.
Building the documentation
From the top of the source tree:
./docs/build.sh
The finished documentation is written to docs/_build/html, and the page to
open is docs/_build/html/index.html.
Sphinx 5.3 or later is all that is needed. Warnings are treated as errors, so a reference to something that does not exist fails the build rather than quietly producing a page with a broken link.
Equations are written as LaTeX in the documentation source and rendered in the reader's browser, so nothing needs to be installed to typeset them. By default the renderer is fetched from a content delivery network, which means viewing the equations needs network access. To use a local copy instead — which is what a distribution package wants — pass its path through:
./docs/build.sh -D mathjax_path=/usr/share/javascript/mathjax/MathJax.js
Anything given to build.sh is passed on to sphinx-build, so any other
setting can be overridden the same way.
Licence
GNU General Public License, version 3 or later. The full text is in LICENSE.
Author
The Sysdyn Developers.
The maintainer's contact address is recorded in the package metadata, which is
the one place it is kept. pip show sysdyn prints it for an installed copy,
and pyproject.toml holds it in the source.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sysdyn-0.1.0.tar.gz.
File metadata
- Download URL: sysdyn-0.1.0.tar.gz
- Upload date:
- Size: 629.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98055ef9c30ea875307dcfbc5279d5f01185b89cef948acf833a42a3fb242eda
|
|
| MD5 |
05ba7db53ac281ec5f78febe5ca4d13d
|
|
| BLAKE2b-256 |
5a524248db4cd1ab60343abb509853ac4973eb7b0d0fe2b38d87d68b742376da
|
File details
Details for the file sysdyn-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sysdyn-0.1.0-py3-none-any.whl
- Upload date:
- Size: 457.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31d6dc8c97480fb022bf5920ed843d55758c51672b42b5d44f520e5ac03f42ec
|
|
| MD5 |
44615b7c02116c04b0806ec204c5fe63
|
|
| BLAKE2b-256 |
a5511bba6ec4e057217c6a72a5caf414984b2b67dda091de77d58049a9e32210
|