Molecular Dynamics Simulator



This is a molecular dynamics simulator I programmed in Fortran in order to understand MD in more detail. Periodic boundary conditions, energy minimizer, thermostat and barostat, as well as a correct physical scale and forcefields for the noble gasses are already implemented and working well. Future steps might include parallelization of the calculation of particle interactions and maybe introducing electrostatics and more complex molecules like water.



The code can be found on Github in the link above. I tried to comment everything as good as possibile to the extent, that I think most of it can be easily understood. I will still explain the main integration loop and features a bit in the following text.


Most of the algorithm is implemented in the main file. The constants file contains all necessary constants and parameters needed. The forcefield file contains four different force returning functions.

Iteration Loop

! Integration loop
integrator: do iter = 0, maxiter

The first thing to be done each iteration is fulfilling the periodic boundary conditions (pbc). The first step is checking for particles, which are not in the boundaries. If they are not, they will be “teleported” across the boundary by adding or subtracting the current box size in that dimension.

  ! "Particle-teleporter" to fulfill periodic boundary condition
  do particle = 1, nparticles ! Iterate over all particles
    do dim = 1, 3 ! Iterate over 3d space

      if (r(dim, particle, 0) > boxsize(dim)) then
        r(dim, particle, :) = r(dim, particle, :) - boxsize(dim)
      else if (r(dim, particle, 0) < 0.0_dp) then
        r(dim, particle, :) = r(dim, particle, :) + boxsize(dim)
      end if

    end do
  end do

The next step is calculating the interactions of the particles with each other. For this, we iterate over each particle, which iterates over all other particles expect itself again. For each interaction, we need to calculate the real-space distance in all three coordinates called d0. Now, to fulfill the pbc, we need to calculate interactions across the boundaries. To do that, we iterate over all three dimensions, each from -1 to +1. This means, for the calculation, not only the real-space cell is used, but also all 26 nearest neighbors (containing the image particles). For each of the image particle interaction, the distance is modified by the respective additional distance given by our current boxsize.

After the distance in thee coordinates is calculated, the total distance l is calculated. This is needed for the cutoff decision as well as the calculation of the force, which is then scaled by the distance in the three spatial coordinates. The force on each particle which is exert by the other particles is added up.

  ! Calculation of particle interactions
  f = 0
  do particle1 = 1, nparticles   ! Interaction for each particle
    do particle2 = 1, nparticles ! ..with each other particle
      if (particle1 /= particle2) then  

        d0 = r(:, particle2, 0) - r(:, particle1, 0)
        do dim1 = -1,1
          do dim2 = -1,1
            do dim3 = -1,1

              ! Define new position of image and for dim1=dim2=dim3=1 of real particle interaction
              d = d0
              d(1) = d(1) + (dim1) * boxsize(1)
              d(2) = d(2) + (dim2) * boxsize(2)
              d(3) = d(3) + (dim3) * boxsize(3)

              l = SQRT(d(1) ** 2 + d(2) ** 2 + d(3) ** 2)

              if (l < cutoff) then
                f(:,particle1,1) = f(:,particle1,1) + fitted_lj_f(d, l, ff_parameters(:,atom_type))
              end if

            end do
          end do
        end do

      end if
    end do
  end do

After that, the integration step can be made using the Verlet algorithm. The velocity is also calculated.

! Do Verlet integration step
  r(:,:,1) = 2 * r(:,:,0) - r(:,:,-1) + (f(:,:,1) / mass(atom_type)) * (dt ** 2)

! Calculate velocities by numerical derivation
  v = (r(:,:,1) - r(:,:,-1)) / (2 * dt) ! v(t+dt)

After the integration step, the whole positional array is shifted upwards and thus making it ready for the next iteration. This is needed, because r in this case is used in the following way: r(xyz-dimension,particlenumber,[t-dt,t,t+dt,t+2dt].

! Move array to t = t+dt for next integration step
  r = cshift(r,  1, DIM=3)

Now, the thermostat follows. This is easily done by implementing the Berendsen weak coupling thermostat.

! Thermostat
  ! Calculate E and instantaneous temperature
  E = (mass(atom_type) / 2) * sum(v ** 2)
  T_inst = ((2 * E) / (3 * kB * nparticles))
  ! Weak coupling thermostat
  v = v * SQRT(1 + (dt / tau_T) * (T0 / T_inst - 1))
  ! Apply velocity to r(t-dt) for algorithm
  r(:,:,-1) = r(:,:,0) - (v(:,:) * dt)

Additionally, the Berendsen barostat is implemented.

! Barostat
  ! Calculate instantaneous volume and pressure
  V_inst = boxsize(1) * boxsize(2) * boxsize(3)
  P_inst = ((2 * E) / (3 * V_inst)) + (1 / (3 * V_inst)) * (sum(r(:,:,-1) * f(:,:,1)))
  ! Scaling factor
  mu = (1 - (dt / tau_P) * (P0 - P_inst)) ** (1./3.)
  ! Scale coordinates and boxsize by mu
  r = r * mu
  boxsize = boxsize * mu
end do integrator

With this, the elementary steps of the whole simulation are explained.

One response to “Molecular Dynamics Simulator”

  1. tigress avatar

    Ѕaved as a favorite, I like your website!

Leave a Reply

Your email address will not be published. Required fields are marked *