/// <summary> /// Fogg's information for this routine came from Dole "Habitable Planets /// for Man", Blaisdell Publishing Company, NY, 1964. From this, he came /// up with his eq.12, which is the equation for the base_angular_velocity /// below. Going a bit further, he found an equation for the change in /// angular velocity per time (dw/dt) from P. Goldreich and S. Soter's paper /// "Q in the Solar System" in Icarus, vol 5, pp.375-389 (1966). Comparing /// to the change in angular velocity for the Earth, we can come up with an /// approximation for our new planet (his eq.13) and take that into account. /// </summary> public static Double DayLength(ref SolarSystem system, Double mass, Double radius, Double orbital_period, Double eccentricity, Boolean giant) { system.spin_resonance = false; Double k2 = giant ? 0.24 : 0.33; Double planetary_mass_in_grams = mass * Constants.SOLAR_MASS_IN_GRAMS; Double equatorial_radius_in_cm = radius * Constants.CM_PER_KM; Double base_angular_velocity = Math.Sqrt(2.0 * Constants.J * (planetary_mass_in_grams) / (k2 * Math.Pow(equatorial_radius_in_cm, 2.0))); /* This next term describes how much a planet's rotation is slowed by */ /* it's moons. Find out what dw/dt is after figuring out Goldreich and */ /* Soter's Q'. */ Double change_in_angular_velocity = 0.0; Double temp = base_angular_velocity + (change_in_angular_velocity * system.age); /* 'temp' is now the angular velocity. Now we change from rad/sec to */ /* hours/rotation. */ temp = 1.0 / ((temp / SolarSystem.radians_per_rotation) * Constants.SECONDS_PER_HOUR); if (!(temp >= orbital_period)) { return(temp); } Double spin_resonance_period = ((1.0 - eccentricity) / (1.0 + eccentricity)) * orbital_period; system.Callback("...maybe: " + spin_resonance_period + "\n"); if (eccentricity > 0.01) { system.Callback("...resonance...\n"); temp = spin_resonance_period; system.spin_resonance = true; } else { temp = orbital_period; } return(temp); }
public static Planet DistributePlanetaryMasses(ref SolarSystem system, Double stellar_mass_ratio, Double stellar_luminosity_ratio, Double inner_dust, Double outer_dust) { SetInitialConditions(system, inner_dust, outer_dust); Double planetesimal_inner_bound = InnermostPlanet(stellar_mass_ratio); Double planetesimal_outer_bound = OutermostPlanet(stellar_mass_ratio); while (system.dust_left) { Double a = system.random.Range(planetesimal_inner_bound, planetesimal_outer_bound); Double e = system.random.Eccentricity(); Double mass = Constants.PROTOPLANET_MASS; if (system.verbose) { system.Callback("Checking " + a + " AU.\n"); } if (!DustAvailable(system, InnerEffectLimit(system, a, e, mass), OuterEffectLimit(system, a, e, mass))) { if (system.verbose) { system.Callback(".. failed.\n"); } continue; } system.Callback(".. Injecting protoplanet.\n"); system.dust_density = Constants.DUST_DENSITY_COEFF * Math.Sqrt(stellar_mass_ratio) * Math.Exp(-Constants.ALPHA * Math.Pow(a, 1.0 / Constants.N)); Double crit_mass = CriticalLimit(a, e, stellar_luminosity_ratio); AccreteDust(ref system, ref mass, a, e, crit_mass, planetesimal_inner_bound, planetesimal_outer_bound); if ((mass != 0.0) && (mass != Constants.PROTOPLANET_MASS)) { CoalescePlanetesimals(ref system, a, e, mass, crit_mass, stellar_luminosity_ratio, planetesimal_inner_bound, planetesimal_outer_bound); } else { system.Callback(".. failed due to large neighbor.\n"); } } return(system.planet_head); }
/// <summary> /// This implements Fogg's eq.17. The 'inventory' returned is unitless. /// </summary> public static Double VolInventory(SolarSystem system, Double mass, Double escape_vel, Double rms_vel, Double stellar_mass, Int32 zone, Boolean greenhouse_effect) { Double proportion_const; Double velocity_ratio = escape_vel / rms_vel; if (!(velocity_ratio >= Constants.GAS_RETENTION_THRESHOLD)) { return(0.0); } switch (zone) { case 1: proportion_const = 100000.0; break; case 2: proportion_const = 75000.0; break; case 3: proportion_const = 250.0; break; default: proportion_const = 10.0; system.Callback("Error: orbital zone not initialized correctly!\n"); break; } Double mass_in_earth_units = mass * Constants.EARTH_MASSES_PER_SOLAR_MASS; Double temp1 = (proportion_const * mass_in_earth_units) / stellar_mass; Double temp2 = system.random.About(temp1, 0.2); if (greenhouse_effect) { return(temp2); } return(temp2 / 100.0); }
public static void CoalescePlanetesimals(ref SolarSystem system, Double a, Double e, Double mass, Double crit_mass, Double stellar_luminosity_ratio, Double body_inner_bound, Double body_outer_bound) { Boolean coalesced = false; Planet node1 = system.planet_head; Planet node2 = null; Planet node3 = null; while (node1 != null) { node2 = node1; Double temp = node1.a - a; Double dist1; Double dist2; if (temp > 0.0) { dist1 = a * (1.0 + e) * (1.0 + system.reduced_mass) - a; /* x aphelion */ system.reduced_mass = Math.Pow(node1.mass / (1.0 + node1.mass), 1.0 / 4.0); dist2 = node1.a - node1.a * (1.0 - node1.e) * (1.0 - system.reduced_mass); } else { dist1 = a - a * (1.0 - e) * (1.0 - system.reduced_mass); /* x perihelion */ system.reduced_mass = Math.Pow(node1.mass / (1.0 + node1.mass), 1.0 / 4.0); dist2 = node1.a * (1.0 + node1.e) * (1.0 + system.reduced_mass) - node1.a; } if ((Math.Abs(temp) <= Math.Abs(dist1)) || (Math.Abs(temp) <= Math.Abs(dist2))) { system.Callback("Collision between two planetesimals!\n"); Double a3 = (node1.mass + mass) / (node1.mass / node1.a + mass / a); temp = node1.mass * Math.Sqrt(node1.a) * Math.Sqrt(1.0 - Math.Pow(node1.e, 2.0)); temp = temp + mass * Math.Sqrt(a) * Math.Sqrt(Math.Sqrt(1.0 - Math.Pow(e, 2.0))); temp = temp / ((node1.mass + mass) * Math.Sqrt(a3)); temp = 1.0 - Math.Pow(temp, 2.0); if ((temp < 0.0) || (temp >= 1.0)) { temp = 0.0; } e = Math.Sqrt(temp); temp = node1.mass + mass; AccreteDust(ref system, ref temp, a3, e, stellar_luminosity_ratio, body_inner_bound, body_outer_bound); node1.a = a3; node1.e = e; node1.mass = temp; node1 = null; coalesced = true; } else { node1 = node1.next_planet; } } if (coalesced) { return; } node3 = new Planet { a = a, e = e, gas_giant = mass >= crit_mass, mass = mass }; system.bodies.Add(node3); if (system.planet_head == null) { system.planet_head = node3; node3.next_planet = null; } else { node1 = system.planet_head; if (a < node1.a) { node3.next_planet = node1; system.planet_head = node3; } else if (system.planet_head.next_planet == null) { system.planet_head.next_planet = node3; node3.next_planet = null; } else { while ((node1 != null) && (node1.a < a)) { node2 = node1; node1 = node1.next_planet; } node3.next_planet = node1; node2.next_planet = node3; } } }