MD Simulation
MD Simulation
D. C. Rapaport
In this column we explain what is involved in writing a molecular dynamics (MD) program that includes animation and, in addition, allows the user
to interact with the simulation while it is running.
The simplest of soft-disk models for a fluid is considered, but the techniques described here provide
a basis that can be readily adapted to a wide range
of problems, both elementary and advanced. Although some effort is required in getting started,
the benefits of knowing how to incorporate graphics and a user interface into a simulation are many.
For example, for the two-dimensional soft-disk system considered here, it is possible to observe the
onset of spatial order at high density, complete with
defects in the resulting crystalline structure. In contrast, at low density the particle motion is diffusive
in appearance. The interactive capability enables
the user to drive the system into states anywhere
between these two extremes.
The usual way of organizing interactive software
is by means of an event-driven approach. The most
conspicuous feature of event-driven software is that
responses to user actions occur promptly. Because
of this requirement, the overall organization of the
program is very different from the customary scientific computation. In the latter, the activity is centered around some computationally intensive task;
in the former, the computation is allowed to proceed only when the user is not busy doing something, such as changing a parameter setting or the
display contents.
The graphic environment on the typical UNIX
workstation is provided by the X11 Window System. This environment is a relatively flexible, although rather complex (especially for novice programmers) windowing system that allows the display and the application to reside on separate computers transparently linked over a network. This environment, which also allows multiple applications
to share space on the same display screen, is commonly referred to as X11, or X. There are two major
elements in X. The first is Xlib, a library of functions that the programmer can use for a multitude
of tasks, such as opening windows, performing basic
drawing operations, and receiving X events that are
user-generated by means of the mouse or keyboard
[1]. The other component is the X server; under X,
an application does not draw directly to the screen,
but packages graphic requests and sends them to
the server (on the same or another machine) which
carries out the graphic operations.
X is adequate for the simple graphics used in
this work. (For more complex rendering, for example three-dimensional graphics, software such as
OpenGL can be added to the environment described
here.) X is not suitable for programming a user interface because it works with windows and events
at much too detailed a level. Higher levels of abstraction can reduce the task of interface construction to comparative simplicity. This reduction is
the goal of Motif, a set of specifications for developing user interfaces that have a consistent look and
feel as far as the user is concerned [2]. From the
practical point of view, Motif consists of a set of
widgets and a library of functions for constructing
and manipulating the widgets. The term widget
embraces all manner of objects. Some of these are
visible on the screen, such as windows, scrollbars,
buttons, textual items, and menus, to name but a
few (all visible widgets actually have their own windows). Others are less conspicuous but nevertheless
extremely useful, because they help with the layout
of the visible objects, for example, in tabular form.
Another group, known as shells, provide a means
of communication between the windows belonging
to the application and whatever else is occurring on
the display screen. The screen contents are under
the control of the X server and, more immediately,
the window manager, whose responsibilities include
window positioning and framing.
Motif actually deals with only part of the wid-
Dennis Rapaport is a professor of physics in the Department of Physics, Bar-Ilan University, Ramat-Gan,
Israel 52900. E-mail: [email protected].
Computers in Physics 11 (1997) 337-347
The first two function calls (discussed below) initialize the graphics and bring the system to a state
from which a run can be started by the user. The
latter two calls are part of the Xt library, and ensure that the program carries out the desired computations and responds to the users actions. The
first of these functions called, XtAppAddWorkProc,
specifies the function MdCycle to be a work procedure. The implication is that whenever no events
are awaiting processing, this function, which is responsible for the MD computations, will be called.
(The variable app is defined later.) The second
function, XtAppMainLoop, contains the central dispatching loop that ensures all events are processed
and that the work procedure is called. The function MdCycle checks if the simulation is actually
running, and if so, calls for the computations required for a single timestep (the value returned by
the function is dictated by Xt):
Boolean MdCycle ()
{
if (running) SingleStep ();
return (False);
}
Molecular dynamics
The discussion of the program begins with a description of the functions and data associated with
the MD computations themselves, starting with the
function SingleStep where the computational work
actually occurs. The reader is assumed to be familiar with the ideas underlying the MD approach
[5-7]. The description of those parts of the program
that create and manage the user interface, as well
as the graphic output, will appear later on.
There are a variety of methods that can be used
to organize the data used to store the particle (i.e.,
atomic) coordinates, velocities and accelerations.
The most natural approach is to arrange the data
in a way that mirrors the mathematics of the problem, namely, to use data structures representing
vectors. Thus we define two-dimensional vectors
for both real (double precision) and integer quantities:
Computers in Physics 11 (1997) 337-347
rrCut = SQ (rCut);
VDiv (invWid, cells, region);
The two innermost loops consider all pairs of particles in the two chosen cells, with a test being made
to ensure that if the two cells are one and the same,
then each particle pair is considered only once. If
the particles are within range, the pair interaction
is computed and the accelerations and potential energy sum updated. The force law used here corresponds to a Lennard-Jones potential that is truncated at its minimum, namely
U (rij ) = 4 (/rij )12 (/rij )6 + ,
for rij < rc = 21/6 . Reduced units are used in
which , and the particle mass are all unity.
DO_CELL (j1, m1) {
User interface
We now focus on implementing the graphics and
user interface. The first stage is the opening of a
window on the screen filled with various user controls, a space for drawing, and a small area for textual information. All this is done by the function
SetupGraphics below; this function turns out to
be rather lengthy, not because of its profundity,
but because it has to take care of numerous details. While the use of widgets hides much of the
difficult work that goes into constructing the interface, it is still necessary to specify how the controls
and other visible entities are to be arranged, the
Computers in Physics 11 (1997) 337-347
Frame (+ RowColumn)
ArrowButton
Scale
Label
PushButton
DrawingArea
Text
window frame
Form (+Shell)
Frame
The control of both the density and the temperature is by means of pairs of ArrowButton widgets,
with a small value change being made each time
the display is refreshed until the button is released.
Each pair of ArrowButtons, together with a descriptive Label widget, are the children of a horizontal RowColumn widget, and this widget in turn is
placed inside a Frame widget that supplies the impression of an etched-in frame. The callback function is provided with an argument that not only distinguishes between widgets, but indicates whether
the button was pushed (armed) or released (disarmed).
for (n = 0; n < 2; n ++) {
wFrame = XtVaCreateManagedWidget ("",
xmFrameWidgetClass, wRowCol,
XmNshadowType,
XmSHADOW_ETCHED_IN,
NULL);
wRowCol2 = XtVaCreateManagedWidget ("",
xmRowColumnWidgetClass, wFrame,
XmNorientation,
XmHORIZONTAL,
XmNspacing,
5,
NULL);
XtVaCreateManagedWidget (buttonName[n],
xmLabelWidgetClass, wRowCol2, NULL);
for (j = 0; j < 2; j ++) {
wArrow = XtVaCreateManagedWidget ("",
xmArrowButtonWidgetClass, wRowCol2,
XmNarrowDirection, (j > 0) ?
XmARROW_UP : XmARROW_DOWN,
NULL);
XtAddCallback (wArrow, XmNarmCallback,
CbArrow, (XtPointer) (3 * n + 2 * j));
XtAddCallback (wArrow, XmNdisarmCallback,
CbArrow, (XtPointer) (3 * n + 1));
}
}
The next control widget to be added to the original RowColumn widget is the PushButton used to
start and stop the run. The activate callback indicates that the PushButton has been pressed and
then released by clicking the left mouse button.
wButtonS = XtVaCreateManagedWidget ("",
xmPushButtonWidgetClass, wRowCol,
XtVaTypedArg, XmNlabelString,
T_STRING ("Start"),
NULL);
XtAddCallback (wButtonS,
XmNactivateCallback, CbButton, 0);
XmNshadowType,
XmSHADOW_IN,
NULL);
wDraw = XtVaCreateManagedWidget ("",
xmDrawingAreaWidgetClass, wFrame,
XmNwidth,
wDrawSize.x,
XmNheight,
wDrawSize.y,
NULL);
XtAddCallback (wDraw,
XmNexposeCallback, CbExpose, 0);
The final widget used here is for displaying textual output (alternatively, we could have overlaid
the text on the MD imagery). The Text widget is
designed for both input and output, and includes
all manner of text editing capabilities; here we use
it merely for output. Certain resources must be
specified to obtain the required appearance and behavior, and the widget is positioned by attaching it
not only to the Form on the left side but also to the
Frame on the right and the RowColumn above.
wText = XtVaCreateManagedWidget ("",
xmTextWidgetClass, wForm,
XmNcolumns,
12,
XmNrows,
4,
XmNeditable,
False,
XmNeditMode,
XmMULTI_LINE_EDIT,
XmNcursorPositionVisible, False,
XmNhighlightThickness, 0,
XmNshadowType,
XmSHADOW_IN,
XmNleftAttachment,
XmATTACH_FORM,
XmNrightAttachment,
XmATTACH_WIDGET,
XmNrightWidget,
wFrame,
XmNrightOffset,
10,
XmNtopAttachment,
XmATTACH_WIDGET,
XmNtopWidget,
wRowCol,
XmNtopOffset,
40,
NULL);
Graphical output
Drawing the current state of the MD system requires rendering a set of suitably positioned disks,
with extra copies needed for any periodic replicas
that intrude into the region. These drawing operations are handled by Xlib, but because the function
for drawing a filled circle has many arguments, we
define a briefer macro alternative:
#define FILL_DISK(x,y) \
XFillArc (dpy, pixmap, gc, x, y, \
diam, diam, 0, 360 * 64)
dx = (inxLo ? -1 : 1) * wDrawSize.x;
dy = (inyLo ? -1 : 1) * wDrawSize.y;
if (inyLo && inyHi)
FILL_DISK (x + dx, y);
else if (inxLo && inxHi)
FILL_DISK (x, y + dy);
else {
FILL_DISK (x + dx, y);
FILL_DISK (x, y + dy);
FILL_DISK (x + dx, y + dy);
}
}
}
Event processing
The callback functions come next. Each is invoked
by one or more widgets in response to certain user
activities. The arguments of these functions have a
particular form. The first points to the widget itself,
the second is the user-defined data item specified
when the callback was created, and the third is a
pointer to a data structure associated with the X
event to which the widget is responding.
The first of these callback functions handles the
two Scale widgets. We start by determining which
widget was involved from the second callback argument, and the new value set by the user. If it
was the particle count that was changed, then the
simulation is reinitialized. If it was the interval between display updates, then this value is simply updated.
void CbScale (Widget w,
XtPointer clientData, XtPointer callData)
{
int id, v;
id = (int) clientData;
v = ((XmScaleCallbackStruct *)
callData)->value;
if (id == 0) {
nAtomEdge = v;
InitializeRun ();
} else stepDraw = v;
}
The next pair of callbacks handle the ArrowButtons and PushButton. For the former it is simply
a matter of interpreting the second callback argument to decide what is required. For the latter, the
state of the simulation is switched between running
and not running, and the label on the PushButton
is updated accordingly. Changes to the number of
particles while the simulation is in progress are disallowed by desensitizing the relevant Scale widget.
void CbArrow (Widget w,
XtPointer clientData, XtPointer callData)
{
int id;
id = (int) clientData;
if (id < 3) changeTemp = id - 1;
else changeDens = id - 4;
}
void CbButton (Widget w,
XtPointer clientData, XtPointer callData)
{
running = ! running;
XtVaSetValues (wButtonS, XtVaTypedArg,
XmNlabelString,
T_STRING (running ? "Stop" : "Start"),
NULL);
XtSetSensitive (wScaleA, ! running);
}
value is within the allowed range. For temperature changes the current velocities are rescaled; for
the density both the region size and (if the region
is made smaller) the coordinates are rescaled, and
a fresh memory allocation for the cell list is made
based on the new region size.
void SetNewTemp (double f)
{
double vvSum; int n;
if (f > 1 && temperature > 5 ||
f < 1 && temperature < 0.02) return;
vvSum = 0;
DO_ATOM {
VScale (rv[n], f);
vvSum += VLenSq (rv[n]);
}
temperature = vvSum / (2 * nAtom);
}
Additional details
Only a few minor details remain. A number of include files must be specified. Those required for a
typical C application are math.h, stdlib.h, and
stdio.h. Most widgets also require their own include files, all located in subdirectory Xm of the
include-file directory. In our case the list is ArrowB.h, DrawingA.h, Form.h, Frame.h, Label.h,
PushB.h, RowColumn.h, Scale.h, Text.h, and MwmUtil.h; these in turn include other files. All functions should be prototyped as a matter of habit.
Finally, when compiling the program, the libraries
should be listed in the order: -lXm for Motif, -lXt
for the X Toolkit, -lX11 for Xlib itself, and -lm for
the C mathematical library.
The end result of this discussion should be an interactive MD simulation which looks very similar to
the one shown in Figure 2. In a number of details
connected with visual appearance we have chosen to
rely on the default settings in effect. Thus the background color of the surrounding window and all the