A first example
The sample code in Tutorial 0 is nice, but as we will learn in later sections, the Glotzilla API is much more powerful when used in an object-oriented fashion. Therefore, the bulk of our tutorials will focus on using the API the way that it was meant to be used. If you are familiar with object oriented programming this is a good place to start. If you are not, we recommend that you at least briefly read up on the most important aspects of OOP. Here we use the concept of inheritance to create a custom simulation class called LennardJonesSystem?. We use this class to run a simple Molecular Dynamics simulation with two particles interaction via the Lennard-Jones potential, just as we did in Tutorial 0. The sample code is given below.
#include <glotzilla++.h> class LennardJonesSimulation : public MdSimulation { public: LennardJonesSimulation() { AddParticle(new MdPointParticle(0,0,0)); AddParticle(new MdPointParticle(1,0,0)); SetInteraction(new LennardJones); SetForceRoutine(new BruteForce); SetBoundaryConditions(new PeriodicBoundary(11)); SetMoveRoutine(new VerletMove); } }; int main(int argc, char ** argv) { LennardJonesSimulation my_simulation; for(int timesteps=0; timesteps<10000; timesteps++) my_simulation ++; return 0; }
Compile the code using
glotzcc md.c
where md.c is the name of the file where the code resides. Let's take a look at the code step by step. The first thing that we do is include the Glotzilla header files. This is accomplished with the line
#include <glotzilla++.h>
The compiler now knows about all of the pre-defined Glotzilla classes. The next thing that we must do is declare a C++ class that defines our system. We accomplish this with the lines:
class LennardJonesSimulation : public MdSimulation
{
public:
LennardJonesSimulation()
{
...
}Here, our custom class LennardJonesSystem? inherits from class MdSimulation. Therefore, our LennardJones system class contains every public member function and member variable that MdSimulation does. We define a constructor using the lines
public:
LennardJonesSimulation()
{
...
}Every time someone creates a new instance of "LennardJonesSimulation?" the constructor is called. For example, in the program above, the constructor is called in the line:
LennardJonesSimulation my_simulation;
Now we must define a method for our constructor. An MD simulation needs a few classes in order to work:
- particles - objects that exist in the simulation
- interactions - defines how particles interact
- force routine - calculates force particles exert on one another
- boundary conditions - the space accessable to the particles
- move routine - defines how the particles move
We define these classes using the following lines:
AddParticle(new MdPointParticle(0,0,0)); AddParticle(new MdPointParticle(1,1,1)); SetInteraction(new LennardJones); SetForceRoutine(new BruteForce); SetBoundaryConditions(new PeriodicBoundary(10)); SetMoveRoutine(new VerletMove);
All of the functions used are inherited from the MdSimulation class. Here, we declare two point particles, one at <0,0,0> and another at <1, 1, 1>. They interact via the 12-6 Lennard-Jones potential. The force routine calculates forces between all particles, interacting or not (brute force). The boundary is periodic with a period of length 10 in x, y, and z. The equations of motion are integrated using the Verlet integration scheme.
In the "main" method, declare an instance of LennardJonesSystem? called "my_simulation." When the class is instantiated, the constructor that we defined above is called, which initializes the system. To run the simulation for 1000 timesteps, we write:
for(int i=0; i<1000; i++) my_simulation ++;
Here, the ++ operator in my_simulation integrates the equations of motion forward by 1 timestep. We do this 1000 times in all, and then the code exits.