private static void ApplyAtomForces(Molecule molecule, UnitValue elapsedTime, ForceCalculatorResult forces, MoleculeDynamicsSimulationSettings settings) { var maxVelocity = 1e2; var dT = settings.TimeStep.In(Unit.Second); foreach (var vertexForce in forces.ForceLookup) { var atom = molecule.GetAtom(vertexForce.Key); var force = vertexForce.Value; if (settings.ForceRampUp && elapsedTime < settings.ForceRampUpPeriod) { var quotient = elapsedTime.Value / settings.ForceRampUpPeriod.Value; force *= quotient;//Math.Pow(10, (int)(-100*quotient)); } if (force.Magnitude() < ForceLowerCutoff) { continue; } atom.Velocity += settings.TimeStep * (force.To(Unit.Newton) / atom.Mass); if (atom.Velocity.Magnitude().In(Unit.MetersPerSecond) > maxVelocity) { atom.Velocity *= maxVelocity / atom.Velocity.Magnitude().In(Unit.MetersPerSecond); } atom.Position += dT * atom.Velocity; if (settings.ResetAtomVelocityAfterEachTimestep) { atom.Velocity = new UnitVector3D(Unit.MetersPerSecond, 0, 0, 0); } else { atom.Velocity *= 1.0; // TODO: Scale velocity to maintain a specific total energy, matching the environement's temperature } } }
private static void ApplyLonePairRepulsion(ForceCalculatorResult forces) { foreach (var lonePairForce in forces.LonePairForceLookup) { var orbital = lonePairForce.Key; var atom = orbital.Atom; var force = lonePairForce.Value; if (force.Magnitude() < ForceLowerCutoff) { continue; } var displacementDirection = force.Normalize(); var atomRadius = atom.Radius.Value; var lonePairVector = atom.Position.VectorTo(orbital.MaximumElectronDensityPosition); var displacementNormal = displacementDirection.ProjectOnto(lonePairVector.Normalize()); var tangentialDisplacement = (displacementDirection - displacementNormal).ToVector3D(); var displacedLonePair = orbital.MaximumElectronDensityPosition + atomRadius * tangentialDisplacement; lonePairVector = atom.Position.VectorTo(displacedLonePair); var scaling = 0.85 * atomRadius / lonePairVector.Magnitude(); orbital.MaximumElectronDensityPosition = atom.Position + scaling * lonePairVector; } }