/// <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); }