Title: | Gravitational N-Body Simulation |
---|---|
Description: | Run simple direct gravitational N-body simulations. The package can access different external N-body simulators (e.g. GADGET-4 by Springel et al. (2021) <doi:10.48550/arXiv.2010.03567>), but also has a simple built-in simulator. This default simulator uses a variable block time step and lets the user choose between a range of integrators, including 4th and 6th order integrators for high-accuracy simulations. Basic top-hat smoothing is available as an option. The code also allows the definition of background particles that are fixed or in uniform motion, not subject to acceleration by other particles. |
Authors: | Danail Obreschkow [aut, cre] |
Maintainer: | Danail Obreschkow <[email protected]> |
License: | GPL-3 |
Version: | 1.48 |
Built: | 2025-02-08 02:35:20 UTC |
Source: | https://github.com/obreschkow/nbody |
Run simple direct gravitational N-body simulations. The package can access different external N-body simulators (e.g. GADGET-4 by Springel et al., 2021), but also has a simple built-in simulator. This default simulator uses a variable block time step and lets the user choose between a range of integrators, including 4th and 6th order integrators for high-accuracy simulations. Basic top-hat smoothing is available as an option. The code also allows the definition of background particles that are fixed or in uniform motion, not subject to acceleration by other particles.
Danail Obreschkow <[email protected]>
Environment used to store paths and options for external code.
.nbody.env
.nbody.env
An object of class environment
of length 0.
Danail Obreschkow
Set a default external simulation code
default.code(code = NULL)
default.code(code = NULL)
code |
structured list specifying the default external simulation code used when calling |
Returns the current list 'code'. If no such last has been set and 'default.code()' is called without argument, an error is produced.
Danail Obreschkow
Computes the instantaneous potential and kinetic energies of all particles in an N-body system. Here, the potential energy of a particle i means the potential energy it has with all other particles (sum_j -G*m[i]*[j]/rij). Hence the total potential energy of the system is half the sum of the individual potential energies.
energy(m, x, v, rsmooth = 0, box.size = 0, G = 6.6743e-11, cpp = TRUE)
energy(m, x, v, rsmooth = 0, box.size = 0, G = 6.6743e-11, cpp = TRUE)
m |
N-vector with the masses of the N particles. Negative masses are treated as positive masses of same magnitude, since negative masses normally represent positive background masses in the nbody package. |
x |
N-by-3 matrix specifying the initial position in Cartesian coordinates |
v |
N-by-3 matrix specifying the initial velocities |
rsmooth |
top-hat smoothing radius. If 0 given, no smoothing is assumed. |
box.size |
scalar>=0. If 0, open boundary conditions are adopted. If >0, potential energies are computed assuming a cubic box of side length box.size with periodic boundary conditions. In this case, the cubic box is contained in the interval [0,box.size) in all three Cartesian coordinates. The separation between any two particles is always calculated along their shortest separation, which may cross 0-3 boundaries. |
G |
gravitational constant. The default is the measured value in SI units. |
cpp |
logical flag. If TRUE (default), the computation is performed efficiently in C++. |
Returns a list with vector items Ekin
, Epot
, Emec=Ekin+Epot
; and the associated total quantities Ekin.tot
, Epot.tot
, Emec=Ekin+Epot.tot
.
Danail Obreschkow
Basic routine to visualise the result of an N-body simulation, projected onto a plane.
## S3 method for class 'simulation' plot( x, y, units = 1, index1 = 1, index2 = 2, xlim = NULL, ylim = NULL, center = c(0, 0, 0), cex = 0.3, pch = 20, title = "", asp = 1, pty = "m", col = "black", alpha.orbits = 1, alpha.snapshots = 1, lwd = 1, show.orbits = TRUE, show.snapshots = TRUE, show.ics = TRUE, show.fcs = TRUE, ... )
## S3 method for class 'simulation' plot( x, y, units = 1, index1 = 1, index2 = 2, xlim = NULL, ylim = NULL, center = c(0, 0, 0), cex = 0.3, pch = 20, title = "", asp = 1, pty = "m", col = "black", alpha.orbits = 1, alpha.snapshots = 1, lwd = 1, show.orbits = TRUE, show.snapshots = TRUE, show.ics = TRUE, show.fcs = TRUE, ... )
x |
is a simulation-object as produced by |
y |
deprecated argument included for consistency with generic |
units |
length unit in SI units |
index1 |
index of the dimension plotted on the x-axis |
index2 |
index of the dimension plotted on the y-axis |
xlim |
2-vector specifying the plotting range along the x-axis |
ylim |
2-vector specifying the plotting range along the y-axis |
center |
3-vector specifying the plotting center in the specified units |
cex |
point size |
pch |
point type |
title |
title of plot |
asp |
aspect ratio of x and y axes |
pty |
character specifying the type of plot region to be used; "s" generates a square plotting region and "m" generates the maximal plotting region. |
col |
either (1) a single color, (2) a n-element vector of colors for each particle or (3) a function(n,...) producing n colors, e.g. 'rainbow' |
alpha.orbits |
opacity (0...1) of orbital lines. |
alpha.snapshots |
opacity (0...1) of snapshot points. |
lwd |
line width of orbital lines. |
show.orbits |
logical flag. If TRUE (default), the orbits are shown as straight lines between snapshots. |
show.snapshots |
logical flag. If TRUE (default), points are shown for each snapshot. |
show.ics |
logical flag. If TRUE (default), the initial positions are highlighted. |
show.fcs |
logical flag. If TRUE (default), the final positions are highlighted. |
... |
additional parameters for |
None
Danail Obreschkow
Routine, designed to reset the center of mass (CM) of the initial conditions (ICs) of an N-body simulation. The CM position and velocity are both shifted to (0,0,0).
reset.cm(sim)
reset.cm(sim)
sim |
list of m, x, v or list with a sublist "ics", made of m, x, v, where
|
Returns a structure of the same format as the input argument, but with re-centered positions and velocities.
Danail Obreschkow
Run direct N-body simulations using an adaptive block timestep.
run.simulation(sim, measure.time = TRUE, verbose = TRUE)
run.simulation(sim, measure.time = TRUE, verbose = TRUE)
sim |
structured list of simulation settings, which must contain the following sublists:
|
measure.time |
logical flag that determines whether time computation time will be measured and displayed. |
verbose |
logical flag indicating whether to show console outputs from external codes. Ignored when using the in-built simulator. |
UNITS: The initial conditions (in the sublist ics
) can be provided in any units. The units of mass, length and velocity then fix the other units.
For instance, [unit of time in seconds] = [unit of length in meters] / [unit of velocity in m/s]. E.g., if initial positions are given in units of 1AU=1.49598e11m and velocities in units of 1km/s, one unit of time is 1.49598e8s=4.74yrs.
Likewise, units of the gravitational constant G
are given via [unit of G in m^3*kg^(-1)*s^(-2)] = [unit of length in meters] * [unit of velocity in m/s]^2 / [unit of mass in kg]. E.g., for length units of 1AU=1.49598e11m, velocity units of 1km/s=1e3m/s and mass units of 1Msun=1.98847e30kg, a unit of G is
7.523272e-14 m^3*kg^(-1)*s^(-2). In these units the true value of G is about 887.154.
NBODYX simulator:
Can be downloaded from github viagit clone https://github.com/obreschkow/nbodyx
Details on installing, compiling and running the code are given in the README file.
Note: To run very high-accuracy simulations, such as the Pythagorean three-body problem, you can use 128-bit floating-point numbers by compiling the code asmake kind=16
GADGET-4 simulator:
This his a very powerful N-body+SPH simulator used primarily for large astrophysical simulations. GADGET-4 is not particularly suitable for small direct N-body problems, but it can nonetheless be used for such simulations for the sake of comparison, at least if not too much accuracy is needed and if a massively increased computational overhead is acceptable.
Please refer to https://wwwmpa.mpa-garching.mpg.de/gadget4 for details on how to download and compile the code. In order to use GADGET-4 with this R-package, it must be compiled with the following compile-time options (in the file Config.sh):NTYPES=2
GADGET2_HEADER
SELFGRAVITY
ALLOW_DIRECT_SUMMATION
HIERARCHICAL_GRAVITY
DOUBLEPRECISION=1
ENLARGE_DYNAMIC_RANGE_IN_TIME
If and only if periodic boundary conditions are used, you also need to add the optionPERIODIC
If you plan to often switch between runs with open and periodic boundaries, it may be advisable to compile two versions of GADGET-4, with and without this option. To do so, one needs to create two sub-directories with the respective Config.sh files and compile them viamake -j [number of cores] DIR=[path containing Config.sh with PERIODIC]
make -j [number of cores] DIR=[path containing Config.sh without PERIODIC]
The runtime parameter file (param.txt) needed by GADGET-4 is written automatically when calling run.simulation
. The gravitational softening length in GADGET-4 is computed as sim$para$rsmooth/2.8, which ensures that the particles behave like point masses at separations beyond sim$para$rsmooth. If rsmooth is not provided, it is computed as stats::sd(apply(sim$ics$x,2,sd))*1e-5
. The accuracy parameter ErrTolIntAccuracy is set equal to sim$para$eta/sim$para$rsmooth*1e-3, which gives roughly comparable accuracy to in-built simulator for the Leapfrog integrator.
The routine returns the structured list of the input argument, with one sublist output
added. This sublist contains the items:
t |
k-vector with the simulation times of the k snapshots. |
x |
k-by-N-by-3 array giving the 3D coordinates of the N particles in k snapshots. |
v |
k-by-N-by-3 array giving the 3D velocities of the N particles in k snapshots. |
n.snapshots |
total number of snapshots. |
n.iterations |
total number of iterations used to run the simulation. |
n.acceleration.evaluations |
total number of acceleration evaluations. |
wall.time |
total computing time in seconds. |
Danail Obreschkow
sim = setup.halley() sim = run.simulation(sim) AU = 149597870700 # Astronomical unit in meters plot(sim, units=AU, xlim=c(-20,60), ylim=c(-40,40), xlab='[AU]', ylab='[AU]') cat(sprintf('This simulation was run with %d iterations.\n',sim$output$n.iterations))
sim = setup.halley() sim = run.simulation(sim) AU = 149597870700 # Astronomical unit in meters plot(sim, units=AU, xlim=c(-20,60), ylim=c(-40,40), xlab='[AU]', ylab='[AU]') cat(sprintf('This simulation was run with %d iterations.\n',sim$output$n.iterations))
Routines to generate the structured lists of initial conditions and simulation parameters required to run an N-body simulation with run.simulation
.
setup() setup.halley( t.max = NULL, nperiods = 1, dt.out = 1e+07, e = 0.96714, s = 2.667928e+12, ... ) setup.sunearth(t.max = 31557600, dt.out = 86400 * 7, ...) setup.ellipse(t.max = NULL, nperiods = 1, e = 0.9, s = 1, f = 0.5, ...) setup.periodic.3body( v1 = 0.347112813567242, v2 = 0.532726851767674, t.max = 6.325, m3 = 1, ... ) setup.pythagoras(t.max = 68, integrator = "yoshida6", eta = 0.002, ...)
setup() setup.halley( t.max = NULL, nperiods = 1, dt.out = 1e+07, e = 0.96714, s = 2.667928e+12, ... ) setup.sunearth(t.max = 31557600, dt.out = 86400 * 7, ...) setup.ellipse(t.max = NULL, nperiods = 1, e = 0.9, s = 1, f = 0.5, ...) setup.periodic.3body( v1 = 0.347112813567242, v2 = 0.532726851767674, t.max = 6.325, m3 = 1, ... ) setup.pythagoras(t.max = 68, integrator = "yoshida6", eta = 0.002, ...)
t.max |
final simulation time |
nperiods |
number of orbital periods to be computed; ignored if |
dt.out |
time step for simulation output |
e |
eccentricity in setup.ellipse() |
s |
semi-major axis in setup.ellipse() |
... |
other simulation parameters used by |
f |
mass-ratio in setup.ellipse() |
v1 |
first velocity parameter in setup.3body.periodic() |
v2 |
second velocity parameter in setup.3body.periodic() |
m3 |
mass of third body in setup.3body.periodic() |
integrator |
integrator used for N-body simulation, see |
eta |
accuracy parameter of adaptive time step, see |
Calling setup()
is identical to calling setup.halley()
setup.halley()
sets up a 2-body simulation of Halley's Comet around the Sun.
setup.sunearth()
sets up a simple 2-body simulation of the Earth around the Sun, using only approximate orbital specifications.
setup.ellipse()
sets up an elliptical Keplerian orbit in natural units
setup.periodic.3body()
can be used to set up a planar zero angular momentum stable 3-body problem with two unit masses and a third mass m3 (maybe equal of different from unity). Such situations can be parameterized with two parameters v1 and v2, following the publications found at https://arxiv.org/abs/1709.04775 and https://arxiv.org/abs/1705.00527.
The default is the famous figure-of-eight, but try, for example, setup.3body.periodic(0.2034916865234370, 0.5181128588867190, 32.850, dt.out=0.02), setup.3body.periodic(0.2009656237, 0.2431076328, 19.0134164290, 0.5, dt.out=0.01) or setup.3body.periodic(0.991198122, 0.711947212, 17.650780784, 4, eta=0.005, dt.out=0.002).
setup.pythagoras()
sets up the Pythagorean three-body problem consisting of three unit masses placed at the vertices of a right triangle with side lengths 3, 4 and 5. The masses are initially at rest and the gravitational constant is unity.
Danail Obreschkow
sim = setup.halley() sim = run.simulation(sim) plot(sim)
sim = setup.halley() sim = run.simulation(sim) plot(sim)