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