def __init__(self, variant, rotational_flattening_model=None):
     self._model = rotational_flattening_model
     self._data = {
         "effect": "Disabled",
         "parameters": {
             "internal": {
                 "distance": 0.0,
                 "factor_for_the_force_induced_by_planet_rotation": 0.0,
                 "factor_for_the_force_induced_by_star_rotation": 0.0,
                 "orthogonal_component_of_the_force_induced_by_planet_rotation": 0.0,
                 "orthogonal_component_of_the_force_induced_by_star_rotation": 0.0,
                 "radial_component_of_the_force_induced_by_rotation": 0.0,
                 "scalar_product_of_vector_position_with_planetary_spin": 0.0,
                 "scalar_product_of_vector_position_with_stellar_spin": 0.0,
                 "shape": Axes(0.0, 0.0, 0.0).get(),
             },
             "output": {
                 "acceleration": Axes(0.0, 0.0, 0.0).get(),
                 "dangular_momentum_dt": Axes(0.0, 0.0, 0.0).get(),
             },
         },
         "coordinates": {
             "position": Axes(0.0, 0.0, 0.0).get(),
             "velocity": Axes(0.0, 0.0, 0.0).get(),
         },
     }
     if variant in ("CentralBody", "OrbitingBody", ):
         self._data["effect"] = {variant: rotational_flattening_model.get()}
     elif variant in ("Disabled", ):
         self._data["effect"] = variant
     else:
         raise Exception("Unknown variant '{}'".format(variant))
Exemplo n.º 2
0
 def __init__(self, variant, properties=None):
     self._data = {
         "effect": "Disabled",
         "parameters": {
             "internal": {
                 "distance": 0.0,
                 "migration_timescale": 0.0,
                 "norm_velocity_vector": 0.0,
                 "norm_velocity_vector_2": 0.0,
             },
             "output": {
                 "acceleration": Axes(0.0, 0.0, 0.0).get(),
             },
         },
         "coordinates": {
             "position": Axes(0.0, 0.0, 0.0).get(),
             "velocity": Axes(0.0, 0.0, 0.0).get(),
         },
     }
     if variant in ("CentralBody", ):
         if properties is None:
             raise Exception("Disk central body requires properties")
         self._data["effect"] = {
             variant: properties,
         }
     elif variant in (
             "OrbitingBody",
             "Disabled",
     ):
         self._data["effect"] = variant
     else:
         raise Exception("Unknown variant '{}'".format(variant))
Exemplo n.º 3
0
def calculate_cartesian_coordinates(target_mass, q, e, i0, p, n0, l, masses=[], positions=[], velocities=[]):
    """
    Calculate the heliocentric position and velocity

    - target_mass: mass (typically the target planet mass+central body mass)
    - q: perihelion distance
    - e: eccentricity
    - i0: inclination (degrees)
    - p: longitude of perihelion
    - n0: longitude of the ascending node (degrees)
    - l: mean anomaly

    In case of instead of a central massive body there are two (i.e., circumbinary
    planet), then it is necessary to provide their masses, positions and velocities
    (as list of Axes objects) and target_mass must correspond only to the planet
    mass. Order is important, for instance:

    - target_mass: planet mass
    - masses: [star1_mass, star2_mass]
    - positions: [star1_position, star2_position]
    - velocities: [star1_velocity, star2_velocity]
    """
    if not isinstance(masses, list):
        masses = [masses]
    if not isinstance(positions, list):
        positions = [positions]
    if not isinstance(velocities, list):
        velocities = [velocities]
    if len(masses) != len(positions):
        raise Exception("The number of masses needs to match the number of positions")
    elif len(masses) != len(velocities):
        raise Exception("The number of masses needs to match the number of velocities")

    if len(positions) > 0:
        center_of_mass_mass, center_of_mass_position, center_of_mass_velocity = calculate_center_of_mass(masses, positions, velocities)
        delta_a = np.sqrt(center_of_mass_position.x()**2 + center_of_mass_position.y()**2 + center_of_mass_position.z()**2)
        delta_q = delta_a * (1.0 - e);                     # perihelion distance
        q -= delta_q

    gm = G*(sum(masses)+target_mass)
    x, y, z, vx, vy, vz = _calculate_cartesian_coordinates(gm, q, e, i0, p, n0, l)

    if len(positions) > 0:
        x += center_of_mass_position.x()
        y += center_of_mass_position.y()
        z += center_of_mass_position.z()
        vx += center_of_mass_velocity.x()
        vy += center_of_mass_velocity.y()
        vz += center_of_mass_velocity.z()

    planet_position = Axes(x, y, z)
    planet_velocity = Axes(vx, vy, vz)
    return planet_position, planet_velocity
Exemplo n.º 4
0
 def __init__(self, variant, input_parameters=None):
     self._data = {
         "effect": "Disabled",
         "parameters": {
             "input": {
                 "love_number": 0.0,
             },
             "internal": {
                 "distance":
                 0.0,
                 "factor_for_the_force_induced_by_planet_rotation":
                 0.0,
                 "factor_for_the_force_induced_by_star_rotation":
                 0.0,
                 "orthogonal_component_of_the_force_induced_by_planet_rotation":
                 0.0,
                 "orthogonal_component_of_the_force_induced_by_star_rotation":
                 0.0,
                 "radial_component_of_the_force_induced_by_rotation":
                 0.0,
                 "scalar_product_of_vector_position_with_planetary_spin":
                 0.0,
                 "scalar_product_of_vector_position_with_stellar_spin":
                 0.0,
             },
             "output": {
                 "acceleration": Axes(0.0, 0.0, 0.0).get(),
                 "dangular_momentum_dt": Axes(0.0, 0.0, 0.0).get(),
             },
         },
         "coordinates": {
             "position": Axes(0.0, 0.0, 0.0).get(),
             "velocity": Axes(0.0, 0.0, 0.0).get(),
         },
     }
     if variant in (
             "CentralBody",
             "OrbitingBody",
     ):
         self._data["effect"] = variant
         # Update default values, ignore non-recognised keys
         for key, value in six.iteritems(input_parameters):
             if key in self._data["parameters"]["input"]:
                 self._data["parameters"]["input"][key] = float(value)
             else:
                 print("Ignored parameter: {}".format(key))
     elif variant in ("Disabled", ):
         self._data["effect"] = variant
     else:
         raise Exception("Unknown variant '{}'".format(variant))
Exemplo n.º 5
0
 def __init__(self, variant, input_parameters=None):
     self._data = {
         "effect": "Disabled",
         "parameters": {
             "input": {
                 "k_factor": 0.0,
                 "rotation_saturation": 0.0,
             },
             "internal": {
                 "rotation_saturation_2": 0.0,
             },
             "output": {
                 "dangular_momentum_dt": Axes(0.0, 0.0, 0.0).get(),
             },
         },
     }
     if variant in ("Interaction", ):
         self._data["effect"] = variant
         # Update default values, ignore non-recognised keys
         for key, value in six.iteritems(input_parameters):
             if key in self._data["parameters"]["input"]:
                 self._data["parameters"]["input"][key] = float(value)
             else:
                 print("Ignored parameter: {}".format(key))
         self._data["parameters"]["internal"]["rotation_saturation_2"] = self._data["parameters"]["input"]["rotation_saturation"]*self._data["parameters"]["input"]["rotation_saturation"]
     elif variant in ("Disabled", ):
         self._data["effect"] = variant
     else:
         raise Exception("Unknown variant '{}'".format(variant))
Exemplo n.º 6
0
def calculate_keplerian_orbital_elements(target_mass, target_position, target_velocity, masses=[], positions=[], velocities=[]):
    """
    Calculate the keplerian orbital elements

    - target_mass: mass (typically the target planet mass+central body mass)
    - target_position: position (Axes)
    - target_velocity: position (Axes)

    In case of instead of a central massive body there are two (i.e., circumbinary
    planet), then it is necessary to provide their masses, positions and velocities
    (as list of Axes objects) and target_mass must correspond only to the planet
    mass. Order is important, for instance:

    - target_mass: planet mass
    - masses: [star1_mass, star2_mass]
    - positions: [star1_position, star2_position]
    - velocities: [star1_velocity, star2_velocity]

    It returns:

    - a: semi-major axis (in AU)
    - q: perihelion distance
    - eccentricity: eccentricity
    - i: inclination
    - p: longitude of perihelion (NOT the argument of perihelion)
    - n: longitude of ascending node
    - l: mean anomaly (or mean longitude if eccentricity < 1.e-8)
    """

    if not isinstance(masses, list):
        masses = [masses]
    if not isinstance(positions, list):
        positions = [positions]
    if not isinstance(velocities, list):
        velocities = [velocities]
    if len(masses) != len(positions):
        raise Exception("The number of masses needs to match the number of positions")
    elif len(masses) != len(velocities):
        raise Exception("The number of masses needs to match the number of velocities")

    if len(positions) > 0:
        center_of_mass_mass, center_of_mass_position, center_of_mass_velocity = calculate_center_of_mass(masses, positions, velocities)
        target_position = Axes(target_position.x()-center_of_mass_position.x(), target_position.y()-center_of_mass_position.y(), target_position.z()-center_of_mass_position.z())
        target_velocity = Axes(target_velocity.x()-center_of_mass_velocity.x(), target_velocity.y()-center_of_mass_velocity.y(), target_velocity.z()-center_of_mass_velocity.z())

    gm = G*(sum(masses)+target_mass)
    a, q, eccentricity, i, p, n, l = _calculate_keplerian_orbital_elements(gm, target_position, target_velocity)

    if len(positions) > 0:
        delta_a = np.sqrt(center_of_mass_position.x()**2 + center_of_mass_position.y()**2 + center_of_mass_position.z()**2)
        delta_q = delta_a * (1.0 - eccentricity);                     # perihelion distance
        a += delta_a
        q += delta_q
    return (a, q, eccentricity, i, p, n, l)
Exemplo n.º 7
0
def calculate_resonance_data(star_data, planets_keys, planets_data):
    # We initialize the arrays
    t = []  # time in years
    a = []  # demi-grand axe en ua
    e = []  # eccentricity
    g = []  # argument of pericentre or argument of perihelion (degrees)
    n = []  # longitude of ascending node (degrees)
    M = []  # Mean anomaly (degrees)
    q = []  # periastron or perihelion (AU)
    Q = []  # apastron or aphelion (AU)

    for key in planets_keys:
        planet_data = planets_data[key]
        target_mass = star_data['mass'] + planet_data['mass']
        target_position = Axes(planet_data['position_x'],
                               planet_data['position_y'],
                               planet_data['position_z'])
        target_velocity = Axes(planet_data['velocity_x'],
                               planet_data['velocity_y'],
                               planet_data['velocity_z'])
        _a, _q, _e, _i, _p, _n, _l = calculate_keplerian_orbital_elements(
            target_mass, target_position, target_velocity)
        t.append(planet_data['current_time'])  # Years
        a.append(_a)  # AU
        e.append(_e)
        # Change from longitude of perihelion to argument of perihelion
        longitude_of_perihelion_degrees = (_p * RAD2DEG) % 360.
        longitude_of_ascending_node_degrees = (_p * RAD2DEG) % 360.
        g.append((longitude_of_perihelion_degrees -
                  longitude_of_ascending_node_degrees) % 360.)
        n.append(longitude_of_ascending_node_degrees)
        M.append((_l * RAD2DEG) % 360.)
        #q.append(planet_data['perihelion_distance'])
        #Q.append(planet_data['semi-major_axis']*2 - planet_data['perihelion_distance'])
        q.append(_a * (1 - _e))
        Q.append(_a * (1 + _e))
    return t, a, e, g, n, M, q, Q
Exemplo n.º 8
0
 def __init__(self, variant, implementation=None):
     self._data = {
         "effect": "Disabled",
         "parameters": {
             "internal": {
                 "distance": 0.0,
                 "factor": 0.0,
                 "norm_velocity_vector": 0.0,
                 "norm_velocity_vector_2": 0.0,
                 "radial_velocity": 0.0,
             },
             "output": {
                 "acceleration": Axes(0.0, 0.0, 0.0).get(),
                 "dangular_momentum_dt": Axes(0.0, 0.0, 0.0).get(),
             },
         },
         "coordinates": {
             "position": Axes(0.0, 0.0, 0.0).get(),
             "velocity": Axes(0.0, 0.0, 0.0).get(),
         },
     }
     if variant in ("CentralBody", ):
         if implementation is None:
             raise Exception(
                 "General relativity central body requires an implementation"
             )
         self._data["effect"] = {
             variant: implementation,
         }
     elif variant in (
             "OrbitingBody",
             "Disabled",
     ):
         self._data["effect"] = variant
     else:
         raise Exception("Unknown variant '{}'".format(variant))
Exemplo n.º 9
0
 def __init__(self):
     mass = 0.0
     radius = 0.0
     radius_of_gyration_2 = 0.0
     position = Axes(0.0, 0.0, 0.0)
     velocity = Axes(0.0, 0.0, 0.0)
     spin = Axes(0.0, 0.0, 0.0)
     reference = MostMassiveParticle()
     tides = effects.tides.Disabled()
     rotational_flattening = effects.rotational_flattening.Disabled()
     general_relativity = effects.general_relativity.Disabled()
     wind = effects.wind.Disabled()
     disk = effects.disk.Disabled()
     evolution = effects.evolution.NonEvolving()
     super(DummyParticle, self).__init__(mass, radius, radius_of_gyration_2,
                                         position, velocity, spin)
     super(DummyParticle, self).set_tides(tides)
     super(DummyParticle,
           self).set_rotational_flattening(rotational_flattening)
     super(DummyParticle, self).set_general_relativity(general_relativity)
     super(DummyParticle, self).set_wind(wind)
     super(DummyParticle, self).set_disk(disk)
     super(DummyParticle, self).set_evolution(evolution)
     super(DummyParticle, self).set_reference(reference)
Exemplo n.º 10
0
    def populate_inertial_frame(self):
        # Compute center of mass
        center_of_mass_position = Axes(0., 0., 0.)
        center_of_mass_velocity = Axes(0., 0., 0.)
        center_of_mass_mass = 0.;

        masses = [p['mass'] for p in self._data['particles']]
        positions = [Axes(p['heliocentric_position']['x'], p['heliocentric_position']['y'], p['heliocentric_position']['z']) for p in self._data['particles']]
        velocities = [Axes(p['heliocentric_velocity']['x'], p['heliocentric_velocity']['y'], p['heliocentric_velocity']['z']) for p in self._data['particles']]
        center_of_mass_mass, center_of_mass_position, center_of_mass_velocity = calculate_center_of_mass(masses, positions, velocities)

        for particle in self._data['particles']:
            particle['inertial_position']['x'] = particle['heliocentric_position']['x'] - center_of_mass_position.x()
            particle['inertial_position']['y'] = particle['heliocentric_position']['y'] - center_of_mass_position.y()
            particle['inertial_position']['z'] = particle['heliocentric_position']['z'] - center_of_mass_position.z()
            particle['inertial_velocity']['x'] = particle['heliocentric_velocity']['x'] - center_of_mass_velocity.x()
            particle['inertial_velocity']['y'] = particle['heliocentric_velocity']['y'] - center_of_mass_velocity.y()
            particle['inertial_velocity']['z'] = particle['heliocentric_velocity']['z'] - center_of_mass_velocity.z()
Exemplo n.º 11
0
def calculate_center_of_mass(masses, positions, velocities):
    if not isinstance(masses, list):
        masses = [masses]
    if not isinstance(positions, list):
        positions = [positions]
    if not isinstance(velocities, list):
        velocities = [velocities]
    if len(masses) != len(positions):
        raise Exception("The number of masses needs to match the number of positions")
    elif len(masses) != len(velocities):
        raise Exception("The number of masses needs to match the number of velocities")
    elif len(masses) == 0:
        raise Exception("At least there should be one mass")

    if isinstance(masses[0], np.ndarray):
        # Case where the first dimension corresponds to different particles
        # and the second dimension to different moments in time of that object
        #
        # masses = [(1., 1.), (0.8, 0.8)]
        # positions = [Axes(...), (...)]
        # velocities = [Axes(...), (...)]
        n = len(masses[0])
        if n != len(positions[0].x()):
            raise Exception("The number of snapshots for masses needs to match the number of snapshots for positions")
        elif n != len(velocities[0].x()):
            raise Exception("The number of snapshots for masses needs to match the number of snapshots for velocities")
        center_of_mass_position = Axes(np.zeros(n), np.zeros(n), np.zeros(n))
        center_of_mass_velocity = Axes(np.zeros(n), np.zeros(n), np.zeros(n))
        center_of_mass_mass = np.zeros(n)
    else:
        center_of_mass_position = Axes(0., 0., 0.)
        center_of_mass_velocity = Axes(0., 0., 0.)
        center_of_mass_mass = 0.

    for particle_mass, particle_position, particle_velocity in zip(masses, positions, velocities):
        center_of_mass_position.set_x(center_of_mass_position.x()*center_of_mass_mass + particle_position.x()*particle_mass)
        center_of_mass_position.set_y(center_of_mass_position.y()*center_of_mass_mass + particle_position.y()*particle_mass)
        center_of_mass_position.set_z(center_of_mass_position.z()*center_of_mass_mass + particle_position.z()*particle_mass)
        center_of_mass_velocity.set_x(center_of_mass_velocity.x()*center_of_mass_mass + particle_velocity.x()*particle_mass)
        center_of_mass_velocity.set_y(center_of_mass_velocity.y()*center_of_mass_mass + particle_velocity.y()*particle_mass)
        center_of_mass_velocity.set_z(center_of_mass_velocity.z()*center_of_mass_mass + particle_velocity.z()*particle_mass)

        center_of_mass_mass = center_of_mass_mass + particle_mass
        # Assumption: no zero zero mass
        center_of_mass_position.set_x(center_of_mass_position.x() / center_of_mass_mass)
        center_of_mass_position.set_y(center_of_mass_position.y() / center_of_mass_mass)
        center_of_mass_position.set_z(center_of_mass_position.z() / center_of_mass_mass)
        center_of_mass_velocity.set_x(center_of_mass_velocity.x() / center_of_mass_mass)
        center_of_mass_velocity.set_y(center_of_mass_velocity.y() / center_of_mass_mass)
        center_of_mass_velocity.set_z(center_of_mass_velocity.z() / center_of_mass_mass)
    return center_of_mass_mass, center_of_mass_position, center_of_mass_velocity
Exemplo n.º 12
0
def calculate_spin(angular_frequency, inclination, obliquity):
    x = 0.
    y = -1.*angular_frequency * np.sin(obliquity+inclination)
    z = angular_frequency * np.cos(obliquity+inclination)
    return Axes(x, y, z)
Exemplo n.º 13
0
def classify(n_particles,
             data,
             reference_particle_index=0,
             discard_first_hundred_years=False):
    # Ignore first 100 years
    data['current_time'] /= 365.25  # From days to years
    if discard_first_hundred_years:
        data = data[data['current_time'] >= 100.]

    star = data['particle'] == reference_particle_index
    star_data = data[star]

    planets_data = {}
    planets_keys = []  # To ensure the order
    for i in range(n_particles - 1):
        planets_data["{}".format(i + 1)] = data[data['particle'] == i + 1]
        planets_keys.append("{}".format(i + 1))

    # From inertial to heliocentric coordinates
    n_data_points = len(star_data['position_x'])
    zeros = Axes(np.zeros(n_data_points), np.zeros(n_data_points),
                 np.zeros(n_data_points))
    for key in planets_keys:
        planets_data[key]['position_x'] -= star_data['position_x']
        planets_data[key]['position_y'] -= star_data['position_y']
        planets_data[key]['position_z'] -= star_data['position_z']
        planets_data[key]['velocity_x'] -= star_data['velocity_x']
        planets_data[key]['velocity_y'] -= star_data['velocity_y']
        planets_data[key]['velocity_z'] -= star_data['velocity_z']
        semimajor_axis = []
        eccentricity = []
        inclination = []
        target_mass = planets_data[key]['mass']
        target_position = Axes(planets_data[key]['position_x'],
                               planets_data[key]['position_y'],
                               planets_data[key]['position_z'])
        target_velocity = Axes(planets_data[key]['velocity_x'],
                               planets_data[key]['velocity_y'],
                               planets_data[key]['velocity_z'])
        masses = [planets_data[k]['mass'] for k in planets_keys if k != key]
        masses.insert(0, star_data['mass'])
        positions = [
            Axes(planets_data[k]['position_x'], planets_data[k]['position_y'],
                 planets_data[k]['position_z']) for k in planets_keys
            if k != key
        ]
        positions.insert(0, zeros)  # Star is at the center
        velocities = [
            Axes(planets_data[k]['velocity_x'], planets_data[k]['velocity_y'],
                 planets_data[k]['velocity_z']) for k in planets_keys
            if k != key
        ]
        velocities.insert(0, zeros)  # Star is resting
        a, q, e, i, p, n, l = posidonius.tools.calculate_keplerian_orbital_elements(
            target_mass,
            target_position,
            target_velocity,
            masses=masses,
            positions=positions,
            velocities=velocities)
        #a, q, e, i, p, n, l = posidonius.tools.calculate_keplerian_orbital_elements(target_mass+star_data['mass'], target_position, target_velocity)
        planets_data[key] = append_fields(
            planets_data[key],
            ('semi-major_axis', 'eccentricity', 'inclination'), (a, e, i),
            usemask=False)
    star_data['position_x'] = 0.
    star_data['position_y'] = 0.
    star_data['position_z'] = 0.
    star_data['velocity_x'] = 0.
    star_data['velocity_y'] = 0.
    star_data['velocity_z'] = 0.
    return star_data, planets_data, planets_keys
Exemplo n.º 14
0
    def add_particle(self, particle):
        if self._data['n_particles'] > MAX_PARTICLES:
            raise Exception("Maximum number of particles reached: {}".format(MAX_PARTICLES))

        if effects.tides.CentralBody in particle.effects():
            if self._data["consider_effects"]["tides"]:
                if self._data['hosts']['index']['tides'] == MAX_PARTICLES+1:
                    self._data['hosts']['index']['tides'] = self._data['n_particles']
                else:
                    raise Exception("There can only be one central body for tidal effects!")
            else:
                print("[WARNING {} UTC] Added a particle with tidal effect (central body) but the tidal effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))
        if not self._data["consider_effects"]["tides"] and effects.tides.OrbitingBody in particle.effects():
            print("[WARNING {} UTC] Added a particle with tidal effect (orbiting body) but the tidal effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        if effects.rotational_flattening.CentralBody in particle.effects():
            if self._data["consider_effects"]["rotational_flattening"]:
                if self._data['hosts']['index']['rotational_flattening'] == MAX_PARTICLES+1:
                    self._data['hosts']['index']['rotational_flattening'] = self._data['n_particles']
                else:
                    raise Exception("There can only be one central body for rotational flattening effects!")
            else:
                print("[WARNING {} UTC] Added a particle with rotational flattening effect (central body) but the rotational flattening effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))
        if not self._data["consider_effects"]["rotational_flattening"] and effects.rotational_flattening.OrbitingBody in particle.effects():
            print("[WARNING {} UTC] Added a particle with rotational flattening effect (orbiting body) but the rotational flattening effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        if effects.general_relativity.CentralBody in particle.effects():
            if self._data["consider_effects"]["general_relativity"]:
                if self._data['hosts']['index']['general_relativity'] == MAX_PARTICLES+1:
                    self._data['hosts']['index']['general_relativity'] = self._data['n_particles']
                else:
                    raise Exception("There can only be one central body for rotational flattening effects!")
                self._data['general_relativity_implementation'] = particle.general_relativity_implementation()
            else:
                print("[WARNING {} UTC] Added a particle with general relativity effect (central body) but the general relativity effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))
        if not self._data["consider_effects"]["general_relativity"] and effects.general_relativity.OrbitingBody in particle.effects():
            print("[WARNING {} UTC] Added a particle with general relativity effect (orbiting body) but the general relativity effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        if effects.disk.CentralBody in particle.effects():
            if self._data["consider_effects"]["disk"]:
                if self._data['hosts']['index']['disk'] == MAX_PARTICLES+1:
                    self._data['hosts']['index']['disk'] = self._data['n_particles']
                else:
                    raise Exception("Only one body with a disk is allowed!")
            else:
                print("[WARNING {} UTC] Added a particle with disk effect (central body) but the disk effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))
        if not self._data["consider_effects"]["disk"] and effects.disk.OrbitingBody in particle.effects():
            print("[WARNING {} UTC] Added a particle with disk effect (orbiting body) but the disk effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        if effects.wind.Interaction in particle.effects():
            if not self._data["consider_effects"]["wind"]:
                print("[WARNING {} UTC] Added a particle with wind effect but the wind effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        if particle.evolution() != effects.evolution.NonEvolving:
            if not self._data["consider_effects"]["evolution"]:
                print("[WARNING {} UTC] Added a particle with evolution effect but the evolution effect is disabled for this simulation".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))

        evolver = particle.get_evolver(self._data['initial_time'])
        if len(evolver['time']) > 0 and evolver['time'][0] > 0.:
            raise Exception("Your initial time ({} days | {:.2e} years) is smaller than the minimum allowed age of the star ({} days | {:.2e} years)".format(self._data['initial_time'], self._data['initial_time']/365.25, evolver['time'][0]+self._data['initial_time'], (evolver['time'][0]+self._data['initial_time'])/365.25));
        if len(evolver['time']) > 0 and evolver['time'][-1] < self._data['initial_time']:
            raise Exception("Your time limit ({} days | {:.2e} years) is greater than the maximum allowed age of the star ({} days | {:.2e} years)", self._data['initial_time'], self._data['initial_time']/365.25, evolver['time'][0], evolver['time'][0]/365.25)

        if particle.evolution() != effects.evolution.NonEvolving and self._data["consider_effects"]["evolution"]:
            # Check if input radius is close enough to evolved radius at the corresponding time and update it + angular momentum if not
            update_angular_momentum = False
            current_time = 0
            if len(evolver.get("radius", [])) > 0:
                # Scipy's spline interpolation of first order is the closest to current rust spline interpolation implementation
                radius = linear_interpolation(current_time, evolver['time'], evolver['radius'])
                if abs(radius - particle._data["radius"]) > 1e-6:
                    print("[WARNING {} UTC] Changed radius value from '{:.6f}' to '{:.6f}' to match expected state following the selected evolving body model".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S"), particle._data["radius"], radius))
                    particle._data["radius"] = radius
                    update_angular_momentum = True
            if len(evolver.get("radius_of_gyration_2", [])) > 0:
                # Scipy's spline interpolation of first order is the closest to current rust spline interpolation implementation
                radius_of_gyration_2 = linear_interpolation(current_time, evolver['time'], evolver['radius_of_gyration_2'])
                if abs(radius_of_gyration_2 - particle._data["radius_of_gyration_2"]) > 1e-6:
                    print("[WARNING {} UTC] Changed radius of gyration value from '{:.6f}' to '{:.6f}' to match expected state following the selected evolving body model".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S"), math.sqrt(particle._data["radius_of_gyration_2"]), math.sqrt(radius_of_gyration_2)))
                    particle._data["radius_of_gyration_2"] = radius_of_gyration_2
                    update_angular_momentum = True
            if update_angular_momentum:
                print("[WARNING {} UTC] Recomputed moment of inertia and angular momentum to match expected state following the selected evolving body model".format(datetime.datetime.utcnow().strftime("%Y.%m.%d %H:%M:%S")))
                particle._data["moment_of_inertia"] = float(particle._data["mass"])*float(particle._data["radius_of_gyration_2"])*float(particle._data["radius"])*float(particle._data["radius"])
                particle._data["angular_momentum"] = Axes(particle._data["spin"]["x"]*particle._data["moment_of_inertia"],
                                                          particle._data["spin"]["y"]*particle._data["moment_of_inertia"],
                                                          particle._data["spin"]["z"]*particle._data["moment_of_inertia"]).get()

        self._data['particles'].append(particle.get())
        self._data['particles_evolvers'].append(evolver)
        self._data['n_particles'] += 1
Exemplo n.º 15
0
 def __init__(self, mass, radius, radius_of_gyration, position, velocity,
              spin):
     radius_of_gyration_2 = float(radius_of_gyration)**2
     reference = MostMassiveParticle()
     tides = effects.tides.Disabled()
     rotational_flattening = effects.rotational_flattening.Disabled()
     general_relativity = effects.general_relativity.Disabled()
     wind = effects.wind.Disabled()
     disk = effects.disk.Disabled()
     evolution = NonEvolving()
     self._data = {
         "dangular_momentum_dt":
         Axes(0.0, 0.0, 0.0).get(),
         "dangular_momentum_dt_per_moment_of_inertia":
         Axes(0.0, 0.0, 0.0).get(),
         "disk":
         disk.get(),
         "evolution":
         evolution.get(),
         "general_relativity":
         general_relativity.get(),
         "heliocentric_distance":
         0.0,
         "heliocentric_norm_velocity_vector":
         0.0,
         "heliocentric_norm_velocity_vector_2":
         0.0,
         "heliocentric_position":
         position.get(),
         "heliocentric_radial_velocity":
         0.0,
         "heliocentric_velocity":
         velocity.get(),
         "id":
         0,
         "inertial_acceleration_error":
         Axes(0.0, 0.0, 0.0).get(),
         "inertial_acceleration":
         Axes(0.0, 0.0, 0.0).get(),
         "inertial_position":
         Axes(0.0, 0.0, 0.0).get(),
         "inertial_velocity":
         Axes(0.0, 0.0, 0.0).get(),
         "mass":
         float(mass),
         "mass_g":
         float(mass) * K2,
         "moment_of_inertia":
         float(mass) * float(radius_of_gyration_2) * float(radius) *
         float(radius),
         "moment_of_inertia_ratio":
         1.0,
         "norm_spin_vector_2":
         spin.x()**2 + spin.y()**2 + spin.z()**2,
         "radius":
         float(radius),
         "radius_of_gyration_2":
         float(radius_of_gyration_2),
         "reference":
         reference.get(),
         "rotational_flattening":
         rotational_flattening.get(),
         "spin":
         spin.get(),
         "tides":
         tides.get(),
         "wind":
         wind.get(),
     }
     self._effects = {
         'tides': tides,
         'rotational_flattening': rotational_flattening,
         'general_relativity': general_relativity,
         'wind': wind,
         'disk': disk,
     }
     self._evolution = evolution