private void DistMoonMasses(ProtoStar star, ProtoPlanet planet) { planet.initDisc(0.0D, star.StellarDustLimit, true); int counter = 0; do { counter++; ProtoPlanet moon = new ProtoPlanet(star.Star, planet.Planet) { SemiMajorAxis = rnd.NextDouble(planet.PlanetInnerBound, planet.PlanetOuterBound), Eccentricity = rnd.RandomEccentricity(), DustMass = Constants.Stargen.PROTOPLANET_MASS, Star = star.Star, IsMoon = true, MoonOf = planet, }; moon.init(); if (planet.IsDustAvailable(moon)) { //var criticalMass = protoPlanet.CriticalLimit; AccreteDust(planet, moon); if (moon.Mass > Constants.Stargen.PROTOPLANET_MASS) { CoalescePlanetesimals(planet, moon); } else { #if LOG4NET_ENABLED logger.Debug("Moon at " + moon.SemiMajorAxis + " failed due to large neighbor!"); #endif } } if (counter == 10000) { #if LOG4NET_ENABLED logger.Debug("Exceeded 10000 attempts to create a planet! Will not continue!"); #endif } }while (planet.DustAvailable && counter < 10000); planet.Planets = new List <ProtoPlanet>(planet.Planets.OrderBy(x => x.SemiMajorAxis)); planet.Planets.ForEach(moon => { moon.Planet.Primary = planet.Star; planet.Planet.Moons.Add(moon.Planet); }); }
public void CollectDust(AccreteDisc Disc, ProtoPlanet p, double inner, double outer, double lastMass) { //ProtoStar star = p.Star; // declear working vars: double bandwidth = 0.0; double temp = 0.0; double temp1 = 0.0; double temp2 = 0.0; double width = 0.0; double volume = 0.0; double dustdensity, gasdensity, massdensity; foreach (AccreteBand band in Disc.Bands) { if (band.Intersect(inner, outer) && band.DustPresent) { bandwidth = outer - inner; temp1 = Math.Max(outer - band.OuterEdge, 0.0); temp2 = Math.Max(band.InnerEdge - inner, 0.0); width = bandwidth - temp1 - temp2; if (!band.DustPresent) { dustdensity = 0.0; gasdensity = 0.0; } else { if ((lastMass > p.CriticalLimit) && band.GasPresent) { massdensity = p.CloudDensity; gasdensity = massdensity - (Constants.Stargen.K * massdensity) / (1.0 + (Math.Sqrt(p.CriticalLimit / p.Mass) * (Constants.Stargen.K - 1.0))); dustdensity = massdensity - gasdensity; } else { dustdensity = p.CloudDensity; gasdensity = 0.0; } } temp = 4.0 * Math.PI * Math.Pow(p.SemiMajorAxis, 2.0) * p.ReducedMass * (1.0 - (p.Eccentricity * (temp1 - temp2) / bandwidth)); volume = temp * width; p.DustMass += volume * dustdensity; p.GasMass += volume * gasdensity; } } }
private void AccreteDust(AccreteDisc Disc, ProtoPlanet p) { //ProtoStar star = p.Star; double startDustMass = p.DustMass; double startGasMass = p.GasMass; //double minAccretion = 0.0001 * startMass; double gatherLast = 0.0; double rInner = 0; double rOuter = 0; do { //gatherLast = gatherNow; gatherLast = p.Mass; p.ReduceMass(); rInner = p.InnerEffectLimit; rOuter = p.OuterEffectLimit; p.DustMass = startDustMass; p.GasMass = startGasMass; //foreach (AccreteBand band in Disc.Bands) { //if(band.Intersect(rInner, rOuter)) { CollectDust(Disc, p, rInner, rOuter, gatherLast); } //band.CollectDust(rInner, rOuter, p, gatherLast); } }while ((p.Mass - gatherLast) >= (0.0001 * p.Mass)); Disc.UpdateDust(p); // Clear dust only on reduced mass? }
public bool Intersect(ProtoPlanet p) { return(Intersect(p.InnerEffectLimit, p.OuterEffectLimit)); }
public bool IsDustAvailable(ProtoPlanet p) { p.ReduceMass(); return(IsDustLeftRange(p.InnerEffectLimit, p.OuterEffectLimit)); }
public void UpdateDust(ProtoPlanet p) { UpdateDust(p.InnerEffectLimit, p.OuterEffectLimit, p.Mass > p.CriticalLimit); }
public bool IsGasAvailable(ProtoPlanet p) { return(IsGasLeftRange(p.InnerEffectLimit, p.OuterEffectLimit)); }
public StarSystem Create(string name) { //create the starsystem var starSystem = new StarSystem(name); _starFactory.Create(name).ForEach(star => { star.StarSystem = starSystem; starSystem.Stars.Add(star); }); // Create some working Vars: double inner = 0.0; double outer = 0.0; for (var i = 0; i < starSystem.Stars.Count; i++) { var star = starSystem.Stars[i]; var protoStar = new ProtoStar(star); for (int j = 0; j < starSystem.Stars.Count; j++) { if (i != j) { var starB = starSystem.Stars[j]; // Forbidden zone inner is 1/3 of the minimum seperation // Forbidden zone outer is 3x the maximum seperation // TODO: Add in effect of eccentricities double minseperation, maxseperation; if (star.SemiMajorAxis > starB.SemiMajorAxis) { // Orbits beyond other star minseperation = Math.Abs(star.SemiMajorAxis * (1.0 - star.Eccentricity) - starB.SemiMajorAxis * (1.0 + starB.Eccentricity)); if (i == 0) { maxseperation = Math.Abs(star.SemiMajorAxis * (1.0 + star.Eccentricity) - starB.SemiMajorAxis * (1.0 - starB.Eccentricity)); } else { maxseperation = 200; } } else { // Orbits inside other star minseperation = Math.Abs(star.SemiMajorAxis * (1.0 + star.Eccentricity) - starB.SemiMajorAxis * (1.0 - starB.Eccentricity)); if (i == 0) { maxseperation = Math.Abs(star.SemiMajorAxis * (1.0 - star.Eccentricity) - starB.SemiMajorAxis * (1.0 + starB.Eccentricity)); } else { maxseperation = 200; } } /*minseperation = Math.Abs(starSystem.Stars[j].SemiMajorAxis - starSystem.Stars[i].SemiMajorAxis); * double maxseperation; * if (i == 0) * maxseperation = Math.Abs(starSystem.Stars[j].SemiMajorAxis + starSystem.Stars[i].SemiMajorAxis); * else * maxseperation = 200;*/ inner = minseperation / 3.0; outer = maxseperation * 3.0; protoStar.UpdateDust(inner, outer, false); } initOrbitPosition(star); } //protoStar.DistributePlanetaryMasses(rnd); int counter = 0; while (protoStar.DustAvailable) { counter++; var protoPlanet = new ProtoPlanet(protoStar.Star, protoStar.Star) { Star = star, SemiMajorAxis = rnd.NextDouble(protoStar.PlanetInnerBound, protoStar.PlanetOuterBound), Eccentricity = rnd.RandomEccentricity(), //Eccentricity = 0.99, DustMass = Constants.Stargen.PROTOPLANET_MASS, }; protoPlanet.init(); if (protoStar.IsDustAvailable(protoPlanet)) { //var criticalMass = protoPlanet.CriticalLimit; AccreteDust(protoStar, protoPlanet); if (protoPlanet.Mass > Constants.Stargen.PROTOPLANET_MASS) { CoalescePlanetesimals(protoStar, protoPlanet); } else { #if LOG4NET_ENABLED logger.Debug("Planet at " + protoPlanet.SemiMajorAxis + " failed due to large neighbor!"); #endif } } if (counter == 10000) { #if LOG4NET_ENABLED logger.Debug("Exceeded 10000 attempts to create a planet! Will not continue!"); #endif } } while (protoStar.DustAvailable && counter < 10000) { ; } //populate the Star from the protoStar protoStar.Planets.ForEach(planet => { planet.Planet.Primary = star; if (_generateMoons) { DistMoonMasses(protoStar, planet); } star.Planets.Add(planet.Planet); }); star.Planets = new BindingList <Planet>(star.Planets.OrderBy(x => x.SemiMajorAxis).ToList()); GeneratePlanets(star); } return(starSystem); }
private bool GeneratePlanet(ProtoPlanet protoplanet) { return(GeneratePlanet(protoplanet.Planet)); }
private void doCollisions(AccreteDisc Disc) { // create working vars: double miu1, miu2; double delta = 1, deltaMin = 0; double newE, newA; double temp; bool collision; do { collision = false; Disc.Planets = new List <ProtoPlanet>(Disc.Planets.OrderBy(x => x.SemiMajorAxis)); for (int i = 0; i < Disc.Planets.Count - 1; i++) { ProtoPlanet aPlanet = Disc.Planets[i]; ProtoPlanet bPlanet = Disc.Planets[i + 1]; miu1 = aPlanet.Mass / Disc.Mass; miu2 = bPlanet.Mass / Disc.Mass; deltaMin = 2.4 * (Math.Pow(miu1 + miu2, 1.0 / 3.0)); delta = Math.Abs((bPlanet.SemiMajorAxis - aPlanet.SemiMajorAxis) / aPlanet.SemiMajorAxis); if (delta <= deltaMin && !Disc.isMoonDisc) { // New orbital distance newA = (aPlanet.Mass + bPlanet.Mass) / ((aPlanet.Mass / aPlanet.SemiMajorAxis) + (bPlanet.Mass / bPlanet.SemiMajorAxis)); //#if LOG4NET_ENABLED //logger.Debug(String.Format("Collision between two planetesimals! {0:N4} AU ({1:N5}) + {2:N4} AU ({3:N5}) -> {4:N4} AU", bPlanet.SemiMajorAxis, bPlanet.MassInEarthMasses, aPlanet.SemiMajorAxis, aPlanet.MassInEarthMasses, newA)); //#endif // Compute new eccentricity temp = aPlanet.Mass * Math.Sqrt(aPlanet.SemiMajorAxis) * Math.Sqrt(1.0 - Math.Pow(aPlanet.Eccentricity, 2.0)); temp = temp + (bPlanet.Mass * Math.Sqrt(bPlanet.SemiMajorAxis) * Math.Sqrt(Math.Sqrt(1.0 - Math.Pow(bPlanet.Eccentricity, 2.0)))); temp = temp / ((aPlanet.Mass + bPlanet.Mass) * Math.Sqrt(newA)); temp = 1.0 - Math.Pow(temp, 2.0); temp = Math.Min(Math.Max(temp, 0.0), 1.0); newE = Math.Sqrt(temp); // Create a new Protoplanet to accrete additional material var newP = new ProtoPlanet(Disc.Star, Disc.Star) { SemiMajorAxis = newA, Eccentricity = newE, DustMass = aPlanet.DustMass + bPlanet.DustMass, GasMass = aPlanet.GasMass + bPlanet.GasMass, Star = Disc.Star, IsMoon = aPlanet.IsMoon, MoonOf = aPlanet.MoonOf }; newP.init(); //newP.CritMass = getCriticalMass(newP); //newP.CloudDensity = getCloudDensity(newP); //double startmass = newP.Mass; AccreteDust(Disc, newP); /* #if LOG4NET_ENABLED * if (newP.Mass < startmass) * logger.Debug("Accretion reduced mass, something is wrong!"); * else if (newP.Mass > startmass) * logger.Debug("Accretion increased mass!"); * else * logger.Debug("Accretion did not change mass!"); #endif */ //#if LOG4NET_ENABLED //logger.Debug(string.Format("New planet at {0:N4} AU with mass {1:N5}!", newP.SemiMajorAxis, newP.MassInEarthMasses)); //#endif Disc.Planets.Remove(aPlanet); Disc.Planets.Remove(bPlanet); Disc.Planets.Add(newP); collision = true; break; } } }while (collision == true); }
private void CoalescePlanetesimals(AccreteDisc Disc, ProtoPlanet p) { Disc.Planets.Add(p); doCollisions(Disc); }