Exemple #1
0
		/// <summary>
		/// velocity verlet routine to propagate the particle ensemble
		/// </summary>
		/// <param name="Height"></param>
		/// <param name="Width"></param>
		/// <param name="pExternalField"></param>
		public void VelocityVerletPropagation(ExternalField pExternalField)
		{
			int i, kk;
			double V = 0.0, T = 0.0, dt, pxnew, pynew, factor;

			AllPositionsUnchangedFromLastStep = true;

			//BoxWidth = Width;
			//BoxHeight = Height;

			if (NumberOfParticlesChangedFlag)
			{
				NumberOfParticlesChangedFlag = false;

				if (NumberOfParticlesIsGreaterFlag)
				{
					for (kk = 0; kk < NumberOfForceFieldObjects; ++kk)
					{				
						// calculate the ij energy terms for particle set including the new ones
						GetForceFieldObject(kk).UpdateEnergyTerms(this);
					}
				}
			}
			else
			{

				//  Timestep = 1.0/(double)ofGetFrameRate();
				Timestep = 0.005;

				dt = Timestep;
				
				// increment ParticleEnsemble Private data member step
				++step;                                 

				if (BerendsenThermostat)
				{                
					//  Berendsen Thermostat
					BerendsenVelocityRescaling();
				}

				// this loop uses verlet scheme (VV) to propagate the positions forward one step
				for (i = 0; i < NumberOfParticles; ++i)
				{
					SetLastXParticlePosition(i, GetXParticlePosition(i));
					SetLastYParticlePosition(i, GetYParticlePosition(i));

					factor = 0.5 * dt * dt / GetParticleMass(i);

					pxnew = GetXParticlePosition(i) + GetXParticleVelocity(i) * dt + GetXParticleForce(i) * factor;
					pynew = GetYParticlePosition(i) + GetYParticleVelocity(i) * dt + GetYParticleForce(i) * factor;

					if (pxnew > GetParticleRadius(i) && pxnew < (BoxWidth - GetParticleRadius(i)))
					{
						// this the standard VV code here
						SetXParticlePosition(i, pxnew);                              
					}
					else
					{ 
						// this is to reflect off the walls; added by DRG in lieu of soft walls to improve real time stability... not part of a standard VV scheme      
						SetXParticlePosition(i, GetLastXParticlePosition(i));
						SetXParticleVelocity(i, -1.0 * GetXParticleVelocity(i));
						SetWasReflectedByWall(i, true);
						calculateParticleVelocitiesInXWallFrame(i);
					}

					if (pynew > GetParticleRadius(i) && pynew < (BoxHeight - GetParticleRadius(i)))
					{     
						// this the standard VV code here
						SetYParticlePosition(i, pynew);
					}
					else
					{  
						// this is to reflect off the walls; added by DRG in lieu of soft walls to improve real time stability... not part of a standard VV scheme
						SetYParticlePosition(i, GetLastYParticlePosition(i));
						SetYParticleVelocity(i, -1.0 * GetYParticleVelocity(i));
						SetWasReflectedByWall(i, true);
						calculateParticleVelocitiesInYWallFrame(i);						
					}

					Particles[i].GridSector.GetSector(Particles[i].Position);
				}

				// check whether all the positions are changed from the last step
				for (i = 0; i < NumberOfParticles; ++i)
				{
					if (GetYParticlePosition(i) != GetLastYParticlePosition(i) || GetXParticlePosition(i) != GetLastXParticlePosition(i))
					{
						AllPositionsUnchangedFromLastStep = false;
					}
				}


				if (AllPositionsUnchangedFromLastStep)
				{    
					// this is a stability measure; if the frame is frozen wrt to the previous frame,					

					// adjust particle positions to eliminate overlap - this can cause the sim to freeze
					EliminateParticleOverlap(BoxHeight, BoxWidth);    

					for (i = 0; i < NumberOfParticles; ++i)
					{           
						//  then we zero out the forces and velocities & repropagate the positions						
						SetXParticleForce(i, 0.0);
						SetYParticleForce(i, 0.0);
						SetLastXParticlePosition(i, GetXParticlePosition(i));
						SetLastYParticlePosition(i, GetYParticlePosition(i));
						SetXParticlePosition(i, GetXParticlePosition(i) + GetXParticleVelocity(i) * dt + (GetXParticleForce(i) / GetParticleMass(i)) * dt * dt * 0.5);
						SetYParticlePosition(i, GetYParticlePosition(i) + GetYParticleVelocity(i) * dt + (GetYParticleForce(i) / GetParticleMass(i)) * dt * dt * 0.5);

						Particles[i].GridSector.GetSector(Particles[i].Position);
					}

					AllPositionsUnchangedFromLastStep = false;
				}

				UpdateInterParticleSeparations();

				if (pExternalField != null)
				{
					pExternalField.CalculateForceField(this);
				}

				if (GetForceFieldObject(0).ForceFieldType == "HardSphereForceField")
				{
					GetForceFieldObject(0).CalculateForceField(this);
				}
				else
				{
					for (i = 0; i < NumberOfParticles; ++i)
					{	
						// save the present forces to t-1 vectors
						SetLastXParticleForce(i, GetXParticleForce(i));
						SetLastYParticleForce(i, GetYParticleForce(i));
					}

					// zero out the force vectors & potential energy
					ZeroXForces();			
					ZeroYForces();
					PotentialEnergy = 0.0;

					for (kk = 0; kk < NumberOfForceFieldObjects; ++kk)
					{				
						// calculate & set the forces at the new positions
						GetForceFieldObject(kk).CalculateForceField(this);
					}

					for (i = 0; i < NumberOfParticles; ++i)
					{                  
						// use VV scheme to propagate the velocities forward
						factor = dt * 0.5 / GetParticleMass(i);
						SetXParticleVelocity(i, GetXParticleVelocity(i) + (GetXParticleForce(i) + GetLastXParticleForce(i)) * factor);
						SetYParticleVelocity(i, GetYParticleVelocity(i) + (GetYParticleForce(i) + GetLastYParticleForce(i)) * factor);
					}

                    // Update the ensemble velocity autocorrelation function
                    //if (m_FFTenabled)
                    //{
                    //    UpdateVelocityAutoCorrelationFunction();
                    //    FFTVelocityAutoCorrelationFunction();
                    //}

					// see whether any collisions occurred
					DetermineIfCollisionsOccurred();

				}
			}

		}
		public static void LoadConfig(string filename)
		{
			#region Load the actual config
			
			if (File.Exists(filename))
			{
				RC.WriteLine(ConsoleThemeColor.TitleText1, "Loading config '" + filename + "'");

				XmlDocument doc = new XmlDocument();

				doc.Load(filename);

				m_Options.Load(doc.DocumentElement);
			}

			#endregion

			#region Setup The Field Image 
			
			m_CompositeFieldImage.Bounds = m_Options.Kinect.Bounds;

			int i = 0;

			foreach (DS.Simulation.CompositeFieldImage.KinectFieldImage field in m_CompositeFieldImage.Images)
			{
				field.X = m_Options.Kinect.Cameras[i].X;
				field.Y = m_Options.Kinect.Cameras[i++].Y;
			}

			#endregion

			#region Setup The Particle Simulation 
			
			double gradScaleFactor = 1000.0;
			double MinRad = 10.0;
			double MaxRad = 30.0;

			List<string> FFtype = new List<string>(new string[] { "SoftSpheres", "ExternalField" });
			
			ParticleStaticObjects.AtomPropertiesDefinition.Clear();
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("A", 1, new Color3(0.0390625f, 0.1953125f, 0.99609375f), 0, 20); // neon blue  0xc00A32FF
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("B", 4, new Color3(1f, 0.03921569f, 0.1960784f), 1, 49); // red 0xc0FF0A32
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("C", 6, new Color3(0.1960784f, 0.03921569f, 1f), 2, 45); // purple 0xc0320AFF
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("D", 9.2, new Color3(0.1490196f, 0.8470589f, 1f), 3, 43); // sky blue 0xc026D8FF // 0xc032FF0A, 3,  43); // green 
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("E", 12.6, new Color3(1f, 0.1960784f, 0.03921569f), 4, 38); // orange 0xc0FF320A

			ParticleStaticObjects.ReSeedRandom(42);			

			m_Ensemble = new ParticleEnsemble(1, MinRad, MaxRad, FFtype, ArtworkStaticObjects.CompositeFieldImage.Height, ArtworkStaticObjects.CompositeFieldImage.Width, gradScaleFactor);
			m_ExternalField = new ExternalField(m_Ensemble, ArtworkStaticObjects.CompositeFieldImage);

			for (int j = 0; j < ParticleStaticObjects.AtomPropertiesDefinition.Count; j++)
			{
				ParticleStaticObjects.AtomPropertiesDefinition.SetAttractiveOrRepulsive(j, Options.Simulation.ParticleTypes[j].AttractiveOrRepulsive);
				ParticleStaticObjects.AtomPropertiesDefinition.SetEnabled(j, Options.Simulation.ParticleTypes[j].IsEnabled);
				ParticleStaticObjects.AtomPropertiesDefinition.SetSound(j, Options.Simulation.ParticleTypes[j].IsSoundOn);
			}

			m_Ensemble.BerendsenThermostatCoupling = Options.Simulation.BerendsenThermostatCoupling;
			m_Ensemble.EquilibriumTemperature = Options.Simulation.EquilibriumTemperature;
			m_Ensemble.GradientScaleFactor = Options.Simulation.GradientScaleFactor;
			
			int newNumber = Options.Simulation.NumberOfParticles;
			while (ArtworkStaticObjects.Ensemble.NumberOfParticles < newNumber)
			{
				ArtworkStaticObjects.Ensemble.InitializeOneNewParticle();
			}

			while (ArtworkStaticObjects.Ensemble.NumberOfParticles > newNumber)
			{
				ArtworkStaticObjects.Ensemble.Particles.Pop();
			}

			m_Ensemble.ParticleScale = Options.Simulation.ParticleScale; 
			m_Ensemble.PotentialEnergy = Options.Simulation.PotentialEnergy;

			//ParticleStaticObjects.AtomPropertiesDefinition.ToggleAttractiveOrRepulsive(0);
			
			#endregion
		}