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(2, unchecked((int)0xc00A32FF), 0, 50); // neon blue ParticleStaticObjects.AtomPropertiesDefinition.addParticleDefinition(4, unchecked((int)0xc0FF0A32), 1, 49); // red ParticleStaticObjects.AtomPropertiesDefinition.addParticleDefinition(6, unchecked((int)0xc0320AFF), 2, 45); // purple ParticleStaticObjects.AtomPropertiesDefinition.addParticleDefinition(9.2, unchecked((int)0xc026D8FF), 3, 43); // sky blue // 0xc032FF0A, 3, 43); // green ParticleStaticObjects.AtomPropertiesDefinition.addParticleDefinition(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); }
/* // function to propagate the particle ensemble public void VelocityVerletPropagation(int, int, ExternalField) { } */ // velocity verlet routine to propagate the particle ensemble public void VelocityVerletPropagation(int Height, int Width, ExternalField pExternalField) { int i, kk; double V = 0.0, T = 0.0, dt, pxnew, pynew, factor; DPVector pnew; DPVector vnew; AllPositionsUnchangedFromLastStep = true; BoxWidth = Width; BoxHeight = Height; if (NumberOfParticlesChangedFlag) { NumberOfParticlesChangedFlag = false; if (NumberOfParticlesIsGreaterFlag) { for (kk = 0; kk < GetNumberOfForceFieldObjects(); ++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; ++step; // increment ParticleEnsemble Private data member step if (BerendsenThermostat) { // Berendsen Thermostat BerendsenVelocityRescaling(); } // T=GetKineticEnergy(); // V=GetPotentialEnergy(); // get the potential energy - pretty useless when the external field is time dependent - but useful for // TotalEnergy=T+V; // testing that new interparticle forceFields conserve energy //this loop uses verlet scheme (VV) to propagate the positions forward one step for (i = 0; i < GetNumberOfParticles(); ++i) { Particle particle = pParticleVector[i]; //SetLastXParticlePosition(i, GetXParticlePosition(i)); //SetLastYParticlePosition(i, GetYParticlePosition(i)); particle.PositionLast = particle.Position; //factor = 0.5 * dt * dt / GetParticleMass(i); factor = 0.5 * dt * dt / particle.Mass; // GetParticleMass(i); //pxnew = GetXParticlePosition(i) + GetXParticleVelocity(i) * dt + GetXParticleForce(i) * factor; //pynew = GetYParticlePosition(i) + GetYParticleVelocity(i) * dt + GetYParticleForce(i) * factor; //pxnew = particle.Position.X + GetXParticleVelocity(i) * dt + GetXParticleForce(i) * factor; //pynew = GetYParticlePosition(i) + GetYParticleVelocity(i) * dt + GetYParticleForce(i) * factor; pnew = particle.Position + particle.Velocity * dt + particle.Force * factor; vnew = particle.Velocity; // cout << "x " << pxnew << " y " << pynew << endl; //if (pxnew > GetParticleRadius(i) && pxnew < (BoxWidth - GetParticleRadius(i))) if (pnew.X <= particle.Radius || pnew.X >= (BoxWidth - particle.Radius)) { // 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)); pnew.X = particle.PositionLast.X; vnew.X *= -1; particle.WasReflectedByWall = true; //SetWasReflectedByWall(i, true); calculateParticleVelocitiesInXWallFrame(i); // cout << "X Wall Reflection, Particle " << i << endl; } //if (pynew > GetParticleRadius(i) && pynew < (BoxHeight - GetParticleRadius(i))) if (pnew.Y <= particle.Radius && pnew.Y >= (BoxHeight - particle.Radius)) { // 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)); pnew.Y = particle.PositionLast.Y; vnew.Y *= -1; particle.WasReflectedByWall = true; // SetWasReflectedByWall(i, true); calculateParticleVelocitiesInYWallFrame(i); // cout << "Y Wall Reflection, Particle " << i << endl; } particle.Position = pnew; particle.Velocity = vnew; //check whether all the positions are changed from the last step if (particle.Position != particle.PositionLast) { AllPositionsUnchangedFromLastStep = false; } } if (AllPositionsUnchangedFromLastStep) { // this is a stability measure; if the frame is frozen wrt to the previous frame, //cout << "Positions unchanged" << endl; EliminateParticleOverlap(BoxHeight, BoxWidth); // adjust particle positions to eliminate overlap - this can cause the sim to freeze for (i = 0; i < GetNumberOfParticles(); ++i) { // then we zero out the forces and velocities & repropagate the positions // cout << px[i] << " " << py[i] << " " << vx[i] << " " << vy[i] << " " << fx[i] << " " << fy[i] << " " << fxLast[i] << " " << fyLast[i] << endl; Particle particle = pParticleVector[i]; particle.Force = new DPVector(0, 0); //SetXParticleForce(i, 0.0); //SetYParticleForce(i, 0.0); particle.PositionLast = particle.Position; //SetLastXParticlePosition(i, GetXParticlePosition(i)); //SetLastYParticlePosition(i, GetYParticlePosition(i)); particle.Position = particle.Position + particle.Velocity * dt + (particle.Force / particle.Mass) * dt * dt * 0.5; //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); } AllPositionsUnchangedFromLastStep = false; } UpdateInterParticleSeparations(); if (pExternalField != null) { pExternalField.CalculateForceField(this); } if (GetForceFieldObject(0).ForceFieldType == "HardSphereForceField") { GetForceFieldObject(0).CalculateForceField(this); } else { for (i = 0; i < GetNumberOfParticles(); ++i) { Particle particle = pParticleVector[i]; // save the present forces to t-1 vectors //SetLastXParticleForce(i, GetXParticleForce(i)); //SetLastYParticleForce(i, GetYParticleForce(i)); particle.ForceLast = particle.Force; } ZeroForces(); // zero out the force vectors & potential energy SetPotentialEnergy(0.0); for (kk = 0; kk < GetNumberOfForceFieldObjects(); ++kk) { // calculate & set the forces at the new positions GetForceFieldObject(kk).CalculateForceField(this); } for (i = 0; i < GetNumberOfParticles(); ++i) { // use VV scheme to propagate the velocities forward Particle particle = pParticleVector[i]; //factor = dt * 0.5 / GetParticleMass(i); factor = dt * 0.5 / particle.Mass; //SetXParticleVelocity(i, GetXParticleVelocity(i) + (GetXParticleForce(i) + GetLastXParticleForce(i)) * factor); //SetYParticleVelocity(i, GetYParticleVelocity(i) + (GetYParticleForce(i) + GetLastYParticleForce(i)) * factor); particle.Velocity = particle.Velocity + (particle.Force + particle.ForceLast) * factor; } // see whether any collisions occurred DetermineIfCollisionsOccurred(); } } }