Unofficial Thoughts on the Good, the Bad, and the Way Forward
AIBN and CTCMS, University of Queensland s.tee@uq.edu.au
26 Apr 2023
A virtual pandemic with realistic geography and temporal mobility, modelled using molecular dynamics! (Alexiadis et al. 2021)
Conductive electrode molecular dynamics is implemented in other packages (GROMACS, OpenMM, MetalWalls, …) but so far only the LAMMPS packages are being widely used outside their developing group!
LAMMPS is a great community code for this cycle!
ASAP: Make your code as simple as possible to understand and extend
AMAP: Enable it to be used in as many as possible ways
Licensing: LGPL can be a good compromise
See also: (Plimpton and Gale 2013)
.cpp
and .h
into lammps/src
and compile, and you get an add-on!fix external
Other packages: “turn these dials”
LAMMPS: “put these dials on your system and turn them”
(For example, a script won’t run any steps without run
and won’t move any atoms without an integrator like fix nvt
!)
Resembles “fluent interface” philosophy
in.peptide
# Solvated 5-mer peptide
pair_style lj/charmm/coul/long 8.0 10.0 10.0
bond_style harmonic
angle_style charmm
dihedral_style charmm
improper_style harmonic
kspace_style pppm 0.0001
read_data data.peptide
neighbor 2.0 bin
timestep 2.0
fix 1 all nvt temp 275.0 275.0 100.0 tchain 1
fix 2 all shake 0.0001 10 100 b 4 6 8 10 12 14 18 a 31
dump 1 all atom 10 atom.peptide
run 300
LAMMPS uses “C with classes”:
What do you think this code does?
fix_jumble.cpp
// ...
int FixJumble::setmask()
{
int mask = 0;
mask |= FixConst::PRE_REVERSE;
// enum'ed in parent class Fix
return mask;
}
void FixJumble::pre_reverse(int, int)
{
double f** = atom->f; // forces
for (int i = 0; i < nlocal; ++i)
{
f[i][0] += rand(); // x-direction
f[i][1] += rand(); // y
f[i][2] += rand(); // z
}
}
// ...
Timestep loop:
fix->initial()
fix->pre_force()
fix->pre_reverse()
fix->post_force()
fix_jumble.cpp
// ...
int FixJumble::setmask()
{
int mask = 0;
mask |= FixConst::PRE_REVERSE;
// enum'ed in parent class Fix
return mask;
}
void FixJumble::pre_reverse(int, int)
{
double f** = atom->f; // forces
for (int i = 0; i < nlocal; ++i)
{
f[i][0] += rand(); // x-direction
f[i][1] += rand(); // y
f[i][2] += rand(); // z
}
}
// ...
Parent “styles” define interfaces:
pair
for MD potentialscompute
for diagnostics (temperature, pressure)fix
for doing anythingChildren styles inherit interface from parents; just override
specific parent virtual functions as needed
fix_jumble.cpp
// ...
int FixJumble::setmask()
{
int mask = 0;
mask |= FixConst::PRE_REVERSE;
// enum'ed in parent class Fix
return mask;
}
void FixJumble::pre_reverse(int, int)
{
double f** = atom->f; // forces
for (int i = 0; i < nlocal; ++i)
{
f[i][0] += rand(); // x-direction
f[i][1] += rand(); // y
f[i][2] += rand(); // z
}
}
// ...
Pointers
class makes shared data “quasi-static”:
pointers.h
Now anything inheriting Pointers
auto-gets references to the necessary data contained in lmp
!
fix_jumble.cpp
// ...
int FixJumble::setmask()
{
int mask = 0;
mask |= FixConst::PRE_REVERSE;
// enum'ed in parent class Fix
return mask;
}
void FixJumble::pre_reverse(int, int)
{
double f** = atom->f; // forces
for (int i = 0; i < nlocal; ++i)
{
f[i][0] += rand(); // x-direction
f[i][1] += rand(); // y
f[i][2] += rand(); // z
}
}
// ...
Factory pattern creates a derived FixJumble
and returns a Fix
pointer to LAMMPS:
modify.cpp
fix_jumble.cpp
// ...
int FixJumble::setmask()
{
int mask = 0;
mask |= FixConst::PRE_REVERSE;
// enum'ed in parent class Fix
return mask;
}
void FixJumble::pre_reverse(int, int)
{
double f** = atom->f; // forces
for (int i = 0; i < nlocal; ++i)
{
f[i][0] += rand(); // x-direction
f[i][1] += rand(); // y
f[i][2] += rand(); // z
}
}
// ...
LAMMPS_NS
namespace prevents code collisionsPointer
classMPI_COMM_WORLD
replaced with communicator used to initialize LAMMPSUser almost completely modified code on their own, made a suitable test, and was just missing some technical details on atom indexing in LAMMPS:
User had an idea for a complicated compute to be used in evaluating a potential, and was asking basic and strange questions a year after his original post:
Programming isn’t about writing the code; it’s about understanding the problem and expressing that understanding through code. (emphasis added)
… Why does having a theory of the program matter? Because this enables rapid and effective modification of the program to respond to changing requirements without piling up technical debt or hacks. (C J Silverio), (Peter Naur)
This illustration is created by Scriberia with The Turing Way community. Used under a CC-BY 4.0 licence. DOI: 10.5281/zenodo.3332807
DOI: 10.5281/zenodo.7857573