Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Some MD-related algorithms

Here I will present codes that implement some of the algorithms discussed in class. We will be using the numpy library, so let’s begin by importing it

1The energy of a Lennard-Jones sytem

Here I will present a code that initialises a system composed of spheres interacting through a Lennard-Jones potential, and then computes its energy by using periodic boundary conditions.

First we set the the number of particles and the overall density, from which we get the dimensions of the simulation cubic box. Then we use these values to initialse the particle positions on a cubic lattice to avoid particle overlaps.

We then define the Lennard-Jones constants and a function that returns the pair potential. Here we use a truncated and shifted interaction with rc=2.5σr_c = 2.5 \sigma. Note the second line of the LJ_energy() function, where periodic boundary conditions are applied.

We now loop over all pairs to compute the potential energy per particle:

Total potential energy per particle: -0.1381362659100002

2Integrating the harmonic oscillator

We start by simulating the motion of two particles of mass mm connected by a spring of constant kk with the Velocity Verlet method and different thermostats.

We start by importing the matplotlib module and defining a plotting utility function

3No thermostat

We start by simulating a system that is not coupled to a thermostat. The total energy of the system, which should be conserved throughout the simulation, is given by

Utot=12m(v12+v22)+12k(∣x1−x2∣−x0)2,U_\text{tot} = \frac{1}{2} m (v_1^2 + v_2^2) + \frac{1}{2} k (|x_1 - x_2| - x_0)^2,

The force acting on particle ii is given by

Fi=−dUtotdxi=−k(∣x1−x2∣−x0)x1−x2∣x1−x2∣,F_i = -\frac{dU_\text{tot}}{dx_i} = -k (|x_1 - x_2| - x_0) \frac{x_1 - x_2}{|x_1 - x_2|},

where the latter factor is due to the derivative of ∣x1−x2∣|x_1 - x_2|. Note that in numerical implementations the denominator can get very close to zero, leading to numerical instabilities. This happens because particles can get very close to each other, since there is no excluded volume. To avoid this issue, in the code below I use sign(x1−x2)\text{sign}(x_1 - x_2) in its place. Try putting the original expression: you’ll see a very bad energy conservation, together with a trajectory that is clearly wrong.

In the next cell I define the model constants and the functions used to compute the force acting between the two particles, as well as the potential and kinetic energy of the system.

Now we define some helper functions used to set the initial conditions, update and print the observables

Now I define a function that is used to integrate forward in time the equations of motion. Here we make use of the Velocity Verlet method presented in class:

  1. Update the velocity, first step, v(t+Δt/2)=v(t)+12a(t)Δtv(t + \Delta t / 2) = v(t) + \frac{1}{2} a(t) \Delta t.

  2. Update the position, x(t+Δt)=x(t)+v(t+Δt/2)Δtx(t + \Delta t) = x(t) + v(t + \Delta t / 2)\Delta t.

  3. Calculate the force (and therefore the acceleration) using the new position.

  4. Update the velocity, second step, v(t+Δt)=v(t+Δt/2)+12a(t+Δt)Δtv(t + \Delta t) = v(t + \Delta t / 2) + \frac{1}{2} a(t + \Delta t)\Delta t.

Here is the part of the code that uses the above functions. We first generate the initial conditions and initialise the data structures where the observables will be stored.

Then, we integrate the equations of motion for num_steps, keeping track of the observables.

         t          U         Uk       Utot
      0.00     0.0200     0.0000     0.0200
      1.00     0.0005     0.0195     0.0200
      2.00     0.0181     0.0019     0.0200
      3.00     0.0041     0.0159     0.0200
      4.00     0.0131     0.0069     0.0200
      5.00     0.0099     0.0101     0.0200
      6.00     0.0070     0.0130     0.0200
      7.00     0.0158     0.0042     0.0200
      8.00     0.0020     0.0180     0.0200
      9.00     0.0195     0.0005     0.0200
<Figure size 360x360 with 1 Axes>
<Figure size 432x288 with 1 Axes>

4The Andersen thermostat

Now we couple the system to a heat bath by using the simplest thermostat we studied in class. We first define a “collision frequency” ν\nu, and then use it to calculate the probability νΔt\nu \Delta t that, at each time step, a random particle undergoes a collision. In this simple scheme, if a particle undergoes a collision, its velocity is extracted from the Maxwell-Boltzmann distribution corresponding to the simulated temperature TT.

The code below is very similar to the one above, with the only difference being the definitions of the constants, and the collision step.

         t          U         Uk       Utot
      0.00     0.0200     0.0000     0.0200
   1000.00     0.3046     3.1439     3.4485
   2000.00     0.2452     0.3006     0.5458
   3000.00     0.1510     1.8942     2.0453
   4000.00     0.0014     3.1096     3.1110
   5000.00     0.0497     2.1607     2.2105
   6000.00     0.8729     0.5158     1.3887
   7000.00     0.1244     0.5481     0.6725
   8000.00     0.5828     0.7177     1.3005
   9000.00     0.1232     0.4656     0.5887
<Figure size 360x360 with 1 Axes>
<Figure size 432x288 with 1 Axes>