Пример #1
0
		private void SetupForTesting(int Nparticles)
		{
			double gradScaleFactor = 3000.0;
			double MinRad = 40.0;
			double MaxRad = 50.0;

			List<string> FFtype = new List<string>(new string[] { "SoftSpheres", "ExternalField" }); 
			
			ParticleStaticObjects.AtomPropertiesDefinition.Clear(); 
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("Hydrogen", 2, unchecked((int)0xc00A32FF), 0, 50); // neon blue
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("Oxygen", 4, unchecked((int)0xc0FF0A32), 1, 49); // red
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("Neon", 6, unchecked((int)0xc0320AFF), 2, 45); // purple
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("Zinc", 9.2, unchecked((int)0xc026D8FF), 3, 43); // sky blue // 0xc032FF0A, 3,  43); // green 
			ParticleStaticObjects.AtomPropertiesDefinition.AddParticleDefinition("Iron", 12.6, unchecked((int)0xc0FF320A), 4, 38); // orange

			ParticleStaticObjects.ReSeedRandom(42); 

			Ensemble1 = new ParticleEnsemble(Nparticles, MinRad, MaxRad, FFtype, m_SizeY, m_SizeX, gradScaleFactor);
			Field = new ExternalField(Ensemble1);

			double[] background = new double[m_NumberOfPixels]; 

			for (int i = 0; i < m_NumberOfPixels; i++)
			{
				background[i] = 512; 
			}

			Field.IncrementGrabberCalls();                         // increment the number of grabber calls			
			Field.BackgroundCalibration(m_NumberOfPixels, background);  // in order to simply set the background to zero 
			Field.SetCalibrating(false);
		}
Пример #2
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(int Height, int Width, ExternalField pExternalField)
		{
			int i, kk;
			double V = 0.0, T = 0.0, dt, pxnew, pynew, factor;

			m_AllPositionsUnchangedFromLastStep = true;

			m_BoxWidth = Width;
			m_BoxHeight = Height;

			if (m_NumberOfParticlesChangedFlag)
			{
				#region Number Of Particles has been adjusted 
				
				m_NumberOfParticlesChangedFlag = false;
				
				if (m_NumberOfParticlesIsGreaterFlag)
				{
					for (kk = 0; kk < NumberOfForceFieldObjects; ++kk)
					{				
						// calculate the ij energy terms for particle set including the new ones
						GetForceFieldObject(kk).UpdateEnergyTerms(this);
					}
				}

				#endregion
			}
			else
			{
				#region Regular Time Step
				
				#region Increment Time Steps

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

				dt = m_Timestep;
				
				// increment ParticleEnsemble Private data member step
				++m_Step;
				
				#endregion

				#region Berendsen Velocity Rescaling

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

				#endregion

				#region Move all particles

				// this loop uses verlet scheme (VV) to propagate the positions forward one step
				for (i = 0; i < NumberOfParticles; ++i)
				{
					Particle particlei = GetParticle(i);
					
					particlei.PositionLast = particlei.Position; 

					factor = 0.5 * dt * dt / particlei.Mass;
					
					pxnew = particlei.Position.X + particlei.Velocity.X * dt + particlei.Force.X * factor;
					pynew = particlei.Position.Y + particlei.Velocity.Y * dt + particlei.Force.Y * factor;

					#region Check for colitions with the wall (left or right)

					if (pxnew > particlei.Radius && pxnew < (m_BoxWidth - particlei.Radius))
					{
						particlei.Position.X = 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      
						particlei.Position.X = particlei.PositionLast.X;
						particlei.Velocity.X = -1.0 * particlei.Velocity.X;

						#if DEBUG 

						if (particlei.Velocity.IsNanOrInfinate == true)
						{
							throw new Exception("Particle Velocity Is Nan Or Infinate");
						}
			
						#endif

						particlei.WasReflectedByWall = true; 

						CalculateParticleVelocitiesInXWallFrame(i);
					}

					#endregion 

					#region Check for colitions with the wall (top or bottom)					

					if (pynew > particlei.Radius && pynew < (m_BoxHeight - particlei.Radius))
					{    
						// this the standard VV code here						
						particlei.Position.Y = 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						
						particlei.Position.Y = particlei.PositionLast.Y;
						particlei.Velocity.Y = -1.0 * particlei.Velocity.Y;

						#if DEBUG 

						if (particlei.Velocity.IsNanOrInfinate == true)
						{
							throw new Exception("Particle Velocity Is Nan Or Infinate");
						}
			
						#endif

						particlei.WasReflectedByWall = true; 

						CalculateParticleVelocitiesInYWallFrame(i);						
					}

					#endregion

					// check whether all the positions are changed from the last step
					if (particlei.Position.Y != particlei.PositionLast.Y || particlei.Position.X != particlei.PositionLast.X)
					{
						m_AllPositionsUnchangedFromLastStep = false;
					}
				}

				#endregion

				#region If all the particles have frozen then we need to rerandomise (should be rare)
				
				// this is a stability measure; if the frame is frozen wrt to the previous frame,
				if (m_AllPositionsUnchangedFromLastStep)
				{
					// adjust particle positions to eliminate overlap - this can cause the sim to freeze
					EliminateParticleOverlap(m_BoxHeight, m_BoxWidth);    

					for (i = 0; i < NumberOfParticles; ++i)
					{
						Particle particlei = GetParticle(i);

						//  then we zero out the forces and velocities & repropagate the positions
						particlei.Force.X = 0;
						particlei.Force.Y = 0;

						particlei.PositionLast.X = particlei.Position.X;
						particlei.PositionLast.Y = particlei.Position.Y;

						particlei.Position.X = particlei.Position.X + particlei.Velocity.X * dt + (particlei.Force.X / particlei.Mass) * dt * dt * 0.5; 
						particlei.Position.Y = particlei.Position.Y + particlei.Velocity.Y * dt + (particlei.Force.Y / particlei.Mass) * dt * dt * 0.5; 
					}

					m_AllPositionsUnchangedFromLastStep = false;
				}

				#endregion

				#region Determin Inter-particle collions
				
				UpdateInterParticleSeparations();

				#endregion

				#region Calculate Force Fields
				
				if (pExternalField != null)
				{
					pExternalField.CalculateForceField(this);
				}

				if (GetForceFieldObject(0).ForceFieldType == "HardSphereForceField")
				{
					GetForceFieldObject(0).CalculateForceField(this);
				}
				else
				{
					for (i = 0; i < NumberOfParticles; ++i)
					{
						Particle particlei = GetParticle(i);
						// save the present forces to t-1 vectors
						particlei.ForceLast.X = particlei.Force.X;
						particlei.ForceLast.Y = particlei.Force.Y;
					}

					// zero out the force vectors & potential energy					
					ZeroForces();			
					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)
					{
						Particle particlei = GetParticle(i);
						// use VV scheme to propagate the velocities forward
						factor = dt * 0.5 / particlei.Mass; 						

						particlei.Velocity.X = particlei.Velocity.X + (particlei.Force.X + particlei.ForceLast.X * factor);
						particlei.Velocity.Y = particlei.Velocity.Y + (particlei.Force.Y + particlei.ForceLast.Y * factor);

						#if DEBUG 

						if (particlei.Velocity.IsNanOrInfinate == true)
						{
							throw new Exception("Particle Velocity Is Nan Or Infinate");
						}
			
						#endif
					}

					// see whether any collisions occurred
					DetermineIfCollisionsOccurred();
				}

				#endregion 

				#endregion
			}
		}