# ModSimPy: a physical modeling course delivered as Jupyter notebooks

> ModSimPy is Allen Downey's free textbook on computational physical modeling, published as Jupyter notebooks plus a single module called modsim.py. It reads like a course, it is aimed at people who have never programmed, and its packaging tells you it is not a library you should depend on.

**AllenDowney/ModSimPy** — Text and supporting code for Modeling and Simulation in Python

- Repository: https://github.com/AllenDowney/ModSimPy
- Website: https://allendowney.github.io/ModSimPy/
- Stars: 938 · Forks: 1,820
- Language: Jupyter Notebook
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/allendowney-modsimpy

## ModSimPy is a course, not a component you install

ModSimPy exists to teach physical modeling to people who have never programmed. The claim in the project's own description is narrow and useful: it is an introduction to physical modeling in Python, suitable for people with no programming experience. The audience is therefore not a simulation engineer looking for a solver, but a student, a self-learner, or an instructor who needs a whole course laid out in a fixed order.

The subject matter is the reason this is a book and not a library. The three parts move from discrete models, including a bikeshare system and world population growth, to first-order systems, including models of infectious disease, thermal systems and pharmacokinetics, and then to second-order systems, including projectiles, celestial mechanics and rotating rigid bodies. The stated benefit of a computational approach is that it allows more realistic models than a first-year physics class typically shows, with features such as friction and drag switched on.

That framing has a direct consequence for anyone weighing adoption. Nothing here is packaged for reuse inside somebody else's codebase. You adopt ModSimPy by reading it and running it. The repository exists to be cloned, executed and studied, not to be added as a dependency.

## modsim.py is one file that travels with the notebooks

Everything in the book rests on a single small module, modsim.py, and the repository is explicit about where that module actually lives. The canonical copy is modsim/modsim.py, sitting next to its tests in modsim/test_modsim.py. The script modsim/build.sh copies that file everywhere else it is needed, and the development notes tell contributors to edit only the canonical copy.

The delivery mechanism is unusual and worth understanding before spending an afternoon in it. The notebooks do not import an installed package. They download modsim.py from the repository at run time, which is why the project states that there is nothing to install. The same applies to a set of loose files: chap03.py, chap06.py, chap11.py, chap12.py, chap13.py, chap15.py, chap18.py, chap22.py, plus data/World_population_estimates.html and figs/baseball_drag.png must stay exactly where they are, because the notebooks fetch them from github.com/AllenDowney/ModSimPy/raw/master/... .

Two published artifacts sit on top of that module. The book itself is a Jupyter Book served from the gh-pages branch, and the API reference for the module is generated with MkDocs and mkdocstrings into site/. A top-level modsim.py also exists in the repository root, but the project describes that one as a copy rather than the source of truth.

## Building the conda environment with mamba or the Makefile

Setting up the notebooks takes a conda or mamba environment, and the Makefile hides the flags. Mamba is the recommended route, but the commands are identical apart from the binary, which matters if mamba is not on your machine.

```bash
mamba env create -f environment.yml
conda activate ModSimPy
```

The same file works with conda, or the Makefile target does both steps in one go.

```bash
make create_environment
conda activate ModSimPy
```

Either route produces what the project describes as a minimal environment with only the core dependencies needed to run the notebooks. The dependency list lives in requirements.txt and is short: beautifulsoup4, html5lib, jupyter, lxml, matplotlib, numpy, pandas, pint, scipy, sympy and tables. Pint is the unit handling library, which is what allows quantities to carry units rather than bare numbers, and sympy supports the symbolic work in the exercises.

Contributors need a different environment file, since the project also runs tests and builds documentation.

```bash
mamba env create -f environment-dev.yml
conda activate ModSimPy
```

That environment adds pytest and nbmake for testing, mkdocs, mkdocstrings and jupyter-book for documentation, ghp-import for build tooling and jupytext for editing notebooks as text. Existing environments are refreshed with a prune flag so removed packages do not linger.

```bash
mamba env update -f environment.yml --prune
```

The Makefile names the interpreter it expects as Python 3.13, and the environment files in the repository are the authoritative pin.

## A notebook change crosses three repositories before it publishes

Publishing a notebook change is a multi-repository sequence, and the project's development notes lay out the order. Three repositories are involved. ModSimPy is the public one, holding the notebooks without solutions under chapters/ and examples/, the modsim.py library and the Jupyter Book site published on the gh-pages branch. ModSimPySolutions is private, and it is where development happens and where the solutions live; it is cloned inside the working tree as a gitignored directory. ModSim, under the same owner, holds the figures and data shared with the MATLAB version.

The whole pipeline is one Makefile target.

```bash
make build
```

Under the hood it copies modsim.py from its canonical location, builds the solution notebooks, copies the examples and the chapters while stripping solutions, pushes once, generates the API documentation into site/, and finally builds the Jupyter Book into gh-pages. The individual commands are:

```bash
cd modsim && sh build.sh
cd ModSimPySolutions/chapters && sh build.sh
cd ModSimPySolutions && sh build.sh
cd examples && sh build.sh
cd chapters && sh build.sh
git push
sh build.sh
cd jb && sh build.sh
```

Two rules in that sequence matter to anyone trying to reproduce it. The scripts only commit, and the push is deliberately done once at the end, because every push to master triggers CI in the private repository. And examples are built before chapters, because the downloadable notebook zip includes both.

## Three limits: a dead PyPI package, a private solutions tree, skipped tests

Three constraints are visible in the project's own files, and each of them changes what you can expect.

First, the published package is not the supported path. The project states that the modsimpy package on PyPI was last released in 2020, is outdated and no longer maintained, and that the notebooks download modsim.py from the repository instead. Starting from the PyPI package gives you a module that has drifted away from the book.

Second, the solution repository is private. A reader can run every notebook, but the reference solutions held in the private repository are not something you can clone, so the CI that runs on every push and once a month cannot be reproduced from the public tree alone.

Third, the test suite is deliberately partial. The Makefile runs pytest against the module and nbmake against the chapter notebooks, while the examples target is commented out.

```bash
cd modsim; python -m pytest test_modsim.py -v
cd chapters; pytest --nbmake chap*.ipynb
```

The stated reason is that many of the examples do not run without their solutions. The consequence for a user is concrete: the public repository does not have a green end-to-end test for every notebook it publishes, so a broken example is a thing you can hit on a fresh clone.

## ModSimPy beside the MATLAB edition and beside raw scipy

The closest comparison is the MATLAB version of the same book, and the two are not separate efforts. Figures and data are shared between them through the AllenDowney/ModSim repository, so the same plot can appear in both texts. What differs is the starting point each edition assumes. The Python edition presents itself as suitable for people with no programming experience and argues for the language on the grounds that it provides high-level data structures well suited to the problems being modelled. A reader who already writes simulation code in MATLAB is the reader for whom that choice pays least.

The other comparison is with a general-purpose scientific Python stack used directly. numpy, scipy and sympy already sit in requirements.txt and carry the numerical work in the exercises. Building a model by hand means writing the discretisation, the state representation and the step loop yourself. modsim.py exists to remove exactly that work, and it does so in a single file whose entire build step is copying it to the locations the notebooks expect.

For a reader who wants the material rather than the repository, there is a third option. The project points readers to a hosted Jupyter Book where the book can be read and the code run, and to a separate documentation site for the module's API. Reading the hosted book and cloning the tree are different levels of commitment, and only the second one gives you the notebooks in a local editing workflow.

## Split licensing and a repository with no releases

ModSimPy is not archived, and the last push was on 2026-10-14. The repository has no GitHub releases, so there is no tagged artefact to pin against. Version tracking rests on the commit history and on the copied chapNN.py files rather than on packaged versions. The activity that does exist is automated, since CI in the private repository runs the notebooks on every push and once a month.

The licensing is split, and that matters if you plan to reuse any of it. The text of the book is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License, which permits reuse with attribution provided the result is not used commercially and is shared under the same terms. The code, including modsim.py, is under the MIT License held in the LICENSE file. A commercial project can take the module and the examples; the prose and the exercises carry the non-commercial condition. That is a reading of the two licences, not legal advice, and anyone with real exposure should confirm it themselves.

The upgrade cost is asymmetric. For a reader, refreshing is mechanical: update the environment with the prune flag, pull, and run. For a contributor, a change to one notebook means running the multi-repository build against the private tree and pushing to master exactly once at the end.

## Conclusion

ModSimPy suits a reader who wants a structured, free course in computational physical modeling and is willing to work through it in chapter order. It does not suit an engineer shopping for a maintained simulation package, since the PyPI release is a dead end and the real module is one file fetched from a repository URL. Before committing, check environment.yml against your own Python version, and confirm that the specific notebook you care about runs on its own, because the example notebooks are excluded from the published test suite.

## FAQ

### Do I need to install modsimpy from PyPI to run the ModSimPy notebooks?

No. The notebooks download modsim.py from the repository at run time, and the project states that the modsimpy package on PyPI, last released in 2020, is outdated and no longer maintained.

### Which Python version does ModSimPy target?

The Makefile sets PYTHON_VERSION = 3.13, and the conda or mamba environment is created from environment.yml or environment-dev.yml.

### How do I set up the ModSimPy development environment for tests and docs?

Run mamba env create -f environment-dev.yml and then conda activate ModSimPy. That environment adds pytest, nbmake, mkdocs, mkdocstrings, jupyter-book, ghp-import and jupytext on top of the user dependencies.

### Are the notebook solutions available in the public ModSimPy repository?

No. The public repository holds the notebooks without solutions under chapters/ and examples/, while the solutions live in the private ModSimPySolutions repository that is cloned inside the working tree as a gitignored directory.

### Does the ModSimPy test suite run the example notebooks?

No. The Makefile runs pytest against modsim/test_modsim.py and nbmake against the chapter notebooks, and the examples target is commented out because many examples do not run without their solutions.

## Sources

- [AllenDowney/ModSimPy on GitHub](https://github.com/AllenDowney/ModSimPy)
- [Issues](https://github.com/AllenDowney/ModSimPy/issues)
- [License: MIT](https://github.com/AllenDowney/ModSimPy/blob/master/LICENSE)
- [Project website](https://allendowney.github.io/ModSimPy/)
- [README](https://github.com/AllenDowney/ModSimPy/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/allendowney-modsimpy
