Skip to content

About

A hands-on introduction and reproducible benchmark for students and beginning researchers exploring N-body integrators, their accuracy, computational cost, and long-term behavior.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Repository files navigation

AstroSimBench Course Notes

An Introduction to Integrators for the N-Body Problem

From one numerical step to a method choice you can defend.

Three measured circular-orbit trajectories on a dark background: Euler drifts outward; RK4 and Leapfrog stay near the analytic circle.

Same initial state and step size, three methods. Lesson 1A explains the difference. Figure inputs and rendering.

These notes teach gravitational simulation through experiments you can run in Python: analytic two-body orbits, interacting and restricted three-body systems, planetary N-body dynamics, and softened three-dimensional clusters. Every lesson comes back to three questions:

  1. What does an integrator assume?
  2. How do we test what it gives us?
  3. When does the evidence support using it?

Higher order is a useful starting point, but it does not settle which method to choose. Two second-order methods can cause about 300 times differ in the same planetary test. The difference comes from how diff methods are approximate: the whole orbit, or the smaller interaction between nearly Keplerian orbits. This course unpacks that difference, then tests where it stops helping.

You can read the whole course on GitHub without running anything. Each lesson ties a physical question to the code that answers it, the measured figures, and the numbers behind them.

Start here

Table of contents

Foundations

Part 1 — Learn with an exact answer

Part 2 — Interactions, encounters, and reference limits

Part 3 — From planetary systems to statistical questions

Part 4 — Test the construction and read its cost

Run python runpart4.py for 4A–4E, python runpart4.py --only 4E for the secular-cycle study, or python runpart4.py --only 4D to inspect the old regime map without new integrations. The original nine-method registry is unchanged. 4A adds one processed WH2 construction through a dedicated fixed-step loop.

Conclusions

Reference

Quick start

From the folder that contains pyproject.toml, with Python 3.10 or newer:

python -m pip install -e ".[plots,reference]"
python runpart1.py --only 1A

Then read Lesson 1A. Figures are saved without opening windows. Add --show if you want to see them as they are made.

Installation, runner options, and troubleshooting

1. Read first, run later

Every lesson and every saved figure can be read on GitHub without Python. To run the experiments, clone or extract the complete folder and open the folder that contains pyproject.toml in your editor. We call this folder the project root.

Use the same Python 3.10-or-newer environment for all four parts. Install once with python -m pip install -e ".[plots,reference]"; the dependency ranges are declared in pyproject.toml. Matplotlib draws the figures; MATLAB is not needed. Part 4 does not require a separate installation or an exact REBOUND version.

Saved runs record the versions that produced them. Their labels describe historical measurements, not required versions for your own run. Compatible versions can change step histories, timings or image pixels. Read your run's reference checks before interpreting small differences. Reproducibility explains the supported ranges and verification reports the combinations actually checked.

2. Create an environment and install

In a terminal at the project root:

python -m venv .venv

On Windows PowerShell:

.\.venv\Scripts\Activate.ps1

On macOS or Linux:

source .venv/bin/activate

Then install the package with the plotting and reference extras:

python -m pip install -e ".[plots,reference]"

If PowerShell will not activate the environment, call .\.venv\Scripts\python.exe wherever these notes write python. In VS Code, select the same interpreter. The editable install imports the code from this folder, so your edits take effect without reinstalling.

NumPy handles arrays, Matplotlib draws the plots, and the reference extra installs REBOUND for the IAS15 and external BS references. Most early two-body lessons run without REBOUND. Lesson 1E and a full reproduction need it. The nine course integrators themselves live in the local core and need nothing extra.

3. Run the first lesson

python runpart1.py --only 1A

The runner prints the output folder. Open it next to Lesson 1A: you should find three PNG figures, summary and history tables, and saved arrays.

Every numbered experiment writes a fresh timestamped folder, including 1A. Repeating the command keeps the bundled results intact. The lesson links still point to the supplied snapshots; the runner prints the location of your new run.

4. The four runners

Task Part 1 Part 2 Part 3 Part 4
List lessons python runpart1.py --list python runpart2.py --list python runpart3.py --list python runpart4.py --list
Run one python runpart1.py --only 1B python runpart2.py --only 2B python runpart3.py --only 3B python runpart4.py --only 4E
Run the whole part python runpart1.py python runpart2.py python runpart3.py python runpart4.py
Show figures Add --show Add --show Add --show Add --show

To run the four main experiment sequences in order:

python runpart1.py
python runpart2.py
python runpart3.py
python runpart4.py

Full scans and long integrations take longer than the first lesson. GL4 is the slowest, because every step solves a dense Newton system. If you use --show, close each figure window to let the run continue.

Part 1 lessons accept a few parameters through the runner. Select exactly one lesson when you pass them:

python runpart1.py --only 1D --help
python runpart1.py --only 1D --orbits 50

Part 1 modules use package-relative imports, so run them through runpart1.py rather than as files. Part 2 and Part 3 scripts can also run directly:

python experiments/three_body/exp2f_spatial_three_body.py --orbits 2 --no-show
python experiments/n_body/exp3e_ensemble_statistics.py --help

For the complete Part 4 sequence, use the root runner. With no --only argument it runs all five experiments, validates 4E, then builds the lesson analysis views:

python runpart4.py

To run only the validated final study, use python runpart4.py --only 4E. The labelled B/C/E follow-ups remain a separate command: python experiments/part4/supplement_part4.py --only 4B 4C 4E. Full Part 4 postprocessing reads the supplied follow-up measurements alongside the new primary runs; the batch input record identifies those sources.

5. Rebuild the final summary

The bundle already holds the earlier results that 3F needs. To rebuild the summary from them without integrating again:

python runpart3.py --only 3F

Inside a full Part 3 batch, 3F reads that batch's 3A–3E plus the existing Part 1 and Part 2 results. Run alone, it searches the bundled result folders for completed runs. You can add other folders explicitly:

python runpart3.py --only 3F --results-root "D:/AstroSimBench-results"

Then read the new source_manifest.json. It lists exactly which runs fed the summary. If missing happend, then it stays unmeasured.

6. Common setup problems

Symptom What to check
No module named astrosimbench Install from the folder that contains pyproject.toml, with the same interpreter that runs the experiment.
The wrong copy of the core is imported Run python -c "import astrosimbench; print(astrosimbench.__file__)" and check that the path points into this project.
Part 1 relative-import error Use python runpart1.py --only ..., not the experiment file directly.
No plot window Figures are saved by default. Add --show, or open the printed output folder. For 4E, the first figures follow its reference checks; stage progress appears in the terminal and 4E.log.
A method row says failed Read its reason and settings. A numerical failure and an import or programming error mean different things.
Orange cells in the regime chart The scanned settings did not reach that target. Read the target and the reference policy before judging the method.

The core tests run after installing the test extras:

python -m pip install -e ".[test]"
python -m unittest discover -s tests -v

Continue to the foundations

Code map

Every lesson links to the exact functions it uses. If you would rather start from the code, these are the files to open.

What it does Where it lives
Shared state, force-model, and cost contracts core.py
Direct gravity and analytic jerk forces.py
The integration driver (fixed and adaptive) integrate()
Euler, RK4, RK45 euler_step(), rk4_step(), rk45_trial()
Leapfrog and GL4 leapfrog_step(), gl4_step()
Hermite4 hermite4_step()
Bulirsch–Stoer bs_trial()
WH2, WH4, and Jacobi coordinates planetary_wh2_step(), planetary_wh4_step(), jacobi.py
Processed WH2 (Part 4 addition) processed.py
Part 4 experiments, external adapters and secular diagnostics Code guide, dynamics.py, zlk.py
Part 4 orchestration and optional current-project checks runpart4.py, check_project.py
Kepler propagation kepler.py, kepler_drift()
Restricted three-body model restricted.py
Initial conditions systems.py
Energy, momentum, elements, distributions diagnostics.py
External references and validity windows references.py
The method registry __init__.py

The experiments live in experiments/, one main script per lesson. 4E also has an output-sampling validation stage. While editing, python check_project.py checks current links, syntax and command-line entry points. Add --results to recompute saved Part 4 measurements and tables without integrating. These optional checks permit normal source edits and write no report files unless requested. See verification scope and measured limits.

Small examples to adapt

After a lesson, a short example is a good place to try your own question. Each module's docstring states its purpose, assumptions, command, outputs, and limits. The examples call the existing core methods. Their main() and recording functions only organize the run. They add no integrators.

Example What it lets you try Command from the project root
two_body.py Connect an initial state, an analytic reference, errors, and costs python -m examples.two_body
nbody.py Change N and the system geometry through the same interface python -m examples.nbody --n 5 --method leapfrog
efficiency.py Collect a full cost table and draw a small error/work plot python -m examples.efficiency
reference_window.py Check when two numerical references stop agreeing python -m examples.reference_window

The first two only print diagnostics. The efficiency example overwrites results/efficiency.png and results/efficiency_costs.csv, so copy those first if you want to keep them. The reference example prints a sampled window and needs REBOUND. For a controlled comparison, use the numbered experiments rather than the examples.

What is included?

Area Contents
Core Nine original course integrators plus the Part 4 processed WH2 construction, gravity models, coordinates, diagnostics, and external-reference adapters
Experiments Twenty original lesson scripts plus five Part 4 additions
Results A reading guide to the saved PNG, CSV, JSON, and NPZ outputs
Lessons The reading path, with code and evidence links
Documentation Methods, glossary, sources, design notes, the Part 4 overview, and the evidence pages
Examples Short scripts to adapt after the relevant lessons
Tests Functional checks for the core, external adapters, runners, sampling, output protection and current-project consistency
Part 1, Part 2, Part 3, Part 4 runners Command-line entry points

Scope These are teaching implementations and finite, measured experiments. IAS15 and the external BS are checked references, not exact trajectories. A run that finishes, a small energy change, and a reached accuracy target are three different outcomes. Every method choice in these notes stays tied to its model, time window, accuracy target, and cost.

Cite and reuse

This is AstroSimBench v1.0.0. CITATION.cff has the name of author, Jingyi(Seph) Zhang (ORCID), and GitHub reads it for the "Cite this repository" button.

Original code is under MIT; original teaching prose, project-generated figures and result collections are under CC BY 4.0, where rights apply. Licensing and attribution explains the boundaries and third-party dependencies. See the release guide for tagging, Git byte preservation and optional Zenodo archiving.

About these notes

The chapter-style Markdown navigation is inspired by CSC207-UofT/207-course-notes. The physics lessons and explanations are written for AstroSimBench, and no CSC207 course content is reproduced. See Sources for the mathematical attributions and for what separates a published algorithm from our implementation of it.

Authorship and development

I started AstroSimBench expecting a higher-order method to be more accurate and therefore a better choice. But during my experiments, they kept splitting that expectation apart. At one reported setting in Lesson 1D, Leapfrog conserved angular momentum to round-off while its state error was about a hundred times RK4’s. In a matched planetary test in Lesson 2C, two second-order methods differed in state error by a factor of about 300. Order was one variable among several. The project became a way to locate the others and to measure where each one stops helping.

My part was the design, the direction, the review and the interpretation. I chose the questions and the order of the lessons, from a two-body orbit with an exact answer to planetary splitting methods and their correctors. I decided what each experiment holds fixed, what counts as evidence, and which conclusions the measurements support. I enjoyed most was watching one small question open into the logic underneath it, until I could explain why a method behaves the way it does.

I wrote the first versions of the nine course integrators myself, together with much of the code they rest on, including the gravity routines in forces.py, the energy diagnostics in diagnostics.py, the universal-variable Kepler drift in universal_kepler.py, the Jacobi coordinates in jacobi.py, and the Wisdom–Holman steps in wisdom_holman.py, wh2.py and wh4.py. I also wrote early versions of the 1A–1D experiments, though that is a small share of the experiment code. As the experiments grew, many methods were revised to fit them, and that later engineering was AI-assisted. So were most of the experiment code, the plotting and the Part 4 additions: ChatGPT and Claude drafted and revised much of that code and the prose, built the test and verification tooling, and helped check the methods against external references such as REBOUND.

I compared implementations with their published equations, investigated changes in the numerical results, and rejected conclusions the data did not support. Published algorithms and coefficients are credited to their sources. The scripts, saved measurements and verification records are included so that readers can repeat the checks and examine the reasoning. I began by asking which method was best. I now ask what the structure of a problem allows a method to leave out.

If you find a mistake, tell us the lesson, the exact command or paragraph, what you expected, and the figure or data that shows the problem. A proposal for a new method should name the physical model and the measurable objective it targets.

About

A hands-on introduction and reproducible benchmark for students and beginning researchers exploring N-body integrators, their accuracy, computational cost, and long-term behavior.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages