private void initOrbitPosition(OrbitingEntity entity) { if (entity.Parent != null) { entity.OrbitalPeriod = EnviroUtilities.Period(entity.SemiMajorAxis, entity.Mass); entity.LongitudeOfApogee = rnd.NextDouble(0.0, 2 * Math.PI); entity.TimeSinceApogee = Convert.ToInt64(rnd.NextDouble(0.0, entity.OrbitalPeriod * Constants.Units.SECONDS_PER_HOUR * 24.0)); } }
private void CalculateGases(Planet planet) { if (planet.SurfacePressure > 0) { //var amounts = new List<double>(); double totamount = 0; var pressure = planet.SurfacePressure / Constants.Units.MILLIBARS_PER_BAR; //bool gasesExist = false; // create some working vars: double yp = 0.0; double amount = 0.0; foreach (Molecule gas in Constants.Gases.GasLookup.Values) //for (int i = 0; i < ElementalTable.Instance.Count; i++) { yp = gas.BoilingPoint / (373.0 * ((Math.Log((pressure) + 0.001) / -5050.5) + (1.0 / 373.0))); if ((yp >= 0 && yp < planet.LowTemperature) && (gas.AtomicWeight >= planet.MolecularWeightRetained)) { var vrms = EnviroUtilities.RootMeanSquareVelocity(gas.AtomicWeight, planet.ExoSphericTemperature); var pvrms = Math.Pow(1 / (1 + vrms / planet.EscapeVelocity), planet.Primary.Age / 1e9); var abund = gas.AbundanceS; /* gases[i].abunde */ var react = 1.0D; var fract = 1.0D; var pres2 = 1.0D; if (gas.Symbol == "Ar") { react = .15 * planet.Primary.Age / 4e9; } else if (gas.Symbol == "He") { abund = abund * (0.001 + (planet.MassOfGas / planet.Mass)); pres2 = (0.75 + pressure); react = Math.Pow(1 / (1 + gas.Reactivity), planet.Primary.Age / 2e9 * pres2); } else if (((gas.Symbol == "O") || (gas.Symbol == "O2")) && (planet.Primary.Age > 2e9) && (planet.SurfaceTemperature > 270 && planet.SurfaceTemperature < 400)) { /* pres2 = (0.65 + pressure/2); Breathable - M: .55-1.4 */ pres2 = (0.89 + pressure / 4); /* Breathable - M: .6 -1.8 */ react = Math.Pow(1 / (1 + gas.Reactivity), Math.Pow(planet.Primary.Age / 2e9, 0.25) * pres2); } else if ((gas.Symbol == "CO2") && (planet.Primary.Age > 2e9) && (planet.SurfaceTemperature > 270 && planet.SurfaceTemperature < 400)) { pres2 = (0.75 + pressure); react = Math.Pow(1 / (1 + gas.Reactivity), Math.Pow(planet.Primary.Age / 2e9, 0.5) * pres2); react *= 1.5; } else { pres2 = (0.75 + pressure); react = Math.Pow(1 / (1 + gas.Reactivity), planet.Primary.Age / 2e9 * pres2); } fract = (1 - (planet.MolecularWeightRetained / gas.AtomicWeight)); amount = abund * pvrms * react * fract; totamount += amount; if (amount > 0.0) { if (planet.Gases == null) { planet.Gases = new BindingList <Gas>(); } planet.Gases.Add(new Gas() { MoleculeId = gas.Id, SurfacePressure = planet.SurfacePressure * amount }); } } } if (planet.Gases != null) { foreach (Gas gas in planet.Gases) { gas.SurfacePressure /= totamount; } } } }
private bool GeneratePlanet(Planet planet) { planet.SurfaceTemperature = 0; planet.HighTemperature = 0; planet.LowTemperature = 0; planet.MaxTemperature = 0; planet.MinTemperature = 0; planet.RiseInTemperatureDueToGreenhouse = 0; planet.IsInResonantRotation = false; planet.OrbitZone = EnviroUtilities.OrbitalZone(planet.Primary.Luminosity, planet.SolarSemiMajorAxis); planet.AxialTilt = Inclination(planet.SolarSemiMajorAxis); initOrbitPosition(planet); planet.ExoSphericTemperature = Constants.Sol.Earth.EXOSPHERE_TEMP / Math.Pow(planet.SolarSemiMajorAxis / planet.Primary.EcoSphereRadius, 2.0); planet.RootMeanSquaredVelocity = EnviroUtilities.RootMeanSquareVelocity(Constants.Gases.MolecularWeights.MOL_NITROGEN, planet.ExoSphericTemperature); planet.RadiusOfCore = EnviroUtilities.KothariRadius(planet.MassOfDust, false, planet.OrbitZone); // Calculate the radius as a gas giant, to verify it will retain gas. // Then if mass > Earth, it's at least 5% gas and retains He, it's // some flavor of gas giant. planet.Density = EnviroUtilities.EmpiricalDensity(planet.Mass, planet.SolarSemiMajorAxis, planet.Primary.EcoSphereRadius, true); planet.Radius = EnviroUtilities.VolumeRadius(planet.Mass, planet.Density); planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); planet.MolecularWeightRetained = EnviroUtilities.MinMolecWeight(planet); if (((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) > 1.0) && ((planet.MassOfGas / planet.Mass) > 0.05) && (EnviroUtilities.MinMolecWeight(planet) <= 4.0)) { if ((planet.MassOfGas / planet.Mass) < 0.20) { planet.PlanetType = PlanetTypes.GasDwarf; } else if ((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) < 20.0) { planet.PlanetType = PlanetTypes.IceGiant; } else { planet.PlanetType = PlanetTypes.GasGiant; } } else // If not, it's rocky. { planet.Radius = EnviroUtilities.KothariRadius(planet.Mass, true, planet.OrbitZone); planet.Density = EnviroUtilities.VolumeDensity(planet.Mass, planet.Radius); if ((planet.MassOfGas / planet.Mass) > 0.000001) { double h2Mass = planet.MassOfGas * 0.85; double heMass = (planet.MassOfGas - h2Mass) * 0.999; double h2Life = EnviroUtilities.GasLife(Constants.Gases.MolecularWeights.MOL_HYDROGEN, planet); double heLife = EnviroUtilities.GasLife(Constants.Gases.MolecularWeights.HELIUM, planet); if (h2Life < planet.Primary.Age) { var h2Loss = ((1.0 - (1.0 / Math.Exp(planet.Primary.Age / h2Life))) * h2Mass); planet.MassOfGas -= h2Loss; //planet.Mass -= h2Loss; //Mass of planet changed so recalculate planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); } if (heLife < planet.Primary.Age) { var heLoss = ((1.0 - (1.0 / Math.Exp(planet.Primary.Age / heLife))) * heMass); planet.MassOfGas -= heLoss; //planet.Mass -= heLoss; //Mass of planet changed so recalculate planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); } } } planet.LengthOfDay = EnviroUtilities.DayLength(planet); /* Modifies planet->resonant_period */ planet.EscapeVelocity = EnviroUtilities.EscapeVel(planet.Mass, planet.Radius); planet.MolecularWeightRetained = EnviroUtilities.MinMolecWeight(planet); if ((planet.PlanetType == PlanetTypes.GasGiant) || (planet.PlanetType == PlanetTypes.IceGiant) || (planet.PlanetType == PlanetTypes.GasDwarf)) { planet.HasGreenhouseEffect = false; planet.VolatileGasInventory = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.SurfacePressure = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.BoilingPoint = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.SurfaceTemperature = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.RiseInTemperatureDueToGreenhouse = 0; planet.Albedo = rnd.About(Constants.Units.GAS_GIANT_ALBEDO, 0.1); planet.HydrosphereCover = 1.0; planet.CloudCover = 1.0; planet.IceCover = 0.0; planet.SurfaceGravity = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.EstimatedTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, planet.Albedo); planet.EstimatedTerrestrialTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, Constants.Sol.Earth.ALBEDO); } else { planet.EstimatedTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, Constants.Sol.Earth.ALBEDO); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); planet.HasGreenhouseEffect = EnviroUtilities.Greenhouse(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis); planet.VolatileGasInventory = EnviroUtilities.VolInventory(planet.Mass, planet.EscapeVelocity, planet.RootMeanSquaredVelocity, planet.Primary.Mass, planet.OrbitZone, planet.HasGreenhouseEffect, (planet.MassOfGas / planet.Mass) > 0.000001); planet.SurfacePressure = EnviroUtilities.Pressure(planet.VolatileGasInventory, planet.Radius, planet.SurfaceGravity); if (planet.SurfacePressure == 0.0D) { planet.BoilingPoint = 0.0; } else { planet.BoilingPoint = EnviroUtilities.BoilingPoint(planet.SurfacePressure); } EnviroUtilities.IterateSurfaceTemp(planet); if ((planet.MaxTemperature >= Constants.Sol.Earth.FREEZING_POINT_OF_WATER) && (planet.MinTemperature <= planet.BoilingPoint)) { CalculateGases(planet); } /* * Next we assign a type to the planet. */ if (planet.SurfacePressure < 1.0) { if (!planet.IsMoon && ((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) < Constants.Stargen.ASTEROID_MASS_LIMIT)) { planet.PlanetType = PlanetTypes.Asteroid; } else { planet.PlanetType = PlanetTypes.Rock; } } else if ((planet.SurfacePressure > 6000.0) && (planet.MolecularWeightRetained <= 2.0)) // Retains Hydrogen { planet.PlanetType = PlanetTypes.GasDwarf; planet.Gases.Clear(); //TODO: Do we really want to clear the atmosphere just because it is a gas dwarf? } else { // Atmospheres: //if (((int)planet.Day == (int)(planet.OrbitalPeriod * 24.0) || (planet.IsInResonantRotation))) // planet.PlanetType = PlanetTypes.Face; //else if (planet.HydrosphereCover >= 0.95) { planet.PlanetType = PlanetTypes.Water; // >95% water } else if (planet.IceCover >= 0.95) { planet.PlanetType = PlanetTypes.Ice; // >95% ice } else if (planet.HydrosphereCover > 0.05) { planet.PlanetType = PlanetTypes.Terrestrial; // Terrestrial // else <5% water } else if (planet.MaxTemperature > planet.BoilingPoint) { planet.PlanetType = PlanetTypes.Venusian; // Hot = Venusian } else if ((planet.MassOfGas / planet.Mass) > 0.0001) { // Accreted gas, But no Greenhouse, or liquid water, Make it an Ice World planet.PlanetType = PlanetTypes.Ice; planet.IceCover = 1.0; } else if (planet.SurfacePressure <= 250.0) { // Thin air = Martian planet.PlanetType = PlanetTypes.Martian; } else if (planet.SurfaceTemperature < Constants.Sol.Earth.FREEZING_POINT_OF_WATER) { planet.PlanetType = PlanetTypes.Ice; } else { planet.PlanetType = PlanetTypes.Unknown; } } } if (_generateMoons && !planet.IsMoon) { if (planet.Moons != null) { // Sort moons planet.Moons = new BindingList <Planet>(planet.Moons.OrderBy(x => x.SemiMajorAxis).ToList()); // Create a copy of the moons list var moonList = planet.Moons.ToList(); var count = 0; var hillSphere = planet.SemiMajorAxis * (1.0 - planet.Eccentricity) * Constants.Units.KM_PER_AU * Math.Pow((planet.Mass / (3.0 * planet.Primary.Mass)), (1.0 / 3.0)) / Constants.Units.KM_PER_AU; for (int n = 0; n < moonList.Count; n++) { bool pass = true; var moon = moonList[n]; if (moon.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES > .000001) { //moon.SemiMajorAxis = planet.SemiMajorAxis; //moon.Eccentricity = planet.Eccentricity; moon.Id = Guid.NewGuid(); moon.Name = string.Format("{0}.{1}", planet.Name, count + 1); moon.Primary = planet.Primary; GeneratePlanet(moon); //TODO: Look at adding atmosphere call to this var rocheLimit = 2.44 * planet.Radius * Math.Pow((planet.Density / moon.Density), (1.0 / 3.0)) / Constants.Units.KM_PER_AU; //if ((rocheLimit * 3.0) < hillSphere) if (moon.SemiMajorAxis < rocheLimit) { // Moon too close. // TODO: Turn moon into rings planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} inside Roche limit", planet.Name)); //#endif } if (moon.SemiMajorAxis > hillSphere) { // Moon too far planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} outside hill radius", planet.Name)); //#endif } } else { // Moon too small planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} too small", planet.Name)); //#endif } if (pass) { count++; } } } } return(true); }