1
0
Fork 0
mirror of https://github.com/Findus23/rebound-collisions.git synced 2024-09-19 15:53:48 +02:00
rebound-collisions/utils.py

174 lines
4.8 KiB
Python
Raw Normal View History

2021-01-23 14:41:41 +01:00
import os
import socket
2021-02-11 14:41:23 +01:00
import subprocess
2020-03-31 15:39:59 +02:00
from ctypes import c_uint32
from pathlib import Path
from random import randint
from sys import argv
from typing import Tuple, Dict
2020-03-31 15:39:59 +02:00
from matplotlib import pyplot as plt
from matplotlib.axes import Axes
from matplotlib.figure import Figure
from numpy import linalg
from rebound import Simulation, Orbit, Particle, OrbitPlot
2021-02-08 19:03:51 +01:00
from scipy.constants import pi, gravitational_constant
2021-01-23 14:41:41 +01:00
from setproctitle import setproctitle
from extradata import ExtraData
2021-02-08 19:03:51 +01:00
solar_radius = 6.957e8
solar_mass = 1.9885e+30
2020-03-31 15:39:59 +02:00
def random_hash() -> c_uint32:
2020-03-31 15:39:59 +02:00
"""
returns a (hopefully) unique 32 bit integer to be used as a particle hash
when a collision occurs and ruins the output data, please complain to the universe
"""
return c_uint32(randint(0, 2 ** 32 - 1))
def unique_hash(ed: ExtraData) -> c_uint32:
ed.meta.hash_counter += 1
return c_uint32(ed.meta.hash_counter)
def innermost_period(sim: Simulation) -> float:
"""
returns the orbital period in years of the innerpost object
for comparison with symplectic time step
"""
minp = None
mina = float("inf")
for p in sim.particles[1:]:
if abs(p.a) < mina:
mina = abs(p.a)
minp = p
orb: Orbit = minp.orbit
return abs(orb.P)
2021-02-08 19:03:51 +01:00
def third_kepler_law(orbital_period: float):
return (
gravitational_constant * solar_mass / (4 * pi ** 2)
* orbital_period ** 2
) ** (1 / 3)
2021-02-04 13:42:22 +01:00
def total_momentum(sim: Simulation) -> float:
total = 0
for p in sim.particles:
total += linalg.norm(p.vxyz) * p.m
return total
2021-02-04 13:42:22 +01:00
def total_mass(sim: Simulation) -> float:
total = 0
for p in sim.particles:
total += p.m
return total
def show_orbits(sim: Simulation):
from matplotlib import pyplot as plt
OrbitPlot(sim, slices=1, color=True)
plt.show()
2020-03-31 15:39:59 +02:00
def clamp(n: float, smallest: float, largest: float) -> float:
assert smallest < largest
return max(smallest, min(n, largest))
2020-12-28 17:23:03 +01:00
def filename_from_argv(argument: str = None) -> Path:
2020-03-31 15:39:59 +02:00
if len(argv) < 2:
raise ValueError("specify filename")
2020-12-28 17:23:03 +01:00
if argument:
fn = argument
else:
fn = argv[1]
2020-03-31 15:39:59 +02:00
fn = fn.replace(".bin", "").replace(".meta.json", "")
if fn.endswith("."):
fn = fn[:-1]
return Path(fn.replace(".bin", "").replace(".meta.json", ""))
def create_figure() -> Tuple[Figure, Axes]:
"""
helper function for matplotlib OOP interface with proper typing
"""
fig: Figure = plt.figure()
ax: Axes = fig.gca()
return fig, ax
def reorder_particles(sim: Simulation, ed: ExtraData) -> None:
2021-01-21 14:28:29 +01:00
"""
probably not needed anymore
"""
particles_by_hash: Dict[int, Particle] = {}
hashes = []
suns = []
gas_giants = []
embryos = []
planetesimals = []
original_N = sim.N
p: Particle
for p in sim.particles:
hash_value = p.hash.value
# save a copy of the particles
particles_by_hash[hash_value] = p.copy()
type = ed.pd(p).type
if type == "sun":
suns.append(hash_value)
# keep sun in the simulation to avoid empty particles list
continue
elif type == "gas giant":
gas_giants.append(hash_value)
elif type == "embryo":
embryos.append(hash_value)
elif type == "planetesimal":
planetesimals.append(hash_value)
else:
raise ValueError(f"unknown type: {type}")
hashes.append(p.hash)
for hash in hashes:
sim.remove(hash=hash)
ordered_particles = gas_giants + embryos + planetesimals
assert len(suns) + len(ordered_particles) == original_N
particle: Particle
for h in ordered_particles:
particle = particles_by_hash[h]
sim.add(particle)
# print(list(sim.particles))
# exit()
sim.N_active = len(suns) + len(ordered_particles) - len(planetesimals)
# mark objects > N_active as testparticle_type = 1
# this means they become semi-active bodies
# TODO: double-check meaning
sim.testparticle_type = 1
assert sim.N == original_N
2021-01-23 14:41:41 +01:00
2021-02-11 14:41:23 +01:00
def git_hash() -> str:
output = subprocess.run(["git", "rev-parse", "--verify", "HEAD"], capture_output=True)
return output.stdout.decode()
def check_heartbeat_needs_recompile() -> None:
library = Path("heartbeat/heartbeat.so")
code = library.with_suffix(".c")
if code.stat().st_mtime > library.stat().st_mtime:
raise RuntimeError("heartbeat.so is out of date. Please recompile it from source.")
2021-02-04 13:42:22 +01:00
def process_friendlyness(fn: Path) -> None:
2021-01-23 14:41:41 +01:00
if socket.gethostname() == "standpc":
# only handle other computers specially
return
2021-03-22 14:05:28 +01:00
setproctitle(f"[{fn.stem}] [rebound-watersim] read /home/winklerl23/sim-info.txt for more information")
2021-01-23 14:41:41 +01:00
os.nice(5)