Пример #1
0
 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));
     }
 }
Пример #2
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;
                    }
                }
            }
        }
Пример #3
0
        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);
        }