class EARTH: RADIUS = n_float(6378.1) * n_exp(3.) """Equatorial radius, m.""" MASS = n_float(5.97237) * n_exp(24.) """Mass, kg.""" ORBIT_RADIUS = n_float(149.6) * n_exp(9.) """Orbit radius, m.""" ORBITAL_VELOCITY = n_float(29.8) * n_exp(3.) """Orbital velocity, m/s.""" ROTATION_PERIOD = n_float(365.2) * 24. * 60. * 60. """Sidereal rotation period, s."""
class Space: """3D space with array of dots and gravitation logic.""" dots: List[dot.Dot] = dataclasses.field(default_factory=list) _gravitation_const: n_float = constants.GRAVITATIONAL_CONST _default_step: n_float = n_float(1) def step_newton(self): """Update dots acceleration by `Newton's law of universal gravitation`.""" G = self.gravitation_const for dot_1_index, dot_1 in enumerate(self.dots): for dot_2_index, dot_2 in enumerate(self.dots[dot_1_index + 1:], start=dot_1_index + 1): x_1 = dot_1.pos m_1 = dot_1.mass x_2 = dot_2.pos m_2 = dot_2.mass dx = x_2 - x_1 distance = numpy.linalg.norm(dx) a = G / numpy.power(distance, 3) * dx print(f"Acc {dot_1_index} {dot_2_index} {a}") a_1 = a * m_2 a_2 = -a * m_1 dot_1.acc = a_1 dot_2.acc = a_2 step_acceleration = step_newton def step_velocity_and_position(self, time=_default_step): """Update dots velotity and position.""" for dot in self.dots: dot.step(time=time) def step(self, time=_default_step): """Do all steps.""" self.step_acceleration() self.step_velocity_and_position(time=time) @staticmethod def distance(vec_a, vec_b): return numpy.linalg.norm(vec_a - vec_b) def __str__(self): return "\n".join( [f"{number} {dot}" for number, dot in enumerate(self.dots)]) @property def gravitation_const(self): return self._gravitation_const @gravitation_const.setter def gravitation_const(self, value): self._gravitation_const = n_float(value) @property def default_step(self): return self._default_step @default_step.setter def default_step(self, value): self._default_step = n_float(value)
class SUN: RADIUS = n_float(695_510) * n_exp(3.) """Equatorial radius, m.""" MASS = n_float(1.989) * n_exp(30.) """Mass, kg."""
class MOON: """Source: `https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html`.""" RADIUS = n_float(1738.1) * n_exp(3.) """Equatorial radius, m.""" MASS = n_float(0.07346) * n_exp(24.) """Mass, kg.""" PERIGEE_ORBIT_RADIUS = n_float(0.3633) * n_exp(9.) """Perigee orbit radius, m.""" MAX_ORBITAL_VELOCITY = n_float(1.082) * n_exp(3.) """Max. orbital velocity, m/s.""" SYNODIC_PERIOD = n_float(29.53) * 24. * 60. * 60. """Synodic period, s.""" SIDEREAL_ROTATION_PERIOD = n_float(655.728) * 60. * 60. """Sidereal rotation period, s.
import functools import numpy from config import n_float n_exp = functools.partial(numpy.power, n_float(10.)) GRAVITATIONAL_CONST = n_float(6.67430) * n_exp(-11.) """Gravitational constant, m^3 * kg^-1 * s^-2.""" class SUN: RADIUS = n_float(695_510) * n_exp(3.) """Equatorial radius, m.""" MASS = n_float(1.989) * n_exp(30.) """Mass, kg.""" class EARTH: RADIUS = n_float(6378.1) * n_exp(3.) """Equatorial radius, m.""" MASS = n_float(5.97237) * n_exp(24.) """Mass, kg.""" ORBIT_RADIUS = n_float(149.6) * n_exp(9.) """Orbit radius, m."""
def default_step(self, value): self._default_step = n_float(value)
def gravitation_const(self, value): self._gravitation_const = n_float(value)
class Dot: """3D dot with position, velocity and acceleration.""" data: numpy.array = dataclasses.field(default_factory=n_data) _mass: n_float = n_float(1) _default_step: n_float = n_float(1) def step(self, time=_default_step): """Update velocity and position by acceleration and time.""" self.vel += self.acc * time self.pos += self.vel * time # self.data[2] = numpy.zeros(shape=(3,)) # ? def __str__(self): header = f"{self.__class__.__name__} m={self.mass}" data = "\n".join([ "{key}: {value}".format(key=key, value=", ".join( [f"{number:.2f}" for number in value])) for key, value in zip("xva", self.data) ]) return "\n".join([header, data]) @property def pos(self): return self.data[0] @pos.setter def pos(self, value): self.data[0] = value @property def vel(self): return self.data[1] @vel.setter def vel(self, value): self.data[1] = value @property def acc(self): return self.data[2] @acc.setter def acc(self, value): self.data[2] = value @property def mass(self): return self._mass @mass.setter def mass(self, value): self._mass = n_float(value) @property def default_step(self): return self._default_step @default_step.setter def default_step(self, value): self._default_step = n_float(value)
def mass(self, value): self._mass = n_float(value)