/// <summary>
        /// Recusively seeds an input particle (seeds all children as well)
        /// </summary>
        /// <param name="Input">The particle to seed</param>
        private static void SeedParticle(Particle Input, double UniverseRadius)
        {
            Input.Position = new Vector(Input.Position.Capacity);

            Input.Velocity = SimMath.RandomVector(Input.Velocity.Capacity, 1, 2);

            if (Input.SubParticles != null)
            {
                if (Input.SubParticles.Count != 0)
                {
                    foreach (Particle P in Input.SubParticles)
                    {
                        SeedParticle(P, UniverseRadius);
                    }
                }
            }

            if (Input.Properties != null)
            {
                if (Input.Properties.Count != 0)
                {
                    foreach (ParticleProperty P in Input.Properties)
                    {
                        P.Value = SimMath.GenerateRandomDouble(P.Type.AcceptedValues.MinimumValue, P.Type.AcceptedValues.MaximumValue);
                    }
                }
            }
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulations.Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure our input particle has "charge" and obtain it
            if (!Input.HasProperty("Charge")) return Force;
            double Charge = Input.GetPropertyVal("Charge");
            if (Charge == 0) return Force;

            //Determine the input's siblings
            List<Particle> Siblings;
            if (Input.ParentParticle != null)
            {
                Siblings = Input.ParentParticle.SubParticles;
            }
            else
            {
                //Assume top layer
                Siblings = Sim.SimUniverse.Particles;
            }

            //Get the electric and magnetic fields on the charge
            Vector ElectricField = CalculateElectricFieldAtPosition(Input.Position, Siblings, Sim.Parameters);
            Vector MagneticField = CalculateMagneticFieldAtPosition(Input.Position, Siblings, Sim.Parameters);

            //Calculate the Lorentz force
            Force = (Charge * ElectricField) + Vector.Vector_3DCross((Charge * Input.Velocity), MagneticField);

            //Return the new net force
            return Force;
        }
 /// <summary>
 /// Checks to see if a particle is within bounds of the entire universe (uses absolute position of the particle and thus can also be used on sub-particles).
 /// If the universe boundary type is set to "Infinate", this will always return true
 /// </summary>
 /// <param name="InputParticle">The particle to check</param>
 public bool CheckInBounds(Particle InputParticle)
 {
     if (this.Radius == double.PositiveInfinity) return true;
     if (this.ResolveScript == null) return true;
     Vector realpos = InputParticle.GetActualPosition();
     return (realpos.Magnitude <= System.Math.Abs(this.Radius));
 }
        /// <summary>
        /// Recusively seeds an input particle (seeds all children as well)
        /// </summary>
        /// <param name="Input">The particle to seed</param>
        private static void SeedParticle(Particle Input, double UniverseRadius)
        {
            if (Input.ParentParticle == null)
            {
                Input.Position = SimMath.RandomSphericalPosition(Input.Position.Capacity, UniverseRadius);
            }
            else
            {
                Input.Position = SimMath.RandomSphericalPosition(Input.Position.Capacity, Input.ParentParticle.Radius);
            }

            if (Input.SubParticles != null)
            {
                if (Input.SubParticles.Count != 0)
                {
                    foreach (Particle P in Input.SubParticles)
                    {
                        SeedParticle(P, UniverseRadius);
                    }
                }
            }

            if (Input.Properties != null)
            {
                if (Input.Properties.Count != 0)
                {
                    foreach (ParticleProperty P in Input.Properties)
                    {
                        P.Value = SimMath.GenerateRandomDouble(P.Type.AcceptedValues.MinimumValue, P.Type.AcceptedValues.MaximumValue);
                    }
                }
            }
        }
        /// <summary>
        /// Returns a copy of an input particle updated against all particles under the same parent
        /// </summary>
        /// <param name="Input">The particle to update</param>
        /// <param name="Sim">The simulation object</param>
        public static Particle UpdateParticle(Particle Input, Simulations.Simulation Sim)
        {
            //Extract all scripts that have the "Force" tag
            InteractionScripts ForceInteractions = Sim.Interactions.ExtractByTag("Force");

            //Extract all scripts that have the "PostForceInteraction" tag
            InteractionScripts PostForceInteractions = Sim.Interactions.ExtractByTag("PostForceInteraction");

            //Complain if we dont have any interaction types
            if (ForceInteractions == null && PostForceInteractions == null) return Input;

            //Create a copy of the input particle that we can return without modifying the origional
            Particle ReturnParticle = Particle.Copy_Shallow(Input, true);

            //Zero-out the net force and acceleration of the particle we are returning
            ReturnParticle.Acceleration = new Vector(Input.Acceleration.Capacity);
            ReturnParticle.NetForce = new Vector(Input.NetForce.Capacity);

            //Calculate force interactions
            if (ForceInteractions != null)
            {
                //For each possible comparison particle:
                foreach (Particle Comparison in Sim.SimUniverse.Particles)
                {
                    //Make sure they aren't the same particle
                    if (ReturnParticle.ID == Comparison.ID) continue;

                    //Calculate the net force of that particle on our return particle
                    foreach (ParticleInteractionScript ForceInteraction in ForceInteractions)
                    {
                        ReturnParticle.NetForce += ForceInteraction.CalculateInteraction(ReturnParticle, Comparison, Sim);
                    }
                }
            }

            //Calculate post force interactions
            if (PostForceInteractions != null)
            {
                foreach (ParticleInteractionScript PostForceInteraction in PostForceInteractions)
                {
                    ReturnParticle.NetForce += PostForceInteraction.CalculateInteraction(ReturnParticle, null, Sim);
                }
            }

            //Here we multiply by 0.0001 to account for the max timer speed
            ReturnParticle.NetForce *= 0.0001;

            //Now lets calculate the acceleration of the particle by dividing the net force by the mass of the particle
            ReturnParticle.Acceleration = ReturnParticle.NetForce / ReturnParticle.GetPropertyVal("Mass");

            //Now we need to calculate velocity
            ReturnParticle.Velocity += ReturnParticle.Acceleration;

            //Now we calculate position and we're done
            ReturnParticle.Position += ReturnParticle.Velocity;

            //Return the updated particle
            return ReturnParticle;
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = Vector.Vector_Copy(Comparison.Position);
            Force.Magnitude = Vector.Vector_Dot(Input.Position, Comparison.Position) * Comparison.Position.Magnitude / 2;

            //Return the new net force
            return Force;
        }
        public override Particle Resolve(Particle Input, UniverseBoundary Boundary)
        {
            //Create a shallow copy of the input particle
            Particle Resolved = Particle.Copy_Shallow(Input, true);

            Resolved.Position = SimMath.RandomSphericalPosition(Input.NumberDimensions, Boundary.Radius);

            //Return the result
            return Resolved;
        }
        public override Particle Resolve(Particle Input, UniverseBoundary Boundary)
        {
            //Create a shallow copy of the input particle
            Particle Resolved = Particle.Copy_Shallow(Input, true);

            Resolved.Position = new Vector(Resolved.Position.Capacity);

            //Return the result
            return Resolved;
        }
        public override Particle Resolve(Particle Input, UniverseBoundary Boundary)
        {
            //Create a shallow copy of the input particle
            Particle Resolved = Particle.Copy_Shallow(Input, true);

            //All we need to do is change the magnitude of the position vector
            Resolved.Position.Magnitude = System.Math.Abs(Boundary.Radius);

            //Return the result
            return Resolved;
        }
        public override Particle Resolve(Particle Input, UniverseBoundary Boundary)
        {
            //Create a shallow copy of the input particle
            Particle Resolved = Particle.Copy_Shallow(Input, true);

            //All we need to do is reverse the direction of the position vector
            Resolved.Position = Vector.Vector_Negate(Resolved.Position);

            //Return the result
            return Resolved;
        }
        public override Particle Resolve(Particle Input, UniverseBoundary Boundary)
        {
            //Create a shallow copy of the input particle
            Particle Resolved = Particle.Copy_Shallow(Input, true);

            Resolved.Position.Magnitude = System.Math.Abs(Boundary.Radius);

            //this isn't right, we don't want to reverse the direction of the velocity, we want to reverse the direction of the direction vector between the particle and the edge
            Resolved.Velocity.Direction = Vector.Vector_Negate(Resolved.Position.Direction);

            //Return the result
            return Resolved;
        }
        /// <summary>
        /// Creates a particle representing the planet Earth in 3 dimensions
        /// </summary>
        public static Particle Earth()
        {
            //Initialize a return particle
            Particle ReturnParticle = new Particle(3);

            //Setup the particle
            ReturnParticle.Radius = 6.371E6;
            ReturnParticle.AddProperty(PhysicsParticleProperties.Mass, 5.97219E24);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Charge, 0);

            //Return the newly created particle
            return ReturnParticle;
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulations.Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure both our input and comparison particles have "mass"
            if (!Input.HasProperty("Mass") || !Comparison.HasProperty("Mass")) return Force;

            //Now we calculate the actual distance between the particles (we will need this later)
            double ActualDistance = (Comparison.Position - Input.Position).Magnitude;
            Vector Dir = (Input.Position - Comparison.Position).Direction;

            //If the "Precision" simulation parameter is available to us:
            if (Sim.Parameters.HasParam("Precision"))
            {
                //Check to see if the actual distance is under the precision value
                if ((System.Math.Abs(ActualDistance) - Input.Radius - Comparison.Radius) <= Sim.Parameters.GetParam("Precision"))
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }
            else //Otherwise:
            {
                //Assume a precision of zero
                if ((System.Math.Abs(ActualDistance) - Input.Radius - Comparison.Radius) <= 0)
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }

            //Get all of our needed parts
            double InputMass = Input.GetPropertyVal("Mass");
            double ComparisonMass = Comparison.GetPropertyVal("Mass");
            double GravitationalConstant;
            if (Sim.Parameters.HasParam("GravitationalConstant"))
            {
                GravitationalConstant = Sim.Parameters.GetParam("GravitationalConstant");
            }
            else
            {
                GravitationalConstant = PhysicsConstants.GravitationalConstant;
            }

            Force = GravitationalConstant * InputMass * ComparisonMass / ActualDistance * Dir;

            //Return the new net force
            return Force;
        }
        /// <summary>
        /// Creates an antiproton of a particular number of dimensions
        /// </summary>
        /// <param name="NumberDimensions">The number of dimensions this antiproton exists in</param>
        public static Particle Antiproton(int NumberDimensions)
        {
            //Initialize a return particle
            Particle ReturnParticle = new Particle(NumberDimensions);

            //Setup the particle
            ReturnParticle.Radius = 8.775E-16;
            ReturnParticle.AddProperty(PhysicsParticleProperties.Mass, PhysicsConstants.ProtonMass);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Charge, -PhysicsConstants.ElementaryCharge);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Spin, 1.0 / 2.0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Parity, 1);
            ReturnParticle.AddProperty(PhysicsParticleProperties.MagneticMoment, 1.410606743E-26);

            //Return the newly created particle
            return ReturnParticle;
        }
        /// <summary>
        /// Creates an electron of a particular number of dimensions
        /// NOTE that this assumes a classical radius of 2.8179E-15 m
        /// </summary>
        /// <param name="NumberDimensions">The number of dimensions this electron exists in</param>
        public static Particle Electron(int NumberDimensions)
        {
            //Initialize a return particle
            Particle ReturnParticle = new Particle(NumberDimensions);

            //Setup the particle
            ReturnParticle.Radius = 2.8179E-15;
            ReturnParticle.AddProperty(PhysicsParticleProperties.Mass, PhysicsConstants.ElectronMass);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Charge, -PhysicsConstants.ElementaryCharge);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Spin, 1.0 / 2.0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Parity, 1);
            ReturnParticle.AddProperty(PhysicsParticleProperties.MagneticMoment, 9.284764E-24);

            //Return the newly created particle
            return ReturnParticle;
        }
        /// <summary>
        /// Creates an antineutron of a particular number of dimensions
        /// </summary>
        /// <param name="NumberDimensions">The number of dimensions this antineutron exists in</param>
        public static Particle Antineutron(int NumberDimensions)
        {
            //Initialize a return particle
            Particle ReturnParticle = new Particle(NumberDimensions);

            //Setup the particle
            ReturnParticle.Radius = 0.8E-15;
            ReturnParticle.AddProperty(PhysicsParticleProperties.Mass, PhysicsConstants.NeutronMass);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Charge, 0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Spin, 1.0 / 2.0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Parity, 1);
            ReturnParticle.AddProperty(PhysicsParticleProperties.MagneticMoment, 0.96623647E-26);

            //Return the newly created particle
            return ReturnParticle;
        }
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure both our input and comparison particles have "mass"
            if (!Input.HasProperty("Mass") || !Comparison.HasProperty("Mass")) return Force;

            //Now we calculate the actual distance between the particles (we will need this later)
            double ActualDistance = (Comparison.Position - Input.Position).Magnitude;
            if (ActualDistance == 0) return new Vector(Input.Acceleration.Count);

            //Assume a precision of zero
            if ((ActualDistance - Input.Radius - Comparison.Radius) <= 0)
            {
                //Return no change in acceleration
                return new Vector(Input.Acceleration.Count);
            }

            //If the "SofteningValue" simulation parameter is available to us:
            double Denominator = System.Math.Pow((ActualDistance * ActualDistance), (3.0 / 2.0));

            //Get all of our needed parts
            double InputMass = Input.GetPropertyVal("Mass");
            double ComparisonMass = Comparison.GetPropertyVal("Mass");

            //For each dimension of movement/location:
            for (int i = 0; i < Force.Capacity; i++)
            {
                //Calculate the component distance of this dimension
                double ComponentDistance = Comparison.Position[i] - Input.Position[i];

                //Calculate the new force
                Force[i] = (SimMath.GenerateRandomDouble(-ComparisonMass, ComparisonMass) * ComponentDistance) / Denominator;
            }

            //Return the new net force
            return Force;
        }
 /// <summary>
 /// Resolves the properties of a particle that has passed the edge of the universe.
 /// </summary>
 /// <param name="Input">The particle to resolve</param>
 /// <param name="Boundary">The boundary of the universe that the particle has escaped.</param>
 public abstract Particle Resolve(Particle Input, UniverseBoundary Boundary);
        public override dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulation Sim)
        {
            //First we create a new force vector to store our result to
            Vector Force = new Vector(Input.NetForce.Capacity);

            //Make sure both our input and comparison particles have "mass"
            if (!Input.HasProperty("Mass") || !Comparison.HasProperty("Mass")) return Force;

            //Now we calculate the actual distance between the particles (we will need this later)
            double ActualDistance = (Comparison.Position - Input.Position).Magnitude;
            if (ActualDistance == 0) return new Vector(Input.Acceleration.Count);

            //If the "Precision" simulation parameter is available to us:
            if (Sim.Parameters.HasParam("Precision"))
            {
                //Check to see if the actual distance is under the precision value
                if ((ActualDistance - Input.Radius - Comparison.Radius) <= Sim.Parameters.GetParam("Precision"))
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }
            else //Otherwise:
            {
                //Assume a precision of zero
                if ((ActualDistance - Input.Radius - Comparison.Radius) <= 0)
                {
                    //Return no change in acceleration
                    return new Vector(Input.Acceleration.Count);
                }
            }

            //If the "SofteningValue" simulation parameter is available to us:
            double Denominator;
            if (Sim.Parameters.HasParam("SofteningValue"))
            {
                //Calculate the denominator of the equation
                double SofteningValue = Sim.Parameters.GetParam("SofteningValue");
                Denominator = System.Math.Pow(((ActualDistance * ActualDistance) + (SofteningValue * SofteningValue)), (3.0 / 2.0));
            }
            else //Otherwise:
            {
                //Calculate the denominator of the equation
                Denominator = System.Math.Pow((ActualDistance * ActualDistance), (3.0 / 2.0));
            }

            //Get all of our needed parts
            double InputMass = Input.GetPropertyVal("Mass");
            double ComparisonMass = Comparison.GetPropertyVal("Mass");
            double GravitationalConstant;
            if (Sim.Parameters.HasParam("GravitationalConstant"))
            {
                GravitationalConstant = Sim.Parameters.GetParam("GravitationalConstant");
            }
            else
            {
                GravitationalConstant = PhysicsConstants.GravitationalConstant;
            }

            //For each dimension of movement/location:
            for (int i = 0; i < Force.Capacity; i++)
            {
                //Calculate the component distance of this dimension
                double ComponentDistance = Comparison.Position[i] - Input.Position[i];

                //Calculate the new force
                Force[i] = GravitationalConstant * (InputMass * ComparisonMass * ComponentDistance) / Denominator;
            }

            //Return the new net force
            return Force;
        }
        /// <summary>
        /// Creates a photon of a particular number of dimensions
        /// </summary>
        /// <param name="NumberDimensions">The number of dimensions this photon exists in</param>
        public static Particle Photon(int NumberDimensions)
        {
            //Initialize a return particle
            Particle ReturnParticle = new Particle(NumberDimensions);

            //Setup the particle
            ReturnParticle.Radius = 0;
            ReturnParticle.AddProperty(PhysicsParticleProperties.Mass, 0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Charge, 0);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Spin, 1);
            ReturnParticle.AddProperty(PhysicsParticleProperties.Parity, -1);

            //Return the newly created particle
            return ReturnParticle;
        }
 /// <summary>
 /// Compares two particles, returning true if they are the same particle.
 /// </summary>
 /// <param name="Particle1">The first particle to compare</param>
 /// <param name="Particle2">The second particle to compare</param>
 public static bool Compare(Particle Particle1, Particle Particle2)
 {
     return (Particle1.ID == Particle2.ID);
 }
        /// <summary>
        /// Copies a particle and all child references but does not copy children.
        /// </summary>
        /// <param name="InputParticle">The particle to copy</param>
        /// <param name="CopyID">Whether to copy the current particle's ID to the new particle</param>
        public static Particle Copy_Shallow(Particle InputParticle, bool CopyID)
        {
            Particle ReturnParticle = new Particle(InputParticle.NumberDimensions);

            ReturnParticle.ParentParticle = InputParticle.ParentParticle; //We MUST make sure that we DON'T make a new parent
            ReturnParticle.Acceleration = Vector.Vector_Copy(InputParticle.Acceleration);
            ReturnParticle.Velocity = Vector.Vector_Copy(InputParticle.Velocity);
            ReturnParticle.Position = Vector.Vector_Copy(InputParticle.Position);
            ReturnParticle.NetForce = Vector.Vector_Copy(InputParticle.NetForce);
            ReturnParticle.Radius = InputParticle.Radius;
            if (CopyID) ReturnParticle.ID = InputParticle.ID;

            foreach (dynamic Prop in InputParticle.Properties)
            {
                ReturnParticle.Properties.Add(Prop.Copy());
            }

            foreach (Particle SubParticle in InputParticle.SubParticles)
            {
                ReturnParticle.SubParticles.Add(SubParticle);
            }

            return ReturnParticle;
        }
 /// <summary>
 /// Calculates the interaction between two particles, returning 
 /// </summary>
 /// <param name="Input">The particle to update</param>
 /// <param name="Comparison">The particle to compare this particle to</param>
 /// <param name="SimParams">The list of simulation parameters</param>
 /// <param name="Interactions">The list of available interaction scripts</param>
 /// <param name="Cosmos">The universe of available particles</param>
 public abstract dynamic CalculateInteraction(Particle Input, Particle Comparison, Simulations.Simulation Sim);
 /// <summary>
 /// Resolves boundary issues for a particular particle (assumes the particle already violates the boundary).
 /// </summary>
 public Particle Boundary_Resolve(Particle InputParticle)
 {
     if (this.Boundary.ResolveScript == null) return InputParticle;
     return this.Boundary.ResolveScript.Resolve(InputParticle, this.Boundary);
 }