Nemesis is a flexible, multi-physics, multi-scale algorithm for integrating hierarchical systems (e.g., planetary systems in star clusters, circumstellar disks, or binaries in galactic environments) embedded within the AMUSE library.
The development is continued on: https://gitlab.strw.leidenuniv.nl/spz/nemesis
Which can be cloned from: [email protected]:spz/nemesis.git
Apologies for the inconvenience.
Simon Portegies Zwart
Nemesis works by decoupling tight subsystems from the global environment, integrating them in isolation, and then synchronising the micro- and macroscales at regular intervals. This scheme allows:
- High parallelisability
- Accurate energy conservation compared to direct N-body only runs
- Seamless inclusion of the galactic tidal field and stellar evolution
A full description is given in Hochart & Portegies Zwart (in prep.).
A demonstration video is available here.
For AMUSE installation instructions, see this guide.
At runtime, Nemesis automatically creates output directories for a given run. These are hosted under data/:
simulation_snapshot/– HDF5 snapshots of particle phase-space and massescollision_snapshot/– plain-text files describing detected collisionssim_stats/– text files with run statistics
Runs can be resumed automatically, provided diagnostic parameters (dtbridge, dt_diag) are unchanged.
- Install dependencies:
conda install --file requirements.txt
or
pip install -r requirements.txt - Compile C++ files. These are used to calculate the correction kicks between subsystems and the global environment, synchronising the micro- and macrostate:
cd src/cpp
make - Generate initial condiitons. For instance:
cd examples/python basic_cluster/particle_initialiser.pyThis will create a particle set with several planetary systems. The particle set are always saved in a folderICs/. - Run simulation. From the project root:
python main.pyIf, instead, you wish to simulate your system for 1 Myr with a bridge time step of 100 yr:python main.py --tend=1Myr --dtbridge=100yrCommand-line arguments are documented in main.py docstrings.
main.py: Run code to simulate your system.examples/: Folders with several examples initialising particles set to be run.src/environment_functions.py: Script containing various functions to define different environment properties.src/globals.py: All global constants and magic numbers used in the simulation.src/grav_correctors.py: Force correction routines to synchronise the micro- and macrostates (synchronise parent with children).src/hierarchical_particles.py: Script to categorise particles into parents and children.src/nemesis.py: Script hosting the evolution procedure.tests/: Folders with several test examples.
In addition to the input functions needed to execute interface.py, the following may vary depending on your simulation:
main.py:
galactic_frame(): The phase-space coordinates of the particles embedded within an analytical galactic potential. Default is centered about a Milky Way-like galaxy.RUN_IDX: The system realisation within yourinitial_particles/directory wished to simulate.
src/globals.py:
ASTEROID_RADIUS: Collision radius for asteroid (test) particles.CONNECTED_COEFF: Threshold for detecting particles within a subsystem that are ejected.EPS: Tolerance with which models have successfully integrated to required time step.GRAV_THRESHOLD: Threshold for modifying the parent particle radius in case it is relatively isolated. This not currently being used.MIN_EVOL_MASS: The minimum mass for a particle to be flagged for stellar evolution.PARENT_NWORKER: Number of workers for parent integrator.PARENT_RADIUS_COEFF: Pre-factor influencing the parent particle radius.PARENT_RADIUS_MAX: Maximum allowed parent particle radius.
src/nemesis.py:
_sub_worker(): Number of child workers. CurrentAMUSEfunctionalities forces this variable to remain fixed tonumber_of_workers = 1. Dedicated gravitational solver for subsystems._parent_worker: Dedicated gravitational solver for parent code.
To run example script, execute python basic_cluster/particle_initialiser.py to create an AMUSE particle set. Afterwards, execute python main.py.
Two example Nemesis test is provided. Running these not only provide a way to gauge if any modifcations alter the physics in ways not wished for, but also allow one to familiarise themselves with the algorithm. Both compare its performance relative to N-body integrators, with one focusing on the von Zeipel-Lidov-Kozai (ZLK) effect and the other a typical cluster simulation.
To run this test follow:
- Set-up initial conditions:
python /tests/ZKL_test/initialise_LZK.py - To run Nemesis:
python -m tests.ZKL_test.run_ZKL - To plot results:
python/tests/ZKL_test/plot_ZKL.py
Some vital notes regarding the test:
- These are some suggested parameters:
- In
nemesis._parent_worker, useHuaynoas parent integrator with modeSHARED10_COLLISIONS. - In
nemesis._sub_worker, useHuaynoas children integrator with modeSHARED10_COLLISIONS. - In
nemesis._sub_workerset child converter withscale_radius / 10. - End time: 10 Myr.
- Bridge time: 500 yr.
- Diagnostic time: 5000 yr.
- Code internal time-step: 0.1.
- Turn off galactic field + stellar evolution.
- Change
PARENT_RADIUS_COEFFinsrc/globalsto 1e-5 au, 100 au and 1000 au. - Turn off children collisions. Make sure that the parent and child code is the same integrator. This allows testing the performance of the child split algorithm vs. non-splitting scenarios.
- In
To run this test follow:
- Set-up initial conditions:
python /tests/cluster_test/initialise_cluster.py - To run Nemesis:
python -m tests.cluster_test.run_clusterwith the flagRUN_NEMESIS = 1 - To run direct N-body code:
python -m tests.cluster_test.run_clusterwith the flagRUN_NEMESIS = 0 - To plot results:
python /tests/cluster_test/plot_cluster.py
Some vital notes regarding the test:
- Ensure that both parent and child integrator within
Nemesisare the same. This should also be an identical integrator to that selected during the direct N-body runs. Additionally, make sure all code parameters (i.e converter, internal time-step...) are identical to ease comparison. A good code to use for this test isPh4since the cluster initialised contains test particles by default andPh4is able to handle such a demographic efficiently. Some advice forNemesisparameters:- In
nemesis._parent_worker, usePh4as parent integrator. - In
nemesis._sub_worker, usePh4as children integrator. - End time: 0.1 Myr -- Deviation will occur due to chaos. This is a short enough time to allow any systematic errors to emerge but not too short for chaos to greatly affect integration.
- Bridge time: 500 yr
- Diagnostic time: 10000 yr
- Code internal time-step: 0.1
- Turn off galactic field + stellar evolution -- This will allow a better comparison in performance on the gravitational side of
Nemesis. - Turn off children collisions
- In
- To setup children at the initial time step, it is required that the particle set contains a
syst_idattribute whose value is an integer. The set of particles with the samesyst_idvalue will be flagged as a subsystem as long assyst_id> 0. - Since Nemesis relies heavily on frequent stop/start (hibernate/resume) cycles for its child integrators, sockets are used instead of MPI. The persistent stop/start cycles conflict with MPI worker behaviour since MPI workers cannot safely handle repeated suspend/resume signals, especially in large-N simulations where hundreds of worker processes are active. Repeated stop/start operations can lead to workers being incorrectly terminated, crashing the simulation altogether. Socket-based channels, however, can tolerate stop/start cyles because they do not use the tightly coupled, state-sensitive collective semantics of MPI. The problem, however, is that children code are restricted to one core per.