public override void CalculateForceField(ParticleEnsemble ensemble) { // variable declarations double posXi, posYi; double posXj, posYj; double ijSeparation = 0.0, LJforce = 0.0, PotentialEnergy = 0.0; // variable initializations int BoxHeight = ensemble.BoxHeight; int BoxWidth = ensemble.BoxWidth; double MaxForce = ensemble.MaxForceThreshold; double MinForce = -1.0 * (ensemble.MaxForceThreshold); DPVector zero = new DPVector(0, 0); // initialize vectors holding forces for (int i = 0; i < ensemble.NumberOfParticles; ++i) { LJforces[i] = zero; } ensemble.ResetAllParticlesNotWithinRange(); for (int i = 0; i < ensemble.NumberOfParticles; ++i) { Particle particlei = ensemble.GetParticle(i); for (int j = (i + 1); j < ensemble.NumberOfParticles; ++j) { Particle particlej = ensemble.GetParticle(j); // get the interparticle separation distances ijSeparation = ensemble.GetInterParticleSeparation(i, j); double LJgradientTermA = particlei.ParticleType.LJgradientTermA[particlej.TypeID]; double LJgradientTermB = particlei.ParticleType.LJgradientTermB[particlej.TypeID]; // update the radial distribution function double cutoffDistance = particlei.ParticleType.MinimumDistance[particlej.TypeID]; // MinimumDistance[i, j]; if (ijSeparation < cutoffDistance) { // for each particle, change the appropriate element of the setWithinRangeOfAnotherParticle vector to true posXi = particlei.Position.X; posYi = particlei.Position.Y; posXj = particlej.Position.X; posYj = particlej.Position.Y; LJforce = (posXj - posXi) * (LJgradientTermA / Math.Pow(ijSeparation, 13.0) + LJgradientTermB / Math.Pow(ijSeparation, 7.0)) / ijSeparation; if (Math.Abs(LJforce) > MaxForce || Math.Abs(LJforce) < MinForce) { // error check for real-time stability... LJforce = 0.0; } else if(double.IsNaN(LJforce) || double.IsInfinity(LJforce)) { // error check for real-time stability... LJforce = 0.0; } LJforces[i].X += LJforce; LJforces[j].X += -1.0 * LJforce; LJforce = (posYj - posYi) * (LJgradientTermA / Math.Pow(ijSeparation, 13.0) + LJgradientTermB / Math.Pow(ijSeparation, 7.0)) / ijSeparation; if (Math.Abs(LJforce) > MaxForce || Math.Abs(LJforce) < MinForce) { // error check for real-time stability... LJforce = 0.0; } else if (double.IsNaN(LJforce) || double.IsInfinity(LJforce)) { // error check for real-time stability... LJforce = 0.0; } LJforces[i].Y += LJforce; LJforces[j].Y += -1.0 * LJforce; ensemble.SetParticlesWithinRange(i, j); ensemble.SetParticlesWithinRange(j, i); } //else //{ // ensemble.SetParticlesNotWithinRange(i, j); //ensemble.SetParticlesNotWithinRange(j, i); //} } } // set the forces in the Particle Ensemble Object ensemble.AddForces(LJforces); // set the potential energy ensemble.AddPotentialEnergy(PotentialEnergy); }
/// <summary> /// function to calculate Soft Spheres forcefield /// </summary> /// <param name="ensemble"></param> public override void CalculateForceField(ParticleEnsemble ensemble) { // variable declarations int i; double posXi, posYi, radius; double PotentialEnergy = 0.0; // variable initializations int BoxHeight = ensemble.BoxHeight; int BoxWidth = ensemble.BoxWidth; DPVector zero = new DPVector(0, 0); // #pragma omp parallel for for (i = 0; i < ensemble.NumberOfParticles; ++i) { // initialize vectors holding forces forces[i] = zero; } //#pragma omp parallel for for (i = 0; i < ensemble.NumberOfParticles; ++i) { Particle particlei = ensemble.GetParticle(i); posXi = particlei.Position.X; posYi = particlei.Position.Y; radius = particlei.Radius; // get pixel vectors along the particle's X & Y axes for getting gradient of image field // there are 2 steps to this process: // (1) do some gaussian smoothing with a user defined width parameter (this determines how // many pixels we need // (2) determine the gradient from linear regression of the 3 surrounding points... // cout << "particle " << i << " Xpos " << posXi << " Ypos " << posYi << endl; // first get the vectors that we need - the length of the vectors depend on the width of the gaussian // if the pixels are near the edge, the pixels beyond them (which arent in the image) are simply returned as zeros if (m_CalculateForceField_TempArray.Length < RangeEitherSide + 1) { m_CalculateForceField_TempArray = new double[RangeEitherSide + 1]; } int count; GetSubsetOfPixelsAlongX(posYi, posXi, RangeEitherSide + 1, ref m_CalculateForceField_TempArray, out count); forces[i].X = ensemble.GradientScaleFactor * GaussianSmoothedSlope(posXi, m_CalculateForceField_TempArray, count); GetSubsetOfPixelsAlongY(posXi, posYi, RangeEitherSide + 1, ref m_CalculateForceField_TempArray, out count); forces[i].Y = ensemble.GradientScaleFactor * GaussianSmoothedSlope(posYi, m_CalculateForceField_TempArray, count); // get the gradient scale factor, depending on whether the particle is attractive or repulsive ParticleInfo typeInfo = ParticleStaticObjects.AtomPropertiesDefinition.Lookup[(ensemble.Particles[i]).TypeID]; double attractiveOrRepulsiveFactor = typeInfo.AttractiveOrRepulsive; forces[i].X *= attractiveOrRepulsiveFactor; forces[i].Y *= attractiveOrRepulsiveFactor; } // set the forces in the Particle Ensemble Object ensemble.AddForces(forces); // add in the potential energy ensemble.AddPotentialEnergy(PotentialEnergy); }