use sciforge::hub::domain::common::constants::{AU, SIGMA_SB};
use crate::{PLANCK_H, SOLAR_EFFECTIVE_TEMP, SOLAR_LUMINOSITY, SOLAR_RADIUS, SPEED_OF_LIGHT};
pub const SOLAR_CONSTANT_WM2: f64 = 1361.0;
pub const UV_FRACTION: f64 = 0.077;
pub const EUV_FRACTION: f64 = 1e-6;
pub const VISIBLE_FRACTION: f64 = 0.39;
pub const IR_FRACTION: f64 = 0.53;
pub const HABITABLE_ZONE_INNER_AU: f64 = 0.95;
pub const HABITABLE_ZONE_OUTER_AU: f64 = 1.67;
pub const HABITABLE_ZONE_CONSERVATIVE_INNER_AU: f64 = 0.99;
pub const HABITABLE_ZONE_CONSERVATIVE_OUTER_AU: f64 = 1.70;
pub const FROST_LINE_AU: f64 = 2.7;
pub struct SolarRadiationField {
pub distance_m: f64,
}
impl SolarRadiationField {
pub fn at_distance_au(distance_au: f64) -> Self {
Self {
distance_m: distance_au * AU,
}
}
pub fn at_distance_m(distance_m: f64) -> Self {
Self { distance_m }
}
pub fn total_flux(&self) -> f64 {
SOLAR_LUMINOSITY / (4.0 * std::f64::consts::PI * self.distance_m * self.distance_m)
}
pub fn uv_flux(&self) -> f64 {
self.total_flux() * UV_FRACTION
}
pub fn euv_flux(&self) -> f64 {
self.total_flux() * EUV_FRACTION
}
pub fn visible_flux(&self) -> f64 {
self.total_flux() * VISIBLE_FRACTION
}
pub fn ir_flux(&self) -> f64 {
self.total_flux() * IR_FRACTION
}
pub fn photon_flux(&self) -> f64 {
let lambda_peak = 2.8977719e-3 / SOLAR_EFFECTIVE_TEMP;
let e_photon = PLANCK_H * SPEED_OF_LIGHT / lambda_peak;
self.total_flux() / e_photon
}
pub fn radiation_pressure(&self) -> f64 {
self.total_flux() / SPEED_OF_LIGHT
}
pub fn equilibrium_temperature(&self) -> f64 {
(self.total_flux() / (4.0 * SIGMA_SB)).powf(0.25)
}
pub fn equilibrium_temperature_with_albedo(&self, albedo: f64) -> f64 {
((1.0 - albedo) * self.total_flux() / (4.0 * SIGMA_SB)).powf(0.25)
}
pub fn flux_ratio_to_earth(&self) -> f64 {
self.total_flux() / SOLAR_CONSTANT_WM2
}
pub fn distance_au(&self) -> f64 {
self.distance_m / AU
}
pub fn angular_diameter_rad(&self) -> f64 {
2.0 * SOLAR_RADIUS / self.distance_m
}
pub fn solid_angle_sr(&self) -> f64 {
std::f64::consts::PI * (SOLAR_RADIUS / self.distance_m).powi(2)
}
}
pub fn solar_flux_at_distance(distance_m: f64) -> f64 {
SOLAR_LUMINOSITY / (4.0 * std::f64::consts::PI * distance_m * distance_m)
}
pub fn solar_flux_at_au(distance_au: f64) -> f64 {
solar_flux_at_distance(distance_au * AU)
}
pub fn is_in_habitable_zone(distance_au: f64) -> bool {
(HABITABLE_ZONE_INNER_AU..=HABITABLE_ZONE_OUTER_AU).contains(&distance_au)
}
pub fn is_in_conservative_habitable_zone(distance_au: f64) -> bool {
(HABITABLE_ZONE_CONSERVATIVE_INNER_AU..=HABITABLE_ZONE_CONSERVATIVE_OUTER_AU)
.contains(&distance_au)
}
pub fn planetary_equilibrium_temperature(distance_au: f64, albedo: f64) -> f64 {
let flux = solar_flux_at_au(distance_au);
((1.0 - albedo) * flux / (4.0 * SIGMA_SB)).powf(0.25)
}
pub fn planck_spectral_radiance(wavelength_m: f64, temperature_k: f64) -> f64 {
let c1 = 2.0 * PLANCK_H * SPEED_OF_LIGHT * SPEED_OF_LIGHT;
let c2 = PLANCK_H * SPEED_OF_LIGHT / (wavelength_m * crate::K_B * temperature_k);
c1 / (wavelength_m.powi(5) * (c2.exp() - 1.0))
}
pub fn spectral_irradiance_at_distance(wavelength_m: f64, distance_m: f64) -> f64 {
let b = planck_spectral_radiance(wavelength_m, SOLAR_EFFECTIVE_TEMP);
let omega = std::f64::consts::PI * (SOLAR_RADIUS / distance_m).powi(2);
b * omega
}
pub fn radiation_force_on_particle(cross_section_m2: f64, distance_m: f64) -> f64 {
let flux = solar_flux_at_distance(distance_m);
flux * cross_section_m2 / SPEED_OF_LIGHT
}
pub fn beta_radiation_gravity(particle_mass_kg: f64, cross_section_m2: f64) -> f64 {
let f_rad = SOLAR_LUMINOSITY * cross_section_m2 / (4.0 * std::f64::consts::PI * SPEED_OF_LIGHT);
let f_grav = sciforge::hub::domain::common::constants::G * SOLAR_MASS * particle_mass_kg;
f_rad / f_grav
}
use sciforge::hub::domain::common::constants::SOLAR_MASS;
pub fn effective_gravity_parameter(beta: f64) -> f64 {
sciforge::hub::domain::common::constants::G * SOLAR_MASS * (1.0 - beta)
}