public MoleculeDynamicsSimulator(Molecule molecule, List <CustomAtomForce> customAtomForces, MoleculeDynamicsSimulationSettings simulationSettings) { this.customAtomForces = customAtomForces; this.simulationSettings = simulationSettings; Molecule = molecule; }
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 } } }