예제 #1
0
        /// <summary> Accretes dust and/or gas from all bands onto the specified protoplanet,
        /// iterating until the marginal mass increase approaches zero.  Once the
        /// new mass has been calculated, the dust bands are updated to reflect the
        /// accretion of dust and/or gas onto the protoplanet.
        /// </summary>
        /// <param name="p">Protoplanet accreting in this cycle
        /// </param>
        public virtual void accrete_dust(Protoplanet p)
        {
            //double temp_mass;
            double start_mass = p.mass;
            double minimum_accretion = 0.0001 * start_mass;
            double r_inner, r_outer, gatherLast, gatherNow;
            DustBand db;

            gatherNow = 0.0;
            do
            {
                gatherLast = gatherNow;
                // calculate new mass of protoplanet, considering last calculated
                // quantity of accreted matter, then calculate region to be swept
                // based on the updated mass.
                p.mass = start_mass + gatherLast;
                p.reduce_mass();
                gas = !p.accretes_gas();
                r_inner = p.inner_reduced_limit(cloud_eccentricity);
                r_outer = p.outer_reduced_limit(cloud_eccentricity);
                if (r_inner < 0.0)
                    r_inner = 0.0;
                // sweep through all dust bands, collecting matter within the
                // effective reach of the protoplanet's gravity.
                gatherNow = 0.0;
                for (db = dust_head; db != null; db = db.next_band)
                {
                    gatherNow += db.collect_dust(r_inner, r_outer, p);
                }
            }
            while ((gatherNow - gatherLast) >= minimum_accretion);
            update_dust_lanes(p.inner_effect_limit(cloud_eccentricity), p.outer_effect_limit(cloud_eccentricity));
        }
예제 #2
0
        /// <summary> Accretes dust and/or gas from all bands onto the specified protoplanet,
        /// iterating until the marginal mass increase approaches zero.  Once the
        /// new mass has been calculated, the dust bands are updated to reflect the
        /// accretion of dust and/or gas onto the protoplanet.
        /// </summary>
        /// <param name="p">Protoplanet accreting in this cycle
        /// </param>
        public virtual void accrete_dust(Protoplanet p)
        {
            //double temp_mass;
            double   start_mass = p.mass;
            double   minimum_accretion = 0.0001 * start_mass;
            double   r_inner, r_outer, gatherLast, gatherNow;
            DustBand db;

            gatherNow = 0.0;
            do
            {
                gatherLast = gatherNow;
                // calculate new mass of protoplanet, considering last calculated
                // quantity of accreted matter, then calculate region to be swept
                // based on the updated mass.
                p.mass = start_mass + gatherLast;
                p.reduce_mass();
                gas     = !p.accretes_gas();
                r_inner = p.inner_reduced_limit(cloud_eccentricity);
                r_outer = p.outer_reduced_limit(cloud_eccentricity);
                if (r_inner < 0.0)
                {
                    r_inner = 0.0;
                }
                // sweep through all dust bands, collecting matter within the
                // effective reach of the protoplanet's gravity.
                gatherNow = 0.0;
                for (db = dust_head; db != null; db = db.next_band)
                {
                    gatherNow += db.collect_dust(r_inner, r_outer, p);
                }
            }while ((gatherNow - gatherLast) >= minimum_accretion);
            update_dust_lanes(p.inner_effect_limit(cloud_eccentricity), p.outer_effect_limit(cloud_eccentricity));
        }
예제 #3
0
        /// <summary> Determines whether dust is present within the effect radius of
        /// a specific Protoplanet.
        /// </summary>
        /// <param name="p">Protoplanet within the disc
        /// </param>
        /// <returns>s true if there is a band containing dust which this body
        /// can accrete.
        /// </returns>
        public virtual bool dust_available(Protoplanet p)
        {
            double   inside_range  = p.inner_effect_limit(cloud_eccentricity);
            double   outside_range = p.outer_effect_limit(cloud_eccentricity);
            DustBand current_dust_band;
            bool     dust_here = false;

            current_dust_band = dust_head;
            while ((current_dust_band != null) && (current_dust_band.outer_edge < inside_range))
            {
                current_dust_band = current_dust_band.next_band;
            }
            if (current_dust_band == null)
            {
                dust_here = false;
            }
            else
            {
                dust_here = current_dust_band.dust_present;
            }
            while ((current_dust_band != null) && (current_dust_band.inner_edge < outside_range))
            {
                dust_here         = dust_here || current_dust_band.dust_present;
                current_dust_band = current_dust_band.next_band;
            }
            return(dust_here);
        }
예제 #4
0
 /// <summary> Copy constructor</summary>
 public Protoplanet(Protoplanet p)
 {
     a            = p.a; e = p.e; mass = p.mass; //next_planet = p.next_planet;
     gas_giant    = p.gas_giant; crit_mass = p.crit_mass;
     dust_density = p.dust_density;
     moons        = new ArrayList();
     if (p.moons != null)
     {
         foreach (Protoplanet moon in p.moons)
         {
             moons.Add(moon);
         }
     }
 }
예제 #5
0
        /// <summary> Calculate the amount of dust which the specified protoplanet can
        /// accrete from this dust band, if any.
        /// </summary>
        /// <returns>s Quantity of dust, in units of solar masses.
        /// </returns>
        public virtual double collect_dust(double r_inner, double r_outer, Protoplanet p)
        {
            double gather = 0.0;

            /* as last_mass increases, temp approaches 1.
             * reduced_mass approaches 1 even quicker.
             * as reduced_mass approaches 1, r_inner approaches 0 and
             * r_outer approaches 2*a*(1.0 + e).  Apparently the integration
             * is from 0 to 2a.
             * The masses are expressed in terms of solar masses; temp is therefore
             * the ratio of the planetary mass to the total system (sun + planet)
             */
            if (intersect(r_inner, r_outer) != DBI_NO_INTERSECTION)
            {
                double bandwidth = (r_outer - r_inner);
                double temp1     = r_outer - outer_edge;
                double temp2     = inner_edge - r_inner;
                double width;
                double temp;
                double volume;

                if (bandwidth <= 0.0)
                {
                    bandwidth = 0.0;
                }
                if (temp1 < 0.0)
                {
                    temp1 = 0.0;
                }
                width = bandwidth - temp1;
                if (temp2 < 0.0)
                {
                    temp2 = 0.0;
                }
                width -= temp2;
                if (width < 0.0)
                {
                    width = 0.0;
                }
                temp   = 4.0 * System.Math.PI * System.Math.Pow(p.a, 2.0) * p.reduced_mass * (1.0 - p.e * (temp1 - temp2) / bandwidth);
                volume = temp * width;
                gather = (volume * p.mass_density(dust_present, gas_present));
            }
            return(gather);
        }
예제 #6
0
        /// <summary> Accretes protoplanets from the dust disc in this system.</summary>
        /// <returns>s First protoplanet of accreted system, as the head
        /// element of a list of protoplanets.
        /// </returns>
        public virtual void dist_planetary_masses()
        {
            Protoplanet p0;

            while (disc.dust_left)
            {
                p0 = new Protoplanet(disc.body_inner_bound, disc.body_outer_bound);
                if (disc.dust_available(p0))
                {
                    p0.dust_density = PhysicalConstants.DUST_DENSITY_COEFF * System.Math.Sqrt(star.SM) * System.Math.Exp((-PhysicalConstants.ALPHA) * System.Math.Pow(p0.a, (1.0 / PhysicalConstants.N)));
                    p0.crit_mass    = star.critical_limit(p0.a, p0.e);
                    disc.accrete_dust(p0);
                    if (p0.massOK())
                    {
                        coalesce_planetesimals(p0);
                    }
                    else
                    {
                        //System.out.println(".. failed due to large neighbor.");
                    }
                }
            }
        }
예제 #7
0
        /// <summary> Determines whether dust is present within the effect radius of
        /// a specific Protoplanet.
        /// </summary>
        /// <param name="p">Protoplanet within the disc
        /// </param>
        /// <returns>s true if there is a band containing dust which this body
        /// can accrete.
        /// </returns>
        public virtual bool dust_available(Protoplanet p)
        {
            double inside_range = p.inner_effect_limit(cloud_eccentricity);
            double outside_range = p.outer_effect_limit(cloud_eccentricity);
            DustBand current_dust_band;
            bool dust_here = false;

            current_dust_band = dust_head;
            while ((current_dust_band != null) && (current_dust_band.outer_edge < inside_range))
                current_dust_band = current_dust_band.next_band;
            if (current_dust_band == null)
                dust_here = false;
            else
                dust_here = current_dust_band.dust_present;
            while ((current_dust_band != null) && (current_dust_band.inner_edge < outside_range))
            {
                dust_here = dust_here || current_dust_band.dust_present;
                current_dust_band = current_dust_band.next_band;
            }
            return (dust_here);
        }
예제 #8
0
 /// <summary> 
 /// Constructor from an accreted protoplanet.
 /// </summary>
 /// <param name="p">Protoplanet that forms the basis of this planet
 /// </param>
 public Planet(Protoplanet p)
 {
     //next_planet = null;
     //first_moon = null;
     a = p.a; e = p.e; mass = p.mass * PhysicalConstants.SUN_MASS_IN_EARTH_MASSES;
     gas_giant = p.gas_giant;
     where_in_orbit = (nextDouble() * 360.0) * PhysicalConstants.DEG_TO_RAD;
     albedo = 0.0; // start with albedo of 0
     plan_class = classify_by_accretion();
     if (mass < 1.0e-6)
     {
         mass = 0.0;
         plan_class = '-';
     }
     density = density_by_temperature(plan_class);
     radius = planet_radius(mass, density, plan_class);
     moons = new ArrayList();
     if (p.moons != null)
     {
         foreach (Protoplanet moon in p.moons)
         {
             moons.Add(moon);
         }
     }
 }
예제 #9
0
 /// <summary> Copy constructor</summary>
 public Protoplanet(Protoplanet p)
 {
     a = p.a; e = p.e; mass = p.mass; //next_planet = p.next_planet;
     gas_giant = p.gas_giant; crit_mass = p.crit_mass;
     dust_density = p.dust_density;
     moons = new ArrayList();
     if (p.moons != null)
     {
         foreach (Protoplanet moon in p.moons)
         {
             moons.Add(moon);
         }
     }
 }
예제 #10
0
        /// <summary> Calculate the amount of dust which the specified protoplanet can
        /// accrete from this dust band, if any.
        /// </summary>
        /// <returns>s Quantity of dust, in units of solar masses. 
        /// </returns>
        public virtual double collect_dust(double r_inner, double r_outer, Protoplanet p)
        {
            double gather = 0.0;

            /* as last_mass increases, temp approaches 1.
            * reduced_mass approaches 1 even quicker.
            * as reduced_mass approaches 1, r_inner approaches 0 and
            * r_outer approaches 2*a*(1.0 + e).  Apparently the integration
            * is from 0 to 2a.
            * The masses are expressed in terms of solar masses; temp is therefore
            * the ratio of the planetary mass to the total system (sun + planet)
            */
            if (intersect(r_inner, r_outer) != DBI_NO_INTERSECTION)
            {
                double bandwidth = (r_outer - r_inner);
                double temp1 = r_outer - outer_edge;
                double temp2 = inner_edge - r_inner;
                double width;
                double temp;
                double volume;

                if (bandwidth <= 0.0)
                    bandwidth = 0.0;
                if (temp1 < 0.0)
                    temp1 = 0.0;
                width = bandwidth - temp1;
                if (temp2 < 0.0)
                    temp2 = 0.0;
                width -= temp2;
                if (width < 0.0)
                    width = 0.0;
                temp = 4.0 * System.Math.PI * System.Math.Pow(p.a, 2.0) * p.reduced_mass * (1.0 - p.e * (temp1 - temp2) / bandwidth);
                volume = temp * width;
                gather = (volume * p.mass_density(dust_present, gas_present));
            }
            return gather;
        }
예제 #11
0
        /// <summary> Searches the planetesimals already present in this system
        /// for a possible collision.  Does not run any long-term simulation
        /// of orbits, doesn't try to eject bodies...
        /// </summary>
        /// <param name="p">
        /// Newly injected accreting protoplanet to test
        /// </param>
        public virtual void coalesce_planetesimals(Protoplanet p)
        {
            // note that p is not consumed by this routine...
            Protoplanet node2, node3;
            bool        finished = false;
            double      temp, dist1, dist2, a3;
            double      reduced_mass = p.mass;

            // try to merge Protoplanets
            //node2 = node1 = planet_head;
            foreach (Protoplanet node1 in this.protoplanetsList)
            {
                node2 = node1;
                temp  = node1.a - p.a;
                if ((temp > 0.0))
                {
                    dist1 = (p.a * (1.0 + p.e) * (1.0 + p.mass)) - p.a;
                    /* x aphelion   */
                    if (node1.mass <= 0.0)
                    {
                        reduced_mass = 0.0;
                    }
                    else
                    {
                        reduced_mass = System.Math.Pow((node1.mass / (1.0 + node1.mass)), (1.0 / 4.0));
                    }
                    dist2 = node1.a - (node1.a * (1.0 - node1.e) * (1.0 - reduced_mass));
                }
                else
                {
                    dist1 = p.a - (p.a * (1.0 - p.e) * (1.0 - p.mass));
                    /* x perihelion */
                    if (node1.mass <= 0.0)
                    {
                        reduced_mass = 0.0;
                    }
                    else
                    {
                        reduced_mass = System.Math.Pow(node1.mass / (1.0 + node1.mass), (1.0 / 4.0));
                    }
                    dist2 = (node1.a * (1.0 + node1.e) * (1.0 + reduced_mass)) - node1.a;
                }
                if (((System.Math.Abs(temp) <= System.Math.Abs(dist1)) || (System.Math.Abs(temp) <= System.Math.Abs(dist2))))
                {
                    //collision
                    if (p.mass > 0.2 /*&& (node1.mass / p.mass) > 0.1*/)
                    {
                    }

                    a3    = (node1.mass + p.mass) / ((node1.mass / node1.a) + (p.mass / p.a));
                    temp  = node1.mass * System.Math.Sqrt(node1.a) * System.Math.Sqrt(1.0 - (node1.e * node1.e));
                    temp += (p.mass * System.Math.Sqrt(p.a) * System.Math.Sqrt(System.Math.Sqrt(1.0 - (p.e * p.e))));
                    temp /= ((node1.mass + p.mass) * System.Math.Sqrt(a3));
                    temp  = 1.0 - (temp * temp);
                    if (((temp < 0.0) || (temp >= 1.0)))
                    {
                        temp = 0.0;
                    }
                    p.e        = System.Math.Sqrt(temp);
                    temp       = node1.mass + p.mass;
                    node1.a    = a3;
                    node1.e    = p.e;
                    node1.mass = temp;
                    disc.accrete_dust(node1);
                    //node1 = null;
                    finished = true;
                }
            }
            if (!finished)
            {
                // add copy of planetesimal to planets list
                node3           = new Protoplanet(p);
                node3.gas_giant = (p.mass >= p.crit_mass);
                protoplanetsList.Add(node3);
                protoplanetsList.Sort(new PlanetSort(SortDirection.Ascending));

                #region Original code, made obsolete by sort method of ArrayList
                //if ((planet_head == null))
                //{
                //    planet_head = node3;
                //}
                //else
                //{
                //    node1 = planet_head;
                //    if ((p.a < node1.a))
                //    {
                //        node3.next_planet = node1;
                //        planet_head = node3;
                //    }
                //    else if ((planet_head.next_planet == null))
                //    {
                //        planet_head.next_planet = node3;
                //    }
                //    else
                //    {
                //        while (((node1 != null) && (node1.a < p.a)))
                //        {
                //            node2 = node1;
                //            node1 = node1.next_planet;
                //        }
                //        node3.next_planet = node1;
                //        node2.next_planet = node3;
                //    }
                //}
                #endregion
            }
        }
예제 #12
0
        /// <summary> Searches the planetesimals already present in this system
        /// for a possible collision.  Does not run any long-term simulation
        /// of orbits, doesn't try to eject bodies...
        /// </summary>
        /// <param name="p">
        /// Newly injected accreting protoplanet to test
        /// </param>
        public virtual void coalesce_planetesimals(Protoplanet p)
        {
            // note that p is not consumed by this routine...
            Protoplanet node2, node3;
            bool finished = false;
            double temp, dist1, dist2, a3;
            double reduced_mass = p.mass;

            // try to merge Protoplanets
            //node2 = node1 = planet_head;
            foreach (Protoplanet node1 in this.protoplanetsList)
            {
                node2 = node1;
                temp = node1.a - p.a;
                if ((temp > 0.0))
                {
                    dist1 = (p.a * (1.0 + p.e) * (1.0 + p.mass)) - p.a;
                    /* x aphelion   */
                    if (node1.mass <= 0.0)
                        reduced_mass = 0.0;
                    else
                        reduced_mass = System.Math.Pow((node1.mass / (1.0 + node1.mass)), (1.0 / 4.0));
                    dist2 = node1.a - (node1.a * (1.0 - node1.e) * (1.0 - reduced_mass));
                }
                else
                {
                    dist1 = p.a - (p.a * (1.0 - p.e) * (1.0 - p.mass));
                    /* x perihelion */
                    if (node1.mass <= 0.0)
                        reduced_mass = 0.0;
                    else
                        reduced_mass = System.Math.Pow(node1.mass / (1.0 + node1.mass), (1.0 / 4.0));
                    dist2 = (node1.a * (1.0 + node1.e) * (1.0 + reduced_mass)) - node1.a;
                }
                if (((System.Math.Abs(temp) <= System.Math.Abs(dist1)) || (System.Math.Abs(temp) <= System.Math.Abs(dist2))))
                {
                    //collision
                    if (p.mass > 0.2 /*&& (node1.mass / p.mass) > 0.1*/)
                    {

                    }

                    a3 = (node1.mass + p.mass) / ((node1.mass / node1.a) + (p.mass / p.a));
                    temp = node1.mass * System.Math.Sqrt(node1.a) * System.Math.Sqrt(1.0 - (node1.e * node1.e));
                    temp += (p.mass * System.Math.Sqrt(p.a) * System.Math.Sqrt(System.Math.Sqrt(1.0 - (p.e * p.e))));
                    temp /= ((node1.mass + p.mass) * System.Math.Sqrt(a3));
                    temp = 1.0 - (temp * temp);
                    if (((temp < 0.0) || (temp >= 1.0)))
                        temp = 0.0;
                    p.e = System.Math.Sqrt(temp);
                    temp = node1.mass + p.mass;
                    node1.a = a3;
                    node1.e = p.e;
                    node1.mass = temp;
                    disc.accrete_dust(node1);
                    //node1 = null;
                    finished = true;
                }
            }
            if (!finished)
            {
                // add copy of planetesimal to planets list
                node3 = new Protoplanet(p);
                node3.gas_giant = (p.mass >= p.crit_mass);
                protoplanetsList.Add(node3);
                protoplanetsList.Sort(new PlanetSort(SortDirection.Ascending));

                #region Original code, made obsolete by sort method of ArrayList
                //if ((planet_head == null))
                //{
                //    planet_head = node3;
                //}
                //else
                //{
                //    node1 = planet_head;
                //    if ((p.a < node1.a))
                //    {
                //        node3.next_planet = node1;
                //        planet_head = node3;
                //    }
                //    else if ((planet_head.next_planet == null))
                //    {
                //        planet_head.next_planet = node3;
                //    }
                //    else
                //    {
                //        while (((node1 != null) && (node1.a < p.a)))
                //        {
                //            node2 = node1;
                //            node1 = node1.next_planet;
                //        }
                //        node3.next_planet = node1;
                //        node2.next_planet = node3;
                //    }
                //}
                #endregion
            }
        }
예제 #13
0
        /// <summary> Accretes protoplanets from the dust disc in this system.</summary>
        /// <returns>s First protoplanet of accreted system, as the head
        /// element of a list of protoplanets.
        /// </returns>
        public virtual void dist_planetary_masses()
        {
            Protoplanet p0;

            while (disc.dust_left)
            {
                p0 = new Protoplanet(disc.body_inner_bound, disc.body_outer_bound);
                if (disc.dust_available(p0))
                {
                    p0.dust_density = PhysicalConstants.DUST_DENSITY_COEFF * System.Math.Sqrt(star.SM) * System.Math.Exp((-PhysicalConstants.ALPHA) * System.Math.Pow(p0.a, (1.0 / PhysicalConstants.N)));
                    p0.crit_mass = star.critical_limit(p0.a, p0.e);
                    disc.accrete_dust(p0);
                    if (p0.massOK())
                        coalesce_planetesimals(p0);
                    else
                    {
                        //System.out.println(".. failed due to large neighbor.");
                    }
                }
            }
        }
예제 #14
0
        int IComparer.Compare(object x, object y)
        {
            if ((x is Protoplanet) && (y is Protoplanet))
            {
                Protoplanet p1 = (Protoplanet)x;
                Protoplanet p2 = (Protoplanet)y;

                if (p1 == null && p2 == null)
                {
                    return(0);
                }
                else if (p1 == null && p2 != null)
                {
                    return((this.m_direction == SortDirection.Ascending) ? -1 : 1);
                }
                else if (p1 != null && p2 == null)
                {
                    return((this.m_direction == SortDirection.Ascending) ? 1 : -1);
                }
                else
                {
                    if (p1.a > 0 && p2.a > 0)
                    {
                        return((this.m_direction == SortDirection.Ascending) ?
                               p1.a.CompareTo(p2.a) :
                               p2.a.CompareTo(p1.a));
                    }
                    else
                    {
                        return(0);
                    }
                }
            }
            else if ((x is Planet) && (y is Planet))
            {
                Planet p1 = (Planet)x;
                Planet p2 = (Planet)y;

                if (p1 == null && p2 == null)
                {
                    return(0);
                }
                else if (p1 == null && p2 != null)
                {
                    return((this.m_direction == SortDirection.Ascending) ? -1 : 1);
                }
                else if (p1 != null && p2 == null)
                {
                    return((this.m_direction == SortDirection.Ascending) ? 1 : -1);
                }
                else
                {
                    if (p1.a > 0 && p2.a > 0)
                    {
                        return((this.m_direction == SortDirection.Ascending) ?
                               p1.a.CompareTo(p2.a) :
                               p2.a.CompareTo(p1.a));
                    }
                    else
                    {
                        return(0);
                    }
                }
            }
            else
            {
                return(0);
            }
        }