/// <summary> /// Copies the information from a particle to a new one. /// </summary> public static Particle Copy(Particle Input) { Particle ReturnParticle = new Particle(Input.Acceleration.Capacity, Input.Properties.Capacity); for (int i = 0; i < Input.Acceleration.Capacity; i++) { ReturnParticle.Acceleration[i] = Input.Acceleration[i]; ReturnParticle.Velocity[i] = Input.Velocity[i]; ReturnParticle.Position[i] = Input.Position[i]; } for (int i = 0; i < Input.Properties.Capacity; i++) { ReturnParticle.Properties[i] = Input.Properties[i]; } return ReturnParticle; }
/// <summary> /// Updates a single particle. /// </summary> public static Particle UpdateParticle(Particle Input, List<Particle> ParticleList, double Precision, double SofteningValue, double GravityConstant, double MaxVelocity) { //Create a copy of the input particle that we can return without modifying the origional Particle ReturnParticle = Particle.Copy(Input); //First thing, we need to calculate acceleration: foreach (Particle Comparison in ParticleList) { //This will add each change in acceleration to the acceleration for each particle ReturnParticle.Acceleration = AddLists(ReturnParticle.Acceleration, CalculateGravitationalAcceleration(ReturnParticle, Comparison, Precision, SofteningValue, GravityConstant)); } //Here we multiply by 0.0001 to account of the max timer speed ReturnParticle.Acceleration = MultiplyListByScalar(ReturnParticle.Acceleration, 0.0001); //Now we need to calculate velocity ReturnParticle.Velocity = AddLists(ReturnParticle.Velocity, ReturnParticle.Acceleration); //Check to see if anything goes over the max velocity double VelMag = VectorMagnitude(ReturnParticle.Velocity); if (VelMag > MaxVelocity) { for (int i = 0; i < ReturnParticle.Velocity.Capacity; i++) { //The new velocity is equal to the old direction multiplied by the new magnitude ReturnParticle.Velocity[i] = (ReturnParticle.Velocity[i] / VelMag) * MaxVelocity; } } //Now we calculate position and we're done (Note the multiplication by 0.0001 to account for the max timer speed - NOT NEEDED) ReturnParticle.Position = AddLists(ReturnParticle.Position, ReturnParticle.Velocity); return ReturnParticle; }
/// <summary> /// Creates a set of particles with random initialized positions within a given grid size. /// </summary> public static List<Particle> Get_RandomParticleSet(int NumberParticles, double GridSize, int NumberDimensions, int NumberProperties) { //Create a new list of particles with a default capacity equal to the amount we want List<Particle> ReturnList = new List<Particle>(NumberParticles); //For each "slot" in the list: for (int i = 0; i < ReturnList.Capacity; i++) { Particle x = new Particle(NumberDimensions, NumberProperties); //Create a new particle x.Position = Get_RandomPosition(GridSize, NumberDimensions); //Set it to a random position ReturnList.Add(x); //Add it to the list } //Return the finished list of particles return ReturnList; }
/// <summary> /// Calculates the CHANGE in acceleration from one particle acting on another. /// </summary> public static List<double> CalculateGravitationalAcceleration(Particle Input, Particle Comparison, double Precision, double SofteningValue, double GravityConstant) { //First we create a new list of acceleration components with the same capacity of the input List<double> Acceleration = new List<double>(Input.Acceleration.Capacity); //Now we calculate the actual distance between the particles (we will need this later) double ActualDistance = CalculateActualDistance(Input.Position, Comparison.Position); //Check to see if the actual distance is under the precision value if (Math.Abs(ActualDistance) <= Precision) { //If it is, then we can just return a list with zero change for (int i = 0; i < Acceleration.Capacity; i++) { Acceleration.Add(0); } return Acceleration; } //Calculate the denominator of the equation double Denominator = Math.Pow(((ActualDistance * ActualDistance) + (SofteningValue * SofteningValue)), (3 / 2)); //For each dimension of movement/location: for (int i = 0; i < Acceleration.Capacity; i++) { //Calculate the component distance of this dimension double ComponentDistance = Comparison.Position[i] - Input.Position[i]; //Calculate the change in acceleration Acceleration.Add(GravityConstant * ((Comparison.Properties[0] * ComponentDistance) / Denominator)); } return Acceleration; }
public static List<double> CalculateElectrostaticAcceleration(Particle Input, Particle Comparison, double SofteningValue, double ElectrostaticConstant) { //First we create a new list of acceleration components with the same capacity of the input List<double> Acceleration = new List<double>(Input.Acceleration.Capacity); //Now we calculate the actual distance between the particles (we will need this later) double ActualDistance = CalculateActualDistance(Input.Position, Comparison.Position); //Since we are dealing with electrostatics, we only want to worry about distances equal to zero if (Math.Abs(ActualDistance) == 0) { //If it is, then we can just return a list with zero change for (int i = 0; i < Acceleration.Capacity; i++) { Acceleration.Add(0); } return Acceleration; } //Calculate the denominator of the equation double Denominator = Math.Pow(((ActualDistance * ActualDistance) + (SofteningValue * SofteningValue)), (3 / 2)); //For each dimension of movement/location: for (int i = 0; i < Acceleration.Capacity; i++) { //Calculate the component distance of this dimension double ComponentDistance = Comparison.Position[i] - Input.Position[i]; //Calculate the change in acceleration Acceleration.Add((ElectrostaticConstant * ((Comparison.Properties[1] * Input.Properties[1] * ComponentDistance) / Denominator)) / Input.Properties[0]); } return Acceleration; }