LAMMPS from scratch · 20 min

The conductor: the LAMMPS class

The whole program is one object of class LAMMPS. It owns fourteen members (atom, update, domain, force, neighbor …), and every line of an input script writes into one of them. You see which member each line of in.melt changes, then predict and check the bookkeeping that the members keep: step number, timestep, simulation time, ghost cutoff, and what clear throws away.

1 · Understand: the whole program in three lines

When you type lmp -in in.melt, the function main() in src/main.cpp:69 does:

69  auto *lammps = new LAMMPS(argc, argv, lammps_comm);   // build the conductor
70  lammps->input->file();                                // read the script, line by line
71  delete lammps;                                        // clean up and finish

Everything else happens inside that one object. Its constructor builds the members in a fixed order (src/lammps.cpp:844), and the comments in the code say why the order matters:

852  comm = new CommBrick(this);       // Comm before Atom, so threads are known
855  neighbor = new Neighbor(this);
861  domain = new Domain(this);
865  atom = new Atom(this);
873  group = new Group(this);
875  force = new Force(this);          // after group, to create temperature
878  modify = new Modify(this);
880  output = new Output(this);        // after group, so "all" exists
882  update = new Update(this);        // after output, force, neighbor
883  timer = new Timer(this);

memory, error, universe and input are made just before. Every class in LAMMPS inherits from Pointers (src/pointers.h:110), which gives it a short name for each member. That is why code anywhere can simply write update->dt or atom->x.

MemberClassKeeps
memoryMemoryallocates and frees all big arrays
errorErrorprints ERROR and WARNING messages and stops
universeUniverseall processors, and partitions for multi-replica runs
inputInputreads the script line by line and calls the right code
atomAtomevery per-atom array: x, v, f, type, mass, charge …
updateUpdatetimestep, step number, units, the integrator (run)
neighborNeighborneighbour lists and the skin
commCommsends atoms between processors; ghost atoms
domainDomainthe box, periodic boundaries, lattice, regions
forceForcepair, bond, angle, dihedral, improper, kspace styles; unit constants
modifyModifythe lists of fixes and computes
groupGroupnamed groups of atoms ("all" exists from the start)
outputOutputthermo, dumps and restart files
timerTimerstopwatches for the timing table (page A.9)

2 · Which member does each line change?

Tap a line of in.melt. The members it writes into light up.

memory
error
universe
input
atom
update
neighbor
comm
domain
force
modify
group
output
timer

3 · Modify: the bookkeeping, predicted by hand

The members keep running totals. Two of them are easy to get wrong. The simulation time is not step × dt: update adds each stretch of steps with the timestep that was in force, every time the timestep changes and at the end of every run (src/update.cpp:552):

552  void Update::update_time()
554    atime += (ntimestep - atimestep) * dt;   // time of the steps since the last update
555    atimestep = ntimestep;

The communication cutoff is how far beyond its own region a processor keeps copies (ghosts) of atoms: the pair cutoff plus the skin, because the neighbour list reaches that far (src/neighbor.cpp:379: cut = cutoff + delta, delta = skin).


    

4 · Observe: clear rebuilds the conductor

clear is three lines of src/input.cpp:886: lmp->destroy(); lmp->create(); lmp->post_create();. Every member is thrown away and built fresh, as if LAMMPS had just started. (This page runs clear before every script for exactly that reason.) The new update sets the defaults of the chosen units (src/update.cpp:149):

unitsdefault dtdefault skincode
lj0.0050.3src/update.cpp:167
real12src/update.cpp:188
metal0.0012src/update.cpp:209
si1e-80.001src/update.cpp:230
cgs1e-80.1src/update.cpp:251
electron0.0012src/update.cpp:272
micro20.1src/update.cpp:293
nano0.000450.1src/update.cpp:314

    

What the conductor shows

Your turn

1. run 200 (dt 0.005), then timestep 0.002, run 500. What are step and time at the end?

2. After that, reset_timestep 0. What is the time now?

3. Which member answers thermo_style custom vol, and which one answers temp?