def definePlanetarySystem(m, a, e, I, m_star=1.0, epoch=0, d=None):
    """ We will assume a certain number of parameters. For example, all bodies will be big bodies. 
  We will also assume that all the bodies will be set with the 'asteroidal' properties (that is to say (a, e, I, g, n, M)). Plus, 
  g, n, M ill be randomly generated (g the argument of pericentre (degrees), n the longitude of the ascending node (degrees), 
  M the mean anomaly (degrees) )
  
  CONSTANTS : 
  PREFIX_BIG : This is a name prefix, whose length must be 7. This will be used to set automatic name to the bodies
  
  Parameters : 
  m_star=1.0 : By default, the mass of the central object will be the mass of our sun.
  epoch=0 : By default, planetary systems are not real. Thus, we set the start time to 0 to be more convenient
  
  m, a, e, I: they must be lists of the same length, one element for each planet. 
  (m the mass (in solar mass), a the semi major axis (in AU), e the eccentricity, I the inclination (in degrees))
  
  d : The density for each body (in g/cm^3), optional argument
  
  
  Return : 
  An object PlanetarySystem defined with the given parameters
  """

    if (type(m) != list):
        raise TypeError("'m' must be a list")

    if (type(a) != list):
        raise TypeError("'a' must be a list")

    if (type(e) != list):
        raise TypeError("'e' must be a list")

    if (type(I) != list):
        raise TypeError("'I' must be a list")

    # We test if the lists are of the same length
    nb_planets = len(a)
    for param in [m, a, e, I]:
        if (len(param) != nb_planets):
            raise ValueError("(m, a, e, I) must be of the same length")

    if (d == None):
        d = [None] * nb_planets

    # We generate randomly g, n, and M
    g = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)
    n = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)
    M = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)

    #~ g = [uniform(0, 360) for i in range(nb_planets)]
    #~ n = [uniform(0, 360) for i in range(nb_planets)]
    #~ M = [uniform(0, 360) for i in range(nb_planets)]

    bodies = []
    index = 1
    for (mi, ai, ei, Ii, gi, ni, Mi, di) in zip(m, a, e, I, g, n, M, d):
        bodies.append(
            mercury.BodyAst("big",
                            m=mi,
                            a=ai,
                            e=ei,
                            I=Ii,
                            g=gi,
                            n=ni,
                            M=Mi,
                            ep=epoch,
                            d=di))
        index += 1

    return mercury.PlanetarySystem(bodies=bodies, m_star=m_star, epoch=epoch)
Example #2
0
def generation_simulation_parameters():
    """the function generate simulations files in the current working directory, given the parameters on top of the script
  """

    output_interval = integration_time / float(nb_outputs)
    data_dump = abs(int(integration_time / (nb_dumps * timestep)))

    if (aei_outputs < nb_outputs):
        aei_time = integration_time / float(aei_outputs)
    else:
        aei_time = 0.0  # We want to see all the outputs of xv.out

    # We begin the random generation of parameters.
    if FIXED_TOTAL_MASS:
        total_mass = 0
        m = []
        if (type(mass_parameters[0]) == list):
            print(
                "Warning: We can only specify a list of pre-planets in the case where the number of planet is fixed (and not the total mass)"
            )
            exit()

        while (total_mass < TOTAL_MASS):
            m0 = simulations_utilities.setParameter(
                mass_parameters, 1
            )[0]  # The function return a list, and we want to have one element
            # the mass must be expressed relatively to the mass of the central body
            m.append(simulations_utilities.significativeRound(m0 * MT / MS, 4))
            total_mass += m0
        nb_planets = len(m)
    else:
        nb_planets = NB_PLANETS

        m = simulations_utilities.setParameter(mass_parameters, nb_planets)
        m = [mi * MT / MS for mi in m]

    # By default, we do not specify density
    d = [None for mi in m]

    #~ # To add manually one massive planet in the set of planets.
    #~ random_index = random.randint(0, nb_planets)
    #~ random_mass = random.uniform(4, 5)
    #~ m.insert(random_index, random_mass * MT / MS)
    #~ nb_planets += 1

    # This type is special and only for orbital distance. It define the various distances upon the mutual hill radii distance.
    # It is possible, by including two values in a tuple instead of a single value to define a random calculation of the distance
    # (whether the initial radius of the innermost planet of the hill separation.)
    if (type(a_parameters) in [list, tuple] and a_parameters[-1] == 'rh'):
        if (type(a_parameters[0]) == tuple):
            a = [random.uniform(a_parameters[0][0], a_parameters[0][1])]
        else:
            a = [a_parameters[0]]

        # If the value is a tuple, we generate a random value of delta between the two values, else, we take the only value.
        if (type(a_parameters[1]) == tuple):
            delta = [
                random.uniform(a_parameters[1][0], a_parameters[1][1])
                for i in range(nb_planets)
            ]  # the first value will never be used
        else:
            delta = [a_parameters[1] for i in range(nb_planets)
                     ]  # the first value will never be used

        for i in range(1, nb_planets):
            chi = delta[i] / 2. * ((m[i - 1] + m[i]) / (3 * m_star))**(1 / 3.)
            ai = a[i - 1] * (1 + chi) / (1 - chi)
            a.append(ai)
    elif (type(a_parameters) in [list, tuple]
          and a_parameters[-1] == 'from-dust'):
        a = []
        previous_position = disk_edges[0]
        dust_to_gas_ratio = a_parameters[0]
        iceline = a_parameters[1]
        HIGH_DENSITY = 3.0  # g/cm^3
        LOW_DENISTY = 1.0  # g/cm^3

        # We will define densities
        d = []

        for mi in m:
            planet_mass = mi * (MS / MT
                                )  # m in solar mass, we want it in earth mass
            ai = planet_from_dust(surface_density, disk_edges,
                                  dust_to_gas_ratio, iceline, planet_mass,
                                  previous_position)
            a.append(ai)

            if (ai < iceline[0]):
                di = HIGH_DENSITY
            else:
                di = LOW_DENISTY
            d.append(di)
            previous_position = ai
        #~ prefactor = 2 * pi * 500. * ((AU * 1e2)**2) / (MT * 1e3)
        #~ total_mass = prefactor / 1.5 * 0.01 * (iceline[0]**1.5 - 0.1**1.5)
        #~ total_mass += prefactor / 1.5 * 0.01 * iceline[1] * (ai**1.5 - iceline[0]**1.5)
        #~ print(np.sum(m) * (MS/MT))
        #~ print("total_mass=%f" % total_mass)

    else:
        a = simulations_utilities.setParameter(a_parameters, nb_planets)

    e = simulations_utilities.setParameter(e_parameters, nb_planets)
    I = simulations_utilities.setParameter(I_parameters, nb_planets)

    # If there is planet beyong the ejection distance, we remove them before the simulation start :
    m_to_del = []
    a_to_del = []
    e_to_del = []
    I_to_del = []
    for (mi, ai, ei, Ii) in zip(m, a, e, I):
        if (ai > EJECTION_DISTANCE):
            m_to_del.append(mi)
            a_to_del.append(ai)
            e_to_del.append(ei)
            I_to_del.append(Ii)
    for (mi, ai, ei, Ii) in zip(m_to_del, a_to_del, e_to_del, I_to_del):
        m.remove(mi)
        a.remove(ai)
        e.remove(ei)
        I.remove(Ii)

    len_m = len(m)
    len_a = len(a)
    len_e = len(e)
    len_I = len(I)

    if ((len_m != len_a) or (len_a != len_e) or (len_e != len_I)):
        raise TypeError("The size of {m,a,e,I} is not the same")

    system = mercury_utilities.definePlanetarySystem(m=m, a=a, e=e, I=I, d=d)

    # We write the files

    bigin = mercury.Big(system)
    bigin.write()

    smallin = mercury.Small(system)
    smallin.write()
    if not (os.path.exists("small.in")):
        pdb.set_trace()

    # Setting the output interval to 0 ensure that we will have every output written in the xv.out in the element files.
    elementin = mercury.Element(
        format_sortie=" a8.5 e8.6 i8.4 g8.4 n8.4 l8.4 m13e ",
        coord="Cen",
        output_interval=aei_time,
        time_format=time_format,
        relative_time=relative_time)
    elementin.write()

    closein = mercury.Close(time_format=time_format,
                            relative_time=relative_time)
    closein.write()

    paramin = mercury.Param(algorithme="HYBRID",
                            start_time=0,
                            stop_time=integration_time,
                            output_interval=output_interval,
                            h=timestep,
                            accuracy=1.e-12,
                            stop_integration="no",
                            collisions="yes",
                            fragmentation="no",
                            time_format=time_format,
                            relative_time=relative_time,
                            output_precision="medium",
                            relativity="no",
                            user_force=user_force,
                            ejection_distance=EJECTION_DISTANCE,
                            radius_star=radius_star,
                            central_mass=1.0,
                            J2=0,
                            J4=0,
                            J6=0,
                            changeover=3.,
                            data_dump=data_dump,
                            periodic_effect=100)
    paramin.write()

    filesin = mercury.Files()
    filesin.write()

    messagein = mercury.Message()
    messagein.write()

    if (user_force == "yes"):
        diskin = mercury.Disk(
            b_over_h=b_h,
            adiabatic_index=adiabatic_index,
            mean_molecular_weight=2.35,
            surface_density=surface_density,
            is_irradiation=is_irradiation,
            disk_edges=disk_edges,
            viscosity=viscosity,
            opacity_type=opacity_type,
            sample=sample,
            dissipation_type=dissipation_type,
            is_turbulence=is_turbulence,
            turbulent_forcing=turbulent_forcing,
            inner_smoothing_width=inner_smoothing_width,
            tau_viscous=tau_viscous,
            tau_photoevap=tau_photoevap,
            dissipation_time_switch=dissipation_time_switch,
            disk_exponential_decay=disk_exponential_decay,
            torque_type=torque_type,
            inner_boundary_condition=inner_boundary_condition,
            outer_boundary_condition=outer_boundary_condition,
            torque_profile_steepness=torque_profile_steepness,
            indep_cz=indep_cz,
            mass_dep_m_min=mass_dep_m_min,
            saturation_torque=saturation_torque,
            mass_dep_m_max=mass_dep_m_max,
            mass_dep_cz_m_min=mass_dep_cz_m_min,
            mass_dep_cz_m_max=mass_dep_cz_m_max)
        diskin.write()

        # If we want to use a manual torque profile, we copy the torque profile from the current working directory
        if (torque_type == 'manual'):
            if (os.path.isfile("../" + torque_file)):
                shutil.copy2("../" + torque_file, "./" + torque_file)
            else:
                raise NameError(
                    "The file " + torque_file +
                    " does not exist in the parent directory\n keep in mind to delete the created folder."
                )

        # If we want to use a manual surface density profile, we copy the density profile from the current working directory
        if (surface_density == 'manual'):
            if (os.path.isfile("../" + density_file)):
                shutil.copy2("../" + density_file, "./" + density_file)
            else:
                raise NameError(
                    "The file " + density_file +
                    " does not exist in the parent directory\n keep in mind to delete the created folder."
                )

    # We store a log file of the simulation parameters
    f = open(SUB_FOLDER_LOG, 'w')
    f.write(PARAMETERS)
    f.close()

    # We reset the counters for planet names
    mercury.Body.resetCounter()
def generation_simulation_parameters():
  """the function generate simulations files in the current working directory, given the parameters on top of the script
  """
  
  output_interval = integration_time / float(nb_outputs)
  data_dump = abs(int(integration_time / (nb_dumps * timestep)))
  
  if (aei_outputs < nb_outputs):
    aei_time = integration_time / float(aei_outputs)
  else:
    aei_time = 0.0 # We want to see all the outputs of xv.out

  # We begin the random generation of parameters.
  if FIXED_TOTAL_MASS:
    total_mass = 0
    m = []
    if (type(mass_parameters[0]) == list):
      print("Warning: We can only specify a list of pre-planets in the case where the number of planet is fixed (and not the total mass)")
      exit()
    
    while (total_mass < TOTAL_MASS):
      m0 = simulations_utilities.setParameter(mass_parameters, 1)[0] # The function return a list, and we want to have one element
      # the mass must be expressed relatively to the mass of the central body
      m.append(simulations_utilities.significativeRound(m0 * MT / MS, 4))
      total_mass += m0
    nb_planets = len(m)
  else:
    nb_planets = NB_PLANETS
    
    m = simulations_utilities.setParameter(mass_parameters, nb_planets)
    m = [mi * MT / MS for mi in m]
  
  # By default, we do not specify density
  d = [None for mi in m]
  
  #~ # To add manually one massive planet in the set of planets.
  #~ random_index = random.randint(0, nb_planets)
  #~ random_mass = random.uniform(4, 5)
  #~ m.insert(random_index, random_mass * MT / MS)
  #~ nb_planets += 1

# This type is special and only for orbital distance. It define the various distances upon the mutual hill radii distance. 
# It is possible, by including two values in a tuple instead of a single value to define a random calculation of the distance 
# (whether the initial radius of the innermost planet of the hill separation.)
  if (type(a_parameters) in [list, tuple] and a_parameters[-1] == 'rh'):
    if (type(a_parameters[0]) == tuple):
      a = [random.uniform(a_parameters[0][0], a_parameters[0][1])]
    else:
      a = [a_parameters[0]]
      
    # If the value is a tuple, we generate a random value of delta between the two values, else, we take the only value.
    if (type(a_parameters[1]) == tuple):
      delta = [random.uniform(a_parameters[1][0], a_parameters[1][1]) for i in range(nb_planets)] # the first value will never be used
    else:
      delta = [a_parameters[1] for i in range(nb_planets)] # the first value will never be used
      
    for i in range(1,nb_planets):
      chi = delta[i] / 2. * ((m[i-1] + m[i]) / (3 * m_star))**(1/3.)
      ai = a[i-1] * (1 + chi) / (1 - chi)
      a.append(ai)
  elif (type(a_parameters) in [list, tuple] and a_parameters[-1] == 'from-dust'):
    a = []
    previous_position = disk_edges[0]
    dust_to_gas_ratio = a_parameters[0]
    iceline = a_parameters[1]
    HIGH_DENSITY = 3.0 # g/cm^3
    LOW_DENISTY  = 1.0 # g/cm^3
    
    # We will define densities
    d = []
    
    for mi in m:
      planet_mass = mi * (MS/MT) # m in solar mass, we want it in earth mass
      ai = planet_from_dust(surface_density, disk_edges, dust_to_gas_ratio, iceline, planet_mass, previous_position)
      a.append(ai)

      if (ai < iceline[0]):
        di = HIGH_DENSITY
      else:
        di = LOW_DENISTY
      d.append(di)
      previous_position = ai
    #~ prefactor = 2 * pi * 500. * ((AU * 1e2)**2) / (MT * 1e3)
    #~ total_mass = prefactor / 1.5 * 0.01 * (iceline[0]**1.5 - 0.1**1.5)
    #~ total_mass += prefactor / 1.5 * 0.01 * iceline[1] * (ai**1.5 - iceline[0]**1.5)
    #~ print(np.sum(m) * (MS/MT))
    #~ print("total_mass=%f" % total_mass)
    
  else:
    a = simulations_utilities.setParameter(a_parameters, nb_planets)
    
  e = simulations_utilities.setParameter(e_parameters, nb_planets)
  I = simulations_utilities.setParameter(I_parameters, nb_planets)
  
  # If there is planet beyong the ejection distance, we remove them before the simulation start :
  m_to_del = []
  a_to_del = []
  e_to_del = []
  I_to_del = []
  for (mi, ai, ei, Ii) in zip(m, a, e, I):
    if (ai > EJECTION_DISTANCE):
      m_to_del.append(mi)
      a_to_del.append(ai)
      e_to_del.append(ei)
      I_to_del.append(Ii)
  for (mi, ai, ei, Ii) in zip(m_to_del, a_to_del, e_to_del, I_to_del):
    m.remove(mi)
    a.remove(ai)
    e.remove(ei)
    I.remove(Ii)
  
  len_m = len(m)
  len_a = len(a)
  len_e = len(e)
  len_I = len(I)
  
  if ((len_m != len_a) or (len_a != len_e) or (len_e != len_I)):
    raise TypeError("The size of {m,a,e,I} is not the same")

  system = mercury_utilities.definePlanetarySystem(m=m, a=a, e=e, I=I, d=d)

  # We write the files

  bigin = mercury.Big(system)
  bigin.write()

  smallin = mercury.Small(system)
  smallin.write()
  if not(os.path.exists("small.in")):
    pdb.set_trace()

  # Setting the output interval to 0 ensure that we will have every output written in the xv.out in the element files.
  elementin = mercury.Element(format_sortie=" a8.5 e8.6 i8.4 g8.4 n8.4 l8.4 m13e ", coord="Cen", 
  output_interval=aei_time, time_format=time_format, relative_time=relative_time)
  elementin.write()

  closein = mercury.Close(time_format=time_format, relative_time=relative_time)
  closein.write()

  paramin = mercury.Param(algorithme="HYBRID", start_time=0, stop_time=integration_time, output_interval=output_interval, 
  h=timestep, accuracy=1.e-12, stop_integration="no", collisions="yes", fragmentation="no", 
  time_format=time_format, relative_time=relative_time, output_precision="medium", relativity="no", 
  user_force=user_force, ejection_distance=EJECTION_DISTANCE, radius_star=radius_star, central_mass=1.0, 
  J2=0, J4=0, J6=0, changeover=3., data_dump=data_dump, periodic_effect=100)
  paramin.write()

  filesin = mercury.Files()
  filesin.write()

  messagein = mercury.Message()
  messagein.write()
  
  

  if (user_force == "yes"):
    diskin = mercury.Disk(b_over_h=b_h, adiabatic_index=adiabatic_index, mean_molecular_weight=2.35, surface_density=surface_density, 
                  is_irradiation=is_irradiation,
                  disk_edges=disk_edges, viscosity=viscosity, opacity_type=opacity_type, sample=sample, dissipation_type=dissipation_type, 
                  is_turbulence=is_turbulence, turbulent_forcing=turbulent_forcing, inner_smoothing_width=inner_smoothing_width,
                  tau_viscous=tau_viscous, tau_photoevap=tau_photoevap, dissipation_time_switch=dissipation_time_switch, 
                  disk_exponential_decay=disk_exponential_decay, torque_type=torque_type,
                  inner_boundary_condition=inner_boundary_condition, outer_boundary_condition=outer_boundary_condition,
                  torque_profile_steepness=torque_profile_steepness, indep_cz=indep_cz, mass_dep_m_min=mass_dep_m_min, 
                  saturation_torque=saturation_torque,
                  mass_dep_m_max=mass_dep_m_max, mass_dep_cz_m_min=mass_dep_cz_m_min, mass_dep_cz_m_max=mass_dep_cz_m_max)
    diskin.write()
    
    # If we want to use a manual torque profile, we copy the torque profile from the current working directory
    if (torque_type == 'manual'):
      if (os.path.isfile("../"+torque_file)):
        shutil.copy2("../"+torque_file, "./"+torque_file)
      else:
        raise NameError("The file "+torque_file+" does not exist in the parent directory\n keep in mind to delete the created folder.")
        
        
    # If we want to use a manual surface density profile, we copy the density profile from the current working directory
    if (surface_density == 'manual'):
      if (os.path.isfile("../"+density_file)):
        shutil.copy2("../"+density_file, "./"+density_file)
      else:
        raise NameError("The file "+density_file+" does not exist in the parent directory\n keep in mind to delete the created folder.")
        
  
  # We store a log file of the simulation parameters
  f = open(SUB_FOLDER_LOG, 'w')
  f.write(PARAMETERS)
  f.close()
  
  # We reset the counters for planet names
  mercury.Body.resetCounter()
Example #4
0
def definePlanetarySystem(m, a, e, I, m_star=1.0, epoch=0, d=None):
  """ We will assume a certain number of parameters. For example, all bodies will be big bodies. 
  We will also assume that all the bodies will be set with the 'asteroidal' properties (that is to say (a, e, I, g, n, M)). Plus, 
  g, n, M ill be randomly generated (g the argument of pericentre (degrees), n the longitude of the ascending node (degrees), 
  M the mean anomaly (degrees) )
  
  CONSTANTS : 
  PREFIX_BIG : This is a name prefix, whose length must be 7. This will be used to set automatic name to the bodies
  
  Parameters : 
  m_star=1.0 : By default, the mass of the central object will be the mass of our sun.
  epoch=0 : By default, planetary systems are not real. Thus, we set the start time to 0 to be more convenient
  
  m, a, e, I: they must be lists of the same length, one element for each planet. 
  (m the mass (in solar mass), a the semi major axis (in AU), e the eccentricity, I the inclination (in degrees))
  
  d : The density for each body (in g/cm^3), optional argument
  
  
  Return : 
  An object PlanetarySystem defined with the given parameters
  """
  
  if (type(m) != list):
    raise TypeError("'m' must be a list")
  
  if (type(a) != list):
    raise TypeError("'a' must be a list")
  
  if (type(e) != list):
    raise TypeError("'e' must be a list")
  
  if (type(I) != list):
    raise TypeError("'I' must be a list")
  
  
  # We test if the lists are of the same length
  nb_planets = len(a)
  for param in [m, a, e, I]:
    if (len(param) != nb_planets):
      raise ValueError("(m, a, e, I) must be of the same length")
  
  if (d == None):
    d = [None] * nb_planets
  
  # We generate randomly g, n, and M
  g = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)
  n = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)
  M = simulations_utilities.setParameter((0, 360, 'uniform'), nb_planets)

  #~ g = [uniform(0, 360) for i in range(nb_planets)]
  #~ n = [uniform(0, 360) for i in range(nb_planets)]
  #~ M = [uniform(0, 360) for i in range(nb_planets)]
  
  bodies = []
  index = 1
  for (mi, ai, ei, Ii, gi, ni, Mi, di) in zip(m, a, e, I, g, n, M, d):
    bodies.append(mercury.BodyAst("big", m=mi, a=ai, e=ei, I=Ii, 
g=gi, n=ni, M=Mi, ep=epoch, d=di))
    index += 1
  
  return mercury.PlanetarySystem(bodies=bodies, m_star=m_star, epoch=epoch)