use crate::config::parameters::*;
use std::f64::consts::PI;
#[derive(Clone, Copy)]
pub enum FormationChannel {
CoreAccretion,
DiskInstability,
PebbleAccretion,
}
pub struct FormationModel {
pub channel: FormationChannel,
pub disk_mass: f64,
pub stellar_mass: f64,
pub metallicity: f64,
pub snow_line_au: f64,
}
impl FormationModel {
pub fn new(
channel: FormationChannel,
disk_mass: f64,
stellar_mass: f64,
metallicity: f64,
snow_line_au: f64,
) -> Self {
Self {
channel,
disk_mass,
stellar_mass,
metallicity,
snow_line_au,
}
}
pub fn solar_like() -> Self {
Self {
channel: FormationChannel::CoreAccretion,
disk_mass: 0.01 * SOLAR_MASS,
stellar_mass: SOLAR_MASS,
metallicity: 0.02,
snow_line_au: 2.7,
}
}
pub fn snow_line_radius(&self) -> f64 {
self.snow_line_au * AU
}
pub fn disk_surface_density(&self, r_au: f64) -> f64 {
let sigma_0 = self.disk_mass / (2.0 * PI * (AU * AU) * 100.0);
sigma_0 * r_au.powf(-1.5)
}
pub fn isolation_mass(&self, r_au: f64) -> f64 {
let sigma = self.disk_surface_density(r_au);
let a = r_au * AU;
let feeding_zone = 10.0 * hill_radius(a, EARTH_MASS, self.stellar_mass);
2.0 * PI * a * feeding_zone * sigma
}
pub fn critical_core_mass(&self) -> f64 {
10.0 * EARTH_MASS
}
pub fn runaway_gas_accretion_rate(&self, core_mass: f64) -> f64 {
let m_crit = self.critical_core_mass();
if core_mass < m_crit {
return 0.0;
}
let excess = (core_mass - m_crit) / m_crit;
1e-3 * EARTH_MASS / YEAR * excess.powi(2)
}
pub fn pebble_accretion_rate(&self, planet_mass: f64, r_au: f64) -> f64 {
let a = r_au * AU;
let v_k = orbital_velocity(self.stellar_mass, a);
let r_h = hill_radius(a, planet_mass, self.stellar_mass);
let pebble_flux = 1e-4 * EARTH_MASS / YEAR;
let tau_s = 0.1;
let r_acc = r_h * (tau_s / 0.1_f64).sqrt();
pebble_flux * (2.0 * r_acc / a).min(1.0) * (v_k / (v_k + 1.0e-30))
}
pub fn disk_instability_mass(&self, r_au: f64) -> f64 {
let sigma = self.disk_surface_density(r_au);
let a = r_au * AU;
let cs = 1000.0;
let q = cs * (G * self.stellar_mass / (a * a * a)).sqrt() / (PI * G * sigma);
if q < 1.0 {
PI * sigma * a * a / 4.0
} else {
0.0
}
}
pub fn formation_timescale(&self, r_au: f64) -> f64 {
match self.channel {
FormationChannel::CoreAccretion => 1e5 * YEAR * r_au.powf(3.0),
FormationChannel::DiskInstability => 1e3 * YEAR,
FormationChannel::PebbleAccretion => 1e4 * YEAR * r_au.powf(1.5),
}
}
}
pub fn minimum_mass_solar_nebula_density(r_au: f64) -> f64 {
1700.0 * r_au.powf(-1.5)
}
pub fn oligarchic_growth_time(planet_mass: f64, sigma: f64, r_au: f64) -> f64 {
let a = r_au * AU;
let rho_s = 3000.0;
let r_p = (3.0 * planet_mass / (4.0 * PI * rho_s)).cbrt();
let v_esc = (2.0 * G * planet_mass / r_p).sqrt();
let omega = (G * SOLAR_MASS / (a * a * a)).sqrt();
planet_mass / (PI * r_p * r_p * sigma * omega * (v_esc / (a * omega)).powi(2))
}