private IEnumerable <Seed> ProcessSeeds(InnerSeed nextSeed) { var seedList = new List <Seed>(); var next = nextSeed; while (next != null) { seedList.Add(next); if (next.FirstSatellite != null) { next.Satellites = ProcessSeeds(next.FirstSatellite); } next = next.NextBody; } return(seedList); }
private void SetInitialConditions(Length inner_limit_of_dust, Length outer_limit_of_dust) { _histHead = new Generation(); _planetHead = null; _dustHead = new DustRecord(); _dustHead.NextBand = null; _dustHead.OuterEdge = outer_limit_of_dust.AstronomicalUnits; _dustHead.InnerEdge = inner_limit_of_dust.AstronomicalUnits; _dustHead.DustPresent = true; _dustHead.GasPresent = true; _dustLeft = true; _cloudEccentricity = CloudEccentricity; _histHead.Dusts = _dustHead; _histHead.Bodies = _planetHead; _histHead.Next = _histHead; }
private void CoalescePlanetesimals(Length a, Ratio e, Mass mass, Mass critMass, Mass dustMass, Mass gasMass, Luminosity stellLuminosityRatio, Length bodyInnerBound, Length bodyOuterBound, bool doMoons) { // First we try to find an existing planet with an over-lapping orbit. InnerSeed thePlanet = null; InnerSeed nextPlanet = null; InnerSeed prevPlanet = null; var finished = false; for (thePlanet = _planetHead; thePlanet != null; thePlanet = thePlanet.NextBody) { Length diff = thePlanet.SemiMajorAxis - a; Length dist1; Length dist2; if (diff.AstronomicalUnits > 0.0) { dist1 = a * (1.0 + e.Value) * (1.0 + _reducedMass) - a; /* x aphelion */ _reducedMass = Math.Pow(thePlanet.Mass.SolarMasses / (1.0 + thePlanet.Mass.SolarMasses), 1.0 / 4.0); dist2 = thePlanet.SemiMajorAxis - thePlanet.SemiMajorAxis * (1.0 - thePlanet.Eccentricity.Value) * (1.0 - _reducedMass); } else { dist1 = a - a * (1.0 - e.Value) * (1.0 - _reducedMass); /* x perihelion */ _reducedMass = Math.Pow(thePlanet.Mass.SolarMasses / (1.0 + thePlanet.Mass.SolarMasses), 1.0 / 4.0); dist2 = thePlanet.SemiMajorAxis * (1.0 + thePlanet.Eccentricity.Value) * (1.0 + _reducedMass) - thePlanet.SemiMajorAxis; } // Did the planetesimal collide with this planet? if (Math.Abs(diff.Value) <= Math.Abs(dist1.Value) || Math.Abs(diff.Value) <= Math.Abs(dist2.Value)) { Mass new_dust = Mass.FromSolarMasses(0.0); Mass new_gas = Mass.FromSolarMasses(0.0); Length new_a = Length.FromAstronomicalUnits((thePlanet.Mass.SolarMasses + mass.SolarMasses) / (thePlanet.Mass.SolarMasses / thePlanet.SemiMajorAxis.AstronomicalUnits + mass.SolarMasses / a.AstronomicalUnits)); e = GetNewEccentricity(thePlanet, e, a, mass, new_a); if (doMoons) { finished = DoMoons(thePlanet, mass, critMass, dustMass, gasMass); } if (!finished) { //Trace.TraceInformation("Collision between two planetesimals!\n {0:0.00} AU ({1:0.00}EM) + {2:0.00} AU ({3:0.00}EM = {4:0.00}EMd + {5:0.00}EMg [{6:0.00}EM]). {7:0.00} AU ({8:0.00})", // the_planet.a, the_planet.mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // a, mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // dust_mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // gas_mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // crit_mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // new_a, e); var newMass = thePlanet.Mass + mass; // TODO: Why is a solar luminosity ratio passed as a Mass for critical mass? AccreteDust(ref newMass, ref new_dust, ref new_gas, new_a, e, Mass.FromSolarMasses(stellLuminosityRatio.SolarLuminosities), bodyInnerBound, bodyOuterBound); thePlanet.SemiMajorAxis = new_a; thePlanet.Eccentricity = e; thePlanet.Mass = newMass; thePlanet.DustMass += dustMass + new_dust; thePlanet.GasMass += gasMass + new_gas; if (thePlanet.Mass >= critMass) { thePlanet.IsGasGiant = true; } while (thePlanet.NextBody != null && thePlanet.NextBody.SemiMajorAxis < new_a) { nextPlanet = thePlanet.NextBody; if (thePlanet == _planetHead) { _planetHead = nextPlanet; } else { prevPlanet.NextBody = nextPlanet; } thePlanet.NextBody = nextPlanet.NextBody; nextPlanet.NextBody = thePlanet; prevPlanet = nextPlanet; } } finished = true; break; } else { prevPlanet = thePlanet; } } // Planetesimals didn't collide. Make it a planet. if (!finished) { thePlanet = new InnerSeed(a, e, mass, dustMass, gasMass); if (mass >= critMass) { thePlanet.IsGasGiant = true; } else { thePlanet.IsGasGiant = false; } if (_planetHead == null) { _planetHead = thePlanet; thePlanet.NextBody = null; } else if (a < _planetHead.SemiMajorAxis) { thePlanet.NextBody = _planetHead; _planetHead = thePlanet; } else if (_planetHead.NextBody == null) { _planetHead.NextBody = thePlanet; thePlanet.NextBody = null; } else { nextPlanet = _planetHead; while (nextPlanet != null && nextPlanet.SemiMajorAxis < a) { prevPlanet = nextPlanet; nextPlanet = nextPlanet.NextBody; } thePlanet.NextBody = nextPlanet; prevPlanet.NextBody = thePlanet; } } }
private bool DoMoons(InnerSeed planet, Mass mass, Mass critMass, Mass dustMass, Mass gasMass) { bool finished = false; Mass existingMass = Mass.FromSolarMasses(0.0); if (planet.FirstSatellite != null) { for (InnerSeed m = planet.FirstSatellite; m != null; m = m.NextBody) { existingMass += m.Mass; } } if (mass < critMass) { if (mass.EarthMasses < 2.5 && mass.EarthMasses > .0001 && existingMass < planet.Mass * .05) { InnerSeed moon = new InnerSeed(Length.FromMeters(0.0), Ratio.FromDecimalFractions(0.0), mass, dustMass, gasMass); if (moon.DustMass + moon.GasMass > planet.DustMass + planet.GasMass) { Mass tempDust = planet.DustMass; Mass tempGas = planet.GasMass; Mass tempMass = planet.Mass; planet.DustMass = moon.DustMass; planet.GasMass = moon.GasMass; planet.Mass = moon.Mass; moon.DustMass = tempDust; moon.GasMass = tempGas; moon.Mass = tempMass; } if (planet.FirstSatellite == null) { planet.FirstSatellite = moon; } else { moon.NextBody = planet.FirstSatellite; planet.FirstSatellite = moon; } finished = true; //Trace.TraceInformation("Moon captured... {0:0.00} AU ({1:0.00}EM) <- {2:0.00} EM", // the_planet.a, // the_planet.mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES); } //else //{ // Trace.TraceInformation("Moon escapes... {0:0.00} AU ({1:0.00} EM){2} {3:0.00}L {4}", // the_planet.a, // the_planet.mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // existing_mass < (the_planet.mass * .05) ? "" : " (big moons)", // mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES, // (mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES) >= 2.5 ? ", too big" : (mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES) <= .0001 ? ", too small" : ""); //} } return(finished); }